From d683f60574f64e4eb708cad486772f59891ba4ab Mon Sep 17 00:00:00 2001 From: 0xPatrick Date: Sat, 26 Oct 2024 15:08:49 -0400 Subject: [PATCH] types: update `OrchestrationAccount` type - fixes `CosmosChainAccountMethods` that depended on non-existent `icaEnabled` parameter - only expose `IcaAccount` methods available on `OrchestrationAccount` - removes `IcaAccount` and `StakingAccountQueries` methods from `OrchestrationAccount` - improve `monitorTransfers` doc string --- packages/orchestration/src/cosmos-api.ts | 66 +++++++++++-------- packages/orchestration/src/exos/README.md | 9 +-- .../orchestration/src/exos/orchestrator.js | 12 +++- .../orchestration/src/orchestration-api.ts | 7 +- packages/orchestration/test/types.test-d.ts | 55 +++++++++++++++- 5 files changed, 110 insertions(+), 39 deletions(-) diff --git a/packages/orchestration/src/cosmos-api.ts b/packages/orchestration/src/cosmos-api.ts index 2b8072a3c87..b718b7fa916 100644 --- a/packages/orchestration/src/cosmos-api.ts +++ b/packages/orchestration/src/cosmos-api.ts @@ -8,6 +8,7 @@ import type { } from '@agoric/cosmic-proto/cosmos/staking/v1beta1/staking.js'; import type { TxBody } from '@agoric/cosmic-proto/cosmos/tx/v1beta1/tx.js'; import type { MsgTransfer } from '@agoric/cosmic-proto/ibc/applications/transfer/v1/tx.js'; +import type { FungibleTokenPacketData } from '@agoric/cosmic-proto/ibc/applications/transfer/v2/packet.js'; import type { State as IBCChannelState, Order, @@ -19,7 +20,11 @@ import type { } from '@agoric/cosmic-proto/tendermint/abci/types.js'; import type { Brand, Purse, Payment, Amount } from '@agoric/ertp/src/types.js'; import type { Port } from '@agoric/network'; -import type { IBCChannelID, IBCConnectionID } from '@agoric/vats'; +import type { + IBCChannelID, + IBCConnectionID, + VTransferIBCEvent, +} from '@agoric/vats'; import type { TargetApp, TargetRegistration, @@ -226,20 +231,10 @@ export interface StakingAccountActions { } /** - * Low level object that supports queries and operations for an account on a remote chain. + * Low level methods from IcaAccount that we pass through to CosmosOrchestrationAccount */ -export interface IcaAccount { - /** - * @returns the address of the account on the remote chain - */ - getAddress: () => ChainAddress; - /** - * Submit a transaction on behalf of the remote account for execution on the remote chain. - * @param msgs - records for the transaction - * @returns acknowledgement string - */ - executeTx: (msgs: TypedJson[]) => Promise; +export interface IcaAccountMethods { /** * Submit a transaction on behalf of the remote account for execution on the remote chain. * @param msgs - records for the transaction @@ -267,6 +262,23 @@ export interface IcaAccount { * @throws {Error} if connection is currently active */ reactivate: () => Promise; +} + +/** + * Low level object that supports queries and operations for an account on a remote chain. + */ +export interface IcaAccount extends IcaAccountMethods { + /** + * @returns the address of the account on the remote chain + */ + getAddress: () => ChainAddress; + + /** + * Submit a transaction on behalf of the remote account for execution on the remote chain. + * @param msgs - records for the transaction + * @returns acknowledgement string + */ + executeTx: (msgs: TypedJson[]) => Promise; /** @returns the address of the remote channel */ getRemoteAddress: () => RemoteIbcAddress; /** @returns the address of the local channel */ @@ -280,16 +292,22 @@ export interface LiquidStakingMethods { liquidStake: (amount: AmountArg) => Promise; } +// TODO support StakingAccountQueries /** Methods supported only on Agoric chain accounts */ -export interface LocalAccountMethods { +export interface LocalAccountMethods extends StakingAccountActions { /** deposit payment (from zoe, for example) to the account */ deposit: (payment: Payment<'nat'>) => Promise; /** withdraw a Payment from the account */ withdraw: (amount: Amount<'nat'>) => Promise>; /** * Register a handler that receives an event each time ICS-20 transfers are - * sent or received by the underlying account. Each account may be associated - * with at most one handler at a given time. + * sent or received by the underlying account. + * + * Handler includes {@link VTransferIBCEvent} and + * {@link FungibleTokenPacketData} that can be used for application logic. + * + * Each account may be associated with at most one handler at a given time. + * * Does not grant the handler the ability to intercept a transfer. For a * blocking handler, aka 'IBC Hooks', leverage `registerActiveTap` from * `transferMiddleware` directly. @@ -320,16 +338,12 @@ export interface IBCMsgTransferOptions { * @see {OrchestrationAccountI} */ export type CosmosChainAccountMethods = - (CCI extends { - icaEnabled: true; - } - ? IcaAccount - : {}) & - CCI extends { - stakingTokens: {}; - } - ? StakingAccountActions & StakingAccountQueries - : {}; + IcaAccountMethods & + (CCI extends { + stakingTokens: {}; + } + ? StakingAccountActions & StakingAccountQueries + : {}); export type ICQQueryFunction = ( msgs: JsonSafe[], diff --git a/packages/orchestration/src/exos/README.md b/packages/orchestration/src/exos/README.md index f147c1bf071..0599cbbbf1a 100644 --- a/packages/orchestration/src/exos/README.md +++ b/packages/orchestration/src/exos/README.md @@ -1,6 +1,6 @@ # Exo structure -Last verified 2024-09-06 +Last verified 2024-10-30 ```mermaid classDiagram @@ -52,9 +52,9 @@ classDiagram %% In other vats class Port { - getLocalAddress() addListener() connect() + getLocalAddress() removeListener() revoke() } @@ -76,9 +76,8 @@ classDiagram deposit() executeTx() getBalance() - withdraw() - executeTx() monitorTransfers() + withdraw() } %% In api consumer vats @@ -113,12 +112,14 @@ classDiagram timer: Timer topicKit: RecorderKit asContinuingOffer() + deactivate() delegate() executeEncodedTx() getAddress() getBalance() getBalances() getPublicTopics() + reactivate() redelegate() send() sendAll() diff --git a/packages/orchestration/src/exos/orchestrator.js b/packages/orchestration/src/exos/orchestrator.js index 97e383dcf12..70e02ee60e7 100644 --- a/packages/orchestration/src/exos/orchestrator.js +++ b/packages/orchestration/src/exos/orchestrator.js @@ -25,7 +25,7 @@ import { * @import {CosmosInterchainService} from './exo-interfaces.js'; * @import {MakeLocalChainFacade} from './local-chain-facade.js'; * @import {MakeRemoteChainFacade} from './remote-chain-facade.js'; - * @import {Chain, ChainInfo, IBCConnectionInfo, Orchestrator} from '../types.js'; + * @import {Chain, ChainInfo, IBCConnectionInfo, KnownChains, Orchestrator} from '../types.js'; */ const { Vow$ } = NetworkShape; // TODO #9611 @@ -148,14 +148,20 @@ const prepareOrchestratorKit = ( if (maybeChain.pending) { throw Fail`wait until getChain(${q(chainName)}) completes before getDenomInfo(${q(denom)})`; } - const chain = maybeChain.value; + const chain = + /** @type {HostInterface>} */ ( + maybeChain.value + ); chainByName.has(baseName) || Fail`use getChain(${q(baseName)}) before getDenomInfo(${q(denom)})`; const maybeBase = chainByName.get(baseName); if (maybeBase.pending) { throw Fail`wait until getChain(${q(baseName)}) completes before getDenomInfo(${q(denom)})`; } - const base = maybeBase.value; + const base = + /** @type {HostInterface>} */ ( + maybeBase.value + ); return harden({ chain, base, brand, baseDenom }); }, /** @type {HostOf} */ diff --git a/packages/orchestration/src/orchestration-api.ts b/packages/orchestration/src/orchestration-api.ts index cf8f84d9c07..986c66ea10f 100644 --- a/packages/orchestration/src/orchestration-api.ts +++ b/packages/orchestration/src/orchestration-api.ts @@ -7,10 +7,7 @@ import type { Amount, Brand, NatAmount } from '@agoric/ertp/src/types.js'; import type { CurrentWalletRecord } from '@agoric/smart-wallet/src/smartWallet.js'; import type { Timestamp } from '@agoric/time'; -import type { - LocalChainAccount, - QueryManyFn, -} from '@agoric/vats/src/localchain.js'; +import type { QueryManyFn } from '@agoric/vats/src/localchain.js'; import type { ResolvedPublicTopic } from '@agoric/zoe/src/contractSupport/topics.js'; import type { Passable } from '@endo/marshal'; import type { @@ -76,7 +73,7 @@ export type ChainAddress = { export type OrchestrationAccount = OrchestrationAccountI & (CI extends CosmosChainInfo ? CI['chainId'] extends `agoric${string}` - ? CosmosChainAccountMethods & LocalAccountMethods + ? LocalAccountMethods : CosmosChainAccountMethods : {}); diff --git a/packages/orchestration/test/types.test-d.ts b/packages/orchestration/test/types.test-d.ts index ba9c3287753..a889ca536e6 100644 --- a/packages/orchestration/test/types.test-d.ts +++ b/packages/orchestration/test/types.test-d.ts @@ -3,7 +3,7 @@ */ import type { HostInterface, HostOf } from '@agoric/async-flow'; -import { type JsonSafe, typedJson } from '@agoric/cosmic-proto'; +import { type AnyJson, type JsonSafe, typedJson } from '@agoric/cosmic-proto'; import type { QueryAllBalancesResponse, QueryBalanceResponse, @@ -14,10 +14,16 @@ import type { Vow, VowTools } from '@agoric/vow'; import type { ResolvedPublicTopic } from '@agoric/zoe/src/contractSupport/topics.js'; import type { Passable } from '@endo/marshal'; import { expectAssignable, expectNotType, expectType } from 'tsd'; +import type { TxBody } from '@agoric/cosmic-proto/cosmos/tx/v1beta1/tx.js'; +import type { + TargetApp, + TargetRegistration, +} from '@agoric/vats/src/bridge-target.js'; import { prepareCosmosOrchestrationAccount } from '../src/exos/cosmos-orchestration-account.js'; import type { LocalOrchestrationAccountKit } from '../src/exos/local-orchestration-account.js'; import type { OrchestrationFacade } from '../src/facade.js'; import type { + AmountArg, Chain, ChainAddress, ChainInfo, @@ -267,3 +273,50 @@ expectNotType(chainAddr); expectAssignable(addr as CosmosValidatorAddress); expectAssignable(denomAmount as DenomAmount); } + +// Test LocalAccountMethods +{ + type ChainFacade = Chain; + const remoteChain: ChainFacade = null as any; + + const account = await remoteChain.makeAccount(); + + // Verify monitorTransfers is available + expectType<(tap: TargetApp) => Promise>( + account.monitorTransfers, + ); + + // Verify StakingAccountActions are available (StakingAccountQueries not yet supported) + expectType< + (validator: CosmosValidatorAddress, amount: AmountArg) => Promise + >(account.delegate); + + // @ts-expect-error executeEncodedTx not available on localAccount + expectType<() => Promise>(account.executeEncodedTx); +} + +// Test CosmosChainAccountMethods +{ + type ChainFacade = Chain< + CosmosChainInfo & { + chainId: 'cosmoshub-4'; + stakingTokens: [{ denom: 'uatom' }]; + } + >; + const remoteChain: ChainFacade = null as any; + + const account = await remoteChain.makeAccount(); + + // Verify executeEncodedTx is available + expectType< + ( + msgs: AnyJson[], + opts?: Partial>, + ) => Promise + >(account.executeEncodedTx); + + // Verify delegate is available via stakingTokens parameter + expectType< + (validator: CosmosValidatorAddress, amount: AmountArg) => Promise + >(account.delegate); +}