mirror of
https://github.com/cosmos/cosmjs.git
synced 2025-03-10 13:47:12 +00:00
commit
8eaa3687e5
@ -87,6 +87,8 @@ and this project adheres to
|
||||
- @cosmjs/stargate: Add transfer queries codec, as well as transfer query
|
||||
methods to IBC query extension.
|
||||
- @cosmjs/tendermint-rpc: Export `ValidatorSecp256k1Pubkey` interface.
|
||||
- @cosmjs/proto-signing: Add transaction decoder `decodeTxRaw` for decoding
|
||||
transaction bytes returned by Tendermint (e.g. in `IndexedTx.tx`).
|
||||
|
||||
### Changed
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
import { fromBase64, toBase64 } from "@cosmjs/encoding";
|
||||
import {
|
||||
decodeTxRaw,
|
||||
DirectSecp256k1HdWallet,
|
||||
encodePubkey,
|
||||
makeAuthInfoBytes,
|
||||
@ -16,7 +17,7 @@ import {
|
||||
isBroadcastTxSuccess,
|
||||
isMsgSendEncodeObject,
|
||||
} from "@cosmjs/stargate";
|
||||
import { Tx, TxRaw } from "@cosmjs/stargate/build/codec/cosmos/tx/v1beta1/tx";
|
||||
import { TxRaw } from "@cosmjs/stargate/build/codec/cosmos/tx/v1beta1/tx";
|
||||
import { assert, sleep } from "@cosmjs/utils";
|
||||
|
||||
import { CosmWasmClient } from "./cosmwasmclient";
|
||||
@ -232,8 +233,8 @@ describe("CosmWasmClient.getTx and .searchTx", () => {
|
||||
|
||||
// Check basic structure of all results
|
||||
for (const result of results) {
|
||||
const tx = Tx.decode(result.tx);
|
||||
const filteredMsgs = tx.body!.messages.filter((msg) => {
|
||||
const tx = decodeTxRaw(result.tx);
|
||||
const filteredMsgs = tx.body.messages.filter((msg) => {
|
||||
if (!isMsgSendEncodeObject(msg)) return false;
|
||||
const decoded = registry.decode(msg);
|
||||
return decoded.fromAddress === sendSuccessful?.sender;
|
||||
@ -260,8 +261,8 @@ describe("CosmWasmClient.getTx and .searchTx", () => {
|
||||
|
||||
// Check basic structure of all results
|
||||
for (const result of results) {
|
||||
const tx = Tx.decode(result.tx);
|
||||
const filteredMsgs = tx.body!.messages.filter((msg) => {
|
||||
const tx = decodeTxRaw(result.tx);
|
||||
const filteredMsgs = tx.body.messages.filter((msg) => {
|
||||
if (!isMsgSendEncodeObject(msg)) return false;
|
||||
const decoded = registry.decode(msg);
|
||||
return decoded.toAddress === sendSuccessful?.recipient;
|
||||
@ -346,8 +347,8 @@ describe("CosmWasmClient.getTx and .searchTx", () => {
|
||||
|
||||
// Check basic structure of all results
|
||||
for (const result of results) {
|
||||
const tx = Tx.decode(result.tx);
|
||||
const msg = fromOneElementArray(tx.body!.messages);
|
||||
const tx = decodeTxRaw(result.tx);
|
||||
const msg = fromOneElementArray(tx.body.messages);
|
||||
expect(msg.typeUrl).toEqual("/cosmos.bank.v1beta1.MsgSend");
|
||||
const decoded = registry.decode(msg);
|
||||
expect(decoded.toAddress).toEqual(sendSuccessful.recipient);
|
||||
|
@ -3,7 +3,7 @@ import { Secp256k1HdWallet } from "@cosmjs/amino";
|
||||
import { UploadMeta } from "@cosmjs/cosmwasm-launchpad";
|
||||
import { sha256 } from "@cosmjs/crypto";
|
||||
import { toHex } from "@cosmjs/encoding";
|
||||
import { DirectSecp256k1HdWallet, Registry } from "@cosmjs/proto-signing";
|
||||
import { decodeTxRaw, DirectSecp256k1HdWallet, Registry } from "@cosmjs/proto-signing";
|
||||
import {
|
||||
AminoMsgDelegate,
|
||||
AminoTypes,
|
||||
@ -17,7 +17,7 @@ import {
|
||||
import { DeepPartial, MsgSend } from "@cosmjs/stargate/build/codec/cosmos/bank/v1beta1/tx";
|
||||
import { Coin } from "@cosmjs/stargate/build/codec/cosmos/base/v1beta1/coin";
|
||||
import { MsgDelegate } from "@cosmjs/stargate/build/codec/cosmos/staking/v1beta1/tx";
|
||||
import { AuthInfo, Tx, TxBody, TxRaw } from "@cosmjs/stargate/build/codec/cosmos/tx/v1beta1/tx";
|
||||
import { AuthInfo, TxBody, TxRaw } from "@cosmjs/stargate/build/codec/cosmos/tx/v1beta1/tx";
|
||||
import { assert, sleep } from "@cosmjs/utils";
|
||||
import Long from "long";
|
||||
import pako from "pako";
|
||||
@ -601,11 +601,11 @@ describe("SigningCosmWasmClient", () => {
|
||||
|
||||
const searchResult = await client.getTx(result.transactionHash);
|
||||
assert(searchResult, "Must find transaction");
|
||||
const tx = Tx.decode(searchResult.tx);
|
||||
const tx = decodeTxRaw(searchResult.tx);
|
||||
// From ModifyingDirectSecp256k1HdWallet
|
||||
expect(tx.body!.memo).toEqual("This was modified");
|
||||
expect({ ...tx.authInfo!.fee!.amount[0] }).toEqual(coin(3000, "ucosm"));
|
||||
expect(tx.authInfo!.fee!.gasLimit.toNumber()).toEqual(333333);
|
||||
expect(tx.body.memo).toEqual("This was modified");
|
||||
expect({ ...tx.authInfo.fee!.amount[0] }).toEqual(coin(3000, "ucosm"));
|
||||
expect(tx.authInfo.fee!.gasLimit.toNumber()).toEqual(333333);
|
||||
});
|
||||
});
|
||||
|
||||
@ -830,11 +830,11 @@ describe("SigningCosmWasmClient", () => {
|
||||
|
||||
const searchResult = await client.getTx(result.transactionHash);
|
||||
assert(searchResult, "Must find transaction");
|
||||
const tx = Tx.decode(searchResult.tx);
|
||||
const tx = decodeTxRaw(searchResult.tx);
|
||||
// From ModifyingSecp256k1HdWallet
|
||||
expect(tx.body!.memo).toEqual("This was modified");
|
||||
expect({ ...tx.authInfo!.fee!.amount[0] }).toEqual(coin(3000, "ucosm"));
|
||||
expect(tx.authInfo!.fee!.gasLimit.toNumber()).toEqual(333333);
|
||||
expect(tx.body.memo).toEqual("This was modified");
|
||||
expect({ ...tx.authInfo.fee!.amount[0] }).toEqual(coin(3000, "ucosm"));
|
||||
expect(tx.authInfo.fee!.gasLimit.toNumber()).toEqual(333333);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
19
packages/proto-signing/src/decode.ts
Normal file
19
packages/proto-signing/src/decode.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { AuthInfo, TxBody, TxRaw } from "./codec/cosmos/tx/v1beta1/tx";
|
||||
|
||||
export interface DecodedTxRaw {
|
||||
readonly authInfo: AuthInfo;
|
||||
readonly body: TxBody;
|
||||
readonly signatures: readonly Uint8Array[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a serialized TxRaw (the bytes stored in Tendermint) and decodes it into something usable.
|
||||
*/
|
||||
export function decodeTxRaw(tx: Uint8Array): DecodedTxRaw {
|
||||
const txRaw = TxRaw.decode(tx);
|
||||
return {
|
||||
authInfo: AuthInfo.decode(txRaw.authInfoBytes),
|
||||
body: TxBody.decode(txRaw.bodyBytes),
|
||||
signatures: txRaw.signatures,
|
||||
};
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
// This type happens to be shared between Amino and Direct sign modes
|
||||
export { Coin, coin, coins, parseCoins } from "@cosmjs/amino";
|
||||
|
||||
export { decodeTxRaw, DecodedTxRaw } from "./decode";
|
||||
export {
|
||||
DecodeObject,
|
||||
EncodeObject,
|
||||
|
@ -2,7 +2,8 @@
|
||||
import { fromBase64, fromHex, toHex } from "@cosmjs/encoding";
|
||||
|
||||
import { SignMode } from "./codec/cosmos/tx/signing/v1beta1/signing";
|
||||
import { Tx, TxRaw } from "./codec/cosmos/tx/v1beta1/tx";
|
||||
import { TxRaw } from "./codec/cosmos/tx/v1beta1/tx";
|
||||
import { decodeTxRaw } from "./decode";
|
||||
import { DirectSecp256k1HdWallet } from "./directsecp256k1hdwallet";
|
||||
import { Registry } from "./registry";
|
||||
import { makeSignBytes, makeSignDoc } from "./signing";
|
||||
@ -22,25 +23,23 @@ describe("signing", () => {
|
||||
const prefixedPubkeyBytes = Uint8Array.from([0x0a, pubkeyBytes.length, ...pubkeyBytes]);
|
||||
|
||||
testVectors.forEach(({ outputs: { signedTxBytes } }) => {
|
||||
const parsedTestTx = Tx.decode(fromHex(signedTxBytes));
|
||||
const parsedTestTx = decodeTxRaw(fromHex(signedTxBytes));
|
||||
expect(parsedTestTx.signatures.length).toEqual(1);
|
||||
expect(parsedTestTx.authInfo!.signerInfos.length).toEqual(1);
|
||||
expect(Uint8Array.from(parsedTestTx.authInfo!.signerInfos[0].publicKey!.value ?? [])).toEqual(
|
||||
expect(parsedTestTx.authInfo.signerInfos.length).toEqual(1);
|
||||
expect(Uint8Array.from(parsedTestTx.authInfo.signerInfos[0].publicKey!.value ?? [])).toEqual(
|
||||
prefixedPubkeyBytes,
|
||||
);
|
||||
expect(parsedTestTx.authInfo?.signerInfos![0].modeInfo!.single!.mode).toEqual(
|
||||
SignMode.SIGN_MODE_DIRECT,
|
||||
);
|
||||
expect({ ...parsedTestTx.authInfo!.fee!.amount[0] }).toEqual({ denom: "ucosm", amount: "2000" });
|
||||
expect(parsedTestTx.authInfo!.fee!.gasLimit.toString()).toEqual(gasLimit.toString());
|
||||
expect(parsedTestTx.body!.extensionOptions).toEqual([]);
|
||||
expect(parsedTestTx.body!.nonCriticalExtensionOptions).toEqual([]);
|
||||
expect(parsedTestTx.body!.messages.length).toEqual(1);
|
||||
expect(parsedTestTx.authInfo.signerInfos[0].modeInfo!.single!.mode).toEqual(SignMode.SIGN_MODE_DIRECT);
|
||||
expect({ ...parsedTestTx.authInfo.fee!.amount[0] }).toEqual({ denom: "ucosm", amount: "2000" });
|
||||
expect(parsedTestTx.authInfo.fee!.gasLimit.toString()).toEqual(gasLimit.toString());
|
||||
expect(parsedTestTx.body.extensionOptions).toEqual([]);
|
||||
expect(parsedTestTx.body.nonCriticalExtensionOptions).toEqual([]);
|
||||
expect(parsedTestTx.body.messages.length).toEqual(1);
|
||||
|
||||
const registry = new Registry();
|
||||
const parsedTestTxMsg = registry.decode({
|
||||
typeUrl: parsedTestTx.body!.messages[0].typeUrl,
|
||||
value: parsedTestTx.body!.messages[0].value,
|
||||
typeUrl: parsedTestTx.body.messages[0].typeUrl,
|
||||
value: parsedTestTx.body.messages[0].value,
|
||||
});
|
||||
expect(parsedTestTxMsg.fromAddress).toEqual(address);
|
||||
expect(parsedTestTxMsg.toAddress).toEqual(toAddress);
|
||||
|
@ -4,12 +4,13 @@ import { coin, coins, DirectSecp256k1HdWallet, Registry } from "@cosmjs/proto-si
|
||||
import { assert, sleep } from "@cosmjs/utils";
|
||||
import protobuf from "protobufjs/minimal";
|
||||
|
||||
import { decodeTxRaw } from "../../proto-signing/build";
|
||||
import { AminoMsgDelegate } from "./aminomsgs";
|
||||
import { AminoTypes } from "./aminotypes";
|
||||
import { MsgSend } from "./codec/cosmos/bank/v1beta1/tx";
|
||||
import { Coin } from "./codec/cosmos/base/v1beta1/coin";
|
||||
import { DeepPartial, MsgDelegate } from "./codec/cosmos/staking/v1beta1/tx";
|
||||
import { AuthInfo, Tx, TxBody, TxRaw } from "./codec/cosmos/tx/v1beta1/tx";
|
||||
import { AuthInfo, TxBody, TxRaw } from "./codec/cosmos/tx/v1beta1/tx";
|
||||
import { MsgDelegateEncodeObject, MsgSendEncodeObject } from "./encodeobjects";
|
||||
import { GasPrice } from "./fee";
|
||||
import { PrivateSigningStargateClient, SigningStargateClient } from "./signingstargateclient";
|
||||
@ -371,11 +372,11 @@ describe("SigningStargateClient", () => {
|
||||
|
||||
const searchResult = await client.getTx(result.transactionHash);
|
||||
assert(searchResult, "Must find transaction");
|
||||
const tx = Tx.decode(searchResult.tx);
|
||||
const tx = decodeTxRaw(searchResult.tx);
|
||||
// From ModifyingDirectSecp256k1HdWallet
|
||||
expect(tx.body!.memo).toEqual("This was modified");
|
||||
expect({ ...tx.authInfo!.fee!.amount[0] }).toEqual(coin(3000, "ucosm"));
|
||||
expect(tx.authInfo!.fee!.gasLimit.toNumber()).toEqual(333333);
|
||||
expect(tx.body.memo).toEqual("This was modified");
|
||||
expect({ ...tx.authInfo.fee!.amount[0] }).toEqual(coin(3000, "ucosm"));
|
||||
expect(tx.authInfo.fee!.gasLimit.toNumber()).toEqual(333333);
|
||||
});
|
||||
});
|
||||
|
||||
@ -568,11 +569,11 @@ describe("SigningStargateClient", () => {
|
||||
|
||||
const searchResult = await client.getTx(result.transactionHash);
|
||||
assert(searchResult, "Must find transaction");
|
||||
const tx = Tx.decode(searchResult.tx);
|
||||
const tx = decodeTxRaw(searchResult.tx);
|
||||
// From ModifyingSecp256k1HdWallet
|
||||
expect(tx.body!.memo).toEqual("This was modified");
|
||||
expect({ ...tx.authInfo!.fee!.amount[0] }).toEqual(coin(3000, "ucosm"));
|
||||
expect(tx.authInfo!.fee!.gasLimit.toNumber()).toEqual(333333);
|
||||
expect(tx.body.memo).toEqual("This was modified");
|
||||
expect({ ...tx.authInfo.fee!.amount[0] }).toEqual(coin(3000, "ucosm"));
|
||||
expect(tx.authInfo.fee!.gasLimit.toNumber()).toEqual(333333);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -10,8 +10,9 @@ import {
|
||||
} from "@cosmjs/proto-signing";
|
||||
import { assert, sleep } from "@cosmjs/utils";
|
||||
|
||||
import { decodeTxRaw } from "../../proto-signing/build";
|
||||
import { Coin } from "./codec/cosmos/base/v1beta1/coin";
|
||||
import { Tx, TxRaw } from "./codec/cosmos/tx/v1beta1/tx";
|
||||
import { TxRaw } from "./codec/cosmos/tx/v1beta1/tx";
|
||||
import { isMsgSendEncodeObject } from "./encodeobjects";
|
||||
import {
|
||||
BroadcastTxResponse,
|
||||
@ -231,8 +232,8 @@ describe("StargateClient.getTx and .searchTx", () => {
|
||||
|
||||
// Check basic structure of all results
|
||||
for (const result of results) {
|
||||
const tx = Tx.decode(result.tx);
|
||||
const filteredMsgs = tx.body!.messages.filter((msg) => {
|
||||
const tx = decodeTxRaw(result.tx);
|
||||
const filteredMsgs = tx.body.messages.filter((msg) => {
|
||||
if (!isMsgSendEncodeObject(msg)) return false;
|
||||
const decoded = registry.decode(msg);
|
||||
return decoded.fromAddress === sendSuccessful?.sender;
|
||||
@ -259,8 +260,8 @@ describe("StargateClient.getTx and .searchTx", () => {
|
||||
|
||||
// Check basic structure of all results
|
||||
for (const result of results) {
|
||||
const tx = Tx.decode(result.tx);
|
||||
const filteredMsgs = tx.body!.messages.filter((msg) => {
|
||||
const tx = decodeTxRaw(result.tx);
|
||||
const filteredMsgs = tx.body.messages.filter((msg) => {
|
||||
if (!isMsgSendEncodeObject(msg)) return false;
|
||||
const decoded = registry.decode(msg);
|
||||
return decoded.toAddress === sendSuccessful?.recipient;
|
||||
@ -345,8 +346,8 @@ describe("StargateClient.getTx and .searchTx", () => {
|
||||
|
||||
// Check basic structure of all results
|
||||
for (const result of results) {
|
||||
const tx = Tx.decode(result.tx);
|
||||
const msg = fromOneElementArray(tx.body!.messages);
|
||||
const tx = decodeTxRaw(result.tx);
|
||||
const msg = fromOneElementArray(tx.body.messages);
|
||||
expect(msg.typeUrl).toEqual("/cosmos.bank.v1beta1.MsgSend");
|
||||
const decoded = registry.decode(msg);
|
||||
expect(decoded.toAddress).toEqual(sendSuccessful.recipient);
|
||||
|
@ -58,6 +58,20 @@ export interface IndexedTx {
|
||||
/** Transaction execution error code. 0 on success. */
|
||||
readonly code: number;
|
||||
readonly rawLog: string;
|
||||
/**
|
||||
* Raw transaction bytes stored in Tendermint.
|
||||
*
|
||||
* If you hash this, you get the transaction hash (= transaction ID):
|
||||
*
|
||||
* ```js
|
||||
* import { sha256 } from "@cosmjs/crypto";
|
||||
* import { toHex } from "@cosmjs/encoding";
|
||||
*
|
||||
* const transactionId = toHex(sha256(indexTx.tx)).toUpperCase();
|
||||
* ```
|
||||
*
|
||||
* Use `decodeTxRaw` from @cosmjs/proto-signing to decode this.
|
||||
*/
|
||||
readonly tx: Uint8Array;
|
||||
readonly gasUsed: number;
|
||||
readonly gasWanted: number;
|
||||
|
Loading…
x
Reference in New Issue
Block a user