@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
|
@@ -0,0 +1,608 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
import { X, q, Fail } from '@endo/errors';
|
|
3
|
+
import { E } from '@endo/far';
|
|
4
|
+
|
|
5
|
+
import { AmountMath, BrandShape } from '@agoric/ertp';
|
|
6
|
+
import { deeplyFulfilledObject, makeTracer } from '@agoric/internal';
|
|
7
|
+
import { UnguardedHelperI } from '@agoric/internal/src/typeGuards.js';
|
|
8
|
+
import {
|
|
9
|
+
observeIteration,
|
|
10
|
+
observeNotifier,
|
|
11
|
+
subscribeEach,
|
|
12
|
+
} from '@agoric/notifier';
|
|
13
|
+
import {
|
|
14
|
+
M,
|
|
15
|
+
makeScalarBigMapStore,
|
|
16
|
+
makeScalarBigSetStore,
|
|
17
|
+
} from '@agoric/vat-data';
|
|
18
|
+
import { makeAtomicProvider, makeScalarMapStore } from '@agoric/store';
|
|
19
|
+
import { PowerFlags } from '@agoric/vats/src/walletFlags.js';
|
|
20
|
+
import {
|
|
21
|
+
PublicTopicShape,
|
|
22
|
+
makeRecorderTopic,
|
|
23
|
+
} from '@agoric/zoe/src/contractSupport/topics.js';
|
|
24
|
+
import { InstanceHandleShape } from '@agoric/zoe/src/typeGuards.js';
|
|
25
|
+
import { isUpgradeDisconnection } from '@agoric/internal/src/upgrade-api.js';
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @import {EReturn} from '@endo/far';
|
|
29
|
+
* @import {BridgeMessage} from '@agoric/cosmic-swingset/src/types.js';
|
|
30
|
+
* @import {Amount, Brand, Payment, Purse} from '@agoric/ertp';
|
|
31
|
+
* @import {StorageNode} from '@agoric/internal/src/lib-chainStorage.js';
|
|
32
|
+
* @import {ZCF} from '@agoric/zoe';
|
|
33
|
+
* @import {ERef} from '@endo/far'
|
|
34
|
+
* @import {Bank, BankManager} from '@agoric/vats/src/vat-bank.js'
|
|
35
|
+
* @import {MapStore, SetStore} from '@agoric/store';
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
const trace = makeTracer('ProvPool');
|
|
39
|
+
|
|
40
|
+
const FIRST_UPPER_KEYWORD = /^[A-Z][a-zA-Z0-9_$]*$/;
|
|
41
|
+
// see https://github.com/Agoric/agoric-sdk/issues/8238
|
|
42
|
+
const FIRST_LOWER_NEAR_KEYWORD = /^[a-z][a-zA-Z0-9_$]*$/;
|
|
43
|
+
|
|
44
|
+
// XXX when inferred, error TS2742: cannot be named without a reference to '../../../node_modules/@endo/exo/src/get-interface.js'. This is likely not portable. A type annotation is necessary.
|
|
45
|
+
/**
|
|
46
|
+
* @typedef {{
|
|
47
|
+
* machine: any;
|
|
48
|
+
* helper: any;
|
|
49
|
+
* forHandler: any;
|
|
50
|
+
* public: any;
|
|
51
|
+
* }} ProvisionPoolKit
|
|
52
|
+
*/
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* @typedef {import('@agoric/zoe/src/zoeService/utils.js').Instance<
|
|
56
|
+
* import('@agoric/inter-protocol/src/psm/psm.js').start
|
|
57
|
+
* >} PsmInstance
|
|
58
|
+
*/
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* @typedef {object} ProvisionPoolKitReferences
|
|
62
|
+
* @property {ERef<BankManager>} bankManager
|
|
63
|
+
* @property {ERef<import('@agoric/vats').NameAdmin>} namesByAddressAdmin
|
|
64
|
+
* @property {ERef<
|
|
65
|
+
* import('@agoric/vats/src/core/startWalletFactory.js').WalletFactoryStartResult['creatorFacet']
|
|
66
|
+
* >} walletFactory
|
|
67
|
+
*/
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* @typedef {object} MetricsNotification Metrics naming scheme is that nouns are
|
|
71
|
+
* present values and past-participles are accumulative.
|
|
72
|
+
* @property {bigint} walletsProvisioned count of new wallets provisioned
|
|
73
|
+
* @property {Amount<'nat'>} totalMintedProvided running sum of Minted provided
|
|
74
|
+
* to new wallets
|
|
75
|
+
* @property {Amount<'nat'>} totalMintedConverted running sum of Minted ever
|
|
76
|
+
* received by the contract from PSM
|
|
77
|
+
*/
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Given attenuated access to the funding purse, handle requests to provision
|
|
81
|
+
* smart wallets.
|
|
82
|
+
*
|
|
83
|
+
* @param {import('@agoric/zone').Zone} zone
|
|
84
|
+
*/
|
|
85
|
+
export const prepareBridgeProvisionTool = zone =>
|
|
86
|
+
zone.exoClass(
|
|
87
|
+
'smartWalletProvisioningHandler',
|
|
88
|
+
M.interface('ProvisionBridgeHandlerMaker', {
|
|
89
|
+
fromBridge: M.callWhen(M.record()).returns(),
|
|
90
|
+
}),
|
|
91
|
+
/**
|
|
92
|
+
* @param {ERef<BankManager>} bankManager
|
|
93
|
+
* @param {ERef<
|
|
94
|
+
* EReturn<
|
|
95
|
+
* import('@agoric/smart-wallet/src/walletFactory.js').start
|
|
96
|
+
* >['creatorFacet']
|
|
97
|
+
* >} walletFactory
|
|
98
|
+
* @param {ERef<import('@agoric/vats').NameAdmin>} namesByAddressAdmin
|
|
99
|
+
* @param {ProvisionPoolKit['forHandler']} forHandler
|
|
100
|
+
*/
|
|
101
|
+
(bankManager, walletFactory, namesByAddressAdmin, forHandler) => ({
|
|
102
|
+
bankManager,
|
|
103
|
+
walletFactory,
|
|
104
|
+
namesByAddressAdmin,
|
|
105
|
+
forHandler,
|
|
106
|
+
}),
|
|
107
|
+
{
|
|
108
|
+
/** @param {BridgeMessage} obj */
|
|
109
|
+
async fromBridge(obj) {
|
|
110
|
+
if (obj.type !== 'PLEASE_PROVISION')
|
|
111
|
+
throw Fail`Unrecognized request ${obj.type}`;
|
|
112
|
+
trace('PLEASE_PROVISION', obj);
|
|
113
|
+
const { address, powerFlags } = obj;
|
|
114
|
+
// XXX expects powerFlags to be an array, but if it's a string then
|
|
115
|
+
// this allows a string that has 'SMART_WALLET' in it.
|
|
116
|
+
powerFlags.includes(PowerFlags.SMART_WALLET) ||
|
|
117
|
+
Fail`missing SMART_WALLET in powerFlags`;
|
|
118
|
+
|
|
119
|
+
const { bankManager, walletFactory, namesByAddressAdmin, forHandler } =
|
|
120
|
+
this.state;
|
|
121
|
+
|
|
122
|
+
const bank = E(bankManager).getBankForAddress(address);
|
|
123
|
+
// only proceed if we can provide funds
|
|
124
|
+
await forHandler.sendInitialPayment(bank);
|
|
125
|
+
|
|
126
|
+
const [_, created] = await E(walletFactory).provideSmartWallet(
|
|
127
|
+
address,
|
|
128
|
+
bank,
|
|
129
|
+
namesByAddressAdmin,
|
|
130
|
+
);
|
|
131
|
+
if (created) {
|
|
132
|
+
forHandler.onProvisioned();
|
|
133
|
+
}
|
|
134
|
+
trace(created ? 'provisioned' : 're-provisioned', address);
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* @param {import('@agoric/zone').Zone} zone
|
|
141
|
+
* @param {{
|
|
142
|
+
* makeRecorderKit: import('@agoric/zoe/src/contractSupport/recorder.js').MakeRecorderKit;
|
|
143
|
+
* params: any;
|
|
144
|
+
* poolBank: import('@endo/far').ERef<Bank>;
|
|
145
|
+
* zcf: ZCF;
|
|
146
|
+
* makeBridgeProvisionTool: ReturnType<typeof prepareBridgeProvisionTool>;
|
|
147
|
+
* }} powers
|
|
148
|
+
*/
|
|
149
|
+
export const prepareProvisionPoolKit = (
|
|
150
|
+
zone,
|
|
151
|
+
{ makeRecorderKit, params, poolBank, zcf, makeBridgeProvisionTool },
|
|
152
|
+
) => {
|
|
153
|
+
const zoe = zcf.getZoeService();
|
|
154
|
+
const ephemeralPurses = makeScalarMapStore('fundingPurseForBrand');
|
|
155
|
+
const purseProvider = makeAtomicProvider(ephemeralPurses);
|
|
156
|
+
const getFundingPurseForBrand = async poolBrand => {
|
|
157
|
+
await null;
|
|
158
|
+
try {
|
|
159
|
+
const purse = await purseProvider.provideAsync(poolBrand, brand =>
|
|
160
|
+
E(poolBank).getPurse(brand),
|
|
161
|
+
);
|
|
162
|
+
return purse;
|
|
163
|
+
} catch (err) {
|
|
164
|
+
trace(`🚨 could not get purse for brand ${poolBrand}`, err);
|
|
165
|
+
throw err;
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
const makeProvisionPoolKitInternal = zone.exoClassKit(
|
|
170
|
+
'ProvisionPoolKit',
|
|
171
|
+
{
|
|
172
|
+
machine: M.interface('ProvisionPoolKit machine', {
|
|
173
|
+
addRevivableAddresses: M.call(M.arrayOf(M.string())).returns(),
|
|
174
|
+
getWalletReviver: M.call().returns(
|
|
175
|
+
M.remotable('ProvisionPoolKit wallet reviver'),
|
|
176
|
+
),
|
|
177
|
+
setReferences: M.callWhen({
|
|
178
|
+
bankManager: M.eref(M.remotable('bankManager')),
|
|
179
|
+
namesByAddressAdmin: M.eref(M.remotable('nameAdmin')),
|
|
180
|
+
walletFactory: M.eref(M.remotable('walletFactory')),
|
|
181
|
+
}).returns(),
|
|
182
|
+
makeHandler: M.call().returns(M.remotable('BridgeHandler')),
|
|
183
|
+
initPSM: M.call(BrandShape, InstanceHandleShape).returns(),
|
|
184
|
+
}),
|
|
185
|
+
walletReviver: M.interface('ProvisionPoolKit wallet reviver', {
|
|
186
|
+
reviveWallet: M.callWhen(M.string()).returns(
|
|
187
|
+
M.remotable('SmartWallet'),
|
|
188
|
+
),
|
|
189
|
+
ackWallet: M.call(M.string()).returns(M.boolean()),
|
|
190
|
+
}),
|
|
191
|
+
helper: UnguardedHelperI,
|
|
192
|
+
forHandler: UnguardedHelperI,
|
|
193
|
+
public: M.interface('ProvisionPoolKit public', {
|
|
194
|
+
getPublicTopics: M.call().returns({ metrics: PublicTopicShape }),
|
|
195
|
+
}),
|
|
196
|
+
},
|
|
197
|
+
/**
|
|
198
|
+
* @param {object} opts
|
|
199
|
+
* @param {Purse<'nat'>} [opts.fundPurse]
|
|
200
|
+
* @param {Brand<'nat'>} opts.poolBrand
|
|
201
|
+
* @param {StorageNode} opts.metricsNode
|
|
202
|
+
*/
|
|
203
|
+
({ fundPurse, poolBrand, metricsNode }) => {
|
|
204
|
+
/** @type {import('@agoric/zoe/src/contractSupport/recorder.js').RecorderKit<MetricsNotification>} */
|
|
205
|
+
const metricsRecorderKit = makeRecorderKit(metricsNode);
|
|
206
|
+
|
|
207
|
+
/** @type {MapStore<ERef<Brand>, PsmInstance>} */
|
|
208
|
+
const brandToPSM = makeScalarBigMapStore('brandToPSM', { durable: true });
|
|
209
|
+
const revivableAddresses = makeScalarBigSetStore('revivableAddresses', {
|
|
210
|
+
durable: true,
|
|
211
|
+
keyShape: M.string(),
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* to be set by `setReferences`
|
|
216
|
+
*
|
|
217
|
+
* @type {Partial<ProvisionPoolKitReferences>}
|
|
218
|
+
*/
|
|
219
|
+
const references = {
|
|
220
|
+
bankManager: undefined,
|
|
221
|
+
namesByAddressAdmin: undefined,
|
|
222
|
+
walletFactory: undefined,
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
return {
|
|
226
|
+
brandToPSM,
|
|
227
|
+
fundPurse,
|
|
228
|
+
metricsRecorderKit,
|
|
229
|
+
poolBrand,
|
|
230
|
+
walletsProvisioned: 0n,
|
|
231
|
+
totalMintedProvided: AmountMath.makeEmpty(poolBrand),
|
|
232
|
+
totalMintedConverted: AmountMath.makeEmpty(poolBrand),
|
|
233
|
+
revivableAddresses,
|
|
234
|
+
...references,
|
|
235
|
+
};
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
// aka "limitedCreatorFacet"
|
|
239
|
+
machine: {
|
|
240
|
+
/** @param {string[]} oldAddresses */
|
|
241
|
+
addRevivableAddresses(oldAddresses) {
|
|
242
|
+
trace('revivableAddresses count', oldAddresses.length);
|
|
243
|
+
this.state.revivableAddresses.addAll(oldAddresses);
|
|
244
|
+
},
|
|
245
|
+
getWalletReviver() {
|
|
246
|
+
return this.facets.walletReviver;
|
|
247
|
+
},
|
|
248
|
+
/** @param {ProvisionPoolKitReferences} erefs */
|
|
249
|
+
async setReferences(erefs) {
|
|
250
|
+
const { bankManager, namesByAddressAdmin, walletFactory } = erefs;
|
|
251
|
+
const obj = harden({
|
|
252
|
+
bankManager,
|
|
253
|
+
namesByAddressAdmin,
|
|
254
|
+
walletFactory,
|
|
255
|
+
});
|
|
256
|
+
const refs = await deeplyFulfilledObject(obj);
|
|
257
|
+
Object.assign(this.state, refs);
|
|
258
|
+
},
|
|
259
|
+
/** @returns {import('@agoric/vats').BridgeHandler} */
|
|
260
|
+
makeHandler() {
|
|
261
|
+
const { bankManager, namesByAddressAdmin, walletFactory } =
|
|
262
|
+
this.state;
|
|
263
|
+
if (!bankManager || !namesByAddressAdmin || !walletFactory) {
|
|
264
|
+
throw Fail`must set references before handling requests`;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
const { forHandler } = this.facets;
|
|
268
|
+
|
|
269
|
+
const provisionHandler = makeBridgeProvisionTool(
|
|
270
|
+
bankManager,
|
|
271
|
+
walletFactory,
|
|
272
|
+
namesByAddressAdmin,
|
|
273
|
+
forHandler,
|
|
274
|
+
);
|
|
275
|
+
|
|
276
|
+
return provisionHandler;
|
|
277
|
+
},
|
|
278
|
+
/**
|
|
279
|
+
* @param {Brand} brand
|
|
280
|
+
* @param {PsmInstance} instance
|
|
281
|
+
*/
|
|
282
|
+
initPSM(brand, instance) {
|
|
283
|
+
const { brandToPSM } = this.state;
|
|
284
|
+
brandToPSM.init(brand, instance);
|
|
285
|
+
},
|
|
286
|
+
},
|
|
287
|
+
walletReviver: {
|
|
288
|
+
/** @param {string} address */
|
|
289
|
+
async reviveWallet(address) {
|
|
290
|
+
const {
|
|
291
|
+
revivableAddresses,
|
|
292
|
+
bankManager,
|
|
293
|
+
namesByAddressAdmin,
|
|
294
|
+
walletFactory,
|
|
295
|
+
} = this.state;
|
|
296
|
+
if (!bankManager || !namesByAddressAdmin || !walletFactory) {
|
|
297
|
+
throw Fail`must set references before handling requests`;
|
|
298
|
+
}
|
|
299
|
+
revivableAddresses.has(address) ||
|
|
300
|
+
Fail`non-revivable address ${address}`;
|
|
301
|
+
const bank = E(bankManager).getBankForAddress(address);
|
|
302
|
+
const [wallet, _created] = await E(walletFactory).provideSmartWallet(
|
|
303
|
+
address,
|
|
304
|
+
bank,
|
|
305
|
+
namesByAddressAdmin,
|
|
306
|
+
);
|
|
307
|
+
return wallet;
|
|
308
|
+
},
|
|
309
|
+
/**
|
|
310
|
+
* @param {string} address
|
|
311
|
+
* @returns {boolean} isRevive
|
|
312
|
+
*/
|
|
313
|
+
ackWallet(address) {
|
|
314
|
+
const { revivableAddresses } = this.state;
|
|
315
|
+
if (!revivableAddresses.has(address)) {
|
|
316
|
+
return false;
|
|
317
|
+
}
|
|
318
|
+
revivableAddresses.delete(address);
|
|
319
|
+
return true;
|
|
320
|
+
},
|
|
321
|
+
},
|
|
322
|
+
helper: {
|
|
323
|
+
publishMetrics() {
|
|
324
|
+
const {
|
|
325
|
+
metricsRecorderKit,
|
|
326
|
+
walletsProvisioned,
|
|
327
|
+
totalMintedConverted,
|
|
328
|
+
totalMintedProvided,
|
|
329
|
+
} = this.state;
|
|
330
|
+
void metricsRecorderKit.recorder.write(
|
|
331
|
+
harden({
|
|
332
|
+
walletsProvisioned,
|
|
333
|
+
totalMintedProvided,
|
|
334
|
+
totalMintedConverted,
|
|
335
|
+
}),
|
|
336
|
+
);
|
|
337
|
+
},
|
|
338
|
+
onTrade(converted) {
|
|
339
|
+
const { state, facets } = this;
|
|
340
|
+
state.totalMintedConverted = AmountMath.add(
|
|
341
|
+
state.totalMintedConverted,
|
|
342
|
+
converted,
|
|
343
|
+
);
|
|
344
|
+
facets.helper.publishMetrics();
|
|
345
|
+
},
|
|
346
|
+
onSendFunds(provided) {
|
|
347
|
+
const { state, facets } = this;
|
|
348
|
+
state.totalMintedProvided = AmountMath.add(
|
|
349
|
+
state.totalMintedProvided,
|
|
350
|
+
provided,
|
|
351
|
+
);
|
|
352
|
+
facets.helper.publishMetrics();
|
|
353
|
+
},
|
|
354
|
+
/**
|
|
355
|
+
* @param {Amount} amount
|
|
356
|
+
* @param {ERef<Purse>} srcPurse
|
|
357
|
+
*/
|
|
358
|
+
async onPoolDeposit(amount, srcPurse) {
|
|
359
|
+
const { helper } = this.facets;
|
|
360
|
+
const { brandToPSM, poolBrand } = this.state;
|
|
361
|
+
|
|
362
|
+
const { brand } = amount;
|
|
363
|
+
if (AmountMath.isEmpty(amount) || brand === poolBrand) {
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// `amount` doesn't match the current `poolBrand`, so we need to swap
|
|
368
|
+
// it.
|
|
369
|
+
if (!brandToPSM.has(brand)) {
|
|
370
|
+
console.error('funds arrived but no PSM instance', brand);
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
const instance = brandToPSM.get(brand);
|
|
374
|
+
const payment = E(srcPurse).withdraw(amount);
|
|
375
|
+
await helper.swap(payment, amount, instance).catch(async reason => {
|
|
376
|
+
console.error(X`swap failed: ${reason}`);
|
|
377
|
+
const resolvedPayment = await payment;
|
|
378
|
+
return E(srcPurse).deposit(resolvedPayment);
|
|
379
|
+
});
|
|
380
|
+
},
|
|
381
|
+
/**
|
|
382
|
+
* @param {ERef<Purse>} exchangePurse
|
|
383
|
+
* @param {ERef<Brand>} brand
|
|
384
|
+
*/
|
|
385
|
+
watchCurrentAmount(exchangePurse, brand) {
|
|
386
|
+
const { helper } = this.facets;
|
|
387
|
+
void observeNotifier(E(exchangePurse).getCurrentAmountNotifier(), {
|
|
388
|
+
updateState: async amount => {
|
|
389
|
+
trace('provisionPool balance update', amount);
|
|
390
|
+
await helper.onPoolDeposit(amount, exchangePurse);
|
|
391
|
+
},
|
|
392
|
+
fail: reason => {
|
|
393
|
+
if (isUpgradeDisconnection(reason)) {
|
|
394
|
+
void helper.watchCurrentAmount(exchangePurse, brand);
|
|
395
|
+
} else {
|
|
396
|
+
console.error(reason);
|
|
397
|
+
}
|
|
398
|
+
},
|
|
399
|
+
});
|
|
400
|
+
},
|
|
401
|
+
watchAssetSubscription() {
|
|
402
|
+
const { facets } = this;
|
|
403
|
+
const { helper } = facets;
|
|
404
|
+
|
|
405
|
+
/** @param {import('@agoric/vats/src/vat-bank.js').AssetDescriptor} desc */
|
|
406
|
+
const repairDesc = desc => {
|
|
407
|
+
if (desc.issuerName.match(FIRST_UPPER_KEYWORD)) {
|
|
408
|
+
trace(`Saving Issuer ${desc.issuerName}`);
|
|
409
|
+
return desc;
|
|
410
|
+
} else if (desc.issuerName.match(FIRST_LOWER_NEAR_KEYWORD)) {
|
|
411
|
+
const bad = desc.issuerName;
|
|
412
|
+
const goodName = bad.replace(bad[0], bad[0].toUpperCase());
|
|
413
|
+
|
|
414
|
+
trace(
|
|
415
|
+
`Saving Issuer ${desc.issuerName} with repaired keyword ${goodName}`,
|
|
416
|
+
);
|
|
417
|
+
return { ...desc, issuerName: goodName };
|
|
418
|
+
} else {
|
|
419
|
+
console.error(
|
|
420
|
+
`unable to save issuer with illegal keyword: ${desc.issuerName}`,
|
|
421
|
+
);
|
|
422
|
+
return undefined;
|
|
423
|
+
}
|
|
424
|
+
};
|
|
425
|
+
|
|
426
|
+
return observeIteration(
|
|
427
|
+
subscribeEach(E(poolBank).getAssetSubscription()),
|
|
428
|
+
{
|
|
429
|
+
updateState: async desc => {
|
|
430
|
+
await null;
|
|
431
|
+
const issuer = zcf.getTerms().issuers[desc.issuerName];
|
|
432
|
+
if (issuer === desc.issuer) {
|
|
433
|
+
trace('provisionPool re-notified of known asset', desc.brand);
|
|
434
|
+
} else {
|
|
435
|
+
const goodDesc = repairDesc(desc);
|
|
436
|
+
if (goodDesc) {
|
|
437
|
+
await zcf.saveIssuer(goodDesc.issuer, goodDesc.issuerName);
|
|
438
|
+
} else {
|
|
439
|
+
console.error(
|
|
440
|
+
`unable to save issuer with illegal keyword: ${desc.issuerName}`,
|
|
441
|
+
);
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
/** @type {ERef<Purse>} */
|
|
446
|
+
const exchangePurse = E(poolBank).getPurse(desc.brand);
|
|
447
|
+
helper.watchCurrentAmount(exchangePurse, desc.brand);
|
|
448
|
+
},
|
|
449
|
+
fail: _reason => {
|
|
450
|
+
void helper.watchAssetSubscription();
|
|
451
|
+
},
|
|
452
|
+
},
|
|
453
|
+
);
|
|
454
|
+
},
|
|
455
|
+
/**
|
|
456
|
+
* @param {Brand<'nat'>} poolBrand
|
|
457
|
+
* @param {object} [options]
|
|
458
|
+
* @param {MetricsNotification} [options.metrics]
|
|
459
|
+
*/
|
|
460
|
+
start(poolBrand, { metrics } = {}) {
|
|
461
|
+
const { facets, state } = this;
|
|
462
|
+
const { helper } = facets;
|
|
463
|
+
const lastPoolBrand = state.poolBrand;
|
|
464
|
+
|
|
465
|
+
// The PerAccountInitialAmount param must use the correct brand for
|
|
466
|
+
// this incarnation.
|
|
467
|
+
AmountMath.coerce(poolBrand, params.getPerAccountInitialAmount());
|
|
468
|
+
|
|
469
|
+
// Restore old metrics.
|
|
470
|
+
if (metrics) {
|
|
471
|
+
const {
|
|
472
|
+
walletsProvisioned,
|
|
473
|
+
totalMintedProvided,
|
|
474
|
+
totalMintedConverted,
|
|
475
|
+
} = metrics;
|
|
476
|
+
assert.typeof(walletsProvisioned, 'bigint');
|
|
477
|
+
AmountMath.coerce(lastPoolBrand, totalMintedProvided);
|
|
478
|
+
AmountMath.coerce(lastPoolBrand, totalMintedConverted);
|
|
479
|
+
Object.assign(state, {
|
|
480
|
+
walletsProvisioned,
|
|
481
|
+
totalMintedProvided,
|
|
482
|
+
totalMintedConverted,
|
|
483
|
+
});
|
|
484
|
+
helper.publishMetrics();
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
// Update as needed when `poolBrand` changes.
|
|
488
|
+
if (poolBrand !== lastPoolBrand) {
|
|
489
|
+
state.poolBrand = poolBrand;
|
|
490
|
+
state.fundPurse = undefined;
|
|
491
|
+
void getFundingPurseForBrand(poolBrand).then(purse =>
|
|
492
|
+
helper.updateFundPurse(purse, poolBrand),
|
|
493
|
+
);
|
|
494
|
+
state.totalMintedProvided = AmountMath.makeEmpty(poolBrand);
|
|
495
|
+
state.totalMintedConverted = AmountMath.makeEmpty(poolBrand);
|
|
496
|
+
helper.publishMetrics();
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
void helper.watchAssetSubscription();
|
|
500
|
+
},
|
|
501
|
+
/**
|
|
502
|
+
* @param {ERef<Payment>} payIn
|
|
503
|
+
* @param {Amount} amount
|
|
504
|
+
* @param {PsmInstance} instance
|
|
505
|
+
*/
|
|
506
|
+
async swap(payIn, amount, instance) {
|
|
507
|
+
await null;
|
|
508
|
+
const { facets, state } = this;
|
|
509
|
+
const { helper } = facets;
|
|
510
|
+
const {
|
|
511
|
+
poolBrand,
|
|
512
|
+
fundPurse = await getFundingPurseForBrand(poolBrand),
|
|
513
|
+
} = state;
|
|
514
|
+
const psmPub = E(zoe).getPublicFacet(instance);
|
|
515
|
+
const proposal = harden({ give: { In: amount } });
|
|
516
|
+
const invitation = E(psmPub).makeWantMintedInvitation();
|
|
517
|
+
const seat = E(zoe).offer(invitation, proposal, { In: payIn });
|
|
518
|
+
const payout = await E(seat).getPayout('Out');
|
|
519
|
+
const rxd = await E(fundPurse).deposit(payout);
|
|
520
|
+
helper.onTrade(rxd);
|
|
521
|
+
return rxd;
|
|
522
|
+
},
|
|
523
|
+
/**
|
|
524
|
+
* @param {Purse<'nat'>} purse
|
|
525
|
+
* @param {Brand<'nat'>} brand
|
|
526
|
+
*/
|
|
527
|
+
updateFundPurse(purse, brand) {
|
|
528
|
+
const { state } = this;
|
|
529
|
+
if (brand !== state.poolBrand || state.fundPurse) return;
|
|
530
|
+
state.fundPurse = purse;
|
|
531
|
+
},
|
|
532
|
+
},
|
|
533
|
+
forHandler: {
|
|
534
|
+
onProvisioned() {
|
|
535
|
+
const { facets, state } = this;
|
|
536
|
+
state.walletsProvisioned += 1n;
|
|
537
|
+
facets.helper.publishMetrics();
|
|
538
|
+
},
|
|
539
|
+
/** @param {ERef<Bank>} destBank */
|
|
540
|
+
async sendInitialPayment(destBank) {
|
|
541
|
+
await null;
|
|
542
|
+
const { facets, state } = this;
|
|
543
|
+
const { helper } = facets;
|
|
544
|
+
const {
|
|
545
|
+
poolBrand,
|
|
546
|
+
fundPurse = await getFundingPurseForBrand(poolBrand),
|
|
547
|
+
} = state;
|
|
548
|
+
const perAccountInitialAmount = /** @type {Amount<'nat'>} */ (
|
|
549
|
+
params.getPerAccountInitialAmount()
|
|
550
|
+
);
|
|
551
|
+
trace('sendInitialPayment withdrawing', perAccountInitialAmount);
|
|
552
|
+
const initialPmt = await E(fundPurse).withdraw(
|
|
553
|
+
perAccountInitialAmount,
|
|
554
|
+
);
|
|
555
|
+
|
|
556
|
+
const destPurse = E(destBank).getPurse(poolBrand);
|
|
557
|
+
return E(destPurse)
|
|
558
|
+
.deposit(initialPmt)
|
|
559
|
+
.then(amt => {
|
|
560
|
+
helper.onSendFunds(perAccountInitialAmount);
|
|
561
|
+
trace('provisionPool sent', amt);
|
|
562
|
+
})
|
|
563
|
+
.catch(reason => {
|
|
564
|
+
console.error(X`initial deposit failed: ${q(reason)}`);
|
|
565
|
+
void E(fundPurse).deposit(initialPmt);
|
|
566
|
+
throw reason;
|
|
567
|
+
});
|
|
568
|
+
},
|
|
569
|
+
},
|
|
570
|
+
public: {
|
|
571
|
+
getPublicTopics() {
|
|
572
|
+
return {
|
|
573
|
+
metrics: makeRecorderTopic(
|
|
574
|
+
'Provision Pool metrics',
|
|
575
|
+
this.state.metricsRecorderKit,
|
|
576
|
+
),
|
|
577
|
+
};
|
|
578
|
+
},
|
|
579
|
+
},
|
|
580
|
+
},
|
|
581
|
+
{
|
|
582
|
+
finish: ({ facets }) => {
|
|
583
|
+
facets.helper.publishMetrics();
|
|
584
|
+
},
|
|
585
|
+
},
|
|
586
|
+
);
|
|
587
|
+
|
|
588
|
+
/**
|
|
589
|
+
* Prepare synchronous values before passing to real Exo maker
|
|
590
|
+
*
|
|
591
|
+
* @param {object} opts
|
|
592
|
+
* @param {Brand<'nat'>} opts.poolBrand
|
|
593
|
+
* @param {ERef<StorageNode>} opts.storageNode
|
|
594
|
+
* @returns {Promise<ProvisionPoolKit>}
|
|
595
|
+
*/
|
|
596
|
+
const makeProvisionPoolKit = async ({ poolBrand, storageNode }) => {
|
|
597
|
+
const fundPurse = await getFundingPurseForBrand(poolBrand);
|
|
598
|
+
const metricsNode = await E(storageNode).makeChildNode('metrics');
|
|
599
|
+
|
|
600
|
+
return makeProvisionPoolKitInternal({
|
|
601
|
+
fundPurse,
|
|
602
|
+
poolBrand,
|
|
603
|
+
metricsNode,
|
|
604
|
+
});
|
|
605
|
+
};
|
|
606
|
+
|
|
607
|
+
return makeProvisionPoolKit;
|
|
608
|
+
};
|