diff --git a/packages/stargate/src/queries/auth.spec.ts b/packages/stargate/src/queries/auth.spec.ts index 3288cae5..ad9ad3d6 100644 --- a/packages/stargate/src/queries/auth.spec.ts +++ b/packages/stargate/src/queries/auth.spec.ts @@ -1,12 +1,16 @@ -import { encodeAminoPubkey } from "@cosmjs/launchpad"; +/* eslint-disable @typescript-eslint/naming-convention */ +import { fromBase64 } from "@cosmjs/encoding"; import { Client as TendermintClient } from "@cosmjs/tendermint-rpc"; import { assert } from "@cosmjs/utils"; import Long from "long"; +import { cosmos, google } from "../codec"; import { nonExistentAddress, pendingWithoutSimapp, simapp, unused, validator } from "../testutils.spec"; import { AuthExtension, setupAuthExtension } from "./auth"; import { QueryClient } from "./queryclient"; -import { toAccAddress } from "./utils"; + +const { PubKey } = cosmos.crypto.secp256k1; +const { Any } = google.protobuf; async function makeClientWithAuth(rpcUrl: string): Promise<[QueryClient & AuthExtension, TendermintClient]> { const tmClient = await TendermintClient.connect(rpcUrl); @@ -18,12 +22,11 @@ describe("AuthExtension", () => { it("works for unused account", async () => { pendingWithoutSimapp(); const [client, tmClient] = await makeClientWithAuth(simapp.tendermintUrl); - const account = await client.auth.account(unused.address); assert(account); expect(account).toEqual({ - address: toAccAddress(unused.address), + address: unused.address, // pubKey not set accountNumber: Long.fromNumber(unused.accountNumber, true), // sequence not set @@ -35,12 +38,19 @@ describe("AuthExtension", () => { it("works for account with pubkey and non-zero sequence", async () => { pendingWithoutSimapp(); const [client, tmClient] = await makeClientWithAuth(simapp.tendermintUrl); - const account = await client.auth.account(validator.address); assert(account); + + const pubkey = PubKey.create({ + key: fromBase64(validator.pubkey.value), + }); + const pubkeyAny = Any.create({ + type_url: "/cosmos.crypto.secp256k1.PubKey", + value: Uint8Array.from(PubKey.encode(pubkey).finish()), + }); expect(account).toEqual({ - address: toAccAddress(validator.address), - pubKey: encodeAminoPubkey(validator.pubkey), + address: validator.address, + pubKey: pubkeyAny, // accountNumber not set sequence: Long.fromNumber(validator.sequence, true), }); @@ -51,8 +61,8 @@ describe("AuthExtension", () => { it("returns null for non-existent address", async () => { pendingWithoutSimapp(); const [client, tmClient] = await makeClientWithAuth(simapp.tendermintUrl); - const account = await client.auth.account(nonExistentAddress); + expect(account).toBeNull(); tmClient.disconnect(); @@ -64,11 +74,11 @@ describe("AuthExtension", () => { it("works for unused account", async () => { pendingWithoutSimapp(); const [client, tmClient] = await makeClientWithAuth(simapp.tendermintUrl); - const account = await client.auth.unverified.account(unused.address); assert(account); + expect(account).toEqual({ - address: toAccAddress(unused.address), + address: unused.address, // pubKey not set accountNumber: Long.fromNumber(unused.accountNumber, true), // sequence not set @@ -80,12 +90,19 @@ describe("AuthExtension", () => { it("works for account with pubkey and non-zero sequence", async () => { pendingWithoutSimapp(); const [client, tmClient] = await makeClientWithAuth(simapp.tendermintUrl); - const account = await client.auth.unverified.account(validator.address); assert(account); + + const pubkey = PubKey.create({ + key: fromBase64(validator.pubkey.value), + }); + const pubkeyAny = Any.create({ + type_url: "/cosmos.crypto.secp256k1.PubKey", + value: Uint8Array.from(PubKey.encode(pubkey).finish()), + }); expect(account).toEqual({ - address: toAccAddress(validator.address), - pubKey: encodeAminoPubkey(validator.pubkey), + address: validator.address, + pubKey: pubkeyAny, // accountNumber not set sequence: Long.fromNumber(validator.sequence, true), }); diff --git a/packages/stargate/src/queries/auth.ts b/packages/stargate/src/queries/auth.ts index aeffb54c..ab23cbf0 100644 --- a/packages/stargate/src/queries/auth.ts +++ b/packages/stargate/src/queries/auth.ts @@ -1,14 +1,17 @@ +/* eslint-disable @typescript-eslint/naming-convention */ import { assert } from "@cosmjs/utils"; import { cosmos, google } from "../codec"; import { QueryClient } from "./queryclient"; import { toAccAddress, toObject } from "./utils"; +const { BaseAccount, Query } = cosmos.auth.v1beta1; + export interface AuthExtension { readonly auth: { - readonly account: (address: string) => Promise; + readonly account: (address: string) => Promise; readonly unverified: { - readonly account: (address: string) => Promise; + readonly account: (address: string) => Promise; }; }; } @@ -16,9 +19,9 @@ export interface AuthExtension { export function setupAuthExtension(base: QueryClient): AuthExtension { // Use this service to get easy typed access to query methods // This cannot be used to for proof verification - const queryService = cosmos.auth.Query.create((method: any, requestData, callback) => { + const queryService = Query.create((method: any, requestData, callback) => { // Parts of the path are unavailable, so we hardcode them here. See https://github.com/protobufjs/protobuf.js/issues/1229 - const path = `/cosmos.auth.Query/${method.name}`; + const path = `/cosmos.auth.v1beta1.Query/${method.name}`; base .queryUnverified(path, requestData) .then((response) => callback(null, response)) @@ -34,8 +37,8 @@ export function setupAuthExtension(base: QueryClient): AuthExtension { if (responseData.length === 0) return null; const account = google.protobuf.Any.decode(responseData); switch (account.type_url) { - case "/cosmos.auth.BaseAccount": { - return toObject(cosmos.auth.BaseAccount.decode(account.value)); + case "/cosmos.auth.v1beta1.BaseAccount": { + return toObject(BaseAccount.decode(account.value)); } default: throw new Error(`Unsupported type: '${account.type_url}'`); @@ -43,12 +46,12 @@ export function setupAuthExtension(base: QueryClient): AuthExtension { }, unverified: { account: async (address: string) => { - const { account } = await queryService.account({ address: toAccAddress(address) }); + const { account } = await queryService.account({ address: address }); if (!account) return null; switch (account.type_url) { - case "/cosmos.auth.BaseAccount": { + case "/cosmos.auth.v1beta1.BaseAccount": { assert(account.value); - return toObject(cosmos.auth.BaseAccount.decode(account.value)); + return toObject(BaseAccount.decode(account.value)); } default: throw new Error(`Unsupported type: '${account.type_url}'`); diff --git a/packages/stargate/src/queries/bank.ts b/packages/stargate/src/queries/bank.ts index 6b85cb8f..8d85da61 100644 --- a/packages/stargate/src/queries/bank.ts +++ b/packages/stargate/src/queries/bank.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/naming-convention */ import { toAscii } from "@cosmjs/encoding"; import { assert } from "@cosmjs/utils"; @@ -5,14 +6,17 @@ import { cosmos } from "../codec"; import { QueryClient } from "./queryclient"; import { toAccAddress, toObject } from "./utils"; +const { Coin } = cosmos.base.v1beta1; +const { Query } = cosmos.bank.v1beta1; + export interface BankExtension { readonly bank: { - readonly balance: (address: string, denom: string) => Promise; + readonly balance: (address: string, denom: string) => Promise; readonly unverified: { - readonly balance: (address: string, denom: string) => Promise; - readonly allBalances: (address: string) => Promise; - readonly totalSupply: () => Promise; - readonly supplyOf: (denom: string) => Promise; + readonly balance: (address: string, denom: string) => Promise; + readonly allBalances: (address: string) => Promise; + readonly totalSupply: () => Promise; + readonly supplyOf: (denom: string) => Promise; }; }; } @@ -20,9 +24,9 @@ export interface BankExtension { export function setupBankExtension(base: QueryClient): BankExtension { // Use this service to get easy typed access to query methods // This cannot be used to for proof verification - const queryService = cosmos.bank.Query.create((method: any, requestData, callback) => { + const queryService = Query.create((method: any, requestData, callback) => { // Parts of the path are unavailable, so we hardcode them here. See https://github.com/protobufjs/protobuf.js/issues/1229 - const path = `/cosmos.bank.Query/${method.name}`; + const path = `/cosmos.bank.v1beta1.Query/${method.name}`; base .queryUnverified(path, requestData) .then((response) => callback(null, response)) @@ -40,16 +44,16 @@ export function setupBankExtension(base: QueryClient): BankExtension { // https://github.com/cosmos/cosmos-sdk/blob/2879c0702c87dc9dd828a8c42b9224dc054e28ad/store/prefix/store.go#L37-L43 const key = Uint8Array.from([...toAscii("balances"), ...toAccAddress(address), ...toAscii(denom)]); const responseData = await base.queryVerified("bank", key); - return responseData.length ? toObject(cosmos.Coin.decode(responseData)) : null; + return responseData.length ? toObject(Coin.decode(responseData)) : null; }, unverified: { balance: async (address: string, denom: string) => { - const { balance } = await queryService.balance({ address: toAccAddress(address), denom: denom }); + const { balance } = await queryService.balance({ address: address, denom: denom }); assert(balance); return toObject(balance); }, allBalances: async (address: string) => { - const { balances } = await queryService.allBalances({ address: toAccAddress(address) }); + const { balances } = await queryService.allBalances({ address: address }); return balances.map(toObject); }, totalSupply: async () => { diff --git a/packages/stargate/src/queries/ibc.spec.ts b/packages/stargate/src/queries/ibc.spec.ts index 53585efc..7c735ea6 100644 --- a/packages/stargate/src/queries/ibc.spec.ts +++ b/packages/stargate/src/queries/ibc.spec.ts @@ -88,13 +88,26 @@ describe("IbcExtension", () => { }); }); - describe("unrelayedPackets", () => { + describe("unreceivedPackets", () => { it("can be called", async () => { pending("Fails with 'Query failed with (1): internal'. Make it work."); pendingWithoutSimapp(); const [client, tmClient] = await makeClientWithIbc(simapp.tendermintUrl); - const response = await client.ibc.unverified.unrelayedPackets("foo", "bar", [0, 1], true); + const response = await client.ibc.unverified.unreceivedPackets("foo", "bar", [0, 1]); + expect(response).toBeTruthy(); // TODO: implement checks + + tmClient.disconnect(); + }); + }); + + describe("unrelayedAcks", () => { + it("can be called", async () => { + pending("Fails with 'Query failed with (1): internal'. Make it work."); + pendingWithoutSimapp(); + const [client, tmClient] = await makeClientWithIbc(simapp.tendermintUrl); + + const response = await client.ibc.unverified.unrelayedAcks("foo", "bar", [0, 1]); expect(response).toBeTruthy(); // TODO: implement checks tmClient.disconnect(); diff --git a/packages/stargate/src/queries/ibc.ts b/packages/stargate/src/queries/ibc.ts index aaa843e7..ccd9c11a 100644 --- a/packages/stargate/src/queries/ibc.ts +++ b/packages/stargate/src/queries/ibc.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/naming-convention */ import { toAscii } from "@cosmjs/encoding"; import { Uint64 } from "@cosmjs/math"; import Long from "long"; @@ -6,9 +7,12 @@ import { ibc } from "../codec"; import { QueryClient } from "./queryclient"; import { toObject } from "./utils"; +const { Query: ChannelQuery } = ibc.core.channel.v1; +const { Query: ConnectionQuery } = ibc.core.connection.v1; + export interface IbcExtension { readonly ibc: { - readonly channel: (portId: string, channelId: string) => Promise; + readonly channel: (portId: string, channelId: string) => Promise; readonly packetCommitment: (portId: string, channelId: string, sequence: number) => Promise; readonly packetAcknowledgement: ( portId: string, @@ -17,44 +21,51 @@ export interface IbcExtension { ) => Promise; readonly nextSequenceReceive: (portId: string, channelId: string) => Promise; readonly unverified: { - // Queries for ibc.channel - readonly channel: (portId: string, channelId: string) => Promise; - readonly channels: () => Promise; + // Queries for ibc.core.channel.v1 + readonly channel: ( + portId: string, + channelId: string, + ) => Promise; + readonly channels: () => Promise; readonly connectionChannels: ( connection: string, - ) => Promise; + ) => Promise; readonly packetCommitment: ( portId: string, channelId: string, sequence: number, - ) => Promise; + ) => Promise; readonly packetCommitments: ( portId: string, channelId: string, - ) => Promise; + ) => Promise; readonly packetAcknowledgement: ( portId: string, channelId: string, sequence: number, - ) => Promise; - readonly unrelayedPackets: ( + ) => Promise; + readonly unreceivedPackets: ( portId: string, channelId: string, packetCommitmentSequences: readonly number[], - acknowledgements: boolean, - ) => Promise; + ) => Promise; + readonly unrelayedAcks: ( + portId: string, + channelId: string, + packetCommitmentSequences: readonly number[], + ) => Promise; readonly nextSequenceReceive: ( portId: string, channelId: string, - ) => Promise; + ) => Promise; - // Queries for ibc.connection + // Queries for ibc.core.connection.v1 - readonly connection: (connectionId: string) => Promise; - readonly connections: () => Promise; + readonly connection: (connectionId: string) => Promise; + readonly connections: () => Promise; readonly clientConnections: ( clientId: string, - ) => Promise; + ) => Promise; }; }; } @@ -63,18 +74,18 @@ export function setupIbcExtension(base: QueryClient): IbcExtension { // Use this service to get easy typed access to query methods // This cannot be used to for proof verification - const channelQuerySerice = ibc.channel.Query.create((method: any, requestData, callback) => { + const channelQuerySerice = ChannelQuery.create((method: any, requestData, callback) => { // Parts of the path are unavailable, so we hardcode them here. See https://github.com/protobufjs/protobuf.js/issues/1229 - const path = `/ibc.channel.Query/${method.name}`; + const path = `/ibc.core.channel.v1.Query/${method.name}`; base .queryUnverified(path, requestData) .then((response) => callback(null, response)) .catch((error) => callback(error)); }); - const connectionQuerySerice = ibc.connection.Query.create((method: any, requestData, callback) => { + const connectionQuerySerice = ConnectionQuery.create((method: any, requestData, callback) => { // Parts of the path are unavailable, so we hardcode them here. See https://github.com/protobufjs/protobuf.js/issues/1229 - const path = `/ibc.connection.Query/${method.name}`; + const path = `/ibc.core.connection.v1.Query/${method.name}`; base .queryUnverified(path, requestData) .then((response) => callback(null, response)) @@ -88,7 +99,7 @@ export function setupIbcExtension(base: QueryClient): IbcExtension { // key: https://github.com/cosmos/cosmos-sdk/blob/ef0a7344af345882729598bc2958a21143930a6b/x/ibc/24-host/keys.go#L117-L120 const key = toAscii(`channelEnds/ports/${portId}/channels/${channelId}`); const responseData = await base.queryVerified("ibc", key); - return responseData.length ? toObject(ibc.channel.Channel.decode(responseData)) : null; + return responseData.length ? toObject(ibc.core.channel.v1.Channel.decode(responseData)) : null; }, packetCommitment: async (portId: string, channelId: string, sequence: number) => { // keeper: https://github.com/cosmos/cosmos-sdk/blob/3bafd8255a502e5a9cee07391cf8261538245dfd/x/ibc/04-channel/keeper/keeper.go#L128-L133 @@ -115,7 +126,7 @@ export function setupIbcExtension(base: QueryClient): IbcExtension { }, unverified: { - // Queries for ibc.channel + // Queries for ibc.core.channel.v1 channel: async (portId: string, channelId: string) => { const response = await channelQuerySerice.channel({ portId: portId, channelId: channelId }); return toObject(response); @@ -151,17 +162,27 @@ export function setupIbcExtension(base: QueryClient): IbcExtension { }); return toObject(response); }, - unrelayedPackets: async ( + unreceivedPackets: async ( portId: string, channelId: string, packetCommitmentSequences: readonly number[], - acknowledgements: boolean, ) => { - const response = await channelQuerySerice.unrelayedPackets({ + const response = await channelQuerySerice.unreceivedPackets({ + portId: portId, + channelId: channelId, + packetCommitmentSequences: packetCommitmentSequences.map((s) => Long.fromNumber(s)), + }); + return toObject(response); + }, + unrelayedAcks: async ( + portId: string, + channelId: string, + packetCommitmentSequences: readonly number[], + ) => { + const response = await channelQuerySerice.unrelayedAcks({ portId: portId, channelId: channelId, packetCommitmentSequences: packetCommitmentSequences.map((s) => Long.fromNumber(s)), - acknowledgements: acknowledgements, }); return toObject(response); }, @@ -173,7 +194,7 @@ export function setupIbcExtension(base: QueryClient): IbcExtension { return toObject(response); }, - // Queries for ibc.connection + // Queries for ibc.core.connection.v1 connection: async (connectionId: string) => { const response = await connectionQuerySerice.connection({ connectionId: connectionId }); diff --git a/packages/stargate/src/queries/queryclient.spec.ts b/packages/stargate/src/queries/queryclient.spec.ts index 3b453bcd..6955c622 100644 --- a/packages/stargate/src/queries/queryclient.spec.ts +++ b/packages/stargate/src/queries/queryclient.spec.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/naming-convention */ import { toAscii } from "@cosmjs/encoding"; import { Client as TendermintClient } from "@cosmjs/tendermint-rpc"; @@ -6,6 +7,9 @@ import { nonNegativeIntegerMatcher, pendingWithoutSimapp, simapp, unused } from import { QueryClient } from "./queryclient"; import { toAccAddress } from "./utils"; +const { Coin } = cosmos.base.v1beta1; +const { QueryAllBalancesRequest, QueryAllBalancesResponse } = cosmos.bank.v1beta1; + async function makeClient(rpcUrl: string): Promise<[QueryClient, TendermintClient]> { const tmClient = await TendermintClient.connect(rpcUrl); return [QueryClient.withExtensions(tmClient), tmClient]; @@ -23,7 +27,7 @@ describe("QueryClient", () => { ...toAscii(simapp.denomFee), ]); const data = await client.queryVerified("bank", key); - const response = cosmos.Coin.decode(data); + const response = Coin.decode(data); expect(response.amount).toMatch(nonNegativeIntegerMatcher); expect(response.denom).toEqual(simapp.denomFee); @@ -40,7 +44,7 @@ describe("QueryClient", () => { ...toAscii(simapp.denomFee), ]); const data = await client.queryVerified("bank", key); - const response = cosmos.Coin.decode(data); + const response = Coin.decode(data); expect(response.amount).toMatch(nonNegativeIntegerMatcher); expect(response.denom).toEqual(simapp.denomFee); @@ -54,10 +58,10 @@ describe("QueryClient", () => { const [client, tmClient] = await makeClient(simapp.tendermintUrlWs); const requestData = Uint8Array.from( - cosmos.bank.QueryAllBalancesRequest.encode({ address: toAccAddress(unused.address) }).finish(), + QueryAllBalancesRequest.encode({ address: unused.address }).finish(), ); - const data = await client.queryUnverified(`/cosmos.bank.Query/AllBalances`, requestData); - const response = cosmos.bank.QueryAllBalancesResponse.decode(data); + const data = await client.queryUnverified(`/cosmos.bank.v1beta1.Query/AllBalances`, requestData); + const response = QueryAllBalancesResponse.decode(data); expect(response.balances.length).toEqual(2); tmClient.disconnect(); @@ -68,10 +72,10 @@ describe("QueryClient", () => { const [client, tmClient] = await makeClient(simapp.tendermintUrlHttp); const requestData = Uint8Array.from( - cosmos.bank.QueryAllBalancesRequest.encode({ address: toAccAddress(unused.address) }).finish(), + QueryAllBalancesRequest.encode({ address: unused.address }).finish(), ); - const data = await client.queryUnverified(`/cosmos.bank.Query/AllBalances`, requestData); - const response = cosmos.bank.QueryAllBalancesResponse.decode(data); + const data = await client.queryUnverified(`/cosmos.bank.v1beta1.Query/AllBalances`, requestData); + const response = QueryAllBalancesResponse.decode(data); expect(response.balances.length).toEqual(2); tmClient.disconnect(); diff --git a/packages/stargate/src/stargateclient.searchtx.spec.ts b/packages/stargate/src/stargateclient.searchtx.spec.ts index b3850f30..97dca3a4 100644 --- a/packages/stargate/src/stargateclient.searchtx.spec.ts +++ b/packages/stargate/src/stargateclient.searchtx.spec.ts @@ -1,10 +1,10 @@ /* eslint-disable @typescript-eslint/naming-convention */ -import { Bech32, fromBase64 } from "@cosmjs/encoding"; +import { fromBase64 } from "@cosmjs/encoding"; import { Coin, coins } from "@cosmjs/launchpad"; import { DirectSecp256k1Wallet, makeAuthInfo, makeSignBytes, Registry } from "@cosmjs/proto-signing"; import { assert, sleep } from "@cosmjs/utils"; -import { cosmos } from "./codec"; +import { cosmos, google } from "./codec"; import { BroadcastTxResponse, isBroadcastTxFailure, @@ -13,8 +13,9 @@ import { } from "./stargateclient"; import { faucet, makeRandomAddress, pendingWithoutSimapp, simapp, simappEnabled } from "./testutils.spec"; -const { AuthInfo, Tx, TxBody } = cosmos.tx; -const { PublicKey } = cosmos.crypto; +const { TxRaw } = cosmos.tx.v1beta1; +const { PubKey } = cosmos.crypto.secp256k1; +const { Any } = google.protobuf; interface TestTxSend { readonly sender: string; @@ -36,16 +37,20 @@ async function sendTokens( readonly tx: Uint8Array; }> { const [{ address: walletAddress, pubkey: pubkeyBytes }] = await wallet.getAccounts(); - const publicKey = PublicKey.create({ secp256k1: pubkeyBytes }); + const pubkey = PubKey.create({ key: pubkeyBytes }); + const pubkeyAny = Any.create({ + type_url: "/cosmos.crypto.secp256k1.PubKey", + value: PubKey.encode(pubkey).finish(), + }); const txBodyFields = { - typeUrl: "/cosmos.tx.TxBody", + typeUrl: "/cosmos.tx.v1beta1.TxBody", value: { messages: [ { - typeUrl: "/cosmos.bank.MsgSend", + typeUrl: "/cosmos.bank.v1beta1.MsgSend", value: { - fromAddress: Bech32.decode(walletAddress).data, - toAddress: Bech32.decode(recipient).data, + fromAddress: walletAddress, + toAddress: recipient, amount: amount, }, }, @@ -54,20 +59,25 @@ async function sendTokens( }, }; const txBodyBytes = registry.encode(txBodyFields); - const txBody = TxBody.decode(txBodyBytes); - const authInfoBytes = makeAuthInfo([publicKey], 200000); - const { accountNumber, sequence } = (await client.getSequence(walletAddress))!; + const feeAmount = [ + { + amount: "2000", + denom: "ucosm", + }, + ]; + const gasLimit = 200000; + const authInfoBytes = makeAuthInfo([pubkeyAny], feeAmount, gasLimit, sequence); + const chainId = await client.getChainId(); - const signDocBytes = makeSignBytes(txBodyBytes, authInfoBytes, chainId, accountNumber, sequence); + const signDocBytes = makeSignBytes(txBodyBytes, authInfoBytes, chainId, accountNumber); const signature = await wallet.sign(walletAddress, signDocBytes); - // TODO: Why is this not a TxRaw? https://github.com/CosmWasm/cosmjs/issues/383 - const txRaw = Tx.create({ - body: txBody, - authInfo: AuthInfo.decode(authInfoBytes), + const txRaw = TxRaw.create({ + bodyBytes: txBodyBytes, + authInfoBytes: authInfoBytes, signatures: [fromBase64(signature.signature)], }); - const txRawBytes = Uint8Array.from(Tx.encode(txRaw).finish()); + const txRawBytes = Uint8Array.from(TxRaw.encode(txRaw).finish()); const broadcastResponse = await client.broadcastTx(txRawBytes); return { broadcastResponse: broadcastResponse, diff --git a/packages/stargate/src/stargateclient.spec.ts b/packages/stargate/src/stargateclient.spec.ts index 6005ee4d..f3cf719c 100644 --- a/packages/stargate/src/stargateclient.spec.ts +++ b/packages/stargate/src/stargateclient.spec.ts @@ -1,14 +1,14 @@ /* eslint-disable @typescript-eslint/naming-convention */ -import { Bech32, fromBase64 } from "@cosmjs/encoding"; +import { fromBase64 } from "@cosmjs/encoding"; import { DirectSecp256k1Wallet, makeAuthInfo, makeSignBytes, Registry } from "@cosmjs/proto-signing"; import { assert, sleep } from "@cosmjs/utils"; import { ReadonlyDate } from "readonly-date"; -import { cosmos } from "./codec"; +import { cosmos, google } from "./codec"; import { assertIsBroadcastTxSuccess, PrivateStargateClient, StargateClient } from "./stargateclient"; import { faucet, - makeRandomAddressBytes, + makeRandomAddress, nonExistentAddress, pendingWithoutSimapp, simapp, @@ -17,8 +17,9 @@ import { validator, } from "./testutils.spec"; -const { AuthInfo, Tx, TxBody } = cosmos.tx; -const { PublicKey } = cosmos.crypto; +const { TxRaw } = cosmos.tx.v1beta1; +const { PubKey } = cosmos.crypto.secp256k1; +const { Any } = google.protobuf; describe("StargateClient", () => { describe("connect", () => { @@ -253,17 +254,21 @@ describe("StargateClient", () => { const client = await StargateClient.connect(simapp.tendermintUrl); const wallet = await DirectSecp256k1Wallet.fromMnemonic(faucet.mnemonic); const [{ address, pubkey: pubkeyBytes }] = await wallet.getAccounts(); - const publicKey = PublicKey.create({ secp256k1: pubkeyBytes }); + const pubkey = PubKey.create({ key: pubkeyBytes }); + const pubkeyAny = Any.create({ + type_url: "/cosmos.crypto.secp256k1.PubKey", + value: PubKey.encode(pubkey).finish(), + }); const registry = new Registry(); const txBodyFields = { - typeUrl: "/cosmos.tx.TxBody", + typeUrl: "/cosmos.tx.v1beta1.TxBody", value: { messages: [ { - typeUrl: "/cosmos.bank.MsgSend", + typeUrl: "/cosmos.bank.v1beta1.MsgSend", value: { - fromAddress: Bech32.decode(address).data, - toAddress: makeRandomAddressBytes(), + fromAddress: address, + toAddress: makeRandomAddress(), amount: [ { denom: "ucosm", @@ -276,20 +281,25 @@ describe("StargateClient", () => { }, }; const txBodyBytes = registry.encode(txBodyFields); - const txBody = TxBody.decode(txBodyBytes); - const authInfoBytes = makeAuthInfo([publicKey], 200000); + const { accountNumber, sequence } = (await client.getSequence(address))!; + const feeAmount = [ + { + amount: "2000", + denom: "ucosm", + }, + ]; + const gasLimit = 200000; + const authInfoBytes = makeAuthInfo([pubkeyAny], feeAmount, gasLimit, sequence); const chainId = await client.getChainId(); - const { accountNumber, sequence } = (await client.getSequence(address))!; - const signDocBytes = makeSignBytes(txBodyBytes, authInfoBytes, chainId, accountNumber, sequence); + const signDocBytes = makeSignBytes(txBodyBytes, authInfoBytes, chainId, accountNumber); const signature = await wallet.sign(address, signDocBytes); - // TODO: Why is this not a TxRaw? https://github.com/CosmWasm/cosmjs/issues/383 - const txRaw = Tx.create({ - body: txBody, - authInfo: AuthInfo.decode(authInfoBytes), + const txRaw = TxRaw.create({ + bodyBytes: txBodyBytes, + authInfoBytes: authInfoBytes, signatures: [fromBase64(signature.signature)], }); - const txRawBytes = Uint8Array.from(Tx.encode(txRaw).finish()); + const txRawBytes = Uint8Array.from(TxRaw.encode(txRaw).finish()); const txResult = await client.broadcastTx(txRawBytes); assertIsBroadcastTxSuccess(txResult); diff --git a/packages/stargate/src/stargateclient.ts b/packages/stargate/src/stargateclient.ts index 447a87bf..b55360c7 100644 --- a/packages/stargate/src/stargateclient.ts +++ b/packages/stargate/src/stargateclient.ts @@ -1,9 +1,9 @@ /* eslint-disable @typescript-eslint/naming-convention */ -import { Bech32, toHex } from "@cosmjs/encoding"; +import { toHex } from "@cosmjs/encoding"; import { Block, Coin, - decodeAminoPubkey, + encodeSecp256k1Pubkey, isSearchByHeightQuery, isSearchByIdQuery, PubKey, @@ -15,7 +15,7 @@ import { broadcastTxCommitSuccess, Client as TendermintClient, QueryString } fro import { assert, assertDefined } from "@cosmjs/utils"; import Long from "long"; -import { cosmos } from "./codec"; +import { cosmos, google } from "./codec"; import { AuthExtension, BankExtension, QueryClient, setupAuthExtension, setupBankExtension } from "./queries"; /** A transaction that is indexed as part of the transaction history */ @@ -85,20 +85,34 @@ function uint64FromProto(input: number | Long | null | undefined): Uint64 { return Uint64.fromString(input.toString()); } -function accountFromProto(input: cosmos.auth.IBaseAccount, prefix: string): Account { +function decodePubkey(pubkey?: google.protobuf.IAny | null): PubKey | null { + if (!pubkey || !pubkey.value) { + return null; + } + + switch (pubkey.type_url) { + case "/cosmos.crypto.secp256k1.PubKey": { + const { key } = cosmos.crypto.secp256k1.PubKey.decode(pubkey.value); + return encodeSecp256k1Pubkey(key); + } + default: + throw new Error("Unknown pubkey type"); + } +} + +function accountFromProto(input: cosmos.auth.v1beta1.IBaseAccount): Account { const { address, pubKey, accountNumber, sequence } = input; - // Pubkey is still Amino-encoded in BaseAccount (https://github.com/cosmos/cosmos-sdk/issues/6886) - const pubkey = pubKey && pubKey.length ? decodeAminoPubkey(pubKey) : null; + const pubkey = decodePubkey(pubKey); assert(address); return { - address: Bech32.encode(prefix, address), + address: address, pubkey: pubkey, accountNumber: uint64FromProto(accountNumber).toNumber(), sequence: uint64FromProto(sequence).toNumber(), }; } -function coinFromProto(input: cosmos.ICoin): Coin { +function coinFromProto(input: cosmos.base.v1beta1.ICoin): Coin { assertDefined(input.amount); assertDefined(input.denom); assert(input.amount !== null); @@ -146,10 +160,8 @@ export class StargateClient { } public async getAccount(searchAddress: string): Promise { - const { prefix } = Bech32.decode(searchAddress); - const account = await this.queryClient.auth.account(searchAddress); - return account ? accountFromProto(account, prefix) : null; + return account ? accountFromProto(account) : null; } public async getSequence(address: string): Promise { diff --git a/packages/stargate/types/queries/auth.d.ts b/packages/stargate/types/queries/auth.d.ts index 1fd1d65c..cbdd3756 100644 --- a/packages/stargate/types/queries/auth.d.ts +++ b/packages/stargate/types/queries/auth.d.ts @@ -2,9 +2,9 @@ import { cosmos } from "../codec"; import { QueryClient } from "./queryclient"; export interface AuthExtension { readonly auth: { - readonly account: (address: string) => Promise; + readonly account: (address: string) => Promise; readonly unverified: { - readonly account: (address: string) => Promise; + readonly account: (address: string) => Promise; }; }; } diff --git a/packages/stargate/types/queries/bank.d.ts b/packages/stargate/types/queries/bank.d.ts index ad67fe12..250a74e5 100644 --- a/packages/stargate/types/queries/bank.d.ts +++ b/packages/stargate/types/queries/bank.d.ts @@ -2,12 +2,12 @@ import { cosmos } from "../codec"; import { QueryClient } from "./queryclient"; export interface BankExtension { readonly bank: { - readonly balance: (address: string, denom: string) => Promise; + readonly balance: (address: string, denom: string) => Promise; readonly unverified: { - readonly balance: (address: string, denom: string) => Promise; - readonly allBalances: (address: string) => Promise; - readonly totalSupply: () => Promise; - readonly supplyOf: (denom: string) => Promise; + readonly balance: (address: string, denom: string) => Promise; + readonly allBalances: (address: string) => Promise; + readonly totalSupply: () => Promise; + readonly supplyOf: (denom: string) => Promise; }; }; } diff --git a/packages/stargate/types/queries/ibc.d.ts b/packages/stargate/types/queries/ibc.d.ts index 9c5ed4dc..7ab22494 100644 --- a/packages/stargate/types/queries/ibc.d.ts +++ b/packages/stargate/types/queries/ibc.d.ts @@ -2,7 +2,7 @@ import { ibc } from "../codec"; import { QueryClient } from "./queryclient"; export interface IbcExtension { readonly ibc: { - readonly channel: (portId: string, channelId: string) => Promise; + readonly channel: (portId: string, channelId: string) => Promise; readonly packetCommitment: (portId: string, channelId: string, sequence: number) => Promise; readonly packetAcknowledgement: ( portId: string, @@ -11,40 +11,47 @@ export interface IbcExtension { ) => Promise; readonly nextSequenceReceive: (portId: string, channelId: string) => Promise; readonly unverified: { - readonly channel: (portId: string, channelId: string) => Promise; - readonly channels: () => Promise; + readonly channel: ( + portId: string, + channelId: string, + ) => Promise; + readonly channels: () => Promise; readonly connectionChannels: ( connection: string, - ) => Promise; + ) => Promise; readonly packetCommitment: ( portId: string, channelId: string, sequence: number, - ) => Promise; + ) => Promise; readonly packetCommitments: ( portId: string, channelId: string, - ) => Promise; + ) => Promise; readonly packetAcknowledgement: ( portId: string, channelId: string, sequence: number, - ) => Promise; - readonly unrelayedPackets: ( + ) => Promise; + readonly unreceivedPackets: ( portId: string, channelId: string, packetCommitmentSequences: readonly number[], - acknowledgements: boolean, - ) => Promise; + ) => Promise; + readonly unrelayedAcks: ( + portId: string, + channelId: string, + packetCommitmentSequences: readonly number[], + ) => Promise; readonly nextSequenceReceive: ( portId: string, channelId: string, - ) => Promise; - readonly connection: (connectionId: string) => Promise; - readonly connections: () => Promise; + ) => Promise; + readonly connection: (connectionId: string) => Promise; + readonly connections: () => Promise; readonly clientConnections: ( clientId: string, - ) => Promise; + ) => Promise; }; }; }