diff --git a/a3p-integration/proposals/a:upgrade-next/.yarn/patches/@agoric-synthetic-chain-npm-0.0.7-3-caab2d7295.patch b/a3p-integration/proposals/a:upgrade-next/.yarn/patches/@agoric-synthetic-chain-npm-0.0.7-3-caab2d7295.patch new file mode 100644 index 000000000000..66152233af14 --- /dev/null +++ b/a3p-integration/proposals/a:upgrade-next/.yarn/patches/@agoric-synthetic-chain-npm-0.0.7-3-caab2d7295.patch @@ -0,0 +1,176 @@ +diff --git a/dist/lib/index.d.ts b/dist/lib/index.d.ts +index 1b963f6d08667abeba3e258c3c368931ae41347e..da831ecc7fc5d55cedfd47fc909310f19d40f9dd 100644 +--- a/dist/lib/index.d.ts ++++ b/dist/lib/index.d.ts +@@ -85,7 +85,7 @@ declare function calculateWalletState(addr: any): Promise; + declare function executeOffer(address: any, offerPromise: any): Promise; + declare function getUser(user: any): Promise; + declare function addUser(user: any): Promise; +-declare function voteLatestProposalAndWait(): Promise<{ ++declare function voteLatestProposalAndWait(title: any): Promise<{ + proposal_id: string; + voting_end_time: unknown; + status: string; +@@ -120,7 +120,11 @@ declare const staticConfig: { + swingstorePath: string; + }; + type StaticConfig = typeof staticConfig; +-declare const passCoreEvalProposal: (bundleInfos: BundleInfo[]) => Promise; ++type CoreEvalConfig = { ++ title?: string; ++ description?: string; ++}; ++declare const passCoreEvalProposal: (bundleInfos: BundleInfo[], coreEvalConfig?: CoreEvalConfig) => Promise; + declare const evalBundles: (dir: string) => Promise; + + declare const getContractInfo: (path: string, io?: any) => Promise; +@@ -232,4 +236,4 @@ type FileRd = ReturnType; + type FileRW = ReturnType; + type WebCache = ReturnType; + +-export { ATOM_DENOM, BINARY, type BundleInfo, CHAINID, type FileRW, type FileRd, GOV1ADDR, GOV2ADDR, GOV3ADDR, HOME, PSM_PAIR, SDK_ROOT, type StaticConfig, type TextRd, USER1ADDR, VALIDATORADDR, type WebCache, addUser, adjustVault, agd, agops, agopsLocation, agoric, bundleDetail, bundleSource, bundleSourceLocation, calculateWalletState, closeVault, dbTool, ensureISTForInstall, evalBundles, executeCommand, executeOffer, flags, getContractInfo, getISTBalance, getIncarnation, getUser, getVatDetails, installBundle, loadedBundleIds, makeAgd, makeFileRW, makeFileRd, makeWebCache, makeWebRd, mintIST, mkTemp, newOfferId, openVault, passCoreEvalProposal, proposalBuilder, provisionSmartWallet, readBundles, smallCapsContext, staticConfig, step, submitProposal, testIncludes, txAbbr, voteLatestProposalAndWait, waitForBlock, wellKnownIdentities }; ++export { ATOM_DENOM, BINARY, type BundleInfo, CHAINID, type CoreEvalConfig, type FileRW, type FileRd, GOV1ADDR, GOV2ADDR, GOV3ADDR, HOME, PSM_PAIR, SDK_ROOT, type StaticConfig, type TextRd, USER1ADDR, VALIDATORADDR, type WebCache, addUser, adjustVault, agd, agops, agopsLocation, agoric, bundleDetail, bundleSource, bundleSourceLocation, calculateWalletState, closeVault, dbTool, ensureISTForInstall, evalBundles, executeCommand, executeOffer, flags, getContractInfo, getISTBalance, getIncarnation, getUser, getVatDetails, installBundle, loadedBundleIds, makeAgd, makeFileRW, makeFileRd, makeWebCache, makeWebRd, mintIST, mkTemp, newOfferId, openVault, passCoreEvalProposal, proposalBuilder, provisionSmartWallet, readBundles, smallCapsContext, staticConfig, step, submitProposal, testIncludes, txAbbr, voteLatestProposalAndWait, waitForBlock, wellKnownIdentities }; +diff --git a/dist/lib/index.js b/dist/lib/index.js +index d87a81074f12c8b5ae323d38c6d5e5f9da3044d0..e2b320f58f5bb0a92c0379de85c47293d3d2ba2b 100644 +--- a/dist/lib/index.js ++++ b/dist/lib/index.js +@@ -386,9 +386,23 @@ var addUser = async (user) => { + const userAddress = await getUser(user); + return userAddress; + }; +-var voteLatestProposalAndWait = async () => { ++var voteLatestProposalAndWait = async (title) => { + await waitForBlock(); +- const proposalsData = await agd.query("gov", "proposals"); ++ let proposalsData = await agd.query("gov", "proposals"); ++ if (title) { ++ proposalsData = proposalsData.filter((proposal) => { ++ if (proposal.content) { ++ return proposal.content.title === title; ++ } else if (proposal.messages) { ++ return proposal.messages.some((message) => { ++ message["@type"] === "/cosmos.gov.v1.MsgExecLegacyContent" || Fail`Unsupported proposal message type ${message["@type"]}`; ++ return proposal.content.title === title; ++ }); ++ } else { ++ Fail`Unrecognized proposal shape ${Object.keys(proposal)}`; ++ } ++ }); ++ } + let lastProposal = proposalsData.proposals.at(-1); + lastProposal || Fail`No proposal found`; + const lastProposalId = lastProposal.proposal_id || lastProposal.id; +@@ -495,7 +509,7 @@ var submitProposal = async (scriptPath, permitPath, title, description) => { + "-bblock", + "--yes" + ); +- await voteLatestProposalAndWait(); ++ await voteLatestProposalAndWait(title); + }; + + // src/lib/core-eval-support.ts +@@ -908,10 +922,11 @@ var staticConfig = { + // conservatively low price. TODO: look up + swingstorePath: "~/.agoric/data/agoric/swingstore.sqlite" + }; +-var makeTestContext = async (staticConfig2) => { ++var makeTestContext = async (staticConfig2, coreEvalConfig) => { + const config = { + chainId: "agoriclocal", +- ...staticConfig2 ++ ...staticConfig2, ++ ...coreEvalConfig + }; + const agd2 = makeAgd({ execFileSync }).withOpts({ + keyringBackend: "test" +@@ -921,11 +936,11 @@ var makeTestContext = async (staticConfig2) => { + const before = /* @__PURE__ */ new Map(); + return { agd: agd2, agoric, swingstore, config, before, fetch }; + }; +-var passCoreEvalProposal = async (bundleInfos) => { ++var passCoreEvalProposal = async (bundleInfos, coreEvalConfig = {}) => { + const config = { + ...staticConfig + }; +- const context = await makeTestContext(config); ++ const context = await makeTestContext(config, coreEvalConfig); + console.log("Passing core evals..."); + for (const { name, bundles, evals } of bundleInfos) { + console.log( +@@ -1030,8 +1045,11 @@ var passCoreEvalProposal = async (bundleInfos) => { + const { agd: agd2, swingstore, config: config2 } = context; + const from = agd2.lookup(config2.proposer); + const { chainId, deposit } = config2; +- const info = { title: config2.title, description: config2.description }; +- console.log("submit proposal", config2.title); ++ const info = { ++ title: config2.title || `Core Eval ${Date.now()}`, ++ description: config2.description || "Core eval proposal" ++ }; ++ console.log("submit proposal", info.title); + const loaded = loadedBundleIds(swingstore); + for (const { bundles } of bundleInfos) { + for (const bundle of bundles) { +@@ -1057,14 +1075,14 @@ var passCoreEvalProposal = async (bundleInfos) => { + ); + console.log(txAbbr(result)); + assert3.equal(result.code, 0); +- const detail = await voteLatestProposalAndWait(); ++ const detail = await voteLatestProposalAndWait(info.title); + console.log(detail.proposal_id, detail.voting_end_time, detail.status); + assert3.equal(detail.status, "PROPOSAL_STATUS_PASSED"); + }); + }; + var evalBundles = async (dir) => { + const bundleInfos = await readBundles(dir); +- await passCoreEvalProposal(bundleInfos); ++ await passCoreEvalProposal(bundleInfos, { title: `Core eval of ${dir}` }); + }; + + // src/lib/webAsset.js +diff --git a/dist/lib/index.js.map b/dist/lib/index.js.map +index c6c12b81a548208f511f50e06eadf566f5d93b94..ebb422a2c6660e1f8e8164e0ea77a60d7dd45af1 100644 +--- a/dist/lib/index.js.map ++++ b/dist/lib/index.js.map +@@ -1 +1 @@ +-{"version":3,"sources":["../../src/lib/agd-lib.ts","../../src/lib/cliHelper.js","../../src/lib/constants.js","../../src/lib/commonUpgradeHelpers.js","../../src/lib/core-eval-support.ts","../../src/lib/assert.js","../../src/lib/unmarshal.js","../../src/lib/econHelpers.js","../../src/lib/core-eval.ts","../../src/lib/vat-status.js","../../src/lib/logging.ts","../../src/lib/webAsset.js"],"sourcesContent":["import assert from 'node:assert';\nimport { ExecFileSyncOptionsWithStringEncoding } from 'node:child_process';\n\nconst { freeze } = Object;\n\nconst agdBinary = 'agd';\n\nexport const makeAgd = ({\n execFileSync,\n}: {\n execFileSync: typeof import('child_process').execFileSync;\n}) => {\n const make = (\n { home, keyringBackend, rpcAddrs } = {} as {\n home?: string;\n keyringBackend?: string;\n rpcAddrs?: string[];\n },\n ) => {\n const keyringArgs = [\n ...(home ? ['--home', home] : []),\n ...(keyringBackend ? [`--keyring-backend`, keyringBackend] : []),\n ];\n if (rpcAddrs) {\n assert.equal(\n rpcAddrs.length,\n 1,\n 'XXX rpcAddrs must contain only one entry',\n );\n }\n const nodeArgs = [...(rpcAddrs ? [`--node`, rpcAddrs[0]] : [])];\n\n const exec = (\n args: string[],\n opts?: ExecFileSyncOptionsWithStringEncoding,\n ) => execFileSync(agdBinary, args, opts).toString();\n\n const outJson = ['--output', 'json'];\n\n const ro = freeze({\n status: async () => JSON.parse(exec([...nodeArgs, 'status'])),\n query: async (\n qArgs:\n | [kind: 'gov', domain: string, ...rest: any]\n | [kind: 'tx', txhash: string]\n | [mod: 'vstorage', kind: 'data' | 'children', path: string],\n ) => {\n const out = exec(['query', ...qArgs, ...nodeArgs, ...outJson], {\n encoding: 'utf-8',\n stdio: ['ignore', 'pipe', 'ignore'],\n });\n\n try {\n return JSON.parse(out);\n } catch (e) {\n console.error(e);\n console.info('output:', out);\n }\n },\n });\n const nameHub = freeze({\n /**\n * NOTE: synchronous I/O\n */\n lookup: (...path: string[]) => {\n if (!Array.isArray(path)) {\n // TODO: use COND || Fail``\n throw TypeError();\n }\n if (path.length !== 1) {\n throw Error(`path length limited to 1: ${path.length}`);\n }\n const [name] = path;\n const txt = exec(['keys', 'show', `--address`, name, ...keyringArgs]);\n return txt.trim();\n },\n });\n const rw = freeze({\n /**\n * TODO: gas\n */\n tx: async (\n txArgs: string[],\n {\n chainId,\n from,\n yes,\n }: { chainId: string; from: string; yes?: boolean },\n ) => {\n const yesArg = yes ? ['--yes'] : [];\n const args = [\n ...nodeArgs,\n ...[`--chain-id`, chainId],\n ...keyringArgs,\n ...[`--from`, from],\n 'tx',\n ...['--broadcast-mode', 'block'],\n ...txArgs,\n ...yesArg,\n ...outJson,\n ];\n const out = exec(args);\n try {\n return JSON.parse(out);\n } catch (e) {\n console.error(e);\n console.info('output:', out);\n }\n },\n ...ro,\n ...nameHub,\n readOnly: () => ro,\n nameHub: () => nameHub,\n keys: {\n add: (name: string, mnemonic: string) => {\n return execFileSync(\n agdBinary,\n [...keyringArgs, 'keys', 'add', name, '--recover'],\n { input: mnemonic },\n ).toString();\n },\n },\n withOpts: (opts: Record) =>\n make({ home, keyringBackend, rpcAddrs, ...opts }),\n });\n return rw;\n };\n return make();\n};\n","import { $, execaCommand } from 'execa';\nimport { BINARY } from './constants.js';\n\nexport const executeCommand = async (command, params, options = {}) => {\n const { stdout } = await execaCommand(\n `${command} ${params.join(' ')}`,\n options,\n );\n return stdout;\n};\n\nexport const agd = {\n query: async (...params) => {\n const newParams = ['query', ...params, '-o json'];\n const data = await executeCommand(BINARY, newParams);\n return JSON.parse(data);\n },\n tx: async (...params) => {\n const newParams = ['tx', '-bblock', ...params, '-o json'];\n const data = await executeCommand(BINARY, newParams, { shell: true });\n return JSON.parse(data);\n },\n keys: async (...params) => {\n let newParams = ['keys', ...params];\n let shouldParse = true;\n\n if (params.includes('show')) {\n if (params.includes('-a') || params.includes('-address')) {\n shouldParse = false;\n }\n }\n\n if (shouldParse) {\n newParams = [...newParams, '--output json'];\n }\n\n const data = await executeCommand(BINARY, newParams, { input: 'Y' });\n if (!shouldParse) {\n return data;\n }\n\n return JSON.parse(data);\n },\n export: async (...params) => {\n const newParams = ['export', ...params];\n const data = await executeCommand(BINARY, newParams);\n return JSON.parse(data);\n },\n};\n\nexport const agoric = {\n follow: async (...params) => {\n let newParams = ['follow', ...params];\n let parseJson = false;\n\n if (!params.includes('-o')) {\n newParams = [...newParams, '-o json'];\n parseJson = true;\n }\n const data = await executeCommand('agoric', newParams);\n\n if (parseJson) {\n return JSON.parse(data);\n }\n\n return data;\n },\n wallet: async (...params) => {\n const newParams = ['wallet', ...params];\n return executeCommand('agoric', newParams);\n },\n run: async (...params) => {\n const newParams = ['run', ...params];\n return executeCommand('agoric', newParams);\n },\n};\n\nexport const { stdout: agopsLocation } = await $({\n shell: true,\n cwd: '/usr/src/agoric-sdk',\n})`yarn bin agops`;\n\nexport const agops = {\n vaults: async (...params) => {\n const newParams = ['vaults', ...params];\n\n const result = await executeCommand(agopsLocation, newParams);\n\n if (params[0] === 'list') {\n if (result === '') return [];\n\n return result.split('\\n');\n }\n\n return result;\n },\n ec: async (...params) => {\n const newParams = ['ec', ...params];\n return executeCommand(agopsLocation, newParams);\n },\n oracle: async (...params) => {\n const newParams = ['oracle', ...params];\n return executeCommand(agopsLocation, newParams);\n },\n perf: async (...params) => {\n const newParams = ['perf', ...params];\n return executeCommand(agopsLocation, newParams);\n },\n auctioneer: async (...params) => {\n const newParams = ['auctioneer', ...params];\n return executeCommand(agopsLocation, newParams);\n },\n};\n\nexport const { stdout: bundleSourceLocation } = await $({\n shell: true,\n cwd: '/usr/src/agoric-sdk',\n})`yarn bin bundle-source`;\n\n/**\n * @param {string} filePath\n * @param {string} bundleName\n * @returns {Promise} Returns the filepath of the bundle\n */\nexport const bundleSource = async (filePath, bundleName) => {\n const output =\n await $`${bundleSourceLocation} --cache-json /tmp ${filePath} ${bundleName}`;\n console.log(output.stderr);\n return `/tmp/bundle-${bundleName}.json`;\n};\n\nexport const wellKnownIdentities = async (io = {}) => {\n const { agoric: { follow = agoric.follow } = {} } = io;\n const zip = (xs, ys) => xs.map((x, i) => [x, ys[i]]);\n const fromSmallCapsEntries = txt => {\n const { body, slots } = JSON.parse(txt);\n const theEntries = zip(JSON.parse(body.slice(1)), slots).map(\n ([[name, ref], boardID]) => {\n const iface = ref.replace(/^\\$\\d+\\./, '');\n return [name, { iface, boardID }];\n },\n );\n return Object.fromEntries(theEntries);\n };\n\n const installation = fromSmallCapsEntries(\n await follow('-lF', ':published.agoricNames.installation', '-o', 'text'),\n );\n\n const instance = fromSmallCapsEntries(\n await follow('-lF', ':published.agoricNames.instance', '-o', 'text'),\n );\n\n const brand = fromSmallCapsEntries(\n await follow('-lF', ':published.agoricNames.brand', '-o', 'text'),\n );\n\n return { brand, installation, instance };\n};\n\nexport const smallCapsContext = () => {\n const slots = []; // XXX global mutable state\n const smallCaps = {\n Nat: n => `+${n}`,\n // XXX mutates obj\n ref: obj => {\n if (obj.ix) return obj.ix;\n const ix = slots.length;\n slots.push(obj.boardID);\n obj.ix = `$${ix}.Alleged: ${obj.iface}`;\n return obj.ix;\n },\n };\n\n const toCapData = body => {\n const capData = { body: `#${JSON.stringify(body)}`, slots };\n return JSON.stringify(capData);\n };\n\n return { smallCaps, toCapData };\n};\n","export const BINARY = process.env.binary;\n\nexport const GOV1ADDR = process.env.GOV1ADDR;\nexport const GOV2ADDR = process.env.GOV2ADDR;\nexport const GOV3ADDR = process.env.GOV3ADDR;\nexport const USER1ADDR = process.env.USER1ADDR;\nexport const VALIDATORADDR = process.env.VALIDATORADDR;\n\nexport const PSM_PAIR = process.env.PSM_PAIR;\nexport const ATOM_DENOM = process.env.ATOM_DENOM;\n\nexport const CHAINID = process.env.CHAINID;\nexport const HOME = process.env.HOME;\n\nexport const SDK_ROOT = '/usr/src/agoric-sdk';\n","import { $ } from 'execa';\nimport fsp from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { agd, agoric, agops } from './cliHelper.js';\nimport { CHAINID, HOME, VALIDATORADDR } from './constants.js';\n\nconst waitForBootstrap = async () => {\n const endpoint = 'localhost';\n while (true) {\n const { stdout: json } = await $({\n reject: false,\n })`curl -s --fail -m 15 ${`${endpoint}:26657/status`}`;\n\n if (json.length === 0) {\n continue;\n }\n\n const data = JSON.parse(json);\n\n if (data.jsonrpc !== '2.0') {\n continue;\n }\n\n const lastHeight = data.result.sync_info.latest_block_height;\n\n if (lastHeight !== '1') {\n return lastHeight;\n }\n\n await new Promise(r => setTimeout(r, 2000));\n }\n};\n\nexport const waitForBlock = async (times = 1) => {\n console.log(times);\n let time = 0;\n while (time < times) {\n const block1 = await waitForBootstrap();\n while (true) {\n const block2 = await waitForBootstrap();\n\n if (block1 !== block2) {\n console.log('block produced');\n break;\n }\n\n await new Promise(r => setTimeout(r, 1000));\n }\n time += 1;\n }\n};\n\nexport const provisionSmartWallet = async (address, amount) => {\n console.log(`funding ${address}`);\n await agd.tx(\n 'bank',\n 'send',\n 'validator',\n address,\n amount,\n '-y',\n '--keyring-backend=test',\n `--chain-id=\"${CHAINID}\"`,\n );\n await waitForBlock();\n\n console.log(`provisioning ${address}`);\n await agd.tx(\n 'swingset',\n 'provision-one',\n 'my-wallet',\n address,\n 'SMART_WALLET',\n '--keyring-backend=test',\n '-y',\n `--chain-id=\"${CHAINID}\"`,\n `--from=\"${address}\"`,\n );\n\n await waitForBlock(2);\n console.log(await agoric.wallet('show', `--from ${address}`));\n};\n\nexport const newOfferId = async () => {\n const { stdout: date } = await $`date +${'%s%3M'}`;\n await new Promise(r => setTimeout(r, 1000));\n\n return date;\n};\n\nexport const mkTemp = async template => {\n const { stdout: data } = await $({\n shell: true,\n })`mktemp -t ${template}`;\n return data;\n};\n\nexport const calculateWalletState = async addr => {\n const result = await agoric.follow(\n '-lF',\n `:published.wallet.${addr}`,\n '-o',\n 'text',\n );\n\n const body = JSON.parse(result).body;\n let state = body;\n\n if (body.includes('@qclass')) {\n state = 'old';\n } else if (body.includes('#{}')) {\n state = 'upgraded';\n } else if (body.includes('#')) {\n state = 'revived';\n }\n\n return state;\n};\n\nexport const executeOffer = async (address, offerPromise) => {\n const offerPath = await mkTemp('agops.XXX');\n const offer = await offerPromise;\n await fsp.writeFile(offerPath, offer);\n\n await agops.perf(\n 'satisfaction',\n '--from',\n address,\n '--executeOffer',\n offerPath,\n '--keyring-backend=test',\n );\n};\n\nexport const getUser = async user => {\n return agd.keys('show', user, '-a', '--keyring-backend=test');\n};\n\nexport const addUser = async user => {\n const userKeyData = await agd.keys('add', user, '--keyring-backend=test');\n await fsp.writeFile(`${HOME}/.agoric/${user}.key`, userKeyData.mnemonic);\n\n const userAddress = await getUser(user);\n return userAddress;\n};\n\n/**\n * @returns {Promise<{ proposal_id: string, voting_end_time: unknown, status: string }>}\n */\nexport const voteLatestProposalAndWait = async () => {\n await waitForBlock();\n const proposalsData = await agd.query('gov', 'proposals');\n let lastProposal = proposalsData.proposals.at(-1);\n\n lastProposal || Fail`No proposal found`;\n\n const lastProposalId = lastProposal.proposal_id || lastProposal.id;\n\n lastProposalId || Fail`Invalid proposal ${lastProposal}`;\n\n if (lastProposal.status === 'PROPOSAL_STATUS_DEPOSIT_PERIOD') {\n await agd.tx(\n 'gov',\n 'deposit',\n lastProposalId,\n '50000000ubld',\n '--from',\n VALIDATORADDR,\n `--chain-id=${CHAINID}`,\n '--yes',\n '--keyring-backend',\n 'test',\n );\n\n await waitForBlock();\n\n lastProposal = await agd.query('gov', 'proposal', lastProposalId);\n }\n\n lastProposal.status === 'PROPOSAL_STATUS_VOTING_PERIOD' ||\n Fail`Latest proposal ${lastProposalId} not in voting period (status=${lastProposal.status})`;\n\n await agd.tx(\n 'gov',\n 'vote',\n lastProposalId,\n 'yes',\n '--from',\n VALIDATORADDR,\n `--chain-id=${CHAINID}`,\n '--yes',\n '--keyring-backend',\n 'test',\n );\n\n for (\n ;\n lastProposal.status !== 'PROPOSAL_STATUS_PASSED' &&\n lastProposal.status !== 'PROPOSAL_STATUS_REJECTED' &&\n lastProposal.status !== 'PROPOSAL_STATUS_FAILED';\n await waitForBlock()\n ) {\n lastProposal = await agd.query('gov', 'proposal', lastProposalId);\n console.log(\n `Waiting for proposal ${lastProposalId} to pass (status=${lastProposal.status})`,\n );\n }\n return { proposal_id: lastProposalId, ...lastProposal };\n};\n\nconst Fail = (template, ...args) => {\n throw Error(String.raw(template, ...args.map(val => String(val))));\n};\n\n/**\n * Parse output of `agoric run proposal-builder.js`\n *\n * @param {string} txt\n *\n * adapted from packages/boot/test/bootstrapTests/supports.js\n */\nconst parseProposalParts = txt => {\n const evals = [\n ...txt.matchAll(/swingset-core-eval (?\\S+) (?