@agoric/inter-protocol 0.16.2-dev-eb7e9eb.0 → 0.16.2-u11.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 (176) hide show
  1. package/CHANGELOG.md +1041 -0
  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 +222 -242
  5. package/bundles/bundle-econCommitteeCharter.js +1 -1
  6. package/bundles/bundle-feeDistributor-js-meta.json +458 -0
  7. package/bundles/bundle-feeDistributor.js +1 -0
  8. package/bundles/bundle-fluxAggregatorKit-js-meta.json +327 -343
  9. package/bundles/bundle-fluxAggregatorKit.js +1 -1
  10. package/bundles/bundle-psm-js-meta.json +308 -328
  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 -0
  14. package/bundles/bundle-scaledPriceAuthority-js-meta.json +542 -0
  15. package/bundles/bundle-scaledPriceAuthority.js +1 -0
  16. package/bundles/bundle-vaultFactory-js-meta.json +790 -0
  17. package/bundles/bundle-vaultFactory.js +1 -0
  18. package/package.json +31 -31
  19. package/scripts/add-collateral-core.js +112 -0
  20. package/scripts/build-bundles.js +21 -5
  21. package/scripts/deploy-contracts.js +100 -0
  22. package/scripts/init-core.js +198 -0
  23. package/scripts/invite-committee-core.js +42 -0
  24. package/scripts/manual-price-feed.js +117 -0
  25. package/scripts/price-feed-core.js +104 -0
  26. package/scripts/start-local-chain.sh +84 -0
  27. package/src/auction/auctionBook.js +56 -68
  28. package/src/auction/auctioneer.js +44 -56
  29. package/src/auction/offerBook.js +11 -12
  30. package/src/auction/params.js +5 -3
  31. package/src/auction/scheduleMath.js +13 -13
  32. package/src/auction/scheduler.js +32 -22
  33. package/src/auction/sortedOffers.js +7 -8
  34. package/src/auction/util.js +4 -4
  35. package/src/clientSupport.js +96 -152
  36. package/src/contractSupport.js +5 -5
  37. package/src/econCommitteeCharter.js +15 -16
  38. package/src/feeDistributor.js +33 -34
  39. package/src/interest.js +14 -20
  40. package/src/price/fluxAggregatorContract.js +45 -51
  41. package/src/price/fluxAggregatorKit.js +32 -47
  42. package/src/price/priceOracleKit.js +13 -11
  43. package/src/price/roundsManager.js +64 -52
  44. package/src/proposals/addAssetToVault.js +3 -15
  45. package/src/proposals/committee-proposal.js +9 -5
  46. package/src/proposals/core-proposal.js +7 -7
  47. package/src/proposals/econ-behaviors.js +32 -57
  48. package/src/proposals/price-feed-proposal.js +26 -59
  49. package/src/proposals/startEconCommittee.js +1 -1
  50. package/src/proposals/startPSM.js +22 -32
  51. package/src/proposals/utils.js +7 -26
  52. package/src/psm/psm.js +63 -69
  53. package/src/reserve/assetReserve.js +18 -27
  54. package/src/reserve/assetReserveKit.js +22 -14
  55. package/src/typeGuards.js +13 -0
  56. package/src/vaultFactory/liquidation.js +17 -30
  57. package/src/vaultFactory/math.js +9 -8
  58. package/src/vaultFactory/orderedVaultStore.js +9 -6
  59. package/src/vaultFactory/params.js +18 -24
  60. package/src/vaultFactory/prioritizedVaults.js +2 -2
  61. package/src/vaultFactory/proceeds.js +18 -24
  62. package/src/vaultFactory/storeUtils.js +12 -8
  63. package/src/vaultFactory/types.js +28 -38
  64. package/src/vaultFactory/vault.js +89 -88
  65. package/src/vaultFactory/vaultDirector.js +41 -33
  66. package/src/vaultFactory/vaultFactory.js +26 -33
  67. package/src/vaultFactory/vaultHolder.js +13 -8
  68. package/src/vaultFactory/vaultKit.js +2 -3
  69. package/src/vaultFactory/vaultManager.js +120 -138
  70. package/src/auction/auctionBook.d.ts +0 -83
  71. package/src/auction/auctionBook.d.ts.map +0 -1
  72. package/src/auction/auctioneer.d.ts +0 -75
  73. package/src/auction/auctioneer.d.ts.map +0 -1
  74. package/src/auction/offerBook.d.ts +0 -72
  75. package/src/auction/offerBook.d.ts.map +0 -1
  76. package/src/auction/params.d.ts +0 -142
  77. package/src/auction/params.d.ts.map +0 -1
  78. package/src/auction/scheduleMath.d.ts +0 -4
  79. package/src/auction/scheduleMath.d.ts.map +0 -1
  80. package/src/auction/scheduler.d.ts +0 -49
  81. package/src/auction/scheduler.d.ts.map +0 -1
  82. package/src/auction/sortedOffers.d.ts +0 -8
  83. package/src/auction/sortedOffers.d.ts.map +0 -1
  84. package/src/auction/util.d.ts +0 -30
  85. package/src/auction/util.d.ts.map +0 -1
  86. package/src/clientSupport.d.ts +0 -167
  87. package/src/clientSupport.d.ts.map +0 -1
  88. package/src/collectFees.d.ts +0 -2
  89. package/src/collectFees.d.ts.map +0 -1
  90. package/src/contractSupport.d.ts +0 -33
  91. package/src/contractSupport.d.ts.map +0 -1
  92. package/src/econCommitteeCharter.d.ts +0 -41
  93. package/src/econCommitteeCharter.d.ts.map +0 -1
  94. package/src/feeDistributor.d.ts +0 -212
  95. package/src/feeDistributor.d.ts.map +0 -1
  96. package/src/index.d.ts +0 -2
  97. package/src/index.d.ts.map +0 -1
  98. package/src/interest-math.d.ts +0 -3
  99. package/src/interest-math.d.ts.map +0 -1
  100. package/src/interest.d.ts +0 -29
  101. package/src/interest.d.ts.map +0 -1
  102. package/src/price/fluxAggregatorContract.d.ts +0 -112
  103. package/src/price/fluxAggregatorContract.d.ts.map +0 -1
  104. package/src/price/fluxAggregatorKit.d.ts +0 -155
  105. package/src/price/fluxAggregatorKit.d.ts.map +0 -1
  106. package/src/price/priceOracleKit.d.ts +0 -52
  107. package/src/price/priceOracleKit.d.ts.map +0 -1
  108. package/src/price/roundsManager.d.ts +0 -330
  109. package/src/price/roundsManager.d.ts.map +0 -1
  110. package/src/proposals/addAssetToVault.d.ts +0 -155
  111. package/src/proposals/addAssetToVault.d.ts.map +0 -1
  112. package/src/proposals/committee-proposal.d.ts +0 -121
  113. package/src/proposals/committee-proposal.d.ts.map +0 -1
  114. package/src/proposals/core-proposal.d.ts +0 -149
  115. package/src/proposals/core-proposal.d.ts.map +0 -1
  116. package/src/proposals/econ-behaviors.d.ts +0 -201
  117. package/src/proposals/econ-behaviors.d.ts.map +0 -1
  118. package/src/proposals/price-feed-proposal.d.ts +0 -83
  119. package/src/proposals/price-feed-proposal.d.ts.map +0 -1
  120. package/src/proposals/startEconCommittee.d.ts +0 -34
  121. package/src/proposals/startEconCommittee.d.ts.map +0 -1
  122. package/src/proposals/startPSM.d.ts +0 -61
  123. package/src/proposals/startPSM.d.ts.map +0 -1
  124. package/src/proposals/utils.d.ts +0 -15
  125. package/src/proposals/utils.d.ts.map +0 -1
  126. package/src/provisionPool.d.ts +0 -165
  127. package/src/provisionPool.d.ts.map +0 -1
  128. package/src/provisionPool.js +0 -119
  129. package/src/provisionPoolKit.d.ts +0 -379
  130. package/src/provisionPoolKit.d.ts.map +0 -1
  131. package/src/provisionPoolKit.js +0 -461
  132. package/src/psm/psm.d.ts +0 -178
  133. package/src/psm/psm.d.ts.map +0 -1
  134. package/src/psm/types.d.ts +0 -2
  135. package/src/psm/types.d.ts.map +0 -1
  136. package/src/reserve/assetReserve.d.ts +0 -44
  137. package/src/reserve/assetReserve.d.ts.map +0 -1
  138. package/src/reserve/assetReserveKit.d.ts +0 -114
  139. package/src/reserve/assetReserveKit.d.ts.map +0 -1
  140. package/src/reserve/params.d.ts +0 -10
  141. package/src/reserve/params.d.ts.map +0 -1
  142. package/src/tokens.d.ts +0 -3
  143. package/src/tokens.d.ts.map +0 -1
  144. package/src/tokens.js +0 -5
  145. package/src/vaultFactory/burn.d.ts +0 -2
  146. package/src/vaultFactory/burn.d.ts.map +0 -1
  147. package/src/vaultFactory/liquidation.d.ts +0 -24
  148. package/src/vaultFactory/liquidation.d.ts.map +0 -1
  149. package/src/vaultFactory/math.d.ts +0 -10
  150. package/src/vaultFactory/math.d.ts.map +0 -1
  151. package/src/vaultFactory/orderedVaultStore.d.ts +0 -94
  152. package/src/vaultFactory/orderedVaultStore.d.ts.map +0 -1
  153. package/src/vaultFactory/params.d.ts +0 -159
  154. package/src/vaultFactory/params.d.ts.map +0 -1
  155. package/src/vaultFactory/prioritizedVaults.d.ts +0 -279
  156. package/src/vaultFactory/prioritizedVaults.d.ts.map +0 -1
  157. package/src/vaultFactory/proceeds.d.ts +0 -34
  158. package/src/vaultFactory/proceeds.d.ts.map +0 -1
  159. package/src/vaultFactory/storeUtils.d.ts +0 -25
  160. package/src/vaultFactory/storeUtils.d.ts.map +0 -1
  161. package/src/vaultFactory/type-imports.d.ts +0 -2
  162. package/src/vaultFactory/type-imports.d.ts.map +0 -1
  163. package/src/vaultFactory/types.d.ts +0 -137
  164. package/src/vaultFactory/types.d.ts.map +0 -1
  165. package/src/vaultFactory/vault.d.ts +0 -529
  166. package/src/vaultFactory/vault.d.ts.map +0 -1
  167. package/src/vaultFactory/vaultDirector.d.ts +0 -560
  168. package/src/vaultFactory/vaultDirector.d.ts.map +0 -1
  169. package/src/vaultFactory/vaultFactory.d.ts +0 -162
  170. package/src/vaultFactory/vaultFactory.d.ts.map +0 -1
  171. package/src/vaultFactory/vaultHolder.d.ts +0 -201
  172. package/src/vaultFactory/vaultHolder.d.ts.map +0 -1
  173. package/src/vaultFactory/vaultKit.d.ts +0 -32
  174. package/src/vaultFactory/vaultKit.d.ts.map +0 -1
  175. package/src/vaultFactory/vaultManager.d.ts +0 -554
  176. package/src/vaultFactory/vaultManager.d.ts.map +0 -1
