From a3c30d1c8a9c2458328fcf05f2b08388af69a50a Mon Sep 17 00:00:00 2001 From: Turadg Aleahmad Date: Wed, 28 Aug 2024 07:10:57 -0700 Subject: [PATCH 1/2] feat(agops): robust to no initial price feed --- packages/agoric-cli/src/commands/oracle.js | 60 ++++++++++++---------- 1 file changed, 32 insertions(+), 28 deletions(-) diff --git a/packages/agoric-cli/src/commands/oracle.js b/packages/agoric-cli/src/commands/oracle.js index af03aad0c21..59f859a4957 100644 --- a/packages/agoric-cli/src/commands/oracle.js +++ b/packages/agoric-cli/src/commands/oracle.js @@ -271,14 +271,13 @@ export const makeOracleCommand = (logger, io = {}) => { ); const unitPrice = scaleDecimals(price); - console.error(`${pair[0]}-${pair[1]}_price_feed: before setPrice`); + const feedPath = `published.priceFeed.${pair[0]}-${pair[1]}_price_feed`; const readPrice = () => /** @type {Promise} */ ( - readLatestHead( - `published.priceFeed.${pair[0]}-${pair[1]}_price_feed`, - ).catch(err => { - console.warn(`cannot get ${pair[0]}-${pair[1]}_price_feed`, err); + readLatestHead(feedPath).catch(() => { + const viewer = `https://vstorage.agoric.net/#${networkConfig.rpcAddrs[0]}|published,published.priceFeed|${feedPath}`; + console.warn(`no existing price data; see ${viewer}`); return undefined; }) ); @@ -297,30 +296,35 @@ export const makeOracleCommand = (logger, io = {}) => { show(fmtFeed(before)); } - console.error( - 'Choose lead oracle operator order based on latestRound...', - ); const keyOrder = keys.map(normalizeAddress); - const latestRoundP = readLatestHead( - `published.priceFeed.${pair[0]}-${pair[1]}_price_feed.latestRound`, - ); - await Promise.race([ - delay(5000), - latestRoundP.then(round => { - // @ts-expect-error XXX get type from contract - const { roundId, startedAt, startedBy } = round; - show({ - startedAt: fmtSecs(startedAt.absValue), - roundId, - startedBy, - }); - if (startedBy === keyOrder[0]) { - keyOrder.reverse(); - } - }), - ]).catch(err => { - console.warn(err); - }); + if (before) { + console.error( + 'Choose lead oracle operator order based on latestRound...', + ); + + const latestRoundP = + /** @type {Promise<{roundId: number, startedAt: import('@agoric/time').TimestampRecord, startedBy: string}>} */ ( + readLatestHead( + `published.priceFeed.${pair[0]}-${pair[1]}_price_feed.latestRound`, + ) + ); + await Promise.race([ + delay(5000), + latestRoundP.then(round => { + const { roundId, startedAt, startedBy } = round; + show({ + startedAt: fmtSecs(startedAt.absValue), + roundId, + startedBy, + }); + if (startedBy === keyOrder[0]) { + keyOrder.reverse(); + } + }), + ]).catch(err => { + console.warn(err); + }); + } const instance = lookupPriceAggregatorInstance(pair); From 1fcf43c3bd5dd854fee02192dae85ef4389e4ccc Mon Sep 17 00:00:00 2001 From: Turadg Aleahmad Date: Wed, 28 Aug 2024 07:29:28 -0700 Subject: [PATCH 2/2] feat(agops): feedback on missing oracle admin ids --- packages/agoric-cli/src/commands/oracle.js | 25 +++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/packages/agoric-cli/src/commands/oracle.js b/packages/agoric-cli/src/commands/oracle.js index 59f859a4957..d8f44b2159b 100644 --- a/packages/agoric-cli/src/commands/oracle.js +++ b/packages/agoric-cli/src/commands/oracle.js @@ -26,6 +26,8 @@ const COSMOS_UNIT = 1_000_000n; const scaleDecimals = num => BigInt(num * Number(COSMOS_UNIT)); /** + * Prints JSON output to stdout and diagnostic info (like logs) to stderr + * * @param {import('anylogger').Logger} logger * @param {{ * delay?: (ms: number) => Promise, @@ -327,17 +329,30 @@ export const makeOracleCommand = (logger, io = {}) => { } const instance = lookupPriceAggregatorInstance(pair); - - console.error('pushPrice from each:', keyOrder); + const adminOfferIds = {}; for await (const from of keyOrder) { - const oracleAdminAcceptOfferId = await findOracleCap( + adminOfferIds[from] = await findOracleCap( instance, from, readLatestHead, ); - if (!oracleAdminAcceptOfferId) { - throw Error(`no oracle invitation found: ${from}`); + if (!adminOfferIds[from]) { + console.error( + `Failed to find an offer accepting oracle invitation for ${from}. Accept and try again:`, + ); + console.error( + ` agops oracle accept > accept.json; agoric wallet send --from ${from} --offer accept.json`, + ); } + } + assert( + Object.values(adminOfferIds).every(x => x), + 'Missing oracle admin offer ids', + ); + + console.error('pushPrice from each:', keyOrder); + for await (const from of keyOrder) { + const oracleAdminAcceptOfferId = adminOfferIds[from]; show({ from, oracleAdminAcceptOfferId }); const offerId = `pushPrice-${Date.now()}`; const offer = Offers.fluxAggregator.PushPrice(