mirror of
https://github.com/cosmos/cosmjs.git
synced 2025-03-10 21:49:15 +00:00
Merge pull request #10 from confio/error-on-failed-tx
Error on failed tx
This commit is contained in:
commit
ae1534896d
@ -24,6 +24,7 @@
|
|||||||
"docs": "shx rm -rf docs && typedoc --options typedoc.js",
|
"docs": "shx rm -rf docs && typedoc --options typedoc.js",
|
||||||
"format": "prettier --write --loglevel warn \"./src/**/*.ts\"",
|
"format": "prettier --write --loglevel warn \"./src/**/*.ts\"",
|
||||||
"lint": "eslint --max-warnings 0 \"**/*.{js,ts}\" && tslint -t verbose --project .",
|
"lint": "eslint --max-warnings 0 \"**/*.{js,ts}\" && tslint -t verbose --project .",
|
||||||
|
"autolint": "eslint --max-warnings 0 \"**/*.{js,ts}\" --fix",
|
||||||
"move-types": "shx rm -rf ./types/* && shx mv build/types/* ./types && rm -rf ./types/testdata && shx rm -f ./types/*.spec.d.ts",
|
"move-types": "shx rm -rf ./types/* && shx mv build/types/* ./types && rm -rf ./types/testdata && shx rm -f ./types/*.spec.d.ts",
|
||||||
"format-types": "prettier --write --loglevel warn \"./types/**/*.d.ts\"",
|
"format-types": "prettier --write --loglevel warn \"./types/**/*.d.ts\"",
|
||||||
"build": "shx rm -rf ./build && tsc && yarn move-types && yarn format-types",
|
"build": "shx rm -rf ./build && tsc && yarn move-types && yarn format-types",
|
||||||
|
@ -18,7 +18,7 @@ import { Sha256 } from "@iov/crypto";
|
|||||||
import { Encoding } from "@iov/encoding";
|
import { Encoding } from "@iov/encoding";
|
||||||
import { marshalTx, unmarshalTx } from "@tendermint/amino-js";
|
import { marshalTx, unmarshalTx } from "@tendermint/amino-js";
|
||||||
|
|
||||||
import { isValidAddress, pubkeyToAddress, CosmosBech32Prefix } from "./address";
|
import { CosmosBech32Prefix, isValidAddress, pubkeyToAddress } from "./address";
|
||||||
import { Caip5 } from "./caip5";
|
import { Caip5 } from "./caip5";
|
||||||
import { parseTx } from "./decode";
|
import { parseTx } from "./decode";
|
||||||
import { buildSignedTx, buildUnsignedTx } from "./encode";
|
import { buildSignedTx, buildUnsignedTx } from "./encode";
|
||||||
@ -91,7 +91,6 @@ export class CosmosCodec implements TxCodec {
|
|||||||
throw new Error("Nonce is required");
|
throw new Error("Nonce is required");
|
||||||
}
|
}
|
||||||
const parsed = unmarshalTx(bytes);
|
const parsed = unmarshalTx(bytes);
|
||||||
// TODO: this needs access to token list
|
|
||||||
return parseTx(parsed, chainId, nonce, this.tokens);
|
return parseTx(parsed, chainId, nonce, this.tokens);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,9 +14,9 @@ import { Secp256k1 } from "@iov/crypto";
|
|||||||
import { Encoding } from "@iov/encoding";
|
import { Encoding } from "@iov/encoding";
|
||||||
import { HdPaths, Secp256k1HdWallet, UserProfile } from "@iov/keycontrol";
|
import { HdPaths, Secp256k1HdWallet, UserProfile } from "@iov/keycontrol";
|
||||||
|
|
||||||
import { cosmosCodec, CosmosCodec } from "./cosmoscodec";
|
|
||||||
import { CosmosConnection } from "./cosmosconnection";
|
|
||||||
import { CosmosBech32Prefix } from "./address";
|
import { CosmosBech32Prefix } from "./address";
|
||||||
|
import { CosmosCodec, cosmosCodec } from "./cosmoscodec";
|
||||||
|
import { CosmosConnection } from "./cosmosconnection";
|
||||||
import { TokenInfos } from "./types";
|
import { TokenInfos } from "./types";
|
||||||
|
|
||||||
const { fromBase64, toHex } = Encoding;
|
const { fromBase64, toHex } = Encoding;
|
||||||
@ -197,11 +197,9 @@ describe("CosmosConnection", () => {
|
|||||||
const nonce = await connection.getNonce({ address: faucetAddress });
|
const nonce = await connection.getNonce({ address: faucetAddress });
|
||||||
// TODO: we need to use custom codecs everywhere
|
// TODO: we need to use custom codecs everywhere
|
||||||
const codec = new CosmosCodec(defaultPrefix, defaultTokens);
|
const codec = new CosmosCodec(defaultPrefix, defaultTokens);
|
||||||
console.log("nonce:", nonce);
|
|
||||||
const signed = await profile.signTransaction(faucet, unsigned, codec, nonce);
|
const signed = await profile.signTransaction(faucet, unsigned, codec, nonce);
|
||||||
const postableBytes = codec.bytesToPost(signed);
|
const postableBytes = codec.bytesToPost(signed);
|
||||||
const response = await connection.postTx(postableBytes);
|
const response = await connection.postTx(postableBytes);
|
||||||
console.log(response);
|
|
||||||
const { transactionId } = response;
|
const { transactionId } = response;
|
||||||
const blockInfo = await response.blockInfo.waitFor(info => !isBlockInfoPending(info));
|
const blockInfo = await response.blockInfo.waitFor(info => !isBlockInfoPending(info));
|
||||||
expect(blockInfo.state).toEqual(TransactionState.Succeeded);
|
expect(blockInfo.state).toEqual(TransactionState.Succeeded);
|
||||||
@ -263,7 +261,6 @@ describe("CosmosConnection", () => {
|
|||||||
const signed = await profile.signTransaction(faucet, unsigned, codec, nonce);
|
const signed = await profile.signTransaction(faucet, unsigned, codec, nonce);
|
||||||
const postableBytes = codec.bytesToPost(signed);
|
const postableBytes = codec.bytesToPost(signed);
|
||||||
const response = await connection.postTx(postableBytes);
|
const response = await connection.postTx(postableBytes);
|
||||||
console.log(response);
|
|
||||||
const { transactionId } = response;
|
const { transactionId } = response;
|
||||||
const blockInfo = await response.blockInfo.waitFor(info => !isBlockInfoPending(info));
|
const blockInfo = await response.blockInfo.waitFor(info => !isBlockInfoPending(info));
|
||||||
expect(blockInfo.state).toEqual(TransactionState.Succeeded);
|
expect(blockInfo.state).toEqual(TransactionState.Succeeded);
|
||||||
|
@ -89,14 +89,13 @@ export class CosmosConnection implements BlockchainConnection {
|
|||||||
|
|
||||||
private readonly restClient: RestClient;
|
private readonly restClient: RestClient;
|
||||||
private readonly chainData: ChainData;
|
private readonly chainData: ChainData;
|
||||||
private readonly primaryToken: Token;
|
|
||||||
|
|
||||||
// TODO: deprecate this???
|
|
||||||
private readonly supportedTokens: readonly Token[];
|
|
||||||
|
|
||||||
private readonly _prefix: CosmosBech32Prefix;
|
private readonly _prefix: CosmosBech32Prefix;
|
||||||
private readonly tokenInfo: TokenInfos;
|
private readonly tokenInfo: TokenInfos;
|
||||||
|
|
||||||
|
// these are derived from arguments (cached for use in multiple functions)
|
||||||
|
private readonly primaryToken: Token;
|
||||||
|
private readonly supportedTokens: readonly Token[];
|
||||||
|
|
||||||
private get prefix(): CosmosBech32Prefix {
|
private get prefix(): CosmosBech32Prefix {
|
||||||
return this._prefix;
|
return this._prefix;
|
||||||
}
|
}
|
||||||
@ -214,8 +213,10 @@ export class CosmosConnection implements BlockchainConnection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async postTx(tx: PostableBytes): Promise<PostTxResponse> {
|
public async postTx(tx: PostableBytes): Promise<PostTxResponse> {
|
||||||
// TODO: we need to check errors here... bad chain-id breaks this
|
const { code, txhash, raw_log } = await this.restClient.postTx(tx);
|
||||||
const { txhash, raw_log } = await this.restClient.postTx(tx);
|
if (code !== 0) {
|
||||||
|
throw new Error(raw_log);
|
||||||
|
}
|
||||||
const transactionId = txhash as TransactionId;
|
const transactionId = txhash as TransactionId;
|
||||||
const firstEvent: BlockInfo = { state: TransactionState.Pending };
|
const firstEvent: BlockInfo = { state: TransactionState.Pending };
|
||||||
let blockInfoInterval: NodeJS.Timeout;
|
let blockInfoInterval: NodeJS.Timeout;
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { ChainConnector, ChainId } from "@iov/bcp";
|
import { ChainConnector, ChainId } from "@iov/bcp";
|
||||||
|
|
||||||
|
import { CosmosBech32Prefix } from "./address";
|
||||||
import { cosmosCodec } from "./cosmoscodec";
|
import { cosmosCodec } from "./cosmoscodec";
|
||||||
import { CosmosConnection } from "./cosmosconnection";
|
import { CosmosConnection } from "./cosmosconnection";
|
||||||
import { CosmosBech32Prefix } from "./address";
|
|
||||||
import { TokenInfos } from "./types";
|
import { TokenInfos } from "./types";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -12,7 +12,6 @@ import {
|
|||||||
SendTransaction,
|
SendTransaction,
|
||||||
SignatureBytes,
|
SignatureBytes,
|
||||||
SignedTransaction,
|
SignedTransaction,
|
||||||
TokenTicker,
|
|
||||||
TransactionId,
|
TransactionId,
|
||||||
UnsignedTransaction,
|
UnsignedTransaction,
|
||||||
} from "@iov/bcp";
|
} from "@iov/bcp";
|
||||||
@ -20,12 +19,10 @@ import { Encoding } from "@iov/encoding";
|
|||||||
import amino from "@tendermint/amino-js";
|
import amino from "@tendermint/amino-js";
|
||||||
|
|
||||||
import { TxsResponse } from "./restclient";
|
import { TxsResponse } from "./restclient";
|
||||||
import { isAminoStdTx, TokenInfos, coinToAmount } from "./types";
|
import { coinToAmount, isAminoStdTx, TokenInfos } from "./types";
|
||||||
|
|
||||||
const { fromBase64 } = Encoding;
|
const { fromBase64 } = Encoding;
|
||||||
|
|
||||||
const atom = "ATOM" as TokenTicker;
|
|
||||||
|
|
||||||
export function decodePubkey(pubkey: amino.PubKey): PubkeyBundle {
|
export function decodePubkey(pubkey: amino.PubKey): PubkeyBundle {
|
||||||
return {
|
return {
|
||||||
algo: Algorithm.Secp256k1,
|
algo: Algorithm.Secp256k1,
|
||||||
@ -45,9 +42,6 @@ export function decodeFullSignature(signature: amino.StdSignature, nonce: number
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: this needs access to token list - we need something more like amountToCoin and coinToAmount here
|
|
||||||
// and wire that info all the way from both connection and codec.
|
|
||||||
|
|
||||||
// TODO: return null vs throw exception for undefined???
|
// TODO: return null vs throw exception for undefined???
|
||||||
export const decodeAmount = (tokens: TokenInfos) => (coin: amino.Coin): Amount => {
|
export const decodeAmount = (tokens: TokenInfos) => (coin: amino.Coin): Amount => {
|
||||||
return coinToAmount(tokens, coin);
|
return coinToAmount(tokens, coin);
|
||||||
@ -69,7 +63,6 @@ export function parseMsg(msg: amino.Msg, chainId: ChainId, tokens: TokenInfos):
|
|||||||
chainId: chainId,
|
chainId: chainId,
|
||||||
sender: msgValue.from_address as Address,
|
sender: msgValue.from_address as Address,
|
||||||
recipient: msgValue.to_address as Address,
|
recipient: msgValue.to_address as Address,
|
||||||
// TODO: this needs access to token list
|
|
||||||
amount: decodeAmount(tokens)(msgValue.amount[0]),
|
amount: decodeAmount(tokens)(msgValue.amount[0]),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -94,9 +87,7 @@ export function parseTx(tx: amino.Tx, chainId: ChainId, nonce: Nonce, tokens: To
|
|||||||
}
|
}
|
||||||
|
|
||||||
const [primarySignature] = txValue.signatures.map(signature => decodeFullSignature(signature, nonce));
|
const [primarySignature] = txValue.signatures.map(signature => decodeFullSignature(signature, nonce));
|
||||||
// TODO: this needs access to token list
|
|
||||||
const msg = parseMsg(txValue.msg[0], chainId, tokens);
|
const msg = parseMsg(txValue.msg[0], chainId, tokens);
|
||||||
// TODO: this needs access to token list
|
|
||||||
const fee = parseFee(txValue.fee, tokens);
|
const fee = parseFee(txValue.fee, tokens);
|
||||||
|
|
||||||
const transaction = {
|
const transaction = {
|
||||||
|
@ -13,7 +13,7 @@ import { Secp256k1 } from "@iov/crypto";
|
|||||||
import { Encoding } from "@iov/encoding";
|
import { Encoding } from "@iov/encoding";
|
||||||
import amino from "@tendermint/amino-js";
|
import amino from "@tendermint/amino-js";
|
||||||
|
|
||||||
import { AminoTx, TokenInfos, amountToCoin } from "./types";
|
import { AminoTx, amountToCoin, TokenInfos } from "./types";
|
||||||
|
|
||||||
const { toBase64 } = Encoding;
|
const { toBase64 } = Encoding;
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ export interface TokenInfo extends Token {
|
|||||||
|
|
||||||
export type TokenInfos = ReadonlyArray<TokenInfo>;
|
export type TokenInfos = ReadonlyArray<TokenInfo>;
|
||||||
|
|
||||||
// TODO: alias amino types
|
// TODO: return null vs throw exception for undefined???
|
||||||
export function amountToCoin(lookup: ReadonlyArray<TokenInfo>, amount: Amount): amino.Coin {
|
export function amountToCoin(lookup: ReadonlyArray<TokenInfo>, amount: Amount): amino.Coin {
|
||||||
const match = lookup.find(({ tokenTicker }) => tokenTicker === amount.tokenTicker);
|
const match = lookup.find(({ tokenTicker }) => tokenTicker === amount.tokenTicker);
|
||||||
if (!match) {
|
if (!match) {
|
||||||
@ -28,6 +28,7 @@ export function amountToCoin(lookup: ReadonlyArray<TokenInfo>, amount: Amount):
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: return null vs throw exception for undefined???
|
||||||
export function coinToAmount(tokens: TokenInfos, coin: amino.Coin): Amount {
|
export function coinToAmount(tokens: TokenInfos, coin: amino.Coin): Amount {
|
||||||
const match = tokens.find(({ denom }) => denom === coin.denom);
|
const match = tokens.find(({ denom }) => denom === coin.denom);
|
||||||
if (!match) {
|
if (!match) {
|
||||||
|
4
types/cosmosconnection.d.ts
vendored
4
types/cosmosconnection.d.ts
vendored
@ -27,10 +27,10 @@ export declare class CosmosConnection implements BlockchainConnection {
|
|||||||
private static initialize;
|
private static initialize;
|
||||||
private readonly restClient;
|
private readonly restClient;
|
||||||
private readonly chainData;
|
private readonly chainData;
|
||||||
private readonly primaryToken;
|
|
||||||
private readonly supportedTokens;
|
|
||||||
private readonly _prefix;
|
private readonly _prefix;
|
||||||
private readonly tokenInfo;
|
private readonly tokenInfo;
|
||||||
|
private readonly primaryToken;
|
||||||
|
private readonly supportedTokens;
|
||||||
private get prefix();
|
private get prefix();
|
||||||
private constructor();
|
private constructor();
|
||||||
disconnect(): void;
|
disconnect(): void;
|
||||||
|
2
types/cosmosconnector.d.ts
vendored
2
types/cosmosconnector.d.ts
vendored
@ -1,6 +1,6 @@
|
|||||||
import { ChainConnector, ChainId } from "@iov/bcp";
|
import { ChainConnector, ChainId } from "@iov/bcp";
|
||||||
import { CosmosConnection } from "./cosmosconnection";
|
|
||||||
import { CosmosBech32Prefix } from "./address";
|
import { CosmosBech32Prefix } from "./address";
|
||||||
|
import { CosmosConnection } from "./cosmosconnection";
|
||||||
import { TokenInfos } from "./types";
|
import { TokenInfos } from "./types";
|
||||||
/**
|
/**
|
||||||
* A helper to connect to a cosmos-based chain at a given url
|
* A helper to connect to a cosmos-based chain at a given url
|
||||||
|
Loading…
x
Reference in New Issue
Block a user