From 0928b56d62c0c31203624cc72354ffa87c8faa14 Mon Sep 17 00:00:00 2001 From: 0xPatrick Date: Wed, 7 Aug 2024 10:33:21 -0400 Subject: [PATCH] feat: publish local and remote ibc addresses to vstorage - publishes remoteAddress (RemoteIBCAddress) and localAddress (LocalIBCAddress) to vstorage for CosmosOrchestrationAccount - goal is to faciliate off-chain clients, which need portId, connectionId, and channelId for the host and controller to perform queries - a better design might publish these values individually, versus putting the burden of parsing on the client - refs: #9066 --- .../test/bootstrapTests/orchestration.test.ts | 21 +++- .../orchestration/restart-contracts.test.ts | 7 +- .../src/examples/stakeIca.contract.js | 25 ++-- .../src/exos/cosmos-orchestration-account.js | 24 +++- .../orchestration/src/exos/ica-account-kit.js | 3 + .../src/exos/remote-chain-facade.js | 73 ++++++----- .../snapshots/stake-ica.contract.test.ts.md | 6 +- .../snapshots/stake-ica.contract.test.ts.snap | Bin 404 -> 638 bytes .../test/examples/stake-ica.contract.test.ts | 14 ++- .../test/exos/make-test-coa-kit.ts | 21 ++-- .../orchestration/test/staking-ops.test.ts | 114 +++++++++++++----- packages/orchestration/test/types.test-d.ts | 1 - 12 files changed, 218 insertions(+), 91 deletions(-) diff --git a/packages/boot/test/bootstrapTests/orchestration.test.ts b/packages/boot/test/bootstrapTests/orchestration.test.ts index 34100dfb7b0a..ab2c0eac0037 100644 --- a/packages/boot/test/bootstrapTests/orchestration.test.ts +++ b/packages/boot/test/bootstrapTests/orchestration.test.ts @@ -171,7 +171,12 @@ test.serial('stakeAtom - smart wallet', async t => { t.like(wd.getLatestUpdateRecord(), { status: { id: 'request-account', numWantsSatisfied: 1 }, }); - t.is(readLatest('published.stakeAtom.accounts.cosmos1test'), ''); + t.deepEqual(readLatest('published.stakeAtom.accounts.cosmos1test'), { + localAddress: + '/ibc-port/icacontroller-1/ordered/{"version":"ics27-1","controllerConnectionId":"connection-8","hostConnectionId":"connection-649","address":"cosmos1test","encoding":"proto3","txType":"sdk_multi_msg"}/ibc-channel/channel-1', + remoteAddress: + '/ibc-hop/connection-8/ibc-port/icahost/ordered/{"version":"ics27-1","controllerConnectionId":"connection-8","hostConnectionId":"connection-649","address":"cosmos1test","encoding":"proto3","txType":"sdk_multi_msg"}/ibc-channel/channel-1', + }); const { ATOM } = agoricNamesRemotes.brand; ATOM || Fail`ATOM missing from agoricNames`; @@ -297,7 +302,12 @@ test('basic-flows', async t => { t.like(wd.getLatestUpdateRecord(), { status: { id: 'request-coa', numWantsSatisfied: 1 }, }); - t.is(readLatest('published.basicFlows.cosmos1test'), ''); + t.deepEqual(readLatest('published.basicFlows.cosmos1test'), { + localAddress: + '/ibc-port/icacontroller-4/ordered/{"version":"ics27-1","controllerConnectionId":"connection-8","hostConnectionId":"connection-649","address":"cosmos1test","encoding":"proto3","txType":"sdk_multi_msg"}/ibc-channel/channel-4', + remoteAddress: + '/ibc-hop/connection-8/ibc-port/icahost/ordered/{"version":"ics27-1","controllerConnectionId":"connection-8","hostConnectionId":"connection-649","address":"cosmos1test","encoding":"proto3","txType":"sdk_multi_msg"}/ibc-channel/channel-4', + }); // create a local orchestration account await wd.executeOffer({ @@ -389,7 +399,12 @@ test.serial('basic-flows - portfolio holder', async t => { status: { id: 'request-portfolio-acct', numWantsSatisfied: 1 }, }); // XXX this overrides a previous account, since mocks only provide one address - t.is(readLatest('published.basicFlows.cosmos1test'), ''); + t.deepEqual(readLatest('published.basicFlows.cosmos1test'), { + localAddress: + '/ibc-port/icacontroller-3/ordered/{"version":"ics27-1","controllerConnectionId":"connection-1","hostConnectionId":"connection-1649","address":"cosmos1test","encoding":"proto3","txType":"sdk_multi_msg"}/ibc-channel/channel-3', + remoteAddress: + '/ibc-hop/connection-1/ibc-port/icahost/ordered/{"version":"ics27-1","controllerConnectionId":"connection-1","hostConnectionId":"connection-1649","address":"cosmos1test","encoding":"proto3","txType":"sdk_multi_msg"}/ibc-channel/channel-3', + }); // XXX this overrides a previous account, since mocks only provide one address t.is(readLatest('published.basicFlows.agoric1mockVlocalchainAddress'), ''); diff --git a/packages/boot/test/orchestration/restart-contracts.test.ts b/packages/boot/test/orchestration/restart-contracts.test.ts index 730a5f8b565f..0ccd27ef114c 100644 --- a/packages/boot/test/orchestration/restart-contracts.test.ts +++ b/packages/boot/test/orchestration/restart-contracts.test.ts @@ -140,7 +140,12 @@ test.serial('stakeAtom', async t => { const accountPath = 'published.stakeAtom.accounts.cosmos1test'; t.throws(() => readLatest(accountPath)); t.is(await flushInboundQueue(), 1); - t.is(readLatest(accountPath), ''); + t.deepEqual(readLatest(accountPath), { + localAddress: + '/ibc-port/icacontroller-4/ordered/{"version":"ics27-1","controllerConnectionId":"connection-8","hostConnectionId":"connection-649","address":"cosmos1test","encoding":"proto3","txType":"sdk_multi_msg"}/ibc-channel/channel-4', + remoteAddress: + '/ibc-hop/connection-8/ibc-port/icahost/ordered/{"version":"ics27-1","controllerConnectionId":"connection-8","hostConnectionId":"connection-649","address":"cosmos1test","encoding":"proto3","txType":"sdk_multi_msg"}/ibc-channel/channel-4', + }); // request-account is complete const { ATOM } = agoricNamesRemotes.brand; diff --git a/packages/orchestration/src/examples/stakeIca.contract.js b/packages/orchestration/src/examples/stakeIca.contract.js index 0f168f052b8d..cd13b96691a3 100644 --- a/packages/orchestration/src/examples/stakeIca.contract.js +++ b/packages/orchestration/src/examples/stakeIca.contract.js @@ -102,17 +102,24 @@ export const start = async (zcf, privateArgs, baggage) => { ? await E(orchestration).provideICQConnection(controllerConnectionId) : undefined; - const accountAddress = await E(account).getAddress(); - trace('account address', accountAddress); + const [chainAddress, localAddress, remoteAddress] = await Promise.all([ + E(account).getAddress(), + E(account).getLocalAddress(), + E(account).getRemoteAddress(), + ]); + trace('account address', chainAddress); const accountNode = await E(accountsStorageNode).makeChildNode( - accountAddress.value, + chainAddress.value, + ); + const holder = makeCosmosOrchestrationAccount( + { chainAddress, bondDenom, localAddress, remoteAddress }, + { + account, + storageNode: accountNode, + icqConnection, + timer, + }, ); - const holder = makeCosmosOrchestrationAccount(accountAddress, bondDenom, { - account, - storageNode: accountNode, - icqConnection, - timer, - }); return holder; } diff --git a/packages/orchestration/src/exos/cosmos-orchestration-account.js b/packages/orchestration/src/exos/cosmos-orchestration-account.js index 08bac4861d90..60cd5ba13801 100644 --- a/packages/orchestration/src/exos/cosmos-orchestration-account.js +++ b/packages/orchestration/src/exos/cosmos-orchestration-account.js @@ -45,6 +45,7 @@ import { orchestrationAccountMethods } from '../utils/orchestrationAccount.js'; * @import {ResponseQuery} from '@agoric/cosmic-proto/tendermint/abci/types.js'; * @import {JsonSafe} from '@agoric/cosmic-proto'; * @import {Matcher} from '@endo/patterns'; + * @import {LocalIbcAddress, RemoteIbcAddress} from '@agoric/vats/tools/ibc-utils.js'; */ const trace = makeTracer('ComosOrchestrationAccountHolder'); @@ -61,6 +62,8 @@ const { Vow$ } = NetworkShape; // TODO #9611 * topicKit: RecorderKit; * account: IcaAccount; * chainAddress: ChainAddress; + * localAddress: LocalIbcAddress; + * remoteAddress: RemoteIbcAddress; * icqConnection: ICQConnection | undefined; * bondDenom: string; * timer: Remote; @@ -148,8 +151,11 @@ export const prepareCosmosOrchestrationAccountKit = ( }), }, /** - * @param {ChainAddress} chainAddress - * @param {string} bondDenom e.g. 'uatom' + * @param {object} info + * @param {ChainAddress} info.chainAddress + * @param {string} info.bondDenom e.g. 'uatom' + * @param {LocalIbcAddress} info.localAddress + * @param {RemoteIbcAddress} info.remoteAddress * @param {object} io * @param {IcaAccount} io.account * @param {Remote} io.storageNode @@ -157,14 +163,22 @@ export const prepareCosmosOrchestrationAccountKit = ( * @param {Remote} io.timer * @returns {State} */ - (chainAddress, bondDenom, io) => { + ({ chainAddress, bondDenom, localAddress, remoteAddress }, io) => { const { storageNode, ...rest } = io; // must be the fully synchronous maker because the kit is held in durable state 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(''); + // XXX consider parsing local/remoteAddr to portId, channelId, counterpartyPortId, counterpartyChannelId, connectionId, counterpartyConnectionId + void E(topicKit.recorder).write({ localAddress, remoteAddress }); - return { chainAddress, bondDenom, topicKit, ...rest }; + return { + chainAddress, + bondDenom, + localAddress, + remoteAddress, + topicKit, + ...rest, + }; }, { helper: { diff --git a/packages/orchestration/src/exos/ica-account-kit.js b/packages/orchestration/src/exos/ica-account-kit.js index 38cca597cd5c..9a5946b7cc2e 100644 --- a/packages/orchestration/src/exos/ica-account-kit.js +++ b/packages/orchestration/src/exos/ica-account-kit.js @@ -179,9 +179,12 @@ export const prepareIcaAccountKit = (zone, { watch, asVow }) => * @param {unknown} reason */ async onClose(_connection, reason) { + console.info('@@@ onClose handler reached', _connection, reason); trace(`ICA Channel closed. Reason: ${reason}`); // FIXME handle connection closing https://github.com/Agoric/agoric-sdk/issues/9192 // XXX is there a scenario where a connection will unexpectedly close? _I think yes_ + // 1. get requestedRemoteAddress from state + // 2. return E(port).connect(requestedRemoteAddress, this.facets.connectionHandler) }, }, }, diff --git a/packages/orchestration/src/exos/remote-chain-facade.js b/packages/orchestration/src/exos/remote-chain-facade.js index c68abb389e4e..07aa19715ea4 100644 --- a/packages/orchestration/src/exos/remote-chain-facade.js +++ b/packages/orchestration/src/exos/remote-chain-facade.js @@ -12,6 +12,7 @@ import { ChainAddressShape, ChainFacadeI } from '../typeGuards.js'; * @import {TimerService} from '@agoric/time'; * @import {Remote} from '@agoric/internal'; * @import {Vow, VowTools} from '@agoric/vow'; + * @import {LocalIbcAddress, RemoteIbcAddress} from '@agoric/vats/tools/ibc-utils.js'; * @import {CosmosInterchainService} from './cosmos-interchain-service.js'; * @import {prepareCosmosOrchestrationAccount} from './cosmos-orchestration-account.js'; * @import {ChainInfo, CosmosChainInfo, IBCConnectionInfo, OrchestrationAccount, ChainAddress, IcaAccount, Denom, Chain} from '../types.js'; @@ -48,7 +49,7 @@ const prepareRemoteChainFacadeKit = ( // consider making an `accounts` childNode storageNode, timer, - vowTools: { asVow, watch }, + vowTools: { asVow, watch, allVows }, }, ) => zone.exoClassKit( @@ -60,18 +61,19 @@ const prepareRemoteChainFacadeKit = ( .optional(M.arrayOf(M.undefined())) // empty context .returns(VowShape), }), - getAddressWatcher: M.interface('getAddressWatcher', { - onFulfilled: M.call(M.record()) - .optional(M.remotable()) - .returns(VowShape), + getAddressesWatcher: M.interface('getAddressesWatcher', { + onFulfilled: M.call( + [ChainAddressShape, M.string(), M.string()], + M.remotable(), + ).returns(VowShape), }), makeChildNodeWatcher: M.interface('makeChildNodeWatcher', { - onFulfilled: M.call(M.remotable()) - .optional({ - account: M.remotable(), - chainAddress: ChainAddressShape, - }) - .returns(M.remotable()), + onFulfilled: M.call(M.remotable(), { + account: M.remotable(), + chainAddress: ChainAddressShape, + localAddress: M.string(), + remoteAddress: M.string(), + }).returns(M.remotable()), }), }, /** @@ -117,22 +119,26 @@ const prepareRemoteChainFacadeKit = ( */ onFulfilled(account) { return watch( - E(account).getAddress(), - this.facets.getAddressWatcher, + allVows([ + E(account).getAddress(), + E(account).getLocalAddress(), + E(account).getRemoteAddress(), + ]), + this.facets.getAddressesWatcher, account, ); }, }, - getAddressWatcher: { + getAddressesWatcher: { /** - * @param {ChainAddress} chainAddress + * @param {[ChainAddress, LocalIbcAddress, RemoteIbcAddress]} chainAddresses * @param {IcaAccount} account */ - onFulfilled(chainAddress, account) { + onFulfilled([chainAddress, localAddress, remoteAddress], account) { return watch( E(storageNode).makeChildNode(chainAddress.value), this.facets.makeChildNodeWatcher, - { account, chainAddress }, + { account, chainAddress, localAddress, remoteAddress }, ); }, }, @@ -142,23 +148,36 @@ const prepareRemoteChainFacadeKit = ( * @param {{ * account: IcaAccount; * chainAddress: ChainAddress; + * localAddress: LocalIbcAddress; + * remoteAddress: RemoteIbcAddress; * }} ctx */ - onFulfilled(childNode, { account, chainAddress }) { + onFulfilled( + childNode, + { account, chainAddress, localAddress, remoteAddress }, + ) { const { remoteChainInfo } = this.state; const stakingDenom = remoteChainInfo.stakingTokens?.[0]?.denom; if (!stakingDenom) { throw Fail`chain info lacks staking denom`; } - return makeCosmosOrchestrationAccount(chainAddress, stakingDenom, { - account, - // 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, - timer, - }); + return makeCosmosOrchestrationAccount( + { + chainAddress, + bondDenom: stakingDenom, + localAddress, + remoteAddress, + }, + { + account, + // 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, + timer, + }, + ); }, }, }, diff --git a/packages/orchestration/test/examples/snapshots/stake-ica.contract.test.ts.md b/packages/orchestration/test/examples/snapshots/stake-ica.contract.test.ts.md index e82b5bc1faa3..e93a0cae30a2 100644 --- a/packages/orchestration/test/examples/snapshots/stake-ica.contract.test.ts.md +++ b/packages/orchestration/test/examples/snapshots/stake-ica.contract.test.ts.md @@ -11,14 +11,14 @@ Generated by [AVA](https://avajs.dev). Object @Map Iterator { [ 'mockChainStorageRoot.stakeAtom.accounts.cosmos1test', - '{"body":"#\\"\\"","slots":[]}', + '{"body":"#{\\"localAddress\\":\\"/ibc-port/icacontroller-1/ordered/{\\\\\\"version\\\\\\":\\\\\\"ics27-1\\\\\\",\\\\\\"controllerConnectionId\\\\\\":\\\\\\"connection-8\\\\\\",\\\\\\"hostConnectionId\\\\\\":\\\\\\"connection-649\\\\\\",\\\\\\"address\\\\\\":\\\\\\"cosmos1test\\\\\\",\\\\\\"encoding\\\\\\":\\\\\\"proto3\\\\\\",\\\\\\"txType\\\\\\":\\\\\\"sdk_multi_msg\\\\\\"}/ibc-channel/channel-0\\",\\"remoteAddress\\":\\"/ibc-hop/connection-8/ibc-port/icahost/ordered/{\\\\\\"version\\\\\\":\\\\\\"ics27-1\\\\\\",\\\\\\"controllerConnectionId\\\\\\":\\\\\\"connection-8\\\\\\",\\\\\\"hostConnectionId\\\\\\":\\\\\\"connection-649\\\\\\",\\\\\\"address\\\\\\":\\\\\\"cosmos1test\\\\\\",\\\\\\"encoding\\\\\\":\\\\\\"proto3\\\\\\",\\\\\\"txType\\\\\\":\\\\\\"sdk_multi_msg\\\\\\"}/ibc-channel/channel-0\\"}","slots":[]}', ], [ 'mockChainStorageRoot.stakeAtom.accounts.cosmos1test1', - '{"body":"#\\"\\"","slots":[]}', + '{"body":"#{\\"localAddress\\":\\"/ibc-port/icacontroller-2/ordered/{\\\\\\"version\\\\\\":\\\\\\"ics27-1\\\\\\",\\\\\\"controllerConnectionId\\\\\\":\\\\\\"connection-8\\\\\\",\\\\\\"hostConnectionId\\\\\\":\\\\\\"connection-649\\\\\\",\\\\\\"address\\\\\\":\\\\\\"cosmos1test1\\\\\\",\\\\\\"encoding\\\\\\":\\\\\\"proto3\\\\\\",\\\\\\"txType\\\\\\":\\\\\\"sdk_multi_msg\\\\\\"}/ibc-channel/channel-1\\",\\"remoteAddress\\":\\"/ibc-hop/connection-8/ibc-port/icahost/ordered/{\\\\\\"version\\\\\\":\\\\\\"ics27-1\\\\\\",\\\\\\"controllerConnectionId\\\\\\":\\\\\\"connection-8\\\\\\",\\\\\\"hostConnectionId\\\\\\":\\\\\\"connection-649\\\\\\",\\\\\\"address\\\\\\":\\\\\\"cosmos1test1\\\\\\",\\\\\\"encoding\\\\\\":\\\\\\"proto3\\\\\\",\\\\\\"txType\\\\\\":\\\\\\"sdk_multi_msg\\\\\\"}/ibc-channel/channel-1\\"}","slots":[]}', ], [ 'mockChainStorageRoot.stakeOsmo.accounts.osmo1test2', - '{"body":"#\\"\\"","slots":[]}', + '{"body":"#{\\"localAddress\\":\\"/ibc-port/icacontroller-3/ordered/{\\\\\\"version\\\\\\":\\\\\\"ics27-1\\\\\\",\\\\\\"controllerConnectionId\\\\\\":\\\\\\"connection-1\\\\\\",\\\\\\"hostConnectionId\\\\\\":\\\\\\"connection-1649\\\\\\",\\\\\\"address\\\\\\":\\\\\\"osmo1test2\\\\\\",\\\\\\"encoding\\\\\\":\\\\\\"proto3\\\\\\",\\\\\\"txType\\\\\\":\\\\\\"sdk_multi_msg\\\\\\"}/ibc-channel/channel-2\\",\\"remoteAddress\\":\\"/ibc-hop/connection-1/ibc-port/icahost/ordered/{\\\\\\"version\\\\\\":\\\\\\"ics27-1\\\\\\",\\\\\\"controllerConnectionId\\\\\\":\\\\\\"connection-1\\\\\\",\\\\\\"hostConnectionId\\\\\\":\\\\\\"connection-1649\\\\\\",\\\\\\"address\\\\\\":\\\\\\"osmo1test2\\\\\\",\\\\\\"encoding\\\\\\":\\\\\\"proto3\\\\\\",\\\\\\"txType\\\\\\":\\\\\\"sdk_multi_msg\\\\\\"}/ibc-channel/channel-0\\"}","slots":[]}', ], } diff --git a/packages/orchestration/test/examples/snapshots/stake-ica.contract.test.ts.snap b/packages/orchestration/test/examples/snapshots/stake-ica.contract.test.ts.snap index 5571fd10de5c40947bbd29c897803ee36448e500..96291e4fd799e78938190c69ce7baa09fc655dff 100644 GIT binary patch literal 638 zcmV-^0)hQORzV@5l#;RIwDRNf=i6NK#u7XhXCfNlW7# zjE$3IUS8u%rMbIbh*}2RmXdIBaU{B43XrF zcwLOD-}X19Xx!s}C8v}ex+T{tBdnD?uRP1>IGylQ8#zIS2Pzl=)Gy!%q| Ywp4U#qasU7T literal 404 zcmV;F0c-w2RzVWO> z8TU?2G9QZw00000000B6kk3j2Q543%Go$uLLB(3Nk!jIJB(0US(N;krR1lRd?#$fO zoS7?gPmx3m*F8k!GxQj(+PCUKiW!wqYEg7H=ezLn`(4h{rR^!Fr-viSUH0VdrZ0N3 z?l|f?;8L+Ix$e55)H==$;fcVJGmowgL|=Cl>*2_C1&dRoVPXN%&>|&v05kyX12_Rt zpj4hxP5VkZOq8e0f#?_aScZaCn9JrsOP~)>n#dkQ(nJr@rZ_%F(TLFI8-RBJ8#KWt z>tQGcWK2^wn~jUd1e_7@I9D|1i!TJc60mB_785hY<@f^`6v)5|nV@8zwtVIEb~~aQ z9I*;TTOKOKWzEqwS@~r#KB+D{O8ZJzSZbayh^COWJIhw?z^Ym6Evsc&B};pXwN*R6 yxc^?e{ReI3AH3C{y-n?_FK?uct<_&yr6+9Z@f1_+2E`jaHhluV;h%=H0ssJYrn~+C diff --git a/packages/orchestration/test/examples/stake-ica.contract.test.ts b/packages/orchestration/test/examples/stake-ica.contract.test.ts index b7cb9f09bbdd..55b699a645d6 100644 --- a/packages/orchestration/test/examples/stake-ica.contract.test.ts +++ b/packages/orchestration/test/examples/stake-ica.contract.test.ts @@ -219,16 +219,26 @@ test('makeAccountInvitationMaker', async t => { offerResult.publicSubscribers.account.subscriber, ); const storageUpdate = await E(accountNotifier).getUpdateSince(); + const expectedStorageValue = { + localAddress: + '/ibc-port/icacontroller-1/ordered/{"version":"ics27-1","controllerConnectionId":"connection-8","hostConnectionId":"connection-649","address":"cosmos1test","encoding":"proto3","txType":"sdk_multi_msg"}/ibc-channel/channel-0', + remoteAddress: + '/ibc-hop/connection-8/ibc-port/icahost/ordered/{"version":"ics27-1","controllerConnectionId":"connection-8","hostConnectionId":"connection-649","address":"cosmos1test","encoding":"proto3","txType":"sdk_multi_msg"}/ibc-channel/channel-0', + }; + t.deepEqual(storageUpdate, { updateCount: 1n, - value: '', + value: expectedStorageValue, }); const vstorageEntry = bootstrap.storage.data.get( 'mockChainStorageRoot.stakeAtom.accounts.cosmos1test', ); t.truthy(vstorageEntry, 'vstorage account entry created'); - t.is(bootstrap.marshaller.fromCapData(JSON.parse(vstorageEntry!)), ''); + t.deepEqual( + bootstrap.marshaller.fromCapData(JSON.parse(vstorageEntry!)), + expectedStorageValue, + ); }); test('CosmosOrchestrationAccount - not yet implemented', async t => { diff --git a/packages/orchestration/test/exos/make-test-coa-kit.ts b/packages/orchestration/test/exos/make-test-coa-kit.ts index 99da8b9880d2..7ae5b5ce4218 100644 --- a/packages/orchestration/test/exos/make-test-coa-kit.ts +++ b/packages/orchestration/test/exos/make-test-coa-kit.ts @@ -55,15 +55,22 @@ export const prepareMakeTestCOAKit = ( controllerConnectionId, ); - const accountAddress = await E(cosmosOrchAccount).getAddress(); + const [chainAddress, localAddress, remoteAddress] = await Promise.all([ + E(cosmosOrchAccount).getAddress(), + E(cosmosOrchAccount).getLocalAddress(), + E(cosmosOrchAccount).getRemoteAddress(), + ]); t.log('make a CosmosOrchestrationAccount'); - const holder = makeCosmosOrchestrationAccount(accountAddress, bondDenom, { - account: cosmosOrchAccount, - storageNode: storageNode.makeChildNode(accountAddress.value), - icqConnection: undefined, - timer, - }); + const holder = makeCosmosOrchestrationAccount( + { chainAddress, bondDenom, localAddress, remoteAddress }, + { + account: cosmosOrchAccount, + storageNode: storageNode.makeChildNode(chainAddress.value), + icqConnection: undefined, + timer, + }, + ); return holder; }; diff --git a/packages/orchestration/test/staking-ops.test.ts b/packages/orchestration/test/staking-ops.test.ts index 040f7ff5e745..cc200f2843ec 100644 --- a/packages/orchestration/test/staking-ops.test.ts +++ b/packages/orchestration/test/staking-ops.test.ts @@ -23,6 +23,7 @@ import { makeDurableZone } from '@agoric/zone/durable.js'; import { decodeBase64 } from '@endo/base64'; import { Far } from '@endo/far'; import { Timestamp } from '@agoric/cosmic-proto/google/protobuf/timestamp.js'; +import { config } from 'process'; import { prepareCosmosOrchestrationAccountKit } from '../src/exos/cosmos-orchestration-account.js'; import type { ChainAddress, IcaAccount, ICQConnection } from '../src/types.js'; import { encodeTxResponse } from '../src/utils/cosmos.js'; @@ -43,6 +44,10 @@ test('MsgDelegateResponse trivial response', t => { const configStaking = { acct1: { value: 'agoric1spy36ltduehs5dmszfrp792f0k2emcntrql3nx', + localAddress: + '/ibc-port/icacontroller-1/ordered/{"version":"ics27-1","controllerConnectionId":"connection-8","hostConnectionId":"connection-649","address":"cosmos1test","encoding":"proto3","txType":"sdk_multi_msg"}/ibc-channel/channel-0', + remoteAddress: + '/ibc-hop/connection-8/ibc-port/icahost/ordered/{"version":"ics27-1","controllerConnectionId":"connection-8","hostConnectionId":"connection-649","address":"cosmos1test","encoding":"proto3","txType":"sdk_multi_msg"}/ibc-channel/channel-0', }, validator: { value: 'agoric1valoper234', @@ -154,8 +159,8 @@ const makeScenario = () => { deposit: () => Fail`mock`, getPurse: () => Fail`mock`, prepareTransfer: () => Fail`mock`, - getLocalAddress: () => Fail`mock`, - getRemoteAddress: () => Fail`mock`, + getLocalAddress: () => configStaking.acct1.localAddress, + getRemoteAddress: () => configStaking.acct1.remoteAddress, getPort: () => Fail`mock`, }); return { account, calls }; @@ -231,12 +236,20 @@ test('makeAccount() writes to storage', async t => { zcf, ); - const { holder } = make(account.getAddress(), 'uatom', { - account, - storageNode, - icqConnection, - timer, - }); + const { holder } = make( + { + chainAddress: account.getAddress(), + localAddress: account.getLocalAddress(), + remoteAddress: account.getRemoteAddress(), + bondDenom: 'uatom', + }, + { + account, + storageNode, + icqConnection, + timer, + }, + ); const { publicSubscribers } = await E.when(holder.asContinuingOffer()); const accountNotifier = makeNotifierFromSubscriber( // @ts-expect-error the promise from `subscriber.getUpdateSince` can't be used in a flow @@ -245,7 +258,10 @@ test('makeAccount() writes to storage', async t => { const storageUpdate = await E(accountNotifier).getUpdateSince(); t.deepEqual(storageUpdate, { updateCount: 1n, - value: '', + value: { + localAddress: configStaking.acct1.localAddress, + remoteAddress: configStaking.acct1.remoteAddress, + }, }); }); @@ -262,12 +278,20 @@ test('withdrawRewards() on StakingAccountHolder formats message correctly', asyn ); // Higher fidelity tests below use invitationMakers. - const { holder } = make(account.getAddress(), 'uatom', { - account, - storageNode, - icqConnection, - timer, - }); + const { holder } = make( + { + chainAddress: account.getAddress(), + localAddress: account.getLocalAddress(), + remoteAddress: account.getRemoteAddress(), + bondDenom: 'uatom', + }, + { + account, + storageNode, + icqConnection, + timer, + }, + ); const { validator } = configStaking; const actual = await E(holder).withdrawReward(validator); t.deepEqual(actual, [{ denom: 'uatom', value: 2n }]); @@ -298,12 +322,20 @@ test(`delegate; redelegate using invitationMakers`, async t => { zcf, ); - const { invitationMakers } = makeAccountKit(account.getAddress(), 'uatom', { - account, - storageNode, - icqConnection, - timer, - }); + const { invitationMakers } = makeAccountKit( + { + chainAddress: account.getAddress(), + localAddress: account.getLocalAddress(), + remoteAddress: account.getRemoteAddress(), + bondDenom: 'uatom', + }, + { + account, + storageNode, + icqConnection, + timer, + }, + ); const { validator, delegations } = configStaking; { @@ -379,12 +411,20 @@ test(`withdraw rewards using invitationMakers`, async t => { zcf, ); - const { invitationMakers } = makeAccountKit(account.getAddress(), 'uatom', { - account, - storageNode, - icqConnection, - timer, - }); + const { invitationMakers } = makeAccountKit( + { + chainAddress: account.getAddress(), + localAddress: account.getLocalAddress(), + remoteAddress: account.getRemoteAddress(), + bondDenom: 'uatom', + }, + { + account, + storageNode, + icqConnection, + timer, + }, + ); const { validator } = configStaking; const toWithdraw = await E(invitationMakers).WithdrawReward(validator); @@ -418,12 +458,20 @@ test(`undelegate waits for unbonding period`, async t => { zcf, ); - const { invitationMakers } = makeAccountKit(account.getAddress(), 'uatom', { - account, - storageNode, - icqConnection, - timer, - }); + const { invitationMakers } = makeAccountKit( + { + chainAddress: account.getAddress(), + localAddress: account.getLocalAddress(), + remoteAddress: account.getRemoteAddress(), + bondDenom: 'uatom', + }, + { + account, + storageNode, + icqConnection, + timer, + }, + ); const { validator, delegations } = configStaking; diff --git a/packages/orchestration/test/types.test-d.ts b/packages/orchestration/test/types.test-d.ts index 0c7512fd3377..004f77eaca8b 100644 --- a/packages/orchestration/test/types.test-d.ts +++ b/packages/orchestration/test/types.test-d.ts @@ -77,7 +77,6 @@ expectNotType(chainAddr); makeCosmosOrchestrationAccount( anyVal, anyVal, - anyVal, ) satisfies HostInterface; }