-
Notifications
You must be signed in to change notification settings - Fork 0
/
forwarder.js
173 lines (128 loc) · 4.11 KB
/
forwarder.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
// @ts-check
/**
*
*/
import { Far } from '@endo/marshal';
import { E } from '@endo/eventual-send';
import { fit, M, makeScalarMapStore } from '@agoric/store';
import { AmountMath } from '@agoric/ertp';
const privateArgsShape = harden({
namesByAddress: 'nameHub',
storageNode: M.eref(M.remotable('storageNode')),
marshaller: M.eref(M.remotable('marshaller')),
});
/**
*
* @type {ContractStartFn}
*/
const start = async (zcf, privateArgs) => {
/* Initial (creatorFacet) code for the contract */
// check validity of private args
fit(privateArgs, privateArgsShape, 'IST Forwarder privateArgs');
/** @type { MapStore<Brand, Instance> } */
const brandToPSM = makeScalarMapStore();
/**
* Creates a mapping of brand <> instance in the variable `brandToPSM`
*
* @param {Brand<AssetKind>} brand An asset brand supported by the PSM
* @param {Instance} instance The PSM contract instance for the supported brand
*/
const initPSM = (brand, instance) => {
fit(brand, M.remotable('brand'));
fit(instance, M.remotable('instance'));
brandToPSM.init(brand, instance);
}
/**
* Supplementary method to initialize `brandToPSM` by an array
*
* @param {[Brand<AssetKind>, Instance][]} arr A list of brands and their related PSM instances
*/
const initMultiplePSM = (arr) => {
arr.map( (item) => initPSM(item[0], item[1]) );
}
/* Exposed (publicFacet) code of the contract */
const zoe = zcf.getZoeService();
/**
* This method interfaces with the PSM instance and returns a payment (of IST)
*
* @param {*} paymentIn
* @param {*} amount
* @param {*} instance
* @returns
*/
const getPayOut = async (paymentIn, amount, instance) => {
const proposal = harden({ give: { In: amount } });
const psmPublic = E(zoe).getPublicFacet(instance);
const invitation = E(psmPublic).makeSwapInvitation();
const seat = E(zoe).offer(invitation, proposal, { In: paymentIn });
const paymentOut = await E(seat).getPayout('Out');
return paymentOut;
// TODO metrics
}
/**
* Deposits the `payment` in the wallet of `address`
*
* @param {*} payment
* @param {*} address
*/
const depositPayment = (payment, address) => {
// `home` may not be available to contract
const depFacet = E(home.namesByAddress).lookup(address, 'depositFacet');
depFacet.receive(payment);
}
/**
* Offer handler
*
* @param {*} seat
*/
const swapAndSend = async (seat, amount, destination) => {
const { give: { In: bought } } = seat.getProposal();
const asset = bought.getAllegedBrand();
// asset, destination
// check destination indeed exists
// check asset is of the correct type
if(AmountMath.isEmpty(amount)) {
console.error(`Empty amount sent for the asset: ${asset}`);
seat.fail(Error(`Empty amount sent for the asset: ${asset}`));
}
if(!brandToPSM.has(asset)) {
console.error(`No PSM mapping for the incomming Asset: ${asset}`);
seat.fail(Error(`No PSM mapping for the sent Asset: ${asset}`));
}
const psmInstance = brandToPSM.get(asset);
const paymentIn = undefined;
const paymentOut = await getPayOut(paymentIn, amount, psmInstance);
depositPayment(paymentOut, destination);
seat.exit();
}
/* Create public and creator facets, and harden */
const publicFacet = Far('', {
makeSwapAndSendInvitation: () => zcf.makeInvitation(swapAndSend, 'swapAndSend'),
});
// tie with governance?
const creatorFacet = Far('', {
initPSM,
initMultiplePSM,
});
// @ts-ignore
// return harden({ creatorFacet, publicFacet });
// TODO: private args
// TODO: setup PSM
// TODO: invitationHandler
const sendHandler = async (seat, amount, destination) => {
}
const swapHandler = async (seat, amount, destination) => {
}
const invitationHandler = async (invitation, amount, destination) => {
await swapHandler();
await sendHandler();
}
// TODO: makeInvitation
const makeSwapAndSendInvitation = async () => {
}
// TODO: Facets
// TODO: return
}
// harden and export
harden(start);
export { start };