@agoric/ertp 0.16.3-mainnet1B-dev-b0c1f78.0 → 0.16.3-orchestration-dev-096c4e8.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.
Files changed (48) hide show
  1. package/package.json +26 -18
  2. package/src/amountMath.js +57 -63
  3. package/src/amountStore.js +32 -0
  4. package/src/index.js +7 -0
  5. package/src/issuerKit.js +218 -74
  6. package/src/legacy-payment-helpers.js +23 -28
  7. package/src/mathHelpers/copyBagMathHelpers.js +2 -4
  8. package/src/mathHelpers/copySetMathHelpers.js +1 -3
  9. package/src/mathHelpers/natMathHelpers.js +6 -7
  10. package/src/payment.js +5 -8
  11. package/src/paymentLedger.js +84 -91
  12. package/src/purse.js +83 -24
  13. package/src/typeGuards.js +37 -43
  14. package/src/types-ambient.js +237 -314
  15. package/src/types.js +237 -314
  16. package/CHANGELOG.md +0 -767
  17. package/src/amountMath.d.ts +0 -53
  18. package/src/amountMath.d.ts.map +0 -1
  19. package/src/displayInfo.d.ts +0 -2
  20. package/src/displayInfo.d.ts.map +0 -1
  21. package/src/index.d.ts +0 -4
  22. package/src/index.d.ts.map +0 -1
  23. package/src/issuerKit.d.ts +0 -19
  24. package/src/issuerKit.d.ts.map +0 -1
  25. package/src/legacy-payment-helpers.d.ts +0 -5
  26. package/src/legacy-payment-helpers.d.ts.map +0 -1
  27. package/src/mathHelpers/copyBagMathHelpers.d.ts +0 -5
  28. package/src/mathHelpers/copyBagMathHelpers.d.ts.map +0 -1
  29. package/src/mathHelpers/copySetMathHelpers.d.ts +0 -5
  30. package/src/mathHelpers/copySetMathHelpers.d.ts.map +0 -1
  31. package/src/mathHelpers/natMathHelpers.d.ts +0 -14
  32. package/src/mathHelpers/natMathHelpers.d.ts.map +0 -1
  33. package/src/mathHelpers/setMathHelpers.d.ts +0 -6
  34. package/src/mathHelpers/setMathHelpers.d.ts.map +0 -1
  35. package/src/payment.d.ts +0 -3
  36. package/src/payment.d.ts.map +0 -1
  37. package/src/paymentLedger.d.ts +0 -3
  38. package/src/paymentLedger.d.ts.map +0 -1
  39. package/src/purse.d.ts +0 -13
  40. package/src/purse.d.ts.map +0 -1
  41. package/src/transientNotifier.d.ts +0 -5
  42. package/src/transientNotifier.d.ts.map +0 -1
  43. package/src/typeGuards.d.ts +0 -42
  44. package/src/typeGuards.d.ts.map +0 -1
  45. package/src/types-ambient.d.ts +0 -376
  46. package/src/types-ambient.d.ts.map +0 -1
  47. package/src/types.d.ts +0 -376
  48. package/src/types.d.ts.map +0 -1
@@ -3,11 +3,6 @@
3
3
  /* eslint-disable no-use-before-define */
4
4
  import { isPromise } from '@endo/promise-kit';
5
5
  import { mustMatch, M, keyEQ } from '@agoric/store';
6
- import {
7
- provideDurableWeakMapStore,
8
- prepareExo,
9
- provide,
10
- } from '@agoric/vat-data';
11
6
  import { AmountMath } from './amountMath.js';
12
7
  import { preparePaymentKind } from './payment.js';
13
8
  import { preparePurseKind } from './purse.js';
@@ -15,8 +10,6 @@ import { preparePurseKind } from './purse.js';
15
10
  import '@agoric/store/exported.js';
16
11
  import { BrandI, makeIssuerInterfaces } from './typeGuards.js';
17
12
 
18
- /** @typedef {import('@agoric/vat-data').Baggage} Baggage */
19
-
20
13
  const { details: X, quote: q, Fail } = assert;
21
14
 
