@agoric/inter-protocol 0.16.2-other-dev-8f8782b.0 → 0.16.2-other-dev-fbe72e7.0.fbe72e7
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/README.md +6 -6
- package/package.json +46 -39
- package/scripts/build-bundles.js +5 -21
- package/src/auction/auctionBook.d.ts +147 -0
- package/src/auction/auctionBook.d.ts.map +1 -0
- package/src/auction/auctionBook.js +182 -151
- package/src/auction/auctionMath.d.ts +17 -0
- package/src/auction/auctionMath.d.ts.map +1 -0
- package/src/auction/auctionMath.js +81 -0
- package/src/auction/auctioneer.d.ts +70 -0
- package/src/auction/auctioneer.d.ts.map +1 -0
- package/src/auction/auctioneer.js +72 -59
- package/src/auction/offerBook.d.ts +46 -0
- package/src/auction/offerBook.d.ts.map +1 -0
- package/src/auction/offerBook.js +17 -12
- package/src/auction/params.d.ts +145 -0
- package/src/auction/params.d.ts.map +1 -0
- package/src/auction/params.js +11 -9
- package/src/auction/scheduleMath.d.ts +5 -0
- package/src/auction/scheduleMath.d.ts.map +1 -0
- package/src/auction/scheduleMath.js +18 -16
- package/src/auction/scheduler.d.ts +50 -0
- package/src/auction/scheduler.d.ts.map +1 -0
- package/src/auction/scheduler.js +53 -47
- package/src/auction/sortedOffers.d.ts +8 -0
- package/src/auction/sortedOffers.d.ts.map +1 -0
- package/src/auction/sortedOffers.js +10 -9
- package/src/auction/util.d.ts +31 -0
- package/src/auction/util.d.ts.map +1 -0
- package/src/auction/util.js +12 -6
- package/src/clientSupport.d.ts +168 -0
- package/src/clientSupport.d.ts.map +1 -0
- package/src/clientSupport.js +161 -98
- package/src/collectFees.d.ts +2 -0
- package/src/collectFees.d.ts.map +1 -0
- package/src/contractSupport.d.ts +28 -0
- package/src/contractSupport.d.ts.map +1 -0
- package/src/contractSupport.js +19 -13
- package/src/econCommitteeCharter.d.ts +43 -0
- package/src/econCommitteeCharter.d.ts.map +1 -0
- package/src/econCommitteeCharter.js +25 -20
- package/src/feeDistributor.d.ts +224 -0
- package/src/feeDistributor.d.ts.map +1 -0
- package/src/feeDistributor.js +41 -33
- package/src/index.d.ts +2 -0
- package/src/index.d.ts.map +1 -0
- package/src/index.js +1 -0
- package/src/interest-math.d.ts +4 -0
- package/src/interest-math.d.ts.map +1 -0
- package/src/interest-math.js +5 -1
- package/src/interest.d.ts +30 -0
- package/src/interest.d.ts.map +1 -0
- package/src/interest.js +25 -23
- package/src/price/README.md +14 -1
- package/src/price/fluxAggregatorContract.d.ts +71 -0
- package/src/price/fluxAggregatorContract.d.ts.map +1 -0
- package/src/price/fluxAggregatorContract.js +64 -55
- package/src/price/fluxAggregatorKit.d.ts +104 -0
- package/src/price/fluxAggregatorKit.d.ts.map +1 -0
- package/src/price/fluxAggregatorKit.js +55 -42
- package/src/price/priceOracleKit.d.ts +39 -0
- package/src/price/priceOracleKit.d.ts.map +1 -0
- package/src/price/priceOracleKit.js +17 -15
- package/src/price/roundsManager.d.ts +204 -0
- package/src/price/roundsManager.d.ts.map +1 -0
- package/src/price/roundsManager.js +132 -85
- package/src/proposals/README.md +2 -3
- package/src/proposals/add-auction.js +285 -0
- package/src/proposals/addAssetToVault.js +192 -40
- package/src/proposals/committee-proposal.js +25 -31
- package/src/proposals/core-proposal.js +9 -11
- package/src/proposals/deploy-price-feeds.js +341 -0
- package/src/proposals/econ-behaviors.js +84 -49
- package/src/proposals/price-feed-proposal.js +109 -51
- package/src/proposals/replace-fee-distributor.js +198 -0
- package/src/proposals/replace-scaledPriceAuthorities.js +124 -0
- package/src/proposals/replaceElectorate.js +610 -0
- package/src/proposals/startEconCommittee.js +2 -2
- package/src/proposals/startPSM.js +44 -29
- package/src/proposals/upgrade-scaledPriceAuthorities.js +78 -0
- package/src/proposals/upgrade-vaults.js +207 -0
- package/src/proposals/utils.d.ts +21 -0
- package/src/proposals/utils.d.ts.map +1 -0
- package/src/proposals/utils.js +66 -9
- package/src/proposals/withdraw-reserve-proposal.js +63 -0
- package/src/provisionPool.d.ts +69 -0
- package/src/provisionPool.d.ts.map +1 -0
- package/src/provisionPool.js +138 -0
- package/src/provisionPoolKit.d.ts +129 -0
- package/src/provisionPoolKit.d.ts.map +1 -0
- package/src/provisionPoolKit.js +608 -0
- package/src/psm/psm.d.ts +133 -0
- package/src/psm/psm.d.ts.map +1 -0
- package/src/psm/psm.js +85 -79
- package/src/psm/types-ambient.d.ts +2 -0
- package/src/psm/types-ambient.d.ts.map +1 -0
- package/src/psm/types-ambient.js +3 -0
- package/src/reserve/assetReserve.d.ts +58 -0
- package/src/reserve/assetReserve.d.ts.map +1 -0
- package/src/reserve/assetReserve.js +42 -34
- package/src/reserve/assetReserveKit.d.ts +103 -0
- package/src/reserve/assetReserveKit.d.ts.map +1 -0
- package/src/reserve/assetReserveKit.js +134 -32
- package/src/reserve/params.d.ts +16 -0
- package/src/reserve/params.d.ts.map +1 -0
- package/src/reserve/params.js +8 -2
- package/src/tokens.d.ts +3 -0
- package/src/tokens.d.ts.map +1 -0
- package/src/tokens.js +5 -0
- package/src/vaultFactory/burn.d.ts +2 -0
- package/src/vaultFactory/burn.d.ts.map +1 -0
- package/src/vaultFactory/burn.js +1 -1
- package/src/vaultFactory/liquidation.d.ts +25 -0
- package/src/vaultFactory/liquidation.d.ts.map +1 -0
- package/src/vaultFactory/liquidation.js +37 -24
- package/src/vaultFactory/math.d.ts +11 -0
- package/src/vaultFactory/math.d.ts.map +1 -0
- package/src/vaultFactory/math.js +11 -10
- package/src/vaultFactory/orderedVaultStore.d.ts +94 -0
- package/src/vaultFactory/orderedVaultStore.d.ts.map +1 -0
- package/src/vaultFactory/orderedVaultStore.js +9 -10
- package/src/vaultFactory/params.d.ts +143 -0
- package/src/vaultFactory/params.d.ts.map +1 -0
- package/src/vaultFactory/params.js +56 -25
- package/src/vaultFactory/prioritizedVaults.d.ts +280 -0
- package/src/vaultFactory/prioritizedVaults.d.ts.map +1 -0
- package/src/vaultFactory/prioritizedVaults.js +7 -4
- package/src/vaultFactory/proceeds.d.ts +35 -0
- package/src/vaultFactory/proceeds.d.ts.map +1 -0
- package/src/vaultFactory/proceeds.js +26 -18
- package/src/vaultFactory/storeUtils.d.ts +25 -0
- package/src/vaultFactory/storeUtils.d.ts.map +1 -0
- package/src/vaultFactory/storeUtils.js +10 -12
- package/src/vaultFactory/types-ambient.d.ts +137 -0
- package/src/vaultFactory/types-ambient.d.ts.map +1 -0
- package/src/vaultFactory/{types.js → types-ambient.js} +47 -44
- package/src/vaultFactory/vault.d.ts +344 -0
- package/src/vaultFactory/vault.d.ts.map +1 -0
- package/src/vaultFactory/vault.js +107 -100
- package/src/vaultFactory/vaultDirector.d.ts +347 -0
- package/src/vaultFactory/vaultDirector.d.ts.map +1 -0
- package/src/vaultFactory/vaultDirector.js +94 -64
- package/src/vaultFactory/vaultFactory.d.ts +250 -0
- package/src/vaultFactory/vaultFactory.d.ts.map +1 -0
- package/src/vaultFactory/vaultFactory.js +56 -33
- package/src/vaultFactory/vaultHolder.d.ts +170 -0
- package/src/vaultFactory/vaultHolder.d.ts.map +1 -0
- package/src/vaultFactory/vaultHolder.js +14 -15
- package/src/vaultFactory/vaultKit.d.ts +33 -0
- package/src/vaultFactory/vaultKit.d.ts.map +1 -0
- package/src/vaultFactory/vaultKit.js +9 -4
- package/src/vaultFactory/vaultManager.d.ts +676 -0
- package/src/vaultFactory/vaultManager.d.ts.map +1 -0
- package/src/vaultFactory/vaultManager.js +286 -167
- package/CHANGELOG.md +0 -1041
- package/exported.js +0 -2
- package/scripts/add-collateral-core.js +0 -112
- package/scripts/deploy-contracts.js +0 -100
- package/scripts/init-core.js +0 -198
- package/scripts/invite-committee-core.js +0 -42
- package/scripts/manual-price-feed.js +0 -117
- package/scripts/price-feed-core.js +0 -104
- package/scripts/start-local-chain.sh +0 -84
- package/src/psm/types.js +0 -3
- package/src/typeGuards.js +0 -13
- package/src/vaultFactory/type-imports.js +0 -4
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
/// <reference types="@agoric/internal/exported" />
|
|
2
|
+
/// <reference types="@agoric/governance/exported" />
|
|
3
|
+
/// <reference types="@agoric/zoe/exported" />
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { Fail } from '@endo/errors';
|
|
6
|
+
import { E } from '@endo/captp';
|
|
7
|
+
import { AmountMath, RatioShape } from '@agoric/ertp';
|
|
6
8
|
import { mustMatch } from '@agoric/store';
|
|
7
9
|
import { M, prepareExoClassKit } from '@agoric/vat-data';
|
|
8
10
|
|
|
9
11
|
import { assertAllDefined, makeTracer } from '@agoric/internal';
|
|
10
12
|
import {
|
|
11
|
-
atomicRearrange,
|
|
12
13
|
ceilMultiplyBy,
|
|
13
|
-
floorDivideBy,
|
|
14
14
|
makeRatioFromAmounts,
|
|
15
15
|
makeRecorderTopic,
|
|
16
16
|
multiplyRatios,
|
|
17
17
|
ratioGTE,
|
|
18
18
|
} from '@agoric/zoe/src/contractSupport/index.js';
|
|
19
|
-
import { E } from '@endo/captp';
|
|
20
19
|
import { observeNotifier } from '@agoric/notifier';
|
|
21
20
|
|
|
22
21
|
import { makeNatAmountShape } from '../contractSupport.js';
|
|
22
|
+
import { amountsToSettle } from './auctionMath.js';
|
|
23
23
|
import { preparePriceBook, prepareScaledBidBook } from './offerBook.js';
|
|
24
24
|
import {
|
|
25
25
|
isScaledBidPriceHigher,
|
|
@@ -27,41 +27,51 @@ import {
|
|
|
27
27
|
priceFrom,
|
|
28
28
|
} from './util.js';
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
/**
|
|
31
|
+
* @import {EReturn} from '@endo/far';
|
|
32
|
+
* @import {Baggage} from '@agoric/vat-data';
|
|
33
|
+
* @import {PriceAuthority} from '@agoric/zoe/tools/types.js';
|
|
34
|
+
* @import {TypedPattern} from '@agoric/internal';
|
|
35
|
+
*/
|
|
36
|
+
|
|
31
37
|
const { makeEmpty } = AmountMath;
|
|
32
38
|
|
|
33
|
-
const
|
|
39
|
+
const QUOTE_SCALE = 10n ** 9n;
|
|
34
40
|
|
|
35
41
|
/**
|
|
36
42
|
* @file The book represents the collateral-specific state of an ongoing
|
|
37
|
-
*
|
|
38
|
-
* the allocation of assets for sale.
|
|
43
|
+
* auction. It holds the book, the capturedPrice, and the collateralSeat that
|
|
44
|
+
* has the allocation of assets for sale.
|
|
45
|
+
*
|
|
46
|
+
* The book contains orders for the collateral. It holds two kinds of orders:
|
|
39
47
|
*
|
|
40
|
-
* The book contains orders for the collateral. It holds two kinds of
|
|
41
|
-
* orders:
|
|
42
48
|
* - Prices express the bidding offer in terms of a Bid amount
|
|
43
|
-
* - ScaledBids express the offer in terms of a discount (or markup) from the
|
|
44
|
-
*
|
|
49
|
+
* - ScaledBids express the offer in terms of a discount (or markup) from the most
|
|
50
|
+
* recent oracle price.
|
|
45
51
|
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
52
|
+
* Offers can be added in three ways. 1) When the auction is not active, prices
|
|
53
|
+
* are automatically added to the appropriate collection. When the auction is
|
|
54
|
+
* active, 2) if a new offer is at or above the current price, it will be
|
|
55
|
+
* settled immediately; 2) If the offer is below the current price, it will be
|
|
56
|
+
* added in the appropriate place and settled when the price reaches that
|
|
57
|
+
* level.
|
|
51
58
|
*/
|
|
52
59
|
|
|
53
60
|
const trace = makeTracer('AucBook', true);
|
|
54
61
|
|
|
55
62
|
/**
|
|
56
63
|
* @typedef {{
|
|
57
|
-
* maxBuy: Amount<'nat'
|
|
64
|
+
* maxBuy: Amount<'nat'>;
|
|
58
65
|
* } & {
|
|
59
|
-
* exitAfterBuy?: boolean
|
|
60
|
-
* } & (
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
66
|
+
* exitAfterBuy?: boolean;
|
|
67
|
+
* } & (
|
|
68
|
+
* | {
|
|
69
|
+
* offerPrice: Ratio;
|
|
70
|
+
* }
|
|
71
|
+
* | {
|
|
72
|
+
* offerBidScaling: Ratio;
|
|
73
|
+
* }
|
|
74
|
+
* )} OfferSpec
|
|
65
75
|
*/
|
|
66
76
|
/**
|
|
67
77
|
* @param {Brand<'nat'>} bidBrand
|
|
@@ -84,21 +94,21 @@ export const makeOfferSpecShape = (bidBrand, collateralBrand) => {
|
|
|
84
94
|
);
|
|
85
95
|
};
|
|
86
96
|
|
|
87
|
-
/** @typedef {import('@agoric/vat-data').Baggage} Baggage */
|
|
88
|
-
|
|
89
97
|
/**
|
|
90
98
|
* @typedef {object} BookDataNotification
|
|
91
|
-
*
|
|
92
|
-
* @property {Ratio
|
|
93
|
-
*
|
|
94
|
-
* @property {Amount<'nat'> | null}
|
|
95
|
-
*
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
* @property {Amount<'nat'>}
|
|
99
|
-
*
|
|
100
|
-
*
|
|
101
|
-
*
|
|
99
|
+
* @property {Ratio | null} startPrice identifies the priceAuthority and price
|
|
100
|
+
* @property {Ratio | null} currentPriceLevel the price at the current auction
|
|
101
|
+
* tier
|
|
102
|
+
* @property {Amount<'nat'> | null} startProceedsGoal The proceeds the sellers
|
|
103
|
+
* were targeting to raise
|
|
104
|
+
* @property {Amount<'nat'> | null} remainingProceedsGoal The remainder of the
|
|
105
|
+
* proceeds the sellers were targeting to raise
|
|
106
|
+
* @property {Amount<'nat'> | undefined} proceedsRaised The proceeds raised so
|
|
107
|
+
* far in the auction
|
|
108
|
+
* @property {Amount<'nat'>} startCollateral How much collateral was available
|
|
109
|
+
* for sale at the start. (If more is deposited later, it'll be added in.)
|
|
110
|
+
* @property {Amount<'nat'> | null} collateralAvailable The amount of collateral
|
|
111
|
+
* remaining
|
|
102
112
|
*/
|
|
103
113
|
|
|
104
114
|
/**
|
|
@@ -109,6 +119,8 @@ export const makeOfferSpecShape = (bidBrand, collateralBrand) => {
|
|
|
109
119
|
export const prepareAuctionBook = (baggage, zcf, makeRecorderKit) => {
|
|
110
120
|
const makeScaledBidBook = prepareScaledBidBook(baggage);
|
|
111
121
|
const makePriceBook = preparePriceBook(baggage);
|
|
122
|
+
// Brands that have or are making active quoteNotifier Observers
|
|
123
|
+
const observedBrands = new Set();
|
|
112
124
|
|
|
113
125
|
const AuctionBookStateShape = harden({
|
|
114
126
|
collateralBrand: M.any(),
|
|
@@ -118,7 +130,7 @@ export const prepareAuctionBook = (baggage, zcf, makeRecorderKit) => {
|
|
|
118
130
|
bidHoldingSeat: M.any(),
|
|
119
131
|
bidAmountShape: M.any(),
|
|
120
132
|
priceAuthority: M.any(),
|
|
121
|
-
updatingOracleQuote: M.
|
|
133
|
+
updatingOracleQuote: M.or(RatioShape, M.null()),
|
|
122
134
|
bookDataKit: M.any(),
|
|
123
135
|
priceBook: M.any(),
|
|
124
136
|
scaledBidBook: M.any(),
|
|
@@ -141,11 +153,6 @@ export const prepareAuctionBook = (baggage, zcf, makeRecorderKit) => {
|
|
|
141
153
|
*/
|
|
142
154
|
(bidBrand, collateralBrand, pAuthority, node) => {
|
|
143
155
|
assertAllDefined({ bidBrand, collateralBrand, pAuthority });
|
|
144
|
-
const zeroBid = makeEmpty(bidBrand);
|
|
145
|
-
const zeroRatio = makeRatioFromAmounts(
|
|
146
|
-
zeroBid,
|
|
147
|
-
AmountMath.make(collateralBrand, 1n),
|
|
148
|
-
);
|
|
149
156
|
|
|
150
157
|
// these don't have to be durable, since we're currently assuming that upgrade
|
|
151
158
|
// from a quiescent state is sufficient. When the auction is quiescent, there
|
|
@@ -168,9 +175,7 @@ export const prepareAuctionBook = (baggage, zcf, makeRecorderKit) => {
|
|
|
168
175
|
|
|
169
176
|
const bookDataKit = makeRecorderKit(
|
|
170
177
|
node,
|
|
171
|
-
/** @type {
|
|
172
|
-
M.any()
|
|
173
|
-
),
|
|
178
|
+
/** @type {TypedPattern<BookDataNotification>} */ (M.any()),
|
|
174
179
|
);
|
|
175
180
|
|
|
176
181
|
return {
|
|
@@ -182,7 +187,7 @@ export const prepareAuctionBook = (baggage, zcf, makeRecorderKit) => {
|
|
|
182
187
|
bidAmountShape,
|
|
183
188
|
|
|
184
189
|
priceAuthority: pAuthority,
|
|
185
|
-
updatingOracleQuote:
|
|
190
|
+
updatingOracleQuote: /** @type {Ratio | null} */ (null),
|
|
186
191
|
|
|
187
192
|
bookDataKit,
|
|
188
193
|
|
|
@@ -231,8 +236,8 @@ export const prepareAuctionBook = (baggage, zcf, makeRecorderKit) => {
|
|
|
231
236
|
{
|
|
232
237
|
helper: {
|
|
233
238
|
/**
|
|
234
|
-
* remove the key from the appropriate book, indicated by whether the
|
|
235
|
-
* is defined.
|
|
239
|
+
* remove the key from the appropriate book, indicated by whether the
|
|
240
|
+
* price is defined.
|
|
236
241
|
*
|
|
237
242
|
* @param {string} key
|
|
238
243
|
* @param {Ratio | undefined} price
|
|
@@ -247,8 +252,8 @@ export const prepareAuctionBook = (baggage, zcf, makeRecorderKit) => {
|
|
|
247
252
|
},
|
|
248
253
|
|
|
249
254
|
/**
|
|
250
|
-
* Update the entry in the appropriate book, indicated by whether the
|
|
251
|
-
* is defined.
|
|
255
|
+
* Update the entry in the appropriate book, indicated by whether the
|
|
256
|
+
* price is defined.
|
|
252
257
|
*
|
|
253
258
|
* @param {string} key
|
|
254
259
|
* @param {Amount} collateralSold
|
|
@@ -264,7 +269,8 @@ export const prepareAuctionBook = (baggage, zcf, makeRecorderKit) => {
|
|
|
264
269
|
},
|
|
265
270
|
|
|
266
271
|
/**
|
|
267
|
-
* Settle with seat. The caller is responsible for updating the book, if
|
|
272
|
+
* Settle with seat. The caller is responsible for updating the book, if
|
|
273
|
+
* any.
|
|
268
274
|
*
|
|
269
275
|
* @param {ZCFSeat} seat
|
|
270
276
|
* @param {Amount<'nat'>} collateralWanted
|
|
@@ -278,46 +284,36 @@ export const prepareAuctionBook = (baggage, zcf, makeRecorderKit) => {
|
|
|
278
284
|
return makeEmpty(collateralBrand);
|
|
279
285
|
}
|
|
280
286
|
|
|
281
|
-
/** @type {Amount<'nat'>} */
|
|
282
|
-
const initialCollateralTarget = AmountMath.min(
|
|
283
|
-
collateralWanted,
|
|
284
|
-
collateralAvailable,
|
|
285
|
-
);
|
|
286
|
-
|
|
287
287
|
const { curAuctionPrice, bidHoldingSeat, remainingProceedsGoal } =
|
|
288
288
|
this.state;
|
|
289
289
|
curAuctionPrice !== null ||
|
|
290
290
|
Fail`auctionPrice must be set before each round`;
|
|
291
291
|
assert(curAuctionPrice);
|
|
292
292
|
|
|
293
|
-
const
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
293
|
+
const { proceedsExpected, proceedsTarget, collateralTarget } =
|
|
294
|
+
amountsToSettle(
|
|
295
|
+
{
|
|
296
|
+
bidAlloc,
|
|
297
|
+
collateralWanted,
|
|
298
|
+
collateralAvailable,
|
|
299
|
+
curAuctionPrice,
|
|
300
|
+
remainingProceedsGoal,
|
|
301
|
+
},
|
|
302
|
+
trace,
|
|
303
|
+
);
|
|
304
|
+
|
|
305
|
+
if (proceedsExpected === null) {
|
|
298
306
|
seat.fail(Error('price fell to zero'));
|
|
299
307
|
return makeEmpty(collateralBrand);
|
|
300
308
|
}
|
|
301
309
|
|
|
302
|
-
|
|
303
|
-
const proceedsLimit = remainingProceedsGoal
|
|
304
|
-
? AmountMath.min(remainingProceedsGoal, minProceedsTarget)
|
|
305
|
-
: minProceedsTarget;
|
|
306
|
-
const isRaiseLimited =
|
|
307
|
-
remainingProceedsGoal ||
|
|
308
|
-
!AmountMath.isGTE(proceedsLimit, proceedsNeeded);
|
|
309
|
-
|
|
310
|
-
const [proceedsTarget, collateralTarget] = isRaiseLimited
|
|
311
|
-
? [proceedsLimit, floorDivideBy(proceedsLimit, curAuctionPrice)]
|
|
312
|
-
: [minProceedsTarget, initialCollateralTarget];
|
|
313
|
-
|
|
310
|
+
// check that the requested amount could be satisfied
|
|
314
311
|
const { Collateral } = seat.getProposal().want;
|
|
315
312
|
if (Collateral && AmountMath.isGTE(Collateral, collateralTarget)) {
|
|
316
313
|
seat.exit('unable to satisfy want');
|
|
317
314
|
}
|
|
318
315
|
|
|
319
|
-
atomicRearrange(
|
|
320
|
-
zcf,
|
|
316
|
+
zcf.atomicRearrange(
|
|
321
317
|
harden([
|
|
322
318
|
[collateralSeat, seat, { Collateral: collateralTarget }],
|
|
323
319
|
[seat, bidHoldingSeat, { Bid: proceedsTarget }],
|
|
@@ -331,7 +327,7 @@ export const prepareAuctionBook = (baggage, zcf, makeRecorderKit) => {
|
|
|
331
327
|
);
|
|
332
328
|
}
|
|
333
329
|
|
|
334
|
-
trace('
|
|
330
|
+
trace('settled', {
|
|
335
331
|
collateralTarget,
|
|
336
332
|
proceedsTarget,
|
|
337
333
|
remainingProceedsGoal: this.state.remainingProceedsGoal,
|
|
@@ -341,15 +337,16 @@ export const prepareAuctionBook = (baggage, zcf, makeRecorderKit) => {
|
|
|
341
337
|
},
|
|
342
338
|
|
|
343
339
|
/**
|
|
344
|
-
*
|
|
345
|
-
*
|
|
340
|
+
* Accept an offer expressed as a price. If the auction is active,
|
|
341
|
+
* attempt to buy collateral. If any of the offer remains add it to the
|
|
342
|
+
* book.
|
|
346
343
|
*
|
|
347
|
-
*
|
|
348
|
-
*
|
|
349
|
-
*
|
|
350
|
-
*
|
|
351
|
-
*
|
|
352
|
-
*
|
|
344
|
+
* @param {ZCFSeat} seat
|
|
345
|
+
* @param {Ratio} price
|
|
346
|
+
* @param {Amount<'nat'>} maxBuy
|
|
347
|
+
* @param {object} opts
|
|
348
|
+
* @param {boolean} opts.trySettle
|
|
349
|
+
* @param {boolean} [opts.exitAfterBuy]
|
|
353
350
|
*/
|
|
354
351
|
acceptPriceOffer(
|
|
355
352
|
seat,
|
|
@@ -388,16 +385,16 @@ export const prepareAuctionBook = (baggage, zcf, makeRecorderKit) => {
|
|
|
388
385
|
},
|
|
389
386
|
|
|
390
387
|
/**
|
|
391
|
-
*
|
|
392
|
-
*
|
|
393
|
-
*
|
|
388
|
+
* Accept an offer expressed as a discount (or markup). If the auction
|
|
389
|
+
* is active, attempt to buy collateral. If any of the offer remains add
|
|
390
|
+
* it to the book.
|
|
394
391
|
*
|
|
395
|
-
*
|
|
396
|
-
*
|
|
397
|
-
*
|
|
398
|
-
*
|
|
399
|
-
*
|
|
400
|
-
*
|
|
392
|
+
* @param {ZCFSeat} seat
|
|
393
|
+
* @param {Ratio} bidScaling
|
|
394
|
+
* @param {Amount<'nat'>} maxBuy
|
|
395
|
+
* @param {object} opts
|
|
396
|
+
* @param {boolean} opts.trySettle
|
|
397
|
+
* @param {boolean} [opts.exitAfterBuy]
|
|
401
398
|
*/
|
|
402
399
|
acceptScaledBidOffer(
|
|
403
400
|
seat,
|
|
@@ -460,16 +457,72 @@ export const prepareAuctionBook = (baggage, zcf, makeRecorderKit) => {
|
|
|
460
457
|
});
|
|
461
458
|
return state.bookDataKit.recorder.write(bookData);
|
|
462
459
|
},
|
|
460
|
+
// Ensure that there is an observer monitoring the quoteNotifier. We
|
|
461
|
+
// assume that all failure modes for quoteNotifier eventually lead to
|
|
462
|
+
// fail or finish.
|
|
463
|
+
ensureQuoteNotifierObserved() {
|
|
464
|
+
const { state, facets } = this;
|
|
465
|
+
const { collateralBrand, bidBrand, priceAuthority } = state;
|
|
466
|
+
|
|
467
|
+
if (observedBrands.has(collateralBrand)) {
|
|
468
|
+
return;
|
|
469
|
+
}
|
|
470
|
+
observedBrands.add(collateralBrand);
|
|
471
|
+
trace('observing');
|
|
472
|
+
|
|
473
|
+
const quoteNotifierP = E(priceAuthority).makeQuoteNotifier(
|
|
474
|
+
AmountMath.make(collateralBrand, QUOTE_SCALE),
|
|
475
|
+
bidBrand,
|
|
476
|
+
);
|
|
477
|
+
|
|
478
|
+
void E.when(
|
|
479
|
+
quoteNotifierP,
|
|
480
|
+
quoteNotifier =>
|
|
481
|
+
observeNotifier(quoteNotifier, {
|
|
482
|
+
updateState: quote => {
|
|
483
|
+
trace(
|
|
484
|
+
`BOOK notifier ${priceFrom(quote).numerator.value}/${
|
|
485
|
+
priceFrom(quote).denominator.value
|
|
486
|
+
}`,
|
|
487
|
+
);
|
|
488
|
+
state.updatingOracleQuote = priceFrom(quote);
|
|
489
|
+
},
|
|
490
|
+
fail: reason => {
|
|
491
|
+
trace(
|
|
492
|
+
`Failure from quoteNotifier (${reason}) setting to null`,
|
|
493
|
+
);
|
|
494
|
+
// lack of quote will trigger restart
|
|
495
|
+
state.updatingOracleQuote = null;
|
|
496
|
+
observedBrands.delete(collateralBrand);
|
|
497
|
+
},
|
|
498
|
+
finish: done => {
|
|
499
|
+
trace(
|
|
500
|
+
`quoteNotifier invoked finish(${done}). setting quote to null`,
|
|
501
|
+
);
|
|
502
|
+
// lack of quote will trigger restart
|
|
503
|
+
state.updatingOracleQuote = null;
|
|
504
|
+
observedBrands.delete(collateralBrand);
|
|
505
|
+
},
|
|
506
|
+
}),
|
|
507
|
+
e => {
|
|
508
|
+
trace('makeQuoteNotifier failed, resetting', e);
|
|
509
|
+
state.updatingOracleQuote = null;
|
|
510
|
+
observedBrands.delete(collateralBrand);
|
|
511
|
+
},
|
|
512
|
+
);
|
|
513
|
+
|
|
514
|
+
void facets.helper.publishBookData();
|
|
515
|
+
},
|
|
463
516
|
},
|
|
464
517
|
self: {
|
|
465
518
|
/**
|
|
466
519
|
* @param {Amount<'nat'>} assetAmount
|
|
467
520
|
* @param {ZCFSeat} sourceSeat
|
|
468
521
|
* @param {Amount<'nat'>} [proceedsGoal] an amount that the depositor
|
|
469
|
-
*
|
|
470
|
-
*
|
|
471
|
-
*
|
|
472
|
-
*
|
|
522
|
+
* would like to raise. The auction is requested to not sell more
|
|
523
|
+
* collateral than required to raise that much. The auctioneer might
|
|
524
|
+
* sell more if there is more than one supplier of collateral, and
|
|
525
|
+
* they request inconsistent limits.
|
|
473
526
|
*/
|
|
474
527
|
addAssets(assetAmount, sourceSeat, proceedsGoal) {
|
|
475
528
|
const { state, facets } = this;
|
|
@@ -531,8 +584,7 @@ export const prepareAuctionBook = (baggage, zcf, makeRecorderKit) => {
|
|
|
531
584
|
state.startProceedsGoal = nextProceedsGoal;
|
|
532
585
|
}
|
|
533
586
|
|
|
534
|
-
atomicRearrange(
|
|
535
|
-
zcf,
|
|
587
|
+
zcf.atomicRearrange(
|
|
536
588
|
harden([[sourceSeat, collateralSeat, { Collateral: assetAmount }]]),
|
|
537
589
|
);
|
|
538
590
|
|
|
@@ -547,9 +599,12 @@ export const prepareAuctionBook = (baggage, zcf, makeRecorderKit) => {
|
|
|
547
599
|
|
|
548
600
|
trace(this.state.collateralBrand, 'settleAtNewRate', reduction);
|
|
549
601
|
const { capturedPriceForRound, priceBook, scaledBidBook } = state;
|
|
550
|
-
capturedPriceForRound
|
|
551
|
-
|
|
552
|
-
|
|
602
|
+
if (!capturedPriceForRound) {
|
|
603
|
+
console.error(
|
|
604
|
+
`⚠️No price for ${this.state.collateralBrand}, skipping auction.`,
|
|
605
|
+
);
|
|
606
|
+
return;
|
|
607
|
+
}
|
|
553
608
|
|
|
554
609
|
state.curAuctionPrice = multiplyRatios(
|
|
555
610
|
reduction,
|
|
@@ -561,20 +616,14 @@ export const prepareAuctionBook = (baggage, zcf, makeRecorderKit) => {
|
|
|
561
616
|
const pricedOffers = priceBook.offersAbove(curAuctionPrice);
|
|
562
617
|
const scaledBidOffers = scaledBidBook.offersAbove(reduction);
|
|
563
618
|
|
|
564
|
-
const compareValues = (v1, v2) => {
|
|
565
|
-
if (v1 < v2) {
|
|
566
|
-
return -1;
|
|
567
|
-
} else if (v1 === v2) {
|
|
568
|
-
return 0;
|
|
569
|
-
} else {
|
|
570
|
-
return 1;
|
|
571
|
-
}
|
|
572
|
-
};
|
|
573
|
-
trace(`settling`, pricedOffers.length, scaledBidOffers.length);
|
|
574
619
|
// requested price or BidScaling gives no priority beyond specifying which
|
|
575
620
|
// round the order will be serviced in.
|
|
576
621
|
const prioritizedOffers = [...pricedOffers, ...scaledBidOffers].sort(
|
|
577
|
-
(a, b) =>
|
|
622
|
+
(a, b) => Number(a[1].seqNum - b[1].seqNum),
|
|
623
|
+
);
|
|
624
|
+
|
|
625
|
+
trace(
|
|
626
|
+
`settling ${prioritizedOffers.length} offers at ${curAuctionPrice} (priced ${pricedOffers.length}, scaled ${scaledBidOffers.length}) `,
|
|
578
627
|
);
|
|
579
628
|
|
|
580
629
|
const { remainingProceedsGoal } = state;
|
|
@@ -619,6 +668,13 @@ export const prepareAuctionBook = (baggage, zcf, makeRecorderKit) => {
|
|
|
619
668
|
const { facets, state } = this;
|
|
620
669
|
|
|
621
670
|
trace(`capturing oracle price `, state.updatingOracleQuote);
|
|
671
|
+
if (!state.updatingOracleQuote) {
|
|
672
|
+
// if the price feed has died (or hasn't been started for this
|
|
673
|
+
// incarnation), (re)start it.
|
|
674
|
+
facets.helper.ensureQuoteNotifierObserved();
|
|
675
|
+
return;
|
|
676
|
+
}
|
|
677
|
+
|
|
622
678
|
state.capturedPriceForRound = state.updatingOracleQuote;
|
|
623
679
|
void facets.helper.publishBookData();
|
|
624
680
|
},
|
|
@@ -718,46 +774,21 @@ export const prepareAuctionBook = (baggage, zcf, makeRecorderKit) => {
|
|
|
718
774
|
finish: ({ state, facets }) => {
|
|
719
775
|
const { collateralBrand, bidBrand, priceAuthority } = state;
|
|
720
776
|
assertAllDefined({ collateralBrand, bidBrand, priceAuthority });
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
({ decimalPlaces = DEFAULT_DECIMALS }) => {
|
|
724
|
-
// TODO(#6946) use this to keep a current price that can be published in state.
|
|
725
|
-
const quoteNotifier = E(priceAuthority).makeQuoteNotifier(
|
|
726
|
-
AmountMath.make(collateralBrand, 10n ** BigInt(decimalPlaces)),
|
|
727
|
-
bidBrand,
|
|
728
|
-
);
|
|
729
|
-
void observeNotifier(quoteNotifier, {
|
|
730
|
-
updateState: quote => {
|
|
731
|
-
trace(
|
|
732
|
-
`BOOK notifier ${priceFrom(quote).numerator.value}/${
|
|
733
|
-
priceFrom(quote).denominator.value
|
|
734
|
-
}`,
|
|
735
|
-
);
|
|
736
|
-
state.updatingOracleQuote = priceFrom(quote);
|
|
737
|
-
},
|
|
738
|
-
fail: reason => {
|
|
739
|
-
throw Error(
|
|
740
|
-
`auction observer of ${collateralBrand} failed: ${reason}`,
|
|
741
|
-
);
|
|
742
|
-
},
|
|
743
|
-
finish: done => {
|
|
744
|
-
throw Error(
|
|
745
|
-
`auction observer for ${collateralBrand} died: ${done}`,
|
|
746
|
-
);
|
|
747
|
-
},
|
|
748
|
-
});
|
|
749
|
-
},
|
|
750
|
-
);
|
|
751
|
-
void facets.helper.publishBookData();
|
|
777
|
+
|
|
778
|
+
facets.helper.ensureQuoteNotifierObserved();
|
|
752
779
|
},
|
|
753
780
|
stateShape: AuctionBookStateShape,
|
|
754
781
|
},
|
|
755
782
|
);
|
|
756
783
|
|
|
757
|
-
/**
|
|
784
|
+
/**
|
|
785
|
+
* @type {(
|
|
786
|
+
* ...args: Parameters<typeof makeAuctionBookKit>
|
|
787
|
+
* ) => ReturnType<typeof makeAuctionBookKit>['self']}
|
|
788
|
+
*/
|
|
758
789
|
const makeAuctionBook = (...args) => makeAuctionBookKit(...args).self;
|
|
759
790
|
return makeAuctionBook;
|
|
760
791
|
};
|
|
761
792
|
harden(prepareAuctionBook);
|
|
762
793
|
|
|
763
|
-
/** @typedef {
|
|
794
|
+
/** @typedef {EReturn<EReturn<typeof prepareAuctionBook>>} AuctionBook */
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export function amountsToSettle({ bidAlloc, collateralWanted, collateralAvailable, curAuctionPrice, remainingProceedsGoal, }: {
|
|
2
|
+
bidAlloc: Amount<"nat">;
|
|
3
|
+
collateralWanted: Amount<"nat">;
|
|
4
|
+
collateralAvailable: Amount<"nat">;
|
|
5
|
+
curAuctionPrice: Ratio;
|
|
6
|
+
remainingProceedsGoal: Amount<"nat"> | null;
|
|
7
|
+
}, log?: (...msgs: any[]) => void): {
|
|
8
|
+
proceedsExpected: null;
|
|
9
|
+
proceedsTarget?: undefined;
|
|
10
|
+
collateralTarget?: undefined;
|
|
11
|
+
} | {
|
|
12
|
+
proceedsExpected: import("@agoric/ertp").NatAmount;
|
|
13
|
+
proceedsTarget: import("@agoric/ertp").NatAmount;
|
|
14
|
+
collateralTarget: import("@agoric/ertp").NatAmount;
|
|
15
|
+
};
|
|
16
|
+
import type { Amount } from '@agoric/ertp/src/types.js';
|
|
17
|
+
//# sourceMappingURL=auctionMath.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auctionMath.d.ts","sourceRoot":"","sources":["auctionMath.js"],"names":[],"mappings":"AAoBO,8HARJ;IAAyB,QAAQ,EAAzB,OAAO,KAAK,CAAC;IACI,gBAAgB,EAAjC,OAAO,KAAK,CAAC;IACI,mBAAmB,EAApC,OAAO,KAAK,CAAC;IACJ,eAAe,EAAxB,KAAK;IACmB,qBAAqB,EAA7C,OAAO,KAAK,CAAC,GAAG,IAAI;CAE5B,QAAQ,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI;;;;;;;;EA6DlC;4BAxEwB,2BAA2B"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { AmountMath } from '@agoric/ertp';
|
|
2
|
+
import {
|
|
3
|
+
ceilMultiplyBy,
|
|
4
|
+
floorDivideBy,
|
|
5
|
+
} from '@agoric/zoe/src/contractSupport/index.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @import {Amount} from '@agoric/ertp/src/types.js';
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @param {object} p
|
|
13
|
+
* @param {Amount<'nat'>} p.bidAlloc current allocation of the bidding seat
|
|
14
|
+
* @param {Amount<'nat'>} p.collateralWanted want of the offer
|
|
15
|
+
* @param {Amount<'nat'>} p.collateralAvailable available to auction
|
|
16
|
+
* @param {Ratio} p.curAuctionPrice current auction price
|
|
17
|
+
* @param {Amount<'nat'> | null} p.remainingProceedsGoal amount still needing
|
|
18
|
+
* liquidating over multiple rounds; null indicates no limit
|
|
19
|
+
* @param {(...msgs: any[]) => void} [log]
|
|
20
|
+
*/
|
|
21
|
+
export const amountsToSettle = (
|
|
22
|
+
{
|
|
23
|
+
bidAlloc,
|
|
24
|
+
collateralWanted,
|
|
25
|
+
collateralAvailable,
|
|
26
|
+
curAuctionPrice,
|
|
27
|
+
remainingProceedsGoal,
|
|
28
|
+
},
|
|
29
|
+
log = () => {},
|
|
30
|
+
) => {
|
|
31
|
+
log('amountsToSettle', {
|
|
32
|
+
bidAlloc,
|
|
33
|
+
collateralWanted,
|
|
34
|
+
collateralAvailable,
|
|
35
|
+
curAuctionPrice,
|
|
36
|
+
remainingProceedsGoal,
|
|
37
|
+
});
|
|
38
|
+
const initialCollateralTarget = AmountMath.min(
|
|
39
|
+
collateralWanted,
|
|
40
|
+
collateralAvailable,
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
const proceedsExpected = ceilMultiplyBy(
|
|
44
|
+
initialCollateralTarget,
|
|
45
|
+
curAuctionPrice,
|
|
46
|
+
);
|
|
47
|
+
if (AmountMath.isEmpty(proceedsExpected)) {
|
|
48
|
+
return { proceedsExpected: null };
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const targetByProceeds = proceedsLimit =>
|
|
52
|
+
AmountMath.min(
|
|
53
|
+
collateralAvailable,
|
|
54
|
+
floorDivideBy(proceedsLimit, curAuctionPrice),
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
const [proceedsTarget, collateralTarget] = (() => {
|
|
58
|
+
// proceeds cannot exceed what is needed or being offered
|
|
59
|
+
const proceedsBidded = AmountMath.min(proceedsExpected, bidAlloc);
|
|
60
|
+
if (remainingProceedsGoal) {
|
|
61
|
+
const goalProceeds = AmountMath.min(
|
|
62
|
+
remainingProceedsGoal,
|
|
63
|
+
proceedsBidded,
|
|
64
|
+
);
|
|
65
|
+
return [goalProceeds, targetByProceeds(goalProceeds)];
|
|
66
|
+
} else if (AmountMath.isGTE(proceedsBidded, proceedsExpected)) {
|
|
67
|
+
// initial collateral suffices
|
|
68
|
+
return [proceedsBidded, initialCollateralTarget];
|
|
69
|
+
} else {
|
|
70
|
+
return [proceedsBidded, targetByProceeds(proceedsBidded)];
|
|
71
|
+
}
|
|
72
|
+
})();
|
|
73
|
+
|
|
74
|
+
assert(
|
|
75
|
+
AmountMath.isGTE(collateralAvailable, collateralTarget),
|
|
76
|
+
'target cannot exceed available',
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
return { proceedsExpected, proceedsTarget, collateralTarget };
|
|
80
|
+
};
|
|
81
|
+
harden(amountsToSettle);
|