mirror of
https://github.com/cosmos/cosmjs.git
synced 2025-03-10 21:49:15 +00:00
stargate: Improve StargateClient.broadcastTx
This commit is contained in:
parent
fcdab9d6d5
commit
46a45f0e8f
@ -1,4 +1,5 @@
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
import { sha256 } from "@cosmjs/crypto";
|
||||
import { toHex } from "@cosmjs/encoding";
|
||||
import { Uint53 } from "@cosmjs/math";
|
||||
import {
|
||||
@ -6,6 +7,7 @@ import {
|
||||
Tendermint34Client,
|
||||
toRfc3339WithNanoseconds,
|
||||
} from "@cosmjs/tendermint-rpc";
|
||||
import { sleep } from "@cosmjs/utils";
|
||||
|
||||
import { Account, accountFromAny } from "./accounts";
|
||||
import { MsgData, TxMsgData } from "./codec/cosmos/base/abci/v1beta1/abci";
|
||||
@ -19,6 +21,15 @@ import {
|
||||
SearchTxQuery,
|
||||
} from "./search";
|
||||
|
||||
class TimeoutError extends Error {
|
||||
public readonly txId: string;
|
||||
|
||||
public constructor(message: string, txId: string) {
|
||||
super(message);
|
||||
this.txId = txId;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the same as BlockHeader from @cosmjs/launchpad but those might diverge in the future.
|
||||
*/
|
||||
@ -268,7 +279,61 @@ export class StargateClient {
|
||||
if (this.tmClient) this.tmClient.disconnect();
|
||||
}
|
||||
|
||||
public async broadcastTx(tx: Uint8Array): Promise<BroadcastTxResponse> {
|
||||
public async broadcastTx(
|
||||
tx: Uint8Array,
|
||||
timeoutMs = 60_000,
|
||||
pollIntervalMs = 3_000,
|
||||
): Promise<BroadcastTxResponse> {
|
||||
const txId = toHex(sha256(tx));
|
||||
let timedOut = false;
|
||||
const timeoutTimeout = setTimeout(() => {
|
||||
timedOut = true;
|
||||
}, timeoutMs);
|
||||
|
||||
const handlePrematureTimeout = (): Promise<BroadcastTxResponse> => {
|
||||
if (timedOut) {
|
||||
throw new TimeoutError(
|
||||
`Transaction with ID ${txId} was submitted but was not yet found on the chain. You might want to check later.`,
|
||||
txId,
|
||||
);
|
||||
}
|
||||
return sleep(pollIntervalMs)
|
||||
.then(() => this.getTx(txId))
|
||||
.then((result) =>
|
||||
result
|
||||
? {
|
||||
code: result.code,
|
||||
height: result.height,
|
||||
rawLog: result.rawLog,
|
||||
transactionHash: txId,
|
||||
}
|
||||
: handlePrematureTimeout(),
|
||||
);
|
||||
};
|
||||
|
||||
return new Promise((resolve, reject) =>
|
||||
this.broadcastTxCommit(tx)
|
||||
.catch((error) => {
|
||||
try {
|
||||
const errorJson = JSON.parse(error.message);
|
||||
if (errorJson.code !== -32603) {
|
||||
// irrelevant error
|
||||
throw error;
|
||||
}
|
||||
} catch {
|
||||
// invalid JSON
|
||||
throw error;
|
||||
}
|
||||
// timed out waiting for tx to be included in a block
|
||||
// now we poll to artificially extend the timeout
|
||||
return handlePrematureTimeout();
|
||||
})
|
||||
.then(resolve, reject)
|
||||
.finally(() => clearTimeout(timeoutTimeout)),
|
||||
);
|
||||
}
|
||||
|
||||
private async broadcastTxCommit(tx: Uint8Array): Promise<BroadcastTxResponse> {
|
||||
const response = await this.forceGetTmClient().broadcastTxCommit({ tx });
|
||||
if (broadcastTxCommitSuccess(response)) {
|
||||
return {
|
||||
|
Loading…
x
Reference in New Issue
Block a user