@agoric/smart-wallet 0.5.4-u13.0 → 0.5.4-upgrade-14-dev-0a0580c.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.
@@ -42,8 +42,8 @@ export function prepare(zcf: ZCF<SmartWalletContractTerms>, privateArgs: {
42
42
  receive(payment: Payment<AssetKind>): Promise<Amount<AssetKind>>;
43
43
  };
44
44
  getOffersFacet(): {
45
- executeOffer(offerSpec: import("./offers.js").OfferSpec): Promise<void>;
46
- tryExitOffer(offerId: import("./offers.js").OfferId): Promise<void>;
45
+ executeOffer(offerSpec: import("./smartWallet.js").OfferSpec): Promise<void>;
46
+ tryExitOffer(offerId: import("./smartWallet.js").OfferId): Promise<void>;
47
47
  };
48
48
  getCurrentSubscriber(): Subscriber<import("./smartWallet.js").CurrentWalletRecord>;
49
49
  getUpdatesSubscriber(): Subscriber<import("./smartWallet.js").UpdateRecord>;
@@ -59,6 +59,7 @@ export function prepare(zcf: ZCF<SmartWalletContractTerms>, privateArgs: {
59
59
  storagePath: Promise<string>;
60
60
  };
61
61
  };
62
+ repairWalletForIncarnation2(key: any): void;
62
63
  }, isNew: boolean]>;
