diff --git a/packages/stargate/src/queries/bank.ts b/packages/stargate/src/queries/bank.ts new file mode 100644 index 00000000..3fa8f3b4 --- /dev/null +++ b/packages/stargate/src/queries/bank.ts @@ -0,0 +1,29 @@ +import { Bech32, toAscii } from "@cosmjs/encoding"; + +import { cosmos } from "../generated/codecimpl"; +import { QueryClient } from "../queryclient"; + +export interface BankExtension { + readonly bank: { + readonly balance: (address: string, denom: string) => Promise; + }; +} + +export function setupBankExtension(base: QueryClient): BankExtension { + return { + bank: { + balance: async (address: string, denom: string) => { + // balance key is a bit tricker, using some prefix stores + // https://github.com/cosmwasm/cosmos-sdk/blob/80f7ff62f79777a487d0c7a53c64b0f7e43c47b9/x/bank/keeper/view.go#L74-L77 + // ("balances", binAddress, denom) + // it seem like prefix stores just do a dumb concat with the keys (no tricks to avoid overlap) + // https://github.com/cosmos/cosmos-sdk/blob/2879c0702c87dc9dd828a8c42b9224dc054e28ad/store/prefix/store.go#L61-L64 + // https://github.com/cosmos/cosmos-sdk/blob/2879c0702c87dc9dd828a8c42b9224dc054e28ad/store/prefix/store.go#L37-L43 + const binAddress = Bech32.decode(address).data; + const bankKey = Uint8Array.from([...toAscii("balances"), ...binAddress, ...toAscii(denom)]); + const responseData = await base.queryVerified("bank", bankKey); + return cosmos.Coin.decode(responseData); + }, + }, + }; +} diff --git a/packages/stargate/src/stargateclient.ts b/packages/stargate/src/stargateclient.ts index 566c0602..4532b8b3 100644 --- a/packages/stargate/src/stargateclient.ts +++ b/packages/stargate/src/stargateclient.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/naming-convention */ -import { Bech32, toAscii, toHex } from "@cosmjs/encoding"; +import { Bech32, toHex } from "@cosmjs/encoding"; import { Block, Coin, @@ -17,6 +17,7 @@ import { assert, assertDefined } from "@cosmjs/utils"; import Long from "long"; import { cosmos } from "./generated/codecimpl"; +import { BankExtension, setupBankExtension } from "./queries/bank"; import { QueryClient } from "./queryclient"; /** A transaction that is indexed as part of the transaction history */ @@ -115,7 +116,7 @@ export interface PrivateStargateClient { export class StargateClient { private readonly tmClient: TendermintClient; - private readonly queryClient: QueryClient; + private readonly queryClient: QueryClient & BankExtension; private chainId: string | undefined; public static async connect(endpoint: string): Promise { @@ -125,7 +126,7 @@ export class StargateClient { private constructor(tmClient: TendermintClient) { this.tmClient = tmClient; - this.queryClient = QueryClient.withExtensions(tmClient); + this.queryClient = QueryClient.withExtensions(tmClient, setupBankExtension); } public async getChainId(): Promise { @@ -192,24 +193,11 @@ export class StargateClient { } public async getBalance(address: string, searchDenom: string): Promise { - // balance key is a bit tricker, using some prefix stores - // https://github.com/cosmwasm/cosmos-sdk/blob/80f7ff62f79777a487d0c7a53c64b0f7e43c47b9/x/bank/keeper/view.go#L74-L77 - // ("balances", binAddress, denom) - // it seem like prefix stores just do a dumb concat with the keys (no tricks to avoid overlap) - // https://github.com/cosmos/cosmos-sdk/blob/2879c0702c87dc9dd828a8c42b9224dc054e28ad/store/prefix/store.go#L61-L64 - // https://github.com/cosmos/cosmos-sdk/blob/2879c0702c87dc9dd828a8c42b9224dc054e28ad/store/prefix/store.go#L37-L43 - const binAddress = Bech32.decode(address).data; - const bankKey = Uint8Array.from([...toAscii("balances"), ...binAddress, ...toAscii(searchDenom)]); - - const responseData = await this.queryClient.queryVerified("bank", bankKey); - const { amount, denom } = cosmos.Coin.decode(responseData); - if (denom === "") { + const balance = await this.queryClient.bank.balance(address, searchDenom); + if (!balance.denom) { return null; } else { - return { - amount: amount, - denom: denom, - }; + return coinFromProto(balance); } } diff --git a/packages/stargate/types/queries/bank.d.ts b/packages/stargate/types/queries/bank.d.ts new file mode 100644 index 00000000..e55feda0 --- /dev/null +++ b/packages/stargate/types/queries/bank.d.ts @@ -0,0 +1,8 @@ +import { cosmos } from "../generated/codecimpl"; +import { QueryClient } from "../queryclient"; +export interface BankExtension { + readonly bank: { + readonly balance: (address: string, denom: string) => Promise; + }; +} +export declare function setupBankExtension(base: QueryClient): BankExtension;