mirror of
https://github.com/cosmos/cosmjs.git
synced 2025-03-11 14:09:15 +00:00
Merge pull request #361 from CosmWasm/getAccount-query
Add StargateClient.getAccount
This commit is contained in:
commit
fcd917d2c7
@ -84,7 +84,7 @@ export {
|
||||
uint64ToString,
|
||||
} from "./lcdapi";
|
||||
export { isMsgDelegate, isMsgSend, Msg, MsgDelegate, MsgSend } from "./msgs";
|
||||
export { decodeBech32Pubkey, encodeBech32Pubkey, encodeSecp256k1Pubkey } from "./pubkey";
|
||||
export { decodeAminoPubkey, decodeBech32Pubkey, encodeBech32Pubkey, encodeSecp256k1Pubkey } from "./pubkey";
|
||||
export { findSequenceForSignedTx } from "./sequence";
|
||||
export { encodeSecp256k1Signature, decodeSignature } from "./signature";
|
||||
export { FeeTable, SigningCosmosClient } from "./signingcosmosclient";
|
||||
|
@ -21,9 +21,7 @@ const pubkeyAminoPrefixEd25519 = fromHex("1624de6420");
|
||||
const pubkeyAminoPrefixSr25519 = fromHex("0dfb1005");
|
||||
const pubkeyAminoPrefixLength = pubkeyAminoPrefixSecp256k1.length;
|
||||
|
||||
export function decodeBech32Pubkey(bechEncoded: string): PubKey {
|
||||
const { data } = Bech32.decode(bechEncoded);
|
||||
|
||||
export function decodeAminoPubkey(data: Uint8Array): PubKey {
|
||||
const aminoPrefix = data.slice(0, pubkeyAminoPrefixLength);
|
||||
const rest = data.slice(pubkeyAminoPrefixLength);
|
||||
if (equal(aminoPrefix, pubkeyAminoPrefixSecp256k1)) {
|
||||
@ -55,6 +53,11 @@ export function decodeBech32Pubkey(bechEncoded: string): PubKey {
|
||||
}
|
||||
}
|
||||
|
||||
export function decodeBech32Pubkey(bechEncoded: string): PubKey {
|
||||
const { data } = Bech32.decode(bechEncoded);
|
||||
return decodeAminoPubkey(data);
|
||||
}
|
||||
|
||||
export function encodeBech32Pubkey(pubkey: PubKey, prefix: string): string {
|
||||
let aminoPrefix: Uint8Array;
|
||||
switch (pubkey.type) {
|
||||
|
2
packages/launchpad/types/index.d.ts
vendored
2
packages/launchpad/types/index.d.ts
vendored
@ -82,7 +82,7 @@ export {
|
||||
uint64ToString,
|
||||
} from "./lcdapi";
|
||||
export { isMsgDelegate, isMsgSend, Msg, MsgDelegate, MsgSend } from "./msgs";
|
||||
export { decodeBech32Pubkey, encodeBech32Pubkey, encodeSecp256k1Pubkey } from "./pubkey";
|
||||
export { decodeAminoPubkey, decodeBech32Pubkey, encodeBech32Pubkey, encodeSecp256k1Pubkey } from "./pubkey";
|
||||
export { findSequenceForSignedTx } from "./sequence";
|
||||
export { encodeSecp256k1Signature, decodeSignature } from "./signature";
|
||||
export { FeeTable, SigningCosmosClient } from "./signingcosmosclient";
|
||||
|
1
packages/launchpad/types/pubkey.d.ts
vendored
1
packages/launchpad/types/pubkey.d.ts
vendored
@ -1,4 +1,5 @@
|
||||
import { PubKey } from "./types";
|
||||
export declare function encodeSecp256k1Pubkey(pubkey: Uint8Array): PubKey;
|
||||
export declare function decodeAminoPubkey(data: Uint8Array): PubKey;
|
||||
export declare function decodeBech32Pubkey(bechEncoded: string): PubKey;
|
||||
export declare function encodeBech32Pubkey(pubkey: PubKey, prefix: string): string;
|
||||
|
@ -1,5 +1,7 @@
|
||||
import { assert } from "@cosmjs/utils";
|
||||
|
||||
import { StargateClient } from "./stargateclient";
|
||||
import { nonExistentAddress, pendingWithoutSimapp, simapp, unused } from "./testutils.spec";
|
||||
import { nonExistentAddress, pendingWithoutSimapp, simapp, unused, validator } from "./testutils.spec";
|
||||
|
||||
describe("StargateClient", () => {
|
||||
describe("connect", () => {
|
||||
@ -11,14 +13,71 @@ describe("StargateClient", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("getAccount", () => {
|
||||
it("works for unused account", async () => {
|
||||
pendingWithoutSimapp();
|
||||
const client = await StargateClient.connect(simapp.tendermintUrl);
|
||||
|
||||
const account = await client.getAccount(unused.address);
|
||||
assert(account);
|
||||
expect(account).toEqual({
|
||||
address: unused.address,
|
||||
pubkey: null,
|
||||
accountNumber: unused.accountNumber,
|
||||
sequence: unused.sequence,
|
||||
});
|
||||
|
||||
client.disconnect();
|
||||
});
|
||||
|
||||
it("works for account with pubkey and non-zero sequence", async () => {
|
||||
pendingWithoutSimapp();
|
||||
const client = await StargateClient.connect(simapp.tendermintUrl);
|
||||
|
||||
const account = await client.getAccount(validator.address);
|
||||
assert(account);
|
||||
expect(account).toEqual({
|
||||
address: validator.address,
|
||||
pubkey: validator.pubkey,
|
||||
accountNumber: validator.accountNumber,
|
||||
sequence: validator.sequence,
|
||||
});
|
||||
|
||||
client.disconnect();
|
||||
});
|
||||
|
||||
it("returns null for non-existent address", async () => {
|
||||
pendingWithoutSimapp();
|
||||
const client = await StargateClient.connect(simapp.tendermintUrl);
|
||||
|
||||
const account = await client.getAccount(nonExistentAddress);
|
||||
expect(account).toBeNull();
|
||||
|
||||
client.disconnect();
|
||||
});
|
||||
});
|
||||
|
||||
describe("getSequence", () => {
|
||||
it("works for unused account", async () => {
|
||||
pendingWithoutSimapp();
|
||||
const client = await StargateClient.connect(simapp.tendermintUrl);
|
||||
|
||||
const { accountNumber, sequence } = await client.getSequence(unused.address);
|
||||
expect(accountNumber).toEqual(unused.accountNumber);
|
||||
expect(sequence).toEqual(unused.sequence);
|
||||
const account = await client.getSequence(unused.address);
|
||||
assert(account);
|
||||
expect(account).toEqual({
|
||||
accountNumber: unused.accountNumber,
|
||||
sequence: unused.sequence,
|
||||
});
|
||||
|
||||
client.disconnect();
|
||||
});
|
||||
|
||||
it("returns null for non-existent address", async () => {
|
||||
pendingWithoutSimapp();
|
||||
const client = await StargateClient.connect(simapp.tendermintUrl);
|
||||
|
||||
const account = await client.getSequence(nonExistentAddress);
|
||||
expect(account).toBeNull();
|
||||
|
||||
client.disconnect();
|
||||
});
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
import { Bech32, toAscii, toHex } from "@cosmjs/encoding";
|
||||
import { Coin } from "@cosmjs/launchpad";
|
||||
import { Coin, decodeAminoPubkey, PubKey } from "@cosmjs/launchpad";
|
||||
import { Uint64 } from "@cosmjs/math";
|
||||
import { decodeAny } from "@cosmjs/proto-signing";
|
||||
import { Client as TendermintClient } from "@cosmjs/tendermint-rpc";
|
||||
@ -9,7 +9,15 @@ import Long from "long";
|
||||
|
||||
import { cosmos } from "./generated/codecimpl";
|
||||
|
||||
export interface GetSequenceResult {
|
||||
export interface Account {
|
||||
/** Bech32 account address */
|
||||
readonly address: string;
|
||||
readonly pubkey: PubKey | null;
|
||||
readonly accountNumber: number;
|
||||
readonly sequence: number;
|
||||
}
|
||||
|
||||
export interface SequenceResponse {
|
||||
readonly accountNumber: number;
|
||||
readonly sequence: number;
|
||||
}
|
||||
@ -18,6 +26,18 @@ function uint64FromProto(input: number | Long): Uint64 {
|
||||
return Uint64.fromString(input.toString());
|
||||
}
|
||||
|
||||
function decodeBaseAccount(data: Uint8Array, prefix: string): Account {
|
||||
const { address, pubKey, accountNumber, sequence } = cosmos.auth.BaseAccount.decode(data);
|
||||
// Pubkey is still Amino-encoded in BaseAccount (https://github.com/cosmos/cosmos-sdk/issues/6886)
|
||||
const pubkey = pubKey.length ? decodeAminoPubkey(pubKey) : null;
|
||||
return {
|
||||
address: Bech32.encode(prefix, address),
|
||||
pubkey: pubkey,
|
||||
accountNumber: uint64FromProto(accountNumber).toNumber(),
|
||||
sequence: uint64FromProto(sequence).toNumber(),
|
||||
};
|
||||
}
|
||||
|
||||
function coinFromProto(input: cosmos.ICoin): Coin {
|
||||
assertDefined(input.amount);
|
||||
assertDefined(input.denom);
|
||||
@ -41,23 +61,33 @@ export class StargateClient {
|
||||
this.tmClient = tmClient;
|
||||
}
|
||||
|
||||
public async getSequence(address: string): Promise<GetSequenceResult> {
|
||||
const binAddress = Bech32.decode(address).data;
|
||||
public async getAccount(searchAddress: string): Promise<Account | null> {
|
||||
const { prefix, data: binAddress } = Bech32.decode(searchAddress);
|
||||
// https://github.com/cosmos/cosmos-sdk/blob/8cab43c8120fec5200c3459cbf4a92017bb6f287/x/auth/types/keys.go#L29-L32
|
||||
const accountKey = Uint8Array.from([0x01, ...binAddress]);
|
||||
const responseData = await this.queryVerified("acc", accountKey);
|
||||
|
||||
if (responseData.length === 0) return null;
|
||||
|
||||
const { typeUrl, value } = decodeAny(responseData);
|
||||
switch (typeUrl) {
|
||||
case "/cosmos.auth.BaseAccount": {
|
||||
const { accountNumber, sequence } = cosmos.auth.BaseAccount.decode(value);
|
||||
return {
|
||||
accountNumber: uint64FromProto(accountNumber).toNumber(),
|
||||
sequence: uint64FromProto(sequence).toNumber(),
|
||||
};
|
||||
return decodeBaseAccount(value, prefix);
|
||||
}
|
||||
default:
|
||||
throw new Error(`Unsupported type: ${typeUrl}`);
|
||||
throw new Error(`Unsupported type: '${typeUrl}'`);
|
||||
}
|
||||
}
|
||||
|
||||
public async getSequence(address: string): Promise<SequenceResponse | null> {
|
||||
const account = await this.getAccount(address);
|
||||
if (account) {
|
||||
return {
|
||||
accountNumber: account.accountNumber,
|
||||
sequence: account.sequence,
|
||||
};
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,4 +24,16 @@ export const unused = {
|
||||
balanceFee: "1000000000", // 1000 COSM
|
||||
};
|
||||
|
||||
export const validator = {
|
||||
/** From first gentx's auth_info.signer_infos in scripts/simapp/template/.simapp/config/genesis.json */
|
||||
pubkey: {
|
||||
type: "tendermint/PubKeySecp256k1",
|
||||
value: "AnFadRAdh6Fl7robHe8jywDMKSWQQjB7SlpoqGsX9Ghw",
|
||||
},
|
||||
/** delegator_address from /cosmos.staking.MsgCreateValidator in scripts/simapp/template/.simapp/config/genesis.json */
|
||||
address: "cosmos12gm9sa666hywxu9nzzmp7hyl7a55hvg769w2kz",
|
||||
accountNumber: 0,
|
||||
sequence: 1,
|
||||
};
|
||||
|
||||
export const nonExistentAddress = "cosmos1p79apjaufyphcmsn4g07cynqf0wyjuezqu84hd";
|
||||
|
14
packages/stargate/types/stargateclient.d.ts
vendored
14
packages/stargate/types/stargateclient.d.ts
vendored
@ -1,5 +1,12 @@
|
||||
import { Coin } from "@cosmjs/launchpad";
|
||||
export interface GetSequenceResult {
|
||||
import { Coin, PubKey } from "@cosmjs/launchpad";
|
||||
export interface Account {
|
||||
/** Bech32 account address */
|
||||
readonly address: string;
|
||||
readonly pubkey: PubKey | null;
|
||||
readonly accountNumber: number;
|
||||
readonly sequence: number;
|
||||
}
|
||||
export interface SequenceResponse {
|
||||
readonly accountNumber: number;
|
||||
readonly sequence: number;
|
||||
}
|
||||
@ -7,7 +14,8 @@ export declare class StargateClient {
|
||||
private readonly tmClient;
|
||||
static connect(endpoint: string): Promise<StargateClient>;
|
||||
private constructor();
|
||||
getSequence(address: string): Promise<GetSequenceResult>;
|
||||
getAccount(searchAddress: string): Promise<Account | null>;
|
||||
getSequence(address: string): Promise<SequenceResponse | null>;
|
||||
getBalance(address: string, searchDenom: string): Promise<Coin | null>;
|
||||
/**
|
||||
* Queries all balances for all denoms that belong to this address.
|
||||
|
Loading…
x
Reference in New Issue
Block a user