diff --git a/packages/boot/test/bootstrapTests/orchestration.test.ts b/packages/boot/test/bootstrapTests/orchestration.test.ts index 4a9c85b9cdb6..ca10df7537f2 100644 --- a/packages/boot/test/bootstrapTests/orchestration.test.ts +++ b/packages/boot/test/bootstrapTests/orchestration.test.ts @@ -241,6 +241,7 @@ test('kitchen-sink', async t => { const wd = await t.context.walletFactoryDriver.provideSmartWallet('agoric1test'); + // create a cosmos orchestration account await wd.executeOffer({ id: 'request-coa', invitationSpec: { @@ -258,9 +259,7 @@ test('kitchen-sink', async t => { [ 'request-coa', { - // FIXME in this PR - account: { payload: { vowV0: { vowV0: undefined } } }, - // account: 'published.kitchenSink.cosmos1test', + account: 'published.kitchenSink.cosmos1test', }, ], ], @@ -268,7 +267,27 @@ test('kitchen-sink', async t => { t.like(wd.getLatestUpdateRecord(), { status: { id: 'request-coa', numWantsSatisfied: 1 }, }); - t.is(readLatest('published.kitchenSink'), ''); - // FIXME in this PR - t.not(readLatest('published.kitchenSink.cosmos1test'), ''); + t.is(readLatest('published.kitchenSink.cosmos1test'), ''); + + // create a local orchestration account + await wd.executeOffer({ + id: 'request-loa', + invitationSpec: { + source: 'agoricContract', + instancePath: ['kitchenSink'], + callPipe: [['makeLocalOrchAcctInvitation']], + }, + proposal: {}, + }); + + const publicSubscriberPaths = Object.fromEntries( + wd.getCurrentWalletRecord().offerToPublicSubscriberPaths, + ); + t.deepEqual(publicSubscriberPaths['request-loa'], { + account: 'published.kitchenSink.agoric1mockVlocalchainAddress', + }); + t.like(wd.getLatestUpdateRecord(), { + status: { id: 'request-loa', numWantsSatisfied: 1 }, + }); + t.is(readLatest('published.kitchenSink.agoric1mockVlocalchainAddress'), ''); }); diff --git a/packages/orchestration/src/exos/cosmos-orchestration-account.js b/packages/orchestration/src/exos/cosmos-orchestration-account.js index 7ee95f003cb9..fb003419ed11 100644 --- a/packages/orchestration/src/exos/cosmos-orchestration-account.js +++ b/packages/orchestration/src/exos/cosmos-orchestration-account.js @@ -22,7 +22,6 @@ import { makeTracer } from '@agoric/internal'; import { Shape as NetworkShape } from '@agoric/network'; import { M } from '@agoric/vat-data'; import { VowShape } from '@agoric/vow'; -import { TopicsRecordShape } from '@agoric/zoe/src/contractSupport/index.js'; import { AmountArgShape, ChainAddressShape, @@ -69,7 +68,6 @@ const { Vow$ } = NetworkShape; // TODO #9611 /** @see {OrchestrationAccountI} */ export const IcaAccountHolderI = M.interface('IcaAccountHolder', { ...orchestrationAccountMethods, - getPublicTopics: M.call().returns(TopicsRecordShape), delegate: M.call(ChainAddressShape, AmountArgShape).returns(VowShape), redelegate: M.call( ChainAddressShape, @@ -100,7 +98,7 @@ const toDenomAmount = c => ({ denom: c.denom, value: BigInt(c.amount) }); export const prepareCosmosOrchestrationAccountKit = ( zone, makeRecorderKit, - { watch, asVow }, + { watch, asVow, when }, zcf, ) => { const makeCosmosOrchestrationAccountKit = zone.exoClassKit( @@ -313,21 +311,31 @@ export const prepareCosmosOrchestrationAccountKit = ( }, holder: { asContinuingOffer() { - const { holder, invitationMakers } = this.facets; - return harden({ - publicSubscribers: holder.getPublicTopics(), - invitationMakers, - holder, + // getStoragePath resolves promptly (same run), so we don't need a watcher + // eslint-disable-next-line no-restricted-syntax + return asVow(async () => { + const { holder, invitationMakers } = this.facets; + return harden({ + // eslint-disable-next-line @jessie.js/safe-await-separator + publicSubscribers: await when(holder.getPublicTopics()), + invitationMakers, + holder, + }); }); }, getPublicTopics() { - const { topicKit } = this.state; - return harden({ - account: { - description: PUBLIC_TOPICS.account[0], - subscriber: topicKit.subscriber, - storagePath: topicKit.recorder.getStoragePath(), - }, + // getStoragePath resolves promptly (same run), so we don't need a watcher + // eslint-disable-next-line no-restricted-syntax + return asVow(async () => { + const { topicKit } = this.state; + return harden({ + account: { + description: PUBLIC_TOPICS.account[0], + subscriber: topicKit.subscriber, + // eslint-disable-next-line @jessie.js/safe-await-separator + storagePath: await topicKit.recorder.getStoragePath(), + }, + }); }); }, diff --git a/packages/orchestration/src/exos/local-orchestration-account.js b/packages/orchestration/src/exos/local-orchestration-account.js index 744db9cb2e29..b051ba2bdb3a 100644 --- a/packages/orchestration/src/exos/local-orchestration-account.js +++ b/packages/orchestration/src/exos/local-orchestration-account.js @@ -5,7 +5,6 @@ import { makeTracer } from '@agoric/internal'; import { Shape as NetworkShape } from '@agoric/network'; import { M } from '@agoric/vat-data'; import { VowShape } from '@agoric/vow'; -import { TopicsRecordShape } from '@agoric/zoe/src/contractSupport/index.js'; import { E } from '@endo/far'; import { ChainAddressShape, @@ -51,7 +50,6 @@ const { Vow$ } = NetworkShape; // TODO #9611 const HolderI = M.interface('holder', { ...orchestrationAccountMethods, - getPublicTopics: M.call().returns(TopicsRecordShape), delegate: M.call(M.string(), AmountShape).returns(VowShape), undelegate: M.call(M.string(), AmountShape).returns(VowShape), deposit: M.call(PaymentShape).returns(VowShape), @@ -77,7 +75,7 @@ export const prepareLocalOrchestrationAccountKit = ( makeRecorderKit, zcf, timerService, - { watch, allVows, asVow }, + { watch, allVows, asVow, when }, chainHub, ) => { const timestampHelper = makeTimestampHelper(timerService); @@ -291,11 +289,16 @@ export const prepareLocalOrchestrationAccountKit = ( }, holder: { asContinuingOffer() { - const { holder, invitationMakers } = this.facets; - return harden({ - publicSubscribers: holder.getPublicTopics(), - invitationMakers, - holder, + // getStoragePath resolves promptly (same run), so we don't need a watcher + // eslint-disable-next-line no-restricted-syntax + return asVow(async () => { + const { holder, invitationMakers } = this.facets; + return harden({ + // eslint-disable-next-line @jessie.js/safe-await-separator + publicSubscribers: await when(holder.getPublicTopics()), + invitationMakers, + holder, + }); }); }, /** @@ -322,13 +325,18 @@ export const prepareLocalOrchestrationAccountKit = ( return asVow(() => Fail`not yet implemented`); }, getPublicTopics() { - const { topicKit } = this.state; - return harden({ - account: { - description: PUBLIC_TOPICS.account[0], - subscriber: topicKit.subscriber, - storagePath: topicKit.recorder.getStoragePath(), - }, + // getStoragePath resolves promptly (same run), so we don't need a watcher + // eslint-disable-next-line no-restricted-syntax + return asVow(async () => { + const { topicKit } = this.state; + return harden({ + account: { + description: PUBLIC_TOPICS.account[0], + subscriber: topicKit.subscriber, + // eslint-disable-next-line @jessie.js/safe-await-separator + storagePath: await topicKit.recorder.getStoragePath(), + }, + }); }); }, /** diff --git a/packages/orchestration/src/utils/orchestrationAccount.js b/packages/orchestration/src/utils/orchestrationAccount.js index 6e120e0a2eeb..67045a591144 100644 --- a/packages/orchestration/src/utils/orchestrationAccount.js +++ b/packages/orchestration/src/utils/orchestrationAccount.js @@ -18,9 +18,12 @@ export const orchestrationAccountMethods = { .optional(M.record()) .returns(VowShape), transferSteps: M.call(AmountArgShape, M.any()).returns(VowShape), - asContinuingOffer: M.call().returns({ - publicSubscribers: TopicsRecordShape, - invitationMakers: M.any(), - holder: M.remotable(), - }), + asContinuingOffer: M.call().returns( + Vow$({ + publicSubscribers: TopicsRecordShape, + invitationMakers: M.any(), + holder: M.remotable(), + }), + ), + getPublicTopics: M.call().returns(Vow$(TopicsRecordShape)), }; diff --git a/packages/orchestration/test/examples/kitchen-sink.contract.test.ts b/packages/orchestration/test/examples/kitchen-sink.contract.test.ts index d38d13850b38..18d1d718b92f 100644 --- a/packages/orchestration/test/examples/kitchen-sink.contract.test.ts +++ b/packages/orchestration/test/examples/kitchen-sink.contract.test.ts @@ -45,10 +45,10 @@ test('orchestrate - LocalOrchAccount returns a ContinuingOfferResult', async t = getInterfaceOf(invitationMakers)!, /Local Orchestration (.*) invitationMakers/, ); + t.log('publicSubscribers', publicSubscribers); const { description, storagePath, subscriber } = publicSubscribers.account; t.regex(description, /Account holder/); - // FIXME in this PR, currently a vow - t.is(getInterfaceOf(storagePath), undefined); + t.is(storagePath, 'mockChainStorageRoot.kitchen-sink.agoric1fakeLCAAddress'); t.regex(getInterfaceOf(subscriber)!, /Durable Publish Kit subscriber/); }); @@ -88,7 +88,6 @@ test('orchestrate - CosmosOrchAccount returns a ContinuingOfferResult', async t ); const { description, storagePath, subscriber } = publicSubscribers.account; t.regex(description, /Account holder/); - // FIXME in this PR, currently a vow - t.is(getInterfaceOf(storagePath), undefined); + t.is(storagePath, 'mockChainStorageRoot.kitchen-sink.cosmos1test'); t.regex(getInterfaceOf(subscriber)!, /Durable Publish Kit subscriber/); }); diff --git a/packages/orchestration/test/staking-ops.test.ts b/packages/orchestration/test/staking-ops.test.ts index 9cea5c578251..0a975f4e290a 100644 --- a/packages/orchestration/test/staking-ops.test.ts +++ b/packages/orchestration/test/staking-ops.test.ts @@ -237,7 +237,7 @@ test('makeAccount() writes to storage', async t => { icqConnection, timer, }); - const { publicSubscribers } = holder.asContinuingOffer(); + const { publicSubscribers } = await E.when(holder.asContinuingOffer()); const accountNotifier = makeNotifierFromSubscriber( publicSubscribers.account.subscriber, );