@agoric/inter-protocol 0.13.3 → 0.13.4-dev-d32a66a.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 (140) hide show
  1. package/README.md +26 -20
  2. package/bundles/bundle-auctioneer-js-meta.json +722 -0
  3. package/bundles/bundle-auctioneer.js +1 -0
  4. package/bundles/bundle-econCommitteeCharter-js-meta.json +514 -0
  5. package/bundles/bundle-econCommitteeCharter.js +1 -0
  6. package/bundles/bundle-feeDistributor-js-meta.json +458 -0
  7. package/bundles/bundle-feeDistributor.js +1 -1
  8. package/bundles/bundle-fluxAggregatorKit-js-meta.json +674 -0
  9. package/bundles/bundle-fluxAggregatorKit.js +1 -0
  10. package/bundles/bundle-psm-js-meta.json +666 -0
  11. package/bundles/bundle-psm.js +1 -1
  12. package/bundles/bundle-reserve-js-meta.json +662 -0
  13. package/bundles/bundle-reserve.js +1 -1
  14. package/bundles/bundle-scaledPriceAuthority-js-meta.json +542 -0
  15. package/bundles/bundle-scaledPriceAuthority.js +1 -1
  16. package/bundles/bundle-vaultFactory-js-meta.json +786 -0
  17. package/bundles/bundle-vaultFactory.js +1 -1
  18. package/exported.js +0 -2
  19. package/package.json +34 -31
  20. package/scripts/add-collateral-core.js +14 -4
  21. package/scripts/build-bundles.js +9 -2
  22. package/scripts/deploy-contracts.js +1 -4
  23. package/scripts/init-core.js +20 -38
  24. package/scripts/invite-committee-core.js +1 -1
  25. package/scripts/manual-price-feed.js +2 -2
  26. package/scripts/price-feed-core.js +7 -6
  27. package/scripts/start-local-chain.sh +84 -0
  28. package/src/auction/auctionBook.js +755 -0
  29. package/src/auction/auctioneer.js +720 -0
  30. package/src/auction/offerBook.js +221 -0
  31. package/src/auction/params.js +174 -0
  32. package/src/auction/scheduleMath.js +167 -0
  33. package/src/auction/scheduler.js +370 -0
  34. package/src/auction/sortedOffers.js +136 -0
  35. package/src/auction/util.js +55 -0
  36. package/src/clientSupport.js +324 -0
  37. package/src/collectFees.js +8 -14
  38. package/src/contractSupport.js +24 -68
  39. package/src/econCommitteeCharter.js +161 -77
  40. package/src/feeDistributor.js +60 -20
  41. package/src/index.js +2 -0
  42. package/src/interest-math.js +1 -4
  43. package/src/interest.js +20 -13
  44. package/src/price/README.md +57 -0
  45. package/src/price/fluxAggregatorContract.js +190 -0
  46. package/src/price/fluxAggregatorKit.js +375 -0
  47. package/src/price/priceOracleKit.js +127 -0
  48. package/src/price/roundsManager.js +726 -0
  49. package/src/proposals/addAssetToVault.js +89 -94
  50. package/src/proposals/committee-proposal.js +141 -40
  51. package/src/proposals/core-proposal.js +100 -167
  52. package/src/proposals/econ-behaviors.js +320 -564
  53. package/src/proposals/price-feed-proposal.js +175 -78
  54. package/src/proposals/startEconCommittee.js +25 -12
  55. package/src/proposals/startPSM.js +231 -211
  56. package/src/proposals/utils.js +31 -17
  57. package/src/psm/README.md +71 -0
  58. package/src/psm/psm.js +272 -160
  59. package/src/psm/types.js +2 -0
  60. package/src/reserve/assetReserve.js +56 -413
  61. package/src/reserve/assetReserveKit.js +303 -0
  62. package/src/reserve/doc.md +1 -3
  63. package/src/reserve/params.js +2 -5
  64. package/src/typeGuards.js +13 -0
  65. package/src/vaultFactory/Liquidation.md +100 -0
  66. package/src/vaultFactory/burn.js +2 -1
  67. package/src/vaultFactory/liquidation.js +270 -108
  68. package/src/vaultFactory/math.js +95 -0
  69. package/src/vaultFactory/orderedVaultStore.js +0 -1
  70. package/src/vaultFactory/params.js +133 -112
  71. package/src/vaultFactory/prioritizedVaults.js +36 -79
  72. package/src/vaultFactory/storeUtils.js +67 -9
  73. package/src/vaultFactory/type-imports.js +2 -0
  74. package/src/vaultFactory/types.js +22 -26
  75. package/src/vaultFactory/vault.js +772 -709
  76. package/src/vaultFactory/vaultDirector.js +480 -483
  77. package/src/vaultFactory/vaultFactory.js +99 -60
  78. package/src/vaultFactory/vaultHolder.js +121 -95
  79. package/src/vaultFactory/vaultKit.js +39 -31
  80. package/src/vaultFactory/vaultManager.js +1249 -868
  81. package/bundles/bundle-amm-meta.js +0 -618
  82. package/bundles/bundle-amm.js +0 -1
  83. package/bundles/bundle-feeDistributor-meta.js +0 -346
  84. package/bundles/bundle-interchainPool-meta.js +0 -534
  85. package/bundles/bundle-interchainPool.js +0 -1
  86. package/bundles/bundle-liquidateIncrementally-meta.js +0 -442
  87. package/bundles/bundle-liquidateIncrementally.js +0 -1
  88. package/bundles/bundle-liquidateMinimum-meta.js +0 -442
  89. package/bundles/bundle-liquidateMinimum.js +0 -1
  90. package/bundles/bundle-psm-meta.js +0 -538
  91. package/bundles/bundle-psmCharter-meta.js +0 -418
  92. package/bundles/bundle-psmCharter.js +0 -1
  93. package/bundles/bundle-reserve-meta.js +0 -542
  94. package/bundles/bundle-scaledPriceAuthority-meta.js +0 -442
  95. package/bundles/bundle-stakeFactory-meta.js +0 -574
  96. package/bundles/bundle-stakeFactory.js +0 -1
  97. package/bundles/bundle-vaultFactory-meta.js +0 -598
  98. package/scripts/add-initial-liquidity.js +0 -180
  99. package/src/collect.js +0 -13
  100. package/src/interchainPool.js +0 -135
  101. package/src/makeTracer.js +0 -36
  102. package/src/my-lien.js +0 -85
  103. package/src/proposals/demoIssuers.js +0 -685
  104. package/src/proposals/sim-behaviors.js +0 -40
  105. package/src/psm/psmCharter.js +0 -139
  106. package/src/stakeFactory/README.md +0 -62
  107. package/src/stakeFactory/attestation.js +0 -267
  108. package/src/stakeFactory/attestationTool.js +0 -66
  109. package/src/stakeFactory/constants.js +0 -16
  110. package/src/stakeFactory/params.js +0 -31
  111. package/src/stakeFactory/stakeFactory.js +0 -236
  112. package/src/stakeFactory/stakeFactoryKit.js +0 -455
  113. package/src/stakeFactory/stakeFactoryManager.js +0 -296
  114. package/src/stakeFactory/types.js +0 -42
  115. package/src/vaultFactory/liquidateIncrementally.js +0 -350
  116. package/src/vaultFactory/liquidateMinimum.js +0 -100
  117. package/src/vpool-xyk-amm/AttackersGuide.md +0 -89
  118. package/src/vpool-xyk-amm/addLiquidity.js +0 -222
  119. package/src/vpool-xyk-amm/addPool.js +0 -197
  120. package/src/vpool-xyk-amm/constantProduct/AMM-Trade.jpeg +0 -0
  121. package/src/vpool-xyk-amm/constantProduct/README.md +0 -204
  122. package/src/vpool-xyk-amm/constantProduct/calcFees.js +0 -99
  123. package/src/vpool-xyk-amm/constantProduct/calcSwapPrices.js +0 -85
  124. package/src/vpool-xyk-amm/constantProduct/core.js +0 -153
  125. package/src/vpool-xyk-amm/constantProduct/defaults.js +0 -5
  126. package/src/vpool-xyk-amm/constantProduct/getXY.js +0 -52
  127. package/src/vpool-xyk-amm/constantProduct/internal-types.js +0 -116
  128. package/src/vpool-xyk-amm/constantProduct/invariants.js +0 -43
  129. package/src/vpool-xyk-amm/constantProduct/swap.js +0 -272
  130. package/src/vpool-xyk-amm/constantProduct/types.js +0 -32
  131. package/src/vpool-xyk-amm/doublePool.js +0 -194
  132. package/src/vpool-xyk-amm/estimate.js +0 -155
  133. package/src/vpool-xyk-amm/multipoolMarketMaker.js +0 -520
  134. package/src/vpool-xyk-amm/params.js +0 -61
  135. package/src/vpool-xyk-amm/pool.js +0 -396
  136. package/src/vpool-xyk-amm/priceAuthority.js +0 -94
  137. package/src/vpool-xyk-amm/removeLiquidity.js +0 -31
  138. package/src/vpool-xyk-amm/singlePool.js +0 -73
  139. package/src/vpool-xyk-amm/swap.js +0 -69
  140. 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() });