From 0a4179ba0064b7325847ac4c49c6e9b5b5facb70 Mon Sep 17 00:00:00 2001 From: Turadg Aleahmad Date: Mon, 13 Jan 2025 12:02:00 -0800 Subject: [PATCH 1/8] refactor: rename .start.js to .core.js --- packages/boot/tools/supports.ts | 2 +- packages/builders/scripts/fast-usdc/init-fast-usdc.js | 10 +++++----- packages/fast-usdc/src/fast-usdc-policy.core.js | 2 +- .../{fast-usdc.start.js => start-fast-usdc.core.js} | 0 4 files changed, 7 insertions(+), 7 deletions(-) rename packages/fast-usdc/src/{fast-usdc.start.js => start-fast-usdc.core.js} (100%) diff --git a/packages/boot/tools/supports.ts b/packages/boot/tools/supports.ts index 8f17cb2be16..35959613993 100644 --- a/packages/boot/tools/supports.ts +++ b/packages/boot/tools/supports.ts @@ -48,7 +48,7 @@ import type { SwingsetController } from '@agoric/swingset-vat/src/controller/con import type { BridgeHandler, IBCDowncallMethod, IBCMethod } from '@agoric/vats'; import type { BootstrapRootObject } from '@agoric/vats/src/core/lib-boot.js'; import type { EProxy } from '@endo/eventual-send'; -import type { FastUSDCCorePowers } from '@agoric/fast-usdc/src/fast-usdc.start.js'; +import type { FastUSDCCorePowers } from '@agoric/fast-usdc/src/start-fast-usdc.core.js'; import { defaultBeansPerVatCreation, defaultBeansPerXsnapComputron, diff --git a/packages/builders/scripts/fast-usdc/init-fast-usdc.js b/packages/builders/scripts/fast-usdc/init-fast-usdc.js index 44187137f4b..ba38b80675a 100644 --- a/packages/builders/scripts/fast-usdc/init-fast-usdc.js +++ b/packages/builders/scripts/fast-usdc/init-fast-usdc.js @@ -1,10 +1,6 @@ // @ts-check import { makeHelpers } from '@agoric/deploy-script-support'; import { AmountMath } from '@agoric/ertp'; -import { - FastUSDCConfigShape, - getManifestForFastUSDC, -} from '@agoric/fast-usdc/src/fast-usdc.start.js'; import { toExternalConfig } from '@agoric/fast-usdc/src/utils/config-marshal.js'; import { configurations } from '@agoric/fast-usdc/src/utils/deploy-config.js'; import { @@ -13,6 +9,10 @@ import { } from '@agoric/zoe/src/contractSupport/ratio.js'; import { Far } from '@endo/far'; import { parseArgs } from 'node:util'; +import { + FastUSDCConfigShape, + getManifestForFastUSDC, +} from '@agoric/fast-usdc/src/start-fast-usdc.core.js'; /** * @import {CoreEvalBuilder, DeployScriptFunction} from '@agoric/deploy-script-support/src/externalTypes.js' @@ -78,7 +78,7 @@ export const defaultProposalBuilder = async ( /** @type {FastUSDCConfig} */ config, ) => { return harden({ - sourceSpec: '@agoric/fast-usdc/src/fast-usdc.start.js', + sourceSpec: '@agoric/fast-usdc/src/start-fast-usdc.core.js', /** @type {[string, Parameters[1]]} */ getManifestCall: [ getManifestForFastUSDC.name, diff --git a/packages/fast-usdc/src/fast-usdc-policy.core.js b/packages/fast-usdc/src/fast-usdc-policy.core.js index 431c0c61524..ee38762a062 100644 --- a/packages/fast-usdc/src/fast-usdc-policy.core.js +++ b/packages/fast-usdc/src/fast-usdc-policy.core.js @@ -19,7 +19,7 @@ const FEED_POLICY = 'feedPolicy'; const marshalData = makeMarshal(_val => Fail`data only`); /** - * XXX copied from fast-usdc.start.js + * XXX copied from start-fast-usdc.core.js * * @param {ERef} node * @param {FeedPolicy} policy diff --git a/packages/fast-usdc/src/fast-usdc.start.js b/packages/fast-usdc/src/start-fast-usdc.core.js similarity index 100% rename from packages/fast-usdc/src/fast-usdc.start.js rename to packages/fast-usdc/src/start-fast-usdc.core.js From b73f6993afd240fe88d8f72be8353718918f4d36 Mon Sep 17 00:00:00 2001 From: Turadg Aleahmad Date: Mon, 13 Jan 2025 15:07:36 -0800 Subject: [PATCH 2/8] refactor: name start-fast-usdc.build.js --- a3p-integration/proposals/f:fast-usdc/package.json | 2 +- multichain-testing/scripts/fast-usdc-tool.ts | 2 +- multichain-testing/test/fast-usdc/fast-usdc.test.ts | 2 +- packages/boot/test/fast-usdc/fast-usdc.test.ts | 2 +- .../fast-usdc/{init-fast-usdc.js => start-fast-usdc.build.js} | 0 5 files changed, 4 insertions(+), 4 deletions(-) rename packages/builders/scripts/fast-usdc/{init-fast-usdc.js => start-fast-usdc.build.js} (100%) diff --git a/a3p-integration/proposals/f:fast-usdc/package.json b/a3p-integration/proposals/f:fast-usdc/package.json index 0c5eee5fa79..dfe43ef1501 100644 --- a/a3p-integration/proposals/f:fast-usdc/package.json +++ b/a3p-integration/proposals/f:fast-usdc/package.json @@ -2,7 +2,7 @@ "agoricProposal": { "source": "subdir", "sdk-generate": [ - "fast-usdc/init-fast-usdc.js submission --net A3P_INTEGRATION --noNoble" + "fast-usdc/start-fast-usdc.build.js submission --net A3P_INTEGRATION --noNoble" ], "type": "/agoric.swingset.CoreEvalProposal" }, diff --git a/multichain-testing/scripts/fast-usdc-tool.ts b/multichain-testing/scripts/fast-usdc-tool.ts index 09cfc72f6a5..2a927777f4a 100755 --- a/multichain-testing/scripts/fast-usdc-tool.ts +++ b/multichain-testing/scripts/fast-usdc-tool.ts @@ -41,7 +41,7 @@ Examples: const contractName = 'fastUsdc'; const contractBuilder = - '../packages/builders/scripts/fast-usdc/init-fast-usdc.js'; + '../packages/builders/scripts/fast-usdc/start-fast-usdc.build.js'; /** ava test context partial, to appease dependencies expecting this */ const runT = { diff --git a/multichain-testing/test/fast-usdc/fast-usdc.test.ts b/multichain-testing/test/fast-usdc/fast-usdc.test.ts index 587989ff82b..c86361e20b6 100644 --- a/multichain-testing/test/fast-usdc/fast-usdc.test.ts +++ b/multichain-testing/test/fast-usdc/fast-usdc.test.ts @@ -44,7 +44,7 @@ const test = anyTest as TestFn< const accounts = [...keys(oracleMnemonics), 'lp']; const contractName = 'fastUsdc'; const contractBuilder = - '../packages/builders/scripts/fast-usdc/init-fast-usdc.js'; + '../packages/builders/scripts/fast-usdc/start-fast-usdc.build.js'; const LP_DEPOSIT_AMOUNT = 8_000n * 10n ** 6n; test.before(async t => { diff --git a/packages/boot/test/fast-usdc/fast-usdc.test.ts b/packages/boot/test/fast-usdc/fast-usdc.test.ts index 4d5eb541799..ea9a48f1c85 100644 --- a/packages/boot/test/fast-usdc/fast-usdc.test.ts +++ b/packages/boot/test/fast-usdc/fast-usdc.test.ts @@ -86,7 +86,7 @@ test.serial( bridgeUtils.setBech32Prefix('noble'); const materials = buildProposal( - '@agoric/builders/scripts/fast-usdc/init-fast-usdc.js', + '@agoric/builders/scripts/fast-usdc/start-fast-usdc.build.js', ['--net', 'MAINNET'], ); await evalProposal(materials); diff --git a/packages/builders/scripts/fast-usdc/init-fast-usdc.js b/packages/builders/scripts/fast-usdc/start-fast-usdc.build.js similarity index 100% rename from packages/builders/scripts/fast-usdc/init-fast-usdc.js rename to packages/builders/scripts/fast-usdc/start-fast-usdc.build.js From 71f7add96c91306a5b0b7deb687e06b4411c68df Mon Sep 17 00:00:00 2001 From: Turadg Aleahmad Date: Mon, 13 Jan 2025 12:07:02 -0800 Subject: [PATCH 3/8] refactor: extract publishFeedPolicy --- .../fast-usdc/src/fast-usdc-policy.core.js | 17 +------------ .../fast-usdc/src/start-fast-usdc.core.js | 12 +--------- packages/fast-usdc/src/utils/core-eval.js | 24 +++++++++++++++++++ 3 files changed, 26 insertions(+), 27 deletions(-) create mode 100644 packages/fast-usdc/src/utils/core-eval.js diff --git a/packages/fast-usdc/src/fast-usdc-policy.core.js b/packages/fast-usdc/src/fast-usdc-policy.core.js index ee38762a062..8ff4a76968d 100644 --- a/packages/fast-usdc/src/fast-usdc-policy.core.js +++ b/packages/fast-usdc/src/fast-usdc-policy.core.js @@ -1,10 +1,9 @@ /** @file core-eval to publish update to Fast USDC feedPolicy */ import { E } from '@endo/far'; -import { makeMarshal } from '@endo/marshal'; -import { Fail } from '@endo/errors'; import { fromExternalConfig } from './utils/config-marshal.js'; import { FeedPolicyShape } from './type-guards.js'; +import { publishFeedPolicy } from './utils/core-eval.js'; /** * @import {Issuer} from '@agoric/ertp'; @@ -15,20 +14,6 @@ import { FeedPolicyShape } from './type-guards.js'; */ const contractName = 'fastUsdc'; -const FEED_POLICY = 'feedPolicy'; -const marshalData = makeMarshal(_val => Fail`data only`); - -/** - * XXX copied from start-fast-usdc.core.js - * - * @param {ERef} node - * @param {FeedPolicy} policy - */ -const publishFeedPolicy = async (node, policy) => { - const feedPolicy = E(node).makeChildNode(FEED_POLICY); - const value = marshalData.toCapData(policy); - await E(feedPolicy).setValue(JSON.stringify(value)); -}; /** * @param {BootstrapPowers & diff --git a/packages/fast-usdc/src/start-fast-usdc.core.js b/packages/fast-usdc/src/start-fast-usdc.core.js index 2be12397286..20388bee239 100644 --- a/packages/fast-usdc/src/start-fast-usdc.core.js +++ b/packages/fast-usdc/src/start-fast-usdc.core.js @@ -14,6 +14,7 @@ import { FeedPolicyShape, } from './type-guards.js'; import { fromExternalConfig } from './utils/config-marshal.js'; +import { publishFeedPolicy } from './utils/core-eval.js'; /** * @import {Amount, Brand, DepositFacet, Issuer, Payment} from '@agoric/ertp'; @@ -85,19 +86,8 @@ const publishDisplayInfo = async (brand, { board, chainStorage }) => { await E(node).setValue(JSON.stringify(aux)); }; -const FEED_POLICY = 'feedPolicy'; const POOL_METRICS = 'poolMetrics'; -/** - * @param {ERef} node - * @param {FeedPolicy} policy - */ -const publishFeedPolicy = async (node, policy) => { - const feedPolicy = E(node).makeChildNode(FEED_POLICY); - const value = marshalData.toCapData(policy); - await E(feedPolicy).setValue(JSON.stringify(value)); -}; - /** * @typedef { PromiseSpaceOf<{ * fastUsdcKit: FastUSDCKit diff --git a/packages/fast-usdc/src/utils/core-eval.js b/packages/fast-usdc/src/utils/core-eval.js new file mode 100644 index 00000000000..017d3fb1627 --- /dev/null +++ b/packages/fast-usdc/src/utils/core-eval.js @@ -0,0 +1,24 @@ +import { Fail } from '@endo/errors'; +import { E } from '@endo/eventual-send'; +import { makeMarshal } from '@endo/marshal'; + +/** + * @import {Issuer} from '@agoric/ertp'; + * @import {Passable} from '@endo/pass-style' + * @import {BootstrapManifest} from '@agoric/vats/src/core/lib-boot.js' + * @import {LegibleCapData} from './utils/config-marshal.js' + * @import {FeedPolicy} from '../types.js' + */ + +export const FEED_POLICY = 'feedPolicy'; +export const marshalData = makeMarshal(_val => Fail`data only`); + +/** + * @param {ERef} node + * @param {FeedPolicy} policy + */ +export const publishFeedPolicy = async (node, policy) => { + const feedPolicy = E(node).makeChildNode(FEED_POLICY); + const value = marshalData.toCapData(policy); + await E(feedPolicy).setValue(JSON.stringify(value)); +}; From 8295bed248875cda98adfcce5dff3a1fcedb6c3c Mon Sep 17 00:00:00 2001 From: Turadg Aleahmad Date: Mon, 13 Jan 2025 12:18:06 -0800 Subject: [PATCH 4/8] refactor: extract inviteOracles --- .../fast-usdc/src/start-fast-usdc.core.js | 27 ++------------ packages/fast-usdc/src/utils/core-eval.js | 36 +++++++++++++++++-- 2 files changed, 37 insertions(+), 26 deletions(-) diff --git a/packages/fast-usdc/src/start-fast-usdc.core.js b/packages/fast-usdc/src/start-fast-usdc.core.js index 20388bee239..87c9c88ec44 100644 --- a/packages/fast-usdc/src/start-fast-usdc.core.js +++ b/packages/fast-usdc/src/start-fast-usdc.core.js @@ -1,4 +1,4 @@ -import { deeplyFulfilledObject, makeTracer, objectMap } from '@agoric/internal'; +import { deeplyFulfilledObject, makeTracer } from '@agoric/internal'; import { CosmosChainInfoShape, DenomDetailShape, @@ -14,7 +14,7 @@ import { FeedPolicyShape, } from './type-guards.js'; import { fromExternalConfig } from './utils/config-marshal.js'; -import { publishFeedPolicy } from './utils/core-eval.js'; +import { inviteOracles, publishFeedPolicy } from './utils/core-eval.js'; /** * @import {Amount, Brand, DepositFacet, Issuer, Payment} from '@agoric/ertp'; @@ -157,18 +157,6 @@ export const startFastUSDC = async ( trace('using terms', terms); trace('using fee config', feeConfig); - trace('look up oracle deposit facets'); - const oracleDepositFacets = await deeplyFulfilledObject( - objectMap(oracles, async address => { - /** @type {DepositFacet} */ - const depositFacet = await E(namesByAddress).lookup( - address, - 'depositFacet', - ); - return depositFacet; - }), - ); - const { storageNode, marshaller } = await makePublishingStorageKit( contractName, { @@ -224,16 +212,7 @@ export const startFastUSDC = async ( brand: shareBrand, }); - await Promise.all( - Object.entries(oracleDepositFacets).map(async ([name, depositFacet]) => { - const address = oracles[name]; - trace('making invitation for', name, address); - const toWatch = await E(creatorFacet).makeOperatorInvitation(address); - - const amt = await E(depositFacet).receive(toWatch); - trace('sent', amt, 'to', name); - }), - ); + await inviteOracles({ creatorFacet, namesByAddress }, oracles); produceInstance.reset(); produceInstance.resolve(instance); diff --git a/packages/fast-usdc/src/utils/core-eval.js b/packages/fast-usdc/src/utils/core-eval.js index 017d3fb1627..70784d97eb2 100644 --- a/packages/fast-usdc/src/utils/core-eval.js +++ b/packages/fast-usdc/src/utils/core-eval.js @@ -1,12 +1,15 @@ +import { deeplyFulfilledObject, makeTracer, objectMap } from '@agoric/internal'; import { Fail } from '@endo/errors'; import { E } from '@endo/eventual-send'; import { makeMarshal } from '@endo/marshal'; +const trace = makeTracer('FUCoreEval'); + /** - * @import {Issuer} from '@agoric/ertp'; + * @import {Amount, Brand, DepositFacet, Issuer, Payment} from '@agoric/ertp'; * @import {Passable} from '@endo/pass-style' * @import {BootstrapManifest} from '@agoric/vats/src/core/lib-boot.js' - * @import {LegibleCapData} from './utils/config-marshal.js' + * @import {FastUSDCKit} from '../start-fast-usdc.core.js' * @import {FeedPolicy} from '../types.js' */ @@ -22,3 +25,32 @@ export const publishFeedPolicy = async (node, policy) => { const value = marshalData.toCapData(policy); await E(feedPolicy).setValue(JSON.stringify(value)); }; + +/** + * @param {object} powers + * @param {FastUSDCKit['creatorFacet']} powers.creatorFacet + * @param {BootstrapPowers['consume']['namesByAddress']} powers.namesByAddress + * @param {Record} oracles + */ +export const inviteOracles = async ( + { creatorFacet, namesByAddress }, + oracles, +) => { + const oracleDepositFacets = await deeplyFulfilledObject( + objectMap( + oracles, + /** @type {(address: string) => Promise} */ + address => E(namesByAddress).lookup(address, 'depositFacet'), + ), + ); + await Promise.all( + Object.entries(oracleDepositFacets).map(async ([name, depositFacet]) => { + const address = oracles[name]; + trace('making invitation for', name, address); + const toWatch = await E(creatorFacet).makeOperatorInvitation(address); + + const amt = await E(depositFacet).receive(toWatch); + trace('sent', amt, 'to', name); + }), + ); +}; From 9e3edbfd3d98efb196ae500809bce9b074fc3913 Mon Sep 17 00:00:00 2001 From: Turadg Aleahmad Date: Mon, 13 Jan 2025 15:40:49 -0800 Subject: [PATCH 5/8] refactor: extract FastUSDCConfigShape --- .../fast-usdc/start-fast-usdc.build.js | 6 ++--- .../fast-usdc/src/start-fast-usdc.core.js | 22 +------------------ packages/fast-usdc/src/type-guards.js | 17 +++++++++++++- 3 files changed, 19 insertions(+), 26 deletions(-) diff --git a/packages/builders/scripts/fast-usdc/start-fast-usdc.build.js b/packages/builders/scripts/fast-usdc/start-fast-usdc.build.js index ba38b80675a..924b6724da8 100644 --- a/packages/builders/scripts/fast-usdc/start-fast-usdc.build.js +++ b/packages/builders/scripts/fast-usdc/start-fast-usdc.build.js @@ -1,6 +1,8 @@ // @ts-check import { makeHelpers } from '@agoric/deploy-script-support'; import { AmountMath } from '@agoric/ertp'; +import { getManifestForFastUSDC } from '@agoric/fast-usdc/src/start-fast-usdc.core.js'; +import { FastUSDCConfigShape } from '@agoric/fast-usdc/src/type-guards.js'; import { toExternalConfig } from '@agoric/fast-usdc/src/utils/config-marshal.js'; import { configurations } from '@agoric/fast-usdc/src/utils/deploy-config.js'; import { @@ -9,10 +11,6 @@ import { } from '@agoric/zoe/src/contractSupport/ratio.js'; import { Far } from '@endo/far'; import { parseArgs } from 'node:util'; -import { - FastUSDCConfigShape, - getManifestForFastUSDC, -} from '@agoric/fast-usdc/src/start-fast-usdc.core.js'; /** * @import {CoreEvalBuilder, DeployScriptFunction} from '@agoric/deploy-script-support/src/externalTypes.js' diff --git a/packages/fast-usdc/src/start-fast-usdc.core.js b/packages/fast-usdc/src/start-fast-usdc.core.js index 87c9c88ec44..1474c17fdc6 100644 --- a/packages/fast-usdc/src/start-fast-usdc.core.js +++ b/packages/fast-usdc/src/start-fast-usdc.core.js @@ -1,18 +1,8 @@ import { deeplyFulfilledObject, makeTracer } from '@agoric/internal'; -import { - CosmosChainInfoShape, - DenomDetailShape, - DenomShape, -} from '@agoric/orchestration'; import { Fail } from '@endo/errors'; import { E } from '@endo/far'; import { makeMarshal } from '@endo/marshal'; -import { M } from '@endo/patterns'; -import { - FastUSDCTermsShape, - FeeConfigShape, - FeedPolicyShape, -} from './type-guards.js'; +import { FastUSDCConfigShape } from './type-guards.js'; import { fromExternalConfig } from './utils/config-marshal.js'; import { inviteOracles, publishFeedPolicy } from './utils/core-eval.js'; @@ -40,16 +30,6 @@ const trace = makeTracer('FUSD-Start', true); const contractName = 'fastUsdc'; -/** @type {TypedPattern} */ -export const FastUSDCConfigShape = M.splitRecord({ - terms: FastUSDCTermsShape, - oracles: M.recordOf(M.string(), M.string()), - feeConfig: FeeConfigShape, - feedPolicy: FeedPolicyShape, - chainInfo: M.recordOf(M.string(), CosmosChainInfoShape), - assetInfo: M.arrayOf([DenomShape, DenomDetailShape]), -}); - /** * XXX Shouldn't the bridge or board vat handle this? * diff --git a/packages/fast-usdc/src/type-guards.js b/packages/fast-usdc/src/type-guards.js index 5ece98c4ac9..b365f53dbb7 100644 --- a/packages/fast-usdc/src/type-guards.js +++ b/packages/fast-usdc/src/type-guards.js @@ -1,5 +1,10 @@ import { AmountShape, BrandShape, RatioShape } from '@agoric/ertp'; import { M } from '@endo/patterns'; +import { + CosmosChainInfoShape, + DenomDetailShape, + DenomShape, +} from '@agoric/orchestration'; import { PendingTxStatus } from './constants.js'; /** @@ -7,7 +12,7 @@ import { PendingTxStatus } from './constants.js'; * @import {TypedPattern} from '@agoric/internal'; * @import {FastUsdcTerms} from './fast-usdc.contract.js'; * @import {USDCProposalShapes} from './pool-share-math.js'; - * @import {CctpTxEvidence, FeeConfig, PendingTx, PoolMetrics, ChainPolicy, FeedPolicy, AddressHook, EvmAddress, EvmHash, RiskAssessment, EvidenceWithRisk} from './types.js'; + * @import {CctpTxEvidence, FastUSDCConfig, FeeConfig, PendingTx, PoolMetrics, ChainPolicy, FeedPolicy, AddressHook, EvmAddress, EvmHash, RiskAssessment, EvidenceWithRisk} from './types.js'; */ /** @@ -153,3 +158,13 @@ export const FeedPolicyShape = M.splitRecord( { eventFilter: M.string() }, ); harden(FeedPolicyShape); + +/** @type {TypedPattern} */ +export const FastUSDCConfigShape = M.splitRecord({ + terms: FastUSDCTermsShape, + oracles: M.recordOf(M.string(), M.string()), + feeConfig: FeeConfigShape, + feedPolicy: FeedPolicyShape, + chainInfo: M.recordOf(M.string(), CosmosChainInfoShape), + assetInfo: M.arrayOf([DenomShape, DenomDetailShape]), +}); From 92c964552dba91707eedee28acc1d61fb66c6e99 Mon Sep 17 00:00:00 2001 From: Turadg Aleahmad Date: Mon, 13 Jan 2025 15:47:47 -0800 Subject: [PATCH 6/8] chore(types): satisfies CoreEvalBuilder --- .../src/register-interchain-bank-assets.builder.js | 2 +- .../scripts/fast-usdc/fast-usdc-update.build.js | 10 +++++++--- .../scripts/fast-usdc/start-fast-usdc.build.js | 8 ++++++-- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/multichain-testing/src/register-interchain-bank-assets.builder.js b/multichain-testing/src/register-interchain-bank-assets.builder.js index 0417c2b92d5..1dd9562a4ff 100644 --- a/multichain-testing/src/register-interchain-bank-assets.builder.js +++ b/multichain-testing/src/register-interchain-bank-assets.builder.js @@ -13,7 +13,7 @@ const parserOpts = { assets: { type: 'string' }, }; -/** @type {CoreEvalBuilder} */ +/** @satisfies {CoreEvalBuilder} */ export const defaultProposalBuilder = async (_, options) => { return harden({ sourceSpec: diff --git a/packages/builders/scripts/fast-usdc/fast-usdc-update.build.js b/packages/builders/scripts/fast-usdc/fast-usdc-update.build.js index 21a1e6a0573..3613a3d7241 100644 --- a/packages/builders/scripts/fast-usdc/fast-usdc-update.build.js +++ b/packages/builders/scripts/fast-usdc/fast-usdc-update.build.js @@ -22,10 +22,14 @@ const feedPolicyUsage = 'use --feedPolicy ...'; * }} FastUSDCUpdateOpts */ -/** @type {CoreEvalBuilder} */ +/** + * @param {Parameters[0]} powers + * @param {FastUSDCConfig} config + * @satisfies {CoreEvalBuilder} + */ export const updateProposalBuilder = async ( - _utils, - /** @type {FastUSDCConfig} */ config, + powers, + /** @type {Pick} */ config, ) => { return harden({ sourceSpec: '@agoric/fast-usdc/src/fast-usdc-policy.core.js', diff --git a/packages/builders/scripts/fast-usdc/start-fast-usdc.build.js b/packages/builders/scripts/fast-usdc/start-fast-usdc.build.js index 924b6724da8..6627bec82d3 100644 --- a/packages/builders/scripts/fast-usdc/start-fast-usdc.build.js +++ b/packages/builders/scripts/fast-usdc/start-fast-usdc.build.js @@ -70,10 +70,14 @@ const { USDC } = crossVatContext; const USDC_DECIMALS = 6; const unit = AmountMath.make(USDC, 10n ** BigInt(USDC_DECIMALS)); -/** @type {CoreEvalBuilder} */ +/** + * @param {Parameters[0]} powers + * @param {FastUSDCConfig} config + * @satisfies {CoreEvalBuilder} + */ export const defaultProposalBuilder = async ( { publishRef, install }, - /** @type {FastUSDCConfig} */ config, + config, ) => { return harden({ sourceSpec: '@agoric/fast-usdc/src/start-fast-usdc.core.js', From 7191f0b7ed8f264db0167d3d695b05fe3dfaafad Mon Sep 17 00:00:00 2001 From: Turadg Aleahmad Date: Mon, 13 Jan 2025 17:36:37 -0800 Subject: [PATCH 7/8] test: print wallets --- a3p-integration/proposals/f:fast-usdc/test.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/a3p-integration/proposals/f:fast-usdc/test.sh b/a3p-integration/proposals/f:fast-usdc/test.sh index f6097021cf2..71ea56a567b 100755 --- a/a3p-integration/proposals/f:fast-usdc/test.sh +++ b/a3p-integration/proposals/f:fast-usdc/test.sh @@ -1,6 +1,9 @@ #!/bin/bash set -euo pipefail +echo AVAILABLE WALLETs +agd query vstorage children published.wallet + yarn ava ./test-cli.sh From da7c727b5318a60c13b41a7fca857b2a95d89250 Mon Sep 17 00:00:00 2001 From: Turadg Aleahmad Date: Mon, 13 Jan 2025 13:23:05 -0800 Subject: [PATCH 8/8] test: add operators --- .../proposals/f:fast-usdc/.gitignore | 1 + .../proposals/f:fast-usdc/deploy.test.js | 9 +- .../proposals/f:fast-usdc/operators.test.js | 78 +++++++++++++++++ .../proposals/f:fast-usdc/package.json | 3 +- .../boot/test/fast-usdc/fast-usdc.test.ts | 51 +++++++++++- .../scripts/fast-usdc/add-operators.build.js | 83 +++++++++++++++++++ packages/fast-usdc/src/add-operators.core.js | 63 ++++++++++++++ 7 files changed, 278 insertions(+), 10 deletions(-) create mode 100644 a3p-integration/proposals/f:fast-usdc/.gitignore create mode 100644 a3p-integration/proposals/f:fast-usdc/operators.test.js create mode 100644 packages/builders/scripts/fast-usdc/add-operators.build.js create mode 100644 packages/fast-usdc/src/add-operators.core.js diff --git a/a3p-integration/proposals/f:fast-usdc/.gitignore b/a3p-integration/proposals/f:fast-usdc/.gitignore new file mode 100644 index 00000000000..f12e6f870ca --- /dev/null +++ b/a3p-integration/proposals/f:fast-usdc/.gitignore @@ -0,0 +1 @@ +add-operators diff --git a/a3p-integration/proposals/f:fast-usdc/deploy.test.js b/a3p-integration/proposals/f:fast-usdc/deploy.test.js index 1bc0aa6b4d8..991766a29f5 100644 --- a/a3p-integration/proposals/f:fast-usdc/deploy.test.js +++ b/a3p-integration/proposals/f:fast-usdc/deploy.test.js @@ -2,19 +2,14 @@ /* eslint-env node */ import test from 'ava'; import '@endo/init/legacy.js'; // axios compat -import { makeSmartWalletKit } from '@agoric/client-utils'; +import { LOCAL_CONFIG, makeSmartWalletKit } from '@agoric/client-utils'; const io = { delay: ms => new Promise(resolve => setTimeout(() => resolve(undefined), ms)), fetch: global.fetch, }; -const networkConfig = { - rpcAddrs: ['http://0.0.0.0:26657'], - chainName: 'agoriclocal', -}; - test('fastUsdc is in agoricNames.instance', async t => { - const { agoricNames } = await makeSmartWalletKit(io, networkConfig); + const { agoricNames } = await makeSmartWalletKit(io, LOCAL_CONFIG); t.log('agoricNames.instance keys', Object.keys(agoricNames.instance)); t.truthy(agoricNames.instance.fastUsdc); diff --git a/a3p-integration/proposals/f:fast-usdc/operators.test.js b/a3p-integration/proposals/f:fast-usdc/operators.test.js new file mode 100644 index 00000000000..5b63acd77f2 --- /dev/null +++ b/a3p-integration/proposals/f:fast-usdc/operators.test.js @@ -0,0 +1,78 @@ +/* eslint-env node */ +import unknownTest from 'ava'; + +import '@endo/init/legacy.js'; // axios compat + +import { LOCAL_CONFIG, makeVstorageKit } from '@agoric/client-utils'; +import { evalBundles, waitForBlock } from '@agoric/synthetic-chain'; + +// XXX ~copied to not take a dependency on Zoe +/** + * @typedef {object} InvitationDetails + * @property {unknown} installation + * @property {unknown} instance + * @property {InvitationHandle} handle + * @property {string} description + * @property {Record} [customDetails] + */ + +/** + * @import {VstorageKit} from '@agoric/client-utils'; + */ + +const test = /** @type {import('ava').TestFn<{ vstorageKit: VstorageKit}>} */ ( + unknownTest +); + +const ADD_OPERATORS_DIR = 'add-operators'; + +/** + * @typedef {import('@agoric/ertp').NatAmount} NatAmount + * @typedef {{ + * allocations: { Fee: NatAmount, USD_LEMONS: NatAmount }, + * }} ReserveAllocations + */ + +test.before(async t => { + const vstorageKit = makeVstorageKit({ fetch }, LOCAL_CONFIG); + + t.context = { + vstorageKit, + }; +}); + +test.serial('add operators', async t => { + const { vstorageKit } = t.context; + + const walletPath = + // account mem3 in test of crabble-start proposal (64) + // This must match the oracleNew value in the add-operators builder argument + 'wallet.agoric1hmdue96vs0p6zj42aa26x6zrqlythpxnvgsgpr.current'; + + const readInvitationsPurseBalance = async () => { + const curr = await vstorageKit.readPublished(walletPath); + return /** @type {InvitationDetails[]} */ (curr.purses[0].balance.value); + }; + + let numInvitationsBefore = 0; + { + const invBalance = await readInvitationsPurseBalance(); + numInvitationsBefore = invBalance.length; + t.false( + invBalance.some(inv => inv.description === 'oracle operator invitation'), + ); + } + + await evalBundles(ADD_OPERATORS_DIR); + // give time for the invitations to be deposited + await waitForBlock(5); + + { + const invBalance = await readInvitationsPurseBalance(); + console.log('after', invBalance); + t.is(invBalance.length, numInvitationsBefore + 1); + t.true( + invBalance.some(inv => inv.description === 'oracle operator invitation'), + ); + } +}); diff --git a/a3p-integration/proposals/f:fast-usdc/package.json b/a3p-integration/proposals/f:fast-usdc/package.json index dfe43ef1501..a92e00c165b 100644 --- a/a3p-integration/proposals/f:fast-usdc/package.json +++ b/a3p-integration/proposals/f:fast-usdc/package.json @@ -2,7 +2,8 @@ "agoricProposal": { "source": "subdir", "sdk-generate": [ - "fast-usdc/start-fast-usdc.build.js submission --net A3P_INTEGRATION --noNoble" + "fast-usdc/start-fast-usdc.build.js submission --net A3P_INTEGRATION --noNoble", + "fast-usdc/add-operators.build.js add-operators --oracle oracleNew:agoric1hmdue96vs0p6zj42aa26x6zrqlythpxnvgsgpr" ], "type": "/agoric.swingset.CoreEvalProposal" }, diff --git a/packages/boot/test/fast-usdc/fast-usdc.test.ts b/packages/boot/test/fast-usdc/fast-usdc.test.ts index ea9a48f1c85..308b020e32d 100644 --- a/packages/boot/test/fast-usdc/fast-usdc.test.ts +++ b/packages/boot/test/fast-usdc/fast-usdc.test.ts @@ -469,6 +469,8 @@ test.serial('restart contract', async t => { test.serial('replace operators', async t => { const { agoricNamesRemotes, + buildProposal, + evalProposal, storage, runUtils: { EV }, walletFactoryDriver: wfd, @@ -521,6 +523,51 @@ test.serial('replace operators', async t => { } } - // TODO test adding new operators - // The naive approach is failing under XS. A new CoreEval may be necessary. + if (defaultManagerType === 'xs-worker') { + // XXX for some reason the code after this when run under XS fails with: + // message: 'unsettled value for "kp2526"', + return; + } + + // Add some new oracle operator + const { + // any one would do + oracles: { gov1: address }, + } = configurations.A3P_INTEGRATION; + const wallet = await wfd.provideSmartWallet(address); + + const addOperators = buildProposal( + '@agoric/builders/scripts/fast-usdc/add-operators.build.js', + ['--oracle', `gov1a3p:${address}`], + ); + await evalProposal(addOperators); + + await wallet.sendOffer({ + id: 'claim-oracle-invitation', + invitationSpec: { + source: 'purse', + instance: agoricNamesRemotes.instance.fastUsdc, + description: 'oracle operator invitation', + }, + proposal: {}, + }); + console.log('accepted invitation'); + + await wallet.sendOffer({ + id: 'submit', + invitationSpec: { + source: 'continuing', + previousOffer: 'claim-oracle-invitation', + invitationMakerName: 'SubmitEvidence', + invitationArgs: [evidence], + }, + proposal: {}, + }); + console.log('submitted price'); + t.like(wallet.getLatestUpdateRecord(), { + status: { + id: 'submit', + result: 'inert; nothing should be expected from this offer', + }, + }); }); diff --git a/packages/builders/scripts/fast-usdc/add-operators.build.js b/packages/builders/scripts/fast-usdc/add-operators.build.js new file mode 100644 index 00000000000..bc506d5cbe7 --- /dev/null +++ b/packages/builders/scripts/fast-usdc/add-operators.build.js @@ -0,0 +1,83 @@ +// @ts-check +import { makeHelpers } from '@agoric/deploy-script-support'; +import { getManifestForAddOperators } from '@agoric/fast-usdc/src/add-operators.core.js'; +import { toExternalConfig } from '@agoric/fast-usdc/src/utils/config-marshal.js'; +import { configurations } from '@agoric/fast-usdc/src/utils/deploy-config.js'; +import { Far } from '@endo/far'; +import { parseArgs } from 'node:util'; + +/** + * @import {CoreEvalBuilder, DeployScriptFunction} from '@agoric/deploy-script-support/src/externalTypes.js'; + * @import {ParseArgsConfig} from 'node:util'; + * @import {FastUSDCConfig, FeedPolicy} from '@agoric/fast-usdc/src/types.js'; + * @import {FastUSDCOpts} from './start-fast-usdc.build.js'; + */ + +const { keys } = Object; + +/** @type {ParseArgsConfig['options']} */ +const options = { + net: { type: 'string' }, + oracle: { type: 'string', multiple: true }, +}; +const oraclesUsage = 'use --oracle name:address ...'; + +const crossVatContext = /** @type {const} */ ({ + /** @type {Brand<'nat'>} */ + USDC: Far('USDC Brand'), +}); + +/** @type {CoreEvalBuilder} */ +export const defaultProposalBuilder = async ( + powers, + /** @type {FastUSDCConfig} */ config, +) => { + return harden({ + sourceSpec: '@agoric/fast-usdc/src/add-operators.core.js', + /** @type {[string, Parameters[1]]} */ + getManifestCall: [ + getManifestForAddOperators.name, + { + options: toExternalConfig(config, crossVatContext), + }, + ], + }); +}; + +/** @type {DeployScriptFunction} */ +export default async (homeP, endowments) => { + const { writeCoreEval } = await makeHelpers(homeP, endowments); + const { scriptArgs } = endowments; + + /** @type {{ values: FastUSDCOpts }} */ + // @ts-expect-error ensured by options + const { + values: { oracle: oracleArgs, net }, + } = parseArgs({ args: scriptArgs, options }); + + const parseOracleArgs = () => { + if (net) { + if (!(net in configurations)) { + throw Error(`${net} not in ${keys(configurations)}`); + } + return configurations[net].oracles; + } + if (!oracleArgs) throw Error(oraclesUsage); + return Object.fromEntries( + oracleArgs.map(arg => { + const result = arg.match(/(?[^:]+):(?
.+)/); + if (!(result && result.groups)) throw Error(oraclesUsage); + const { name, address } = result.groups; + return [name, address]; + }), + ); + }; + + const config = harden({ + oracles: parseOracleArgs(), + }); + + await writeCoreEval('add-operators', utils => + defaultProposalBuilder(utils, config), + ); +}; diff --git a/packages/fast-usdc/src/add-operators.core.js b/packages/fast-usdc/src/add-operators.core.js new file mode 100644 index 00000000000..a11faa2ebfc --- /dev/null +++ b/packages/fast-usdc/src/add-operators.core.js @@ -0,0 +1,63 @@ +import { makeTracer } from '@agoric/internal'; +import { inviteOracles } from './utils/core-eval.js'; + +/** + * @import {ManifestBundleRef} from '@agoric/deploy-script-support/src/externalTypes.js' + * @import {BootstrapManifest} from '@agoric/vats/src/core/lib-boot.js' + * @import {LegibleCapData} from './utils/config-marshal.js' + * @import {FastUSDCConfig} from './types.js' + * @import {FastUSDCCorePowers, FastUSDCKit} from './start-fast-usdc.core.js'; + */ + +const trace = makeTracer('FUSD-AddOperators', true); + +/** + * @throws if oracle smart wallets are not yet provisioned + * + * @param {BootstrapPowers & FastUSDCCorePowers } powers + * @param {{ options: LegibleCapData }} config + */ +export const addOperators = async ( + { consume: { namesByAddress, fastUsdcKit } }, + config, +) => { + trace(addOperators.name); + + const kit = await fastUsdcKit; + + const { creatorFacet } = kit; + + trace(config); + + // @ts-expect-error XXX LegibleCapData typedef + const { oracles } = config.options.structure; + + await inviteOracles({ creatorFacet, namesByAddress }, oracles); +}; +harden(addOperators); + +/** + * @param {{ + * restoreRef: (b: ERef) => Promise; + * }} utils + * @param {{ + * options: LegibleCapData; + * }} param1 + */ +export const getManifestForAddOperators = ({ restoreRef: _ }, { options }) => { + return { + /** @type {BootstrapManifest} */ + manifest: { + [addOperators.name]: { + consume: { + fastUsdcKit: true, + + // widely shared: name services + agoricNames: true, + namesByAddress: true, + }, + }, + }, + options, + }; +};