-
Notifications
You must be signed in to change notification settings - Fork 214
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
test(a3p): migrate wallet and vaults related tests from `a3p-proposal…
…s` to the `z:acceptance` (#10123) closes: https://github.com/Agoric/BytePitchPartnerEng/issues/5 closes: https://github.com/Agoric/BytePitchPartnerEng/issues/7 refs: #10049 ## Description This PR is part of an ongoing effort to migrate some of the selected test cases from `a3p-proposals` to the `z:acceptance` test phase. This particular PR new tests focus on: - invitations and payments behavior within the smart wallet - actions that can be executed on vaults The source code of the migrated tests are: - [send invitation via namesByAddress](https://github.com/Agoric/agoric-3-proposals/blob/main/proposals/75%3Aupgrade-16/provisioning.test.js#L34-L51) - [exitOffer tool reclaims stuck payment](https://github.com/Agoric/agoric-3-proposals/blob/main/proposals/74%3Aupgrade-15/exit-reclaim.test.js#L9-L38) - [ante handler sends fee only to vbank/reserve](https://github.com/Agoric/agoric-3-proposals/blob/main/proposals/71%3Aupgrade-14/ante-fees.test.js#L5-L74) - Vault actions executed on [actions.sh](https://github.com/Agoric/agoric-sdk/blob/mainnet1B-rc3/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/actions.sh#L105-L176) ### Security Considerations n/a ### Scaling Considerations n/a ### Documentation Considerations One commit included in this PR fixes a small typo on `a3p-integration/proposals/README.md` ### Testing Considerations The new test files included in this PR are invoked through `test.sh`, so no changes to the current testing workflow are necessary. However, as pointed out by @dckc in this [comment](bytepitch@6afaba3#r146887047), using `waitForBlock()` can lead to unexpected behavior. To address this, we plan to update the `z:acceptance` tests to mitigate this issue. As a solution, we propose extending the `@agoric/synthetic-chain` package to export a method like [makeRetryUntilCondition](https://github.com/Agoric/agoric-sdk/blob/f291362e4bc62ec31552cef29ec1a5f5cfbf7bd7/multichain-testing/tools/sleep.ts#L62) or a similar function. This would provide a more reliable alternative to `waitForBlock()`. Additionally, there is already an [test-vaults.mts](https://github.com/Agoric/agoric-sdk/blob/master/a3p-integration/proposals/z%3Aacceptance/scripts/test-vaults.mts) file that test operations related to changes on auctions parameters. To avoid confusion with `vaults.test` due to the similarity in names, I propose renaming this file to `auction.test` and expanding its scope to cover all auction-related tests. ### Upgrade Considerations n/a
- Loading branch information
Showing
8 changed files
with
565 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
// Note: limit imports to node modules for portability | ||
import { parseArgs, promisify } from 'node:util'; | ||
import { execFile } from 'node:child_process'; | ||
import { writeFile, mkdtemp, rm } from 'node:fs/promises'; | ||
import { join } from 'node:path'; | ||
|
||
const options = /** @type {const} */ ({ | ||
id: { type: 'string' }, | ||
from: { type: 'string' }, | ||
bin: { type: 'string', default: '/usr/src/agoric-sdk/node_modules/.bin' }, | ||
}); | ||
|
||
const Usage = ` | ||
Try to exit an offer, reclaiming any associated payments. | ||
node exitOffer.js --id ID --from FROM [--bin PATH] | ||
Options: | ||
--id <offer id> | ||
--from <address or key name> | ||
--bin <path to agoric and agd> default: ${options.bin.default} | ||
`; | ||
|
||
const badUsage = () => { | ||
const reason = new Error(Usage); | ||
reason.name = 'USAGE'; | ||
throw reason; | ||
}; | ||
|
||
const { stringify: jq } = JSON; | ||
// limited to JSON data: no remotables/promises; no undefined. | ||
const toCapData = data => ({ body: `#${jq(data)}`, slots: [] }); | ||
|
||
const { entries } = Object; | ||
/** | ||
* @param {Record<string, string>} obj - e.g. { color: 'blue' } | ||
* @returns {string[]} - e.g. ['--color', 'blue'] | ||
*/ | ||
const flags = obj => | ||
entries(obj) | ||
.map(([k, v]) => [`--${k}`, v]) | ||
.flat(); | ||
|
||
const execP = promisify(execFile); | ||
|
||
const showAndRun = (file, args) => { | ||
console.log('$', file, ...args); | ||
return execP(file, args); | ||
}; | ||
|
||
const withTempFile = async (tail, fn) => { | ||
const tmpDir = await mkdtemp('offers-'); | ||
const tmpFile = join(tmpDir, tail); | ||
try { | ||
const result = await fn(tmpFile); | ||
return result; | ||
} finally { | ||
await rm(tmpDir, { recursive: true, force: true }).catch(err => | ||
console.error(err), | ||
); | ||
} | ||
}; | ||
|
||
const doAction = async (action, from) => { | ||
await withTempFile('offer.json', async tmpOffer => { | ||
await writeFile(tmpOffer, jq(toCapData(action))); | ||
|
||
const out = await showAndRun('agoric', [ | ||
'wallet', | ||
...flags({ 'keyring-backend': 'test' }), | ||
'send', | ||
...flags({ offer: tmpOffer, from }), | ||
]); | ||
return out.stdout; | ||
}); | ||
}; | ||
|
||
const main = async (argv, env) => { | ||
const { values } = parseArgs({ args: argv.slice(2), options }); | ||
const { id: offerId, from, bin } = values; | ||
(offerId && from) || badUsage(); | ||
|
||
env.PATH = `${bin}:${env.PATH}`; | ||
const action = { method: 'tryExitOffer', offerId }; | ||
const out = await doAction(action, from); | ||
console.log(out); | ||
}; | ||
|
||
main(process.argv, process.env).catch(e => { | ||
if (e.name === 'USAGE' || e.code === 'ERR_PARSE_ARGS_UNKNOWN_OPTION') { | ||
console.error(e.message); | ||
} else { | ||
console.error(e); | ||
} | ||
process.exit(1); | ||
}); |
1 change: 1 addition & 0 deletions
1
a3p-integration/proposals/z:acceptance/invitation-test-submission/send-script-permit.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
true |
33 changes: 33 additions & 0 deletions
33
a3p-integration/proposals/z:acceptance/invitation-test-submission/send-script.tjs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
/* global E */ | ||
|
||
/// <reference types="@agoric/vats/src/core/core-eval-env"/> | ||
/// <reference types="@agoric/vats/src/core/types-ambient"/> | ||
|
||
/** | ||
* The primary purpose of this script is to access the depositFacet of a given address | ||
* via the namesByAddress and then send a payment to it. | ||
* | ||
* The {{ADDRESS}} placeholder should be replaced with the desired address before use. | ||
* | ||
* The payment in this case is an invitation to add collateral to the reserve. | ||
* However, the use of the reserve is incidental and simply provides an easy payment to construct. | ||
* | ||
* see a3p-integration/proposals/z:acceptance/wallet.test.js | ||
* | ||
* @param {BootstrapPowers} powers | ||
*/ | ||
const sendIt = async powers => { | ||
const addr = '{{ADDRESS}}'; | ||
const { | ||
consume: { namesByAddress, zoe }, | ||
instance: { | ||
consume: { reserve }, | ||
}, | ||
} = powers; | ||
const pf = E(zoe).getPublicFacet(reserve); | ||
const anInvitation = await E(pf).makeAddCollateralInvitation(); | ||
const addressDepositFacet = E(namesByAddress).lookup(addr, 'depositFacet'); | ||
await E(addressDepositFacet).receive(anInvitation); | ||
}; | ||
|
||
sendIt; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
import { makeAgd, agops } from '@agoric/synthetic-chain'; | ||
import { execFileSync } from 'node:child_process'; | ||
import { readFile, writeFile } from 'node:fs/promises'; | ||
|
||
/** | ||
* @param {string} fileName base file name without .tjs extension | ||
* @param {Record<string, string>} replacements | ||
*/ | ||
export const replaceTemplateValuesInFile = async (fileName, replacements) => { | ||
let script = await readFile(`${fileName}.tjs`, 'utf-8'); | ||
for (const [template, value] of Object.entries(replacements)) { | ||
script = script.replaceAll(`{{${template}}}`, value); | ||
} | ||
await writeFile(`${fileName}.js`, script); | ||
}; | ||
|
||
const showAndExec = (file, args, opts) => { | ||
console.log('$', file, ...args); | ||
return execFileSync(file, args, opts); | ||
}; | ||
|
||
// @ts-expect-error string is not assignable to Buffer | ||
export const agd = makeAgd({ execFileSync: showAndExec }).withOpts({ | ||
keyringBackend: 'test', | ||
}); | ||
|
||
/** | ||
* @param {string[]} addresses | ||
* @param {string} [targetDenom] | ||
*/ | ||
export const getBalances = async (addresses, targetDenom = undefined) => { | ||
const balancesList = await Promise.all( | ||
addresses.map(async address => { | ||
const { balances } = await agd.query(['bank', 'balances', address]); | ||
|
||
if (targetDenom) { | ||
const balance = balances.find(({ denom }) => denom === targetDenom); | ||
return balance ? BigInt(balance.amount) : undefined; | ||
} | ||
|
||
return balances; | ||
}), | ||
); | ||
|
||
return addresses.length === 1 ? balancesList[0] : balancesList; | ||
}; | ||
|
||
export const agopsVaults = async addr => | ||
await agops.vaults('list', '--from', addr); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.