@agoric/inter-protocol 0.13.4-pismo-dev-0d5327f.0 → 0.14.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 (141) hide show
  1. package/CHANGELOG.md +287 -0
  2. package/README.md +26 -20
  3. package/bundles/bundle-auctioneer-js-meta.json +722 -0
  4. package/bundles/bundle-auctioneer.js +1 -0
  5. package/bundles/bundle-econCommitteeCharter-js-meta.json +514 -0
  6. package/bundles/bundle-econCommitteeCharter.js +1 -0
  7. package/bundles/bundle-feeDistributor-js-meta.json +458 -0
  8. package/bundles/bundle-feeDistributor.js +1 -1
  9. package/bundles/bundle-fluxAggregatorKit-js-meta.json +674 -0
  10. package/bundles/bundle-fluxAggregatorKit.js +1 -0
  11. package/bundles/bundle-psm-js-meta.json +666 -0
  12. package/bundles/bundle-psm.js +1 -1
  13. package/bundles/bundle-reserve-js-meta.json +662 -0
  14. package/bundles/bundle-reserve.js +1 -1
  15. package/bundles/bundle-scaledPriceAuthority-js-meta.json +542 -0
  16. package/bundles/bundle-scaledPriceAuthority.js +1 -1
  17. package/bundles/bundle-vaultFactory-js-meta.json +786 -0
  18. package/bundles/bundle-vaultFactory.js +1 -1
  19. package/exported.js +0 -2
  20. package/package.json +34 -31
  21. package/scripts/add-collateral-core.js +14 -4
  22. package/scripts/build-bundles.js +9 -2
  23. package/scripts/deploy-contracts.js +1 -4
  24. package/scripts/init-core.js +20 -38
  25. package/scripts/invite-committee-core.js +1 -1
  26. package/scripts/manual-price-feed.js +2 -2
  27. package/scripts/price-feed-core.js +7 -6
  28. package/scripts/start-local-chain.sh +84 -0
  29. package/src/auction/auctionBook.js +755 -0
  30. package/src/auction/auctioneer.js +720 -0
  31. package/src/auction/offerBook.js +221 -0
  32. package/src/auction/params.js +174 -0
  33. package/src/auction/scheduleMath.js +167 -0
  34. package/src/auction/scheduler.js +370 -0
  35. package/src/auction/sortedOffers.js +136 -0
  36. package/src/auction/util.js +55 -0
  37. package/src/clientSupport.js +324 -0
  38. package/src/collectFees.js +8 -14
  39. package/src/contractSupport.js +24 -68
  40. package/src/econCommitteeCharter.js +161 -77
  41. package/src/feeDistributor.js +60 -20
  42. package/src/index.js +2 -0
  43. package/src/interest-math.js +1 -4
  44. package/src/interest.js +20 -13
  45. package/src/price/README.md +57 -0
  46. package/src/price/fluxAggregatorContract.js +190 -0
  47. package/src/price/fluxAggregatorKit.js +375 -0
  48. package/src/price/priceOracleKit.js +127 -0
  49. package/src/price/roundsManager.js +726 -0
  50. package/src/proposals/addAssetToVault.js +89 -94
  51. package/src/proposals/committee-proposal.js +141 -40
  52. package/src/proposals/core-proposal.js +100 -167
  53. package/src/proposals/econ-behaviors.js +320 -564
  54. package/src/proposals/price-feed-proposal.js +175 -78
  55. package/src/proposals/startEconCommittee.js +25 -12
  56. package/src/proposals/startPSM.js +231 -211
  57. package/src/proposals/utils.js +31 -17
  58. package/src/psm/README.md +71 -0
  59. package/src/psm/psm.js +272 -160
  60. package/src/psm/types.js +2 -0
  61. package/src/reserve/assetReserve.js +56 -413
  62. package/src/reserve/assetReserveKit.js +303 -0
  63. package/src/reserve/doc.md +1 -3
  64. package/src/reserve/params.js +2 -5
  65. package/src/typeGuards.js +13 -0
  66. package/src/vaultFactory/Liquidation.md +100 -0
  67. package/src/vaultFactory/burn.js +2 -1
  68. package/src/vaultFactory/liquidation.js +270 -108
  69. package/src/vaultFactory/math.js +95 -0
  70. package/src/vaultFactory/orderedVaultStore.js +0 -1
  71. package/src/vaultFactory/params.js +133 -112
  72. package/src/vaultFactory/prioritizedVaults.js +36 -79
  73. package/src/vaultFactory/storeUtils.js +67 -9
  74. package/src/vaultFactory/type-imports.js +2 -0
  75. package/src/vaultFactory/types.js +22 -26
  76. package/src/vaultFactory/vault.js +772 -709
  77. package/src/vaultFactory/vaultDirector.js +480 -483
  78. package/src/vaultFactory/vaultFactory.js +99 -60
  79. package/src/vaultFactory/vaultHolder.js +121 -95
  80. package/src/vaultFactory/vaultKit.js +39 -31
  81. package/src/vaultFactory/vaultManager.js +1249 -868
  82. package/bundles/bundle-amm-meta.js +0 -618
  83. package/bundles/bundle-amm.js +0 -1
  84. package/bundles/bundle-feeDistributor-meta.js +0 -346
  85. package/bundles/bundle-interchainPool-meta.js +0 -534
  86. package/bundles/bundle-interchainPool.js +0 -1
  87. package/bundles/bundle-liquidateIncrementally-meta.js +0 -442
  88. package/bundles/bundle-liquidateIncrementally.js +0 -1
  89. package/bundles/bundle-liquidateMinimum-meta.js +0 -442
  90. package/bundles/bundle-liquidateMinimum.js +0 -1
  91. package/bundles/bundle-psm-meta.js +0 -538
  92. package/bundles/bundle-psmCharter-meta.js +0 -418
  93. package/bundles/bundle-psmCharter.js +0 -1
  94. package/bundles/bundle-reserve-meta.js +0 -542
  95. package/bundles/bundle-scaledPriceAuthority-meta.js +0 -442
  96. package/bundles/bundle-stakeFactory-meta.js +0 -574
  97. package/bundles/bundle-stakeFactory.js +0 -1
  98. package/bundles/bundle-vaultFactory-meta.js +0 -598
  99. package/scripts/add-initial-liquidity.js +0 -180
  100. package/src/collect.js +0 -13
  101. package/src/interchainPool.js +0 -135
  102. package/src/makeTracer.js +0 -36
  103. package/src/my-lien.js +0 -85
  104. package/src/proposals/demoIssuers.js +0 -685
  105. package/src/proposals/sim-behaviors.js +0 -40
  106. package/src/psm/psmCharter.js +0 -139
  107. package/src/stakeFactory/README.md +0 -62
  108. package/src/stakeFactory/attestation.js +0 -267
  109. package/src/stakeFactory/attestationTool.js +0 -66
  110. package/src/stakeFactory/constants.js +0 -16
  111. package/src/stakeFactory/params.js +0 -31
  112. package/src/stakeFactory/stakeFactory.js +0 -236
  113. package/src/stakeFactory/stakeFactoryKit.js +0 -455
  114. package/src/stakeFactory/stakeFactoryManager.js +0 -296
  115. package/src/stakeFactory/types.js +0 -42
  116. package/src/vaultFactory/liquidateIncrementally.js +0 -350
  117. package/src/vaultFactory/liquidateMinimum.js +0 -100
  118. package/src/vpool-xyk-amm/AttackersGuide.md +0 -89
  119. package/src/vpool-xyk-amm/addLiquidity.js +0 -222
  120. package/src/vpool-xyk-amm/addPool.js +0 -197
  121. package/src/vpool-xyk-amm/constantProduct/AMM-Trade.jpeg +0 -0
  122. package/src/vpool-xyk-amm/constantProduct/README.md +0 -204
  123. package/src/vpool-xyk-amm/constantProduct/calcFees.js +0 -99
  124. package/src/vpool-xyk-amm/constantProduct/calcSwapPrices.js +0 -85
  125. package/src/vpool-xyk-amm/constantProduct/core.js +0 -153
  126. package/src/vpool-xyk-amm/constantProduct/defaults.js +0 -5
  127. package/src/vpool-xyk-amm/constantProduct/getXY.js +0 -52
  128. package/src/vpool-xyk-amm/constantProduct/internal-types.js +0 -116
  129. package/src/vpool-xyk-amm/constantProduct/invariants.js +0 -43
  130. package/src/vpool-xyk-amm/constantProduct/swap.js +0 -272
  131. package/src/vpool-xyk-amm/constantProduct/types.js +0 -32
  132. package/src/vpool-xyk-amm/doublePool.js +0 -194
  133. package/src/vpool-xyk-amm/estimate.js +0 -155
  134. package/src/vpool-xyk-amm/multipoolMarketMaker.js +0 -520
  135. package/src/vpool-xyk-amm/params.js +0 -61
  136. package/src/vpool-xyk-amm/pool.js +0 -396
  137. package/src/vpool-xyk-amm/priceAuthority.js +0 -94
  138. package/src/vpool-xyk-amm/removeLiquidity.js +0 -31
  139. package/src/vpool-xyk-amm/singlePool.js +0 -73
  140. package/src/vpool-xyk-amm/swap.js +0 -69
  141. package/src/vpool-xyk-amm/types.js +0 -154
