diff --git a/packages/orchestration/src/exos/README.md b/packages/orchestration/src/exos/README.md index b78588788040..4e76d011ab37 100644 --- a/packages/orchestration/src/exos/README.md +++ b/packages/orchestration/src/exos/README.md @@ -96,6 +96,7 @@ classDiagram executeTx() getAddress() getBalance() + getBalances() getPublicTopics() monitorTransfers() send() diff --git a/packages/orchestration/src/exos/local-orchestration-account.js b/packages/orchestration/src/exos/local-orchestration-account.js index b0e845682ed9..355852bb8898 100644 --- a/packages/orchestration/src/exos/local-orchestration-account.js +++ b/packages/orchestration/src/exos/local-orchestration-account.js @@ -143,6 +143,11 @@ export const prepareLocalOrchestrationAccountKit = ( queryBalanceWatcher: M.interface('queryBalanceWatcher', { onFulfilled: M.call(TypedJsonShape).returns(DenomAmountShape), }), + queryBalancesWatcher: M.interface('queryBalancesWatcher', { + onFulfilled: M.call(TypedJsonShape).returns( + M.arrayOf(DenomAmountShape), + ), + }), invitationMakers: M.interface('invitationMakers', { Delegate: M.call(M.string(), AmountShape).returns(M.promise()), Undelegate: M.call(M.string(), AmountShape).returns(M.promise()), @@ -374,6 +379,25 @@ export const prepareLocalOrchestrationAccountKit = ( return harden(toDenomAmount(balance)); }, }, + /** + * handles a QueryAllBalancesRequest from localchain.query and returns the + * balances as a DenomAmounts + */ + queryBalancesWatcher: { + /** + * @param {ResponseTo< + * TypedJson<'/cosmos.bank.v1beta1.QueryAllBalancesRequest'> + * >} result + * @returns {DenomAmount[]} + */ + onFulfilled(result) { + const { balances } = result; + if (!balances || !Array.isArray(balances)) { + throw Fail`Expected balances ${q(result)};`; + } + return harden(balances.map(toDenomAmount)); + }, + }, holder: { /** @type {HostOf} */ asContinuingOffer() { @@ -432,8 +456,14 @@ export const prepareLocalOrchestrationAccountKit = ( }, /** @type {HostOf} */ getBalances() { - // TODO https://github.com/Agoric/agoric-sdk/issues/9610 - return asVow(() => Fail`not yet implemented`); + return watch( + E(localchain).query( + typedJson('/cosmos.bank.v1beta1.QueryAllBalancesRequest', { + address: this.state.address.value, + }), + ), + this.facets.queryBalancesWatcher, + ); }, /** diff --git a/packages/orchestration/test/exos/local-orchestration-account-kit.test.ts b/packages/orchestration/test/exos/local-orchestration-account-kit.test.ts index 20309410e5b9..7fff8a234e05 100644 --- a/packages/orchestration/test/exos/local-orchestration-account-kit.test.ts +++ b/packages/orchestration/test/exos/local-orchestration-account-kit.test.ts @@ -3,7 +3,10 @@ import { test } from '@agoric/zoe/tools/prepare-test-env-ava.js'; import { AmountMath, makeIssuerKit } from '@agoric/ertp'; import { eventLoopIteration } from '@agoric/internal/src/testing-utils.js'; import { TargetApp } from '@agoric/vats/src/bridge-target.js'; -import { SIMULATED_ERRORS } from '@agoric/vats/tools/fake-bridge.js'; +import { + LOCALCHAIN_QUERY_ALL_BALANCES_RESPONSE, + SIMULATED_ERRORS, +} from '@agoric/vats/tools/fake-bridge.js'; import { heapVowE as VE } from '@agoric/vow/vat.js'; import { withAmountUtils } from '@agoric/zoe/tools/test-utils.js'; import { ChainAddress, type AmountArg } from '../../src/orchestration-api.js'; @@ -401,3 +404,25 @@ test('getBalance', async t => { 'only sent query for ibc/1234', ); }); + +test('getBalances', async t => { + const common = await commonSetup(t); + const makeTestLOAKit = prepareMakeTestLOAKit(t, common); + const account = await makeTestLOAKit(); + t.truthy(account, 'account is returned'); + + const { + utils: { inspectLocalBridge }, + } = common; + + t.deepEqual( + await VE(account).getBalances(), + LOCALCHAIN_QUERY_ALL_BALANCES_RESPONSE, + ); + + const localBridgeMessages = inspectLocalBridge(); + const queryMessages = localBridgeMessages.filter( + x => x.type === 'VLOCALCHAIN_QUERY_MANY', + ); + t.is(queryMessages.length, 1, 'getBalances sends query to cosmos golang'); +});