@agoric/ertp 0.16.3-dev-64cb69f.0 → 0.16.3-dev-c5284e4.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 +17 -16
- package/src/amountStore.js +32 -0
- package/src/index.js +7 -0
- package/src/issuerKit.js +79 -21
- package/src/mathHelpers/copyBagMathHelpers.js +2 -2
- package/src/payment.js +5 -13
- package/src/paymentLedger.js +61 -66
- package/src/purse.js +72 -31
- package/src/types-ambient.js +32 -13
- package/src/types.js +32 -13
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agoric/ertp",
|
|
3
|
-
"version": "0.16.3-dev-
|
|
3
|
+
"version": "0.16.3-dev-c5284e4.0+c5284e4",
|
|
4
4
|
"description": "Electronic Rights Transfer Protocol (ERTP). A smart contract framework for exchanging electronic rights",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.js",
|
|
@@ -39,23 +39,24 @@
|
|
|
39
39
|
},
|
|
40
40
|
"homepage": "https://github.com/Agoric/agoric-sdk#readme",
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@agoric/assert": "0.6.1-dev-
|
|
43
|
-
"@agoric/notifier": "0.6.3-dev-
|
|
44
|
-
"@agoric/store": "0.9.3-dev-
|
|
45
|
-
"@agoric/vat-data": "0.5.3-dev-
|
|
46
|
-
"@
|
|
47
|
-
"@endo/
|
|
48
|
-
"@endo/
|
|
49
|
-
"@endo/
|
|
50
|
-
"@endo/
|
|
51
|
-
"@endo/
|
|
42
|
+
"@agoric/assert": "0.6.1-dev-c5284e4.0+c5284e4",
|
|
43
|
+
"@agoric/notifier": "0.6.3-dev-c5284e4.0+c5284e4",
|
|
44
|
+
"@agoric/store": "0.9.3-dev-c5284e4.0+c5284e4",
|
|
45
|
+
"@agoric/vat-data": "0.5.3-dev-c5284e4.0+c5284e4",
|
|
46
|
+
"@agoric/zone": "0.2.3-dev-c5284e4.0+c5284e4",
|
|
47
|
+
"@endo/eventual-send": "^1.1.2",
|
|
48
|
+
"@endo/far": "^1.0.4",
|
|
49
|
+
"@endo/marshal": "^1.3.0",
|
|
50
|
+
"@endo/nat": "^5.0.4",
|
|
51
|
+
"@endo/patterns": "^1.2.0",
|
|
52
|
+
"@endo/promise-kit": "^1.0.4"
|
|
52
53
|
},
|
|
53
54
|
"devDependencies": {
|
|
54
|
-
"@agoric/swingset-vat": "0.32.3-dev-
|
|
55
|
-
"@endo/bundle-source": "^3.0
|
|
55
|
+
"@agoric/swingset-vat": "0.32.3-dev-c5284e4.0+c5284e4",
|
|
56
|
+
"@endo/bundle-source": "^3.1.0",
|
|
56
57
|
"@fast-check/ava": "^1.1.5",
|
|
57
58
|
"ava": "^5.3.0",
|
|
58
|
-
"tsd": "^0.
|
|
59
|
+
"tsd": "^0.30.4"
|
|
59
60
|
},
|
|
60
61
|
"files": [
|
|
61
62
|
"src",
|
|
@@ -84,7 +85,7 @@
|
|
|
84
85
|
"access": "public"
|
|
85
86
|
},
|
|
86
87
|
"typeCoverage": {
|
|
87
|
-
"atLeast": 90.
|
|
88
|
+
"atLeast": 90.56
|
|
88
89
|
},
|
|
89
|
-
"gitHead": "
|
|
90
|
+
"gitHead": "c5284e4721ad2702c4551f216bb8eed7abe4d7cf"
|
|
90
91
|
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { AmountMath } from './amountMath.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @template {AssetKind} [K=AssetKind]
|
|
5
|
+
* @typedef {object} AmountStore
|
|
6
|
+
* @property {() => Amount<K>} getAmount
|
|
7
|
+
* @property {(delta: Amount<K>) => void} increment
|
|
8
|
+
* @property {(delta: Amount<K>) => boolean} decrement
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @template {AssetKind} [K=AssetKind]
|
|
13
|
+
* @param {object} state
|
|
14
|
+
* @param {string} key
|
|
15
|
+
* @returns {AmountStore<K>}
|
|
16
|
+
*/
|
|
17
|
+
export const makeAmountStore = (state, key) => {
|
|
18
|
+
return harden({
|
|
19
|
+
getAmount: () => state[key],
|
|
20
|
+
increment: delta => {
|
|
21
|
+
state[key] = AmountMath.add(state[key], delta);
|
|
22
|
+
},
|
|
23
|
+
decrement: delta => {
|
|
24
|
+
if (AmountMath.isGTE(state[key], delta)) {
|
|
25
|
+
state[key] = AmountMath.subtract(state[key], delta);
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
return false;
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
};
|
|
32
|
+
harden(makeAmountStore);
|
package/src/index.js
CHANGED
|
@@ -3,3 +3,10 @@
|
|
|
3
3
|
export * from './amountMath.js';
|
|
4
4
|
export * from './issuerKit.js';
|
|
5
5
|
export * from './typeGuards.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Importing Baggage from `@agoric/ertp` is deprecated. Import Baggage from
|
|
9
|
+
* `@agoric/vat-data` instead
|
|
10
|
+
*
|
|
11
|
+
* @typedef {import('@agoric/vat-data').Baggage} Baggage
|
|
12
|
+
*/
|
package/src/issuerKit.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
// @jessie-check
|
|
2
2
|
|
|
3
|
-
import { assert } from '@agoric/assert';
|
|
3
|
+
import { assert, Fail } from '@agoric/assert';
|
|
4
4
|
import { assertPattern } from '@agoric/store';
|
|
5
5
|
import { makeScalarBigMapStore } from '@agoric/vat-data';
|
|
6
|
+
import { makeDurableZone } from '@agoric/zone/durable.js';
|
|
6
7
|
|
|
7
8
|
import { AssetKind, assertAssetKind } from './amountMath.js';
|
|
8
9
|
import { coerceDisplayInfo } from './displayInfo.js';
|
|
@@ -10,10 +11,6 @@ import { preparePaymentLedger } from './paymentLedger.js';
|
|
|
10
11
|
|
|
11
12
|
import './types-ambient.js';
|
|
12
13
|
|
|
13
|
-
// TODO Why does TypeScript lose the `MapStore` typing of `Baggage` here, even
|
|
14
|
-
// though it knows the correct type at the exporting `@agoric/vat-data`
|
|
15
|
-
/** @typedef {import('@agoric/vat-data').Baggage} Baggage */
|
|
16
|
-
|
|
17
14
|
/**
|
|
18
15
|
* @template {AssetKind} K
|
|
19
16
|
* @typedef {object} IssuerRecord
|
|
@@ -28,7 +25,9 @@ import './types-ambient.js';
|
|
|
28
25
|
*
|
|
29
26
|
* @template {AssetKind} K
|
|
30
27
|
* @param {IssuerRecord<K>} issuerRecord
|
|
31
|
-
* @param {
|
|
28
|
+
* @param {import('@agoric/zone').Zone} issuerZone
|
|
29
|
+
* @param {RecoverySetsOption} recoverySetsState Omitted from issuerRecord
|
|
30
|
+
* because it was added in an upgrade.
|
|
32
31
|
* @param {ShutdownWithFailure} [optShutdownWithFailure] If this issuer fails in
|
|
33
32
|
* the middle of an atomic action (which btw should never happen), it
|
|
34
33
|
* potentially leaves its ledger in a corrupted state. If this function was
|
|
@@ -40,7 +39,8 @@ import './types-ambient.js';
|
|
|
40
39
|
*/
|
|
41
40
|
const setupIssuerKit = (
|
|
42
41
|
{ name, assetKind, displayInfo, elementShape },
|
|
43
|
-
|
|
42
|
+
issuerZone,
|
|
43
|
+
recoverySetsState,
|
|
44
44
|
optShutdownWithFailure = undefined,
|
|
45
45
|
) => {
|
|
46
46
|
assert.typeof(name, 'string');
|
|
@@ -60,11 +60,12 @@ const setupIssuerKit = (
|
|
|
60
60
|
/** @type {PaymentLedger<K>} */
|
|
61
61
|
// @ts-expect-error could be instantiated with different subtype of AssetKind
|
|
62
62
|
const { issuer, mint, brand, mintRecoveryPurse } = preparePaymentLedger(
|
|
63
|
-
|
|
63
|
+
issuerZone,
|
|
64
64
|
name,
|
|
65
65
|
assetKind,
|
|
66
66
|
cleanDisplayInfo,
|
|
67
67
|
elementShape,
|
|
68
|
+
recoverySetsState,
|
|
68
69
|
optShutdownWithFailure,
|
|
69
70
|
);
|
|
70
71
|
|
|
@@ -80,13 +81,19 @@ harden(setupIssuerKit);
|
|
|
80
81
|
|
|
81
82
|
/** The key at which the issuer record is stored. */
|
|
82
83
|
const INSTANCE_KEY = 'issuer';
|
|
84
|
+
/**
|
|
85
|
+
* The key at which the issuerKit's `RecoverySetsOption` state is stored.
|
|
86
|
+
* Introduced by an upgrade, so may be absent on a predecessor incarnation. See
|
|
87
|
+
* `RecoverySetsOption` for defaulting behavior.
|
|
88
|
+
*/
|
|
89
|
+
const RECOVERY_SETS_STATE = 'recoverySetsState';
|
|
83
90
|
|
|
84
91
|
/**
|
|
85
92
|
* Used _only_ to upgrade a predecessor issuerKit. Use `makeDurableIssuerKit` to
|
|
86
93
|
* make a new one.
|
|
87
94
|
*
|
|
88
95
|
* @template {AssetKind} K
|
|
89
|
-
* @param {Baggage} issuerBaggage
|
|
96
|
+
* @param {import('@agoric/vat-data').Baggage} issuerBaggage
|
|
90
97
|
* @param {ShutdownWithFailure} [optShutdownWithFailure] If this issuer fails in
|
|
91
98
|
* the middle of an atomic action (which btw should never happen), it
|
|
92
99
|
* potentially leaves its ledger in a corrupted state. If this function was
|
|
@@ -94,21 +101,46 @@ const INSTANCE_KEY = 'issuer';
|
|
|
94
101
|
* unit of computation, like the enclosing vat, can be shutdown before
|
|
95
102
|
* anything else is corrupted by that corrupted state. See
|
|
96
103
|
* https://github.com/Agoric/agoric-sdk/issues/3434
|
|
104
|
+
* @param {RecoverySetsOption} [recoverySetsOption] Added in upgrade, so last
|
|
105
|
+
* and optional. See `RecoverySetsOption` for defaulting behavior.
|
|
97
106
|
* @returns {IssuerKit<K>}
|
|
98
107
|
*/
|
|
99
108
|
export const upgradeIssuerKit = (
|
|
100
109
|
issuerBaggage,
|
|
101
110
|
optShutdownWithFailure = undefined,
|
|
111
|
+
recoverySetsOption = undefined,
|
|
102
112
|
) => {
|
|
103
113
|
const issuerRecord = issuerBaggage.get(INSTANCE_KEY);
|
|
104
|
-
|
|
114
|
+
const issuerZone = makeDurableZone(issuerBaggage);
|
|
115
|
+
const oldRecoverySetsState = issuerBaggage.has(RECOVERY_SETS_STATE)
|
|
116
|
+
? issuerBaggage.get(RECOVERY_SETS_STATE)
|
|
117
|
+
: 'hasRecoverySets';
|
|
118
|
+
if (
|
|
119
|
+
oldRecoverySetsState === 'noRecoverySets' &&
|
|
120
|
+
recoverySetsOption === 'hasRecoverySets'
|
|
121
|
+
) {
|
|
122
|
+
Fail`Cannot (yet?) upgrade from 'noRecoverySets' to 'hasRecoverySets'`;
|
|
123
|
+
}
|
|
124
|
+
if (
|
|
125
|
+
oldRecoverySetsState === 'hasRecoverySets' &&
|
|
126
|
+
recoverySetsOption === 'noRecoverySets'
|
|
127
|
+
) {
|
|
128
|
+
Fail`Cannot (yet?) upgrade from 'hasRecoverySets' to 'noRecoverySets'`;
|
|
129
|
+
}
|
|
130
|
+
const recoverySetsState = recoverySetsOption || oldRecoverySetsState;
|
|
131
|
+
return setupIssuerKit(
|
|
132
|
+
issuerRecord,
|
|
133
|
+
issuerZone,
|
|
134
|
+
recoverySetsState,
|
|
135
|
+
optShutdownWithFailure,
|
|
136
|
+
);
|
|
105
137
|
};
|
|
106
138
|
harden(upgradeIssuerKit);
|
|
107
139
|
|
|
108
140
|
/**
|
|
109
141
|
* Does baggage already have an issuerKit?
|
|
110
142
|
*
|
|
111
|
-
* @param {Baggage} baggage
|
|
143
|
+
* @param {import('@agoric/vat-data').Baggage} baggage
|
|
112
144
|
*/
|
|
113
145
|
export const hasIssuer = baggage => baggage.has(INSTANCE_KEY);
|
|
114
146
|
|
|
@@ -121,8 +153,14 @@ export const hasIssuer = baggage => baggage.has(INSTANCE_KEY);
|
|
|
121
153
|
* typically, the amount of an invitation payment is a singleton set. Such a
|
|
122
154
|
* payment is often referred to in the singular as "an invitation".)
|
|
123
155
|
*
|
|
156
|
+
* `recoverySetsOption` added in upgrade. Note that `IssuerOptionsRecord` is
|
|
157
|
+
* never stored, so we never need to worry about inheriting one from a
|
|
158
|
+
* predecessor predating the introduction of recovery sets. See
|
|
159
|
+
* `RecoverySetsOption` for defaulting behavior.
|
|
160
|
+
*
|
|
124
161
|
* @typedef {Partial<{
|
|
125
162
|
* elementShape: Pattern;
|
|
163
|
+
* recoverySetsOption: RecoverySetsOption;
|
|
126
164
|
* }>} IssuerOptionsRecord
|
|
127
165
|
*/
|
|
128
166
|
|
|
@@ -142,7 +180,7 @@ export const hasIssuer = baggage => baggage.has(INSTANCE_KEY);
|
|
|
142
180
|
* basic fungible tokens.
|
|
143
181
|
*
|
|
144
182
|
* `displayInfo` gives information to the UI on how to display the amount.
|
|
145
|
-
* @param {Baggage} issuerBaggage
|
|
183
|
+
* @param {import('@agoric/vat-data').Baggage} issuerBaggage
|
|
146
184
|
* @param {string} name
|
|
147
185
|
* @param {K} [assetKind]
|
|
148
186
|
* @param {AdditionalDisplayInfo} [displayInfo]
|
|
@@ -163,11 +201,24 @@ export const makeDurableIssuerKit = (
|
|
|
163
201
|
assetKind = AssetKind.NAT,
|
|
164
202
|
displayInfo = harden({}),
|
|
165
203
|
optShutdownWithFailure = undefined,
|
|
166
|
-
{ elementShape = undefined } = {},
|
|
204
|
+
{ elementShape = undefined, recoverySetsOption = undefined } = {},
|
|
167
205
|
) => {
|
|
168
|
-
const issuerData = harden({
|
|
206
|
+
const issuerData = harden({
|
|
207
|
+
name,
|
|
208
|
+
assetKind,
|
|
209
|
+
displayInfo,
|
|
210
|
+
elementShape,
|
|
211
|
+
});
|
|
169
212
|
issuerBaggage.init(INSTANCE_KEY, issuerData);
|
|
170
|
-
|
|
213
|
+
const issuerZone = makeDurableZone(issuerBaggage);
|
|
214
|
+
const recoverySetsState = recoverySetsOption || 'hasRecoverySets';
|
|
215
|
+
issuerBaggage.init(RECOVERY_SETS_STATE, recoverySetsState);
|
|
216
|
+
return setupIssuerKit(
|
|
217
|
+
issuerData,
|
|
218
|
+
issuerZone,
|
|
219
|
+
recoverySetsState,
|
|
220
|
+
optShutdownWithFailure,
|
|
221
|
+
);
|
|
171
222
|
};
|
|
172
223
|
harden(makeDurableIssuerKit);
|
|
173
224
|
|
|
@@ -187,7 +238,7 @@ harden(makeDurableIssuerKit);
|
|
|
187
238
|
* basic fungible tokens.
|
|
188
239
|
*
|
|
189
240
|
* `displayInfo` gives information to the UI on how to display the amount.
|
|
190
|
-
* @param {Baggage} issuerBaggage
|
|
241
|
+
* @param {import('@agoric/vat-data').Baggage} issuerBaggage
|
|
191
242
|
* @param {string} name
|
|
192
243
|
* @param {K} [assetKind]
|
|
193
244
|
* @param {AdditionalDisplayInfo} [displayInfo]
|
|
@@ -211,12 +262,19 @@ export const prepareIssuerKit = (
|
|
|
211
262
|
options = {},
|
|
212
263
|
) => {
|
|
213
264
|
if (hasIssuer(issuerBaggage)) {
|
|
214
|
-
const { elementShape: _ = undefined } =
|
|
215
|
-
|
|
265
|
+
const { elementShape: _ = undefined, recoverySetsOption = undefined } =
|
|
266
|
+
options;
|
|
267
|
+
const issuerKit = upgradeIssuerKit(
|
|
268
|
+
issuerBaggage,
|
|
269
|
+
optShutdownWithFailure,
|
|
270
|
+
recoverySetsOption,
|
|
271
|
+
);
|
|
216
272
|
|
|
217
273
|
// TODO check consistency with name, assetKind, displayInfo, elementShape.
|
|
218
274
|
// Consistency either means that these are the same, or that they differ
|
|
219
|
-
// in a direction we are prepared to upgrade.
|
|
275
|
+
// in a direction we are prepared to upgrade. Note that it is the
|
|
276
|
+
// responsibility of `upgradeIssuerKit` to check consistency of
|
|
277
|
+
// `recoverySetsOption`, so continue to not do that here.
|
|
220
278
|
|
|
221
279
|
// @ts-expect-error Type parameter confusion.
|
|
222
280
|
return issuerKit;
|
|
@@ -274,7 +332,7 @@ export const makeIssuerKit = (
|
|
|
274
332
|
assetKind = AssetKind.NAT,
|
|
275
333
|
displayInfo = harden({}),
|
|
276
334
|
optShutdownWithFailure = undefined,
|
|
277
|
-
{ elementShape = undefined } = {},
|
|
335
|
+
{ elementShape = undefined, recoverySetsOption = undefined } = {},
|
|
278
336
|
) =>
|
|
279
337
|
makeDurableIssuerKit(
|
|
280
338
|
makeScalarBigMapStore('dropped issuer kit', { durable: true }),
|
|
@@ -282,6 +340,6 @@ export const makeIssuerKit = (
|
|
|
282
340
|
assetKind,
|
|
283
341
|
displayInfo,
|
|
284
342
|
optShutdownWithFailure,
|
|
285
|
-
{ elementShape },
|
|
343
|
+
{ elementShape, recoverySetsOption },
|
|
286
344
|
);
|
|
287
345
|
harden(makeIssuerKit);
|
|
@@ -12,10 +12,10 @@ import {
|
|
|
12
12
|
} from '@agoric/store';
|
|
13
13
|
import '../types-ambient.js';
|
|
14
14
|
|
|
15
|
-
/** @type {CopyBag} */
|
|
15
|
+
/** @type {import('@endo/patterns').CopyBag} */
|
|
16
16
|
const empty = makeCopyBag([]);
|
|
17
17
|
|
|
18
|
-
/** @type {MathHelpers<CopyBag>} */
|
|
18
|
+
/** @type {MathHelpers<import('@endo/patterns').CopyBag>} */
|
|
19
19
|
export const copyBagMathHelpers = harden({
|
|
20
20
|
doCoerce: bag => {
|
|
21
21
|
mustMatch(bag, M.bag(), 'bag of amount');
|
package/src/payment.js
CHANGED
|
@@ -1,26 +1,18 @@
|
|
|
1
1
|
// @jessie-check
|
|
2
2
|
|
|
3
3
|
import { initEmpty } from '@agoric/store';
|
|
4
|
-
import { prepareExoClass } from '@agoric/vat-data';
|
|
5
|
-
|
|
6
|
-
/** @typedef {import('@endo/patterns').MethodGuard} MethodGuard */
|
|
7
|
-
/**
|
|
8
|
-
* @template {Record<string | symbol, MethodGuard>} [T=Record<string | symbol, MethodGuard>]
|
|
9
|
-
* @typedef {import('@endo/patterns').InterfaceGuard<T>} InterfaceGuard
|
|
10
|
-
*/
|
|
11
|
-
/** @typedef {import('@agoric/vat-data').Baggage} Baggage */
|
|
12
4
|
|
|
5
|
+
// TODO Type InterfaceGuard better than InterfaceGuard<any>
|
|
13
6
|
/**
|
|
14
7
|
* @template {AssetKind} K
|
|
15
|
-
* @param {
|
|
8
|
+
* @param {import('@agoric/zone').Zone} issuerZone
|
|
16
9
|
* @param {string} name
|
|
17
10
|
* @param {Brand<K>} brand
|
|
18
|
-
* @param {InterfaceGuard} PaymentI
|
|
11
|
+
* @param {import('@endo/patterns').InterfaceGuard<any>} PaymentI
|
|
19
12
|
* @returns {() => Payment<K>}
|
|
20
13
|
*/
|
|
21
|
-
export const preparePaymentKind = (
|
|
22
|
-
const makePayment =
|
|
23
|
-
issuerBaggage,
|
|
14
|
+
export const preparePaymentKind = (issuerZone, name, brand, PaymentI) => {
|
|
15
|
+
const makePayment = issuerZone.exoClass(
|
|
24
16
|
`${name} payment`,
|
|
25
17
|
PaymentI,
|
|
26
18
|
initEmpty,
|
package/src/paymentLedger.js
CHANGED
|
@@ -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
|
/**
|
|
@@ -74,25 +67,31 @@ const amountShapeFromElementShape = (brand, assetKind, elementShape) => {
|
|
|
74
67
|
* minting and transfer authority originates here.
|
|
75
68
|
*
|
|
76
69
|
* @template {AssetKind} K
|
|
77
|
-
* @param {
|
|
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
|
-
|
|
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
|
-
//
|
|
95
|
-
|
|
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(
|
|
123
|
+
const makePayment = preparePaymentKind(issuerZone, name, brand, PaymentI);
|
|
125
124
|
|
|
126
125
|
/** @type {ShutdownWithFailure} */
|
|
127
126
|
const shutdownLedgerWithFailure = reason => {
|
|
@@ -139,18 +138,16 @@ export const preparePaymentLedger = (
|
|
|
139
138
|
};
|
|
140
139
|
|
|
141
140
|
/** @type {WeakMapStore<Payment, Amount>} */
|
|
142
|
-
const paymentLedger =
|
|
143
|
-
|
|
144
|
-
|
|
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
|
-
* it was withdrawn from. Let's call these "recoverable" payments.
|
|
151
|
-
* recoverable payments are live, but not all live payments are
|
|
152
|
-
* We do the bookkeeping for payment recovery with this weakmap
|
|
153
|
-
* recoverable payments to the recovery set they are in. A bunch of
|
|
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
|
|
154
151
|
* interesting invariants here:
|
|
155
152
|
*
|
|
156
153
|
* - Every payment that is a key in the outer `paymentRecoverySets` weakMap is
|
|
@@ -162,12 +159,12 @@ export const preparePaymentLedger = (
|
|
|
162
159
|
* - A purse's recovery set only contains payments withdrawn from that purse and
|
|
163
160
|
* not yet consumed.
|
|
164
161
|
*
|
|
162
|
+
* If `recoverySetsState === 'noRecoverySets'`, then nothing should ever be
|
|
163
|
+
* added to this WeakStore.
|
|
164
|
+
*
|
|
165
165
|
* @type {WeakMapStore<Payment, SetStore<Payment>>}
|
|
166
166
|
*/
|
|
167
|
-
const paymentRecoverySets =
|
|
168
|
-
issuerBaggage,
|
|
169
|
-
'paymentRecoverySets',
|
|
170
|
-
);
|
|
167
|
+
const paymentRecoverySets = issuerZone.weakMapStore('paymentRecoverySets');
|
|
171
168
|
|
|
172
169
|
/**
|
|
173
170
|
* To maintain the invariants listed in the `paymentRecoverySets` comment,
|
|
@@ -178,7 +175,11 @@ export const preparePaymentLedger = (
|
|
|
178
175
|
* @param {SetStore<Payment>} [optRecoverySet]
|
|
179
176
|
*/
|
|
180
177
|
const initPayment = (payment, amount, optRecoverySet = undefined) => {
|
|
181
|
-
if (
|
|
178
|
+
if (recoverySetsState === 'noRecoverySets') {
|
|
179
|
+
optRecoverySet === undefined ||
|
|
180
|
+
Fail`when recoverSetsState === 'noRecoverySets', optRecoverySet must be empty`;
|
|
181
|
+
}
|
|
182
|
+
if (optRecoverySet !== undefined && !AmountMath.isEmpty(amount)) {
|
|
182
183
|
optRecoverySet.add(payment);
|
|
183
184
|
paymentRecoverySets.init(payment, optRecoverySet);
|
|
184
185
|
}
|
|
@@ -200,10 +201,6 @@ export const preparePaymentLedger = (
|
|
|
200
201
|
}
|
|
201
202
|
};
|
|
202
203
|
|
|
203
|
-
/** @type {(left: Amount, right: Amount) => Amount} */
|
|
204
|
-
const add = (left, right) => AmountMath.add(left, right, brand);
|
|
205
|
-
/** @type {(left: Amount, right: Amount) => Amount} */
|
|
206
|
-
const subtract = (left, right) => AmountMath.subtract(left, right, brand);
|
|
207
204
|
/** @type {(allegedAmount: Amount) => Amount} */
|
|
208
205
|
const coerce = allegedAmount => AmountMath.coerce(brand, allegedAmount);
|
|
209
206
|
/** @type {(left: Amount, right: Amount) => boolean} */
|
|
@@ -239,17 +236,13 @@ export const preparePaymentLedger = (
|
|
|
239
236
|
/**
|
|
240
237
|
* Used by the purse code to implement purse.deposit
|
|
241
238
|
*
|
|
242
|
-
* @param {
|
|
243
|
-
* deposit
|
|
244
|
-
* @param {(newPurseBalance: Amount) => void} updatePurseBalance - commit the
|
|
245
|
-
* purse balance
|
|
239
|
+
* @param {import('./amountStore.js').AmountStore} balanceStore
|
|
246
240
|
* @param {Payment} srcPayment
|
|
247
241
|
* @param {Pattern} [optAmountShape]
|
|
248
242
|
* @returns {Amount}
|
|
249
243
|
*/
|
|
250
244
|
const depositInternal = (
|
|
251
|
-
|
|
252
|
-
updatePurseBalance,
|
|
245
|
+
balanceStore,
|
|
253
246
|
srcPayment,
|
|
254
247
|
optAmountShape = undefined,
|
|
255
248
|
) => {
|
|
@@ -261,13 +254,12 @@ export const preparePaymentLedger = (
|
|
|
261
254
|
assertLivePayment(srcPayment);
|
|
262
255
|
const srcPaymentBalance = paymentLedger.get(srcPayment);
|
|
263
256
|
assertAmountConsistent(srcPaymentBalance, optAmountShape);
|
|
264
|
-
const newPurseBalance = add(srcPaymentBalance, currentBalance);
|
|
265
257
|
try {
|
|
266
258
|
// COMMIT POINT
|
|
267
259
|
// Move the assets in `srcPayment` into this purse, using up the
|
|
268
260
|
// source payment, such that total assets are conserved.
|
|
269
261
|
deletePayment(srcPayment);
|
|
270
|
-
|
|
262
|
+
balanceStore.increment(srcPaymentBalance);
|
|
271
263
|
} catch (err) {
|
|
272
264
|
shutdownLedgerWithFailure(err);
|
|
273
265
|
throw err;
|
|
@@ -278,30 +270,19 @@ export const preparePaymentLedger = (
|
|
|
278
270
|
/**
|
|
279
271
|
* Used by the purse code to implement purse.withdraw
|
|
280
272
|
*
|
|
281
|
-
* @param {
|
|
282
|
-
* withdrawal
|
|
283
|
-
* @param {(newPurseBalance: Amount) => void} updatePurseBalance - commit the
|
|
284
|
-
* purse balance
|
|
273
|
+
* @param {import('./amountStore.js').AmountStore} balanceStore
|
|
285
274
|
* @param {Amount} amount - the amount to be withdrawn
|
|
286
|
-
* @param {SetStore<Payment>} recoverySet
|
|
275
|
+
* @param {SetStore<Payment>} [recoverySet]
|
|
287
276
|
* @returns {Payment}
|
|
288
277
|
*/
|
|
289
|
-
const withdrawInternal = (
|
|
290
|
-
currentBalance,
|
|
291
|
-
updatePurseBalance,
|
|
292
|
-
amount,
|
|
293
|
-
recoverySet,
|
|
294
|
-
) => {
|
|
278
|
+
const withdrawInternal = (balanceStore, amount, recoverySet = undefined) => {
|
|
295
279
|
amount = coerce(amount);
|
|
296
|
-
AmountMath.isGTE(currentBalance, amount) ||
|
|
297
|
-
Fail`Withdrawal of ${amount} failed because the purse only contained ${currentBalance}`;
|
|
298
|
-
const newPurseBalance = subtract(currentBalance, amount);
|
|
299
|
-
|
|
300
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()}`;
|
|
301
285
|
try {
|
|
302
|
-
// COMMIT POINT Move the withdrawn assets from this purse into
|
|
303
|
-
// payment. Total assets must remain conserved.
|
|
304
|
-
updatePurseBalance(newPurseBalance);
|
|
305
286
|
initPayment(payment, amount, recoverySet);
|
|
306
287
|
} catch (err) {
|
|
307
288
|
shutdownLedgerWithFailure(err);
|
|
@@ -313,7 +294,7 @@ export const preparePaymentLedger = (
|
|
|
313
294
|
/** @type {() => Purse<K>} */
|
|
314
295
|
// @ts-expect-error type parameter confusion
|
|
315
296
|
const makeEmptyPurse = preparePurseKind(
|
|
316
|
-
|
|
297
|
+
issuerZone,
|
|
317
298
|
name,
|
|
318
299
|
assetKind,
|
|
319
300
|
brand,
|
|
@@ -322,11 +303,17 @@ export const preparePaymentLedger = (
|
|
|
322
303
|
depositInternal,
|
|
323
304
|
withdrawInternal,
|
|
324
305
|
}),
|
|
306
|
+
recoverySetsState,
|
|
307
|
+
paymentRecoverySets,
|
|
325
308
|
);
|
|
326
309
|
|
|
327
310
|
/** @type {Issuer<K>} */
|
|
328
|
-
//
|
|
329
|
-
|
|
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, {
|
|
330
317
|
getBrand() {
|
|
331
318
|
return brand;
|
|
332
319
|
},
|
|
@@ -379,20 +366,28 @@ export const preparePaymentLedger = (
|
|
|
379
366
|
* Because the `mintRecoveryPurse` is placed in baggage, even if the caller of
|
|
380
367
|
* `makeIssuerKit` drops it on the floor, it can still be recovered in an
|
|
381
368
|
* emergency upgrade.
|
|
382
|
-
*
|
|
383
|
-
* @type {Purse<K>}
|
|
384
369
|
*/
|
|
385
|
-
|
|
386
|
-
|
|
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())
|
|
387
378
|
);
|
|
388
379
|
|
|
389
380
|
/** @type {Mint<K>} */
|
|
390
|
-
const mint =
|
|
381
|
+
const mint = issuerZone.exo(`${name} mint`, MintI, {
|
|
391
382
|
getIssuer() {
|
|
392
383
|
return issuer;
|
|
393
384
|
},
|
|
394
385
|
mintPayment(newAmount) {
|
|
395
|
-
//
|
|
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
|
|
396
391
|
newAmount = coerce(newAmount);
|
|
397
392
|
mustMatch(newAmount, amountShape, 'minted amount');
|
|
398
393
|
// `rawPayment` is not associated with any recovery set, and
|
package/src/purse.js
CHANGED
|
@@ -1,45 +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';
|
|
5
|
-
|
|
6
|
-
// TODO `InterfaceGuard` type parameter
|
|
7
|
-
/** @typedef {import('@endo/patterns').InterfaceGuard} InterfaceGuard */
|
|
8
|
-
/** @typedef {import('@agoric/vat-data').Baggage} Baggage */
|
|
4
|
+
import { makeAmountStore } from './amountStore.js';
|
|
9
5
|
|
|
10
6
|
const { Fail } = assert;
|
|
11
7
|
|
|
8
|
+
const EMPTY_COPY_SET = makeCopySet([]);
|
|
9
|
+
|
|
10
|
+
// TODO Type InterfaceGuard better than InterfaceGuard<any>
|
|
12
11
|
/**
|
|
13
|
-
* @param {
|
|
12
|
+
* @param {import('@agoric/zone').Zone} issuerZone
|
|
14
13
|
* @param {string} name
|
|
15
14
|
* @param {AssetKind} assetKind
|
|
16
15
|
* @param {Brand} brand
|
|
17
16
|
* @param {{
|
|
18
|
-
* purse: InterfaceGuard
|
|
19
|
-
* depositFacet: InterfaceGuard
|
|
17
|
+
* purse: import('@endo/patterns').InterfaceGuard<any>;
|
|
18
|
+
* depositFacet: import('@endo/patterns').InterfaceGuard<any>;
|
|
20
19
|
* }} PurseIKit
|
|
21
20
|
* @param {{
|
|
22
21
|
* depositInternal: any;
|
|
23
22
|
* withdrawInternal: any;
|
|
24
23
|
* }} purseMethods
|
|
24
|
+
* @param {RecoverySetsOption} recoverySetsState
|
|
25
|
+
* @param {WeakMapStore<Payment, SetStore<Payment>>} paymentRecoverySets
|
|
25
26
|
*/
|
|
26
27
|
export const preparePurseKind = (
|
|
27
|
-
|
|
28
|
+
issuerZone,
|
|
28
29
|
name,
|
|
29
30
|
assetKind,
|
|
30
31
|
brand,
|
|
31
32
|
PurseIKit,
|
|
32
33
|
purseMethods,
|
|
34
|
+
recoverySetsState,
|
|
35
|
+
paymentRecoverySets,
|
|
33
36
|
) => {
|
|
34
37
|
const amountShape = brand.getAmountShape();
|
|
35
38
|
|
|
36
39
|
// Note: Virtual for high cardinality, but *not* durable, and so
|
|
37
40
|
// broken across an upgrade.
|
|
41
|
+
// TODO propagate zonifying to notifiers, maybe?
|
|
38
42
|
const { provideNotifier, update: updateBalance } = makeTransientNotifierKit();
|
|
39
43
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
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
|
+
}
|
|
43
70
|
};
|
|
44
71
|
|
|
45
72
|
// - This kind is a pair of purse and depositFacet that have a 1:1
|
|
@@ -49,17 +76,14 @@ export const preparePurseKind = (
|
|
|
49
76
|
// that created depositFacet as needed. But this approach ensures a constant
|
|
50
77
|
// identity for the facet and exercises the multi-faceted object style.
|
|
51
78
|
const { depositInternal, withdrawInternal } = purseMethods;
|
|
52
|
-
const makePurseKit =
|
|
53
|
-
issuerBaggage,
|
|
79
|
+
const makePurseKit = issuerZone.exoClassKit(
|
|
54
80
|
`${name} Purse`,
|
|
55
81
|
PurseIKit,
|
|
56
82
|
() => {
|
|
57
83
|
const currentBalance = AmountMath.makeEmpty(brand, assetKind);
|
|
58
84
|
|
|
59
85
|
/** @type {SetStore<Payment>} */
|
|
60
|
-
const recoverySet =
|
|
61
|
-
durable: true,
|
|
62
|
-
});
|
|
86
|
+
const recoverySet = issuerZone.detached().setStore('recovery set');
|
|
63
87
|
|
|
64
88
|
return {
|
|
65
89
|
currentBalance,
|
|
@@ -72,28 +96,36 @@ export const preparePurseKind = (
|
|
|
72
96
|
// PurseI does *not* delay `deposit` until `srcPayment` is fulfulled.
|
|
73
97
|
// See the comments on PurseI.deposit in typeGuards.js
|
|
74
98
|
const { state } = this;
|
|
99
|
+
const { purse } = this.facets;
|
|
100
|
+
const balanceStore = makeAmountStore(state, 'currentBalance');
|
|
75
101
|
// Note COMMIT POINT within deposit.
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
newPurseBalance =>
|
|
79
|
-
updatePurseBalance(state, newPurseBalance, this.facets.purse),
|
|
102
|
+
const srcPaymentBalance = depositInternal(
|
|
103
|
+
balanceStore,
|
|
80
104
|
srcPayment,
|
|
81
105
|
optAmountShape,
|
|
82
106
|
);
|
|
107
|
+
updateBalance(purse, balanceStore.getAmount());
|
|
108
|
+
return srcPaymentBalance;
|
|
83
109
|
},
|
|
84
110
|
withdraw(amount) {
|
|
85
111
|
const { state } = this;
|
|
112
|
+
const { purse } = this.facets;
|
|
113
|
+
|
|
114
|
+
const optRecoverySet = maybeRecoverySet(state);
|
|
115
|
+
const balanceStore = makeAmountStore(state, 'currentBalance');
|
|
86
116
|
// Note COMMIT POINT within withdraw.
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
newPurseBalance =>
|
|
90
|
-
updatePurseBalance(state, newPurseBalance, this.facets.purse),
|
|
117
|
+
const payment = withdrawInternal(
|
|
118
|
+
balanceStore,
|
|
91
119
|
amount,
|
|
92
|
-
|
|
120
|
+
optRecoverySet,
|
|
93
121
|
);
|
|
122
|
+
updateBalance(purse, balanceStore.getAmount());
|
|
123
|
+
return payment;
|
|
94
124
|
},
|
|
95
125
|
getCurrentAmount() {
|
|
96
|
-
|
|
126
|
+
const { state } = this;
|
|
127
|
+
const balanceStore = makeAmountStore(state, 'currentBalance');
|
|
128
|
+
return balanceStore.getAmount();
|
|
97
129
|
},
|
|
98
130
|
getCurrentAmountNotifier() {
|
|
99
131
|
return provideNotifier(this.facets.purse);
|
|
@@ -107,18 +139,27 @@ export const preparePurseKind = (
|
|
|
107
139
|
},
|
|
108
140
|
|
|
109
141
|
getRecoverySet() {
|
|
110
|
-
|
|
142
|
+
const { state } = this;
|
|
143
|
+
const optRecoverySet = maybeRecoverySet(state);
|
|
144
|
+
if (optRecoverySet === undefined) {
|
|
145
|
+
return EMPTY_COPY_SET;
|
|
146
|
+
}
|
|
147
|
+
return optRecoverySet.snapshot();
|
|
111
148
|
},
|
|
112
149
|
recoverAll() {
|
|
113
150
|
const { state, facets } = this;
|
|
114
151
|
let amount = AmountMath.makeEmpty(brand, assetKind);
|
|
115
|
-
|
|
152
|
+
const optRecoverySet = maybeRecoverySet(state);
|
|
153
|
+
if (optRecoverySet === undefined) {
|
|
154
|
+
return amount; // empty at this time
|
|
155
|
+
}
|
|
156
|
+
for (const payment of optRecoverySet.keys()) {
|
|
116
157
|
// This does cause deletions from the set while iterating,
|
|
117
158
|
// but this special case is allowed.
|
|
118
159
|
const delta = facets.purse.deposit(payment);
|
|
119
160
|
amount = AmountMath.add(amount, delta, brand);
|
|
120
161
|
}
|
|
121
|
-
|
|
162
|
+
optRecoverySet.getSize() === 0 ||
|
|
122
163
|
Fail`internal: Remaining unrecovered payments: ${facets.purse.getRecoverySet()}`;
|
|
123
164
|
return amount;
|
|
124
165
|
},
|
package/src/types-ambient.js
CHANGED
|
@@ -2,11 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
/// <reference types="ses"/>
|
|
4
4
|
|
|
5
|
-
/**
|
|
6
|
-
* @template {Key} [K=Key]
|
|
7
|
-
* @typedef {import('@endo/patterns').CopyBag<K>} CopyBag
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
5
|
/**
|
|
11
6
|
* @template {AssetKind} [K=AssetKind]
|
|
12
7
|
* @typedef {object} Amount Amounts are descriptions of digital assets,
|
|
@@ -22,8 +17,8 @@
|
|
|
22
17
|
*/
|
|
23
18
|
|
|
24
19
|
/**
|
|
25
|
-
* @typedef {NatValue | SetValue | CopySet | CopyBag} AmountValue
|
|
26
|
-
* `AmountValue` describes a set or quantity of assets that can be owned or
|
|
20
|
+
* @typedef {NatValue | SetValue | CopySet | import('@endo/patterns').CopyBag} AmountValue
|
|
21
|
+
* An `AmountValue` describes a set or quantity of assets that can be owned or
|
|
27
22
|
* shared.
|
|
28
23
|
*
|
|
29
24
|
* A fungible `AmountValue` uses a non-negative bigint to represent a quantity
|
|
@@ -58,7 +53,7 @@
|
|
|
58
53
|
* : K extends 'copySet'
|
|
59
54
|
* ? CopySet
|
|
60
55
|
* : K extends 'copyBag'
|
|
61
|
-
* ? CopyBag
|
|
56
|
+
* ? import('@endo/patterns').CopyBag
|
|
62
57
|
* : never} AssetValueForKind
|
|
63
58
|
*/
|
|
64
59
|
|
|
@@ -70,7 +65,7 @@
|
|
|
70
65
|
* ? 'set'
|
|
71
66
|
* : V extends CopySet
|
|
72
67
|
* ? 'copySet'
|
|
73
|
-
* : V extends CopyBag
|
|
68
|
+
* : V extends import('@endo/patterns').CopyBag
|
|
74
69
|
* ? 'copyBag'
|
|
75
70
|
* : never} AssetKindForValue
|
|
76
71
|
*/
|
|
@@ -178,8 +173,9 @@
|
|
|
178
173
|
* @template {AssetKind} [K=AssetKind]
|
|
179
174
|
* @typedef {object} PaymentLedger
|
|
180
175
|
* @property {Mint<K>} mint
|
|
181
|
-
* @property {Purse<K>} mintRecoveryPurse
|
|
182
|
-
*
|
|
176
|
+
* @property {Purse<K>} mintRecoveryPurse Externally useful only if this issuer
|
|
177
|
+
* uses recovery sets. Can be used to get the recovery set associated with
|
|
178
|
+
* minted payments that are still live.
|
|
183
179
|
* @property {Issuer<K>} issuer
|
|
184
180
|
* @property {Brand<K>} brand
|
|
185
181
|
*/
|
|
@@ -188,8 +184,9 @@
|
|
|
188
184
|
* @template {AssetKind} [K=AssetKind]
|
|
189
185
|
* @typedef {object} IssuerKit
|
|
190
186
|
* @property {Mint<K>} mint
|
|
191
|
-
* @property {Purse<K>} mintRecoveryPurse
|
|
192
|
-
*
|
|
187
|
+
* @property {Purse<K>} mintRecoveryPurse Externally useful only if this issuer
|
|
188
|
+
* uses recovery sets. Can be used to get the recovery set associated with
|
|
189
|
+
* minted payments that are still live.
|
|
193
190
|
* @property {Issuer<K>} issuer
|
|
194
191
|
* @property {Brand<K>} brand
|
|
195
192
|
* @property {DisplayInfo} displayInfo
|
|
@@ -222,6 +219,24 @@
|
|
|
222
219
|
|
|
223
220
|
// /////////////////////////// Purse / Payment /////////////////////////////////
|
|
224
221
|
|
|
222
|
+
/**
|
|
223
|
+
* Issuers first became durable with mandatory recovery sets. Later they were
|
|
224
|
+
* made optional, but there is no support for converting from one state to the
|
|
225
|
+
* other. Thus, absence of a `RecoverySetsOption` state is equivalent to
|
|
226
|
+
* `'hasRecoverySets'`. In the absence of a `recoverySetsOption` parameter,
|
|
227
|
+
* upgradeIssuerKit defaults to the predecessor's `RecoverySetsOption` state, or
|
|
228
|
+
* `'hasRecoverySets'` if none.
|
|
229
|
+
*
|
|
230
|
+
* At this time, issuers started in one of the states (`'noRecoverySets'`, or
|
|
231
|
+
* `'hasRecoverySets'`) cannot be converted to the other on upgrade. If this
|
|
232
|
+
* transition is needed, it can likely be supported in a future upgrade. File an
|
|
233
|
+
* issue on github and explain what you need and why.
|
|
234
|
+
*
|
|
235
|
+
* @typedef {'hasRecoverySets' | 'noRecoverySets'} RecoverySetsOption
|
|
236
|
+
*/
|
|
237
|
+
|
|
238
|
+
// /////////////////////////// Purse / Payment /////////////////////////////////
|
|
239
|
+
|
|
225
240
|
/**
|
|
226
241
|
* @callback DepositFacetReceive
|
|
227
242
|
* @param {Payment} payment
|
|
@@ -281,10 +296,14 @@
|
|
|
281
296
|
* can spend the assets at stake on other things. Afterwards, if the recipient
|
|
282
297
|
* of the original check finally gets around to depositing it, their deposit
|
|
283
298
|
* fails.
|
|
299
|
+
*
|
|
300
|
+
* Returns an empty set if this issuer does not support recovery sets.
|
|
284
301
|
* @property {() => Amount<K>} recoverAll For use in emergencies, such as coming
|
|
285
302
|
* back from a traumatic crash and upgrade. This deposits all the payments in
|
|
286
303
|
* this purse's recovery set into the purse itself, returning the total amount
|
|
287
304
|
* of assets recovered.
|
|
305
|
+
*
|
|
306
|
+
* Returns an empty amount if this issuer does not support recovery sets.
|
|
288
307
|
*/
|
|
289
308
|
|
|
290
309
|
/**
|
package/src/types.js
CHANGED
|
@@ -3,11 +3,6 @@ export {};
|
|
|
3
3
|
|
|
4
4
|
/// <reference types="ses"/>
|
|
5
5
|
|
|
6
|
-
/**
|
|
7
|
-
* @template {Key} [K=Key]
|
|
8
|
-
* @typedef {import('@endo/patterns').CopyBag<K>} CopyBag
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
6
|
/**
|
|
12
7
|
* @template {AssetKind} [K=AssetKind]
|
|
13
8
|
* @typedef {object} Amount Amounts are descriptions of digital assets,
|
|
@@ -23,8 +18,8 @@ export {};
|
|
|
23
18
|
*/
|
|
24
19
|
|
|
25
20
|
/**
|
|
26
|
-
* @typedef {NatValue | SetValue | CopySet | CopyBag} AmountValue
|
|
27
|
-
* `AmountValue` describes a set or quantity of assets that can be owned or
|
|
21
|
+
* @typedef {NatValue | SetValue | CopySet | import('@endo/patterns').CopyBag} AmountValue
|
|
22
|
+
* An `AmountValue` describes a set or quantity of assets that can be owned or
|
|
28
23
|
* shared.
|
|
29
24
|
*
|
|
30
25
|
* A fungible `AmountValue` uses a non-negative bigint to represent a quantity
|
|
@@ -59,7 +54,7 @@ export {};
|
|
|
59
54
|
* : K extends 'copySet'
|
|
60
55
|
* ? CopySet
|
|
61
56
|
* : K extends 'copyBag'
|
|
62
|
-
* ? CopyBag
|
|
57
|
+
* ? import('@endo/patterns').CopyBag
|
|
63
58
|
* : never} AssetValueForKind
|
|
64
59
|
*/
|
|
65
60
|
|
|
@@ -71,7 +66,7 @@ export {};
|
|
|
71
66
|
* ? 'set'
|
|
72
67
|
* : V extends CopySet
|
|
73
68
|
* ? 'copySet'
|
|
74
|
-
* : V extends CopyBag
|
|
69
|
+
* : V extends import('@endo/patterns').CopyBag
|
|
75
70
|
* ? 'copyBag'
|
|
76
71
|
* : never} AssetKindForValue
|
|
77
72
|
*/
|
|
@@ -179,8 +174,9 @@ export {};
|
|
|
179
174
|
* @template {AssetKind} [K=AssetKind]
|
|
180
175
|
* @typedef {object} PaymentLedger
|
|
181
176
|
* @property {Mint<K>} mint
|
|
182
|
-
* @property {Purse<K>} mintRecoveryPurse
|
|
183
|
-
*
|
|
177
|
+
* @property {Purse<K>} mintRecoveryPurse Externally useful only if this issuer
|
|
178
|
+
* uses recovery sets. Can be used to get the recovery set associated with
|
|
179
|
+
* minted payments that are still live.
|
|
184
180
|
* @property {Issuer<K>} issuer
|
|
185
181
|
* @property {Brand<K>} brand
|
|
186
182
|
*/
|
|
@@ -189,8 +185,9 @@ export {};
|
|
|
189
185
|
* @template {AssetKind} [K=AssetKind]
|
|
190
186
|
* @typedef {object} IssuerKit
|
|
191
187
|
* @property {Mint<K>} mint
|
|
192
|
-
* @property {Purse<K>} mintRecoveryPurse
|
|
193
|
-
*
|
|
188
|
+
* @property {Purse<K>} mintRecoveryPurse Externally useful only if this issuer
|
|
189
|
+
* uses recovery sets. Can be used to get the recovery set associated with
|
|
190
|
+
* minted payments that are still live.
|
|
194
191
|
* @property {Issuer<K>} issuer
|
|
195
192
|
* @property {Brand<K>} brand
|
|
196
193
|
* @property {DisplayInfo} displayInfo
|
|
@@ -223,6 +220,24 @@ export {};
|
|
|
223
220
|
|
|
224
221
|
// /////////////////////////// Purse / Payment /////////////////////////////////
|
|
225
222
|
|
|
223
|
+
/**
|
|
224
|
+
* Issuers first became durable with mandatory recovery sets. Later they were
|
|
225
|
+
* made optional, but there is no support for converting from one state to the
|
|
226
|
+
* other. Thus, absence of a `RecoverySetsOption` state is equivalent to
|
|
227
|
+
* `'hasRecoverySets'`. In the absence of a `recoverySetsOption` parameter,
|
|
228
|
+
* upgradeIssuerKit defaults to the predecessor's `RecoverySetsOption` state, or
|
|
229
|
+
* `'hasRecoverySets'` if none.
|
|
230
|
+
*
|
|
231
|
+
* At this time, issuers started in one of the states (`'noRecoverySets'`, or
|
|
232
|
+
* `'hasRecoverySets'`) cannot be converted to the other on upgrade. If this
|
|
233
|
+
* transition is needed, it can likely be supported in a future upgrade. File an
|
|
234
|
+
* issue on github and explain what you need and why.
|
|
235
|
+
*
|
|
236
|
+
* @typedef {'hasRecoverySets' | 'noRecoverySets'} RecoverySetsOption
|
|
237
|
+
*/
|
|
238
|
+
|
|
239
|
+
// /////////////////////////// Purse / Payment /////////////////////////////////
|
|
240
|
+
|
|
226
241
|
/**
|
|
227
242
|
* @callback DepositFacetReceive
|
|
228
243
|
* @param {Payment} payment
|
|
@@ -282,10 +297,14 @@ export {};
|
|
|
282
297
|
* can spend the assets at stake on other things. Afterwards, if the recipient
|
|
283
298
|
* of the original check finally gets around to depositing it, their deposit
|
|
284
299
|
* fails.
|
|
300
|
+
*
|
|
301
|
+
* Returns an empty set if this issuer does not support recovery sets.
|
|
285
302
|
* @property {() => Amount<K>} recoverAll For use in emergencies, such as coming
|
|
286
303
|
* back from a traumatic crash and upgrade. This deposits all the payments in
|
|
287
304
|
* this purse's recovery set into the purse itself, returning the total amount
|
|
288
305
|
* of assets recovered.
|
|
306
|
+
*
|
|
307
|
+
* Returns an empty amount if this issuer does not support recovery sets.
|
|
289
308
|
*/
|
|
290
309
|
|
|
291
310
|
/**
|