diff --git a/CHANGELOG.md b/CHANGELOG.md index f52ea98b98..042efec1d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ and this project adheres to ## [Unreleased] +### Added + +- @cosmjs/stargate: Added the ability to specify a custom account parser for `StargateClient` + ### Fixed - @cosmjs/proto-signing: Add missing runtime dependencies @cosmjs/encoding and diff --git a/packages/stargate/src/accounts.ts b/packages/stargate/src/accounts.ts index 20c8a3aa27..8b5d74a1dd 100644 --- a/packages/stargate/src/accounts.ts +++ b/packages/stargate/src/accounts.ts @@ -36,8 +36,13 @@ function accountFromBaseAccount(input: BaseAccount): Account { } /** - * Takes an `Any` encoded account from the chain and extracts some common - * `Account` information from it. This is supposed to support the most relevant + * Represents a generic function that takes an `Any` encoded account from the chain + * and extracts some common `Account` information from it. + */ +export type AccountParser = (any: Any) => Account; + +/** + * Basic implementation of AccountParser. This is supposed to support the most relevant * common Cosmos SDK account types. If you need support for exotic account types, * you'll need to write your own account decoder. */ diff --git a/packages/stargate/src/index.ts b/packages/stargate/src/index.ts index c85a447c3f..6af58edc10 100644 --- a/packages/stargate/src/index.ts +++ b/packages/stargate/src/index.ts @@ -1,4 +1,4 @@ -export { Account, accountFromAny } from "./accounts"; +export { Account, accountFromAny, AccountParser } from "./accounts"; export { AminoConverter, AminoConverters, AminoTypes } from "./aminotypes"; export { calculateFee, GasPrice } from "./fee"; export * as logs from "./logs"; @@ -117,6 +117,7 @@ export { isDeliverTxSuccess, SequenceResponse, StargateClient, + StargateClientOptions, TimeoutError, } from "./stargateclient"; export { StdFee } from "@cosmjs/amino"; diff --git a/packages/stargate/src/signingstargateclient.ts b/packages/stargate/src/signingstargateclient.ts index cfba5f33a8..858f9f9e5a 100644 --- a/packages/stargate/src/signingstargateclient.ts +++ b/packages/stargate/src/signingstargateclient.ts @@ -48,7 +48,7 @@ import { createIbcAminoConverters, createStakingAminoConverters, } from "./modules"; -import { DeliverTxResponse, StargateClient } from "./stargateclient"; +import { DeliverTxResponse, StargateClient, StargateClientOptions } from "./stargateclient"; export const defaultRegistryTypes: ReadonlyArray<[string, GeneratedType]> = [ ["/cosmos.base.v1beta1.Coin", Coin], @@ -81,7 +81,7 @@ export interface PrivateSigningStargateClient { readonly registry: Registry; } -export interface SigningStargateClientOptions { +export interface SigningStargateClientOptions extends StargateClientOptions { readonly registry?: Registry; readonly aminoTypes?: AminoTypes; readonly prefix?: string; @@ -141,7 +141,7 @@ export class SigningStargateClient extends StargateClient { signer: OfflineSigner, options: SigningStargateClientOptions, ) { - super(tmClient); + super(tmClient, options); // TODO: do we really want to set a default here? Ideally we could get it from the signer such that users only have to set it once. const prefix = options.prefix ?? "cosmos"; const { registry = createDefaultRegistry(), aminoTypes = new AminoTypes(createDefaultTypes(prefix)) } = diff --git a/packages/stargate/src/stargateclient.ts b/packages/stargate/src/stargateclient.ts index 997b0328a9..96ef6a7dc2 100644 --- a/packages/stargate/src/stargateclient.ts +++ b/packages/stargate/src/stargateclient.ts @@ -6,7 +6,7 @@ import { sleep } from "@cosmjs/utils"; import { MsgData } from "cosmjs-types/cosmos/base/abci/v1beta1/abci"; import { Coin } from "cosmjs-types/cosmos/base/v1beta1/coin"; -import { Account, accountFromAny } from "./accounts"; +import { Account, accountFromAny, AccountParser } from "./accounts"; import { AuthExtension, BankExtension, @@ -136,19 +136,27 @@ export interface PrivateStargateClient { readonly tmClient: Tendermint34Client | undefined; } +export interface StargateClientOptions { + readonly accountParser?: AccountParser; +} + export class StargateClient { private readonly tmClient: Tendermint34Client | undefined; private readonly queryClient: | (QueryClient & AuthExtension & BankExtension & StakingExtension & TxExtension) | undefined; private chainId: string | undefined; + private readonly accountParser: AccountParser; - public static async connect(endpoint: string): Promise { + public static async connect( + endpoint: string, + options: StargateClientOptions = {}, + ): Promise { const tmClient = await Tendermint34Client.connect(endpoint); - return new StargateClient(tmClient); + return new StargateClient(tmClient, options); } - protected constructor(tmClient: Tendermint34Client | undefined) { + protected constructor(tmClient: Tendermint34Client | undefined, options: StargateClientOptions) { if (tmClient) { this.tmClient = tmClient; this.queryClient = QueryClient.withExtensions( @@ -159,6 +167,8 @@ export class StargateClient { setupTxExtension, ); } + const { accountParser = accountFromAny } = options; + this.accountParser = accountParser; } protected getTmClient(): Tendermint34Client | undefined { @@ -210,7 +220,7 @@ export class StargateClient { public async getAccount(searchAddress: string): Promise { try { const account = await this.forceGetQueryClient().auth.account(searchAddress); - return account ? accountFromAny(account) : null; + return account ? this.accountParser(account) : null; } catch (error: any) { if (/rpc error: code = NotFound/i.test(error.toString())) { return null;