diff --git a/packages/synthetic-chain/package.json b/packages/synthetic-chain/package.json index fbeada9f..7f5b401a 100644 --- a/packages/synthetic-chain/package.json +++ b/packages/synthetic-chain/package.json @@ -26,6 +26,7 @@ "execa": "^8.0.1" }, "devDependencies": { + "@agoric/smart-wallet": "0.5.4-u14.1", "@types/better-sqlite3": "^7.6.9", "@types/node": "^18.19.14", "ava": "^5.3.1", diff --git a/packages/synthetic-chain/src/lib/cliHelper.js b/packages/synthetic-chain/src/lib/cliHelper.js index 98f0e666..d7ccd47d 100644 --- a/packages/synthetic-chain/src/lib/cliHelper.js +++ b/packages/synthetic-chain/src/lib/cliHelper.js @@ -84,8 +84,7 @@ export const agoric = { export const { stdout: agopsLocation } = await $({ shell: true, - cwd: '/usr/src/agoric-sdk', -})`yarn bin agops`; +})`YARN_IGNORE_NODE=1 yarn bin agops`; export const agops = { vaults: async (...params) => { diff --git a/packages/synthetic-chain/src/lib/commonUpgradeHelpers.js b/packages/synthetic-chain/src/lib/commonUpgradeHelpers.ts similarity index 80% rename from packages/synthetic-chain/src/lib/commonUpgradeHelpers.js rename to packages/synthetic-chain/src/lib/commonUpgradeHelpers.ts index 1c2e8db6..a477c921 100644 --- a/packages/synthetic-chain/src/lib/commonUpgradeHelpers.js +++ b/packages/synthetic-chain/src/lib/commonUpgradeHelpers.ts @@ -4,6 +4,11 @@ import * as path from 'node:path'; import { agd, agoric, agops } from './cliHelper.js'; import { CHAINID, HOME, VALIDATORADDR } from './constants.js'; +import type { OfferSpec } from '@agoric/smart-wallet/src/offers.js'; +import assert from 'node:assert'; + +type ERef = T | Promise; + const waitForBootstrap = async () => { const endpoint = 'localhost'; while (true) { @@ -50,7 +55,7 @@ export const waitForBlock = async (times = 1) => { } }; -export const provisionSmartWallet = async (address, amount) => { +export const provisionSmartWallet = async (address: string, amount: string) => { console.log(`funding ${address}`); await agd.tx( 'bank', @@ -88,14 +93,14 @@ export const newOfferId = async () => { return date; }; -export const mkTemp = async template => { +export const mkTemp = async (template: string) => { const { stdout: data } = await $({ shell: true, })`mktemp -t ${template}`; return data; }; -export const calculateWalletState = async addr => { +export const calculateWalletState = async (addr: string) => { const result = await agoric.follow( '-lF', `:published.wallet.${addr}`, @@ -117,10 +122,19 @@ export const calculateWalletState = async addr => { return state; }; -export const executeOffer = async (address, offerPromise) => { +export const executeOffer = async ( + address: string, + offerJsonOrStringP: ERef, +) => { const offerPath = await mkTemp('agops.XXX'); - const offer = await offerPromise; - await fsp.writeFile(offerPath, offer); + const offerJsonOrString = await offerJsonOrStringP; + const offerJson: OfferSpec = + typeof offerJsonOrString === 'string' + ? // this is going to be stringified again but this we we guarantee it's valid JSON + JSON.parse(offerJsonOrString) + : offerJsonOrString; + + await fsp.writeFile(offerPath, JSON.stringify(offerJson)); await agops.perf( 'satisfaction', @@ -132,11 +146,11 @@ export const executeOffer = async (address, offerPromise) => { ); }; -export const getUser = async user => { +export const getUser = async (user: string) => { return agd.keys('show', user, '-a', '--keyring-backend=test'); }; -export const addUser = async user => { +export const addUser = async (user: string) => { const userKeyData = await agd.keys('add', user, '--keyring-backend=test'); await fsp.writeFile(`${HOME}/.agoric/${user}.key`, userKeyData.mnemonic); @@ -144,13 +158,18 @@ export const addUser = async user => { return userAddress; }; -/** - * @params {string} [title] - * @returns {Promise<{ proposal_id: string, voting_end_time: unknown, status: string }>} - */ -export const voteLatestProposalAndWait = async title => { +export const voteLatestProposalAndWait = async (title?: string) => { await waitForBlock(); - let { proposals } = await agd.query('gov', 'proposals'); + let { proposals } = (await agd.query('gov', 'proposals')) as { + proposals: { + proposal_id?: string; + id?: string; + voting_end_time: unknown; + status: string; + content: any; + messages: any[]; + }[]; + }; if (title) { proposals = proposals.filter(proposal => { if (proposal.content) { @@ -168,7 +187,9 @@ export const voteLatestProposalAndWait = async title => { } let lastProposal = proposals.at(-1); - lastProposal || Fail`No proposal found`; + if (!lastProposal) { + throw Fail`No proposal found`; + } const lastProposalId = lastProposal.proposal_id || lastProposal.id; @@ -193,6 +214,8 @@ export const voteLatestProposalAndWait = async title => { lastProposal = await agd.query('gov', 'proposal', lastProposalId); } + assert(lastProposal); + lastProposal.status === 'PROPOSAL_STATUS_VOTING_PERIOD' || Fail`Latest proposal ${lastProposalId} not in voting period (status=${lastProposal.status})`; @@ -217,6 +240,7 @@ export const voteLatestProposalAndWait = async title => { await waitForBlock() ) { lastProposal = await agd.query('gov', 'proposal', lastProposalId); + assert(lastProposal); console.log( `Waiting for proposal ${lastProposalId} to pass (status=${lastProposal.status})`, ); @@ -224,7 +248,7 @@ export const voteLatestProposalAndWait = async title => { return { proposal_id: lastProposalId, ...lastProposal }; }; -const Fail = (template, ...args) => { +const Fail = (template: any, ...args: any[]) => { throw Error(String.raw(template, ...args.map(val => String(val)))); }; @@ -235,7 +259,7 @@ const Fail = (template, ...args) => { * * adapted from packages/boot/test/bootstrapTests/supports.js */ -const parseProposalParts = txt => { +const parseProposalParts = (txt: string) => { const evals = [ ...txt.matchAll(/swingset-core-eval (?\S+) (?