@agoric/smart-wallet 0.5.4-dev-68c3c09.0.68c3c09 → 0.5.4-dev-d5eddaf.0.d5eddaf

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agoric/smart-wallet",
3
- "version": "0.5.4-dev-68c3c09.0.68c3c09",
3
+ "version": "0.5.4-dev-d5eddaf.0.d5eddaf",
4
4
  "description": "Wallet contract",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -18,9 +18,9 @@
18
18
  "lint:eslint": "yarn run -T eslint ."
19
19
  },
20
20
  "devDependencies": {
21
- "@agoric/casting": "0.4.3-dev-68c3c09.0.68c3c09",
22
- "@agoric/cosmic-proto": "0.4.1-dev-68c3c09.0.68c3c09",
23
- "@agoric/swingset-vat": "0.32.3-dev-68c3c09.0.68c3c09",
21
+ "@agoric/casting": "0.4.3-dev-d5eddaf.0.d5eddaf",
22
+ "@agoric/cosmic-proto": "0.4.1-dev-d5eddaf.0.d5eddaf",
23
+ "@agoric/swingset-vat": "0.32.3-dev-d5eddaf.0.d5eddaf",
24
24
  "@endo/bundle-source": "^4.1.2",
25
25
  "@endo/captp": "^4.4.8",
26
26
  "@endo/init": "^1.1.12",
@@ -28,15 +28,15 @@
28
28
  "import-meta-resolve": "^4.1.0"
29
29
  },
30
30
  "dependencies": {
31
- "@agoric/ertp": "0.16.3-dev-68c3c09.0.68c3c09",
32
- "@agoric/internal": "0.3.3-dev-68c3c09.0.68c3c09",
33
- "@agoric/notifier": "0.6.3-dev-68c3c09.0.68c3c09",
34
- "@agoric/store": "0.9.3-dev-68c3c09.0.68c3c09",
35
- "@agoric/vat-data": "0.5.3-dev-68c3c09.0.68c3c09",
36
- "@agoric/vats": "0.15.2-dev-68c3c09.0.68c3c09",
37
- "@agoric/vow": "0.1.1-dev-68c3c09.0.68c3c09",
38
- "@agoric/zoe": "0.26.3-dev-68c3c09.0.68c3c09",
39
- "@agoric/zone": "0.2.3-dev-68c3c09.0.68c3c09",
31
+ "@agoric/ertp": "0.16.3-dev-d5eddaf.0.d5eddaf",
32
+ "@agoric/internal": "0.3.3-dev-d5eddaf.0.d5eddaf",
33
+ "@agoric/notifier": "0.6.3-dev-d5eddaf.0.d5eddaf",
34
+ "@agoric/store": "0.9.3-dev-d5eddaf.0.d5eddaf",
35
+ "@agoric/vat-data": "0.5.3-dev-d5eddaf.0.d5eddaf",
36
+ "@agoric/vats": "0.15.2-dev-d5eddaf.0.d5eddaf",
37
+ "@agoric/vow": "0.1.1-dev-d5eddaf.0.d5eddaf",
38
+ "@agoric/zoe": "0.26.3-dev-d5eddaf.0.d5eddaf",
39
+ "@agoric/zone": "0.2.3-dev-d5eddaf.0.d5eddaf",
40
40
  "@endo/errors": "^1.2.13",
41
41
  "@endo/eventual-send": "^1.3.4",
42
42
  "@endo/far": "^1.1.14",
@@ -77,5 +77,5 @@
77
77
  "engines": {
78
78
  "node": "^20.9 || ^22.11"
79
79
  },
80
- "gitHead": "68c3c09cacc1373a4c64f530c44a50737a60066a"
80
+ "gitHead": "d5eddafd1d0d753e222640ce22eb00da23acca03"
81
81
  }
