@agoric/fast-usdc 0.1.1-other-dev-3eb1a1d.0 → 0.1.1-other-dev-d15096d.0.d15096d

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.
@@ -1,235 +0,0 @@
1
- import { AssetKind } from '@agoric/ertp';
2
- import {
3
- assertAllDefined,
4
- deeplyFulfilledObject,
5
- makeTracer,
6
- } from '@agoric/internal';
7
- import { observeIteration, subscribeEach } from '@agoric/notifier';
8
- import {
9
- OrchestrationPowersShape,
10
- withOrchestration,
11
- } from '@agoric/orchestration';
12
- import { provideSingleton } from '@agoric/zoe/src/contractSupport/durability.js';
13
- import { prepareRecorderKitMakers } from '@agoric/zoe/src/contractSupport/recorder.js';
14
- import { makeZoeTools } from '@agoric/orchestration/src/utils/zoe-tools.js';
15
- import { depositToSeat } from '@agoric/zoe/src/contractSupport/zoeHelpers.js';
16
- import { E } from '@endo/far';
17
- import { M, objectMap } from '@endo/patterns';
18
- import { prepareAdvancer } from './exos/advancer.js';
19
- import { prepareLiquidityPoolKit } from './exos/liquidity-pool.js';
20
- import { prepareSettler } from './exos/settler.js';
21
- import { prepareStatusManager } from './exos/status-manager.js';
22
- import { prepareTransactionFeedKit } from './exos/transaction-feed.js';
23
- import { defineInertInvitation } from './utils/zoe.js';
24
- import { FastUSDCTermsShape, FeeConfigShape } from './type-guards.js';
25
- import * as flows from './fast-usdc.flows.js';
26
-
27
- const trace = makeTracer('FastUsdc');
28
-
29
- /**
30
- * @import {Denom} from '@agoric/orchestration';
31
- * @import {HostInterface} from '@agoric/async-flow';
32
- * @import {OrchestrationAccount} from '@agoric/orchestration';
33
- * @import {OrchestrationPowers, OrchestrationTools} from '@agoric/orchestration/src/utils/start-helper.js';
34
- * @import {Vow} from '@agoric/vow';
35
- * @import {Zone} from '@agoric/zone';
36
- * @import {OperatorKit} from './exos/operator-kit.js';
37
- * @import {CctpTxEvidence, FeeConfig} from './types.js';
38
- * @import {RepayAmountKWR, RepayPaymentKWR} from './exos/liquidity-pool.js';
39
- */
40
-
41
- /**
42
- * @typedef {{
43
- * usdcDenom: Denom;
44
- * }} FastUsdcTerms
45
- */
46
-
47
- /** @type {ContractMeta<typeof start>} */
48
- export const meta = {
49
- // @ts-expect-error TypedPattern not recognized as record
50
- customTermsShape: FastUSDCTermsShape,
51
- privateArgsShape: {
52
- // @ts-expect-error TypedPattern not recognized as record
53
- ...OrchestrationPowersShape,
54
- feeConfig: FeeConfigShape,
55
- marshaller: M.remotable(),
56
- },
57
- };
58
- harden(meta);
59
-
60
- /**
61
- * @param {ZCF<FastUsdcTerms>} zcf
62
- * @param {OrchestrationPowers & {
63
- * marshaller: Marshaller;
64
- * feeConfig: FeeConfig;
65
- * }} privateArgs
66
- * @param {Zone} zone
67
- * @param {OrchestrationTools} tools
68
- */
69
- export const contract = async (zcf, privateArgs, zone, tools) => {
70
- assert(tools, 'no tools');
71
- const terms = zcf.getTerms();
72
- assert('USDC' in terms.brands, 'no USDC brand');
73
- assert('usdcDenom' in terms, 'no usdcDenom');
74
- const { feeConfig, marshaller } = privateArgs;
75
- const { makeRecorderKit } = prepareRecorderKitMakers(
76
- zone.mapStore('vstorage'),
77
- marshaller,
78
- );
79
- const statusManager = prepareStatusManager(zone);
80
- const makeSettler = prepareSettler(zone, { statusManager });
81
- const { chainHub, orchestrateAll, vowTools } = tools;
82
- const { localTransfer } = makeZoeTools(zcf, vowTools);
83
- const makeAdvancer = prepareAdvancer(zone, {
84
- chainHub,
85
- feeConfig,
86
- localTransfer,
87
- usdc: harden({
88
- brand: terms.brands.USDC,
89
- denom: terms.usdcDenom,
90
- }),
91
- statusManager,
92
- vowTools,
93
- zcf,
94
- });
95
- const makeFeedKit = prepareTransactionFeedKit(zone, zcf);
96
- assertAllDefined({ makeFeedKit, makeAdvancer, makeSettler, statusManager });
97
- const makeLiquidityPoolKit = prepareLiquidityPoolKit(
98
- zone,
99
- zcf,
100
- terms.brands.USDC,
101
- { makeRecorderKit },
102
- );
103
-
104
- const makeTestInvitation = defineInertInvitation(
105
- zcf,
106
- 'test of forcing evidence',
107
- );
108
-
109
- const { makeLocalAccount } = orchestrateAll(flows, {});
110
-
111
- const creatorFacet = zone.exo('Fast USDC Creator', undefined, {
112
- /** @type {(operatorId: string) => Promise<Invitation<OperatorKit>>} */
113
- async makeOperatorInvitation(operatorId) {
114
- // eslint-disable-next-line no-use-before-define
115
- return feedKit.creator.makeOperatorInvitation(operatorId);
116
- },
117
- /**
118
- * @param {{ USDC: Amount<'nat'>}} amounts
119
- */
120
- testBorrow(amounts) {
121
- console.log('🚧🚧 UNTIL: borrow is integrated (#10388) 🚧🚧', amounts);
122
- const { zcfSeat: tmpAssetManagerSeat } = zcf.makeEmptySeatKit();
123
- poolKit.borrower.borrow(tmpAssetManagerSeat, amounts);
124
- return tmpAssetManagerSeat.getCurrentAllocation();
125
- },
126
- /**
127
- *
128
- * @param {RepayAmountKWR} amounts
129
- * @param {RepayPaymentKWR} payments
130
- * @returns {Promise<AmountKeywordRecord>}
131
- */
132
- async testRepay(amounts, payments) {
133
- console.log('🚧🚧 UNTIL: repay is integrated (#10388) 🚧🚧', amounts);
134
- const { zcfSeat: tmpAssetManagerSeat } = zcf.makeEmptySeatKit();
135
- await depositToSeat(
136
- zcf,
137
- tmpAssetManagerSeat,
138
- await deeplyFulfilledObject(
139
- objectMap(payments, pmt => E(terms.issuers.USDC).getAmountOf(pmt)),
140
- ),
141
- payments,
142
- );
143
- poolKit.repayer.repay(tmpAssetManagerSeat, amounts);
144
- return tmpAssetManagerSeat.getCurrentAllocation();
145
- },
146
- });
147
-
148
- const publicFacet = zone.exo('Fast USDC Public', undefined, {
149
- // XXX to be removed before production
150
- /**
151
- * NB: Any caller with access to this invitation maker has the ability to
152
- * force handling of evidence.
153
- *
154
- * Provide an API call in the form of an invitation maker, so that the
155
- * capability is available in the smart-wallet bridge during UI testing.
156
- *
157
- * @param {CctpTxEvidence} evidence
158
- */
159
- makeTestPushInvitation(evidence) {
160
- // eslint-disable-next-line no-use-before-define
161
- void advancer.handleTransactionEvent(evidence);
162
- return makeTestInvitation();
163
- },
164
- makeDepositInvitation() {
165
- return poolKit.public.makeDepositInvitation();
166
- },
167
- makeWithdrawInvitation() {
168
- return poolKit.public.makeWithdrawInvitation();
169
- },
170
- getPublicTopics() {
171
- return poolKit.public.getPublicTopics();
172
- },
173
- });
174
-
175
- // ^^^ Define all kinds above this line. Keep remote calls below. vvv
176
-
177
- // NOTE: Using a ZCFMint is helpful for the usual reasons (
178
- // synchronous mint/burn, keeping assets out of contract vats, ...).
179
- // And there's just one pool, which suggests building it with zone.exo().
180
- //
181
- // But zone.exo() defines a kind and
182
- // all kinds have to be defined before any remote calls,
183
- // such as the one to the zoe vat as part of making a ZCFMint.
184
- //
185
- // So we use zone.exoClassKit above to define the liquidity pool kind
186
- // and pass the shareMint into the maker / init function.
187
-
188
- const shareMint = await provideSingleton(
189
- zone.mapStore('mint'),
190
- 'PoolShare',
191
- () =>
192
- zcf.makeZCFMint('PoolShares', AssetKind.NAT, {
193
- decimalPlaces: 6,
194
- }),
195
- );
196
-
197
- const poolKit = zone.makeOnce('Liquidity Pool kit', () =>
198
- makeLiquidityPoolKit(shareMint, privateArgs.storageNode),
199
- );
200
-
201
- const feedKit = zone.makeOnce('Feed Kit', () => makeFeedKit());
202
-
203
- const poolAccountV =
204
- // cast to HostInterface
205
- /** @type { Vow<HostInterface<OrchestrationAccount<{chainId: 'agoric';}>>>} */ (
206
- /** @type {unknown}*/ (
207
- zone.makeOnce('Pool Local Orch Account', () => makeLocalAccount())
208
- )
209
- );
210
- const poolAccount = await vowTools.when(poolAccountV);
211
-
212
- const advancer = zone.makeOnce('Advancer', () =>
213
- makeAdvancer({
214
- borrowerFacet: poolKit.borrower,
215
- poolAccount,
216
- }),
217
- );
218
- // Connect evidence stream to advancer
219
- void observeIteration(subscribeEach(feedKit.public.getEvidenceSubscriber()), {
220
- updateState(evidence) {
221
- try {
222
- void advancer.handleTransactionEvent(evidence);
223
- } catch (err) {
224
- trace('🚨 Error handling transaction event', err);
225
- }
226
- },
227
- });
228
-
229
- return harden({ creatorFacet, publicFacet });
230
- };
231
- harden(contract);
232
-
233
- export const start = withOrchestration(contract);
234
- harden(start);
235
- /** @typedef {typeof start} FastUsdcSF */
@@ -1,13 +0,0 @@
1
- /**
2
- * @import {Orchestrator, OrchestrationFlow} from '@agoric/orchestration';
3
- */
4
-
5
- /**
6
- * @satisfies {OrchestrationFlow}
7
- * @param {Orchestrator} orch
8
- */
9
- export const makeLocalAccount = async orch => {
10
- const agoricChain = await orch.getChain('agoric');
11
- return agoricChain.makeAccount();
12
- };
13
- harden(makeLocalAccount);
@@ -1,284 +0,0 @@
1
- import { deeplyFulfilledObject, makeTracer, objectMap } from '@agoric/internal';
2
- import { Fail } from '@endo/errors';
3
- import { E } from '@endo/far';
4
- import { makeMarshal } from '@endo/marshal';
5
- import { M } from '@endo/patterns';
6
- import {
7
- FastUSDCTermsShape,
8
- FeeConfigShape,
9
- FeedPolicyShape,
10
- } from './type-guards.js';
11
- import { fromExternalConfig } from './utils/config-marshal.js';
12
-
13
- /**
14
- * @import {DepositFacet} from '@agoric/ertp/src/types.js'
15
- * @import {TypedPattern} from '@agoric/internal'
16
- * @import {Instance, StartParams} from '@agoric/zoe/src/zoeService/utils'
17
- * @import {Board} from '@agoric/vats'
18
- * @import {ManifestBundleRef} from '@agoric/deploy-script-support/src/externalTypes.js'
19
- * @import {BootstrapManifest} from '@agoric/vats/src/core/lib-boot.js'
20
- * @import {Passable} from '@endo/marshal';
21
- * @import {LegibleCapData} from './utils/config-marshal.js'
22
- * @import {FastUsdcSF, FastUsdcTerms} from './fast-usdc.contract.js'
23
- * @import {FeeConfig, FeedPolicy} from './types.js'
24
- */
25
-
26
- const trace = makeTracer('FUSD-Start', true);
27
-
28
- const contractName = 'fastUsdc';
29
-
30
- /**
31
- * @typedef {{
32
- * terms: FastUsdcTerms;
33
- * oracles: Record<string, string>;
34
- * feeConfig: FeeConfig;
35
- * feedPolicy: FeedPolicy & Passable;
36
- * }} FastUSDCConfig
37
- */
38
- /** @type {TypedPattern<FastUSDCConfig>} */
39
- export const FastUSDCConfigShape = M.splitRecord({
40
- terms: FastUSDCTermsShape,
41
- oracles: M.recordOf(M.string(), M.string()),
42
- feeConfig: FeeConfigShape,
43
- feedPolicy: FeedPolicyShape,
44
- });
45
-
46
- /**
47
- * XXX Shouldn't the bridge or board vat handle this?
48
- *
49
- * @param {string} path
50
- * @param {{
51
- * chainStorage: ERef<StorageNode>;
52
- * board: ERef<Board>;
53
- * }} io
54
- */
55
- const makePublishingStorageKit = async (path, { chainStorage, board }) => {
56
- const storageNode = await E(chainStorage).makeChildNode(path);
57
-
58
- const marshaller = await E(board).getPublishingMarshaller();
59
- return { storageNode, marshaller };
60
- };
61
-
62
- const BOARD_AUX = 'boardAux';
63
- const marshalData = makeMarshal(_val => Fail`data only`);
64
- /**
65
- * @param {Brand} brand
66
- * @param {Pick<BootstrapPowers['consume'], 'board' | 'chainStorage'>} powers
67
- */
68
- const publishDisplayInfo = async (brand, { board, chainStorage }) => {
69
- // chainStorage type includes undefined, which doesn't apply here.
70
- // @ts-expect-error UNTIL https://github.com/Agoric/agoric-sdk/issues/8247
71
- const boardAux = E(chainStorage).makeChildNode(BOARD_AUX);
72
- const [id, displayInfo, allegedName] = await Promise.all([
73
- E(board).getId(brand),
74
- E(brand).getDisplayInfo(),
75
- E(brand).getAllegedName(),
76
- ]);
77
- const node = E(boardAux).makeChildNode(id);
78
- const aux = marshalData.toCapData(harden({ allegedName, displayInfo }));
79
- await E(node).setValue(JSON.stringify(aux));
80
- };
81
-
82
- const FEED_POLICY = 'feedPolicy';
83
-
84
- /**
85
- * @param {ERef<StorageNode>} node
86
- * @param {FeedPolicy} policy
87
- */
88
- const publishFeedPolicy = async (node, policy) => {
89
- const feedPolicy = E(node).makeChildNode(FEED_POLICY);
90
- await E(feedPolicy).setValue(JSON.stringify(policy));
91
- };
92
-
93
- /**
94
- * @typedef { PromiseSpaceOf<{
95
- * fastUsdcKit: FastUSDCKit
96
- * }> & {
97
- * installation: PromiseSpaceOf<{ fastUsdc: Installation<FastUsdcSF> }>;
98
- * instance: PromiseSpaceOf<{ fastUsdc: Instance<FastUsdcSF> }>;
99
- * issuer: PromiseSpaceOf<{ FastLP: Issuer }>;
100
- * brand: PromiseSpaceOf<{ FastLP: Brand }>;
101
- * }} FastUSDCCorePowers
102
- *
103
- * @typedef {StartedInstanceKitWithLabel & {
104
- * privateArgs: StartParams<FastUsdcSF>['privateArgs'];
105
- * }} FastUSDCKit
106
- */
107
-
108
- /**
109
- * @throws if oracle smart wallets are not yet provisioned
110
- *
111
- * @param {BootstrapPowers & FastUSDCCorePowers } powers
112
- * @param {{ options: LegibleCapData<FastUSDCConfig> }} config
113
- */
114
- export const startFastUSDC = async (
115
- {
116
- produce: { fastUsdcKit },
117
- consume: {
118
- agoricNames,
119
- namesByAddress,
120
- board,
121
- chainStorage,
122
- chainTimerService: timerService,
123
- localchain,
124
- cosmosInterchainService,
125
- startUpgradable,
126
- zoe,
127
- },
128
- issuer: {
129
- produce: { FastLP: produceShareIssuer },
130
- },
131
- brand: {
132
- produce: { FastLP: produceShareBrand },
133
- },
134
- installation: {
135
- consume: { fastUsdc },
136
- },
137
- instance: {
138
- produce: { fastUsdc: produceInstance },
139
- },
140
- },
141
- config,
142
- ) => {
143
- trace('startFastUSDC');
144
-
145
- await null;
146
- /** @type {Issuer<'nat'>} */
147
- const USDCissuer = await E(agoricNames).lookup('issuer', 'USDC');
148
- const brands = harden({
149
- USDC: await E(USDCissuer).getBrand(),
150
- });
151
-
152
- const { terms, oracles, feeConfig, feedPolicy } = fromExternalConfig(
153
- config?.options, // just in case config is missing somehow
154
- brands,
155
- FastUSDCConfigShape,
156
- );
157
- trace('using terms', terms);
158
- trace('using fee config', feeConfig);
159
-
160
- trace('look up oracle deposit facets');
161
- const oracleDepositFacets = await deeplyFulfilledObject(
162
- objectMap(oracles, async address => {
163
- /** @type {DepositFacet} */
164
- const depositFacet = await E(namesByAddress).lookup(
165
- address,
166
- 'depositFacet',
167
- );
168
- return depositFacet;
169
- }),
170
- );
171
-
172
- const { storageNode, marshaller } = await makePublishingStorageKit(
173
- contractName,
174
- {
175
- board,
176
- // @ts-expect-error Promise<null> case is vestigial
177
- chainStorage,
178
- },
179
- );
180
-
181
- const privateArgs = await deeplyFulfilledObject(
182
- harden({
183
- agoricNames,
184
- feeConfig,
185
- localchain,
186
- orchestrationService: cosmosInterchainService,
187
- storageNode,
188
- timerService,
189
- marshaller,
190
- }),
191
- );
192
-
193
- const kit = await E(startUpgradable)({
194
- label: contractName,
195
- installation: fastUsdc,
196
- issuerKeywordRecord: harden({ USDC: USDCissuer }),
197
- terms,
198
- privateArgs,
199
- });
200
- fastUsdcKit.resolve(harden({ ...kit, privateArgs }));
201
- const { instance, creatorFacet } = kit;
202
-
203
- await publishFeedPolicy(storageNode, feedPolicy);
204
-
205
- const {
206
- issuers: { PoolShares: shareIssuer },
207
- brands: { PoolShares: shareBrand },
208
- } = await E(zoe).getTerms(instance);
209
- produceShareIssuer.resolve(shareIssuer);
210
- produceShareBrand.resolve(shareBrand);
211
- await publishDisplayInfo(shareBrand, { board, chainStorage });
212
-
213
- await Promise.all(
214
- Object.entries(oracleDepositFacets).map(async ([name, depositFacet]) => {
215
- const address = oracles[name];
216
- trace('making invitation for', name, address);
217
- const toWatch = await E(creatorFacet).makeOperatorInvitation(address);
218
-
219
- const amt = await E(depositFacet).receive(toWatch);
220
- trace('sent', amt, 'to', name);
221
- }),
222
- );
223
-
224
- produceInstance.reset();
225
- produceInstance.resolve(instance);
226
- trace('startFastUSDC done', instance);
227
- };
228
- harden(startFastUSDC);
229
-
230
- /**
231
- * @param {{
232
- * restoreRef: (b: ERef<ManifestBundleRef>) => Promise<Installation>;
233
- * }} utils
234
- * @param {{
235
- * installKeys: { fastUsdc: ERef<ManifestBundleRef> };
236
- * options: LegibleCapData<FastUSDCConfig>;
237
- * }} param1
238
- */
239
- export const getManifestForFastUSDC = (
240
- { restoreRef },
241
- { installKeys, options },
242
- ) => {
243
- return {
244
- /** @type {BootstrapManifest} */
245
- manifest: {
246
- [startFastUSDC.name]: {
247
- produce: {
248
- fastUsdcKit: true,
249
- },
250
- consume: {
251
- chainStorage: true,
252
- chainTimerService: true,
253
- localchain: true,
254
- cosmosInterchainService: true,
255
-
256
- // limited distribution durin MN2: contract installation
257
- startUpgradable: true,
258
- zoe: true, // only getTerms() is needed. XXX should be split?
259
-
260
- // widely shared: name services
261
- agoricNames: true,
262
- namesByAddress: true,
263
- board: true,
264
- },
265
- issuer: {
266
- produce: { FastLP: true }, // UNTIL #10432
267
- },
268
- brand: {
269
- produce: { FastLP: true }, // UNTIL #10432
270
- },
271
- instance: {
272
- produce: { fastUsdc: true },
273
- },
274
- installation: {
275
- consume: { fastUsdc: true },
276
- },
277
- },
278
- },
279
- installations: {
280
- fastUsdc: restoreRef(installKeys.fastUsdc),
281
- },
282
- options,
283
- };
284
- };
@@ -1,12 +0,0 @@
1
- /** @import { VStorage } from '@agoric/client-utils' */
2
-
3
- export const queryFastUSDCLocalChainAccount = async (
4
- /** @type {VStorage} */ vstorage,
5
- out = console,
6
- ) => {
7
- const agoricAddr = await vstorage.readLatest(
8
- 'published.fastUSDC.settlementAccount',
9
- );
10
- out.log(`Got Fast USDC Local Chain Account ${agoricAddr}`);
11
- return agoricAddr;
12
- };
@@ -1,71 +0,0 @@
1
- import { makeError, q } from '@endo/errors';
2
- import { M, mustMatch } from '@endo/patterns';
3
-
4
- /**
5
- * @import {Pattern} from '@endo/patterns';
6
- */
7
-
8
- /**
9
- * Default pattern matcher for `getQueryParams`.
10
- * Does not assert keys exist, but ensures existing keys are strings.
11
- */
12
- const QueryParamsShape = M.splitRecord(
13
- {},
14
- {},
15
- M.recordOf(M.string(), M.string()),
16
- );
17
-
18
- /**
19
- * Very minimal 'URL query string'-like parser that handles:
20
- * - Query string delimiter (?)
21
- * - Key-value separator (=)
22
- * - Query parameter separator (&)
23
- *
24
- * Does not handle:
25
- * - Subpaths (`agoric1bech32addr/opt/account?k=v`)
26
- * - URI encoding/decoding (`%20` -> ` `)
27
- * - note: `decodeURIComponent` seems to be available in XS
28
- * - Multiple question marks (foo?bar=1?baz=2)
29
- * - Empty parameters (foo=)
30
- * - Array parameters (`foo?k=v1&k=v2` -> k: [v1, v2])
31
- * - Parameters without values (foo&bar=2)
32
- */
33
- export const addressTools = {
34
- /**
35
- * @param {string} address
36
- * @returns {boolean}
37
- */
38
- hasQueryParams: address => {
39
- try {
40
- const params = addressTools.getQueryParams(address);
41
- return Object.keys(params).length > 0;
42
- } catch {
43
- return false;
44
- }
45
- },
46
- /**
47
- * @param {string} address
48
- * @param {Pattern} [shape]
49
- * @returns {Record<string, string>}
50
- * @throws {Error} if the address cannot be parsed or params do not match `shape`
51
- */
52
- getQueryParams: (address, shape = QueryParamsShape) => {
53
- const parts = address.split('?');
54
- if (parts.length !== 2) {
55
- throw makeError(`Unable to parse query params: ${q(address)}`);
56
- }
57
- /** @type {Record<string, string>} */
58
- const result = {};
59
- const paramPairs = parts[1].split('&');
60
- for (const pair of paramPairs) {
61
- const [key, value] = pair.split('=');
62
- if (!key || !value) {
63
- throw makeError(`Invalid parameter format in pair: ${q(pair)}`);
64
- }
65
- result[key] = value;
66
- }
67
- harden(result);
68
- mustMatch(result, shape);
69
- return result;
70
- },
71
- };