@agoric/smart-wallet 0.5.4-dev-7ffae88.0 → 0.5.4-dev-32c4d68.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +22 -22
- package/src/offerWatcher.d.ts +14 -3
- package/src/offerWatcher.d.ts.map +1 -1
- package/src/offerWatcher.js +60 -11
- package/src/smartWallet.d.ts +4 -5
- package/src/smartWallet.d.ts.map +1 -1
- package/src/smartWallet.js +79 -43
- package/src/types.d.ts +3 -3
- package/src/walletFactory.d.ts +4 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agoric/smart-wallet",
|
|
3
|
-
"version": "0.5.4-dev-
|
|
3
|
+
"version": "0.5.4-dev-32c4d68.0+32c4d68",
|
|
4
4
|
"description": "Wallet contract",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -16,29 +16,29 @@
|
|
|
16
16
|
"lint:eslint": "eslint ."
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
19
|
-
"@agoric/cosmic-proto": "0.
|
|
20
|
-
"@agoric/swingset-vat": "0.32.3-dev-
|
|
21
|
-
"@endo/bundle-source": "^3.0
|
|
22
|
-
"@endo/captp": "^4.0.
|
|
23
|
-
"@endo/init": "^1.0.
|
|
19
|
+
"@agoric/cosmic-proto": "0.4.1-dev-32c4d68.0+32c4d68",
|
|
20
|
+
"@agoric/swingset-vat": "0.32.3-dev-32c4d68.0+32c4d68",
|
|
21
|
+
"@endo/bundle-source": "^3.1.0",
|
|
22
|
+
"@endo/captp": "^4.0.4",
|
|
23
|
+
"@endo/init": "^1.0.4",
|
|
24
24
|
"ava": "^5.3.0",
|
|
25
25
|
"import-meta-resolve": "^2.2.1"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@agoric/assert": "0.6.1-dev-
|
|
29
|
-
"@agoric/casting": "0.4.3-dev-
|
|
30
|
-
"@agoric/ertp": "0.16.3-dev-
|
|
31
|
-
"@agoric/internal": "0.3.3-dev-
|
|
32
|
-
"@agoric/notifier": "0.6.3-dev-
|
|
33
|
-
"@agoric/store": "0.9.3-dev-
|
|
34
|
-
"@agoric/vat-data": "0.5.3-dev-
|
|
35
|
-
"@agoric/vats": "0.15.2-dev-
|
|
36
|
-
"@agoric/zoe": "0.26.3-dev-
|
|
37
|
-
"@endo/eventual-send": "^1.1.
|
|
38
|
-
"@endo/far": "^1.0.
|
|
39
|
-
"@endo/marshal": "^1.
|
|
40
|
-
"@endo/nat": "^5.0.
|
|
41
|
-
"@endo/promise-kit": "^1.0.
|
|
28
|
+
"@agoric/assert": "0.6.1-dev-32c4d68.0+32c4d68",
|
|
29
|
+
"@agoric/casting": "0.4.3-dev-32c4d68.0+32c4d68",
|
|
30
|
+
"@agoric/ertp": "0.16.3-dev-32c4d68.0+32c4d68",
|
|
31
|
+
"@agoric/internal": "0.3.3-dev-32c4d68.0+32c4d68",
|
|
32
|
+
"@agoric/notifier": "0.6.3-dev-32c4d68.0+32c4d68",
|
|
33
|
+
"@agoric/store": "0.9.3-dev-32c4d68.0+32c4d68",
|
|
34
|
+
"@agoric/vat-data": "0.5.3-dev-32c4d68.0+32c4d68",
|
|
35
|
+
"@agoric/vats": "0.15.2-dev-32c4d68.0+32c4d68",
|
|
36
|
+
"@agoric/zoe": "0.26.3-dev-32c4d68.0+32c4d68",
|
|
37
|
+
"@endo/eventual-send": "^1.1.2",
|
|
38
|
+
"@endo/far": "^1.0.4",
|
|
39
|
+
"@endo/marshal": "^1.3.0",
|
|
40
|
+
"@endo/nat": "^5.0.4",
|
|
41
|
+
"@endo/promise-kit": "^1.0.4"
|
|
42
42
|
},
|
|
43
43
|
"files": [
|
|
44
44
|
"src/"
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
"access": "public"
|
|
68
68
|
},
|
|
69
69
|
"typeCoverage": {
|
|
70
|
-
"atLeast":
|
|
70
|
+
"atLeast": 93.75
|
|
71
71
|
},
|
|
72
|
-
"gitHead": "
|
|
72
|
+
"gitHead": "32c4d68c5f675f1e8fea1a8bc08621816e7b491e"
|
|
73
73
|
}
|
package/src/offerWatcher.d.ts
CHANGED
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
export function watchOfferOutcomes(watchers: OutcomeWatchers, seat: UserSeat): Promise<[unknown, 0 | 1, PaymentPKeywordRecord]>;
|
|
2
|
-
export function prepareOfferWatcher(baggage:
|
|
2
|
+
export function prepareOfferWatcher(baggage: import('@agoric/vat-data').Baggage): (walletHelper: any, deposit: any, offerSpec: import("./offers.js").OfferSpec, address: string, invitationAmount: Amount<"set">, seatRef: UserSeat<unknown>) => import("@endo/exo/src/exo-makers.js").GuardedKit<{
|
|
3
3
|
helper: {
|
|
4
|
-
|
|
4
|
+
/**
|
|
5
|
+
* @param {Record<string, unknown>} offerStatusUpdates
|
|
6
|
+
*/
|
|
7
|
+
updateStatus(offerStatusUpdates: Record<string, unknown>): void;
|
|
5
8
|
onNewContinuingOffer(offerId: any, invitationAmount: any, invitationMakers: any, publicSubscribers: any): void;
|
|
6
|
-
|
|
9
|
+
/** @param {unknown} result */
|
|
10
|
+
publishResult(result: unknown): void;
|
|
11
|
+
/**
|
|
12
|
+
* Called when the offer result promise rejects. The other two watchers
|
|
13
|
+
* are waiting for particular values out of Zoe but they settle at the same time
|
|
14
|
+
* and don't need their own error handling.
|
|
15
|
+
* @param {Error} err
|
|
16
|
+
*/
|
|
17
|
+
handleError(err: Error): void;
|
|
7
18
|
};
|
|
8
19
|
/** @type {OutcomeWatchers['paymentWatcher']} */
|
|
9
20
|
paymentWatcher: OutcomeWatchers['paymentWatcher'];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"offerWatcher.d.ts","sourceRoot":"","sources":["offerWatcher.js"],"names":[],"mappings":"AAsEO,6CAHI,eAAe,QACf,QAAQ,oDAQlB;
|
|
1
|
+
{"version":3,"file":"offerWatcher.d.ts","sourceRoot":"","sources":["offerWatcher.js"],"names":[],"mappings":"AAsEO,6CAHI,eAAe,QACf,QAAQ,oDAQlB;AAkCM,6CAFI,OAAO,kBAAkB,EAAE,OAAO;;QA0BrC;;WAEG;yCADQ,OAAO,MAAM,EAAE,OAAO,CAAC;;QAwBlC,8BAA8B;8BAAlB,OAAO;QAoCnB;;;;;WAKG;yBADQ,KAAK;;IAclB,gDAAgD;oBAArC,eAAe,CAAC,gBAAgB,CAAC;IA6B5C,+CAA+C;mBAApC,eAAe,CAAC,eAAe,CAAC;IAsB3C,iDAAiD;qBAAtC,eAAe,CAAC,iBAAiB,CAAC;GA0BlD;0BAnRY,OAAO,aAAa,EAAE,SAAS,GAAG;IAC9C,KAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,MAAU,CAAC,EAAE,OAAO,GAAG,cAAc,aAAa,EAAE,kBAAkB,CAAC;IACvE,OAAW,CAAC,EAAE,mBAAmB,CAAC;CAC/B;;;;qDAKS,OAAO,4BAA4B,EAAE,cAAc,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC;8BAIlE;IACZ,aAAe,EAAE,oBAAoB,OAAO,CAAC,CAAC;IAC9C,eAAiB,EAAE,oBAAoB,MAAM,CAAC,CAAC;IAC/C,cAAgB,EAAE,oBAAoB,qBAAqB,CAAC,CAAC;CAC1D;+BAoQU,WAAW,0BAA0B,CAAC"}
|
package/src/offerWatcher.js
CHANGED
|
@@ -87,6 +87,7 @@ const offerWatcherGuard = harden({
|
|
|
87
87
|
.optional(M.record())
|
|
88
88
|
.returns(),
|
|
89
89
|
publishResult: M.call(M.any()).returns(),
|
|
90
|
+
handleError: M.call(M.error()).returns(),
|
|
90
91
|
}),
|
|
91
92
|
paymentWatcher: M.interface('paymentWatcher', {
|
|
92
93
|
onFulfilled: M.call(PaymentPKeywordRecordShape, SeatShape).returns(
|
|
@@ -104,21 +105,36 @@ const offerWatcherGuard = harden({
|
|
|
104
105
|
}),
|
|
105
106
|
});
|
|
106
107
|
|
|
108
|
+
/**
|
|
109
|
+
* @param {import('@agoric/vat-data').Baggage} baggage
|
|
110
|
+
*/
|
|
107
111
|
export const prepareOfferWatcher = baggage => {
|
|
108
112
|
return prepareExoClassKit(
|
|
109
113
|
baggage,
|
|
110
114
|
'OfferWatcher',
|
|
111
115
|
offerWatcherGuard,
|
|
112
|
-
|
|
116
|
+
/**
|
|
117
|
+
*
|
|
118
|
+
* @param {*} walletHelper
|
|
119
|
+
* @param {*} deposit
|
|
120
|
+
* @param {import('./offers.js').OfferSpec} offerSpec
|
|
121
|
+
* @param {string} address
|
|
122
|
+
* @param {Amount<'set'>} invitationAmount
|
|
123
|
+
* @param {UserSeat} seatRef
|
|
124
|
+
*/
|
|
125
|
+
(walletHelper, deposit, offerSpec, address, invitationAmount, seatRef) => ({
|
|
113
126
|
walletHelper,
|
|
114
127
|
deposit,
|
|
115
128
|
status: offerSpec,
|
|
116
129
|
address,
|
|
117
|
-
invitationAmount
|
|
130
|
+
invitationAmount,
|
|
118
131
|
seatRef,
|
|
119
132
|
}),
|
|
120
133
|
{
|
|
121
134
|
helper: {
|
|
135
|
+
/**
|
|
136
|
+
* @param {Record<string, unknown>} offerStatusUpdates
|
|
137
|
+
*/
|
|
122
138
|
updateStatus(offerStatusUpdates) {
|
|
123
139
|
const { state } = this;
|
|
124
140
|
state.status = harden({ ...state.status, ...offerStatusUpdates });
|
|
@@ -141,6 +157,7 @@ export const prepareOfferWatcher = baggage => {
|
|
|
141
157
|
);
|
|
142
158
|
},
|
|
143
159
|
|
|
160
|
+
/** @param {unknown} result */
|
|
144
161
|
publishResult(result) {
|
|
145
162
|
const { state, facets } = this;
|
|
146
163
|
|
|
@@ -157,6 +174,7 @@ export const prepareOfferWatcher = baggage => {
|
|
|
157
174
|
facets.helper.updateStatus({ result });
|
|
158
175
|
break;
|
|
159
176
|
case 'copyRecord':
|
|
177
|
+
// @ts-expect-error narrowed by passStyle
|
|
160
178
|
if ('invitationMakers' in result) {
|
|
161
179
|
// save for continuing invitation offer
|
|
162
180
|
|
|
@@ -164,6 +182,7 @@ export const prepareOfferWatcher = baggage => {
|
|
|
164
182
|
String(state.status.id),
|
|
165
183
|
state.invitationAmount,
|
|
166
184
|
result.invitationMakers,
|
|
185
|
+
// @ts-expect-error narrowed by passStyle
|
|
167
186
|
result.publicSubscribers,
|
|
168
187
|
);
|
|
169
188
|
}
|
|
@@ -174,6 +193,22 @@ export const prepareOfferWatcher = baggage => {
|
|
|
174
193
|
facets.helper.updateStatus({ result: UNPUBLISHED_RESULT });
|
|
175
194
|
}
|
|
176
195
|
},
|
|
196
|
+
/**
|
|
197
|
+
* Called when the offer result promise rejects. The other two watchers
|
|
198
|
+
* are waiting for particular values out of Zoe but they settle at the same time
|
|
199
|
+
* and don't need their own error handling.
|
|
200
|
+
* @param {Error} err
|
|
201
|
+
*/
|
|
202
|
+
handleError(err) {
|
|
203
|
+
const { facets } = this;
|
|
204
|
+
facets.helper.updateStatus({ error: err.toString() });
|
|
205
|
+
const { seatRef } = this.state;
|
|
206
|
+
void E.when(E(seatRef).hasExited(), hasExited => {
|
|
207
|
+
if (!hasExited) {
|
|
208
|
+
void E(seatRef).tryExit();
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
},
|
|
177
212
|
},
|
|
178
213
|
|
|
179
214
|
/** @type {OutcomeWatchers['paymentWatcher']} */
|
|
@@ -190,13 +225,17 @@ export const prepareOfferWatcher = baggage => {
|
|
|
190
225
|
facets.helper.updateStatus({ payouts: amounts });
|
|
191
226
|
},
|
|
192
227
|
/**
|
|
193
|
-
*
|
|
228
|
+
* If promise disconnected, watch again. Or if there's an Error, handle it.
|
|
229
|
+
*
|
|
230
|
+
* @param {Error | import('@agoric/internal/src/upgrade-api.js').UpgradeDisconnection} reason
|
|
194
231
|
* @param {UserSeat} seat
|
|
195
232
|
*/
|
|
196
|
-
onRejected(
|
|
233
|
+
onRejected(reason, seat) {
|
|
197
234
|
const { facets } = this;
|
|
198
|
-
if (isUpgradeDisconnection(
|
|
235
|
+
if (isUpgradeDisconnection(reason)) {
|
|
199
236
|
void watchForPayout(facets, seat);
|
|
237
|
+
} else {
|
|
238
|
+
facets.helper.handleError(reason);
|
|
200
239
|
}
|
|
201
240
|
},
|
|
202
241
|
},
|
|
@@ -208,13 +247,17 @@ export const prepareOfferWatcher = baggage => {
|
|
|
208
247
|
facets.helper.publishResult(result);
|
|
209
248
|
},
|
|
210
249
|
/**
|
|
211
|
-
*
|
|
250
|
+
* If promise disconnected, watch again. Or if there's an Error, handle it.
|
|
251
|
+
*
|
|
252
|
+
* @param {Error | import('@agoric/internal/src/upgrade-api.js').UpgradeDisconnection} reason
|
|
212
253
|
* @param {UserSeat} seat
|
|
213
254
|
*/
|
|
214
|
-
onRejected(
|
|
255
|
+
onRejected(reason, seat) {
|
|
215
256
|
const { facets } = this;
|
|
216
|
-
if (isUpgradeDisconnection(
|
|
257
|
+
if (isUpgradeDisconnection(reason)) {
|
|
217
258
|
void watchForOfferResult(facets, seat);
|
|
259
|
+
} else {
|
|
260
|
+
facets.helper.handleError(reason);
|
|
218
261
|
}
|
|
219
262
|
},
|
|
220
263
|
},
|
|
@@ -227,12 +270,18 @@ export const prepareOfferWatcher = baggage => {
|
|
|
227
270
|
facets.helper.updateStatus({ numWantsSatisfied: numSatisfied });
|
|
228
271
|
},
|
|
229
272
|
/**
|
|
230
|
-
*
|
|
273
|
+
* If promise disconnected, watch again.
|
|
274
|
+
*
|
|
275
|
+
* Errors are handled by the paymentWatcher because numWantsSatisfied()
|
|
276
|
+
* and getPayouts() settle the same (they await the same promise and
|
|
277
|
+
* then synchronously return a local value).
|
|
278
|
+
*
|
|
279
|
+
* @param {Error | import('@agoric/internal/src/upgrade-api.js').UpgradeDisconnection} reason
|
|
231
280
|
* @param {UserSeat} seat
|
|
232
281
|
*/
|
|
233
|
-
onRejected(
|
|
282
|
+
onRejected(reason, seat) {
|
|
234
283
|
const { facets } = this;
|
|
235
|
-
if (isUpgradeDisconnection(
|
|
284
|
+
if (isUpgradeDisconnection(reason)) {
|
|
236
285
|
void watchForNumWants(facets, seat);
|
|
237
286
|
}
|
|
238
287
|
},
|
package/src/smartWallet.d.ts
CHANGED
|
@@ -5,11 +5,11 @@ export function prepareSmartWallet(baggage: import('@agoric/vat-data').Baggage,
|
|
|
5
5
|
/**
|
|
6
6
|
* Umarshals the actionCapData and delegates to the appropriate action handler.
|
|
7
7
|
*
|
|
8
|
-
* @param {import('@endo/marshal').CapData<string>} actionCapData of type BridgeAction
|
|
8
|
+
* @param {import('@endo/marshal').CapData<string | null>} actionCapData of type BridgeAction
|
|
9
9
|
* @param {boolean} [canSpend]
|
|
10
10
|
* @returns {Promise<void>}
|
|
11
11
|
*/
|
|
12
|
-
handleBridgeAction(actionCapData: import('@endo/marshal').CapData<string>, canSpend?: boolean | undefined): Promise<void>;
|
|
12
|
+
handleBridgeAction(actionCapData: import('@endo/marshal').CapData<string | null>, canSpend?: boolean | undefined): Promise<void>;
|
|
13
13
|
getDepositFacet(): import("@endo/exo/src/exo-makers.js").Guarded<{
|
|
14
14
|
/**
|
|
15
15
|
* Put the assets from the payment into the appropriate purse.
|
|
@@ -57,8 +57,7 @@ export function prepareSmartWallet(baggage: import('@agoric/vat-data').Baggage,
|
|
|
57
57
|
};
|
|
58
58
|
};
|
|
59
59
|
/**
|
|
60
|
-
*
|
|
61
|
-
* repair has taken place.
|
|
60
|
+
* To be called once ever per wallet.
|
|
62
61
|
*
|
|
63
62
|
* @param {object} key
|
|
64
63
|
*/
|
|
@@ -177,7 +176,7 @@ export type ImmutableState = Readonly<UniqueParams & {
|
|
|
177
176
|
paymentQueues: MapStore<Brand, Array<Payment>>;
|
|
178
177
|
offerToInvitationMakers: MapStore<string, import('./types.js').InvitationMakers>;
|
|
179
178
|
offerToPublicSubscriberPaths: MapStore<string, Record<string, string>>;
|
|
180
|
-
offerToUsedInvitation: MapStore<string, Amount
|
|
179
|
+
offerToUsedInvitation: MapStore<string, Amount<'set'>>;
|
|
181
180
|
purseBalances: MapStore<Purse, Amount>;
|
|
182
181
|
updateRecorderKit: import('@agoric/zoe/src/contractSupport/recorder.js').RecorderKit<UpdateRecord>;
|
|
183
182
|
currentRecorderKit: import('@agoric/zoe/src/contractSupport/recorder.js').RecorderKit<CurrentWalletRecord>;
|
package/src/smartWallet.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"smartWallet.d.ts","sourceRoot":"","sources":["smartWallet.js"],"names":[],"mappings":"AAiOA,kDAAmD;AAiB5C,4CAHI,OAAO,kBAAkB,EAAE,OAAO,UAClC,YAAY;
|
|
1
|
+
{"version":3,"file":"smartWallet.d.ts","sourceRoot":"","sources":["smartWallet.js"],"names":[],"mappings":"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"}
|
package/src/smartWallet.js
CHANGED
|
@@ -173,7 +173,7 @@ const trace = makeTracer('SmrtWlt');
|
|
|
173
173
|
* paymentQueues: MapStore<Brand, Array<Payment>>,
|
|
174
174
|
* offerToInvitationMakers: MapStore<string, import('./types.js').InvitationMakers>,
|
|
175
175
|
* offerToPublicSubscriberPaths: MapStore<string, Record<string, string>>,
|
|
176
|
-
* offerToUsedInvitation: MapStore<string, Amount
|
|
176
|
+
* offerToUsedInvitation: MapStore<string, Amount<'set'>>,
|
|
177
177
|
* purseBalances: MapStore<Purse, Amount>,
|
|
178
178
|
* updateRecorderKit: import('@agoric/zoe/src/contractSupport/recorder.js').RecorderKit<UpdateRecord>,
|
|
179
179
|
* currentRecorderKit: import('@agoric/zoe/src/contractSupport/recorder.js').RecorderKit<CurrentWalletRecord>,
|
|
@@ -456,6 +456,7 @@ export const prepareSmartWallet = (baggage, shared) => {
|
|
|
456
456
|
}),
|
|
457
457
|
};
|
|
458
458
|
|
|
459
|
+
// TODO move to top level so its type can be exported
|
|
459
460
|
/**
|
|
460
461
|
* Make the durable object to return, but taking some parameters that are awaited by a wrapping function.
|
|
461
462
|
* This is necessary because the class kit construction helpers, `initState` and `finish` run synchronously
|
|
@@ -643,24 +644,47 @@ export const prepareSmartWallet = (baggage, shared) => {
|
|
|
643
644
|
const offerSpec = liveOffers.get(seatId);
|
|
644
645
|
const seat = liveOfferSeats.get(seatId);
|
|
645
646
|
|
|
646
|
-
const
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
offerSpec,
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
647
|
+
const watchOutcome = (async () => {
|
|
648
|
+
await null;
|
|
649
|
+
let invitationAmount = state.offerToUsedInvitation.has(
|
|
650
|
+
// @ts-expect-error older type allowed number
|
|
651
|
+
offerSpec.id,
|
|
652
|
+
)
|
|
653
|
+
? state.offerToUsedInvitation.get(
|
|
654
|
+
// @ts-expect-error older type allowed number
|
|
655
|
+
offerSpec.id,
|
|
656
|
+
)
|
|
657
|
+
: undefined;
|
|
658
|
+
if (invitationAmount) {
|
|
659
|
+
facets.helper.logWalletInfo(
|
|
660
|
+
'recovered invitation amount for offer',
|
|
661
|
+
offerSpec.id,
|
|
662
|
+
);
|
|
663
|
+
} else {
|
|
664
|
+
facets.helper.logWalletInfo(
|
|
665
|
+
'inferring invitation amount for offer',
|
|
666
|
+
offerSpec.id,
|
|
667
|
+
);
|
|
668
|
+
const tempInvitation = invitationFromSpec(
|
|
669
|
+
offerSpec.invitationSpec,
|
|
670
|
+
);
|
|
671
|
+
invitationAmount =
|
|
672
|
+
await E(invitationIssuer).getAmountOf(tempInvitation);
|
|
673
|
+
void E(invitationIssuer).burn(tempInvitation);
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
const watcher = makeOfferWatcher(
|
|
677
|
+
facets.helper,
|
|
678
|
+
facets.deposit,
|
|
679
|
+
offerSpec,
|
|
680
|
+
address,
|
|
681
|
+
invitationAmount,
|
|
682
|
+
seat,
|
|
683
|
+
);
|
|
684
|
+
return watchOfferOutcomes(watcher, seat);
|
|
685
|
+
})();
|
|
663
686
|
trace(`Repaired seat ${seatId} for wallet ${address}`);
|
|
687
|
+
watcherPromises.push(watchOutcome);
|
|
664
688
|
}
|
|
665
689
|
|
|
666
690
|
await Promise.all(watcherPromises);
|
|
@@ -830,6 +854,10 @@ export const prepareSmartWallet = (baggage, shared) => {
|
|
|
830
854
|
|
|
831
855
|
payments: {
|
|
832
856
|
/**
|
|
857
|
+
* Withdraw the offered amount from the appropriate purse of this wallet.
|
|
858
|
+
*
|
|
859
|
+
* Save its amount in liveOfferPayments in case we need to reclaim the payment.
|
|
860
|
+
*
|
|
833
861
|
* @param {AmountKeywordRecord} give
|
|
834
862
|
* @param {OfferId} offerId
|
|
835
863
|
* @returns {PaymentPKeywordRecord}
|
|
@@ -845,8 +873,8 @@ export const prepareSmartWallet = (baggage, shared) => {
|
|
|
845
873
|
.getLiveOfferPayments()
|
|
846
874
|
.init(offerId, brandPaymentRecord);
|
|
847
875
|
|
|
848
|
-
// Add each payment to
|
|
849
|
-
// there's an error
|
|
876
|
+
// Add each payment amount to brandPaymentRecord as it is withdrawn. If
|
|
877
|
+
// there's an error later, we can use it to redeposit the correct amount.
|
|
850
878
|
return objectMap(give, amount => {
|
|
851
879
|
/** @type {Promise<Purse>} */
|
|
852
880
|
const purseP = facets.helper.purseForBrand(amount.brand);
|
|
@@ -867,19 +895,27 @@ export const prepareSmartWallet = (baggage, shared) => {
|
|
|
867
895
|
});
|
|
868
896
|
},
|
|
869
897
|
|
|
898
|
+
/**
|
|
899
|
+
* Find the live payments for the offer and deposit them back in the appropriate purses.
|
|
900
|
+
*
|
|
901
|
+
* @param {OfferId} offerId
|
|
902
|
+
* @returns {Promise<void>}
|
|
903
|
+
*/
|
|
870
904
|
async tryReclaimingWithdrawnPayments(offerId) {
|
|
871
905
|
const { facets } = this;
|
|
872
906
|
|
|
907
|
+
await null;
|
|
908
|
+
|
|
873
909
|
const liveOfferPayments = facets.helper.getLiveOfferPayments();
|
|
874
910
|
if (liveOfferPayments.has(offerId)) {
|
|
875
911
|
const brandPaymentRecord = liveOfferPayments.get(offerId);
|
|
876
912
|
if (!brandPaymentRecord) {
|
|
877
|
-
return
|
|
913
|
+
return;
|
|
878
914
|
}
|
|
879
915
|
// Use allSettled to ensure we attempt all the deposits, regardless of
|
|
880
916
|
// individual rejections.
|
|
881
|
-
|
|
882
|
-
Array.from(brandPaymentRecord.entries()).map(
|
|
917
|
+
await Promise.allSettled(
|
|
918
|
+
Array.from(brandPaymentRecord.entries()).map(([b, p]) => {
|
|
883
919
|
// Wait for the withdrawal to complete. This protects against a
|
|
884
920
|
// race when updating paymentToPurse.
|
|
885
921
|
const purseP = facets.helper.purseForBrand(b);
|
|
@@ -966,22 +1002,24 @@ export const prepareSmartWallet = (baggage, shared) => {
|
|
|
966
1002
|
|
|
967
1003
|
// await so that any errors are caught and handled below
|
|
968
1004
|
await watchOfferOutcomes(watcher, seatRef);
|
|
969
|
-
} catch (
|
|
970
|
-
|
|
1005
|
+
} catch (reason) {
|
|
1006
|
+
// This block only runs if the block above fails during one vat incarnation.
|
|
1007
|
+
facets.helper.logWalletError('IMMEDIATE OFFER ERROR:', reason);
|
|
971
1008
|
|
|
972
|
-
//
|
|
973
|
-
if (
|
|
1009
|
+
// Update status to observers
|
|
1010
|
+
if (isUpgradeDisconnection(reason)) {
|
|
974
1011
|
// The offer watchers will reconnect. Don't reclaim or exit
|
|
975
1012
|
return;
|
|
976
1013
|
} else if (watcher) {
|
|
977
|
-
watcher
|
|
1014
|
+
// The watcher's onRejected will updateStatus()
|
|
978
1015
|
} else {
|
|
979
1016
|
facets.helper.updateStatus({
|
|
980
|
-
error:
|
|
1017
|
+
error: reason.toString(),
|
|
981
1018
|
...offerSpec,
|
|
982
1019
|
});
|
|
983
1020
|
}
|
|
984
1021
|
|
|
1022
|
+
// Backstop recovery, in case something very basic fails.
|
|
985
1023
|
if (offerSpec?.proposal?.give) {
|
|
986
1024
|
facets.payments
|
|
987
1025
|
.tryReclaimingWithdrawnPayments(offerSpec.id)
|
|
@@ -993,15 +1031,9 @@ export const prepareSmartWallet = (baggage, shared) => {
|
|
|
993
1031
|
);
|
|
994
1032
|
}
|
|
995
1033
|
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
void E(seatRef).tryExit();
|
|
1000
|
-
}
|
|
1001
|
-
});
|
|
1002
|
-
}
|
|
1003
|
-
|
|
1004
|
-
throw err;
|
|
1034
|
+
// XXX tests rely on throwing immediate errors, not covering the
|
|
1035
|
+
// error handling in the event the failure is after an upgrade
|
|
1036
|
+
throw reason;
|
|
1005
1037
|
}
|
|
1006
1038
|
},
|
|
1007
1039
|
/**
|
|
@@ -1020,7 +1052,7 @@ export const prepareSmartWallet = (baggage, shared) => {
|
|
|
1020
1052
|
/**
|
|
1021
1053
|
* Umarshals the actionCapData and delegates to the appropriate action handler.
|
|
1022
1054
|
*
|
|
1023
|
-
* @param {import('@endo/marshal').CapData<string>} actionCapData of type BridgeAction
|
|
1055
|
+
* @param {import('@endo/marshal').CapData<string | null>} actionCapData of type BridgeAction
|
|
1024
1056
|
* @param {boolean} [canSpend]
|
|
1025
1057
|
* @returns {Promise<void>}
|
|
1026
1058
|
*/
|
|
@@ -1102,9 +1134,9 @@ export const prepareSmartWallet = (baggage, shared) => {
|
|
|
1102
1134
|
},
|
|
1103
1135
|
});
|
|
1104
1136
|
},
|
|
1137
|
+
// TODO remove this and repairUnwatchedSeats once the repair has taken place.
|
|
1105
1138
|
/**
|
|
1106
|
-
*
|
|
1107
|
-
* repair has taken place.
|
|
1139
|
+
* To be called once ever per wallet.
|
|
1108
1140
|
*
|
|
1109
1141
|
* @param {object} key
|
|
1110
1142
|
*/
|
|
@@ -1115,8 +1147,12 @@ export const prepareSmartWallet = (baggage, shared) => {
|
|
|
1115
1147
|
return;
|
|
1116
1148
|
}
|
|
1117
1149
|
|
|
1118
|
-
|
|
1119
|
-
|
|
1150
|
+
facets.helper.repairUnwatchedSeats().catch(e => {
|
|
1151
|
+
console.error('repairUnwatchedSeats rejection', e);
|
|
1152
|
+
});
|
|
1153
|
+
facets.helper.repairUnwatchedPurses().catch(e => {
|
|
1154
|
+
console.error('repairUnwatchedPurses rejection', e);
|
|
1155
|
+
});
|
|
1120
1156
|
trace(`repaired wallet ${state.address}`);
|
|
1121
1157
|
},
|
|
1122
1158
|
},
|
package/src/types.d.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
import type { ERef } from '@endo/far';
|
|
9
9
|
import type { CapData } from '@endo/marshal';
|
|
10
|
-
import type {
|
|
10
|
+
import type { agoric } from '@agoric/cosmic-proto';
|
|
11
11
|
import type { AgoricNamesRemotes } from '@agoric/vats/tools/board-utils.js';
|
|
12
12
|
import type { OfferSpec } from './offers.js';
|
|
13
13
|
|
|
@@ -40,7 +40,7 @@ export type BridgeActionCapData = WalletCapData<
|
|
|
40
40
|
/**
|
|
41
41
|
* Defined by walletAction struct in msg_server.go
|
|
42
42
|
*
|
|
43
|
-
* @see {
|
|
43
|
+
* @see {agoric.swingset.MsgWalletAction} and walletSpendAction in msg_server.go
|
|
44
44
|
*/
|
|
45
45
|
export type WalletActionMsg = {
|
|
46
46
|
type: 'WALLET_ACTION';
|
|
@@ -55,7 +55,7 @@ export type WalletActionMsg = {
|
|
|
55
55
|
/**
|
|
56
56
|
* Defined by walletSpendAction struct in msg_server.go
|
|
57
57
|
*
|
|
58
|
-
* @see {MsgWalletSpendAction} and walletSpendAction in msg_server.go
|
|
58
|
+
* @see {agoric.swingset.MsgWalletSpendAction} and walletSpendAction in msg_server.go
|
|
59
59
|
*/
|
|
60
60
|
export type WalletSpendActionMsg = {
|
|
61
61
|
type: 'WALLET_SPEND_ACTION';
|
package/src/walletFactory.d.ts
CHANGED
|
@@ -37,7 +37,7 @@ export function prepare(zcf: ZCF<SmartWalletContractTerms>, privateArgs: {
|
|
|
37
37
|
* and creating a new one.
|
|
38
38
|
*/
|
|
39
39
|
provideSmartWallet(address: string, bank: ERef<import('@agoric/vats/src/vat-bank.js').Bank>, namesByAddressAdmin: ERef<import('@agoric/vats/src/types.js').NameAdmin>): Promise<[wallet: {
|
|
40
|
-
handleBridgeAction(actionCapData: import("@endo/marshal").CapData<string>, canSpend?: boolean | undefined): Promise<void>;
|
|
40
|
+
handleBridgeAction(actionCapData: import("@endo/marshal").CapData<string | null>, canSpend?: boolean | undefined): Promise<void>;
|
|
41
41
|
getDepositFacet(): import("@endo/exo/src/exo-makers.js").Guarded<{
|
|
42
42
|
receive(payment: Payment<AssetKind>): Promise<Amount<AssetKind>>;
|
|
43
43
|
}>;
|
|
@@ -61,7 +61,7 @@ export function prepare(zcf: ZCF<SmartWalletContractTerms>, privateArgs: {
|
|
|
61
61
|
};
|
|
62
62
|
repairWalletForIncarnation2(key: any): void;
|
|
63
63
|
} & import("@endo/exo/src/get-interface.js").GetInterfaceGuard<{
|
|
64
|
-
handleBridgeAction(actionCapData: import("@endo/marshal").CapData<string>, canSpend?: boolean | undefined): Promise<void>;
|
|
64
|
+
handleBridgeAction(actionCapData: import("@endo/marshal").CapData<string | null>, canSpend?: boolean | undefined): Promise<void>;
|
|
65
65
|
getDepositFacet(): import("@endo/exo/src/exo-makers.js").Guarded<{
|
|
66
66
|
receive(payment: Payment<AssetKind>): Promise<Amount<AssetKind>>;
|
|
67
67
|
}>;
|
|
@@ -85,7 +85,7 @@ export function prepare(zcf: ZCF<SmartWalletContractTerms>, privateArgs: {
|
|
|
85
85
|
};
|
|
86
86
|
repairWalletForIncarnation2(key: any): void;
|
|
87
87
|
}> & import("@endo/eventual-send").RemotableBrand<{}, {
|
|
88
|
-
handleBridgeAction(actionCapData: import("@endo/marshal").CapData<string>, canSpend?: boolean | undefined): Promise<void>;
|
|
88
|
+
handleBridgeAction(actionCapData: import("@endo/marshal").CapData<string | null>, canSpend?: boolean | undefined): Promise<void>;
|
|
89
89
|
getDepositFacet(): import("@endo/exo/src/exo-makers.js").Guarded<{
|
|
90
90
|
receive(payment: Payment<AssetKind>): Promise<Amount<AssetKind>>;
|
|
91
91
|
}>;
|
|
@@ -109,7 +109,7 @@ export function prepare(zcf: ZCF<SmartWalletContractTerms>, privateArgs: {
|
|
|
109
109
|
};
|
|
110
110
|
repairWalletForIncarnation2(key: any): void;
|
|
111
111
|
} & import("@endo/exo/src/get-interface.js").GetInterfaceGuard<{
|
|
112
|
-
handleBridgeAction(actionCapData: import("@endo/marshal").CapData<string>, canSpend?: boolean | undefined): Promise<void>;
|
|
112
|
+
handleBridgeAction(actionCapData: import("@endo/marshal").CapData<string | null>, canSpend?: boolean | undefined): Promise<void>;
|
|
113
113
|
getDepositFacet(): import("@endo/exo/src/exo-makers.js").Guarded<{
|
|
114
114
|
receive(payment: Payment<AssetKind>): Promise<Amount<AssetKind>>;
|
|
115
115
|
}>;
|