diff --git a/packages/orchestration/src/exos/chainAccountKit.js b/packages/orchestration/src/exos/chainAccountKit.js index 01f3d92afe57..61e687276a31 100644 --- a/packages/orchestration/src/exos/chainAccountKit.js +++ b/packages/orchestration/src/exos/chainAccountKit.js @@ -2,7 +2,7 @@ import { NonNullish } from '@agoric/assert'; import { PurseShape } from '@agoric/ertp'; import { makeTracer } from '@agoric/internal'; -import { V as E } from '@agoric/vow/vat.js'; +import { E } from '@endo/far'; import { M } from '@endo/patterns'; import { ChainAddressShape, @@ -15,7 +15,7 @@ import { makeTxPacket, parseTxPacket } from '../utils/packet.js'; /** * @import {Zone} from '@agoric/base-zone'; * @import {Connection, Port} from '@agoric/network'; - * @import {Remote} from '@agoric/vow'; + * @import {Remote, VowTools} from '@agoric/vow'; * @import {AnyJson} from '@agoric/cosmic-proto'; * @import {TxBody} from '@agoric/cosmic-proto/cosmos/tx/v1beta1/tx.js'; * @import {LocalIbcAddress, RemoteIbcAddress} from '@agoric/vats/tools/ibc-utils.js'; @@ -54,11 +54,22 @@ export const ChainAccountI = M.interface('ChainAccount', { * }} State */ -/** @param {Zone} zone */ -export const prepareChainAccountKit = zone => +/** + * @param {Zone} zone + * @param {VowTools} vowTools + */ +export const prepareChainAccountKit = (zone, { watch, when }) => zone.exoClassKit( 'ChainAccountKit', - { account: ChainAccountI, connectionHandler: ConnectionHandlerI }, + { + account: ChainAccountI, + connectionHandler: ConnectionHandlerI, + handleExecuteEncodedTxWatcher: M.interface('HandleQueryWatcher', { + onFulfilled: M.call(M.string()) + .optional(M.arrayOf(M.undefined())) // does not need watcherContext + .returns(M.string()), + }), + }, /** * @param {Port} port * @param {string} requestedRemoteAddress @@ -73,6 +84,12 @@ export const prepareChainAccountKit = zone => localAddress: undefined, }), { + handleExecuteEncodedTxWatcher: { + /** @param {string} ack */ + onFulfilled(ack) { + return parseTxPacket(ack); + }, + }, account: { /** @returns {ChainAddress} */ getAddress() { @@ -120,20 +137,21 @@ export const prepareChainAccountKit = zone => executeEncodedTx(msgs, opts) { const { connection } = this.state; if (!connection) throw Fail`connection not available`; - return E.when( - E(connection).send(makeTxPacket(msgs, opts)), - // if parseTxPacket cannot find a `result` key, it throws - ack => parseTxPacket(ack), + return when( + watch( + E(connection).send(makeTxPacket(msgs, opts)), + this.facets.handleExecuteEncodedTxWatcher, + ), ); }, /** Close the remote account */ - async close() { - /// XXX what should the behavior be here? and `onClose`? + close() { + /// TODO #9192 what should the behavior be here? and `onClose`? // - retrieve assets? // - revoke the port? const { connection } = this.state; if (!connection) throw Fail`connection not available`; - await E(connection).close(); + return when(watch(E(connection).close())); }, /** * get Purse for a brand to .withdraw() a Payment from the account diff --git a/packages/orchestration/src/service.js b/packages/orchestration/src/service.js index 5194ceeb95df..690760dab449 100644 --- a/packages/orchestration/src/service.js +++ b/packages/orchestration/src/service.js @@ -237,7 +237,7 @@ const prepareOrchestrationKit = ( * @param {VowTools} vowTools */ export const prepareOrchestrationTools = (zone, vowTools) => { - const makeChainAccountKit = prepareChainAccountKit(zone); + const makeChainAccountKit = prepareChainAccountKit(zone, vowTools); const makeICQConnectionKit = prepareICQConnectionKit(zone, vowTools); const makeOrchestrationKit = prepareOrchestrationKit( zone, diff --git a/packages/orchestration/test/service.test.ts b/packages/orchestration/test/service.test.ts index 0a324843eeb7..5bbf024ef885 100644 --- a/packages/orchestration/test/service.test.ts +++ b/packages/orchestration/test/service.test.ts @@ -4,7 +4,9 @@ import { toRequestQueryJson } from '@agoric/cosmic-proto'; import { QueryBalanceRequest } from '@agoric/cosmic-proto/cosmos/bank/v1beta1/query.js'; import { MsgDelegate } from '@agoric/cosmic-proto/cosmos/staking/v1beta1/tx.js'; import { Any } from '@agoric/cosmic-proto/google/protobuf/any.js'; +import { matches } from '@endo/patterns'; import { commonSetup } from './supports.js'; +import { ChainAddressShape } from '../src/typeGuards.js'; test('makeICQConnection returns an ICQConnection', async t => { const { @@ -89,17 +91,32 @@ test('makeAccount returns a ChainAccount', async t => { 'remote address contains version and encoding in version string', ); + t.true(matches(chainAddr, ChainAddressShape)); + t.regex( + chainAddr.address, + /UNPARSABLE_CHAIN_ADDRESS/, + 'TODO use mocked ibc connection instead of echo connection', + ); + + const delegateMsg = Any.toJSON( + MsgDelegate.toProtoMsg({ + delegatorAddress: 'cosmos1test', + validatorAddress: 'cosmosvaloper1test', + amount: { denom: 'uatom', amount: '10' }, + }), + ); await t.throwsAsync( - E(account).executeEncodedTx([ - Any.toJSON( - MsgDelegate.toProtoMsg({ - delegatorAddress: 'cosmos1test', - validatorAddress: 'cosmosvaloper1test', - amount: { denom: 'uatom', amount: '10' }, - }), - ), - ]), + E(account).executeEncodedTx([delegateMsg]), { message: /"type":1(.*)"data":"(.*)"memo":""/ }, 'TODO do not use echo connection', ); + + await E(account).close(); + await t.throwsAsync( + E(account).executeEncodedTx([delegateMsg]), + { + message: 'Connection closed', + }, + 'cannot execute transaction if connection is closed', + ); });