-
Notifications
You must be signed in to change notification settings - Fork 215
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
test(a3p): add mintHolder upgrade test and helpers
- Loading branch information
1 parent
c1ae023
commit 4468330
Showing
6 changed files
with
438 additions
and
1 deletion.
There are no files selected for viewing
1 change: 1 addition & 0 deletions
1
a3p-integration/proposals/p:upgrade-19/mint-payment/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 |
56 changes: 56 additions & 0 deletions
56
a3p-integration/proposals/p:upgrade-19/mint-payment/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,56 @@ | ||
/* 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 mint a payment of a certain | ||
* bankAsset and deposit in an user wallet. | ||
* | ||
* The receiverAddress and label placeholders should be replaced with | ||
* the desired address and asset name during the execution of each test case. | ||
* | ||
* See z:acceptance/mintHolder.test.js | ||
* | ||
* @param {BootstrapPowers} powers | ||
*/ | ||
const sendBankAsset = async powers => { | ||
const { | ||
consume: { namesByAddress, contractKits: contractKitsP }, | ||
} = powers; | ||
|
||
const receiverAddress = '{{ADDRESS}}'; | ||
const label = '{{LABEL}}'; | ||
const valueStr = '{{VALUE}}'; | ||
const value = BigInt(valueStr) | ||
|
||
console.log(`Start sendBankAsset for ${label}`); | ||
|
||
const contractKits = await contractKitsP; | ||
const mintHolderKit = Array.from(contractKits.values()).filter( | ||
kit => kit.label && kit.label === label, | ||
); | ||
|
||
const { creatorFacet: mint, publicFacet: issuer } = mintHolderKit[0]; | ||
|
||
/* | ||
* Ensure that publicFacet holds an issuer by verifying that has | ||
* the makeEmptyPurse method. | ||
*/ | ||
await E(issuer).makeEmptyPurse() | ||
|
||
const brand = await E(issuer).getBrand(); | ||
const amount = harden({ value, brand }); | ||
const payment = await E(mint).mintPayment(amount); | ||
|
||
const receiverDepositFacet = E(namesByAddress).lookup( | ||
receiverAddress, | ||
'depositFacet', | ||
); | ||
|
||
await E(receiverDepositFacet).receive(payment); | ||
|
||
console.log(`Finished sendBankAsset for ${label}`); | ||
}; | ||
|
||
sendBankAsset; |
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,32 @@ | ||
/* eslint-env node */ | ||
|
||
import '@endo/init'; | ||
import test from 'ava'; | ||
import { addUser, provisionSmartWallet } from '@agoric/synthetic-chain'; | ||
import { | ||
mintPayment, | ||
getAssetList, | ||
swap, | ||
getPSMChildren, | ||
upgradeMintHolder, | ||
} from './test-lib/mintHolder-helpers.js'; | ||
|
||
const networkConfig = { | ||
rpcAddrs: ['http://0.0.0.0:26657'], | ||
chainName: 'agoriclocal', | ||
}; | ||
|
||
test('mintHolder contract is upgraded', async t => { | ||
const receiver = await addUser('receiver'); | ||
await provisionSmartWallet(receiver, `20000000ubld`); | ||
|
||
let assetList = await getAssetList(); | ||
t.log('List of mintHolder vats being upgraded: ', assetList); | ||
await upgradeMintHolder(`upgrade-mintHolder`, assetList); | ||
await mintPayment(t, receiver, assetList, 10); | ||
|
||
const psmLabelList = await getPSMChildren(fetch, networkConfig); | ||
assetList = await getAssetList(psmLabelList); | ||
t.log('List of assets being swapped with IST via PSM: ', assetList); | ||
await swap(t, receiver, assetList, 5); | ||
}); |
156 changes: 156 additions & 0 deletions
156
a3p-integration/proposals/p:upgrade-19/test-lib/mintHolder-helpers.js
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,156 @@ | ||
/* eslint-env node */ | ||
|
||
import { | ||
agoric, | ||
evalBundles, | ||
getDetailsMatchingVats, | ||
getISTBalance, | ||
} from '@agoric/synthetic-chain'; | ||
import { makeVstorageKit, retryUntilCondition } from '@agoric/client-utils'; | ||
import { readFile, writeFile } from 'node:fs/promises'; | ||
import { sendOfferAgd, psmSwap, snapshotAgoricNames } from './psm-helpers.js'; | ||
|
||
/** | ||
* @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); | ||
}; | ||
|
||
export const getPSMChildren = async (fetch, networkConfig) => { | ||
const { | ||
vstorage: { keys }, | ||
} = await makeVstorageKit({ fetch }, networkConfig); | ||
|
||
const children = await keys('published.psm.IST'); | ||
|
||
return children; | ||
}; | ||
|
||
export const getAssetList = async labelList => { | ||
const assetList = []; | ||
const { vbankAssets } = await snapshotAgoricNames(); | ||
|
||
// Determine the assets to consider based on labelList | ||
const assetsToConsider = | ||
labelList || Object.values(vbankAssets).map(asset => asset.issuerName); | ||
|
||
for (const label of assetsToConsider) { | ||
if (label === 'IST') { | ||
break; | ||
} | ||
|
||
const vbankAsset = Object.values(vbankAssets).find( | ||
asset => asset.issuerName === label, | ||
); | ||
assert(vbankAsset, `vbankAsset not found for ${label}`); | ||
|
||
const { denom } = vbankAsset; | ||
const mintHolderVat = `zcf-mintHolder-${label}`; | ||
|
||
assetList.push({ label, denom, mintHolderVat }); | ||
} | ||
|
||
return assetList; | ||
}; | ||
|
||
export const mintPayment = async (t, address, assetList, value) => { | ||
const SUBMISSION_DIR = 'mint-payment'; | ||
|
||
for (const asset of assetList) { | ||
const { label, denom } = asset; | ||
const scaled = BigInt(parseInt(value, 10) * 1_000_000).toString(); | ||
|
||
await replaceTemplateValuesInFile(`${SUBMISSION_DIR}/send-script`, { | ||
ADDRESS: address, | ||
LABEL: label, | ||
VALUE: scaled, | ||
}); | ||
|
||
await evalBundles(SUBMISSION_DIR); | ||
|
||
const balance = await getISTBalance(address, denom); | ||
|
||
// Add to value the BLD provisioned to smart wallet | ||
if (label === 'BLD') { | ||
value += 10; | ||
} | ||
|
||
t.is( | ||
balance, | ||
value, | ||
`receiver ${denom} balance ${balance} is not ${value}`, | ||
); | ||
} | ||
}; | ||
|
||
export const swap = async (t, address, assetList, want) => { | ||
for (const asset of assetList) { | ||
const { label, denom } = asset; | ||
|
||
// TODO: remove condition after fixing issue #10655 | ||
if (/^DAI/.test(label)) { | ||
break; | ||
} | ||
|
||
const pair = `IST.${label}`; | ||
|
||
const istBalanceBefore = await getISTBalance(address, 'uist'); | ||
const anchorBalanceBefore = await getISTBalance(address, denom); | ||
|
||
await psmSwap(address, ['swap', '--pair', pair, '--wantMinted', want], { | ||
now: Date.now, | ||
follow: agoric.follow, | ||
setTimeout, | ||
sendOffer: sendOfferAgd, | ||
}); | ||
|
||
const istBalanceAfter = await getISTBalance(address, 'uist'); | ||
const anchorBalanceAfter = await getISTBalance(address, denom); | ||
|
||
t.is(istBalanceAfter, istBalanceBefore + want); | ||
t.is(anchorBalanceAfter, anchorBalanceBefore - want); | ||
} | ||
}; | ||
|
||
const getIncarnationForAllVats = async assetList => { | ||
const vatsIncarnation = {}; | ||
|
||
for (const asset of assetList) { | ||
const { label, mintHolderVat } = asset; | ||
const matchingVats = await getDetailsMatchingVats(label); | ||
const expectedVat = matchingVats.find(vat => vat.vatName === mintHolderVat); | ||
vatsIncarnation[label] = expectedVat.incarnation; | ||
} | ||
assert(Object.keys(vatsIncarnation).length === assetList.length); | ||
|
||
return vatsIncarnation; | ||
}; | ||
|
||
const checkVatsUpgraded = (before, current) => { | ||
for (const vatLabel in before) { | ||
if (current[vatLabel] !== before[vatLabel] + 1) { | ||
console.log(`${vatLabel} upgrade failed. `); | ||
return false; | ||
} | ||
} | ||
return true; | ||
}; | ||
|
||
export const upgradeMintHolder = async (submissionPath, assetList) => { | ||
const before = await getIncarnationForAllVats(assetList); | ||
|
||
await evalBundles(submissionPath); | ||
|
||
return retryUntilCondition( | ||
async () => getIncarnationForAllVats(assetList), | ||
current => checkVatsUpgraded(before, current), | ||
`mintHolder upgrade not processed yet`, | ||
{ setTimeout, retryIntervalMs: 5000, maxRetries: 15 }, | ||
); | ||
}; |
Oops, something went wrong.