diff --git a/packages/stargate/src/stargateclient.spec.ts b/packages/stargate/src/stargateclient.spec.ts index 7e42e103a4..4def60d477 100644 --- a/packages/stargate/src/stargateclient.spec.ts +++ b/packages/stargate/src/stargateclient.spec.ts @@ -11,13 +11,20 @@ import { assert, sleep } from "@cosmjs/utils"; import { ReadonlyDate } from "readonly-date"; import { TxRaw } from "./codec/cosmos/tx/v1beta1/tx"; -import { assertIsBroadcastTxSuccess, PrivateStargateClient, StargateClient } from "./stargateclient"; +import { + assertIsBroadcastTxSuccess, + PrivateStargateClient, + StargateClient, + TimeoutError, +} from "./stargateclient"; import { faucet, makeRandomAddress, nonExistentAddress, pendingWithoutSimapp, + pendingWithoutSlowSimapp, simapp, + slowSimapp, tendermintIdMatcher, unused, validator, @@ -331,5 +338,78 @@ describe("StargateClient", () => { client.disconnect(); }); + + it("respects user timeouts rather than RPC timeouts", async () => { + pendingWithoutSlowSimapp(); + const client = await StargateClient.connect(slowSimapp.tendermintUrl); + const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic); + const [{ address, pubkey: pubkeyBytes }] = await wallet.getAccounts(); + const pubkey = encodePubkey({ + type: "tendermint/PubKeySecp256k1", + value: toBase64(pubkeyBytes), + }); + const registry = new Registry(); + const txBodyFields = { + typeUrl: "/cosmos.tx.v1beta1.TxBody", + value: { + messages: [ + { + typeUrl: "/cosmos.bank.v1beta1.MsgSend", + value: { + fromAddress: address, + toAddress: makeRandomAddress(), + amount: [ + { + denom: "ucosm", + amount: "1234567", + }, + ], + }, + }, + ], + }, + }; + const txBodyBytes = registry.encode(txBodyFields); + const chainId = await client.getChainId(); + const feeAmount = [ + { + amount: "2000", + denom: "ucosm", + }, + ]; + const gasLimit = 200000; + + const { accountNumber: accountNumber1, sequence: sequence1 } = (await client.getSequence(address))!; + const authInfoBytes1 = makeAuthInfoBytes([pubkey], feeAmount, gasLimit, sequence1); + const signDoc1 = makeSignDoc(txBodyBytes, authInfoBytes1, chainId, accountNumber1); + const { signature: signature1 } = await wallet.signDirect(address, signDoc1); + const txRaw1 = TxRaw.fromPartial({ + bodyBytes: txBodyBytes, + authInfoBytes: authInfoBytes1, + signatures: [fromBase64(signature1.signature)], + }); + const txRawBytes1 = Uint8Array.from(TxRaw.encode(txRaw1).finish()); + const largeTimeoutMs = 30_000; + const txResult = await client.broadcastTx(txRawBytes1, largeTimeoutMs); + assertIsBroadcastTxSuccess(txResult); + + const { accountNumber: accountNumber2, sequence: sequence2 } = (await client.getSequence(address))!; + const authInfoBytes2 = makeAuthInfoBytes([pubkey], feeAmount, gasLimit, sequence2); + const signDoc2 = makeSignDoc(txBodyBytes, authInfoBytes2, chainId, accountNumber2); + const { signature: signature2 } = await wallet.signDirect(address, signDoc2); + const txRaw2 = TxRaw.fromPartial({ + bodyBytes: txBodyBytes, + authInfoBytes: authInfoBytes2, + signatures: [fromBase64(signature2.signature)], + }); + const txRawBytes2 = Uint8Array.from(TxRaw.encode(txRaw2).finish()); + const smallTimeoutMs = 1_000; + await expectAsync(client.broadcastTx(txRawBytes2, smallTimeoutMs)).toBeRejectedWithError( + TimeoutError, + /transaction with id .+ was submitted but was not yet found on the chain/i, + ); + + client.disconnect(); + }); }); }); diff --git a/packages/stargate/src/testutils.spec.ts b/packages/stargate/src/testutils.spec.ts index 35f8cc829b..3a23683e00 100644 --- a/packages/stargate/src/testutils.spec.ts +++ b/packages/stargate/src/testutils.spec.ts @@ -29,6 +29,16 @@ export function pendingWithoutSimapp(): void { } } +export function slowSimappEnabled(): boolean { + return !!process.env.SLOW_SIMAPP_ENABLED; +} + +export function pendingWithoutSlowSimapp(): void { + if (!slowSimappEnabled()) { + return pending("Set SLOW_SIMAPP_ENABLED to enable slow Simapp based tests"); + } +} + export function makeRandomAddressBytes(): Uint8Array { return Random.getBytes(20); } @@ -54,6 +64,17 @@ export const simapp = { totalSupply: 21000000000, }; +export const slowSimapp = { + tendermintUrl: "localhost:26660", + tendermintUrlWs: "ws://localhost:26660", + tendermintUrlHttp: "http://localhost:26660", + chainId: "simd-testing", + denomStaking: "ustake", + denomFee: "ucosm", + blockTime: 1_000, // ms + totalSupply: 21000000000, +}; + export const faucet = { mnemonic: "economy stock theory fatal elder harbor betray wasp final emotion task crumble siren bottom lizard educate guess current outdoor pair theory focus wife stone",