22
15
  /**
@@ -70,29 +63,35 @@ const amountShapeFromElementShape = (brand, assetKind, elementShape) => {
70
63
  };
71
64
 
72
65
  /**
73
- * Make the paymentLedger, the source of truth for the balances of
74
- * payments. All minting and transfer authority originates here.
66
+ * Make the paymentLedger, the source of truth for the balances of payments. All
67
+ * minting and transfer authority originates here.
75
68
  *
76
69
  * @template {AssetKind} K
77
- * @param {Baggage} issuerBaggage
70
+ * @param {import('@agoric/zone').Zone} issuerZone
78
71
  * @param {string} name
79
72
  * @param {K} assetKind
80
73
  * @param {DisplayInfo<K>} displayInfo
81
74
  * @param {Pattern} elementShape
75
+ * @param {RecoverySetsOption} recoverySetsState
82
76
  * @param {ShutdownWithFailure} [optShutdownWithFailure]
83
77
  * @returns {PaymentLedger<K>}
84
78
  */
85
79
  export const preparePaymentLedger = (
86
- issuerBaggage,
80
+ issuerZone,
87
81
  name,
88
82
  assetKind,
89
83
  displayInfo,
90
84
  elementShape,
85
+ recoverySetsState,
91
86
  optShutdownWithFailure = undefined,
92
87
  ) => {
93
88
  /** @type {Brand<K>} */
94
- // @ts-expect-error XXX callWhen
95
- const brand = prepareExo(issuerBaggage, `${name} brand`, BrandI, {
89
+ // Should be
90
+ // at-ts-expect-error XXX callWhen
91
+ // but ran into the usual disagreement between local lint and CI
92
+ // eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error
93
+ // @ts-ignore
94
+ const brand = issuerZone.exo(`${name} brand`, BrandI, {
96
95
  isMyIssuer(allegedIssuer) {
97
96
  // BrandI delays calling this method until `allegedIssuer` is a Remotable
98
97
  return allegedIssuer === issuer;
@@ -121,7 +120,7 @@ export const preparePaymentLedger = (
121
120
  amountShape,
122
121
  );
123
122
 
124
- const makePayment = preparePaymentKind(issuerBaggage, name, brand, PaymentI);
123
+ const makePayment = preparePaymentKind(issuerZone, name, brand, PaymentI);
125
124
 
126
125
  /** @type {ShutdownWithFailure} */
127
126
  const shutdownLedgerWithFailure = reason => {
@@ -139,48 +138,48 @@ export const preparePaymentLedger = (
139
138
  };
140
139
 
141
140
  /** @type {WeakMapStore<Payment, Amount>} */
142
- const paymentLedger = provideDurableWeakMapStore(
143
- issuerBaggage,
144
- 'paymentLedger',
145
- { valueShape: amountShape },
146
- );
141
+ const paymentLedger = issuerZone.weakMapStore('paymentLedger', {
142
+ valueShape: amountShape,
143
+ });
147
144
 
148
145
  /**
149
- * A withdrawn live payment is associated with the recovery set of
150
- * the purse it was withdrawn from. Let's call these "recoverable"
151
- * payments. All recoverable payments are live, but not all live
152
- * payments are recoverable. We do the bookkeeping for payment recovery
153
- * with this weakmap from recoverable payments to the recovery set they are
154
- * in.
155
- * A bunch of interesting invariants here:
156
- * * Every payment that is a key in the outer `paymentRecoverySets`
157
- * weakMap is also in the recovery set indexed by that payment.
158
- * * Implied by the above but worth stating: the payment is only
159
- * in at most one recovery set.
160
- * * A recovery set only contains such payments.
161
- * * Every purse is associated with exactly one recovery set unique to
162
- * it.
163
- * * A purse's recovery set only contains payments withdrawn from
164
- * that purse and not yet consumed.
146
+ * A (non-empty) withdrawn live payment is associated with the recovery set of
147
+ * the purse it was withdrawn from. Let's call these "recoverable" payments.
148
+ * All recoverable payments are live, but not all live payments are
149
+ * recoverable. We do the bookkeeping for payment recovery with this weakmap
150
+ * from recoverable payments to the recovery set they are in. A bunch of
151
+ * interesting invariants here:
152
+ *
153
+ * - Every payment that is a key in the outer `paymentRecoverySets` weakMap is
154
+ * also in the recovery set indexed by that payment.
155
+ * - Implied by the above but worth stating: the payment is only in at most one
156
+ * recovery set.
157
+ * - A recovery set only contains such payments.
158
+ * - Every purse is associated with exactly one recovery set unique to it.
159
+ * - A purse's recovery set only contains payments withdrawn from that purse and
160
+ * not yet consumed.
161
+ *
162
+ * If `recoverySetsState === 'noRecoverySets'`, then nothing should ever be
163
+ * added to this WeakStore.
165
164
  *
166
165
  * @type {WeakMapStore<Payment, SetStore<Payment>>}
167
166
  */
168
- const paymentRecoverySets = provideDurableWeakMapStore(
169
- issuerBaggage,
170
- 'paymentRecoverySets',
171
- );
167
+ const paymentRecoverySets = issuerZone.weakMapStore('paymentRecoverySets');
172
168
 
173
169
  /**
174
170
  * To maintain the invariants listed in the `paymentRecoverySets` comment,
175
- * `initPayment` should contain the only
176
- * call to `paymentLedger.init`.
171
+ * `initPayment` should contain the only call to `paymentLedger.init`.
177
172
  *
178
173
  * @param {Payment} payment
179
174
  * @param {Amount} amount
180
175
  * @param {SetStore<Payment>} [optRecoverySet]
181
176
  */
182
177
  const initPayment = (payment, amount, optRecoverySet = undefined) => {
183
- if (optRecoverySet !== undefined) {
178
+ if (recoverySetsState === 'noRecoverySets') {
179
+ optRecoverySet === undefined ||
180
+ Fail`when recoverSetsState === 'noRecoverySets', optRecoverySet must be empty`;
181
+ }
182
+ if (optRecoverySet !== undefined && !AmountMath.isEmpty(amount)) {
184
183
  optRecoverySet.add(payment);
185
184
  paymentRecoverySets.init(payment, optRecoverySet);
186
185
  }
@@ -189,8 +188,7 @@ export const preparePaymentLedger = (
189
188
 
190
189
  /**
191
190
  * To maintain the invariants listed in the `paymentRecoverySets` comment,
192
- * `deletePayment` should contain the only
193
- * call to `paymentLedger.delete`.
191
+ * `deletePayment` should contain the only call to `paymentLedger.delete`.
194
192
  *
195
193
  * @param {Payment} payment
196
194
  */
@@ -203,19 +201,14 @@ export const preparePaymentLedger = (
203
201
  }
204
202
  };
205
203
 
206
- /** @type {(left: Amount, right: Amount) => Amount } */
207
- const add = (left, right) => AmountMath.add(left, right, brand);
208
- /** @type {(left: Amount, right: Amount) => Amount } */
209
- const subtract = (left, right) => AmountMath.subtract(left, right, brand);
210
204
  /** @type {(allegedAmount: Amount) => Amount} */
211
205
  const coerce = allegedAmount => AmountMath.coerce(brand, allegedAmount);
212
- /** @type {(left: Amount, right: Amount) => boolean } */
206
+ /** @type {(left: Amount, right: Amount) => boolean} */
213
207
 
214
208
  /**
215
- * Methods like deposit() have an optional second parameter
216
- * `optAmountShape`
217
- * which, if present, is supposed to match the balance of the
218
- * payment. This helper function does that check.
209
+ * Methods like deposit() have an optional second parameter `optAmountShape`
210
+ * which, if present, is supposed to match the balance of the payment. This
211
+ * helper function does that check.
219
212
  *
220
213
  * Note: `optAmountShape` is user-supplied with no previous validation.
221
214
  *
@@ -243,17 +236,13 @@ export const preparePaymentLedger = (
243
236
  /**
244
237
  * Used by the purse code to implement purse.deposit
245
238
  *
246
- * @param {Amount} currentBalance - the current balance of the purse
247
- * before a deposit
248
- * @param {(newPurseBalance: Amount) => void} updatePurseBalance -
249
- * commit the purse balance
239
+ * @param {import('./amountStore.js').AmountStore} balanceStore
250
240
  * @param {Payment} srcPayment
251
241
  * @param {Pattern} [optAmountShape]
252
242
  * @returns {Amount}
253
243
  */
254
244
  const depositInternal = (
255
- currentBalance,
256
- updatePurseBalance,
245
+ balanceStore,
257
246
  srcPayment,
258
247
  optAmountShape = undefined,
259
248
  ) => {
@@ -265,13 +254,12 @@ export const preparePaymentLedger = (
265
254
  assertLivePayment(srcPayment);
266
255
  const srcPaymentBalance = paymentLedger.get(srcPayment);
267
256
  assertAmountConsistent(srcPaymentBalance, optAmountShape);
268
- const newPurseBalance = add(srcPaymentBalance, currentBalance);
269
257
  try {
270
258
  // COMMIT POINT
271
259
  // Move the assets in `srcPayment` into this purse, using up the
272
260
  // source payment, such that total assets are conserved.
273
261
  deletePayment(srcPayment);
274
- updatePurseBalance(newPurseBalance);
262
+ balanceStore.increment(srcPaymentBalance);
275
263
  } catch (err) {
276
264
  shutdownLedgerWithFailure(err);
277
265
  throw err;
@@ -282,30 +270,19 @@ export const preparePaymentLedger = (
282
270
  /**
283
271
  * Used by the purse code to implement purse.withdraw
284
272
  *
285
- * @param {Amount} currentBalance - the current balance of the purse
286
- * before a withdrawal
287
- * @param {(newPurseBalance: Amount) => void} updatePurseBalance -
288
- * commit the purse balance
273
+ * @param {import('./amountStore.js').AmountStore} balanceStore
289
274
  * @param {Amount} amount - the amount to be withdrawn
290
- * @param {SetStore<Payment>} recoverySet
275
+ * @param {SetStore<Payment>} [recoverySet]
291
276
  * @returns {Payment}
292
277
  */
293
- const withdrawInternal = (
294
- currentBalance,
295
- updatePurseBalance,
296
- amount,
297
- recoverySet,
298
- ) => {
278
+ const withdrawInternal = (balanceStore, amount, recoverySet = undefined) => {
299
279
  amount = coerce(amount);
300
- AmountMath.isGTE(currentBalance, amount) ||
301
- Fail`Withdrawal of ${amount} failed because the purse only contained ${currentBalance}`;
302
- const newPurseBalance = subtract(currentBalance, amount);
303
-
304
280
  const payment = makePayment();
281
+ // COMMIT POINT Move the withdrawn assets from this purse into
282
+ // payment. Total assets must remain conserved.
283
+ balanceStore.decrement(amount) ||
284
+ Fail`Withdrawal of ${amount} failed because the purse only contained ${balanceStore.getAmount()}`;
305
285
  try {
306
- // COMMIT POINT Move the withdrawn assets from this purse into
307
- // payment. Total assets must remain conserved.
308
- updatePurseBalance(newPurseBalance);
309
286
  initPayment(payment, amount, recoverySet);
310
287
  } catch (err) {
311
288
  shutdownLedgerWithFailure(err);
@@ -314,8 +291,10 @@ export const preparePaymentLedger = (
314
291
  return payment;
315
292
  };
316
293
 
294
+ /** @type {() => Purse<K>} */
295
+ // @ts-expect-error type parameter confusion
317
296
  const makeEmptyPurse = preparePurseKind(
318
- issuerBaggage,
297
+ issuerZone,
319
298
  name,
320
299
  assetKind,
321
300
  brand,
@@ -324,11 +303,17 @@ export const preparePaymentLedger = (
324
303
  depositInternal,
325
304
  withdrawInternal,
326
305
  }),
306
+ recoverySetsState,
307
+ paymentRecoverySets,
327
308
  );
328
309
 
329
310
  /** @type {Issuer<K>} */
330
- // @ts-expect-error cast due to callWhen discrepancy
331
- const issuer = prepareExo(issuerBaggage, `${name} issuer`, IssuerI, {
311
+ // Should be
312
+ // at-ts-expect-error cast due to callWhen discrepancy
313
+ // but ran into the usual disagreement between local lint and CI
314
+ // eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error
315
+ // @ts-ignore
316
+ const issuer = issuerZone.exo(`${name} issuer`, IssuerI, {
332
317
  getBrand() {
333
318
  return brand;
334
319
  },
@@ -378,23 +363,31 @@ export const preparePaymentLedger = (
378
363
  /**
379
364
  * Provides for the recovery of newly minted but not-yet-deposited payments.
380
365
  *
381
- * Because the `mintRecoveryPurse` is placed in baggage, even if the
382
- * caller of `makeIssuerKit` drops it on the floor, it can still be
383
- * recovered in an emergency upgrade.
384
- *
385
- * @type {Purse<K>}
366
+ * Because the `mintRecoveryPurse` is placed in baggage, even if the caller of
367
+ * `makeIssuerKit` drops it on the floor, it can still be recovered in an
368
+ * emergency upgrade.
386
369
  */
387
- const mintRecoveryPurse = provide(issuerBaggage, 'mintRecoveryPurse', () =>
388
- makeEmptyPurse(),
370
+ // Should be
371
+ // at-ts-expect-error checked cast
372
+ // but ran into the usual disagreement between local lint and IDE lint.
373
+ // Don't know yet about lint under CI.
374
+ // eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error
375
+ // @ts-ignore
376
+ const mintRecoveryPurse = /** @type {Purse<K>} */ (
377
+ issuerZone.makeOnce('mintRecoveryPurse', () => makeEmptyPurse())
389
378
  );
390
379
 
391
380
  /** @type {Mint<K>} */
392
- const mint = prepareExo(issuerBaggage, `${name} mint`, MintI, {
381
+ const mint = issuerZone.exo(`${name} mint`, MintI, {
393
382
  getIssuer() {
394
383
  return issuer;
395
384
  },
396
385
  mintPayment(newAmount) {
397
- // @ts-expect-error checked cast
386
+ // Should be
387
+ // at-ts-expect-error checked cast
388
+ // but ran into the usual disagreement between local lint and CI
389
+ // eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error
390
+ // @ts-ignore
398
391
  newAmount = coerce(newAmount);
399
392
  mustMatch(newAmount, amountShape, 'minted amount');
400
393
  // `rawPayment` is not associated with any recovery set, and
package/src/purse.js CHANGED
@@ -1,27 +1,72 @@
1
- import { M } from '@agoric/store';
2
- import { prepareExoClassKit, makeScalarBigSetStore } from '@agoric/vat-data';
1
+ import { M, makeCopySet } from '@agoric/store';
3
2
  import { AmountMath } from './amountMath.js';
4
3
  import { makeTransientNotifierKit } from './transientNotifier.js';
4
+ import { makeAmountStore } from './amountStore.js';
5
5
 
6
6
  const { Fail } = assert;
7
7
 
8
+ const EMPTY_COPY_SET = makeCopySet([]);
9
+
10
+ // TODO Type InterfaceGuard better than InterfaceGuard<any>
11
+ /**
12
+ * @param {import('@agoric/zone').Zone} issuerZone
13
+ * @param {string} name
14
+ * @param {AssetKind} assetKind
15
+ * @param {Brand} brand
16
+ * @param {{
17
+ * purse: import('@endo/patterns').InterfaceGuard<any>;
18
+ * depositFacet: import('@endo/patterns').InterfaceGuard<any>;
19
+ * }} PurseIKit
20
+ * @param {{
21
+ * depositInternal: any;
22
+ * withdrawInternal: any;
23
+ * }} purseMethods
24
+ * @param {RecoverySetsOption} recoverySetsState
25
+ * @param {WeakMapStore<Payment, SetStore<Payment>>} paymentRecoverySets
26
+ */
8
27
  export const preparePurseKind = (
9
- issuerBaggage,
28
+ issuerZone,
10
29
  name,
11
30
  assetKind,
12
31
  brand,
13
32
  PurseIKit,
14
33
  purseMethods,
34
+ recoverySetsState,
35
+ paymentRecoverySets,
15
36
  ) => {
16
37
  const amountShape = brand.getAmountShape();
17
38
 
18
39
  // Note: Virtual for high cardinality, but *not* durable, and so
19
40
  // broken across an upgrade.
41
+ // TODO propagate zonifying to notifiers, maybe?
20
42
  const { provideNotifier, update: updateBalance } = makeTransientNotifierKit();
21
43
 
22
- const updatePurseBalance = (state, newPurseBalance, purse) => {
23
- state.currentBalance = newPurseBalance;
24
- updateBalance(purse, purse.getCurrentAmount());
44
+ /**
45
+ * If `recoverySetsState === 'hasRecoverySets'` (the normal state), then just
46
+ * return `state.recoverySet`.
47
+ *
48
+ * If `recoverySetsState === 'noRecoverySets'`, return `undefined`. Callers
49
+ * must be aware that the `undefined` return happens iff `recoverySetsState
50
+ * === 'noRecoverySets'`, and to avoid storing or retrieving anything from the
51
+ * actual recovery set.
52
+ *
53
+ * @param {{ recoverySet: SetStore<Payment> }} state
54
+ * @returns {SetStore<Payment> | undefined}
55
+ */
56
+ const maybeRecoverySet = state => {
57
+ const { recoverySet } = state;
58
+ if (recoverySetsState === 'hasRecoverySets') {
59
+ return recoverySet;
60
+ } else {
61
+ recoverySetsState === 'noRecoverySets' ||
62
+ Fail`recoverSetsState must be noRecoverySets if it isn't hasRecoverSets`;
63
+ paymentRecoverySets !== undefined ||
64
+ Fail`paymentRecoverySets must always be defined`;
65
+ recoverySet.getSize() === 0 ||
66
+ Fail`With noRecoverySets, recoverySet must be empty`;
67
+
68
+ return undefined;
69
+ }
25
70
  };
26
71
 
27
72
  // - This kind is a pair of purse and depositFacet that have a 1:1
@@ -31,17 +76,14 @@ export const preparePurseKind = (
31
76
  // that created depositFacet as needed. But this approach ensures a constant
32
77
  // identity for the facet and exercises the multi-faceted object style.
33
78
  const { depositInternal, withdrawInternal } = purseMethods;
34
- const makePurseKit = prepareExoClassKit(
35
- issuerBaggage,
79
+ const makePurseKit = issuerZone.exoClassKit(
36
80
  `${name} Purse`,
37
81
  PurseIKit,
38
82
  () => {
39
83
  const currentBalance = AmountMath.makeEmpty(brand, assetKind);
40
84
 
41
85
  /** @type {SetStore<Payment>} */
42
- const recoverySet = makeScalarBigSetStore('recovery set', {
43
- durable: true,
44
- });
86
+ const recoverySet = issuerZone.detached().setStore('recovery set');
45
87
 
46
88
  return {
47
89
  currentBalance,
@@ -54,28 +96,36 @@ export const preparePurseKind = (
54
96
  // PurseI does *not* delay `deposit` until `srcPayment` is fulfulled.
55
97
  // See the comments on PurseI.deposit in typeGuards.js
56
98
  const { state } = this;
99
+ const { purse } = this.facets;
100
+ const balanceStore = makeAmountStore(state, 'currentBalance');
57
101
  // Note COMMIT POINT within deposit.
58
- return depositInternal(
59
- state.currentBalance,
60
- newPurseBalance =>
61
- updatePurseBalance(state, newPurseBalance, this.facets.purse),
102
+ const srcPaymentBalance = depositInternal(
103
+ balanceStore,
62
104
  srcPayment,
63
105
  optAmountShape,
64
106
  );
107
+ updateBalance(purse, balanceStore.getAmount());
108
+ return srcPaymentBalance;
65
109
  },
66
110
  withdraw(amount) {
67
111
  const { state } = this;
112
+ const { purse } = this.facets;
113
+
114
+ const optRecoverySet = maybeRecoverySet(state);
115
+ const balanceStore = makeAmountStore(state, 'currentBalance');
68
116
  // Note COMMIT POINT within withdraw.
69
- return withdrawInternal(
70
- state.currentBalance,
71
- newPurseBalance =>
72
- updatePurseBalance(state, newPurseBalance, this.facets.purse),
117
+ const payment = withdrawInternal(
118
+ balanceStore,
73
119
  amount,
74
- state.recoverySet,
120
+ optRecoverySet,
75
121
  );
122
+ updateBalance(purse, balanceStore.getAmount());
123
+ return payment;
76
124
  },
77
125
  getCurrentAmount() {
78
- return this.state.currentBalance;
126
+ const { state } = this;
127
+ const balanceStore = makeAmountStore(state, 'currentBalance');
128
+ return balanceStore.getAmount();
79
129
  },
80
130
  getCurrentAmountNotifier() {
81
131
  return provideNotifier(this.facets.purse);
@@ -89,18 +139,27 @@ export const preparePurseKind = (
89
139
  },
90
140
 
91
141
  getRecoverySet() {
92
- return this.state.recoverySet.snapshot();
142
+ const { state } = this;
143
+ const optRecoverySet = maybeRecoverySet(state);
144
+ if (optRecoverySet === undefined) {
145
+ return EMPTY_COPY_SET;
146
+ }
147
+ return optRecoverySet.snapshot();
93
148
  },
94
149
  recoverAll() {
95
150
  const { state, facets } = this;
96
151
  let amount = AmountMath.makeEmpty(brand, assetKind);
97
- for (const payment of state.recoverySet.keys()) {
152
+ const optRecoverySet = maybeRecoverySet(state);
153
+ if (optRecoverySet === undefined) {
154
+ return amount; // empty at this time
155
+ }
156
+ for (const payment of optRecoverySet.keys()) {
98
157
  // This does cause deletions from the set while iterating,
99
158
  // but this special case is allowed.
100
159
  const delta = facets.purse.deposit(payment);
101
160
  amount = AmountMath.add(amount, delta, brand);
102
161
  }
103
- state.recoverySet.getSize() === 0 ||
162
+ optRecoverySet.getSize() === 0 ||
104
163
  Fail`internal: Remaining unrecovered payments: ${facets.purse.getRecoverySet()}`;
105
164
  return amount;
106
165
  },
package/src/typeGuards.js CHANGED
@@ -1,6 +1,6 @@
1
1
  // @jessie-check
2
2
 
3
- import { M, matches } from '@agoric/store';
3
+ import { M, matches, getInterfaceGuardPayload } from '@endo/patterns';
4
4
 
5
5
  export const BrandShape = M.remotable('Brand');
6
6
  export const IssuerShape = M.remotable('Issuer');
@@ -11,62 +11,56 @@ export const NotifierShape = M.remotable('Notifier');
11
11
  export const MintShape = M.remotable('Mint');
12
12
 
13
13
  /**
14
- * When the AmountValue of an Amount fits the NatValueShape, i.e., when it is
15
- * a non-negative bigint, then it represents that many units of the
16
- * fungible asset represented by that amount. The brand of that amount
17
- * should indeed represent a kind of asset consisting of a countable
18
- * set of fungible units.
14
+ * When the AmountValue of an Amount fits the NatValueShape, i.e., when it is a
15
+ * non-negative bigint, then it represents that many units of the fungible asset
16
+ * represented by that amount. The brand of that amount should indeed represent
17
+ * a kind of asset consisting of a countable set of fungible units.
19
18
  */
20
19
  const NatValueShape = M.nat();
21
20
 
22
21
  /**
23
22
  * When the AmountValue of an Amount fits the CopySetValueShape, i.e., when it
24
- * is a CopySet, then it represents the set of those
25
- * keys, where each key represents some individual non-fungible
26
- * item, like a concert ticket, from the non-fungible asset class
27
- * represented by that amount's brand. The amount itself represents
28
- * the set of these items, as opposed to any of the other items
29
- * from the same asset class.
23
+ * is a CopySet, then it represents the set of those keys, where each key
24
+ * represents some individual non-fungible item, like a concert ticket, from the
25
+ * non-fungible asset class represented by that amount's brand. The amount
26
+ * itself represents the set of these items, as opposed to any of the other
27
+ * items from the same asset class.
30
28
  *
31
- * If a given value class represents concert tickets, it seems bizarre
32
- * that we can form amounts of any key. The hard constraint is that
33
- * the code that holds the mint for that asset class---the one associated
34
- * with that brand, only mints the items representing the real units
35
- * of that asset class as defined by it. Anyone else can put together
36
- * an amount expressing, for example, that they "want" some items that
37
- * will never be minted. That want will never be satisfied.
38
- * "You can't always get..."
29
+ * If a given value class represents concert tickets, it seems bizarre that we
30
+ * can form amounts of any key. The hard constraint is that the code that holds
31
+ * the mint for that asset class---the one associated with that brand, only
32
+ * mints the items representing the real units of that asset class as defined by
33
+ * it. Anyone else can put together an amount expressing, for example, that they
34
+ * "want" some items that will never be minted. That want will never be
35
+ * satisfied. "You can't always get..."
39
36
  */
40
37
  const CopySetValueShape = M.set();
41
38
 
42
39
  /**
43
- * When the AmountValue of an Amount fits the SetValueShape, i.e., when it
44
- * is a CopyArray of passable Keys. This representation is deprecated.
40
+ * When the AmountValue of an Amount fits the SetValueShape, i.e., when it is a
41
+ * CopyArray of passable Keys. This representation is deprecated.
45
42
  *
46
43
  * @deprecated Please change from using array-based SetValues to CopySet-based
47
- * CopySetValues.
44
+ * CopySetValues.
48
45
  */
49
46
  const SetValueShape = M.arrayOf(M.key());
50
47
 
51
48
  /**
52
49
  * When the AmountValue of an Amount fits the CopyBagValueShape, i.e., when it
53
- * is a CopyBag, then it represents the bag (multiset) of those
54
- * keys, where each key represents some individual semi-fungible
55
- * item, like a concert ticket, from the semi-fungible asset class
56
- * represented by that amount's brand. The number of times that key
57
- * appears in the bag is the number of fungible units of that key.
58
- * The amount itself represents
59
- * the bag of these items, as opposed to any of the other items
60
- * from the same asset class.
50
+ * is a CopyBag, then it represents the bag (multiset) of those keys, where each
51
+ * key represents some individual semi-fungible item, like a concert ticket,
52
+ * from the semi-fungible asset class represented by that amount's brand. The
53
+ * number of times that key appears in the bag is the number of fungible units
54
+ * of that key. The amount itself represents the bag of these items, as opposed
55
+ * to any of the other items from the same asset class.
61
56
  *
62
- * If a given value class represents concert tickets, it seems bizarre
63
- * that we can form amounts of any key. The hard constraint is that
64
- * the code that holds the mint for that asset class---the one associated
65
- * with that brand, only mints the items representing the real units
66
- * of that asset class as defined by it. Anyone else can put together
67
- * an amount expressing, for example, that they "want" some items that
68
- * will never be minted. That want will never be satisfied.
69
- * "You can't always get..."
57
+ * If a given value class represents concert tickets, it seems bizarre that we
58
+ * can form amounts of any key. The hard constraint is that the code that holds
59
+ * the mint for that asset class---the one associated with that brand, only
60
+ * mints the items representing the real units of that asset class as defined by
61
+ * it. Anyone else can put together an amount expressing, for example, that they
62
+ * "want" some items that will never be minted. That want will never be
63
+ * satisfied. "You can't always get..."
70
64
  */
71
65
  const CopyBagValueShape = M.bag();
72
66
 
@@ -106,11 +100,11 @@ export const isCopySetValue = value => matches(value, CopySetValueShape);
106
100
  harden(isCopySetValue);
107
101
 
108
102
  /**
109
- * Returns true if value is a pass by copy array structure. Does not
110
- * check for duplicates. To check for duplicates, use setMathHelpers.coerce.
103
+ * Returns true if value is a pass by copy array structure. Does not check for
104
+ * duplicates. To check for duplicates, use setMathHelpers.coerce.
111
105
  *
112
106
  * @deprecated Please change from using array-based SetValues to CopySet-based
113
- * CopySetValues.
107
+ * CopySetValues.
114
108
  * @param {AmountValue} value
115
109
  * @returns {value is SetValue}
116
110
  */
@@ -218,7 +212,7 @@ export const makeIssuerInterfaces = (
218
212
  });
219
213
 
220
214
  const DepositFacetI = M.interface('DepositFacet', {
221
- receive: PurseI.methodGuards.deposit,
215
+ receive: getInterfaceGuardPayload(PurseI).methodGuards.deposit,
222
216
  });
223
217
 
224
218
  const PurseIKit = harden({