diff --git a/a3p-integration/proposals/z:acceptance/package.json b/a3p-integration/proposals/z:acceptance/package.json index e5941bd1a8d..425de5fd527 100644 --- a/a3p-integration/proposals/z:acceptance/package.json +++ b/a3p-integration/proposals/z:acceptance/package.json @@ -15,9 +15,9 @@ "@endo/far": "^1.1.5", "@endo/init": "^1.1.4", "ava": "^6.1.2", + "better-sqlite3": "11.5.0", "execa": "^9.3.1", - "tsx": "^4.17.0", - "better-sqlite3": "11.5.0" + "tsx": "^4.17.0" }, "ava": { "concurrency": 1, diff --git a/a3p-integration/proposals/z:acceptance/priceFeed.test.js b/a3p-integration/proposals/z:acceptance/priceFeed.test.js index 94be7d731ac..37c5ddfef7b 100644 --- a/a3p-integration/proposals/z:acceptance/priceFeed.test.js +++ b/a3p-integration/proposals/z:acceptance/priceFeed.test.js @@ -1,6 +1,20 @@ +/* eslint-env node */ + +/** + * @file The purpose of this test is to make sure; + * - Old priceFeed and scaledPriceAuthority vats that are replaced with new ones are truly quiescent. + * The method we use for this is to check if those vats received any deliveries from swingset that + * are of type "message" or "notify" (We give delivery types related to GC a pass since GC cycles + * aren't in our control). + * - Make sure new price feeds can produce quotes + * - Make sure vaults receive quotes + */ + import test from 'ava'; import '@endo/init'; import { + agd, + agoric, generateOracleMap, getPriceQuote, GOV1ADDR, @@ -8,7 +22,6 @@ import { GOV3ADDR, pushPrices, registerOraclesForBrand, - waitForBlock, } from '@agoric/synthetic-chain'; import { snapshotVat } from './test-lib/vat-helpers.js'; import { @@ -18,6 +31,16 @@ import { pollRoundIdAndPushPrice, scale6, } from './test-lib/priceFeed-lib.js'; +import { + retryUntilCondition, + waitUntilOfferResult, +} from './test-lib/sync-tools.js'; + +const ambientAuthority = { + query: agd.query, + follow: agoric.follow, + setTimeout, +}; const config = { vatNames: [ @@ -41,16 +64,80 @@ const config = { }, }; -// Remove this one when #10296 goes in +/** + * https://github.com/Agoric/agoric-sdk/pull/10074 introduced new price feeds to the system. + * However, `f:replace-price-feeds` does not activate oracles for future layers of the build. + * Meaning, proposals running after `f:replace-price-feeds` will not have oracles that received + * invitationMakers for new price feeds and there will not be quotes published by new + * price feeds. There are conflicting work to fix this issue, see; + * - https://github.com/Agoric/agoric-sdk/pull/10296 + * - https://github.com/Agoric/agoric-sdk/pull/10317 + * - https://github.com/Agoric/agoric-sdk/pull/10296#pullrequestreview-2389390624 + * + * The purpose of init() is to unblock testing new price feeds from the situation above. We can remove + * this when it resolves. + * + * @param {Map>} oraclesByBrand + */ const init = async oraclesByBrand => { - await registerOraclesForBrand('ATOM', oraclesByBrand); - await waitForBlock(3); - await registerOraclesForBrand('stATOM', oraclesByBrand); - await waitForBlock(3); + const retryOptions = { + log: console.log, + maxRetries: 5, + retryIntervalMs: 3000, + }; + + const atomInviteOffers = []; + registerOraclesForBrand('ATOM', oraclesByBrand); + // @ts-expect-error we expect oraclesByBrand.get('ATOM') will not return undefined + for (const { address, offerId } of oraclesByBrand.get('ATOM')) { + const offerP = waitUntilOfferResult( + address, + offerId, + false, + ambientAuthority, + { + errorMessage: `ERROR: ${address} could not accept invite, offerID: ${offerId}`, + ...retryOptions, + }, + ); + atomInviteOffers.push(offerP); + } + await Promise.all(atomInviteOffers); + + const stAtomInviteOffers = []; + registerOraclesForBrand('stATOM', oraclesByBrand); + // @ts-expect-error we expect oraclesByBrand.get('ATOM') will not return undefined + for (const { address, offerId } of oraclesByBrand.get('stATOM')) { + const offerP = waitUntilOfferResult( + address, + offerId, + false, + ambientAuthority, + { + errorMessage: `ERROR: ${address} could not accept invite, offerID: ${offerId}`, + ...retryOptions, + }, + ); + + stAtomInviteOffers.push(offerP); + } + await Promise.all(stAtomInviteOffers); await pushPrices(1, 'ATOM', oraclesByBrand, 1); - await waitForBlock(3); + // await waitForBlock(3); + await retryUntilCondition( + () => getPriceQuote('ATOM'), + res => res === '+1000000', + 'ATOM quote not received', + { ...retryOptions, setTimeout }, + ); await pushPrices(1, 'stATOM', oraclesByBrand, 1); + await retryUntilCondition( + () => getPriceQuote('stATOM'), + res => res === '+1000000', + 'stATOM quote not received', + { ...retryOptions, setTimeout }, + ); }; /** @@ -62,7 +149,7 @@ test.before(async t => { await bankSend(GOV2ADDR, '10000000uist', GOV1ADDR); await bankSend(GOV3ADDR, '10000000uist', GOV1ADDR); - const oraclesByBrand = generateOracleMap('f-priceFeeds', ['ATOM', 'stATOM']); + const oraclesByBrand = generateOracleMap('z-acc', ['ATOM', 'stATOM']); t.log(oraclesByBrand); await init(oraclesByBrand); diff --git a/a3p-integration/proposals/z:acceptance/test-lib/vat-helpers.js b/a3p-integration/proposals/z:acceptance/test-lib/vat-helpers.js index f4e42d8a3c6..b37af097248 100644 --- a/a3p-integration/proposals/z:acceptance/test-lib/vat-helpers.js +++ b/a3p-integration/proposals/z:acceptance/test-lib/vat-helpers.js @@ -8,9 +8,12 @@ import { HOME, dbTool } from '@agoric/synthetic-chain'; const swingstorePath = '~/.agoric/data/agoric/swingstore.sqlite'; /** + * Initially from https://github.com/Agoric/agoric-3-proposals/blob/93bb953db209433499db08ae563942d1bf7eeb46/proposals/76%3Avaults-auctions/vatDetails.js#L36 + * but with small modifications + * * @param {import('better-sqlite3').Database} db */ -export const makeSwingstore = db => { +const makeSwingstore = db => { const sql = dbTool(db); /** @param {string} key */ @@ -65,23 +68,6 @@ const initSwingstore = () => { return makeSwingstore(dbOpenAmbient(fullPath, { readonly: true })); }; -/** - * @param {string} vatName - */ -export const getVatsWithSameName = async vatName => { - const kStore = initSwingstore(); - - const vatIDs = kStore.findVatsExact(vatName); - const vats = vatIDs.map(id => { - const vatLookup = kStore.lookupVat(id); - return { - options: vatLookup.options(), - currentSpan: vatLookup.currentSpan(), - }; - }); - return vats; -}; - /** * * @param {string} vatId @@ -114,7 +100,3 @@ export const snapshotVat = vatName => { return snapshots; }; - -export const swingStore = makeSwingstore( - dbOpenAmbient(swingstorePath.replace(/^~/, HOME), { readonly: true }), -); diff --git a/a3p-integration/proposals/z:acceptance/test.sh b/a3p-integration/proposals/z:acceptance/test.sh index f9982b31916..a83c2f51b53 100755 --- a/a3p-integration/proposals/z:acceptance/test.sh +++ b/a3p-integration/proposals/z:acceptance/test.sh @@ -26,5 +26,8 @@ echo ACCEPTANCE TESTING state sync echo ACCEPTANCE TESTING wallet yarn ava wallet.test.js +echo ACCEPTANCE TESTING replaced price feeds +yarn ava priceFeed.test.js + echo ACCEPTANCE TESTING vaults yarn ava vaults.test.js diff --git a/a3p-integration/proposals/z:acceptance/vaults.test.js b/a3p-integration/proposals/z:acceptance/vaults.test.js index 5545a9381be..1b21a049367 100644 --- a/a3p-integration/proposals/z:acceptance/vaults.test.js +++ b/a3p-integration/proposals/z:acceptance/vaults.test.js @@ -14,7 +14,6 @@ import { ATOM_DENOM, USER1ADDR, waitForBlock, - registerOraclesForBrand, generateOracleMap, } from '@agoric/synthetic-chain'; import { getBalances, agopsVaults } from './test-lib/utils.js'; @@ -30,13 +29,12 @@ test.before(async t => { retryIntervalMs: 5000, // in ms }; t.context = { - roundId: 1, + roundId: 3, retryOpts: { pushPriceRetryOpts, }, }; const oraclesByBrand = generateOracleMap('z-acc', ['ATOM']); - await registerOraclesForBrand('ATOM', oraclesByBrand); const price = 15.2; // @ts-expect-error t.context is fine diff --git a/a3p-integration/proposals/z:acceptance/yarn.lock b/a3p-integration/proposals/z:acceptance/yarn.lock index 72977f2a884..8741b14d421 100644 --- a/a3p-integration/proposals/z:acceptance/yarn.lock +++ b/a3p-integration/proposals/z:acceptance/yarn.lock @@ -784,6 +784,17 @@ __metadata: languageName: node linkType: hard +"better-sqlite3@npm:11.5.0": + version: 11.5.0 + resolution: "better-sqlite3@npm:11.5.0" + dependencies: + bindings: "npm:^1.5.0" + node-gyp: "npm:latest" + prebuild-install: "npm:^7.1.1" + checksum: 10c0/c24200972e11f6f99c4e6538122bd7ec8b31b92b2fa095f4b595cc39fedf924cb0a93fd326f0900415eccdf634367f7bba2ba4eaa4d164edd7352f4cfaaaec51 + languageName: node + linkType: hard + "better-sqlite3@npm:^9.6.0": version: 9.6.0 resolution: "better-sqlite3@npm:9.6.0" @@ -2517,6 +2528,7 @@ __metadata: "@endo/far": "npm:^1.1.5" "@endo/init": "npm:^1.1.4" ava: "npm:^6.1.2" + better-sqlite3: "npm:11.5.0" execa: "npm:^9.3.1" tsx: "npm:^4.17.0" typescript: "npm:^5.5.4"