diff --git a/packages/orchestration/src/exos/local-chain-facade.js b/packages/orchestration/src/exos/local-chain-facade.js index ddada8f15f4..357ebcb3120 100644 --- a/packages/orchestration/src/exos/local-chain-facade.js +++ b/packages/orchestration/src/exos/local-chain-facade.js @@ -2,6 +2,7 @@ import { E } from '@endo/far'; import { M } from '@endo/patterns'; import { pickFacet } from '@agoric/vat-data'; +import { VowShape } from '@agoric/vow'; import { ChainFacadeI } from '../typeGuards.js'; @@ -36,6 +37,8 @@ const prepareLocalChainFacadeKit = ( { makeLocalOrchestrationAccountKit, localchain, + // TODO vstorage design https://github.com/Agoric/agoric-sdk/issues/9066 + // consider making an `accounts` childNode storageNode, vowTools: { allVows, watch }, }, @@ -44,9 +47,14 @@ const prepareLocalChainFacadeKit = ( 'LocalChainFacade', { public: ChainFacadeI, - makeAccountWatcher: M.interface('undelegateWatcher', { + makeAccountWatcher: M.interface('makeAccountWatcher', { onFulfilled: M.call([M.remotable('LCA Account'), M.string()]) .optional(M.arrayOf(M.undefined())) // empty context + .returns(VowShape), + }), + makeChildNodeWatcher: M.interface('makeChildNodeWatcher', { + onFulfilled: M.call(M.remotable()) + .optional({ account: M.remotable(), address: M.string() }) // empty context .returns(M.remotable()), }), }, @@ -82,6 +90,22 @@ const prepareLocalChainFacadeKit = ( * @param {[LocalChainAccount, ChainAddress['value']]} results */ onFulfilled([account, address]) { + return watch( + E(storageNode).makeChildNode(address), + this.facets.makeChildNodeWatcher, + { account, address }, + ); + }, + }, + makeChildNodeWatcher: { + /** + * @param {Remote} childNode + * @param {{ + * account: LocalChainAccount; + * address: ChainAddress['value']; + * }} ctx + */ + onFulfilled(childNode, { account, address }) { const { localChainInfo } = this.state; const { holder } = makeLocalOrchestrationAccountKit({ account, @@ -91,7 +115,7 @@ const prepareLocalChainFacadeKit = ( chainId: localChainInfo.chainId, }), // FIXME storage path https://github.com/Agoric/agoric-sdk/issues/9066 - storageNode, + storageNode: childNode, }); return holder; }, diff --git a/packages/orchestration/src/exos/local-orchestration-account.js b/packages/orchestration/src/exos/local-orchestration-account.js index 52c95c9580d..7ff8966fcf1 100644 --- a/packages/orchestration/src/exos/local-orchestration-account.js +++ b/packages/orchestration/src/exos/local-orchestration-account.js @@ -140,6 +140,8 @@ export const prepareLocalOrchestrationAccountKit = ( // must be the fully synchronous maker because the kit is held in durable state // @ts-expect-error XXX Patterns const topicKit = makeRecorderKit(storageNode, PUBLIC_TOPICS.account[1]); + // TODO determine what goes in vstorage https://github.com/Agoric/agoric-sdk/issues/9066 + void E(topicKit.recorder).write(''); return { account, address, topicKit }; }, diff --git a/packages/orchestration/src/exos/remote-chain-facade.js b/packages/orchestration/src/exos/remote-chain-facade.js index 3b87240c39d..762d23c8f61 100644 --- a/packages/orchestration/src/exos/remote-chain-facade.js +++ b/packages/orchestration/src/exos/remote-chain-facade.js @@ -4,7 +4,7 @@ import { E } from '@endo/far'; import { M } from '@endo/patterns'; import { pickFacet } from '@agoric/vat-data'; import { VowShape } from '@agoric/vow'; -import { ChainFacadeI } from '../typeGuards.js'; +import { ChainAddressShape, ChainFacadeI } from '../typeGuards.js'; /** * @import {Zone} from '@agoric/base-zone'; @@ -43,6 +43,8 @@ const prepareRemoteChainFacadeKit = ( { makeCosmosOrchestrationAccount, orchestration, + // TODO vstorage design https://github.com/Agoric/agoric-sdk/issues/9066 + // consider making an `accounts` childNode storageNode, timer, vowTools: { asVow, watch }, @@ -54,12 +56,20 @@ const prepareRemoteChainFacadeKit = ( public: ChainFacadeI, makeAccountWatcher: M.interface('makeAccountWatcher', { onFulfilled: M.call(M.remotable()) - .optional(M.string()) + .optional(M.arrayOf(M.undefined())) // empty context .returns(VowShape), }), - getAddressWatcher: M.interface('makeAccountWatcher', { + getAddressWatcher: M.interface('getAddressWatcher', { onFulfilled: M.call(M.record()) - .optional({ stakingDenom: M.string(), account: M.remotable() }) + .optional(M.remotable()) + .returns(VowShape), + }), + makeChildNodeWatcher: M.interface('makeChildNodeWatcher', { + onFulfilled: M.call(M.remotable()) + .optional({ + account: M.remotable(), + chainAddress: ChainAddressShape, + }) .returns(M.remotable()), }), }, @@ -95,32 +105,55 @@ const prepareRemoteChainFacadeKit = ( connectionInfo.counterparty.connection_id, ), this.facets.makeAccountWatcher, - stakingDenom, ); }); }, }, makeAccountWatcher: { /** + * XXX Pipeline vows allVows and E + * * @param {IcaAccount} account - * @param {Denom} stakingDenom */ - onFulfilled(account, stakingDenom) { - return watch(E(account).getAddress(), this.facets.getAddressWatcher, { - stakingDenom, + onFulfilled(account) { + return watch( + E(account).getAddress(), + this.facets.getAddressWatcher, account, - }); + ); }, }, getAddressWatcher: { /** * @param {ChainAddress} chainAddress - * @param {{ stakingDenom: Denom; account: IcaAccount }} ctx + * @param {IcaAccount} account + */ + onFulfilled(chainAddress, account) { + return watch( + E(storageNode).makeChildNode(chainAddress.value), + this.facets.makeChildNodeWatcher, + { account, chainAddress }, + ); + }, + }, + makeChildNodeWatcher: { + /** + * @param {Remote} childNode + * @param {{ + * account: IcaAccount; + * chainAddress: ChainAddress; + * }} ctx */ - onFulfilled(chainAddress, { account, stakingDenom }) { + onFulfilled(childNode, { account, chainAddress }) { + const { remoteChainInfo } = this.state; + const stakingDenom = remoteChainInfo.stakingTokens?.[0]?.denom; + if (!stakingDenom) { + throw Fail`chain info lacks staking denom`; + } return makeCosmosOrchestrationAccount(chainAddress, stakingDenom, { account, - storageNode, + // FIXME storage path https://github.com/Agoric/agoric-sdk/issues/9066 + storageNode: childNode, // FIXME provide real ICQ connection // FIXME make Query Connection available via chain, not orchestrationAccount icqConnection: anyVal,