@@ -0,0 +1,324 @@
1
+ // @ts-check
2
+
3
+ import { Fail } from '@agoric/assert';
4
+ import { AmountMath } from '@agoric/ertp';
5
+ import { assertAllDefined } from '@agoric/internal';
6
+ import { parseRatio } from '@agoric/zoe/src/contractSupport/ratio.js';
7
+
8
+ // XXX support other decimal places
9
+ const COSMOS_UNIT = 1_000_000n;
10
+ const scaleDecimals = num => BigInt(num * Number(COSMOS_UNIT));
11
+
12
+ // NB: not really a Proposal because the brands are not remotes
13
+ // Instead they're copyRecord like "{"boardId":"board0257","iface":"Alleged: IST brand"}" to pass through the boardId
14
+ // mustMatch(harden(proposal), ProposalShape);
15
+ /**
16
+ * Give/want
17
+ *
18
+ * @param {Record<string, Brand>} brands
19
+ * @param {{ giveMinted?: number, wantMinted?: number } | { collateralBrandKey: string, giveCollateral?: number, wantCollateral?: number }} opts
20
+ * @returns {Proposal}
21
+ */
22
+ const makeVaultProposal = (brands, opts) => {
23
+ const proposal = { give: {}, want: {} };
24
+
25
+ if ('giveCollateral' in opts && opts.giveCollateral) {
26
+ const { collateralBrandKey } = opts;
27
+ proposal.give.Collateral = {
28
+ brand: brands[collateralBrandKey],
29
+ value: scaleDecimals(opts.giveCollateral),
30
+ };
31
+ }
32
+ if ('giveMinted' in opts && opts.giveMinted) {
33
+ proposal.give.Minted = {
34
+ brand: brands.IST,
35
+ value: scaleDecimals(opts.giveMinted),
36
+ };
37
+ }
38
+
39
+ if ('wantCollateral' in opts && opts.wantCollateral) {
40
+ const { collateralBrandKey } = opts;
41
+ proposal.want.Collateral = {
42
+ brand: brands[collateralBrandKey],
43
+ value: scaleDecimals(opts.wantCollateral),
44
+ };
45
+ }
46
+ if ('wantMinted' in opts && opts.wantMinted) {
47
+ proposal.want.Minted = {
48
+ brand: brands.IST,
49
+ value: scaleDecimals(opts.wantMinted),
50
+ };
51
+ }
52
+
53
+ return harden(proposal);
54
+ };
55
+
56
+ /**
57
+ * @param {Record<string, Brand>} brands
58
+ * @param {{ offerId: string, wantMinted: number, giveCollateral: number, collateralBrandKey: string }} opts
59
+ * @returns {import('@agoric/smart-wallet/src/offers.js').OfferSpec}
60
+ */
61
+ const makeOpenOffer = (brands, opts) => {
62
+ const proposal = makeVaultProposal(brands, opts);
63
+
64
+ // NB: not really a Proposal because the brands are not remotes
65
+ // Instead they're copyRecord like "{"boardId":"board0257","iface":"Alleged: IST brand"}" to pass through the boardId
66
+ // mustMatch(harden(proposal), ProposalShape);
67
+
68
+ const collateralBrand = brands[opts.collateralBrandKey];
69
+
70
+ return {
71
+ id: opts.offerId,
72
+ invitationSpec: {
73
+ source: 'agoricContract',
74
+ instancePath: ['VaultFactory'],
75
+ callPipe: [
76
+ ['getCollateralManager', [collateralBrand]],
77
+ ['makeVaultInvitation'],
78
+ ],
79
+ },
80
+ proposal,
81
+ };
82
+ };
83
+
84
+ /**
85
+ * @param {Record<string, Brand>} brands
86
+ * @param {{ offerId: string, collateralBrandKey?: string, giveCollateral?: number, wantCollateral?: number, giveMinted?: number, wantMinted?: number }} opts
87
+ * @param {string} previousOffer
88
+ * @returns {import('@agoric/smart-wallet/src/offers.js').OfferSpec}
89
+ */
90
+ const makeAdjustOffer = (brands, opts, previousOffer) => {
91
+ // NB: not really a Proposal because the brands are not remotes
92
+ // Instead they're copyRecord like "{"boardId":"board0257","iface":"Alleged: IST brand"}" to pass through the boardId
93
+ // mustMatch(harden(proposal), ProposalShape);
94
+ const proposal = makeVaultProposal(brands, opts);
95
+
96
+ return {
97
+ id: opts.offerId,
98
+ invitationSpec: {
99
+ source: 'continuing',
100
+ previousOffer,
101
+ invitationMakerName: 'AdjustBalances',
102
+ },
103
+ proposal,
104
+ };
105
+ };
106
+
107
+ /**
108
+ * @param {Record<string, Brand>} brands
109
+ * @param {{ offerId: string, collateralBrandKey?: string, giveMinted: number }} opts
110
+ * @param {string} previousOffer
111
+ * @returns {import('@agoric/smart-wallet/src/offers.js').OfferSpec}
112
+ */
113
+ const makeCloseOffer = (brands, opts, previousOffer) => {
114
+ const proposal = makeVaultProposal(brands, opts);
115
+
116
+ return {
117
+ id: opts.offerId,
118
+ invitationSpec: {
119
+ source: 'continuing',
120
+ previousOffer,
121
+ invitationMakerName: 'CloseVault',
122
+ },
123
+ proposal,
124
+ };
125
+ };
126
+
127
+ /**
128
+ * @param {string} vaultId
129
+ * @param {Promise<import('@agoric/smart-wallet/src/smartWallet').CurrentWalletRecord>} currentP
130
+ * @returns {Promise<string>} offer id in which the vault was made
131
+ */
132
+ export const lookupOfferIdForVault = async (vaultId, currentP) => {
133
+ const { offerToPublicSubscriberPaths } = await currentP;
134
+
135
+ for (const [offerId, publicSubscribers] of offerToPublicSubscriberPaths) {
136
+ if (publicSubscribers.vault?.endsWith(vaultId)) {
137
+ return offerId;
138
+ }
139
+ }
140
+ throw Fail`vault ${vaultId} not found`;
141
+ };
142
+
143
+ /**
144
+ * @param {Record<string, Brand>} brands
145
+ * @param {({ wantMinted: number | undefined, giveMinted: number | undefined })} opts
146
+ * @param {number} [fee=0]
147
+ * @param {string} [anchor]
148
+ * @returns {Proposal} XXX not a real proposal, uses BoardRemote
149
+ */
150
+ const makePsmProposal = (brands, opts, fee = 0, anchor = 'AUSD') => {
151
+ const giving = opts.giveMinted ? 'minted' : 'anchor';
152
+ const brand =
153
+ giving === 'anchor'
154
+ ? { in: brands[anchor], out: brands.IST }
155
+ : { in: brands.IST, out: brands[anchor] };
156
+ const value =
157
+ Number(giving === 'anchor' ? opts.wantMinted : opts.giveMinted) *
158
+ Number(COSMOS_UNIT);
159
+ const adjusted = {
160
+ in: BigInt(Math.ceil(giving === 'anchor' ? value / (1 - fee) : value)),
161
+ out: BigInt(Math.ceil(giving === 'minted' ? value * (1 - fee) : value)),
162
+ };
163
+ return {
164
+ give: {
165
+ In: { brand: brand.in, value: adjusted.in },
166
+ },
167
+ want: {
168
+ Out: { brand: brand.out, value: adjusted.out },
169
+ },
170
+ };
171
+ };
172
+
173
+ /**
174
+ * @param {Instance} instance
175
+ * @param {Record<string, Brand>} brands
176
+ * @param {{ offerId: number, feePct?: number } &
177
+ * ({ wantMinted: number | undefined, giveMinted: number | undefined, pair: [string, string] })} opts
178
+ * @returns {import('@agoric/smart-wallet/src/offers.js').OfferSpec}
179
+ */
180
+ const makePsmSwapOffer = (instance, brands, opts) => {
181
+ const method = opts.wantMinted
182
+ ? 'makeWantMintedInvitation'
183
+ : 'makeGiveMintedInvitation'; // ref psm.js
184
+ const proposal = makePsmProposal(
185
+ brands,
186
+ opts,
187
+ opts.feePct ? opts.feePct / 100 : undefined,
188
+ opts.pair[1],
189
+ );
190
+
191
+ // NB: not really a Proposal because the brands are not remotes
192
+ // Instead they're copyRecord like "{"boardId":"board0257","iface":"Alleged: IST brand"}" to pass through the boardId
193
+ // mustMatch(harden(proposal), ProposalShape);
194
+
195
+ return {
196
+ id: opts.offerId,
197
+ invitationSpec: {
198
+ source: 'contract',
199
+ instance,
200
+ publicInvitationMaker: method,
201
+ },
202
+ proposal,
203
+ };
204
+ };
205
+
206
+ /**
207
+ * @param {Record<string, Brand>} _brands
208
+ * @param {{
209
+ * offerId: string,
210
+ * give: string,
211
+ * maxBuy: string,
212
+ * wantMinimum?: string,
213
+ * parseAmount: (x: string) => Amount<'nat'>,
214
+ * } & ({
215
+ * price: number,
216
+ * } | {
217
+ * discount: number, // -1 to 1. e.g. 0.10 for 10% discount, -0.05 for 5% markup
218
+ * })} opts
219
+ * @returns {import('@agoric/smart-wallet/src/offers.js').OfferSpec}
220
+ */
221
+ const makeBidOffer = (_brands, opts) => {
222
+ assert.typeof(opts.parseAmount, 'function');
223
+ assertAllDefined({
224
+ offerId: opts.offerId,
225
+ give: opts.give,
226
+ maxBuy: opts.maxBuy,
227
+ });
228
+ const { parseAmount } = opts;
229
+ const proposal = {
230
+ give: { Bid: parseAmount(opts.give) },
231
+ ...(opts.wantMinimum
232
+ ? { want: { Collateral: parseAmount(opts.wantMinimum) } }
233
+ : {}),
234
+ };
235
+ const istBrand = proposal.give.Bid.brand;
236
+ const maxBuy = parseAmount(opts.maxBuy);
237
+
238
+ const bounds = (x, lo, hi) => {
239
+ assert(x >= lo && x <= hi);
240
+ return x;
241
+ };
242
+
243
+ assert(
244
+ 'price' in opts || 'discount' in opts,
245
+ 'must specify price or discount',
246
+ );
247
+ /** @type {import('./auction/auctionBook.js').OfferSpec} */
248
+ const offerArgs =
249
+ 'price' in opts
250
+ ? {
251
+ maxBuy: parseAmount(opts.maxBuy),
252
+ offerPrice: parseRatio(opts.price, istBrand, maxBuy.brand),
253
+ }
254
+ : {
255
+ maxBuy,
256
+ offerBidScaling: parseRatio(
257
+ (1 - bounds(opts.discount, -1, 1)).toFixed(2),
258
+ istBrand,
259
+ istBrand,
260
+ ),
261
+ };
262
+
263
+ /** @type {import('@agoric/smart-wallet/src/offers.js').OfferSpec} */
264
+ const offerSpec = {
265
+ id: opts.offerId,
266
+ invitationSpec: {
267
+ source: 'agoricContract',
268
+ instancePath: ['auctioneer'],
269
+ callPipe: [['makeBidInvitation', [maxBuy.brand]]],
270
+ },
271
+ proposal,
272
+ offerArgs,
273
+ };
274
+ return offerSpec;
275
+ };
276
+
277
+ /**
278
+ * @param {Record<string, Brand>} brands
279
+ * @param {{
280
+ * offerId: string,
281
+ * give: number,
282
+ * collateralBrandKey: string,
283
+ * }} opts
284
+ * @returns {import('@agoric/smart-wallet/src/offers.js').OfferSpec}
285
+ */
286
+ const makeAddCollateralOffer = (brands, opts) => {
287
+ /** @type {AmountKeywordRecord} */
288
+ const give = {
289
+ Collateral: AmountMath.make(
290
+ brands[opts.collateralBrandKey],
291
+ scaleDecimals(opts.give),
292
+ ),
293
+ };
294
+
295
+ /** @type {import('@agoric/smart-wallet/src/offers.js').OfferSpec} */
296
+ const offerSpec = {
297
+ id: opts.offerId,
298
+ invitationSpec: {
299
+ source: 'agoricContract',
300
+ instancePath: ['reserve'],
301
+ callPipe: [['makeAddCollateralInvitation', []]],
302
+ },
303
+ proposal: { give },
304
+ };
305
+ return offerSpec;
306
+ };
307
+
308
+ export const Offers = {
309
+ auction: {
310
+ Bid: makeBidOffer,
311
+ },
312
+ psm: {
313
+ // lowercase because it's not an invitation name. Instead it's an abstraction over two invitation makers.
314
+ swap: makePsmSwapOffer,
315
+ },
316
+ vaults: {
317
+ OpenVault: makeOpenOffer,
318
+ AdjustBalances: makeAdjustOffer,
319
+ CloseVault: makeCloseOffer,
320
+ },
321
+ reserve: {
322
+ AddCollateral: makeAddCollateralOffer,
323
+ },
324
+ };
@@ -1,4 +1,7 @@
1
- // @ts-check
1
+ // @jessie-check
2
+
3
+ import { atomicTransfer } from '@agoric/zoe/src/contractSupport/index.js';
4
+
2
5
  /**
3
6
  * Provide shared support for providing access to fees from a service contract.
4
7
  *
@@ -6,25 +9,16 @@
6
9
  * @param {ZCFSeat} feeSeat
7
10
  * @param {Brand} feeBrand
8
11
  * @param {string} keyword
12
+ * @returns {Promise<Invitation<string>>}
9
13
  */
