From abc48dcf26d9770a6c79f61686170928d4ecd373 Mon Sep 17 00:00:00 2001 From: anilhelvaci Date: Fri, 1 Nov 2024 15:16:11 +0300 Subject: [PATCH 1/3] chore(acceptance-sync-tools): implement `waitUntilElectionResults` Refs: https://github.com/Agoric/agoric-sdk/issues/10378 chore(acceptance-sync-tools): address requested changes Refs: https://github.com/Agoric/agoric-sdk/issues/10378 --- packages/client-utils/src/sync-tools.js | 97 +++++++- packages/client-utils/test/sync-tools.test.js | 211 +++++++++++++++++- 2 files changed, 303 insertions(+), 5 deletions(-) diff --git a/packages/client-utils/src/sync-tools.js b/packages/client-utils/src/sync-tools.js index 35701da3263..65eaa354457 100644 --- a/packages/client-utils/src/sync-tools.js +++ b/packages/client-utils/src/sync-tools.js @@ -10,7 +10,7 @@ * - condition: dest account has a balance >= sent token * - Making sure an offer resulted successfully * - Making sure an offer was exited successfully - * + * - Make sure an election held by a given committee (see @agoric/governance) turned out as expected */ /** @@ -98,7 +98,7 @@ export const retryUntilCondition = async ( } } catch (error) { if (error instanceof Error) { - log(`Error: ${error.message}`); + log(`Error: ${error.message}: ${error.stack}`); } else { log(`Unknown error: ${String(error)}`); } @@ -325,3 +325,96 @@ export const waitUntilOfferExited = async (addr, offerId, io, options) => { { setTimeout, ...resolvedOptions }, ); }; + +/// ////////// Make sure an election held by a given committee (see @agoric/governance) turned out as expected ///////////// + +/** + * @typedef {{ + * latestOutcome: { + * outcome: string; + * question: import('@endo/marshal').RemotableObject + * }, + * latestQuestion: { + * closingRule: { deadline: bigint }, + * questionHandle: import('@endo/marshal').RemotableObject + * } + * }} ElectionResult + */ + +/** + * @param {string} basePath + * @param {{follow: (...params: string[]) => Promise; marshaller: import("@endo/marshal").Marshal}} io + * @returns {Promise} + */ +export const fetchLatestEcQuestion = async (basePath, io) => { + const { follow, marshaller } = io; + const pathOutcome = `:${basePath}.latestOutcome`; + const pathQuestion = `:${basePath}.latestQuestion`; + + const [latestOutcome, latestQuestion] = await Promise.all([ + follow('-lF', pathOutcome, '-o', 'text').then(outcomeRaw => + marshaller.fromCapData(JSON.parse(outcomeRaw)), + ), + follow('-lF', pathQuestion, '-o', 'text').then(questionRaw => + marshaller.fromCapData(JSON.parse(questionRaw)), + ), + ]); + + return { latestOutcome, latestQuestion }; +}; + +/** + * + * @param {ElectionResult} electionResult + * @param {{ outcome: string; deadline: bigint }} expectedResult + * @returns {boolean} + */ +const checkCommitteeElectionResult = (electionResult, expectedResult) => { + const { + latestOutcome: { outcome, question }, + latestQuestion: { + closingRule: { deadline }, + questionHandle, + }, + } = electionResult; + const { outcome: expectedOutcome, deadline: expectedDeadline } = + expectedResult; + + return ( + expectedOutcome === outcome && + deadline === expectedDeadline && + question === questionHandle + ); +}; + +/** + * Depends on "@agoric/governance" package's committee implementation where for a given committee + * there's two child nodes in vstorage named "latestOutcome" and "latestQuestion" respectively. + * + * @param {string} committeePathBase + * @param {{ + * outcome: string; + * deadline: bigint; + * }} expectedResult + * @param {{follow: (...params: string[]) => Promise; marshaller: import("@endo/marshal").Marshal}} ambientAuthority + * @param {WaitUntilOptions} options + */ +export const waitUntilElectionResult = ( + committeePathBase, + expectedResult, + ambientAuthority, + options, +) => { + const { follow, marshaller } = ambientAuthority; + + const { maxRetries, retryIntervalMs, errorMessage, log } = + overrideDefaultOptions(options); + + return retryUntilCondition( + () => fetchLatestEcQuestion(committeePathBase, { follow, marshaller }), + electionResult => + checkCommitteeElectionResult(electionResult, expectedResult), + errorMessage, + { maxRetries, retryIntervalMs, log, setTimeout }, + ); +}; diff --git a/packages/client-utils/test/sync-tools.test.js b/packages/client-utils/test/sync-tools.test.js index 0d880324937..38ee93a3d61 100644 --- a/packages/client-utils/test/sync-tools.test.js +++ b/packages/client-utils/test/sync-tools.test.js @@ -1,10 +1,13 @@ /* eslint-env node */ // @ts-check import test from 'ava'; - +import '@endo/init/debug.js'; +import { makeMarshal } from '@endo/marshal'; +import { Far } from '@endo/far'; import { waitUntilAccountFunded, waitUntilContractDeployed, + waitUntilElectionResult, waitUntilInvitationReceived, waitUntilOfferExited, waitUntilOfferResult, @@ -14,13 +17,43 @@ import { const retryIntervalMs = 10; const DEFAULT_TIMEOUT = 30; +const makeSimpleMarshaller = () => { + const vals = []; + const fromVal = val => { + vals.push(val); + return vals.length - 1; + }; + const toVal = slot => vals[slot]; + return makeMarshal(fromVal, toVal, { + serializeBodyFormat: 'smallcaps', + marshalSaveError: err => { + throw err; + }, + }); +}; +harden(makeSimpleMarshaller); + const makeFakeFollow = () => { - let value = [[]]; + const marshaller = makeSimpleMarshaller(); + let value; const setValue = newValue => (value = newValue); const follow = () => Promise.resolve(value); + /** + * + * @param {any} _ + * @param {string} path Assumes the path will be something like 'published.auction.book0' + * where value = { book0: {...} } + */ + const followByPath = (_, path) => { + const propName = path.split('.').at(-1); + return Promise.resolve( + // @ts-expect-error path will be a sequence of strings joined by "." + JSON.stringify(marshaller.toCapData(value[propName])), + ); + }; - return { setValue, follow }; + return { setValue, follow, followByPath, marshaller }; }; const makeFakeBalanceQuery = () => { @@ -422,3 +455,175 @@ test.serial('wait until offer exited', async t => { await t.throwsAsync(waitP); }); + +test.serial('wait election result: question handle is adhered', async t => { + const oldQuestionHandle = Far('Question 1', {}); + const newQuestionHandle = Far('Question 2', {}); + + const { setValue, followByPath, marshaller } = makeFakeFollow(); + const initState = harden({ + latestOutcome: { outcome: 'win', question: oldQuestionHandle }, + latestQuestion: { + closingRule: { deadline: 2n }, + questionHandle: newQuestionHandle, + }, + }); + setValue(initState); + + const waitFailP = waitUntilElectionResult( + 'dummyPath', + { outcome: 'win', deadline: 2n }, + { + follow: followByPath, + marshaller, + }, + { + errorMessage: 'Oops, election did not turn out as expected', + maxRetries: 3, + retryIntervalMs: 500, + log: console.log, + }, + ); + + // Make sure the promise rejects when state is not updated + await t.throwsAsync(waitFailP); + + const waitHappyP = waitUntilElectionResult( + 'dummyPath', + { outcome: 'win', deadline: 2n }, + { + follow: followByPath, + marshaller, + }, + { + errorMessage: 'Oops, election did not turn out as expected', + maxRetries: 5, + retryIntervalMs: 1000, + log: console.log, + }, + ); + + // Now set the state to a value where the promise should resolve + const updatedState = harden({ + ...initState, + latestOutcome: { outcome: 'win', question: newQuestionHandle }, + }); + setTimeout(() => setValue(updatedState), 2000); + + await t.notThrowsAsync(waitHappyP); +}); + +test.serial('wait election result: deadline is adhered', async t => { + const questionHandle = Far('Question', {}); + + const { setValue, followByPath, marshaller } = makeFakeFollow(); + const initState = harden({ + latestOutcome: { outcome: 'win', question: questionHandle }, + latestQuestion: { + closingRule: { deadline: 2n }, + questionHandle, + }, + }); + setValue(initState); + + const waitFailP = waitUntilElectionResult( + 'dummyPath', + { outcome: 'win', deadline: 5n }, + { + follow: followByPath, + marshaller, + }, + { + errorMessage: 'Oops, election did not turn out as expected', + maxRetries: 3, + retryIntervalMs: 500, + log: console.log, + }, + ); + + // Make sure the promise rejects when state is not updated + await t.throwsAsync(waitFailP); + + const waitHappyP = waitUntilElectionResult( + 'dummyPath', + { outcome: 'win', deadline: 5n }, + { + follow: followByPath, + marshaller, + }, + { + errorMessage: 'Oops, election did not turn out as expected', + maxRetries: 5, + retryIntervalMs: 1000, + log: console.log, + }, + ); + + // Now set the state to a value where the promise should resolve + const updatedState = harden({ + ...initState, + latestQuestion: { + closingRule: { deadline: 5n }, + questionHandle, + }, + }); + setTimeout(() => setValue(updatedState), 2000); + + await t.notThrowsAsync(waitHappyP); +}); + +test.serial('wait election result: outcome is adhered', async t => { + const questionHandle = Far('Question', {}); + + const { setValue, followByPath, marshaller } = makeFakeFollow(); + const initState = harden({ + latestOutcome: { outcome: 'lose', question: questionHandle }, + latestQuestion: { + closingRule: { deadline: 5n }, + questionHandle, + }, + }); + setValue(initState); + + const waitFailP = waitUntilElectionResult( + 'dummyPath', + { outcome: 'win', deadline: 5n }, + { + follow: followByPath, + marshaller, + }, + { + errorMessage: 'Oops, election did not turn out as expected', + maxRetries: 3, + retryIntervalMs: 500, + log: console.log, + }, + ); + + // Make sure the promise rejects when state is not updated + await t.throwsAsync(waitFailP); + + const waitHappyP = waitUntilElectionResult( + 'dummyPath', + { outcome: 'win', deadline: 5n }, + { + follow: followByPath, + marshaller, + }, + { + errorMessage: 'Oops, election did not turn out as expected', + maxRetries: 5, + retryIntervalMs: 1000, + log: console.log, + }, + ); + + // Now set the state to a value where the promise should resolve + const updatedState = harden({ + ...initState, + latestOutcome: { outcome: 'win', question: questionHandle }, + }); + setTimeout(() => setValue(updatedState), 2000); + + await t.notThrowsAsync(waitHappyP); +}); From a5baf9cd8a2679b89aaa55fc6ab27cdccef936fe Mon Sep 17 00:00:00 2001 From: anilhelvaci Date: Wed, 13 Nov 2024 17:55:36 +0300 Subject: [PATCH 2/3] chore(sync-tools): move to `@agoric/client-utils`, adhere to testing speed and new type rules Refs: #10378 --- packages/client-utils/src/sync-tools.js | 13 ++++-- .../test/snapshots/exports.test.js.md | 2 + packages/client-utils/test/sync-tools.test.js | 41 +++++++++++-------- 3 files changed, 34 insertions(+), 22 deletions(-) diff --git a/packages/client-utils/src/sync-tools.js b/packages/client-utils/src/sync-tools.js index 65eaa354457..1f02d62a153 100644 --- a/packages/client-utils/src/sync-tools.js +++ b/packages/client-utils/src/sync-tools.js @@ -396,18 +396,23 @@ const checkCommitteeElectionResult = (electionResult, expectedResult) => { * outcome: string; * deadline: bigint; * }} expectedResult - * @param {{follow: (...params: string[]) => Promise; marshaller: import("@endo/marshal").Marshal}} ambientAuthority + * @param {{ + * follow: (...params: string[]) => Promise; + * marshaller: import("@endo/marshal").Marshal, + * log: typeof console.log, + * setTimeout: typeof global.setTimeout + * }} io * @param {WaitUntilOptions} options */ export const waitUntilElectionResult = ( committeePathBase, expectedResult, - ambientAuthority, + io, options, ) => { - const { follow, marshaller } = ambientAuthority; + const { follow, marshaller, log, setTimeout } = io; - const { maxRetries, retryIntervalMs, errorMessage, log } = + const { maxRetries, retryIntervalMs, errorMessage } = overrideDefaultOptions(options); return retryUntilCondition( diff --git a/packages/client-utils/test/snapshots/exports.test.js.md b/packages/client-utils/test/snapshots/exports.test.js.md index 7c39db1562f..4b08b118a85 100644 --- a/packages/client-utils/test/snapshots/exports.test.js.md +++ b/packages/client-utils/test/snapshots/exports.test.js.md @@ -10,6 +10,7 @@ Generated by [AVA](https://avajs.dev). [ 'boardSlottingMarshaller', + 'fetchLatestEcQuestion', 'makeAgoricNames', 'makeFromBoard', 'makeStargateClient', @@ -23,6 +24,7 @@ Generated by [AVA](https://avajs.dev). 'storageHelper', 'waitUntilAccountFunded', 'waitUntilContractDeployed', + 'waitUntilElectionResult', 'waitUntilInvitationReceived', 'waitUntilOfferExited', 'waitUntilOfferResult', diff --git a/packages/client-utils/test/sync-tools.test.js b/packages/client-utils/test/sync-tools.test.js index 38ee93a3d61..ce241538aa5 100644 --- a/packages/client-utils/test/sync-tools.test.js +++ b/packages/client-utils/test/sync-tools.test.js @@ -1,9 +1,7 @@ /* eslint-env node */ // @ts-check import test from 'ava'; -import '@endo/init/debug.js'; -import { makeMarshal } from '@endo/marshal'; -import { Far } from '@endo/far'; +import { makeMarshal, Far } from '@endo/marshal'; import { waitUntilAccountFunded, waitUntilContractDeployed, @@ -82,6 +80,7 @@ const makeFakeBalanceQuery = () => { test.serial('wait until contract is deployed', async t => { const { setValue, follow } = makeFakeFollow(); + setValue([['arbitrary', true]]); const waitP = waitUntilContractDeployed( 'name', { @@ -476,12 +475,13 @@ test.serial('wait election result: question handle is adhered', async t => { { follow: followByPath, marshaller, + log: console.log, + setTimeout, }, { errorMessage: 'Oops, election did not turn out as expected', maxRetries: 3, - retryIntervalMs: 500, - log: console.log, + retryIntervalMs, }, ); @@ -494,12 +494,13 @@ test.serial('wait election result: question handle is adhered', async t => { { follow: followByPath, marshaller, + log: console.log, + setTimeout, }, { errorMessage: 'Oops, election did not turn out as expected', maxRetries: 5, - retryIntervalMs: 1000, - log: console.log, + retryIntervalMs, }, ); @@ -508,7 +509,7 @@ test.serial('wait election result: question handle is adhered', async t => { ...initState, latestOutcome: { outcome: 'win', question: newQuestionHandle }, }); - setTimeout(() => setValue(updatedState), 2000); + setTimeout(() => setValue(updatedState), DEFAULT_TIMEOUT); await t.notThrowsAsync(waitHappyP); }); @@ -532,12 +533,13 @@ test.serial('wait election result: deadline is adhered', async t => { { follow: followByPath, marshaller, + log: console.log, + setTimeout, }, { errorMessage: 'Oops, election did not turn out as expected', maxRetries: 3, - retryIntervalMs: 500, - log: console.log, + retryIntervalMs, }, ); @@ -550,12 +552,13 @@ test.serial('wait election result: deadline is adhered', async t => { { follow: followByPath, marshaller, + log: console.log, + setTimeout, }, { errorMessage: 'Oops, election did not turn out as expected', maxRetries: 5, - retryIntervalMs: 1000, - log: console.log, + retryIntervalMs, }, ); @@ -567,7 +570,7 @@ test.serial('wait election result: deadline is adhered', async t => { questionHandle, }, }); - setTimeout(() => setValue(updatedState), 2000); + setTimeout(() => setValue(updatedState), DEFAULT_TIMEOUT); await t.notThrowsAsync(waitHappyP); }); @@ -591,12 +594,13 @@ test.serial('wait election result: outcome is adhered', async t => { { follow: followByPath, marshaller, + log: console.log, + setTimeout, }, { errorMessage: 'Oops, election did not turn out as expected', maxRetries: 3, - retryIntervalMs: 500, - log: console.log, + retryIntervalMs, }, ); @@ -609,12 +613,13 @@ test.serial('wait election result: outcome is adhered', async t => { { follow: followByPath, marshaller, + log: console.log, + setTimeout, }, { errorMessage: 'Oops, election did not turn out as expected', maxRetries: 5, - retryIntervalMs: 1000, - log: console.log, + retryIntervalMs, }, ); @@ -623,7 +628,7 @@ test.serial('wait election result: outcome is adhered', async t => { ...initState, latestOutcome: { outcome: 'win', question: questionHandle }, }); - setTimeout(() => setValue(updatedState), 2000); + setTimeout(() => setValue(updatedState), DEFAULT_TIMEOUT); await t.notThrowsAsync(waitHappyP); }); From d560d723cb7b10c451d0a8505f8818dc7a921543 Mon Sep 17 00:00:00 2001 From: anilhelvaci Date: Wed, 13 Nov 2024 20:59:09 +0300 Subject: [PATCH 3/3] chore(sync-tools): stop exporting fetchLatestEcQuestion Refs: https://github.com/Agoric/agoric-sdk/issues/10378 fix: rebase cleanup --- packages/client-utils/src/sync-tools.js | 27 +++-- .../test/snapshots/exports.test.js.md | 1 - .../test/snapshots/exports.test.js.snap | Bin 472 -> 489 bytes packages/client-utils/test/sync-tools.test.js | 96 +++++++----------- 4 files changed, 51 insertions(+), 73 deletions(-) diff --git a/packages/client-utils/src/sync-tools.js b/packages/client-utils/src/sync-tools.js index 1f02d62a153..84e4b3b9b23 100644 --- a/packages/client-utils/src/sync-tools.js +++ b/packages/client-utils/src/sync-tools.js @@ -326,7 +326,8 @@ export const waitUntilOfferExited = async (addr, offerId, io, options) => { ); }; -/// ////////// Make sure an election held by a given committee (see @agoric/governance) turned out as expected ///////////// +/// ////////// Make sure an election held by a given committee ////////// +/// ////////// (see @agoric/governance) turned out as expected ////////// /** * @typedef {{ @@ -343,20 +344,19 @@ export const waitUntilOfferExited = async (addr, offerId, io, options) => { /** * @param {string} basePath - * @param {{follow: (...params: string[]) => Promise; marshaller: import("@endo/marshal").Marshal}} io + * @param {import('./vstorage-kit').VstorageKit} vstorage * @returns {Promise} */ -export const fetchLatestEcQuestion = async (basePath, io) => { - const { follow, marshaller } = io; - const pathOutcome = `:${basePath}.latestOutcome`; - const pathQuestion = `:${basePath}.latestQuestion`; +const fetchLatestEcQuestion = async (basePath, vstorage) => { + const pathOutcome = `${basePath}.latestOutcome`; + const pathQuestion = `${basePath}.latestQuestion`; const [latestOutcome, latestQuestion] = await Promise.all([ - follow('-lF', pathOutcome, '-o', 'text').then(outcomeRaw => - marshaller.fromCapData(JSON.parse(outcomeRaw)), + /** @type {Promise} */ ( + vstorage.readLatestHead(pathOutcome) ), - follow('-lF', pathQuestion, '-o', 'text').then(questionRaw => - marshaller.fromCapData(JSON.parse(questionRaw)), + /** @type {Promise} */ ( + vstorage.readLatestHead(pathQuestion) ), ]); @@ -397,8 +397,7 @@ const checkCommitteeElectionResult = (electionResult, expectedResult) => { * deadline: bigint; * }} expectedResult * @param {{ - * follow: (...params: string[]) => Promise; - * marshaller: import("@endo/marshal").Marshal, + * vstorage: import('./vstorage-kit').VstorageKit; * log: typeof console.log, * setTimeout: typeof global.setTimeout * }} io @@ -410,13 +409,13 @@ export const waitUntilElectionResult = ( io, options, ) => { - const { follow, marshaller, log, setTimeout } = io; + const { vstorage, log, setTimeout } = io; const { maxRetries, retryIntervalMs, errorMessage } = overrideDefaultOptions(options); return retryUntilCondition( - () => fetchLatestEcQuestion(committeePathBase, { follow, marshaller }), + () => fetchLatestEcQuestion(committeePathBase, vstorage), electionResult => checkCommitteeElectionResult(electionResult, expectedResult), errorMessage, diff --git a/packages/client-utils/test/snapshots/exports.test.js.md b/packages/client-utils/test/snapshots/exports.test.js.md index 4b08b118a85..7ff15cea05e 100644 --- a/packages/client-utils/test/snapshots/exports.test.js.md +++ b/packages/client-utils/test/snapshots/exports.test.js.md @@ -10,7 +10,6 @@ Generated by [AVA](https://avajs.dev). [ 'boardSlottingMarshaller', - 'fetchLatestEcQuestion', 'makeAgoricNames', 'makeFromBoard', 'makeStargateClient', diff --git a/packages/client-utils/test/snapshots/exports.test.js.snap b/packages/client-utils/test/snapshots/exports.test.js.snap index 6d65d812692c36b4fdfedccf522d6ba2aafec158..f995fc8c424bd77a5bd2e4529824dcf8f0a565a6 100644 GIT binary patch literal 489 zcmV7&4$mT$e$G|o#VGt8wpAsc4k zcw$VTjUS5$00000000AZ(Xnn5K@bMuf7Un&!QpTm1tH!5N_YWd90egjiW4Ks&E42p zdA)nu8=JU7X?X~wP*Ly>JOK?4K*d8)Mu)R|a=}%r`@fr=nY*5xTc6LWtFJ6ZEVFS1 zUz*D4vbyk6U0oN27X3l}ZDAYrLp#(f0W1N00q_IBZvcvbCj=Z5Uo3iz&oUkd2aR+rlS5cG;Dp0X?h?Sl3}9rQ@yfLfq-mmZ#b9g30lBF0VM z=ull~YdPFHq6o9Oo^gNbgUR3OIad*=2=;1l6#V=}T`|V381L8dNOYKL;ej>mB$_+X z9MDtkCYBwH<4|>Wm-P-7MT&>gBCVjrW0p8bR%9$9OM%hXAOOwxr zt|+}}ZoeDTUSJ8UGbhFlyeo_t?;_fbs9jm+GQPf-mUP?JG260Pawjd|qc-xdazD@g z!pYIX6`Yp27u}=e2Hr`~xxD1k`c*^kryrc?&~je)dcxJhrm?aJA1CS8oC1pudfe?3i0C<6rwgMqQN@x*BcXyJG z;@B(iq-{>97aoFJ5j+J?fOrE=JPDwM+N&J!$@2esJf5rRiS@<2zWl^0YMI5Ad?B?n zRekEUzPu_+qvl=qy@O3Oi?(Rj0tf&;0{9Bx2Y_Dy9ulxm02AJCFNE26l|^BlAd>VtY1P=-C~fVzFUcj8SbC)TTqo4qulJ~h^I zxOPMl<_k0D;mijqUYP~g5o8hUG~h7!#nYx@j5{&jZQ_ZVFf+;{E9^9y8`0ct%o}zk zhlMzO{AAsAqw6*9c%nX-8OL;Et<&TBU;0AQ_02W#w)v(Wso3^28cd=4Tv@+r>Fr1#B>LQ)iJGR{F&8XnEzTp}OZfG4%HiNbv{iThqsCk> Ot^NVs@fE4{0ssKW58UDa diff --git a/packages/client-utils/test/sync-tools.test.js b/packages/client-utils/test/sync-tools.test.js index ce241538aa5..4ad93a84016 100644 --- a/packages/client-utils/test/sync-tools.test.js +++ b/packages/client-utils/test/sync-tools.test.js @@ -1,7 +1,7 @@ /* eslint-env node */ // @ts-check import test from 'ava'; -import { makeMarshal, Far } from '@endo/marshal'; +import { Far } from '@endo/marshal'; import { waitUntilAccountFunded, waitUntilContractDeployed, @@ -15,43 +15,23 @@ import { const retryIntervalMs = 10; const DEFAULT_TIMEOUT = 30; -const makeSimpleMarshaller = () => { - const vals = []; - const fromVal = val => { - vals.push(val); - return vals.length - 1; - }; - const toVal = slot => vals[slot]; - return makeMarshal(fromVal, toVal, { - serializeBodyFormat: 'smallcaps', - marshalSaveError: err => { - throw err; - }, - }); -}; -harden(makeSimpleMarshaller); - -const makeFakeFollow = () => { - const marshaller = makeSimpleMarshaller(); +const makeFakeVstorageKit = () => { let value; const setValue = newValue => (value = newValue); + // TODO remove this when we switch all sync-tools to use client-utils's vstorageKit const follow = () => Promise.resolve(value); /** - * - * @param {any} _ * @param {string} path Assumes the path will be something like 'published.auction.book0' * where value = { book0: {...} } */ - const followByPath = (_, path) => { - const propName = path.split('.').at(-1); - return Promise.resolve( - // @ts-expect-error path will be a sequence of strings joined by "." - JSON.stringify(marshaller.toCapData(value[propName])), - ); + const readLatestHead = path => { + const key = path.split('.').at(-1); + // @ts-expect-error path will be a string joined by "." + return Promise.resolve(value[key]); }; - return { setValue, follow, followByPath, marshaller }; + return { setValue, follow, readLatestHead }; }; const makeFakeBalanceQuery = () => { @@ -79,7 +59,7 @@ const makeFakeBalanceQuery = () => { }; test.serial('wait until contract is deployed', async t => { - const { setValue, follow } = makeFakeFollow(); + const { setValue, follow } = makeFakeVstorageKit(); setValue([['arbitrary', true]]); const waitP = waitUntilContractDeployed( 'name', @@ -179,7 +159,7 @@ test.serial('wait until account funded, insufficient balance', async t => { test.serial( 'wait until offer result, balance update - should throw', async t => { - const { setValue, follow } = makeFakeFollow(); + const { setValue, follow } = makeFakeVstorageKit(); setValue({ status: {}, updated: 'balance' }); const waitP = waitUntilOfferResult( @@ -199,7 +179,7 @@ test.serial( ); test.serial('wait until offer result, wrong id - should throw', async t => { - const { setValue, follow } = makeFakeFollow(); + const { setValue, follow } = makeFakeVstorageKit(); setValue({ status: { id: 'your-offer' }, updated: 'offerStatus' }); const waitP = waitUntilOfferResult( @@ -218,7 +198,7 @@ test.serial('wait until offer result, wrong id - should throw', async t => { }); test.serial('wait until offer result, no "status" - should throw', async t => { - const { setValue, follow } = makeFakeFollow(); + const { setValue, follow } = makeFakeVstorageKit(); setValue({ updated: 'offerStatus' }); const waitP = waitUntilOfferResult( @@ -239,7 +219,7 @@ test.serial('wait until offer result, no "status" - should throw', async t => { test.serial( 'wait until offer result, numWantsSatisfied not equals to 1 - should throw', async t => { - const { setValue, follow } = makeFakeFollow(); + const { setValue, follow } = makeFakeVstorageKit(); setValue({ status: { id: 'my-offer', numWantsSatisfied: 0 }, updated: 'offerStatus', @@ -262,7 +242,7 @@ test.serial( ); test.serial('wait until offer result, do not wait for "payouts"', async t => { - const { setValue, follow } = makeFakeFollow(); + const { setValue, follow } = makeFakeVstorageKit(); setValue({ status: { id: 'my-offer' }, updated: 'offerStatus' }); const waitP = waitUntilOfferResult( @@ -298,7 +278,7 @@ test.serial('wait until offer result, do not wait for "payouts"', async t => { }); test.serial('wait until offer result, wait for "payouts"', async t => { - const { setValue, follow } = makeFakeFollow(); + const { setValue, follow } = makeFakeVstorageKit(); setValue({ status: { id: 'my-offer' }, updated: 'offerStatus' }); const waitP = waitUntilOfferResult( @@ -349,7 +329,7 @@ test.serial('wait until offer result, wait for "payouts"', async t => { test.serial( 'wait until invitation recevied, wrong "updated" value', async t => { - const { setValue, follow } = makeFakeFollow(); + const { setValue, follow } = makeFakeVstorageKit(); setValue({ updated: 'offerStatus' }); const waitP = waitUntilInvitationReceived( @@ -369,7 +349,7 @@ test.serial( test.serial( 'wait until invitation recevied, falty "currentAmount" object', async t => { - const { setValue, follow } = makeFakeFollow(); + const { setValue, follow } = makeFakeVstorageKit(); setValue({ updated: 'balance' }); const waitP = waitUntilInvitationReceived( @@ -394,7 +374,7 @@ test.serial( test.serial( 'wait until invitation recevied, brand string do not match', async t => { - const { setValue, follow } = makeFakeFollow(); + const { setValue, follow } = makeFakeVstorageKit(); setValue({ updated: 'balance', currentAmount: { brand: 'foo bar foo' } }); const waitP = waitUntilInvitationReceived( @@ -412,7 +392,7 @@ test.serial( ); test.serial('wait until invitation recevied', async t => { - const { setValue, follow } = makeFakeFollow(); + const { setValue, follow } = makeFakeVstorageKit(); setValue({}); const waitP = waitUntilInvitationReceived( @@ -438,7 +418,7 @@ test.serial('wait until invitation recevied', async t => { }); test.serial('wait until offer exited', async t => { - const { setValue, follow } = makeFakeFollow(); + const { setValue, follow } = makeFakeVstorageKit(); setValue({}); const waitP = waitUntilOfferExited( @@ -455,11 +435,11 @@ test.serial('wait until offer exited', async t => { await t.throwsAsync(waitP); }); -test.serial('wait election result: question handle is adhered', async t => { +test.serial('wait election result: question handle is respected', async t => { const oldQuestionHandle = Far('Question 1', {}); const newQuestionHandle = Far('Question 2', {}); - const { setValue, followByPath, marshaller } = makeFakeFollow(); + const { setValue, readLatestHead } = makeFakeVstorageKit(); const initState = harden({ latestOutcome: { outcome: 'win', question: oldQuestionHandle }, latestQuestion: { @@ -473,8 +453,8 @@ test.serial('wait election result: question handle is adhered', async t => { 'dummyPath', { outcome: 'win', deadline: 2n }, { - follow: followByPath, - marshaller, + // @ts-expect-error casting + vstorage: { readLatestHead }, log: console.log, setTimeout, }, @@ -492,8 +472,8 @@ test.serial('wait election result: question handle is adhered', async t => { 'dummyPath', { outcome: 'win', deadline: 2n }, { - follow: followByPath, - marshaller, + // @ts-expect-error casting + vstorage: { readLatestHead }, log: console.log, setTimeout, }, @@ -514,10 +494,10 @@ test.serial('wait election result: question handle is adhered', async t => { await t.notThrowsAsync(waitHappyP); }); -test.serial('wait election result: deadline is adhered', async t => { +test.serial('wait election result: deadline is respected', async t => { const questionHandle = Far('Question', {}); - const { setValue, followByPath, marshaller } = makeFakeFollow(); + const { setValue, readLatestHead } = makeFakeVstorageKit(); const initState = harden({ latestOutcome: { outcome: 'win', question: questionHandle }, latestQuestion: { @@ -531,8 +511,8 @@ test.serial('wait election result: deadline is adhered', async t => { 'dummyPath', { outcome: 'win', deadline: 5n }, { - follow: followByPath, - marshaller, + // @ts-expect-error casting + vstorage: { readLatestHead }, log: console.log, setTimeout, }, @@ -550,8 +530,8 @@ test.serial('wait election result: deadline is adhered', async t => { 'dummyPath', { outcome: 'win', deadline: 5n }, { - follow: followByPath, - marshaller, + // @ts-expect-error casting + vstorage: { readLatestHead }, log: console.log, setTimeout, }, @@ -575,10 +555,10 @@ test.serial('wait election result: deadline is adhered', async t => { await t.notThrowsAsync(waitHappyP); }); -test.serial('wait election result: outcome is adhered', async t => { +test.serial('wait election result: outcome is respected', async t => { const questionHandle = Far('Question', {}); - const { setValue, followByPath, marshaller } = makeFakeFollow(); + const { setValue, readLatestHead } = makeFakeVstorageKit(); const initState = harden({ latestOutcome: { outcome: 'lose', question: questionHandle }, latestQuestion: { @@ -592,8 +572,8 @@ test.serial('wait election result: outcome is adhered', async t => { 'dummyPath', { outcome: 'win', deadline: 5n }, { - follow: followByPath, - marshaller, + // @ts-expect-error casting + vstorage: { readLatestHead }, log: console.log, setTimeout, }, @@ -611,8 +591,8 @@ test.serial('wait election result: outcome is adhered', async t => { 'dummyPath', { outcome: 'win', deadline: 5n }, { - follow: followByPath, - marshaller, + // @ts-expect-error casting + vstorage: { readLatestHead }, log: console.log, setTimeout, },