@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
@@ -1,155 +0,0 @@
1
- // @ts-check
2
-
3
- import { natSafeMath } from '@agoric/zoe/src/contractSupport/index.js';
4
- import { AmountMath } from '@agoric/ertp';
5
- import { BASIS_POINTS } from './constantProduct/defaults.js';
6
-
7
- /**
8
- * @file support the UI in calculating how much to offer, taking slippage
9
- * into account, and not requiring a round trip to the chain.
10
- */
11
-
12
- const { ceilDivide, floorDivide } = natSafeMath;
13
-
14
- export const charge = (chargeBP, amount) => {
15
- return AmountMath.make(
16
- amount.brand,
17
- ceilDivide(amount.value * chargeBP, BASIS_POINTS),
18
- );
19
- };
20
-
21
- export const chargeFloor = (chargeBP, amount) => {
22
- return AmountMath.make(
23
- amount.brand,
24
- floorDivide(amount.value * chargeBP, BASIS_POINTS),
25
- );
26
- };
27
-
28
- const makeEstimator = (centralBrand, rates) => {
29
- const { poolFeeBP, protocolFeeBP, slippageBP } = rates;
30
-
31
- // Proceeds less slippage when specifying the amount to add to a single pool
32
- function estimateSinglePoolProceeds(amountIn, brandOut, pools) {
33
- const isCentralIn = amountIn.brand === centralBrand;
34
- const pool = isCentralIn ? pools.get(brandOut) : pools.get(amountIn.brand);
35
- const kPre = pool.secondaryAmount.value * pool.centralAmount.value;
36
-
37
- function calcYFromX(X) {
38
- const denom = isCentralIn
39
- ? AmountMath.add(pool.centralAmount, X)
40
- : AmountMath.add(pool.secondaryAmount, X);
41
- const finalOutBalance = AmountMath.make(
42
- brandOut,
43
- ceilDivide(kPre, denom.value),
44
- );
45
-
46
- return isCentralIn
47
- ? AmountMath.subtract(pool.secondaryAmount, finalOutBalance)
48
- : AmountMath.subtract(pool.centralAmount, finalOutBalance);
49
- }
50
-
51
- const amountAdded = isCentralIn
52
- ? AmountMath.subtract(amountIn, charge(protocolFeeBP, amountIn))
53
- : amountIn;
54
- const amountOutForFees = calcYFromX(amountIn);
55
- const amountOut = calcYFromX(amountAdded);
56
- const amountRemoved = AmountMath.subtract(
57
- amountOut,
58
- charge(poolFeeBP, amountOutForFees),
59
- );
60
- const amountReturned = isCentralIn
61
- ? amountRemoved
62
- : AmountMath.subtract(
63
- amountRemoved,
64
- charge(protocolFeeBP, amountOutForFees),
65
- );
66
-
67
- return amountReturned;
68
- }
69
-
70
- // Payment w/slippage when specifying the amount to receive from a single pool
71
- function estimateSinglePoolRequired(brandIn, amountOut, pools) {
72
- const isCentralIn = brandIn === centralBrand;
73
- const pool = isCentralIn ? pools.get(amountOut.brand) : pools.get(brandIn);
74
- const kPre = pool.secondaryAmount.value * pool.centralAmount.value;
75
- const amountWithdrawn = isCentralIn
76
- ? AmountMath.add(amountOut, charge(protocolFeeBP, amountOut))
77
- : amountOut;
78
-
79
- const calcXFromY = y => {
80
- const denom = isCentralIn
81
- ? AmountMath.subtract(pool.secondaryAmount, y)
82
- : AmountMath.subtract(pool.centralAmount, y);
83
- const finalInBalance = AmountMath.make(
84
- brandIn,
85
- ceilDivide(kPre, denom.value),
86
- );
87
- return isCentralIn
88
- ? AmountMath.subtract(finalInBalance, pool.centralAmount)
89
- : AmountMath.subtract(finalInBalance, pool.secondaryAmount);
90
- };
91
-
92
- const amountInForFees = calcXFromY(amountOut);
93
- const amountIn = calcXFromY(amountWithdrawn);
94
- const amountAddToPool = AmountMath.add(
95
- amountIn,
96
- charge(poolFeeBP, amountInForFees),
97
- );
98
- const amountToBePaid = isCentralIn
99
- ? amountAddToPool
100
- : AmountMath.add(
101
- amountAddToPool,
102
- chargeFloor(protocolFeeBP, amountInForFees),
103
- );
104
-
105
- return amountToBePaid;
106
- }
107
-
108
- // ignores price improvement
109
- function estimateDoublePoolProceeds(amountIn, brandOut, pools) {
110
- const inProceeds = estimateSinglePoolProceeds(
111
- amountIn,
112
- centralBrand,
113
- pools,
114
- );
115
- const outProceeds = estimateSinglePoolProceeds(inProceeds, brandOut, pools);
116
- return outProceeds;
117
- }
118
-
119
- // ignores price improvement
120
- function estimateDoublePoolRequired(brandIn, amountOut, pools) {
121
- const outRequired = estimateSinglePoolRequired(
122
- centralBrand,
123
- amountOut,
124
- pools,
125
- );
126
- const inRequired = estimateSinglePoolRequired(brandIn, outRequired, pools);
127
- return inRequired;
128
- }
129
-
130
- const estimateProceeds = (amountIn, brandOut, pools) => {
131
- let proceeds;
132
- if (amountIn.brand === centralBrand || brandOut === centralBrand) {
133
- proceeds = estimateSinglePoolProceeds(amountIn, brandOut, pools);
134
- } else {
135
- proceeds = estimateDoublePoolProceeds(amountIn, brandOut, pools);
136
- }
137
- return AmountMath.subtract(proceeds, charge(slippageBP, proceeds));
138
- };
139
-
140
- const estimateRequired = (brandIn, amountOut, pools) => {
141
- let required;
142
- if (brandIn === centralBrand || amountOut.brand === centralBrand) {
143
- required = estimateSinglePoolRequired(brandIn, amountOut, pools);
144
- } else {
145
- required = estimateDoublePoolRequired(brandIn, amountOut, pools);
146
- }
147
-
148
- return AmountMath.add(required, charge(slippageBP, required));
149
- };
150
-
151
- return { estimateProceeds, estimateRequired };
152
- };
153
- harden(makeEstimator);
154
-
155
- export { makeEstimator };
@@ -1,520 +0,0 @@
1
- // @ts-check
2
-
3
- import '@agoric/zoe/exported.js';
4
-
5
- import { AssetKind, makeIssuerKit } from '@agoric/ertp';
6
- import { handleParamGovernance, ParamTypes } from '@agoric/governance';
7
- import { makeAtomicProvider } from '@agoric/store/src/stores/store-utils.js';
8
- import {
9
- assertIssuerKeywords,
10
- offerTo,
11
- } from '@agoric/zoe/src/contractSupport/index.js';
12
- import { E } from '@endo/far';
13
- import { Far } from '@endo/marshal';
14
- import { initEmpty } from '@agoric/store';
15
- import {
16
- provideDurableMapStore,
17
- provideDurableWeakMapStore,
18
- provide,
19
- vivifyKindMulti,
20
- } from '@agoric/vat-data';
21
- import { makeMakeCollectFeesInvitation } from '../collectFees.js';
22
- import { makeMetricsPublisherKit } from '../contractSupport.js';
23
- import { makeTracer } from '../makeTracer.js';
24
- import {
25
- makeMakeAddLiquidityAtRateInvitation,
26
- makeMakeAddLiquidityInvitation,
27
- } from './addLiquidity.js';
28
- import { makeAddIssuer, makeAddPoolInvitation } from './addPool.js';
29
- import { makeDoublePool } from './doublePool.js';
30
- import {
31
- MIN_INITIAL_POOL_LIQUIDITY_KEY,
32
- POOL_FEE_KEY,
33
- PROTOCOL_FEE_KEY,
34
- } from './params.js';
35
- import { publicPrices } from './pool.js';
36
- import { makeMakeRemoveLiquidityInvitation } from './removeLiquidity.js';
37
- import { makeMakeSwapInvitation } from './swap.js';
38
-
39
- import '@agoric/governance/src/exported.js';
40
-
41
- const { quote: q, details: X } = assert;
42
-
43
- const trace = makeTracer('XykAmm', false);
44
-
45
- /**
46
- * @typedef {object} MetricsNotification
47
- * @property {Brand[]} XYK brands of pools that use an X*Y=K pricing policy
48
- */
49
-
50
- /** @typedef {GovernanceTerms< {MinInitialPoolLiquidity: 'amount'} & {ProtocolFee: 'amount'} & {PoolFee: 'amount'}>} AmmGovernanceParams */
51
-
52
- /** @typedef {{brands:BrandKeywordRecord,timer:TimerService}} AmmTerms */
53
-
54
- /**
55
- * @typedef {Readonly<{
56
- * zcf: ZCF<AmmTerms>,
57
- * secondaryBrandToPool: WeakMapStore<Brand,PoolFacets>,
58
- * secondaryBrandToLiquidityMint: WeakMapStore<Brand,ZCFMint<'nat'>>,
59
- * centralBrand: Brand,
60
- * timer: TimerService,
61
- * quoteIssuerKit: IssuerKit,
62
- * params: import('@agoric/governance/src/contractGovernance/typedParamManager').Getters<import('./params.js').AmmParams>,
63
- * protocolSeat: ZCFSeat,
64
- * }>} AmmPowers
65
- */
66
-
67
- // All the state at the AMM level is shared lexically. Some functions here have
68
- // to ignore their first parameter since they have other parameters and are
69
- // included in virtual/durable facets.
70
- /** @typedef {{}} MethodContext */
71
-
72
- /** @typedef {import('@agoric/vat-data').Baggage} Baggage */
73
-
74
- /**
75
- * Multipool AMM is a rewrite of Uniswap that supports multiple liquidity pools,
76
- * and direct exchanges across pools. Please see the documentation for more:
77
- * https://agoric.com/documentation/zoe/guide/contracts/multipoolAMM.html It
78
- * also uses a unique approach to charging fees. Each pool grows on every trade,
79
- * and a protocolFee is extracted.
80
- *
81
- * We expect that this contract will have tens to hundreds of issuers. Each
82
- * liquidity pool is between the central token and a secondary token. Secondary
83
- * tokens can be exchanged with each other, but only through the central
84
- * token. For example, if X and Y are two token types and C is the central
85
- * token, a swap giving X and wanting Y would first use the pool (X, C) then the
86
- * pool (Y, C). There are no liquidity pools directly between two secondary
87
- * tokens.
88
- *
89
- * There should only need to be one instance of this contract, so liquidity can
90
- * be shared as much as possible.
91
- *
92
- * When the contract is instantiated, the central token is specified in the
93
- * terms. Separate invitations are available by calling methods on the
94
- * publicFacet for adding and removing liquidity and for making trades. Other
95
- * publicFacet operations support querying prices and the sizes of pools. New
96
- * Pools can be created by first calling addIssuer() and then exercising an
97
- * invitation from addPoolInvitation().
98
- *
99
- * When making trades or requesting prices, the caller must specify either a
100
- * maximum input amount (swapIn, getInputPrice) or a minimum output amount
101
- * (swapOut, getOutPutPrice) or both. For swaps, the required keywords are `In`
102
- * for the trader's `give` amount, and `Out` for the trader's `want` amount.
103
- * getInputPrice and getOutputPrice each take two Amounts. The price functions
104
- * return both amountIn (which may be lower than the original amount) and
105
- * amountOut (which may be higher). When both prices are specified, no swap will
106
- * be made (and no price provided) if both restrictions can't be honored.
107
- *
108
- * When adding and removing liquidity, the keywords are Central, Secondary, and
109
- * Liquidity. adding liquidity has Central and Secondary in the `give` section,
110
- * while removing liquidity has `want` and `give` swapped.
111
- *
112
- * Transactions that don't require an invitation include addPool and the
113
- * queries: getInputPrice, getOutputPrice, getPoolAllocation,
114
- * getLiquidityIssuer, and getLiquiditySupply.
115
- *
116
- * This contract has two parameters (poolFee and protocolFee) that are
117
- * managed by governance. The contract calls `handleParamGovernance()` at
118
- * startup, which allows a contractManager to call for votes that would change
119
- * the parameter values in a transparent way. When correctly set up, customers
120
- * with access to this contract's publicFacet can verify the connectivity, and
121
- * see which Electorate has the ability to vote on changes, and which votes are
122
- * ongoing or have taken place. If not correctly set up, the validation checks
123
- * will fail visibly.
124
- *
125
- * The initial values of the parameters are provided as poolFeeBP and
126
- * protocolFeeBP in terms. The poolFee is charged in {Central} and each collateral, so
127
- * it is provided as a bigint. The protocolFee is always charged in {Fee}, but the
128
- * initial value is specified as a bigint for consistency.
129
- *
130
- * The contract gets the initial values for those parameters from its terms, and
131
- * thereafter can be seen to only use the values provided by the
132
- * getter method returned by the paramManager.
133
- *
134
- * `handleParamGovernance()` adds several methods to the publicFacet of the
135
- * contract, and bundles the privateFacet to ensure that governance
136
- * functionality is only accessible to the contractGovernor.
137
- *
138
- * The creatorFacet has one method (makeCollectFeesInvitation, which returns
139
- * collected fees to the creator). `handleParamGovernance()` adds internal
140
- * methods used by the contractGovernor. The contractGovernor then has access to
141
- * those internal methods, and reveals the original AMM creatorFacet to its own
142
- * creator.
143
- *
144
- * @param {ZCF<AMMTerms>} zcf
145
- * @param {{
146
- * initialPoserInvitation: Invitation,
147
- * storageNode: ERef<StorageNode>,
148
- * marshaller: ERef<Marshaller>,
149
- * }} privateArgs
150
- * @param {Baggage} baggage
151
- */
152
- const start = async (zcf, privateArgs, baggage) => {
153
- /**
154
- * This contract must have a "Central" keyword and issuer in the
155
- * IssuerKeywordRecord.
156
- */
157
- const {
158
- brands: { Central: centralBrand },
159
- timer,
160
- } = zcf.getTerms();
161
- assertIssuerKeywords(zcf, ['Central']);
162
- assert(centralBrand !== undefined, 'centralBrand must be present');
163
-
164
- const [
165
- { augmentVirtualPublicFacet, makeVirtualGovernorFacet, params },
166
- centralDisplayInfo,
167
- ] = await Promise.all([
168
- handleParamGovernance(
169
- zcf,
170
- privateArgs.initialPoserInvitation,
171
- {
172
- [POOL_FEE_KEY]: ParamTypes.NAT,
173
- [PROTOCOL_FEE_KEY]: ParamTypes.NAT,
174
- [MIN_INITIAL_POOL_LIQUIDITY_KEY]: ParamTypes.AMOUNT,
175
- },
176
- privateArgs.storageNode,
177
- privateArgs.marshaller,
178
- ),
179
- E(centralBrand).getDisplayInfo(),
180
- privateArgs.storageNode,
181
- privateArgs.marshaller,
182
- ]);
183
-
184
- assert.equal(
185
- centralDisplayInfo.assetKind,
186
- AssetKind.NAT,
187
- X`Central must be of kind ${q(AssetKind.NAT)}, not ${q(
188
- centralDisplayInfo.assetKind,
189
- )}`,
190
- );
191
-
192
- /** @type {Store<Brand,PoolFacets>} */
193
- const secondaryBrandToPool = provideDurableMapStore(
194
- baggage,
195
- 'secondaryBrandToPool',
196
- );
197
- const getPool = brand => {
198
- // TODO: https://github.com/Agoric/agoric-sdk/issues/5776
199
- assert(
200
- secondaryBrandToPool.has(brand),
201
- `"secondaryBrandToPool" not found: ${q(brand)}`,
202
- );
203
- return secondaryBrandToPool.get(brand).pool;
204
- };
205
- const getPoolHelper = brand => secondaryBrandToPool.get(brand).helper;
206
- // XXX a brand can be in secondaryBrandToLiquidityMint and return false for this check
207
- // if it's called between addIssuer and addPool
208
- const isSecondary = secondaryBrandToPool.has;
209
-
210
- // The liquidityBrand has to exist to allow the addPool Offer to specify want
211
- /** @type {WeakMapStore<Brand,ZCFMint<'nat'>>} */
212
- const secondaryBrandToLiquidityMint = provideDurableWeakMapStore(
213
- baggage,
214
- 'secondaryBrandToLiquidityMint',
215
- );
216
- const secondaryBrandToLiquidityMintProvider = makeAtomicProvider(
217
- secondaryBrandToLiquidityMint,
218
- );
219
-
220
- const quoteIssuerKit = provide(baggage, 'quoteIssuerKit', () =>
221
- makeIssuerKit('Quote', AssetKind.SET),
222
- );
223
-
224
- const { metricsPublication, metricsSubscription } = makeMetricsPublisherKit(
225
- privateArgs.storageNode,
226
- privateArgs.marshaller,
227
- );
228
- const updateMetrics = () => {
229
- metricsPublication.updateState(
230
- harden({ XYK: Array.from(secondaryBrandToPool.keys()) }),
231
- );
232
- };
233
- updateMetrics();
234
-
235
- // For now, this seat collects protocol fees. It needs to be connected to
236
- // something that will extract the fees.
237
- const protocolSeat = provide(
238
- baggage,
239
- 'protocolSeat',
240
- () => zcf.makeEmptySeatKit().zcfSeat,
241
- );
242
-
243
- /** @type {AssetReservePublicFacet=} */
244
- let reserveFacet = baggage.has('reserveFacet')
245
- ? baggage.get('reserveFacet')
246
- : undefined;
247
-
248
- /**
249
- * @param {Brand} secondaryBrand
250
- * @param {ZCFSeat} reserveLiquidityTokenSeat
251
- * @param {Keyword} liquidityKeyword
252
- * @returns {Promise<void>} up to caller whether to await or handle rejections
253
- */
254
- const handlePoolAdded = async (
255
- secondaryBrand,
256
- reserveLiquidityTokenSeat,
257
- liquidityKeyword,
258
- ) => {
259
- trace('handlePoolAdded', { secondaryBrand, liquidityKeyword });
260
- updateMetrics();
261
-
262
- assert(reserveFacet, 'Missing reserveFacet');
263
- assert(reserveLiquidityTokenSeat, 'Missing reserveLiquidityTokenSeat');
264
-
265
- const secondaryIssuer = await zcf.getIssuerForBrand(secondaryBrand);
266
- trace('ensuring reserve has the liquidity issuer', {
267
- secondaryBrand,
268
- secondaryIssuer,
269
- });
270
- await E(reserveFacet).addLiquidityIssuer(secondaryIssuer);
271
-
272
- trace(
273
- `move ${liquidityKeyword} to the reserve`,
274
- reserveLiquidityTokenSeat.getCurrentAllocation(),
275
- );
276
- const addCollateral = await E(reserveFacet).makeAddCollateralInvitation();
277
- const proposal = harden({
278
- give: {
279
- Collateral:
280
- reserveLiquidityTokenSeat.getCurrentAllocation()[liquidityKeyword],
281
- },
282
- });
283
- const { deposited, userSeatPromise } = await offerTo(
284
- zcf,
285
- addCollateral,
286
- harden({ [liquidityKeyword]: 'Collateral' }),
287
- proposal,
288
- reserveLiquidityTokenSeat,
289
- );
290
- const deposits = await deposited;
291
- trace('handlePoolAdded deposited', deposits);
292
- await E(userSeatPromise).getOfferResult();
293
- reserveLiquidityTokenSeat.exit();
294
- trace('handlePoolAdded done');
295
- };
296
-
297
- /**
298
- * @param {MethodContext} _context
299
- * @param {Brand} brand
300
- */
301
- const getLiquidityIssuer = (_context, brand) =>
302
- secondaryBrandToLiquidityMint.get(brand).getIssuerRecord().issuer;
303
- /**
304
- * @param {MethodContext} _context
305
- * @param {Brand} brand
306
- */
307
- const getLiquiditySupply = (_context, brand) =>
308
- getPool(brand).getLiquiditySupply();
309
-
310
- /**
311
- * @param {MethodContext} _context
312
- * @param {Brand} brand
313
- */
314
- const getSecondaryIssuer = (_context, brand) => {
315
- assert(
316
- secondaryBrandToLiquidityMint.has(brand),
317
- 'Brand not a secondary of the AMM',
318
- );
319
- return zcf.getIssuerForBrand(brand);
320
- };
321
- const poolStorageNode = await (privateArgs.storageNode &&
322
- E(privateArgs.storageNode).makeChildNode(
323
- // NB: the set of pools grows monotonically
324
- `pool${secondaryBrandToPool.getSize()}`,
325
- ));
326
-
327
- // shared AMM state that will be lexically accessible to all pools
328
- /** @type {AmmPowers} */
329
- const ammPowers = harden({
330
- zcf,
331
- secondaryBrandToPool,
332
- secondaryBrandToLiquidityMint,
333
- centralBrand,
334
- timer,
335
- quoteIssuerKit,
336
- params,
337
- protocolSeat,
338
- });
339
- const addPoolInvitation = makeAddPoolInvitation(
340
- baggage,
341
- ammPowers,
342
- handlePoolAdded,
343
- poolStorageNode,
344
- privateArgs.marshaller,
345
- );
346
- const addIssuer = makeAddIssuer(
347
- zcf,
348
- isSecondary,
349
- secondaryBrandToLiquidityMintProvider,
350
- () => {
351
- assert(reserveFacet, 'Must first resolveReserveFacet');
352
- return secondaryBrand =>
353
- E(
354
- /** @type {AssetReservePublicFacet} */ (reserveFacet),
355
- ).addIssuerFromAmm(secondaryBrand);
356
- },
357
- );
358
-
359
- /**
360
- * @param {unknown} _context
361
- * @param {Brand} brand
362
- */
363
- const getPoolAllocation = (_context, brand) =>
364
- getPool(brand).getPoolSeat().getCurrentAllocation();
365
-
366
- const getPriceAuthorities = (_context, brand) => {
367
- const pool = getPool(brand);
368
- return {
369
- toCentral: pool.getToCentralPriceAuthority(),
370
- fromCentral: pool.getFromCentralPriceAuthority(),
371
- };
372
- };
373
-
374
- /**
375
- * @param {MethodContext} _context
376
- * @param {Brand} brand
377
- */
378
- const getPoolMetrics = (_context, brand) => getPool(brand).getMetrics();
379
-
380
- /**
381
- * @param {Brand} brandIn
382
- * @param {Brand} [brandOut]
383
- * @returns {VirtualPool}
384
- */
385
- const provideVPool = (brandIn, brandOut) => {
386
- if (!brandOut) {
387
- return getPool(brandIn).getVPool();
388
- }
389
-
390
- if (isSecondary(brandIn) && isSecondary(brandOut)) {
391
- return makeDoublePool(
392
- zcf,
393
- getPool(brandIn),
394
- getPool(brandOut),
395
- params.getProtocolFee,
396
- params.getPoolFee,
397
- protocolSeat,
398
- );
399
- }
400
-
401
- const pool = isSecondary(brandOut) ? getPool(brandOut) : getPool(brandIn);
402
- return pool.getVPool();
403
- };
404
-
405
- const getInputPrice = (_context, amountIn, amountOut) => {
406
- const pool = provideVPool(amountIn.brand, amountOut.brand);
407
- return publicPrices(pool.getPriceForInput(amountIn, amountOut));
408
- };
409
-
410
- const getOutputPrice = (_context, amountIn, amountOut) => {
411
- const pool = provideVPool(amountIn.brand, amountOut.brand);
412
- return publicPrices(pool.getPriceForOutput(amountIn, amountOut));
413
- };
414
-
415
- const { makeSwapInInvitation, makeSwapOutInvitation } =
416
- makeMakeSwapInvitation(zcf, provideVPool);
417
- const makeAddLiquidityInvitation = makeMakeAddLiquidityInvitation(
418
- zcf,
419
- getPool,
420
- );
421
- const makeAddLiquidityAtRateInvitation = makeMakeAddLiquidityAtRateInvitation(
422
- zcf,
423
- getPool,
424
- provideVPool,
425
- protocolSeat,
426
- getPoolHelper,
427
- );
428
-
429
- const makeRemoveLiquidityInvitation = makeMakeRemoveLiquidityInvitation(
430
- zcf,
431
- getPool,
432
- );
433
-
434
- const { makeCollectFeesInvitation } = makeMakeCollectFeesInvitation(
435
- zcf,
436
- protocolSeat,
437
- centralBrand,
438
- 'Fee',
439
- );
440
-
441
- const publicFacet = augmentVirtualPublicFacet(
442
- Far('AMM public facet', {
443
- addPoolInvitation,
444
- addIssuer,
445
- getPoolAllocation,
446
- getLiquidityIssuer,
447
- getLiquiditySupply,
448
- getInputPrice,
449
- getOutputPrice,
450
- getSecondaryIssuer,
451
- makeSwapInvitation: makeSwapInInvitation,
452
- makeSwapInInvitation,
453
- makeSwapOutInvitation,
454
- makeAddLiquidityInvitation,
455
- makeAddLiquidityAtRateInvitation,
456
- makeRemoveLiquidityInvitation,
457
- getQuoteIssuer: () => quoteIssuerKit.issuer,
458
- getPriceAuthorities,
459
- getAllPoolBrands: () =>
460
- Object.values(zcf.getTerms().brands).filter(isSecondary),
461
- getProtocolPoolBalance: () => protocolSeat.getCurrentAllocation(),
462
- getMetrics: () => metricsSubscription,
463
- getPoolMetrics,
464
- ...params,
465
- }),
466
- );
467
-
468
- const { governorFacet, limitedCreatorFacet } = makeVirtualGovernorFacet(
469
- harden({
470
- makeCollectFeesInvitation,
471
- /**
472
- * Must be called before adding pools. Not provided at contract start time
473
- * due to cyclic dependency.
474
- *
475
- * @param {MethodContext} _context
476
- * @param {AssetReservePublicFacet} facet
477
- */
478
- resolveReserveFacet: (_context, facet) => {
479
- assert(!reserveFacet, 'reserveFacet already resolved');
480
- reserveFacet = facet;
481
- baggage.init('reserveFacet', facet);
482
- },
483
- }),
484
- );
485
-
486
- const makeAMM = vivifyKindMulti(baggage, 'AMM', initEmpty, {
487
- publicFacet,
488
- creatorFacet: governorFacet,
489
- limitedCreatorFacet,
490
- });
491
- const { creatorFacet, publicFacet: pFacet } = makeAMM();
492
- return { creatorFacet, publicFacet: pFacet };
493
- };
494
-
495
- harden(start);
496
- export { start };
497
-
498
- /**
499
- * @typedef {object} AMMParamGetters
500
- * @property {() => NatValue} getPoolFee
501
- * @property {() => NatValue} getProtocolFee
502
- * @property {() => Amount<'nat'>} getMinInitialPoolLiquidity
503
- * @property {() => Amount} getElectorate
504
- */
505
-
506
- /**
507
- * @typedef { bigint } BasisPoints -- hundredths of a percent
508
- *
509
- * @typedef {GovernanceTerms<{
510
- * PoolFee: 'nat',
511
- * ProtocolFee: 'nat',
512
- * MinInitialPoolLiquidity: 'amount',
513
- * }> & {
514
- * brands: { Central: Brand },
515
- * issuers: {},
516
- * timer: TimerService,
517
- * poolFeeBP: BasisPoints, // portion of the fees that go into the pool
518
- * protocolFeeBP: BasisPoints, // portion of the fees that are shared with validators
519
- * }} AMMTerms
520
- */