@agoric/smart-wallet 0.5.4-u13.0 → 0.5.4-u14.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/CHANGELOG.md CHANGED
@@ -3,6 +3,26 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ### [0.5.4-u14.0](https://github.com/Agoric/agoric/compare/@agoric/smart-wallet@0.5.4-u13.0...@agoric/smart-wallet@0.5.4-u14.0) (2024-02-27)
7
+
8
+
9
+ ### Features
10
+
11
+ * smartWallet verstion 2 with watchedPromises ([31d7c2f](https://github.com/Agoric/agoric/commit/31d7c2f4ecea9a34956cc6716fb8d73cbeb12e64))
12
+ * repairUnwatchedPurses ([aad9f16](https://github.com/Agoric/agoric/commit/aad9f1640e46da4e80f959767a485e1ee7fb0ea5))
13
+
14
+
15
+ ### Bug Fixes
16
+
17
+ * burn invitation made for repair ([be80ef9](https://github.com/Agoric/agoric/commit/be80ef92b7cbbb161e00414851ccf397ec9d3180))
18
+ * handle promises in repairWalletForIncarnation2 ([2a8dab2](https://github.com/Agoric/agoric/commit/2a8dab23ae0d20f77481f26d7ed098f649537bf7))
19
+ * publish 'error' message for failure after upgrade ([d4ab282](https://github.com/Agoric/agoric/commit/d4ab282d8b07fdaf52326d5952fcb1ad9528b353))
20
+ * re-use invitation from offerToUsedInvitation ([445dec7](https://github.com/Agoric/agoric/commit/445dec7d468609a41cf1c3078570a282f6789779))
21
+ * repair incorrect fix for repairWalletForIncarnation2 (backport [#8984](https://github.com/Agoric/agoric/issues/8984)) ([#8985](https://github.com/Agoric/agoric/issues/8985)) ([b818d30](https://github.com/Agoric/agoric/commit/b818d30fed4fdaeb3f76af920e6a67824c608318))
22
+ * **smartWallet:** handle upgrade disconnects from purse notifiers ([f82b82b](https://github.com/Agoric/agoric/commit/f82b82bb79b21c0789609cc26b1c8f58ccdb32bc))
23
+
24
+
25
+
6
26
  ### [0.5.4-u13.0](https://github.com/Agoric/agoric/compare/@agoric/smart-wallet@0.5.4-u12.0...@agoric/smart-wallet@0.5.4-u13.0) (2023-12-07)
7
27
 
8
28
  **Note:** Version bump only for package @agoric/smart-wallet
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agoric/smart-wallet",
3
- "version": "0.5.4-u13.0",
3
+ "version": "0.5.4-u14.0",
4
4
  "description": "Wallet contract",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -16,7 +16,8 @@
16
16
  "lint:eslint": "eslint ."
17
17
  },
18
18
  "devDependencies": {
19
- "@agoric/cosmic-proto": "^0.3.0",
19
+ "@agoric/cosmic-proto": "^0.3.1-u14.0",
20
+ "@agoric/vats": "^0.15.2-u13.0",
20
21
  "@endo/bundle-source": "2.5.2-upstream-rollup",
21
22
  "@endo/captp": "3.1.1",
22
23
  "@endo/init": "0.5.56",
@@ -25,15 +26,16 @@
25
26
  },
26
27
  "dependencies": {
27
28
  "@agoric/assert": "^0.6.1-u11wf.0",
28
- "@agoric/casting": "^0.4.3-u13.0",
29
- "@agoric/ertp": "^0.16.3-u13.0",
30
- "@agoric/internal": "^0.4.0-u13.0",
31
- "@agoric/notifier": "^0.6.3-u13.0",
32
- "@agoric/store": "^0.9.3-u13.0",
33
- "@agoric/swingset-vat": "^0.32.3-u13.0",
34
- "@agoric/vat-data": "^0.5.3-u13.0",
35
- "@agoric/vats": "^0.15.2-u13.0",
36
- "@agoric/zoe": "^0.26.3-u13.0",
29
+ "@agoric/casting": "^0.4.3-u14.0",
30
+ "@agoric/deploy-script-support": "^0.10.4-u14.0",
31
+ "@agoric/ertp": "^0.16.3-u14.0",
32
+ "@agoric/internal": "^0.4.0-u14.0",
33
+ "@agoric/notifier": "^0.6.3-u14.0",
34
+ "@agoric/store": "^0.9.3-u14.0",
35
+ "@agoric/swingset-vat": "^0.32.3-u14.0",
36
+ "@agoric/vat-data": "^0.5.3-u14.0",
37
+ "@agoric/vats": "^0.15.2-u14.0",
38
+ "@agoric/zoe": "^0.26.3-u14.0",
37
39
  "@endo/eventual-send": "0.17.2",
38
40
  "@endo/far": "0.2.18",
39
41
  "@endo/marshal": "0.8.5",
@@ -63,5 +65,5 @@
63
65
  "publishConfig": {
64
66
  "access": "public"
65
67
  },
66
- "gitHead": "5a6cdeb0c18ae9700d706445acf402f8d1e873c3"
68
+ "gitHead": "b3a6f3374cb3bddab39fc6d6f426429cae6c29c6"
67
69
  }
@@ -0,0 +1,66 @@
1
+ export function watchOfferOutcomes(watchers: OutcomeWatchers, seat: UserSeat): Promise<[unknown, 0 | 1, PaymentPKeywordRecord]>;
2
+ export function prepareOfferWatcher(baggage: MapStore<string, unknown>): (walletHelper: any, deposit: any, offerSpec: import("./offers.js").OfferSpec, address: string, invitationAmount: Amount<"set">, seatRef: UserSeat<unknown>) => {
3
+ helper: {
4
+ /**
5
+ * @param {Record<string, unknown>} offerStatusUpdates
6
+ */
7
+ updateStatus(offerStatusUpdates: Record<string, unknown>): void;
8
+ onNewContinuingOffer(offerId: any, invitationAmount: any, invitationMakers: any, publicSubscribers: any): void;
9
+ publishResult(result: any): void;
10
+ /**
11
+ * Called when the offer result promise rejects. The other two watchers
12
+ * are waiting for particular values out of Zoe but they settle at the same time
13
+ * and don't need their own error handling.
14
+ * @param {Error} err
15
+ */
16
+ handleError(err: Error): void;
17
+ };
18
+ /** @type {OutcomeWatchers['paymentWatcher']} */
19
+ paymentWatcher: OutcomeWatchers['paymentWatcher'];
20
+ /** @type {OutcomeWatchers['resultWatcher']} */
21
+ resultWatcher: OutcomeWatchers['resultWatcher'];
22
+ /** @type {OutcomeWatchers['numWantsWatcher']} */
23
+ numWantsWatcher: OutcomeWatchers['numWantsWatcher'];
24
+ } & import("@endo/eventual-send").RemotableBrand<{}, {
25
+ helper: {
26
+ /**
27
+ * @param {Record<string, unknown>} offerStatusUpdates
28
+ */
29
+ updateStatus(offerStatusUpdates: Record<string, unknown>): void;
30
+ onNewContinuingOffer(offerId: any, invitationAmount: any, invitationMakers: any, publicSubscribers: any): void;
31
+ publishResult(result: any): void;
32
+ /**
33
+ * Called when the offer result promise rejects. The other two watchers
34
+ * are waiting for particular values out of Zoe but they settle at the same time
35
+ * and don't need their own error handling.
36
+ * @param {Error} err
37
+ */
38
+ handleError(err: Error): void;
39
+ };
40
+ /** @type {OutcomeWatchers['paymentWatcher']} */
41
+ paymentWatcher: OutcomeWatchers['paymentWatcher'];
42
+ /** @type {OutcomeWatchers['resultWatcher']} */
43
+ resultWatcher: OutcomeWatchers['resultWatcher'];
44
+ /** @type {OutcomeWatchers['numWantsWatcher']} */
45
+ numWantsWatcher: OutcomeWatchers['numWantsWatcher'];
46
+ }>;
47
+ export type OfferStatus = import('./offers.js').OfferSpec & {
48
+ error?: string;
49
+ numWantsSatisfied?: number;
50
+ result?: unknown | typeof import('./offers.js').UNPUBLISHED_RESULT;
51
+ payouts?: AmountKeywordRecord;
52
+ };
53
+ /**
54
+ * <T, [UserSeat]
55
+ */
56
+ export type OfferPromiseWatcher<T extends unknown> = {
57
+ onFulfilled: (any: any) => any;
58
+ onRejected: (err: Error, seat: any) => void;
59
+ };
60
+ export type OutcomeWatchers = {
61
+ resultWatcher: OfferPromiseWatcher<unknown>;
62
+ numWantsWatcher: OfferPromiseWatcher<number>;
63
+ paymentWatcher: OfferPromiseWatcher<PaymentPKeywordRecord>;
64
+ };
65
+ export type MakeOfferWatcher = ReturnType<typeof prepareOfferWatcher>;
66
+ //# sourceMappingURL=offerWatcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"offerWatcher.d.ts","sourceRoot":"","sources":["offerWatcher.js"],"names":[],"mappings":"AAyEO,6CAHI,eAAe,QACf,QAAQ,oDAQlB;AAkCM;;QAwBC;;WAEG;yCADQ,OAAO,MAAM,EAAE,OAAO,CAAC;;;QAyDlC;;;;;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;;;QA/H3C;;WAEG;yCADQ,OAAO,MAAM,EAAE,OAAO,CAAC;;;QAyDlC;;;;;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;;;;;+BAKiC,GAAG;sBAAoB,KAAK,QAAQ,GAAG,KAAK,IAAI;;8BAIxE;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"}
@@ -0,0 +1,294 @@
1
+ import { E, passStyleOf } from '@endo/far';
2
+
3
+ import { isUpgradeDisconnection } from '@agoric/internal/src/upgrade-api.js';
4
+ import { prepareExoClassKit, watchPromise } from '@agoric/vat-data';
5
+ import { M } from '@agoric/store';
6
+ import {
7
+ PaymentPKeywordRecordShape,
8
+ SeatShape,
9
+ } from '@agoric/zoe/src/typeGuards.js';
10
+ import { AmountShape } from '@agoric/ertp/src/typeGuards.js';
11
+ import { deeplyFulfilledObject, objectMap } from '@agoric/internal';
12
+
13
+ import { UNPUBLISHED_RESULT } from './offers.js';
14
+
15
+ /**
16
+ * @typedef {import('./offers.js').OfferSpec & {
17
+ * error?: string,
18
+ * numWantsSatisfied?: number
19
+ * result?: unknown | typeof import('./offers.js').UNPUBLISHED_RESULT,
20
+ * payouts?: AmountKeywordRecord,
21
+ * }} OfferStatus
22
+ */
23
+
24
+ /**
25
+ * @template {any} T
26
+ * @typedef {{ onFulfilled: (any) => any, onRejected: (err: Error, seat: any) => void }} OfferPromiseWatcher<T, [UserSeat]
27
+ */
28
+
29
+ /**
30
+ * @typedef {{
31
+ * resultWatcher: OfferPromiseWatcher<unknown>,
32
+ * numWantsWatcher: OfferPromiseWatcher<number>,
33
+ * paymentWatcher: OfferPromiseWatcher<PaymentPKeywordRecord>,
34
+ * }} OutcomeWatchers
35
+ */
36
+
37
+ /**
38
+ * @param {OutcomeWatchers} watchers
39
+ * @param {UserSeat} seat
40
+ */
41
+ const watchForOfferResult = ({ resultWatcher }, seat) => {
42
+ const p = E(seat).getOfferResult();
43
+ // @ts-expect-error missing declarations?
44
+ watchPromise(p, resultWatcher, seat);
45
+ return p;
46
+ };
47
+
48
+ /**
49
+ * @param {OutcomeWatchers} watchers
50
+ * @param {UserSeat} seat
51
+ */
52
+ const watchForNumWants = ({ numWantsWatcher }, seat) => {
53
+ const p = E(seat).numWantsSatisfied();
54
+ // @ts-expect-error missing declarations?
55
+ watchPromise(p, numWantsWatcher, seat);
56
+ return p;
57
+ };
58
+
59
+ /**
60
+ * @param {OutcomeWatchers} watchers
61
+ * @param {UserSeat} seat
62
+ */
63
+ const watchForPayout = ({ paymentWatcher }, seat) => {
64
+ const p = E(seat).getPayouts();
65
+ // @ts-expect-error missing declarations?
66
+ watchPromise(p, paymentWatcher, seat);
67
+ return p;
68
+ };
69
+
70
+ /**
71
+ * @param {OutcomeWatchers} watchers
72
+ * @param {UserSeat} seat
73
+ */
74
+ export const watchOfferOutcomes = (watchers, seat) => {
75
+ return Promise.all([
76
+ watchForOfferResult(watchers, seat),
77
+ watchForNumWants(watchers, seat),
78
+ watchForPayout(watchers, seat),
79
+ ]);
80
+ };
81
+
82
+ const offerWatcherGuard = harden({
83
+ helper: M.interface('InstanceAdminStorage', {
84
+ updateStatus: M.call(M.any()).returns(),
85
+ onNewContinuingOffer: M.call(
86
+ M.or(M.number(), M.string()),
87
+ AmountShape,
88
+ M.any(),
89
+ )
90
+ .optional(M.record())
91
+ .returns(),
92
+ publishResult: M.call(M.any()).returns(),
93
+ handleError: M.call(M.error()).returns(),
94
+ }),
95
+ paymentWatcher: M.interface('paymentWatcher', {
96
+ onFulfilled: M.call(PaymentPKeywordRecordShape, SeatShape).returns(
97
+ M.promise(),
98
+ ),
99
+ onRejected: M.call(M.any(), SeatShape).returns(),
100
+ }),
101
+ resultWatcher: M.interface('resultWatcher', {
102
+ onFulfilled: M.call(M.any(), SeatShape).returns(),
103
+ onRejected: M.call(M.any(), SeatShape).returns(),
104
+ }),
105
+ numWantsWatcher: M.interface('numWantsWatcher', {
106
+ onFulfilled: M.call(M.number(), SeatShape).returns(),
107
+ onRejected: M.call(M.any(), SeatShape).returns(),
108
+ }),
109
+ });
110
+
111
+ /**
112
+ * @param {import('@agoric/vat-data').Baggage} baggage
113
+ */
114
+ export const prepareOfferWatcher = baggage => {
115
+ return prepareExoClassKit(
116
+ baggage,
117
+ 'OfferWatcher',
118
+ offerWatcherGuard,
119
+ /**
120
+ *
121
+ * @param {*} walletHelper
122
+ * @param {*} deposit
123
+ * @param {import('./offers.js').OfferSpec} offerSpec
124
+ * @param {string} address
125
+ * @param {Amount<'set'>} invitationAmount
126
+ * @param {UserSeat} seatRef
127
+ */
128
+ (walletHelper, deposit, offerSpec, address, invitationAmount, seatRef) => ({
129
+ walletHelper,
130
+ deposit,
131
+ status: offerSpec,
132
+ address,
133
+ invitationAmount,
134
+ seatRef,
135
+ }),
136
+ {
137
+ helper: {
138
+ /**
139
+ * @param {Record<string, unknown>} offerStatusUpdates
140
+ */
141
+ updateStatus(offerStatusUpdates) {
142
+ const { state } = this;
143
+ state.status = harden({ ...state.status, ...offerStatusUpdates });
144
+
145
+ state.walletHelper.updateStatus(state.status);
146
+ },
147
+ onNewContinuingOffer(
148
+ offerId,
149
+ invitationAmount,
150
+ invitationMakers,
151
+ publicSubscribers,
152
+ ) {
153
+ const { state } = this;
154
+
155
+ void state.walletHelper.addContinuingOffer(
156
+ offerId,
157
+ invitationAmount,
158
+ invitationMakers,
159
+ publicSubscribers,
160
+ );
161
+ },
162
+
163
+ publishResult(result) {
164
+ const { state, facets } = this;
165
+
166
+ const passStyle = passStyleOf(result);
167
+ // someday can we get TS to type narrow based on the passStyleOf result match?
168
+ switch (passStyle) {
169
+ case 'bigint':
170
+ case 'boolean':
171
+ case 'null':
172
+ case 'number':
173
+ case 'string':
174
+ case 'symbol':
175
+ case 'undefined':
176
+ facets.helper.updateStatus({ result });
177
+ break;
178
+ case 'copyRecord':
179
+ if ('invitationMakers' in result) {
180
+ // save for continuing invitation offer
181
+
182
+ void facets.helper.onNewContinuingOffer(
183
+ String(state.status.id),
184
+ state.invitationAmount,
185
+ result.invitationMakers,
186
+ result.publicSubscribers,
187
+ );
188
+ }
189
+ facets.helper.updateStatus({ result: UNPUBLISHED_RESULT });
190
+ break;
191
+ default:
192
+ // drop the result
193
+ facets.helper.updateStatus({ result: UNPUBLISHED_RESULT });
194
+ }
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
+ },
212
+ },
213
+
214
+ /** @type {OutcomeWatchers['paymentWatcher']} */
215
+ paymentWatcher: {
216
+ async onFulfilled(payouts) {
217
+ const { state, facets } = this;
218
+
219
+ // This will block until all payouts succeed, but user will be updated
220
+ // since each payout will trigger its corresponding purse notifier.
221
+ const amountPKeywordRecord = objectMap(payouts, paymentRef =>
222
+ E.when(paymentRef, payment => state.deposit.receive(payment)),
223
+ );
224
+ const amounts = await deeplyFulfilledObject(amountPKeywordRecord);
225
+ facets.helper.updateStatus({ payouts: amounts });
226
+ },
227
+ /**
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').DisconnectionObject} reason
231
+ * @param {UserSeat} seat
232
+ */
233
+ onRejected(reason, seat) {
234
+ const { facets } = this;
235
+ if (isUpgradeDisconnection(reason)) {
236
+ void watchForPayout(facets, seat);
237
+ } else {
238
+ facets.helper.handleError(reason);
239
+ }
240
+ },
241
+ },
242
+
243
+ /** @type {OutcomeWatchers['resultWatcher']} */
244
+ resultWatcher: {
245
+ onFulfilled(result) {
246
+ const { facets } = this;
247
+ facets.helper.publishResult(result);
248
+ },
249
+ /**
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').DisconnectionObject} reason
253
+ * @param {UserSeat} seat
254
+ */
255
+ onRejected(reason, seat) {
256
+ const { facets } = this;
257
+ if (isUpgradeDisconnection(reason)) {
258
+ void watchForOfferResult(facets, seat);
259
+ } else {
260
+ facets.helper.handleError(reason);
261
+ }
262
+ },
263
+ },
264
+
265
+ /** @type {OutcomeWatchers['numWantsWatcher']} */
266
+ numWantsWatcher: {
267
+ onFulfilled(numSatisfied) {
268
+ const { facets } = this;
269
+
270
+ facets.helper.updateStatus({ numWantsSatisfied: numSatisfied });
271
+ },
272
+ /**
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').DisconnectionObject} reason
280
+ * @param {UserSeat} seat
281
+ */
282
+ onRejected(reason, seat) {
283
+ const { facets } = this;
284
+ if (isUpgradeDisconnection(reason)) {
285
+ void watchForNumWants(facets, seat);
286
+ }
287
+ },
288
+ },
289
+ },
290
+ );
291
+ };
292
+ harden(prepareOfferWatcher);
293
+
294
+ /** @typedef {ReturnType<typeof prepareOfferWatcher>} MakeOfferWatcher */
package/src/offers.d.ts CHANGED
@@ -11,30 +11,6 @@
11
11
  */
12
12
  /** Value for "result" field when the result can't be published */
13
13
  export const UNPUBLISHED_RESULT: "UNPUBLISHED";
14
- export function makeOfferExecutor({ zoe, depositFacet, invitationIssuer, powers, onStatusChange, onNewContinuingOffer, }: {
15
- zoe: ERef<ZoeService>;
16
- depositFacet: {
17
- receive: (payment: any) => Promise<Amount>;
18
- };
19
- invitationIssuer: ERef<Issuer<'set'>>;
20
- powers: {
21
- logger: Pick<Console, 'info' | 'error'>;
22
- invitationFromSpec: (spec: import('./invitations').InvitationSpec) => ERef<Invitation>;
23
- purseForBrand: (brand: Brand) => Promise<import('./types').RemotePurse>;
24
- };
25
- onStatusChange: (status: OfferStatus) => void;
26
- onNewContinuingOffer: (offerId: string, invitationAmount: Amount<'set'>, invitationMakers: import('./types').RemoteInvitationMakers, publicSubscribers: import('./types').PublicSubscribers | import('@agoric/zoe/src/contractSupport').TopicsRecord) => Promise<void>;
27
- }): {
28
- /**
29
- * Take an offer description provided in capData, augment it with payments and call zoe.offer()
30
- *
31
- * @param {OfferSpec} offerSpec
32
- * @param {(seatRef: UserSeat) => void} onSeatCreated
33
- * @returns {Promise<void>} when the offer has been sent to Zoe; payouts go into this wallet's purses
34
- * @throws if any parts of the offer are determined to be invalid before calling Zoe's `offer()`
35
- */
36
- executeOffer(offerSpec: OfferSpec, onSeatCreated: (seatRef: UserSeat) => void): Promise<void>;
37
- };
38
14
  export type OfferId = number | string;
39
15
  export type OfferSpec = {
40
16
  id: OfferId;
@@ -1 +1 @@
1
- {"version":3,"file":"offers.d.ts","sourceRoot":"","sources":["offers.js"],"names":[],"mappings":"AAIA;;GAEG;AAEH;;;;;;;GAOG;AAEH,kEAAkE;AAClE,+CAAgD;AAwBzC;SAVI,KAAK,UAAU,CAAC;;mCACW,QAAQ,MAAM,CAAC;;sBAC1C,KAAK,OAAO,KAAK,CAAC,CAAC;;gBAEnB,KAAK,OAAO,EAAE,MAAM,GAAE,OAAO,CAAC;mCACvB,OAAO,eAAe,EAAE,cAAc,KAAK,KAAK,UAAU,CAAC;+BAC1D,KAAK,KAAK,QAAQ,OAAO,SAAS,EAAE,WAAW,CAAC;;6BAC/C,WAAW,KAAK,IAAI;oCACnB,MAAM,oBAAoB,OAAO,KAAK,CAAC,oBAAoB,OAAO,SAAS,EAAE,sBAAsB,qBAAqB,OAAO,SAAS,EAAE,iBAAiB,GAAG,OAAO,iCAAiC,EAAE,YAAY,KAAM,QAAQ,IAAI,CAAC;;IAaxP;;;;;;;OAOG;4BAJQ,SAAS,2BACC,QAAQ,KAAK,IAAI,GACzB,QAAQ,IAAI,CAAC;EA0I7B;sBA/LY,MAAM,GAAG,MAAM;wBAIf;IACZ,EAAM,EAAE,OAAO,CAAC;IAChB,cAAkB,EAAE,OAAO,eAAe,EAAE,cAAc,CAAC;IAC3D,QAAY,EAAE,QAAQ,CAAC;IACvB,SAAa,CAAC,EAAE,OAAO,CAAA;CACpB;0BAOS,OAAO,aAAa,EAAE,SAAS,GAAG;IAC9C,KAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B,MAAQ,CAAC,EAAE,OAAO,GAAG,yBAAyB,CAAC;IAC/C,OAAS,CAAC,EAAE,mBAAmB,CAAC;CAC7B"}
1
+ {"version":3,"file":"offers.d.ts","sourceRoot":"","sources":["offers.js"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;;;;GAOG;AAEH,kEAAkE;AAClE,+CAAgD;sBAbnC,MAAM,GAAG,MAAM;wBAIf;IACZ,EAAM,EAAE,OAAO,CAAC;IAChB,cAAkB,EAAE,OAAO,eAAe,EAAE,cAAc,CAAC;IAC3D,QAAY,EAAE,QAAQ,CAAC;IACvB,SAAa,CAAC,EAAE,OAAO,CAAA;CACpB;0BAOS,OAAO,aAAa,EAAE,SAAS,GAAG;IAC9C,KAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B,MAAQ,CAAC,EAAE,OAAO,GAAG,yBAAyB,CAAC;IAC/C,OAAS,CAAC,EAAE,mBAAmB,CAAC;CAC7B"}
package/src/offers.js CHANGED
@@ -1,7 +1,3 @@
1
- import { E, passStyleOf } from '@endo/far';
2
- import { deeplyFulfilledObject } from '@agoric/internal';
3
- import { makePaymentsHelper } from './payments.js';
4
-
5
1
  /**
6
2
  * @typedef {number | string} OfferId
7
3
  */
@@ -26,173 +22,3 @@ export const UNPUBLISHED_RESULT = 'UNPUBLISHED';
26
22
  * payouts?: AmountKeywordRecord,
27
23
  * }} OfferStatus
28
24
  */
29
-
30
- /* eslint-disable jsdoc/check-param-names -- bug(?) with nested objects */
31
- /**
32
- * @param {object} opts
33
- * @param {ERef<ZoeService>} opts.zoe
34
- * @param {{ receive: (payment: *) => Promise<Amount> }} opts.depositFacet
35
- * @param {ERef<Issuer<'set'>>} opts.invitationIssuer
36
- * @param {object} opts.powers
37
- * @param {Pick<Console, 'info'| 'error'>} opts.powers.logger
38
- * @param {(spec: import('./invitations').InvitationSpec) => ERef<Invitation>} opts.powers.invitationFromSpec
39
- * @param {(brand: Brand) => Promise<import('./types').RemotePurse>} opts.powers.purseForBrand
40
- * @param {(status: OfferStatus) => void} opts.onStatusChange
41
- * @param {(offerId: string, invitationAmount: Amount<'set'>, invitationMakers: import('./types').RemoteInvitationMakers, publicSubscribers: import('./types').PublicSubscribers | import('@agoric/zoe/src/contractSupport').TopicsRecord ) => Promise<void>} opts.onNewContinuingOffer
42
- */
43
- export const makeOfferExecutor = ({
44
- zoe,
45
- depositFacet,
46
- invitationIssuer,
47
- powers,
48
- onStatusChange,
49
- onNewContinuingOffer,
50
- }) => {
51
- const { invitationFromSpec, logger, purseForBrand } = powers;
52
-
53
- return {
54
- /**
55
- * Take an offer description provided in capData, augment it with payments and call zoe.offer()
56
- *
57
- * @param {OfferSpec} offerSpec
58
- * @param {(seatRef: UserSeat) => void} onSeatCreated
59
- * @returns {Promise<void>} when the offer has been sent to Zoe; payouts go into this wallet's purses
60
- * @throws if any parts of the offer are determined to be invalid before calling Zoe's `offer()`
61
- */
62
- async executeOffer(offerSpec, onSeatCreated) {
63
- logger.info('starting executeOffer', offerSpec.id);
64
-
65
- const paymentsManager = makePaymentsHelper(purseForBrand, depositFacet);
66
-
67
- /** @type {OfferStatus} */
68
- let status = {
69
- ...offerSpec,
70
- };
71
- /** @param {Partial<OfferStatus>} changes */
72
- const updateStatus = changes => {
73
- status = { ...status, ...changes };
74
- onStatusChange(status);
75
- };
76
-
77
- /** @type {UserSeat} */
78
- let seatRef;
79
-
80
- const tryBody = async () => {
81
- // 1. Prepare values and validate synchronously.
82
- const { id, invitationSpec, proposal, offerArgs } = offerSpec;
83
-
84
- /** @type {PaymentKeywordRecord | undefined} */
85
- const paymentKeywordRecord = await (proposal?.give &&
86
- deeplyFulfilledObject(paymentsManager.withdrawGive(proposal.give)));
87
-
88
- const invitation = invitationFromSpec(invitationSpec);
89
- const invitationAmount = await E(invitationIssuer).getAmountOf(
90
- invitation,
91
- );
92
-
93
- // 2. Begin executing offer
94
- // No explicit signal to user that we reached here but if anything above
95
- // failed they'd get an 'error' status update.
96
-
97
- // eslint-disable-next-line @jessie.js/no-nested-await -- unconditional
98
- seatRef = await E(zoe).offer(
99
- invitation,
100
- proposal,
101
- paymentKeywordRecord,
102
- offerArgs,
103
- );
104
- logger.info(id, 'seated');
105
- onSeatCreated(seatRef);
106
-
107
- const publishResult = E.when(E(seatRef).getOfferResult(), result => {
108
- const passStyle = passStyleOf(result);
109
- logger.info(id, 'offerResult', passStyle, result);
110
- // someday can we get TS to type narrow based on the passStyleOf result match?
111
- switch (passStyle) {
112
- case 'bigint':
113
- case 'boolean':
114
- case 'null':
115
- case 'number':
116
- case 'string':
117
- case 'symbol':
118
- case 'undefined':
119
- updateStatus({ result });
120
- break;
121
- case 'copyRecord':
122
- // @ts-expect-error result narrowed by passStyle
123
- if ('invitationMakers' in result) {
124
- // save for continuing invitation offer
125
- void onNewContinuingOffer(
126
- String(id),
127
- invitationAmount,
128
- // @ts-expect-error result narrowed by passStyle
129
- result.invitationMakers,
130
- // @ts-expect-error result narrowed by passStyle
131
- result.publicSubscribers,
132
- );
133
- }
134
- // copyRecord is valid to publish but not safe as it may have private info
135
- updateStatus({ result: UNPUBLISHED_RESULT });
136
- break;
137
- default:
138
- // drop the result
139
- updateStatus({ result: UNPUBLISHED_RESULT });
140
- }
141
- });
142
-
143
- const publishWantsSatisfied = E.when(
144
- E(seatRef).numWantsSatisfied(),
145
- numSatisfied => {
146
- logger.info(id, 'numSatisfied', numSatisfied);
147
- if (numSatisfied === 0) {
148
- updateStatus({ numWantsSatisfied: 0 });
149
- }
150
- updateStatus({
151
- numWantsSatisfied: numSatisfied,
152
- });
153
- },
154
- );
155
-
156
- // This will block until all payouts succeed, but user will be updated
157
- // as each payout will trigger its corresponding purse notifier.
158
- const publishPayouts = E.when(E(seatRef).getPayouts(), payouts =>
159
- paymentsManager.depositPayouts(payouts).then(amountsOrDeferred => {
160
- updateStatus({ payouts: amountsOrDeferred });
161
- }),
162
- );
163
-
164
- // The offer is complete when these promises are resolved.
165
- // If any reject then executeOffer rejects and that must be handled.
166
- return Promise.all([
167
- publishResult,
168
- publishWantsSatisfied,
169
- publishPayouts,
170
- ]);
171
- };
172
-
173
- await tryBody().catch(err => {
174
- logger.error('OFFER ERROR:', err);
175
- // Notify the user
176
- updateStatus({ error: err.toString() });
177
- // Attempt to recover payments
178
- void paymentsManager.tryReclaimingWithdrawnPayments().then(result => {
179
- if (result) {
180
- updateStatus({ result });
181
- }
182
- });
183
- if (seatRef) {
184
- void E(seatRef)
185
- .hasExited()
186
- .then(hasExited => {
187
- if (!hasExited) {
188
- void E(seatRef).tryExit();
189
- }
190
- });
191
- }
192
- // propagate to caller
193
- throw err;
194
- });
195
- },
196
- };
197
- };
198
- harden(makeOfferExecutor);
@@ -0,0 +1,23 @@
1
+ export function upgradeWalletFactory({ consume: { walletFactoryStartResult, provisionPoolStartResult, chainStorage, walletBridgeManager: walletBridgeManagerP, }, }: BootstrapPowers & ChainBootstrapSpace, options: {
2
+ options: {
3
+ walletRef: VatSourceRef;
4
+ };
5
+ }): Promise<void>;
6
+ export function getManifestForUpgradeWallet(_powers: any, { walletRef }: {
7
+ walletRef: any;
8
+ }): {
9
+ manifest: {
10
+ [x: string]: {
11
+ consume: {
12
+ walletFactoryStartResult: string;
13
+ provisionPoolStartResult: string;
14
+ chainStorage: string;
15
+ walletBridgeManager: string;
16
+ };
17
+ };
18
+ };
19
+ options: {
20
+ walletRef: any;
21
+ };
22
+ };
23
+ //# sourceMappingURL=upgrade-wallet-factory2-proposal.d.ts.map