@@ -15,31 +15,23 @@ const scaleDecimals = num => BigInt(num * Number(COSMOS_UNIT));
15
15
  /**
16
16
  * Give/want
17
17
  *
18
- * @param {Pick<
19
- * import('@agoric/vats/tools/board-utils.js').AgoricNamesRemotes,
20
- * 'brand'
21
- * >} agoricNames
22
- * @param {| { giveMinted?: number; wantMinted?: number }
23
- * | {
24
- * collateralBrandKey: string;
25
- * giveCollateral?: number;
26
- * wantCollateral?: number;
27
- * }} opts
18
+ * @param {Record<string, Brand>} brands
19
+ * @param {{ giveMinted?: number, wantMinted?: number } | { collateralBrandKey: string, giveCollateral?: number, wantCollateral?: number }} opts
28
20
  * @returns {Proposal}
29
21
  */
30
- const makeVaultProposal = ({ brand }, opts) => {
22
+ const makeVaultProposal = (brands, opts) => {
31
23
  const proposal = { give: {}, want: {} };
32
24
 
33
25
  if ('giveCollateral' in opts && opts.giveCollateral) {
34
26
  const { collateralBrandKey } = opts;
35
27
  proposal.give.Collateral = {
36
- brand: brand[collateralBrandKey],
28
+ brand: brands[collateralBrandKey],
37
29
  value: scaleDecimals(opts.giveCollateral),
38
30
  };
39
31
  }
40
32
  if ('giveMinted' in opts && opts.giveMinted) {
41
33
  proposal.give.Minted = {
42
- brand: brand.IST,
34
+ brand: brands.IST,
43
35
  value: scaleDecimals(opts.giveMinted),
44
36
  };
45
37
  }
@@ -47,13 +39,13 @@ const makeVaultProposal = ({ brand }, opts) => {
47
39
  if ('wantCollateral' in opts && opts.wantCollateral) {
48
40
  const { collateralBrandKey } = opts;
49
41
  proposal.want.Collateral = {
50
- brand: brand[collateralBrandKey],
42
+ brand: brands[collateralBrandKey],
51
43
  value: scaleDecimals(opts.wantCollateral),
52
44
  };
53
45
  }
54
46
  if ('wantMinted' in opts && opts.wantMinted) {
55
47
  proposal.want.Minted = {
56
- brand: brand.IST,
48
+ brand: brands.IST,
57
49
  value: scaleDecimals(opts.wantMinted),
58
50
  };
59
51
  }
@@ -62,26 +54,18 @@ const makeVaultProposal = ({ brand }, opts) => {
62
54
  };
63
55
 
64
56
  /**
65
- * @param {Pick<
66
- * import('@agoric/vats/tools/board-utils.js').AgoricNamesRemotes,
67
- * 'brand'
68
- * >} agoricNames
69
- * @param {{
70
- * offerId: string;
71
- * wantMinted: number;
72
- * giveCollateral: number;
73
- * collateralBrandKey: string;
74
- * }} opts
57
+ * @param {Record<string, Brand>} brands
58
+ * @param {{ offerId: string, wantMinted: number, giveCollateral: number, collateralBrandKey: string }} opts
75
59
  * @returns {import('@agoric/smart-wallet/src/offers.js').OfferSpec}
76
60
  */
77
- const makeOpenOffer = ({ brand }, opts) => {
78
- const proposal = makeVaultProposal({ brand }, opts);
61
+ const makeOpenOffer = (brands, opts) => {
62
+ const proposal = makeVaultProposal(brands, opts);
79
63
 
80
64
  // NB: not really a Proposal because the brands are not remotes
81
65
  // Instead they're copyRecord like "{"boardId":"board0257","iface":"Alleged: IST brand"}" to pass through the boardId
82
66
  // mustMatch(harden(proposal), ProposalShape);
83
67
 
84
- const collateralBrand = brand[opts.collateralBrandKey];
68
+ const collateralBrand = brands[opts.collateralBrandKey];
85
69
 
86
70
  return {
87
71
  id: opts.offerId,
@@ -98,26 +82,16 @@ const makeOpenOffer = ({ brand }, opts) => {
98
82
  };
99
83
 
100
84
  /**
101
- * @param {Pick<
102
- * import('@agoric/vats/tools/board-utils.js').AgoricNamesRemotes,
103
- * 'brand'
104
- * >} agoricNames
105
- * @param {{
106
- * offerId: string;
107
- * collateralBrandKey?: string;
108
- * giveCollateral?: number;
109
- * wantCollateral?: number;
110
- * giveMinted?: number;
111
- * wantMinted?: number;
112
- * }} opts
85
+ * @param {Record<string, Brand>} brands
86
+ * @param {{ offerId: string, collateralBrandKey?: string, giveCollateral?: number, wantCollateral?: number, giveMinted?: number, wantMinted?: number }} opts
113
87
  * @param {string} previousOffer
114
88
  * @returns {import('@agoric/smart-wallet/src/offers.js').OfferSpec}
115
89
  */
116
- const makeAdjustOffer = ({ brand }, opts, previousOffer) => {
90
+ const makeAdjustOffer = (brands, opts, previousOffer) => {
117
91
  // NB: not really a Proposal because the brands are not remotes
118
92
  // Instead they're copyRecord like "{"boardId":"board0257","iface":"Alleged: IST brand"}" to pass through the boardId
119
93
  // mustMatch(harden(proposal), ProposalShape);
120
- const proposal = makeVaultProposal({ brand }, opts);
94
+ const proposal = makeVaultProposal(brands, opts);
121
95
 
122
96
  return {
123
97
  id: opts.offerId,
@@ -131,20 +105,13 @@ const makeAdjustOffer = ({ brand }, opts, previousOffer) => {
131
105
  };
132
106
 
133
107
  /**
134
- * @param {Pick<
135
- * import('@agoric/vats/tools/board-utils.js').AgoricNamesRemotes,
136
- * 'brand'
137
- * >} agoricNames
138
- * @param {{
139
- * offerId: string;
140
- * collateralBrandKey?: string;
141
- * giveMinted: number;
142
- * }} opts
108
+ * @param {Record<string, Brand>} brands
109
+ * @param {{ offerId: string, collateralBrandKey?: string, giveMinted: number }} opts
143
110
  * @param {string} previousOffer
144
111
  * @returns {import('@agoric/smart-wallet/src/offers.js').OfferSpec}
145
112
  */
146
- const makeCloseOffer = ({ brand }, opts, previousOffer) => {
147
- const proposal = makeVaultProposal({ brand }, opts);
113
+ const makeCloseOffer = (brands, opts, previousOffer) => {
114
+ const proposal = makeVaultProposal(brands, opts);
148
115
 
149
116
  return {
150
117
  id: opts.offerId,
@@ -159,9 +126,7 @@ const makeCloseOffer = ({ brand }, opts, previousOffer) => {
159
126
 
160
127
  /**
161
128
  * @param {string} vaultId
162
- * @param {Promise<
163
- * import('@agoric/smart-wallet/src/smartWallet').CurrentWalletRecord
164
- * >} currentP
129
+ * @param {Promise<import('@agoric/smart-wallet/src/smartWallet').CurrentWalletRecord>} currentP
165
130
  * @returns {Promise<string>} offer id in which the vault was made
166
131
  */
167
132
  export const lookupOfferIdForVault = async (vaultId, currentP) => {
@@ -176,14 +141,11 @@ export const lookupOfferIdForVault = async (vaultId, currentP) => {
176
141
  };
177
142
 
178
143
  /**
179
- * @param {Record<
180
- * string,
181
- * import('@agoric/internal/src/marshal.js').BoardRemote
182
- * >} brands
183
- * @param {| { wantMinted: number; giveMinted?: undefined }
184
- * | { giveMinted: number; wantMinted?: undefined }} opts
185
- * @param {number} [fee]
144
+ * @param {Record<string, Brand>} brands
145
+ * @param {({ wantMinted: number, giveMinted?: undefined } | { giveMinted: number, wantMinted?: undefined })} opts
146
+ * @param {number} [fee=0]
186
147
  * @param {string} [anchor]
148
+ * @returns {Proposal} XXX not a real proposal, uses BoardRemote
187
149
  */
188
150
  const makePsmProposal = (brands, opts, fee = 0, anchor = 'AUSD') => {
189
151
  const giving = 'giveMinted' in opts ? 'minted' : 'anchor';
@@ -209,24 +171,19 @@ const makePsmProposal = (brands, opts, fee = 0, anchor = 'AUSD') => {
209
171
  };
210
172
 
211
173
  /**
212
- * @param {Pick<
213
- * import('@agoric/vats/tools/board-utils.js').AgoricNamesRemotes,
214
- * 'brand'
215
- * >} agoricNames
216
174
  * @param {Instance} instance
217
- * @param {{ offerId: string; feePct?: number; pair: [string, string] } & (
218
- * | { wantMinted: number }
219
- * | { giveMinted: number }
220
- * )} opts
175
+ * @param {Record<string, Brand>} brands
176
+ * @param {{ offerId: string, feePct?: number, pair: [string, string] } &
177
+ * ({ wantMinted: number } | { giveMinted: number })} opts
221
178
  * @returns {import('@agoric/smart-wallet/src/offers.js').OfferSpec}
222
179
  */
223
- const makePsmSwapOffer = ({ brand }, instance, opts) => {
180
+ const makePsmSwapOffer = (instance, brands, opts) => {
224
181
  const method =
225
182
  'wantMinted' in opts
226
183
  ? 'makeWantMintedInvitation'
227
184
  : 'makeGiveMintedInvitation'; // ref psm.js
228
185
  const proposal = makePsmProposal(
229
- brand,
186
+ brands,
230
187
  opts,
231
188
  opts.feePct ? opts.feePct / 100 : undefined,
232
189
  opts.pair[1],
@@ -243,79 +200,33 @@ const makePsmSwapOffer = ({ brand }, instance, opts) => {
243
200
  instance,
244
201
  publicInvitationMaker: method,
245
202
  },
246
- // @ts-expect-error BoardRemote not a Brand object
247
203
  proposal,
248
204
  };
249
205
  };
250
206
 
251
207
  /**
252
- * @param {Pick<
253
- * import('@agoric/vats/tools/board-utils.js').AgoricNamesRemotes,
254
- * 'brand' | 'vbankAsset'
255
- * >} agoricNames
256
- * @param {(msg: string) => Error} makeError error constructor
257
- * @returns {(a: string) => Amount<'nat'>}
258
- */
259
- export const makeParseAmount =
260
- (agoricNames, makeError = msg => RangeError(msg)) =>
261
- opt => {
262
- assert.typeof(opt, 'string', 'parseAmount expected string');
263
- const m = opt.match(/^(?<value>[\d_]+(\.[\d_]+)?)(?<brand>[A-Z]\w*?)$/);
264
- if (!m || !m.groups) {
265
- throw makeError(`invalid amount: ${opt}`);
266
- }
267
- const anyBrand = agoricNames.brand[m.groups.brand];
268
- if (!anyBrand) {
269
- throw makeError(`unknown brand: ${m.groups.brand}`);
270
- }
271
- const assetDesc = Object.values(agoricNames.vbankAsset).find(
272
- d => d.brand === anyBrand,
273
- );
274
- if (!assetDesc) {
275
- throw makeError(`unknown brand: ${m.groups.brand}`);
276
- }
277
- const { displayInfo } = assetDesc;
278
- if (!displayInfo.decimalPlaces || displayInfo.assetKind !== 'nat') {
279
- throw makeError(`bad brand: ${displayInfo}`);
280
- }
281
- const value = BigInt(
282
- Number(m.groups.value.replace(/_/g, '')) *
283
- 10 ** displayInfo.decimalPlaces,
284
- );
285
- /** @type {Brand<'nat'>} */
286
- // @ts-expect-error dynamic cast
287
- const natBrand = anyBrand;
288
- const amt = { value, brand: natBrand };
289
- return amt;
290
- };
291
-
292
- /**
293
- * @param {Pick<
294
- * import('@agoric/vats/tools/board-utils.js').AgoricNamesRemotes,
295
- * 'brand' | 'vbankAsset'
296
- * >} agoricNames
208
+ * @param {Record<string, Brand>} _brands
297
209
  * @param {{
298
- * offerId: string;
299
- * give: string;
300
- * maxBuy: string;
301
- * wantMinimum?: string;
302
- * } & (
303
- * | {
304
- * price: number;
305
- * }
306
- * | {
307
- * discount: number; // -1 to 1. e.g. 0.10 for 10% discount, -0.05 for 5% markup
308
- * }
309
- * )} opts
210
+ * offerId: string,
211
+ * give: string,
212
+ * maxBuy: string,
213
+ * wantMinimum?: string,
214
+ * parseAmount: (x: string) => Amount<'nat'>,
215
+ * } & ({
216
+ * price: number,
217
+ * } | {
218
+ * discount: number, // -1 to 1. e.g. 0.10 for 10% discount, -0.05 for 5% markup
219
+ * })} opts
310
220
  * @returns {import('@agoric/smart-wallet/src/offers.js').OfferSpec}
311
221
  */
312
- const makeBidOffer = (agoricNames, opts) => {
222
+ const makeBidOffer = (_brands, opts) => {
223
+ assert.typeof(opts.parseAmount, 'function');
313
224
  assertAllDefined({
314
225
  offerId: opts.offerId,
315
226
  give: opts.give,
316
227
  maxBuy: opts.maxBuy,
317
228
  });
318
- const parseAmount = makeParseAmount(agoricNames);
229
+ const { parseAmount } = opts;
319
230
  const proposal = {
320
231
  give: { Bid: parseAmount(opts.give) },
321
232
  ...(opts.wantMinimum
@@ -365,23 +276,19 @@ const makeBidOffer = (agoricNames, opts) => {
365
276
  };
366
277
 
367
278
  /**
368
- * @param {Pick<
369
- * import('@agoric/vats/tools/board-utils.js').AgoricNamesRemotes,
370
- * 'brand'
371
- * >} agoricNames
279
+ * @param {Record<string, Brand>} brands
372
280
  * @param {{
373
- * offerId: string;
374
- * give: number;
375
- * collateralBrandKey: string;
281
+ * offerId: string,
282
+ * give: number,
283
+ * collateralBrandKey: string,
376
284
  * }} opts
377
285
  * @returns {import('@agoric/smart-wallet/src/offers.js').OfferSpec}
378
286
  */
379
- const makeAddCollateralOffer = ({ brand }, opts) => {
287
+ const makeAddCollateralOffer = (brands, opts) => {
380
288
  /** @type {AmountKeywordRecord} */
381
289
  const give = {
382
290
  Collateral: AmountMath.make(
383
- // @ts-expect-error BoardRemote not a Brand object
384
- brand[opts.collateralBrandKey],
291
+ brands[opts.collateralBrandKey],
385
292
  scaleDecimals(opts.give),
386
293
  ),
387
294
  };
@@ -400,16 +307,17 @@ const makeAddCollateralOffer = ({ brand }, opts) => {
400
307
  };
401
308
 
402
309
  /**
403
- * @param {unknown} _agoricNames
310
+ *
311
+ * @param {Record<string, Brand>} _brands
404
312
  * @param {{
405
- * offerId: string;
406
- * roundId?: bigint;
407
- * unitPrice: bigint;
313
+ * offerId: string,
314
+ * roundId?: bigint,
315
+ * unitPrice: bigint,
408
316
  * }} opts
409
317
  * @param {string} previousOffer
410
318
  * @returns {import('@agoric/smart-wallet/src/offers.js').OfferSpec}
411
319
  */
412
- const makePushPriceOffer = (_agoricNames, opts, previousOffer) => {
320
+ const makePushPriceOffer = (_brands, opts, previousOffer) => {
413
321
  return {
414
322
  id: opts.offerId,
415
323
  invitationSpec: {
@@ -424,12 +332,48 @@ const makePushPriceOffer = (_agoricNames, opts, previousOffer) => {
424
332
  };
425
333
  };
426
334
 
335
+ // TODO DRY with CLI wallet.js
427
336
  /**
428
- * @satisfies {Record<
429
- * string,
430
- * Record<string, import('@agoric/smart-wallet/src/types.js').OfferMaker>
431
- * >}
337
+ * @param {{
338
+ * brand: Record<string, Brand>,
339
+ * vbankAsset: Record<string, { brand: Brand, displayInfo: DisplayInfo }>,
340
+ * }} agoricNames
341
+ * @param {(msg: string) => Error} makeError error constructor
342
+ * @returns {(a: string) => Amount<'nat'>}
432
343
  */
344
+ export const makeParseAmount =
345
+ (agoricNames, makeError = msg => RangeError(msg)) =>
346
+ opt => {
347
+ assert.typeof(opt, 'string', 'parseAmount expected string');
348
+ const m = opt.match(/^(?<value>[\d_]+(\.[\d_]+)?)(?<brand>[A-Z]\w*?)$/);
349
+ if (!m || !m.groups) {
350
+ throw makeError(`invalid amount: ${opt}`);
351
+ }
352
+ const anyBrand = agoricNames.brand[m.groups.brand];
353
+ if (!anyBrand) {
354
+ throw makeError(`unknown brand: ${m.groups.brand}`);
355
+ }
356
+ const assetDesc = Object.values(agoricNames.vbankAsset).find(
357
+ d => d.brand === anyBrand,
358
+ );
359
+ if (!assetDesc) {
360
+ throw makeError(`unknown brand: ${m.groups.brand}`);
361
+ }
362
+ const { displayInfo } = assetDesc;
363
+ if (!displayInfo.decimalPlaces || displayInfo.assetKind !== 'nat') {
364
+ throw makeError(`bad brand: ${displayInfo}`);
365
+ }
366
+ const value = BigInt(
367
+ Number(m.groups.value.replace(/_/g, '')) *
368
+ 10 ** displayInfo.decimalPlaces,
369
+ );
370
+ /** @type {Brand<'nat'>} */
371
+ // @ts-expect-error dynamic cast
372
+ const natBrand = anyBrand;
373
+ const amt = { value, brand: natBrand };
374
+ return amt;
375
+ };
376
+
433
377
  export const Offers = {
434
378
  auction: {
435
379
  Bid: makeBidOffer,
@@ -13,11 +13,11 @@ export const ratioPattern = harden({
13
13
  });
14
14
 
15
15
  /**
16
- * Apply a delta to the `base` Amount, where the delta is represented as an
17
- * amount to gain and an amount to lose. Typically one of those will be empty
18
- * because gain/loss comes from the give/want for a specific asset on a
19
- * proposal. We use two Amounts because an Amount cannot represent a negative
20
- * number (so we use a "loss" that will be subtracted).
16
+ * Apply a delta to the `base` Amount, where the delta is represented as
17
+ * an amount to gain and an amount to lose. Typically one of those will
18
+ * be empty because gain/loss comes from the give/want for a specific asset
19
+ * on a proposal. We use two Amounts because an Amount cannot represent
20
+ * a negative number (so we use a "loss" that will be subtracted).
21
21
  *
22
22
  * @template {AssetKind} K
23
23
  * @param {Amount<K>} base
@@ -13,10 +13,12 @@ import {
13
13
  import { E } from '@endo/far';
14
14
 
15
15
  /**
16
- * @file This contract makes it possible for those who govern contracts to call
17
- * for votes on changes. A more complete implementation would validate
18
- * parameters, constrain deadlines and possibly split the ability to call for
19
- * votes into separate capabilities for finer grain encapsulation.
16
+ * @file
17
+ *
18
+ * This contract makes it possible for those who govern contracts to call for
19
+ * votes on changes. A more complete implementation would validate parameters,
20
+ * constrain deadlines and possibly split the ability to call for votes into
21
+ * separate capabilities for finer grain encapsulation.
20
22
  */
21
23
 
22
24
  export const INVITATION_MAKERS_DESC = 'charter member invitation';
@@ -26,7 +28,7 @@ export const INVITATION_MAKERS_DESC = 'charter member invitation';
26
28
  * @property {bigint} deadline
27
29
  * @property {Instance} instance
28
30
  * @property {Record<string, unknown>} params
29
- * @property {{ paramPath: { key: string } }} [path]
31
+ * @property {{paramPath: { key: string }}} [path]
30
32
  */
31
33
  const ParamChangesOfferArgsShape = M.splitRecord(
32
34
  {
@@ -39,21 +41,19 @@ const ParamChangesOfferArgsShape = M.splitRecord(
39
41
  },
40
42
  );
41
43
 
42
- /** @type {ContractMeta} */
43
- export const meta = {
44
- customTermsShape: {
45
- binaryVoteCounterInstallation: InstallationShape,
46
- },
47
- upgradability: 'canUpgrade',
48
- };
49
- harden(meta);
44
+ /**
45
+ * A pattern for Zoe to check custom terms before `start()`ing the contract.
46
+ */
47
+ export const customTermsShape = harden({
48
+ binaryVoteCounterInstallation: InstallationShape,
49
+ });
50
50
 
51
51
  /**
52
- * @param {ZCF<{ binaryVoteCounterInstallation: Installation }>} zcf
52
+ * @param {ZCF<{binaryVoteCounterInstallation: Installation}>} zcf
53
53
  * @param {undefined} privateArgs
54
54
  * @param {import('@agoric/vat-data').Baggage} baggage
55
55
  */
56
- export const start = async (zcf, privateArgs, baggage) => {
56
+ export const prepare = async (zcf, privateArgs, baggage) => {
57
57
  const { binaryVoteCounterInstallation: counter } = zcf.getTerms();
58
58
  /** @type {MapStore<Instance, GovernorCreatorFacet<any>>} */
59
59
  const instanceToGovernor = provideDurableMapStore(
@@ -184,4 +184,3 @@ export const start = async (zcf, privateArgs, baggage) => {
184
184
 
185
185
  return harden({ creatorFacet });
186
186
  };
187
- harden(start);
@@ -9,24 +9,23 @@ import { KeywordShape } from '@agoric/zoe/src/typeGuards.js';
9
9
 
10
10
  const KeywordSharesShape = M.recordOf(KeywordShape, M.nat());
11
11
 
12
- /** @type {ContractMeta} */
13
- export const meta = {
14
- customTermsShape: {
15
- keywordShares: KeywordSharesShape,
16
- timerService: M.eref(M.remotable('TimerService')),
17
- collectionInterval: RelativeTimeShape,
18
- },
19
- };
20
- harden(meta);
12
+ /**
13
+ * A pattern for Zoe to check custom terms before `start()`ing the contract.
14
+ */
15
+ export const customTermsShape = harden({
16
+ keywordShares: KeywordSharesShape,
17
+ timerService: M.eref(M.remotable('TimerService')),
18
+ collectionInterval: RelativeTimeShape,
19
+ });
21
20
 
22
21
  /**
23
22
  * @typedef {import('@agoric/time/src/types').RelativeTime} RelativeTime
24
- *
25
23
  * @typedef {import('@agoric/time/src/types').TimerService} TimerService
26
24
  */
27
25
 
28
26
  /**
29
27
  * @typedef {object} FeeCollector
28
+ *
30
29
  * @property {() => ERef<Payment<'nat'>>} collectFees
31
30
  */
32
31
 
@@ -66,12 +65,10 @@ export const makeContractFeeCollector = (zoe, creatorFacet) => {
66
65
  * for fees that have been collected to date and send that payment to the
67
66
  * depositFacet.
68
67
  *
69
- * @param {() => Promise<unknown>} schedulePayments - distribute to the
70
- * destinations
71
- * @param {ERef<TimerService>} timerService - timer that is used to schedule
72
- * collections
68
+ * @param {() => Promise<unknown>} schedulePayments - distribute to the destinations
69
+ * @param {ERef<TimerService>} timerService - timer that is used to schedule collections
73
70
  * @param {RelativeTime} [collectionInterval] - how often to collect fees in the
74
- * `timerService` unit
71
+ * `timerService` unit
75
72
  */
76
73
  export const startDistributing = (
77
74
  schedulePayments,
@@ -102,9 +99,8 @@ export const startDistributing = (
102
99
  };
103
100
 
104
101
  /**
105
- * @typedef {{
106
- * pushPayment: (payment: Payment, issuer: ERef<Issuer>) => Promise<Amount>;
107
- * }} FeeDestination
102
+ * @typedef {{ pushPayment: (payment: Payment, issuer: ERef<Issuer>) => Promise<Amount>}} FeeDestination
103
+ *
108
104
  * @param {Record<Keyword, ERef<FeeDestination>>} [destinations]
109
105
  * @param {Record<Keyword, NatValue>} [keywordShares]
110
106
  */
@@ -165,16 +161,17 @@ export const sharePayment = async (
165
161
  .filter(([_, amt]) => !AmountMath.isEmpty(amt));
166
162
 
167
163
  /**
168
- * If the `sharedPayment[i]` payments that are sent to the fee `destination`
169
- * with `pushPayment` never arrive, or never get deposited (or otherwise used
170
- * up), then they remain in the recovery set of the `recoveryPurse`. The
171
- * purpose of this, and of recovery sets in general, is to be able, in
172
- * emergencies, to recover the assets of payments in flight that seem to be
173
- * stuck. This is much like cancelling a check that may still be undeposited.
164
+ * If the `sharedPayment[i]` payments that are sent to the fee
165
+ * `destination` with `pushPayment` never arrive, or never get deposited
166
+ * (or otherwise used up), then they remain in the recovery set of the
167
+ * `recoveryPurse`. The purpose of this, and of recovery sets in general,
168
+ * is to be able, in emergencies, to recover the assets of payments in flight
169
+ * that seem to be stuck. This is much like cancelling a check that may still
170
+ * be undeposited.
174
171
  *
175
172
  * TODO: However, for this to be possible, the `recoveryPurse` holding that
176
- * recovery set must remain accessible to someone that should legitimately be
177
- * able to recover those payments. But this `recoveryPurse` is currently
173
+ * recovery set must remain accessible to someone that should legitimately
174
+ * be able to recover those payments. But this `recoveryPurse` is currently
178
175
  * dropped on the floor instead.
179
176
  */
180
177
  const recoveryPurse = E(issuer).makeEmptyPurse();
@@ -196,11 +193,7 @@ export const sharePayment = async (
196
193
 
197
194
  /**
198
195
  * @param {ERef<Issuer<'nat'>>} feeIssuer
199
- * @param {{
200
- * keywordShares: Record<Keyword, NatValue>;
201
- * timerService: ERef<TimerService>;
202
- * collectionInterval: RelativeTime;
203
- * }} terms
196
+ * @param {{ keywordShares: Record<Keyword, NatValue>, timerService: ERef<TimerService>, collectionInterval: RelativeTime}} terms
204
197
  */
205
198
  export const makeFeeDistributor = (feeIssuer, terms) => {
206
199
  const { timerService, collectionInterval } = terms;
@@ -268,7 +261,9 @@ export const makeFeeDistributor = (feeIssuer, terms) => {
268
261
  return periodicCollector;
269
262
  },
270
263
 
271
- /** @param {import('@endo/far').EOnly<DepositFacet>} depositFacet */
264
+ /**
265
+ * @param {import('@endo/far').EOnly<DepositFacet>} depositFacet
266
+ */
272
267
  makeDepositFacetDestination: depositFacet => {
273
268
  return Far(`DepositFacetDestination`, {
274
269
  pushPayment: async (payment, _issuer) => {
@@ -320,7 +315,9 @@ export const makeFeeDistributor = (feeIssuer, terms) => {
320
315
  });
321
316
  },
322
317
 
323
- /** @param {Record<Keyword, ERef<FeeDestination>>} newDestinations */
318
+ /**
319
+ * @param {Record<Keyword, ERef<FeeDestination>>} newDestinations
320
+ */
324
321
  setDestinations: async newDestinations => {
325
322
  destinations = newDestinations;
326
323
  shareConfig = makeShareConfig(destinations, keywordShares);
@@ -347,7 +344,9 @@ export const makeFeeDistributor = (feeIssuer, terms) => {
347
344
  /** @typedef {ReturnType<typeof makeFeeDistributor>['creatorFacet']} FeeDistributorCreatorFacet */
348
345
  /** @typedef {ReturnType<typeof makeFeeDistributor>['publicFacet']} FeeDistributorPublicFacet */
349
346
 
350
- /** @param {ZCF<Parameters<typeof makeFeeDistributor>[1]>} zcf */
347
+ /**
348
+ * @param {ZCF<Parameters<typeof makeFeeDistributor>[1]>} zcf
349
+ */
351
350
  export const start = async zcf => {
352
351
  const feeIssuer = E(zcf.getZoeService()).getFeeIssuer();
353
352
  return makeFeeDistributor(feeIssuer, zcf.getTerms());
package/src/interest.js CHANGED
@@ -12,7 +12,6 @@ import { TimeMath } from '@agoric/time';
12
12
 
13
13
  /**
14
14
  * @typedef {import('@agoric/time/src/types').Timestamp} Timestamp
15
- *
16
15
  * @typedef {import('@agoric/time/src/types').RelativeTime} RelativeTime
17
16
  */
18
17
 
@@ -21,7 +20,9 @@ const BASIS_POINTS = 10000;
21
20
  // single digit APR is less than a basis point per day.
22
21
  const LARGE_DENOMINATOR = BASIS_POINTS * BASIS_POINTS;
23
22
 
24
- /** Number chosen from 6 digits for a basis point, doubled for multiplication. */
23
+ /**
24
+ * Number chosen from 6 digits for a basis point, doubled for multiplication.
25
+ */
25
26
  const COMPOUNDED_INTEREST_DENOMINATOR = 10n ** 20n;
26
27
 
27
28
  /**
@@ -146,27 +147,20 @@ const validatedBrand = (mint, debt) => {
146
147
  * Charge interest accrued between `latestInterestUpdate` and `accruedUntil`.
147
148
  *
148
149
  * @param {{
149
- * mint: ZCFMint<'nat'>;
150
- * mintAndTransferWithFee: MintAndTransfer;
151
- * poolIncrementSeat: ZCFSeat;
152
- * seatAllocationKeyword: Keyword;
153
- * }} powers
150
+ * mint: ZCFMint<'nat'>,
151
+ * mintAndTransferWithFee: MintAndTransfer,
152
+ * poolIncrementSeat: ZCFSeat,
153
+ * seatAllocationKeyword: Keyword }} powers
154
154
  * @param {{
155
- * interestRate: Ratio;
156
- * chargingPeriod: RelativeTime;
157
- * recordingPeriod: RelativeTime;
158
- * }} params
155
+ * interestRate: Ratio,
156
+ * chargingPeriod: RelativeTime,
157
+ * recordingPeriod: RelativeTime}} params
159
158
  * @param {{
160
- * latestInterestUpdate: Timestamp;
161
- * compoundedInterest: Ratio;
162
- * totalDebt: Amount<'nat'>;
163
- * }} prior
159
+ * latestInterestUpdate: Timestamp,
160
+ * compoundedInterest: Ratio,
161
+ * totalDebt: Amount<'nat'>}} prior
164
162
  * @param {Timestamp} accruedUntil
165
- * @returns {{
166
- * compoundedInterest: Ratio;
167
- * latestInterestUpdate: Timestamp;
168
- * totalDebt: Amount<'nat'>;
169
- * }}
163
+ * @returns {{compoundedInterest: Ratio, latestInterestUpdate: Timestamp, totalDebt: Amount<'nat'> }}
170
164
  */
171
165
  export const chargeInterest = (powers, params, prior, accruedUntil) => {
172
166
  const brand = validatedBrand(powers.mint, prior.totalDebt);