63
64
  } & import("@endo/eventual-send").RemotableBrand<{}, {
64
65
  /**
@@ -75,8 +76,8 @@ export function prepare(zcf: ZCF<SmartWalletContractTerms>, privateArgs: {
75
76
  receive(payment: Payment<AssetKind>): Promise<Amount<AssetKind>>;
76
77
  };
77
78
  getOffersFacet(): {
78
- executeOffer(offerSpec: import("./offers.js").OfferSpec): Promise<void>;
79
- tryExitOffer(offerId: import("./offers.js").OfferId): Promise<void>;
79
+ executeOffer(offerSpec: import("./smartWallet.js").OfferSpec): Promise<void>;
80
+ tryExitOffer(offerId: import("./smartWallet.js").OfferId): Promise<void>;
80
81
  };
81
82
  getCurrentSubscriber(): Subscriber<import("./smartWallet.js").CurrentWalletRecord>;
82
83
  getUpdatesSubscriber(): Subscriber<import("./smartWallet.js").UpdateRecord>;
@@ -92,6 +93,7 @@ export function prepare(zcf: ZCF<SmartWalletContractTerms>, privateArgs: {
92
93
  storagePath: Promise<string>;
93
94
  };
94
95
  };
96
+ repairWalletForIncarnation2(key: any): void;
95
97
  }, isNew: boolean]>;
96
98
  }>;
97
99
  }>;
@@ -1 +1 @@
1
- {"version":3,"file":"walletFactory.d.ts","sourceRoot":"","sources":["walletFactory.js"],"names":[],"mappings":";;;;;AAwBA,gEAKE;AAUK,6CAJI,MAAM,UACN,OAAO,kBAAkB,EAAE,WAAW,uBACtC,KAAK,OAAO,cAAc,EAAE,SAAS,CAAC,oBAehD;AAWM,kDAFI,cAAc;IAwCrB,2BAA2B;iBAAf,KAAK;IAEjB,2BAA2B;iBAAf,KAAK;eApCP,KAAK;qBACC,WAAW;gBAChB,MAAM;iBACL,OAAO,SAAS,EAAE,OAAO;;;eAH3B,KAAK;qBACC,WAAW;gBAChB,MAAM;iBACL,OAAO,SAAS,EAAE,OAAO;;EAsCxC;AAmCM,6BARI,IAAI,wBAAwB,CAAC;iBAEtB,KAAK,WAAW,CAAC;;;;;QAiH7B;;;;;;;WAOG;oCANQ,MAAM,QACN,KAAK,OAAO,2BAA2B,EAAE,IAAI,CAAC,uBAC9C,KAAK,OAAO,eAAe,EAAE,SAAS,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;QAHlD;;;;;;;WAOG;oCANQ,MAAM,QACN,KAAK,OAAO,2BAA2B,EAAE,IAAI,CAAC,uBAC9C,KAAK,OAAO,eAAe,EAAE,SAAS,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;GAoDvD;uCAlMY;IACZ,WAAe,EAAE,KAAK,OAAO,CAAC,CAAC;IAC/B,KAAS,EAAE,KAAK,OAAO,cAAc,EAAE,KAAK,CAAC,CAAC;IAC9C,cAAkB,EAAE,cAAc,CAAC;CAChC;sBAES,OAAO,cAAc,EAAE,OAAO;6BAE9B;IACZ,oBAAwB,EAAE,MAAM,KAChC,kBAAwB,OAAO,2BAA2B,EAAE,eAAe,CAAC,CAAC,CAAA;CAC1E;uBAES,OAAO;;4BAES,MAAM,KAAK,QAAQ,OAAO,eAAe,EAAE,WAAW,CAAC;yBAC1D,MAAM,KAAK,QAAQ;;oBAuL/B,cAAc"}
1
+ {"version":3,"file":"walletFactory.d.ts","sourceRoot":"","sources":["walletFactory.js"],"names":[],"mappings":";;;;;AA2BA,gEAKE;AAaK,6CAJI,MAAM,UACN,OAAO,kBAAkB,EAAE,WAAW,uBACtC,KAAK,OAAO,cAAc,EAAE,SAAS,CAAC,oBAehD;AAWM,kDAFI,cAAc;IAwCrB,2BAA2B;iBAAf,KAAK;IAEjB,2BAA2B;iBAAf,KAAK;eApCP,KAAK;qBACC,WAAW;gBAChB,MAAM;iBACL,OAAO,SAAS,EAAE,OAAO;;;eAH3B,KAAK;qBACC,WAAW;gBAChB,MAAM;iBACL,OAAO,SAAS,EAAE,OAAO;;EAsCxC;AAmCM,6BARI,IAAI,wBAAwB,CAAC;iBAEtB,KAAK,WAAW,CAAC;;;;;QA2I7B;;;;;;;WAOG;oCANQ,MAAM,QACN,KAAK,OAAO,2BAA2B,EAAE,IAAI,CAAC,uBAC9C,KAAK,OAAO,eAAe,EAAE,SAAS,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;QAHlD;;;;;;;WAOG;oCANQ,MAAM,QACN,KAAK,OAAO,2BAA2B,EAAE,IAAI,CAAC,uBAC9C,KAAK,OAAO,eAAe,EAAE,SAAS,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDvD;uCA5NY;IACZ,WAAe,EAAE,KAAK,OAAO,CAAC,CAAC;IAC/B,KAAS,EAAE,KAAK,OAAO,cAAc,EAAE,KAAK,CAAC,CAAC;IAC9C,cAAkB,EAAE,cAAc,CAAC;CAChC;sBAES,OAAO,cAAc,EAAE,OAAO;6BAE9B;IACZ,oBAAwB,EAAE,MAAM,KAChC,kBAAwB,OAAO,2BAA2B,EAAE,eAAe,CAAC,CAAC,CAAA;CAC1E;uBAES,OAAO;;4BAES,MAAM,KAAK,QAAQ,OAAO,eAAe,EAAE,WAAW,CAAC;yBAC1D,MAAM,KAAK,QAAQ;;oBAiN/B,cAAc"}
@@ -2,6 +2,9 @@
2
2
  * @file Wallet Factory
3
3
  *
4
4
  * Contract to make smart wallets.
5
+ *
6
+ * Note: The upgrade test uses a slightly modified copy of this file. When the
7
+ * interface changes here, that will also need to change.
5
8
  */
6
9
 
7
10
  import { makeTracer, WalletName } from '@agoric/internal';
@@ -29,6 +32,9 @@ export const privateArgsShape = harden(
29
32
  ),
30
33
  );
31
34
 
35
+ const WALLETS_BY_ADDRESS = 'walletsByAddress';
36
+ const UPGRADE_TO_INCARNATION_TWO = 'upgrade to incarnation two';
37
+
32
38
  /**
33
39
  * Provide a NameHub for this address and insert depositFacet only if not
34
40
  * already done.
@@ -129,7 +135,7 @@ export const makeAssetRegistry = assetPublisher => {
129
135
  * }} WalletReviver
130
136
  */
131
137
 
132
- // NB: even though all the wallets share this contract, they
138
+ // NB: even though all the wallets share this contract,
133
139
  // 1. they should not rely on that; they may be partitioned later
