From 9686fb70b48ffb61c46cf987bf5be06683233b65 Mon Sep 17 00:00:00 2001 From: Chris Hibbert Date: Wed, 19 Jun 2024 13:29:41 -0700 Subject: [PATCH] test: move vault upgrade from test to use phase refactor oracle registration to make it simpler to push prices later --- .../proposals/a:upgrade-next/agd-tools.js | 55 +++++++++++++++---- .../proposals/a:upgrade-next/upgradeVaults.js | 30 ++++++++++ .../a:upgrade-next/upgradeVaults.test.js | 35 +++--------- .../proposals/a:upgrade-next/use.sh | 2 + 4 files changed, 85 insertions(+), 37 deletions(-) create mode 100644 a3p-integration/proposals/a:upgrade-next/upgradeVaults.js diff --git a/a3p-integration/proposals/a:upgrade-next/agd-tools.js b/a3p-integration/proposals/a:upgrade-next/agd-tools.js index f9da630c7851..2c3fd01ad1aa 100644 --- a/a3p-integration/proposals/a:upgrade-next/agd-tools.js +++ b/a3p-integration/proposals/a:upgrade-next/agd-tools.js @@ -48,30 +48,63 @@ export const checkForOracle = async (t, name) => { t.truthy(instance); }; -export const addOraclesForBrand = async (brandIn, oraclesByBrand) => { +export const registerOraclesForBrand = async (brandIn, oraclesByBrand) => { await null; const promiseArray = []; - const oraclesWithID = []; - // newOfferId() waits 1 second - const offerIdBase = await newOfferId(); - for (let i = 0; i < ORACLE_ADDRESSES.length; i += 1) { - const oracleAddress = ORACLE_ADDRESSES[i]; - const offerId = `${offerIdBase}.${i}`; - oraclesWithID.push({ address: oracleAddress, offerId }); - + const oraclesWithID = oraclesByBrand.get(brandIn); + for (const oracle of oraclesWithID) { + const { address, offerId } = oracle; promiseArray.push( executeOffer( - oracleAddress, + address, agops.oracle('accept', '--offerId', offerId, `--pair ${brandIn}.USD`), ), ); } - oraclesByBrand.set(brandIn, oraclesWithID); return Promise.all(promiseArray); }; +/** + * Generate a consistent map of oracleIDs for a brand that can be used to + * register oracles or to push prices. The baseID changes each time new + * invitations are sent/accepted, and need to be maintained as constants in + * scripts that use the oracles. Each oracleAddress and brand needs a unique + * offerId, so we create recoverable IDs using the brandName and oracle id, + * mixed with the upgrade at which the invitations were accepted. + * + * @param {string} baseId + * @param {string} brandName + */ +const addOraclesForBrand = (baseId, brandName) => { + const oraclesWithID = []; + for (let i = 0; i < ORACLE_ADDRESSES.length; i += 1) { + const oracleAddress = ORACLE_ADDRESSES[i]; + const offerId = `${brandName}.${baseId}.${i}`; + oraclesWithID.push({ address: oracleAddress, offerId }); + } + return oraclesWithID; +}; + +/** + * Generate a consistent map of oracleIDs and brands that can be used to + * register oracles or to push prices. The baseID changes each time new + * invitations are sent/accepted, and need to be maintained as constants in + * scripts that use these records to push prices. + * + * @param {string} baseId + * @param {string[]} brandNames + */ +export const generateOracleMap = (baseId, brandNames) => { + const oraclesByBrand = new Map(); + for (const brandName of brandNames) { + const oraclesWithID = addOraclesForBrand(baseId, brandName); + oraclesByBrand.set(brandName, oraclesWithID); + } + return oraclesByBrand; +}; + export const pushPrices = (price, brandIn, oraclesByBrand) => { const promiseArray = []; diff --git a/a3p-integration/proposals/a:upgrade-next/upgradeVaults.js b/a3p-integration/proposals/a:upgrade-next/upgradeVaults.js new file mode 100644 index 000000000000..981daeba3268 --- /dev/null +++ b/a3p-integration/proposals/a:upgrade-next/upgradeVaults.js @@ -0,0 +1,30 @@ +#!/usr/bin/env node + +import assert from 'node:assert/strict'; +import { + generateOracleMap, + getPriceQuote, + pushPrices, + registerOraclesForBrand, +} from './agd-tools.js'; + +const BRANDNAMES = ['ATOM', 'stATOM', 'stTIA', 'stOSMO', 'stkATOM']; +const oraclesByBrand = generateOracleMap('u16', BRANDNAMES); + +// There are no old prices for the other currencies. +const atomOutPre = await getPriceQuote('ATOM'); +assert.equal(atomOutPre, '+12010000'); + +console.log('adding oracle for each brand'); +await registerOraclesForBrand('ATOM', oraclesByBrand); +await registerOraclesForBrand('stATOM', oraclesByBrand); +await registerOraclesForBrand('stTIA', oraclesByBrand); +await registerOraclesForBrand('stOSMO', oraclesByBrand); +await registerOraclesForBrand('stkATOM', oraclesByBrand); + +console.log('pushing new prices'); +await pushPrices(11.2, 'ATOM', oraclesByBrand); +await pushPrices(11.3, 'stTIA', oraclesByBrand); +await pushPrices(11.4, 'stATOM', oraclesByBrand); +await pushPrices(11.5, 'stOSMO', oraclesByBrand); +await pushPrices(11.6, 'stkATOM', oraclesByBrand); diff --git a/a3p-integration/proposals/a:upgrade-next/upgradeVaults.test.js b/a3p-integration/proposals/a:upgrade-next/upgradeVaults.test.js index 1dc1c6622328..890a58173121 100644 --- a/a3p-integration/proposals/a:upgrade-next/upgradeVaults.test.js +++ b/a3p-integration/proposals/a:upgrade-next/upgradeVaults.test.js @@ -10,11 +10,11 @@ import { } from '@agoric/synthetic-chain'; import { - addOraclesForBrand, bankSend, BID_OFFER_ID, checkForOracle, createBid, + generateOracleMap, getLiveOffers, getPriceQuote, pushPrices, @@ -40,27 +40,10 @@ const checkPriceFeedVatsUpdated = async t => { ]); }; -const oraclesByBrand = new Map(); - -const tryPushPrices = async t => { - // There are no old prices for the other currencies. - const atomOutPre = await getPriceQuote('ATOM'); - t.is(atomOutPre, '+12010000'); - - t.log('adding oracle for each brand'); - await addOraclesForBrand('ATOM', oraclesByBrand); - await addOraclesForBrand('stATOM', oraclesByBrand); - await addOraclesForBrand('stTIA', oraclesByBrand); - await addOraclesForBrand('stOSMO', oraclesByBrand); - await addOraclesForBrand('stkATOM', oraclesByBrand); - - t.log('pushing new prices'); - await pushPrices(11.2, 'ATOM', oraclesByBrand); - await pushPrices(11.3, 'stTIA', oraclesByBrand); - await pushPrices(11.4, 'stATOM', oraclesByBrand); - await pushPrices(11.5, 'stOSMO', oraclesByBrand); - await pushPrices(11.6, 'stkATOM', oraclesByBrand); +const BRANDNAMES = ['ATOM', 'stATOM', 'stTIA', 'stOSMO', 'stkATOM']; +const oraclesByBrand = generateOracleMap('u16', BRANDNAMES); +const checkNewQuotes = async t => { t.log('awaiting new quotes'); const atomOut = await getPriceQuote('ATOM'); t.is(atomOut, '+11200000'); @@ -71,7 +54,7 @@ const tryPushPrices = async t => { const osmoOut = await getPriceQuote('stOSMO'); t.is(osmoOut, '+11500000'); const stkAtomOut = await getPriceQuote('stkATOM'); - t.is(stkAtomOut, '+11600000'); + await t.is(stkAtomOut, '+11600000'); }; const createNewBid = async t => { @@ -106,7 +89,7 @@ const triggerAuction = async t => { t.is(atomOut, '+5200000'); }; -const makeNewAuctionVat = async t => { +const checkAuctionVat = async t => { const details = await getDetailsMatchingVats('auctioneer'); // This query matches both the auction and its governor, so double the count t.true(Object.keys(details).length > 2); @@ -117,8 +100,8 @@ test('liquidation post upgrade', async t => { t.log('starting upgrade vaults test'); await checkPriceFeedVatsUpdated(t); - t.log('starting pushPrices'); - await tryPushPrices(t); + t.log('check new price quotes'); + await checkNewQuotes(t); t.log('create a new Bid for the auction'); await createNewBid(t); @@ -130,5 +113,5 @@ test('liquidation post upgrade', async t => { await triggerAuction(t); t.log('make new auction'); - await makeNewAuctionVat(t); + await checkAuctionVat(t); }); diff --git a/a3p-integration/proposals/a:upgrade-next/use.sh b/a3p-integration/proposals/a:upgrade-next/use.sh index 094b3f7f881c..dff35e765b1d 100755 --- a/a3p-integration/proposals/a:upgrade-next/use.sh +++ b/a3p-integration/proposals/a:upgrade-next/use.sh @@ -4,3 +4,5 @@ # actions are executed in the upgraded chain software and the effects are # persisted in the generated image for the upgrade, so they can be used in # later steps, such as the "test" step, or further proposal layers. + +./upgradeVaults.js