Return full info on 500 errors

This commit is contained in:
Ethan Frey 2020-02-10 12:41:47 +01:00
parent efcca8a769
commit abe8eeeac3
3 changed files with 41 additions and 9 deletions

View File

@ -421,6 +421,8 @@ describe("RestClient", () => {
// create new instance and compare before and after
const existingContracts = await client.listContractAddresses();
const existingContractsByCode = await client.listContractsByCodeId(codeId);
existingContractsByCode.forEach(ctc => expect(ctc.code_id).toEqual(codeId));
const result = await instantiateContract(client, pen, codeId, beneficiaryAddress, transferAmount);
expect(result.code).toBeFalsy();
@ -437,6 +439,11 @@ describe("RestClient", () => {
const lastContract = diff[0];
expect(lastContract).toEqual(myAddress);
// also by codeID list
const newContractsByCode = await client.listContractsByCodeId(codeId);
newContractsByCode.forEach(ctc => expect(ctc.code_id).toEqual(codeId));
expect(newContractsByCode.length).toEqual(existingContractsByCode.length + 1);
// check out info
const myInfo = await client.getContractInfo(myAddress);
expect(myInfo.code_id).toEqual(codeId);
@ -514,18 +521,14 @@ describe("RestClient", () => {
// invalid query syntax throws an error
await client.queryContractSmart(contractAddress, { nosuchkey: {} }).then(
() => fail("shouldn't succeed"),
error => expect(error).toBeTruthy(),
error => expect(error).toMatch("Error parsing QueryMsg"),
);
// TODO: debug rest server. I expect a 'Parse Error', but get
// Request failed with status code 500 to match 'Parse Error:'
// invalid address throws an error
await client.queryContractSmart(noContract, { verifier: {} }).then(
() => fail("shouldn't succeed"),
error => expect(error).toBeTruthy(),
error => expect(error).toMatch("not found"),
);
// TODO: debug rest server. I expect a 'not found', but get
// Request failed with status code 500 to match 'Parse Error:'
});
});
});

View File

@ -1,5 +1,5 @@
import { Encoding } from "@iov/encoding";
import axios, { AxiosInstance } from "axios";
import axios, { AxiosError, AxiosInstance } from "axios";
import { AminoTx, CodeInfo, ContractInfo, CosmosSdkAccount, isAminoStdTx, StdTx, WasmData } from "./types";
@ -128,6 +128,26 @@ function parseWasmResponse(response: WasmResponse<string>): any {
return JSON.parse(response.result);
}
// We want to get message data from 500 errors
// https://stackoverflow.com/questions/56577124/how-to-handle-500-error-message-with-axios
// this should be chained to catch one error and throw a more informative one
function parseAxios500error(err: AxiosError): never {
// use the error message sent from server, not default 500 msg
if (err.response?.data) {
const data = err.response.data;
// expect { error: string }, but otherwise dump
if (data.error) {
throw new Error(data.error);
} else if (typeof data === "string") {
throw new Error(data);
} else {
throw new Error(JSON.stringify(data));
}
} else {
throw err;
}
}
export class RestClient {
private readonly client: AxiosInstance;
// From https://cosmos.network/rpc/#/ICS0/post_txs
@ -146,7 +166,7 @@ export class RestClient {
}
public async get(path: string): Promise<RestClientResponse> {
const { data } = await this.client.get(path);
const { data } = await this.client.get(path).catch(parseAxios500error);
if (data === null) {
throw new Error("Received null response from server");
}
@ -154,7 +174,7 @@ export class RestClient {
}
public async post(path: string, params: PostTxsParams): Promise<RestClientResponse> {
const { data } = await this.client.post(path, params);
const { data } = await this.client.post(path, params).catch(parseAxios500error);
if (data === null) {
throw new Error("Received null response from server");
}
@ -264,6 +284,14 @@ export class RestClient {
return addresses || [];
}
public async listContractsByCodeId(id: number): Promise<readonly ContractInfo[]> {
const path = `/wasm/code/${id}/contracts`;
const responseData = await this.get(path);
// answer may be null (go's encoding of empty array)
const contracts: ContractInfo[] | null = parseWasmResponse(responseData as WasmResponse);
return contracts || [];
}
// throws error if no contract at this address
public async getContractInfo(address: string): Promise<ContractInfo> {
const path = `/wasm/contract/${address}`;

View File

@ -100,6 +100,7 @@ export declare class RestClient {
listCodeInfo(): Promise<readonly CodeInfo[]>;
getCode(id: number): Promise<Uint8Array>;
listContractAddresses(): Promise<readonly string[]>;
listContractsByCodeId(id: number): Promise<readonly ContractInfo[]>;
getContractInfo(address: string): Promise<ContractInfo>;
getAllContractState(address: string): Promise<readonly WasmData[]>;
queryContractRaw(address: string, key: Uint8Array): Promise<unknown | null>;