134
140
  // 2. they should never be able to detect behaviors from another wallet
135
141
  /**
@@ -142,14 +148,14 @@ export const makeAssetRegistry = assetPublisher => {
142
148
  * @param {import('@agoric/vat-data').Baggage} baggage
143
149
  */
144
150
  export const prepare = async (zcf, privateArgs, baggage) => {
145
- const upgrading = baggage.has('walletsByAddress');
151
+ const upgrading = baggage.has(WALLETS_BY_ADDRESS);
146
152
  const { agoricNames, board, assetPublisher } = zcf.getTerms();
147
153
 
148
154
  const zoe = zcf.getZoeService();
149
155
  const { storageNode, walletBridgeManager, walletReviver } = privateArgs;
150
156
 
151
157
  /** @type {MapStore<string, import('./smartWallet.js').SmartWallet>} */
152
- const walletsByAddress = provideDurableMapStore(baggage, 'walletsByAddress');
158
+ const walletsByAddress = provideDurableMapStore(baggage, WALLETS_BY_ADDRESS);
153
159
  const provider = makeAtomicProvider(walletsByAddress);
154
160
 
155
161
  const handleWalletAction = makeExo(
@@ -220,6 +226,15 @@ export const prepare = async (zcf, privateArgs, baggage) => {
220
226
 
221
227
  const registry = makeAssetRegistry(assetPublisher);
222
228
 
229
+ /**
230
+ * An object known only to walletFactory and smartWallets. The WalletFactory
231
+ * only has the self facet for the pre-existing wallets that must be repaired.
232
+ * Self is too accessible, so use of the repair function requires use of a
233
+ * secret that clients won't have. This can be removed once the upgrade has
234
+ * taken place.
235
+ */
236
+ const upgradeToIncarnation2Key = harden({});
237
+
223
238
  const shared = harden({
224
239
  agoricNames,
225
240
  invitationBrand,
@@ -228,6 +243,7 @@ export const prepare = async (zcf, privateArgs, baggage) => {
228
243
  publicMarshaller,
229
244
  registry,
230
245
  zoe,
246
+ secretWalletFactoryKey: upgradeToIncarnation2Key,
231
247
  });
232
248
 
233
249
  /**
@@ -237,6 +253,22 @@ export const prepare = async (zcf, privateArgs, baggage) => {
237
253
  */
238
254
  const makeSmartWallet = prepareSmartWallet(baggage, shared);
239
255
 
256
+ // One time repair for incarnation 2. We're adding WatchedPromises to allow
257
+ // wallets to durably monitor offer outcomes, but wallets that already exist
258
+ // need to be backfilled. This code needs to run once at the beginning of
259
+ // incarnation 2, and then shouldn't be needed again.
260
+ if (!baggage.has(UPGRADE_TO_INCARNATION_TWO)) {
261
+ trace('Wallet Factory upgrading to incarnation 2');
262
+
263
+ // This could take a while, depending on how many outstanding wallets exist.
264
+ // The current plan is that it will run exactly once, and inside an upgrade
265
+ // handler, between blocks.
266
+ for (const wallet of walletsByAddress.values()) {
267
+ wallet.repairWalletForIncarnation2(upgradeToIncarnation2Key);
268
+ }
269
+ baggage.init(UPGRADE_TO_INCARNATION_TWO, 'done');
270
+ }
271
+
240
272
  const creatorFacet = prepareExo(
241
273
  baggage,
242
274
  'walletFactoryCreator',
package/src/payments.d.ts DELETED
@@ -1,20 +0,0 @@
1
- export function makePaymentsHelper(purseForBrand: (brand: Brand) => Promise<import('./types').RemotePurse>, depositFacet: {
2
- receive: (payment: any) => Promise<Amount>;
3
- }): {
4
- /**
5
- * @param {AmountKeywordRecord} give
6
- * @returns {PaymentPKeywordRecord}
7
- */
8
- withdrawGive(give: AmountKeywordRecord): PaymentPKeywordRecord;
9
- /**
10
- * Try reclaiming any of our payments that we successfully withdrew, but
11
- * were left unclaimed.
12
- */
13
- tryReclaimingWithdrawnPayments(): Promise<undefined> | Promise<PromiseSettledResult<Amount<unknown> | undefined>[]>;
14
- /**
15
- * @param {PaymentPKeywordRecord} payouts
16
- * @returns {Promise<AmountKeywordRecord>} amounts for deferred deposits will be empty
17
- */
18
- depositPayouts(payouts: PaymentPKeywordRecord): Promise<AmountKeywordRecord>;
19
- };
20
- //# sourceMappingURL=payments.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"payments.d.ts","sourceRoot":"","sources":["payments.js"],"names":[],"mappings":"AAUO,0DAHY,KAAK,KAAK,QAAQ,OAAO,SAAS,EAAE,WAAW,CAAC;+BAC7B,QAAQ,MAAM,CAAC;;IAcjD;;;OAGG;uBAFQ,mBAAmB,GACjB,qBAAqB;IAkBlC;;;OAGG;;IA8BH;;;OAGG;4BAFQ,qBAAqB,GACnB,QAAQ,mBAAmB,CAAC;EAU5C"}
package/src/payments.js DELETED
@@ -1,89 +0,0 @@
1
- import { Fail } from '@agoric/assert';
2
- import { deeplyFulfilledObject, objectMap } from '@agoric/internal';
3
- import { E } from '@endo/far';
4
-
5
- /**
6
- * Used in an offer execution to manage payments state safely.
7
- *
8
- * @param {(brand: Brand) => Promise<import('./types').RemotePurse>} purseForBrand
9
- * @param {{ receive: (payment: *) => Promise<Amount> }} depositFacet
10
- */
11
- export const makePaymentsHelper = (purseForBrand, depositFacet) => {
12
- /** @type {PaymentPKeywordRecord | null} */
13
- let keywordPaymentPromises = null;
14
-
15
- /**
16
- * Tracks from whence our payment came.
17
- *
18
- * @type {Map<Payment, import('./types').RemotePurse>}
19
- */
20
- const paymentToPurse = new Map();
21
-
22
- return {
23
- /**
24
- * @param {AmountKeywordRecord} give
25
- * @returns {PaymentPKeywordRecord}
26
- */
27
- withdrawGive(give) {
28
- !keywordPaymentPromises ||
29
- Fail`withdrawPayments can be called once per helper`;
30
- keywordPaymentPromises = objectMap(give, amount => {
31
- /** @type {Promise<import('./types').RemotePurse<any>>} */
32
- const purseP = purseForBrand(amount.brand);
33
- return Promise.all([purseP, E(purseP).withdraw(amount)]).then(
34
- ([purse, payment]) => {
35
- paymentToPurse.set(payment, purse);
36
- return payment;
37
- },
38
- );
39
- });
40
- return keywordPaymentPromises;
41
- },
42
-
43
- /**
44
- * Try reclaiming any of our payments that we successfully withdrew, but
45
- * were left unclaimed.
46
- */
47
- tryReclaimingWithdrawnPayments() {
48
- if (!keywordPaymentPromises) return Promise.resolve(undefined);
49
- const paymentPromises = Object.values(keywordPaymentPromises);
50
- // Use allSettled to ensure we attempt all the deposits, regardless of
51
- // individual rejections.
52
- return Promise.allSettled(
53
- paymentPromises.map(async paymentP => {
54
- // Wait for the withdrawal to complete. This protects against a race
55
- // when updating paymentToPurse.
56
- const payment = await paymentP;
57
-
58
- // Find out where it came from.
59
- const purse = paymentToPurse.get(payment);
60
- if (purse === undefined) {
61
- // We already tried to reclaim this payment, so stop here.
62
- return undefined;
63
- }
64
-
65
- // Now send it back to the purse.
66
- try {
67
- return E(purse).deposit(payment);
68
- } finally {
69
- // Once we've called addPayment, mark this one as done.
70
- paymentToPurse.delete(payment);
71
- }
72
- }),
73
- );
74
- },
75
-
76
- /**
77
- * @param {PaymentPKeywordRecord} payouts
78
- * @returns {Promise<AmountKeywordRecord>} amounts for deferred deposits will be empty
79
- */
80
- async depositPayouts(payouts) {
81
- /** Record<string, Promise<Amount>> */
82
- const amountPKeywordRecord = objectMap(payouts, paymentRef =>
83
- E.when(paymentRef, payment => depositFacet.receive(payment)),
84
- );
85
- return deeplyFulfilledObject(amountPKeywordRecord);
86
- },
87
- };
88
- };
89
- harden(makePaymentsHelper);