10
- export const makeMakeCollectFeesInvitation = (
11
- zcf,
12
- feeSeat,
13
- feeBrand,
14
- keyword,
15
- ) => {
14
+ export const makeCollectFeesInvitation = (zcf, feeSeat, feeBrand, keyword) => {
16
15
  const collectFees = seat => {
17
16
  const amount = feeSeat.getAmountAllocated(keyword, feeBrand);
18
- feeSeat.decrementBy(harden({ [keyword]: amount }));
19
- seat.incrementBy(harden({ Fee: amount }));
20
- zcf.reallocate(seat, feeSeat);
17
+ atomicTransfer(zcf, feeSeat, seat, { [keyword]: amount }, { Fee: amount });
21
18
 
22
19
  seat.exit();
23
20
  return `paid out ${amount.value}`;
24
21
  };
25
22
 
26
- const makeCollectFeesInvitation = () =>
27
- zcf.makeInvitation(collectFees, 'collect fees');
28
-
29
- return { makeCollectFeesInvitation };
23
+ return zcf.makeInvitation(collectFees, 'collect fees');
30
24
  };
@@ -1,10 +1,11 @@
1
- // @ts-check
1
+ // @jessie-check
2
+
2
3
  import { AmountMath } from '@agoric/ertp';
3
4
  import { makeStoredPublisherKit, makeStoredPublishKit } from '@agoric/notifier';
4
5
  import { M } from '@agoric/store';
5
6
  import { E } from '@endo/eventual-send';
6
7
 
7
- const { details: X, quote: q } = assert;
8
+ const { Fail, quote: q } = assert;
8
9
 
9
10
  export const amountPattern = harden({ brand: M.remotable(), value: M.any() });
10
11
  export const ratioPattern = harden({
@@ -19,10 +20,11 @@ export const ratioPattern = harden({
19
20
  * on a proposal. We use two Amounts because an Amount cannot represent
20
21
  * a negative number (so we use a "loss" that will be subtracted).
21
22
  *
22
- * @param {Amount} base
23
- * @param {Amount} gain
24
- * @param {Amount} loss
25
- * @returns {Amount}
23
+ * @template {AssetKind} K
24
+ * @param {Amount<K>} base
25
+ * @param {Amount<K>} gain
26
+ * @param {Amount<K>} loss
27
+ * @returns {Amount<K>}
26
28
  */
27
29
  export const addSubtract = (base, gain, loss) =>
28
30
  AmountMath.subtract(AmountMath.add(base, gain), loss);
@@ -37,31 +39,16 @@ export const assertOnlyKeys = (proposal, keys) => {
37
39
  /** @param {AmountKeywordRecord} clause */
38
40
  const onlyKeys = clause =>
39
41
  Object.getOwnPropertyNames(clause).every(c => keys.includes(c));
40
- onlyKeys(proposal.give) ||
41
- assert.fail(X`extraneous terms in give: ${proposal.give}`);
42
- onlyKeys(proposal.want) ||
43
- assert.fail(X`extraneous terms in want: ${proposal.want}`);
42
+ onlyKeys(proposal.give) || Fail`extraneous terms in give: ${proposal.give}`;
43
+ onlyKeys(proposal.want) || Fail`extraneous terms in want: ${proposal.want}`;
44
44
  };
45
45
 
46
46
  /**
47
- * Stage a transfer between `fromSeat` and `toSeat`, specified as the delta between
48
- * the gain and a loss on the `fromSeat`. The gain/loss are typically from the
49
- * give/want respectively of a proposal. The `key` is the allocation keyword.
50
- *
51
- * @param {ZCFSeat} fromSeat
52
- * @param {ZCFSeat} toSeat
53
- * @param {Amount} fromLoses
54
- * @param {Amount} fromGains
55
- * @param {Keyword} key
47
+ * @param {Amount[]} amounts
48
+ * @returns {boolean}
56
49
  */
57
- export const stageDelta = (fromSeat, toSeat, fromLoses, fromGains, key) => {
58
- // Must check `isEmpty`; can't subtract `empty` from a missing allocation.
59
- if (!AmountMath.isEmpty(fromLoses)) {
60
- toSeat.incrementBy(fromSeat.decrementBy(harden({ [key]: fromLoses })));
61
- }
62
- if (!AmountMath.isEmpty(fromGains)) {
63
- fromSeat.incrementBy(toSeat.decrementBy(harden({ [key]: fromGains })));
64
- }
50
+ export const allEmpty = amounts => {
51
+ return amounts.every(a => AmountMath.isEmpty(a));
65
52
  };
66
53
 
67
54
  /**
@@ -72,16 +59,14 @@ export const stageDelta = (fromSeat, toSeat, fromLoses, fromGains, key) => {
72
59
  */
73
60
  export const checkDebtLimit = (debtLimit, totalDebt, toMint) => {
74
61
  const debtPost = AmountMath.add(totalDebt, toMint);
75
- assert(
76
- !AmountMath.isGTE(debtPost, debtLimit),
77
- X`Minting ${q(toMint)} past ${q(totalDebt)} would hit total debt limit ${q(
78
- debtLimit,
79
- )}`,
80
- );
62
+ AmountMath.isGTE(debtLimit, debtPost) ||
63
+ Fail`Minting ${q(toMint)} past ${q(
64
+ totalDebt,
65
+ )} would hit total debt limit ${q(debtLimit)}`;
81
66
  };
82
67
 
83
68
  /**
84
- * @deprecated use makeMetricsPublishKit
69
+ * @deprecated incompatible with durability; instead handle vstorage ephemerally on a durable PublishKit
85
70
  * @template T
86
71
  * @param {ERef<StorageNode>} storageNode
87
72
  * @param {ERef<Marshaller>} marshaller
@@ -116,6 +101,7 @@ harden(makeMetricsPublisherKit);
116
101
  */
117
102
 
118
103
  /**
104
+ * @deprecated incompatible with durability; instead handle vstorage ephemerally on a durable PublishKit
119
105
  * @template T
120
106
  * @param {ERef<StorageNode>} storageNode
121
107
  * @param {ERef<Marshaller>} marshaller
@@ -137,38 +123,8 @@ export const makeMetricsPublishKit = (storageNode, marshaller) => {
137
123
  harden(makeMetricsPublishKit);
138
124
 
139
125
  /**
140
- * @template K Key
141
- * @template {{}} E Ephemeral state
142
- * @param {() => E} init
126
+ * @param {Brand} brand must be a 'nat' brand, not checked
127
+ * @param {NatValue} [min]
143
128
  */
144
- export const makeEphemeraProvider = init => {
145
- /** @type {Map<K, E>} */
146
- const ephemeras = new Map();
147
-
148
- /**
149
- * Provide an object to hold state that need not (or cannot) be durable.
150
- *
151
- * @type {(key: K) => E}
152
- */
153
- return key => {
154
- if (ephemeras.has(key)) {
155
- // @ts-expect-error cast
156
- return ephemeras.get(key);
157
- }
158
- const newEph = init();
159
- ephemeras.set(key, newEph);
160
- return newEph;
161
- };
162
- };
163
- harden(makeEphemeraProvider);
164
-
165
- /**
166
- * @template {Record<string, unknown>} T
167
- * @param {T} specimen
168
- * @param {Array<keyof T>} keyList
169
- */
170
- export const assertKeysDefined = (specimen, keyList) => {
171
- for (const key of keyList) {
172
- assert(specimen[key], X`Missing ${q(key)}`);
173
- }
174
- };
129
+ export const makeNatAmountShape = (brand, min) =>
130
+ harden({ brand, value: min ? M.gte(min) : M.nat() });