Merge pull request #210 from CosmWasm/199-client-error-handling
Reorganise error handling
This commit is contained in:
commit
0c6410612c
@ -1,9 +1,8 @@
|
||||
/* eslint-disable @typescript-eslint/camelcase */
|
||||
import { Uint53 } from "@cosmjs/math";
|
||||
import { Coin, CosmosSdkTx, isMsgSend, makeSignBytes, MsgSend, Secp256k1Pen } from "@cosmjs/sdk38";
|
||||
import { assert, sleep } from "@cosmjs/utils";
|
||||
|
||||
import { CosmWasmClient } from "./cosmwasmclient";
|
||||
import { CosmWasmClient, isPostTxFailure } from "./cosmwasmclient";
|
||||
import { isMsgExecuteContract, isMsgInstantiateContract } from "./msgs";
|
||||
import { RestClient } from "./restclient";
|
||||
import { SigningCosmWasmClient } from "./signingcosmwasmclient";
|
||||
@ -113,19 +112,13 @@ describe("CosmWasmClient.searchTx", () => {
|
||||
},
|
||||
};
|
||||
const transactionId = await client.getIdentifier(tx);
|
||||
try {
|
||||
await client.postTx(tx.value);
|
||||
} catch (error) {
|
||||
// postTx() throws on execution failures, which is a questionable design. Ignore for now.
|
||||
// console.log(error);
|
||||
const errorMessage: string = error.toString();
|
||||
const [_, heightMatch] = errorMessage.match(/at height ([0-9]+)/) || ["", ""];
|
||||
|
||||
const result = await client.postTx(tx.value);
|
||||
if (isPostTxFailure(result)) {
|
||||
sendUnsuccessful = {
|
||||
sender: alice.address0,
|
||||
recipient: recipient,
|
||||
hash: transactionId,
|
||||
height: Uint53.fromString(heightMatch).toNumber(),
|
||||
height: result.height,
|
||||
tx: tx,
|
||||
};
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@ import { makeSignBytes, MsgSend, Secp256k1Pen, StdFee } from "@cosmjs/sdk38";
|
||||
import { assert, sleep } from "@cosmjs/utils";
|
||||
import { ReadonlyDate } from "readonly-date";
|
||||
|
||||
import { Code, CosmWasmClient, PrivateCosmWasmClient } from "./cosmwasmclient";
|
||||
import { Code, CosmWasmClient, isPostTxFailure, PrivateCosmWasmClient } from "./cosmwasmclient";
|
||||
import { findAttribute } from "./logs";
|
||||
import { SigningCosmWasmClient } from "./signingcosmwasmclient";
|
||||
import cosmoshub from "./testdata/cosmoshub.json";
|
||||
@ -242,7 +242,9 @@ describe("CosmWasmClient", () => {
|
||||
memo: memo,
|
||||
signatures: [signature],
|
||||
};
|
||||
const { logs, transactionHash } = await client.postTx(signedTx);
|
||||
const result = await client.postTx(signedTx);
|
||||
assert(!isPostTxFailure(result));
|
||||
const { logs, transactionHash } = result;
|
||||
const amountAttr = findAttribute(logs, "transfer", "amount");
|
||||
expect(amountAttr.value).toEqual("1234567ucosm");
|
||||
expect(transactionHash).toMatch(/^[0-9A-F]{64}$/);
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { Sha256 } from "@cosmjs/crypto";
|
||||
import { fromBase64, fromHex, toHex } from "@cosmjs/encoding";
|
||||
import { Uint53 } from "@cosmjs/math";
|
||||
import {
|
||||
BroadcastMode,
|
||||
Coin,
|
||||
@ -28,11 +29,26 @@ export interface Account {
|
||||
readonly sequence: number;
|
||||
}
|
||||
|
||||
export interface PostTxResult {
|
||||
export interface PostTxFailure {
|
||||
/** Transaction hash (might be used as transaction ID). Guaranteed to be non-empty upper-case hex */
|
||||
readonly transactionHash: string;
|
||||
readonly height: number;
|
||||
readonly code: number;
|
||||
readonly rawLog: string;
|
||||
}
|
||||
|
||||
export interface PostTxSuccess {
|
||||
readonly logs: readonly Log[];
|
||||
readonly rawLog: string;
|
||||
/** Transaction hash (might be used as transaction ID). Guaranteed to be non-empty upper-case hex */
|
||||
readonly transactionHash: string;
|
||||
readonly data?: Uint8Array;
|
||||
}
|
||||
|
||||
export type PostTxResult = PostTxSuccess | PostTxFailure;
|
||||
|
||||
export function isPostTxFailure(postTxResult: PostTxResult): postTxResult is PostTxFailure {
|
||||
return !!(postTxResult as PostTxFailure).code;
|
||||
}
|
||||
|
||||
export interface SearchByIdQuery {
|
||||
@ -294,17 +310,19 @@ export class CosmWasmClient {
|
||||
throw new Error("Received ill-formatted txhash. Must be non-empty upper-case hex");
|
||||
}
|
||||
|
||||
if (result.code) {
|
||||
throw new Error(
|
||||
`Error when posting tx ${result.txhash} at height ${result.height}. Code: ${result.code}; Raw log: ${result.raw_log}`,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
logs: result.logs ? parseLogs(result.logs) : [],
|
||||
rawLog: result.raw_log || "",
|
||||
transactionHash: result.txhash,
|
||||
};
|
||||
return result.code !== undefined
|
||||
? {
|
||||
height: Uint53.fromString(result.height).toNumber(),
|
||||
transactionHash: result.txhash,
|
||||
code: result.code,
|
||||
rawLog: result.raw_log || "",
|
||||
}
|
||||
: {
|
||||
logs: result.logs ? parseLogs(result.logs) : [],
|
||||
rawLog: result.raw_log || "",
|
||||
transactionHash: result.txhash,
|
||||
data: result.data ? fromHex(result.data) : undefined,
|
||||
};
|
||||
}
|
||||
|
||||
public async getCodes(): Promise<readonly Code[]> {
|
||||
|
||||
@ -19,6 +19,7 @@ import {
|
||||
import { assert, sleep } from "@cosmjs/utils";
|
||||
import { ReadonlyDate } from "readonly-date";
|
||||
|
||||
import { isPostTxFailure } from "./cosmwasmclient";
|
||||
import { findAttribute, parseLogs } from "./logs";
|
||||
import {
|
||||
isMsgInstantiateContract,
|
||||
@ -400,12 +401,8 @@ describe("RestClient", () => {
|
||||
signatures: [signature],
|
||||
};
|
||||
const transactionId = await client.getIdentifier({ type: "cosmos-sdk/StdTx", value: signedTx });
|
||||
try {
|
||||
await client.postTx(signedTx);
|
||||
} catch (error) {
|
||||
// postTx() throws on execution failures, which is a questionable design. Ignore for now.
|
||||
// console.log(error);
|
||||
}
|
||||
const result = await client.postTx(signedTx);
|
||||
assert(isPostTxFailure(result));
|
||||
unsuccessful = {
|
||||
sender: alice.address0,
|
||||
recipient: recipient,
|
||||
@ -858,7 +855,6 @@ describe("RestClient", () => {
|
||||
signatures: [signature1, signature2, signature3],
|
||||
};
|
||||
const postResult = await client.postTx(signedTx);
|
||||
// console.log(postResult.raw_log);
|
||||
expect(postResult.code).toEqual(4);
|
||||
expect(postResult.raw_log).toContain("wrong number of signers");
|
||||
});
|
||||
@ -918,7 +914,6 @@ describe("RestClient", () => {
|
||||
signatures: [signature1],
|
||||
};
|
||||
const postResult = await client.postTx(signedTx);
|
||||
// console.log(postResult.raw_log);
|
||||
expect(postResult.code).toBeUndefined();
|
||||
});
|
||||
|
||||
@ -982,7 +977,6 @@ describe("RestClient", () => {
|
||||
signatures: [signature2, signature1],
|
||||
};
|
||||
const postResult = await client.postTx(signedTx);
|
||||
// console.log(postResult.raw_log);
|
||||
expect(postResult.code).toBeUndefined();
|
||||
|
||||
await sleep(500);
|
||||
@ -1051,7 +1045,6 @@ describe("RestClient", () => {
|
||||
signatures: [signature2, signature1],
|
||||
};
|
||||
const postResult = await client.postTx(signedTx);
|
||||
// console.log(postResult.raw_log);
|
||||
expect(postResult.code).toEqual(8);
|
||||
});
|
||||
|
||||
@ -1115,7 +1108,6 @@ describe("RestClient", () => {
|
||||
signatures: [signature1, signature2],
|
||||
};
|
||||
const postResult = await client.postTx(signedTx);
|
||||
// console.log(postResult.raw_log);
|
||||
expect(postResult.code).toEqual(8);
|
||||
});
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@ import { toHex } from "@cosmjs/encoding";
|
||||
import { Coin, Secp256k1Pen } from "@cosmjs/sdk38";
|
||||
import { assert } from "@cosmjs/utils";
|
||||
|
||||
import { PrivateCosmWasmClient } from "./cosmwasmclient";
|
||||
import { isPostTxFailure, PrivateCosmWasmClient } from "./cosmwasmclient";
|
||||
import { RestClient } from "./restclient";
|
||||
import { SigningCosmWasmClient, UploadMeta } from "./signingcosmwasmclient";
|
||||
import { alice, getHackatom, makeRandomAddress, pendingWithoutWasmd } from "./testutils.spec";
|
||||
@ -205,6 +205,7 @@ describe("SigningCosmWasmClient", () => {
|
||||
|
||||
// send
|
||||
const result = await client.sendTokens(beneficiaryAddress, transferAmount, "for dinner");
|
||||
assert(!isPostTxFailure(result));
|
||||
const [firstLog] = result.logs;
|
||||
expect(firstLog).toBeTruthy();
|
||||
|
||||
|
||||
@ -4,7 +4,14 @@ import { BroadcastMode, Coin, coins, makeSignBytes, MsgSend, StdFee, StdSignatur
|
||||
import pako from "pako";
|
||||
|
||||
import { isValidBuilder } from "./builder";
|
||||
import { Account, CosmWasmClient, GetNonceResult, PostTxResult } from "./cosmwasmclient";
|
||||
import {
|
||||
Account,
|
||||
CosmWasmClient,
|
||||
GetNonceResult,
|
||||
isPostTxFailure,
|
||||
PostTxFailure,
|
||||
PostTxResult,
|
||||
} from "./cosmwasmclient";
|
||||
import { findAttribute, Log } from "./logs";
|
||||
import { MsgExecuteContract, MsgInstantiateContract, MsgStoreCode } from "./msgs";
|
||||
|
||||
@ -84,6 +91,10 @@ export interface ExecuteResult {
|
||||
readonly transactionHash: string;
|
||||
}
|
||||
|
||||
function createPostTxErrorMessage(result: PostTxFailure): string {
|
||||
return `Error when posting tx ${result.transactionHash} at height ${result.height}. Code: ${result.code}; Raw log: ${result.rawLog}`;
|
||||
}
|
||||
|
||||
export class SigningCosmWasmClient extends CosmWasmClient {
|
||||
public readonly senderAddress: string;
|
||||
|
||||
@ -154,6 +165,9 @@ export class SigningCosmWasmClient extends CosmWasmClient {
|
||||
};
|
||||
|
||||
const result = await this.postTx(signedTx);
|
||||
if (isPostTxFailure(result)) {
|
||||
throw new Error(createPostTxErrorMessage(result));
|
||||
}
|
||||
const codeIdAttr = findAttribute(result.logs, "message", "code_id");
|
||||
return {
|
||||
originalSize: wasmCode.length,
|
||||
@ -200,6 +214,9 @@ export class SigningCosmWasmClient extends CosmWasmClient {
|
||||
};
|
||||
|
||||
const result = await this.postTx(signedTx);
|
||||
if (isPostTxFailure(result)) {
|
||||
throw new Error(createPostTxErrorMessage(result));
|
||||
}
|
||||
const contractAddressAttr = findAttribute(result.logs, "message", "contract_address");
|
||||
return {
|
||||
contractAddress: contractAddressAttr.value,
|
||||
@ -237,6 +254,9 @@ export class SigningCosmWasmClient extends CosmWasmClient {
|
||||
};
|
||||
|
||||
const result = await this.postTx(signedTx);
|
||||
if (isPostTxFailure(result)) {
|
||||
throw new Error(createPostTxErrorMessage(result));
|
||||
}
|
||||
return {
|
||||
logs: result.logs,
|
||||
transactionHash: result.transactionHash,
|
||||
|
||||
12
packages/cosmwasm/types/cosmwasmclient.d.ts
vendored
12
packages/cosmwasm/types/cosmwasmclient.d.ts
vendored
@ -14,12 +14,22 @@ export interface Account {
|
||||
readonly accountNumber: number;
|
||||
readonly sequence: number;
|
||||
}
|
||||
export interface PostTxResult {
|
||||
export interface PostTxFailure {
|
||||
/** Transaction hash (might be used as transaction ID). Guaranteed to be non-empty upper-case hex */
|
||||
readonly transactionHash: string;
|
||||
readonly height: number;
|
||||
readonly code: number;
|
||||
readonly rawLog: string;
|
||||
}
|
||||
export interface PostTxSuccess {
|
||||
readonly logs: readonly Log[];
|
||||
readonly rawLog: string;
|
||||
/** Transaction hash (might be used as transaction ID). Guaranteed to be non-empty upper-case hex */
|
||||
readonly transactionHash: string;
|
||||
readonly data?: Uint8Array;
|
||||
}
|
||||
export declare type PostTxResult = PostTxSuccess | PostTxFailure;
|
||||
export declare function isPostTxFailure(postTxResult: PostTxResult): postTxResult is PostTxFailure;
|
||||
export interface SearchByIdQuery {
|
||||
readonly id: string;
|
||||
}
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
/* eslint-disable @typescript-eslint/camelcase */
|
||||
import { Uint53 } from "@cosmjs/math";
|
||||
import { assert, sleep } from "@cosmjs/utils";
|
||||
|
||||
import { Coin } from "./coins";
|
||||
import { CosmosClient } from "./cosmosclient";
|
||||
import { CosmosClient, isPostTxFailure } from "./cosmosclient";
|
||||
import { makeSignBytes } from "./encoding";
|
||||
import { Secp256k1Pen } from "./pen";
|
||||
import { RestClient } from "./restclient";
|
||||
@ -105,19 +104,13 @@ describe("CosmosClient.searchTx", () => {
|
||||
},
|
||||
};
|
||||
const transactionId = await client.getIdentifier(tx);
|
||||
try {
|
||||
await client.postTx(tx.value);
|
||||
} catch (error) {
|
||||
// postTx() throws on execution failures, which is a questionable design. Ignore for now.
|
||||
// console.log(error);
|
||||
const errorMessage: string = error.toString();
|
||||
const [_, heightMatch] = errorMessage.match(/at height ([0-9]+)/) || ["", ""];
|
||||
|
||||
const result = await client.postTx(tx.value);
|
||||
if (isPostTxFailure(result)) {
|
||||
sendUnsuccessful = {
|
||||
sender: faucet.address,
|
||||
recipient: recipient,
|
||||
hash: transactionId,
|
||||
height: Uint53.fromString(heightMatch).toNumber(),
|
||||
height: result.height,
|
||||
tx: tx,
|
||||
};
|
||||
}
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
/* eslint-disable @typescript-eslint/camelcase */
|
||||
import { sleep } from "@cosmjs/utils";
|
||||
import { assert, sleep } from "@cosmjs/utils";
|
||||
import { ReadonlyDate } from "readonly-date";
|
||||
|
||||
import { CosmosClient, PrivateCosmWasmClient } from "./cosmosclient";
|
||||
import { CosmosClient, isPostTxFailure, PrivateCosmWasmClient } from "./cosmosclient";
|
||||
import { makeSignBytes } from "./encoding";
|
||||
import { findAttribute } from "./logs";
|
||||
import { Secp256k1Pen } from "./pen";
|
||||
@ -230,7 +230,9 @@ describe("CosmosClient", () => {
|
||||
memo: memo,
|
||||
signatures: [signature],
|
||||
};
|
||||
const { logs, transactionHash } = await client.postTx(signedTx);
|
||||
const txResult = await client.postTx(signedTx);
|
||||
assert(!isPostTxFailure(txResult));
|
||||
const { logs, transactionHash } = txResult;
|
||||
const amountAttr = findAttribute(logs, "transfer", "amount");
|
||||
expect(amountAttr.value).toEqual("1234567ucosm");
|
||||
expect(transactionHash).toMatch(/^[0-9A-F]{64}$/);
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { Sha256 } from "@cosmjs/crypto";
|
||||
import { fromBase64, toHex } from "@cosmjs/encoding";
|
||||
import { fromBase64, fromHex, toHex } from "@cosmjs/encoding";
|
||||
import { Uint53 } from "@cosmjs/math";
|
||||
|
||||
import { Coin } from "./coins";
|
||||
import { Log, parseLogs } from "./logs";
|
||||
@ -21,11 +22,26 @@ export interface Account {
|
||||
readonly sequence: number;
|
||||
}
|
||||
|
||||
export interface PostTxResult {
|
||||
export interface PostTxFailure {
|
||||
/** Transaction hash (might be used as transaction ID). Guaranteed to be non-empty upper-case hex */
|
||||
readonly transactionHash: string;
|
||||
readonly height: number;
|
||||
readonly code: number;
|
||||
readonly rawLog: string;
|
||||
}
|
||||
|
||||
export interface PostTxSuccess {
|
||||
readonly logs: readonly Log[];
|
||||
readonly rawLog: string;
|
||||
/** Transaction hash (might be used as transaction ID). Guaranteed to be non-empty upper-case hex */
|
||||
readonly transactionHash: string;
|
||||
readonly data?: Uint8Array;
|
||||
}
|
||||
|
||||
export type PostTxResult = PostTxSuccess | PostTxFailure;
|
||||
|
||||
export function isPostTxFailure(postTxResult: PostTxResult): postTxResult is PostTxFailure {
|
||||
return !!(postTxResult as PostTxFailure).code;
|
||||
}
|
||||
|
||||
export interface SearchByIdQuery {
|
||||
@ -276,17 +292,19 @@ export class CosmosClient {
|
||||
throw new Error("Received ill-formatted txhash. Must be non-empty upper-case hex");
|
||||
}
|
||||
|
||||
if (result.code) {
|
||||
throw new Error(
|
||||
`Error when posting tx ${result.txhash} at height ${result.height}. Code: ${result.code}; Raw log: ${result.raw_log}`,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
logs: result.logs ? parseLogs(result.logs) : [],
|
||||
rawLog: result.raw_log || "",
|
||||
transactionHash: result.txhash,
|
||||
};
|
||||
return result.code !== undefined
|
||||
? {
|
||||
height: Uint53.fromString(result.height).toNumber(),
|
||||
transactionHash: result.txhash,
|
||||
code: result.code,
|
||||
rawLog: result.raw_log || "",
|
||||
}
|
||||
: {
|
||||
logs: result.logs ? parseLogs(result.logs) : [],
|
||||
rawLog: result.raw_log || "",
|
||||
transactionHash: result.txhash,
|
||||
data: result.data ? fromHex(result.data) : undefined,
|
||||
};
|
||||
}
|
||||
|
||||
private async txsQuery(query: string): Promise<readonly IndexedTx[]> {
|
||||
|
||||
@ -4,6 +4,7 @@ import { assert, sleep } from "@cosmjs/utils";
|
||||
import { ReadonlyDate } from "readonly-date";
|
||||
|
||||
import { rawSecp256k1PubkeyToAddress } from "./address";
|
||||
import { isPostTxFailure } from "./cosmosclient";
|
||||
import { makeSignBytes } from "./encoding";
|
||||
import { parseLogs } from "./logs";
|
||||
import { makeCosmoshubPath, Secp256k1Pen } from "./pen";
|
||||
@ -275,12 +276,8 @@ describe("RestClient", () => {
|
||||
signatures: [signature],
|
||||
};
|
||||
const transactionId = await client.getIdentifier({ type: "cosmos-sdk/StdTx", value: signedTx });
|
||||
try {
|
||||
await client.postTx(signedTx);
|
||||
} catch (error) {
|
||||
// postTx() throws on execution failures, which is a questionable design. Ignore for now.
|
||||
// console.log(error);
|
||||
}
|
||||
const result = await client.postTx(signedTx);
|
||||
assert(isPostTxFailure(result));
|
||||
unsuccessful = {
|
||||
sender: faucet.address,
|
||||
recipient: recipient,
|
||||
@ -631,7 +628,6 @@ describe("RestClient", () => {
|
||||
signatures: [signature1, signature2, signature3],
|
||||
};
|
||||
const postResult = await client.postTx(signedTx);
|
||||
// console.log(postResult.raw_log);
|
||||
expect(postResult.code).toEqual(4);
|
||||
expect(postResult.raw_log).toContain("wrong number of signers");
|
||||
});
|
||||
@ -691,7 +687,6 @@ describe("RestClient", () => {
|
||||
signatures: [signature1],
|
||||
};
|
||||
const postResult = await client.postTx(signedTx);
|
||||
// console.log(postResult.raw_log);
|
||||
expect(postResult.code).toBeUndefined();
|
||||
});
|
||||
|
||||
@ -755,7 +750,6 @@ describe("RestClient", () => {
|
||||
signatures: [signature2, signature1],
|
||||
};
|
||||
const postResult = await client.postTx(signedTx);
|
||||
// console.log(postResult.raw_log);
|
||||
expect(postResult.code).toBeUndefined();
|
||||
|
||||
await sleep(500);
|
||||
@ -824,7 +818,6 @@ describe("RestClient", () => {
|
||||
signatures: [signature2, signature1],
|
||||
};
|
||||
const postResult = await client.postTx(signedTx);
|
||||
// console.log(postResult.raw_log);
|
||||
expect(postResult.code).toEqual(8);
|
||||
});
|
||||
|
||||
@ -888,7 +881,6 @@ describe("RestClient", () => {
|
||||
signatures: [signature1, signature2],
|
||||
};
|
||||
const postResult = await client.postTx(signedTx);
|
||||
// console.log(postResult.raw_log);
|
||||
expect(postResult.code).toEqual(8);
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { assert } from "@cosmjs/utils";
|
||||
|
||||
import { Coin } from "./coins";
|
||||
import { PrivateCosmWasmClient } from "./cosmosclient";
|
||||
import { isPostTxFailure, PrivateCosmWasmClient } from "./cosmosclient";
|
||||
import { Secp256k1Pen } from "./pen";
|
||||
import { SigningCosmosClient } from "./signingcosmosclient";
|
||||
import { makeRandomAddress, pendingWithoutWasmd } from "./testutils.spec";
|
||||
@ -66,6 +66,7 @@ describe("SigningCosmosClient", () => {
|
||||
|
||||
// send
|
||||
const result = await client.sendTokens(beneficiaryAddress, transferAmount, "for dinner");
|
||||
assert(!isPostTxFailure(result));
|
||||
const [firstLog] = result.logs;
|
||||
expect(firstLog).toBeTruthy();
|
||||
|
||||
|
||||
12
packages/sdk38/types/cosmosclient.d.ts
vendored
12
packages/sdk38/types/cosmosclient.d.ts
vendored
@ -14,12 +14,22 @@ export interface Account {
|
||||
readonly accountNumber: number;
|
||||
readonly sequence: number;
|
||||
}
|
||||
export interface PostTxResult {
|
||||
export interface PostTxFailure {
|
||||
/** Transaction hash (might be used as transaction ID). Guaranteed to be non-empty upper-case hex */
|
||||
readonly transactionHash: string;
|
||||
readonly height: number;
|
||||
readonly code: number;
|
||||
readonly rawLog: string;
|
||||
}
|
||||
export interface PostTxSuccess {
|
||||
readonly logs: readonly Log[];
|
||||
readonly rawLog: string;
|
||||
/** Transaction hash (might be used as transaction ID). Guaranteed to be non-empty upper-case hex */
|
||||
readonly transactionHash: string;
|
||||
readonly data?: Uint8Array;
|
||||
}
|
||||
export declare type PostTxResult = PostTxSuccess | PostTxFailure;
|
||||
export declare function isPostTxFailure(postTxResult: PostTxResult): postTxResult is PostTxFailure;
|
||||
export interface SearchByIdQuery {
|
||||
readonly id: string;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user