Merge pull request #73 from confio/update-rest-queries

Update return types for queries
This commit is contained in:
merge-when-green[bot] 2020-02-11 10:34:14 +00:00 committed by GitHub
commit 708f7744e7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 72 additions and 35 deletions

View File

@ -41,7 +41,7 @@ import { Caip5 } from "./caip5";
import { decodeAmount, parseTxsResponse } from "./decode";
import { accountToNonce, BankToken, Erc20Token } from "./types";
const { toHex } = Encoding;
const { fromAscii, toHex } = Encoding;
interface ChainData {
readonly chainId: ChainId;
@ -168,9 +168,8 @@ export class CosmWasmConnection implements BlockchainConnection {
this.erc20Tokens.map(
async (erc20): Promise<Amount> => {
const queryMsg = { balance: { address: address } };
const response = JSON.parse(
await this.restClient.queryContractSmart(erc20.contractAddress, queryMsg),
);
const smart = await this.restClient.queryContractSmart(erc20.contractAddress, queryMsg);
const response = JSON.parse(fromAscii(smart));
const normalizedBalance = new BN(response.balance).toString();
return {
fractionalDigits: erc20.fractionalDigits,

View File

@ -23,7 +23,7 @@ import {
StdTx,
} from "./types";
const { fromBase64, fromHex, toAscii, toBase64, toHex } = Encoding;
const { fromAscii, fromBase64, fromHex, toAscii, toBase64, toHex } = Encoding;
const httpUrl = "http://localhost:1317";
const defaultNetworkId = "testing";
@ -496,9 +496,10 @@ describe("RestClient", () => {
const state = await client.getAllContractState(contractAddress!);
expect(state.length).toEqual(1);
const data = state[0];
expect(data.key.toLowerCase()).toEqual(toHex(expectedKey));
expect((data.val as any).verifier).toBeDefined();
expect((data.val as any).beneficiary).toBeDefined();
expect(data.key).toEqual(expectedKey);
const value = JSON.parse(fromAscii(data.val));
expect(value.verifier).toBeDefined();
expect(value.beneficiary).toBeDefined();
// bad address is empty array
const noContractState = await client.getAllContractState(noContract);
@ -509,10 +510,11 @@ describe("RestClient", () => {
pendingWithoutCosmos();
// query by one key
const model = await client.queryContractRaw(contractAddress!, expectedKey);
expect(model).not.toBeNull();
expect((model as any).verifier).toBeDefined();
expect((model as any).beneficiary).toBeDefined();
const raw = await client.queryContractRaw(contractAddress!, expectedKey);
assert(raw, "must get result");
const model = JSON.parse(fromAscii(raw));
expect(model.verifier).toBeDefined();
expect(model.beneficiary).toBeDefined();
// missing key is null
const missing = await client.queryContractRaw(contractAddress!, fromHex("cafe0dad"));
@ -528,7 +530,7 @@ describe("RestClient", () => {
// we can query the verifier properly
const verifier = await client.queryContractSmart(contractAddress!, { verifier: {} });
expect(verifier).toEqual(faucet.address);
expect(fromAscii(verifier)).toEqual(faucet.address);
// invalid query syntax throws an error
await client.queryContractSmart(contractAddress!, { nosuchkey: {} }).then(

View File

@ -1,7 +1,17 @@
import { Encoding } from "@iov/encoding";
import axios, { AxiosError, AxiosInstance } from "axios";
import { AminoTx, CodeInfo, ContractInfo, CosmosSdkAccount, isAminoStdTx, StdTx, WasmData } from "./types";
import {
AminoTx,
CodeInfo,
ContractInfo,
CosmosSdkAccount,
isAminoStdTx,
Model,
parseWasmData,
StdTx,
WasmData,
} from "./types";
const { fromBase64, fromUtf8, toHex, toUtf8 } = Encoding;
@ -97,6 +107,11 @@ interface GetCodeResult {
readonly code: string;
}
interface SmartQueryResponse {
// base64 encoded response
readonly smart: string;
}
type RestClientResponse =
| NodeInfoResponse
| BlocksResponse
@ -306,32 +321,31 @@ export class RestClient {
// Returns all contract state.
// This is an empty array if no such contract, or contract has no data.
public async getAllContractState(address: string): Promise<readonly WasmData[]> {
public async getAllContractState(address: string): Promise<readonly Model[]> {
const path = `/wasm/contract/${address}/state`;
const responseData = await this.get(path);
return parseWasmResponse(responseData as WasmResponse);
const responseData = (await this.get(path)) as WasmResponse<WasmData[]>;
const r = unwrapWasmResponse(responseData);
return r ? r.map(parseWasmData) : [];
}
// Returns the data at the key if present (unknown decoded json),
// or null if no data at this (contract address, key) pair
public async queryContractRaw(address: string, key: Uint8Array): Promise<unknown | null> {
public async queryContractRaw(address: string, key: Uint8Array): Promise<Uint8Array | null> {
const hexKey = toHex(key);
const path = `/wasm/contract/${address}/raw/${hexKey}?encoding=hex`;
const responseData = await this.get(path);
const data: readonly WasmData[] = parseWasmResponse(responseData as WasmResponse);
return data.length === 0 ? null : data[0].val;
const responseData = (await this.get(path)) as WasmResponse<WasmData[]>;
const data = unwrapWasmResponse(responseData);
return data.length === 0 ? null : fromBase64(data[0].val);
}
// Makes a "smart query" on the contract, returns response verbatim (json.RawMessage)
// Throws error if no such contract or invalid query format
public async queryContractSmart(address: string, query: object): Promise<string> {
public async queryContractSmart(address: string, query: object): Promise<Uint8Array> {
const encoded = toHex(toUtf8(JSON.stringify(query)));
const path = `/wasm/contract/${address}/smart/${encoded}?encoding=hex`;
const responseData = (await this.get(path)) as WasmResponse;
if (isWasmError(responseData)) {
throw new Error(responseData.error);
}
const responseData = (await this.get(path)) as WasmResponse<SmartQueryResponse>;
const result = unwrapWasmResponse(responseData);
// no extra parse here for now, see https://github.com/confio/cosmwasm/issues/144
return responseData.result;
return fromBase64(result.smart);
}
}

View File

@ -1,3 +1,7 @@
import { Encoding } from "@iov/encoding";
const { fromBase64, fromHex } = Encoding;
// We will move all needed *interfaces* from amino-js here
// This means bcp can just import them from here (if needed at all)
export interface Tx {
@ -190,6 +194,19 @@ export interface ContractInfo {
export interface WasmData {
// key is hex-encoded
readonly key: string;
// value can be any decoded json, often an object but can be anything
readonly val: unknown;
// value is base64 encoded
readonly val: string;
}
// Model is a parsed WasmData object
export interface Model {
readonly key: Uint8Array;
readonly val: Uint8Array;
}
export function parseWasmData({ key, val }: WasmData): Model {
return {
key: fromHex(key),
val: fromBase64(val),
};
}

View File

@ -1,4 +1,4 @@
import { AminoTx, CodeInfo, ContractInfo, CosmosSdkAccount, StdTx, WasmData } from "./types";
import { AminoTx, CodeInfo, ContractInfo, CosmosSdkAccount, Model, StdTx } from "./types";
interface NodeInfo {
readonly network: string;
}
@ -102,8 +102,8 @@ export declare class RestClient {
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>;
queryContractSmart(address: string, query: object): Promise<string>;
getAllContractState(address: string): Promise<readonly Model[]>;
queryContractRaw(address: string, key: Uint8Array): Promise<Uint8Array | null>;
queryContractSmart(address: string, query: object): Promise<Uint8Array>;
}
export {};

View File

@ -141,6 +141,11 @@ export interface ContractInfo {
}
export interface WasmData {
readonly key: string;
readonly val: unknown;
readonly val: string;
}
export interface Model {
readonly key: Uint8Array;
readonly val: Uint8Array;
}
export declare function parseWasmData({ key, val }: WasmData): Model;
export {};

View File

@ -1,5 +1,5 @@
# Choose from https://hub.docker.com/r/cosmwasm/wasmd-demo/tags
REPOSITORY="cosmwasm/wasmd-demo"
VERSION="v0.0.5"
VERSION="v0.6.0"
CONTAINER_NAME="wasmd"