@@ -1,5 +1,5 @@
1
1
  export function makeWatchOfferOutcomes(vowTools: VowTools): (watchers: OutcomeWatchers, seat: UserSeat) => Promise<(void | 0 | 1 | PaymentPKeywordRecord)[]>;
2
- export function prepareOfferWatcher(baggage: Baggage, vowTools: VowTools): (walletHelper: any, deposit: {
2
+ export function prepareOfferWatcher(baggage: Baggage, vowTools: VowTools, zone: Zone): (walletHelper: any, deposit: {
3
3
  receive: (payment: Payment) => Promise<Amount>;
4
4
  }, offerSpec: OfferSpec, address: string, invitationAmount: import("@agoric/ertp").SetAmount<import("@endo/patterns").Key>, seatRef: UserSeat) => import("@endo/exo").GuardedKit<{
5
5
  helper: {
@@ -47,6 +47,7 @@ import type { VowTools } from '@agoric/vow';
47
47
  import type { UserSeat } from '@agoric/zoe';
48
48
  import type { PaymentPKeywordRecord } from '@agoric/zoe';
49
49
  import type { Baggage } from '@agoric/vat-data';
50
+ import type { Zone } from '@agoric/base-zone';
50
51
  import type { OfferSpec } from './offers.js';
51
52
  import type { InvitationMakers } from './types.js';
52
53
  import type { PublicSubscribers } from './types.js';
@@ -1 +1 @@
1
- {"version":3,"file":"offerWatcher.d.ts","sourceRoot":"","sources":["offerWatcher.js"],"names":[],"mappings":"AA4EO,iDADK,QAAQ,cAKP,eAAe,QACf,QAAQ,uDAiBpB;AAmCM,6CAHI,OAAO,YACP,QAAQ;aAWO,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,MAAM,CAAC;;;QAgBvD;;WAEG;yCADQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;QAQlC;;;;;WAKG;sCAJQ,MAAM,oBACN,MAAM,CAAC,KAAK,CAAC,oBACb,gBAAgB,qBAChB,iBAAiB;QAkB5B,uDAAuD;8BAA3C,QAAQ,GAAG,qBAAqB;QAoC5C;;;;;;WAMG;yBADQ,KAAK;;IAclB,gDAAgD;oBAArC,eAAe,CAAC,gBAAgB,CAAC;IA8B5C,+CAA+C;mBAApC,eAAe,CAAC,eAAe,CAAC;IAsC3C,iDAAiD;qBAAtC,eAAe,CAAC,iBAAiB,CAAC;GA0BlD;;;;gCAtTkB,CAAC,oBACP,eAAe,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC;8BAI7B;IACR,aAAa,EAAE,mBAAmB,CAAC,QAAQ,CAAC,CAAC;IAC7C,eAAe,EAAE,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAC7C,cAAc,EAAE,mBAAmB,CAAC,qBAAqB,CAAC,CAAC;CAC5D;+BAgTU,UAAU,CAAC,OAAO,mBAAmB,CAAC;2BACtC,UAAU,CAAC,gBAAgB,CAAC;8BAlUV,aAAa;8BAC2B,aAAa;2CAAb,aAAa;6BAF3D,kBAAkB;+BAJhB,aAAa;sCAON,YAAY;uCACX,YAAY;8BANrB,kBAAkB;2CADL,YAAY;oCAEnB,4BAA4B"}
1
+ {"version":3,"file":"offerWatcher.d.ts","sourceRoot":"","sources":["offerWatcher.js"],"names":[],"mappings":"AAsGO,iDADK,QAAQ,cAKP,eAAe,QACf,QAAQ,uDAiBpB;AAoCM,6CAJI,OAAO,YACP,QAAQ,QACR,IAAI;aAkDW,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,MAAM,CAAC;;;QAgBvD;;WAEG;yCADQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;QAQlC;;;;;WAKG;sCAJQ,MAAM,oBACN,MAAM,CAAC,KAAK,CAAC,oBACb,gBAAgB,qBAChB,iBAAiB;QAkB5B,uDAAuD;8BAA3C,QAAQ,GAAG,qBAAqB;QAoC5C;;;;;;WAMG;yBADQ,KAAK;;IAclB,gDAAgD;oBAArC,eAAe,CAAC,gBAAgB,CAAC;IA8B5C,+CAA+C;mBAApC,eAAe,CAAC,eAAe,CAAC;IAsC3C,iDAAiD;qBAAtC,eAAe,CAAC,iBAAiB,CAAC;GA6BlD;;;;gCAvXkB,CAAC,oBACP,eAAe,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC;8BAI7B;IACR,aAAa,EAAE,mBAAmB,CAAC,QAAQ,CAAC,CAAC;IAC7C,eAAe,EAAE,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAC7C,cAAc,EAAE,mBAAmB,CAAC,qBAAqB,CAAC,CAAC;CAC5D;+BAiXU,UAAU,CAAC,OAAO,mBAAmB,CAAC;2BACtC,UAAU,CAAC,gBAAgB,CAAC;8BApYV,aAAa;8BAE2B,aAAa;2CAAb,aAAa;6BAH3D,kBAAkB;0BAErB,mBAAmB;+BANd,aAAa;sCAQN,YAAY;uCACX,YAAY;8BAPrB,kBAAkB;2CADL,YAAY;oCAEnB,4BAA4B"}
@@ -1,6 +1,9 @@
1
1
  import { E, passStyleOf } from '@endo/far';
2
2
 
3
- import { isUpgradeDisconnection } from '@agoric/internal/src/upgrade-api.js';
3
+ import {
4
+ isAbandonedError,
5
+ isUpgradeDisconnection,
6
+ } from '@agoric/internal/src/upgrade-api.js';
4
7
  import { prepareExoClassKit, watchPromise } from '@agoric/vat-data';
5
8
  import { M } from '@agoric/store';
6
9
  import {
@@ -19,6 +22,7 @@ import { UNPUBLISHED_RESULT } from './offers.js';
19
22
  * @import {PromiseWatcher} from '@agoric/swingset-liveslots';
20
23
  * @import {Baggage} from '@agoric/vat-data';
21
24
  * @import {Vow, VowTools} from '@agoric/vow';
25
+ * @import {Zone} from '@agoric/base-zone';
22
26
  * @import {PaymentPKeywordRecord, Proposal, UserSeat, ZoeService} from '@agoric/zoe';
23
27
  * @import {InvitationMakers} from './types.js';
24
28
  * @import {PublicSubscribers} from './types.js';
@@ -38,6 +42,28 @@ import { UNPUBLISHED_RESULT } from './offers.js';
38
42
  * }} OutcomeWatchers
39
43
  */
40
44
 
45
+ /**
46
+ * Adopted from `@agoric/vow/vat.js`
47
+ *
48
+ * @param {unknown} reason
49
+ * @param {unknown} priorRetryValue
50
+ */
51
+ const isRetryableReason = (reason, priorRetryValue) => {
52
+ if (
53
+ isUpgradeDisconnection(reason) &&
54
+ (!isUpgradeDisconnection(priorRetryValue) ||
55
+ reason.incarnationNumber > priorRetryValue.incarnationNumber)
56
+ ) {
57
+ return reason;
58
+ }
59
+ // For abandoned errors there is no way to differentiate errors from
60
+ // consecutive upgrades
61
+ if (isAbandonedError(reason) && !isAbandonedError(priorRetryValue)) {
62
+ return reason;
63
+ }
64
+ return undefined;
65
+ };
66
+
41
67
  /** @param {VowTools} vowTools */
42
68
  const makeWatchForOfferResult = ({ watch }) => {
43
69
  /**
@@ -130,9 +156,49 @@ const offerWatcherGuard = harden({
130
156
  /**
131
157
  * @param {Baggage} baggage
132
158
  * @param {VowTools} vowTools
159
+ * @param {Zone} zone
133
160
  */
134
- export const prepareOfferWatcher = (baggage, vowTools) => {
161
+ export const prepareOfferWatcher = (baggage, vowTools, zone) => {
135
162
  const watchForOfferResult = makeWatchForOfferResult(vowTools);
163
+
164
+ const extraProps = zone.weakMapStore('offerWatcherExtraProps');
165
+ /**
166
+ * Implement retry logic for offer watchers. This uses the stateful
167
+ * `isRetryableReason` to avoid infinite promise rejection loops upon remote
168
+ * vat upgrade.
169
+ *
170
+ * @param {{}} facet
171
+ * @param {unknown} reason
172
+ * @returns {reason is UpgradeDisconnection} roughly
173
+ */
174
+ const needsRetry = (facet, reason) => {
175
+ const exists = extraProps.has(facet);
176
+ const extra = exists ? extraProps.get(facet) : harden({});
177
+
178
+ const key = `priorRetry`;
179
+ const priorRetryable = extra[key];
180
+ const retryable = isRetryableReason(reason, priorRetryable);
181
+ if (retryable) {
182
+ // Insert / update the new state.
183
+ extraProps[exists ? 'set' : 'init'](
184
+ facet,
185
+ harden({
186
+ ...extra,
187
+ [key]: retryable,
188
+ }),
189
+ );
190
+ } else if (exists) {
191
+ // Delete/shrink existing state to clean up unnecessary state.
192
+ const { [key]: _omit, ...rest } = extra;
193
+ if (Object.keys(rest).length === 0) {
194
+ extraProps.delete(facet);
195
+ } else {
196
+ extraProps.set(facet, harden(rest));
197
+ }
198
+ }
199
+ return !!retryable;
200
+ };
201
+
136
202
  return prepareExoClassKit(
137
203
  baggage,
138
204
  'OfferWatcher',
@@ -264,7 +330,7 @@ export const prepareOfferWatcher = (baggage, vowTools) => {
264
330
  */
265
331
  onRejected(reason, seat) {
266
332
  const { facets } = this;
267
- if (isUpgradeDisconnection(reason)) {
333
+ if (needsRetry(facets.paymentWatcher, reason)) {
268
334
  void watchForPayout(facets, seat);
269
335
  } else {
270
336
  facets.helper.handleError(reason);
@@ -300,7 +366,7 @@ export const prepareOfferWatcher = (baggage, vowTools) => {
300
366
  */
301
367
  onRejected(reason, seat) {
302
368
  const { facets } = this;
303
- if (isUpgradeDisconnection(reason)) {
369
+ if (needsRetry(facets.resultWatcher, reason)) {
304
370
  void watchForOfferResult(facets, seat);
305
371
  } else {
306
372
  facets.helper.handleError(reason);
@@ -329,9 +395,12 @@ export const prepareOfferWatcher = (baggage, vowTools) => {
329
395
  */
330
396
  onRejected(reason, seat) {
331
397
  const { facets } = this;
332
- if (isUpgradeDisconnection(reason)) {
398
+ if (needsRetry(facets.numWantsWatcher, reason)) {
333
399
  void watchForNumWants(facets, seat);
400
+ } else {
401
+ facets.helper.handleError(reason);
334
402
  }
403
+ throw reason;
335
404
  },
336
405
  },
337
406
  },
@@ -333,7 +333,7 @@ export const prepareSmartWallet = (baggage, shared, setTestJig) => {
333
333
 
334
334
  const vowTools = prepareVowTools(zone.subZone('vow'));
335
335
 
336
- const makeOfferWatcher = prepareOfferWatcher(baggage, vowTools);
336
+ const makeOfferWatcher = prepareOfferWatcher(baggage, vowTools, zone);
337
337
  const watchOfferOutcomes = makeWatchOfferOutcomes(vowTools);
338
338
 
339
339
  const updateShape = {