@@ -43,8 +43,6 @@ import { decodeAmount, decodePubkey, parseTxsResponseSigned, parseTxsResponseUns
|
||||
import { buildSignedTx } from "./encode";
|
||||
import { accountToNonce, BankToken, Erc20Token } from "./types";
|
||||
|
||||
const { fromAscii } = Encoding;
|
||||
|
||||
// poll every 0.5 seconds (block time 1s)
|
||||
const defaultPollInterval = 500;
|
||||
|
||||
@@ -170,8 +168,7 @@ export class CosmWasmConnection implements BlockchainConnection {
|
||||
this.erc20Tokens.map(
|
||||
async (erc20): Promise<Amount> => {
|
||||
const queryMsg = { balance: { address: address } };
|
||||
const smart = await this.cosmWasmClient.queryContractSmart(erc20.contractAddress, queryMsg);
|
||||
const response = JSON.parse(fromAscii(smart));
|
||||
const response = await this.cosmWasmClient.queryContractSmart(erc20.contractAddress, queryMsg);
|
||||
const normalizedBalance = new BN(response.balance).toString();
|
||||
return {
|
||||
fractionalDigits: erc20.fractionalDigits,
|
||||
|
||||
@@ -60,9 +60,8 @@ const connect = async (mnemonic: string, opts: Partial<Options>): Promise<{
|
||||
};
|
||||
|
||||
// smartQuery assumes the content is proper JSON data and parses before returning it
|
||||
const smartQuery = async (client: CosmWasmClient, addr: string, query: object): Promise<any> => {
|
||||
const bin = await client.queryContractSmart(addr, query);
|
||||
return JSON.parse(fromUtf8(bin));
|
||||
async function smartQuery(client: CosmWasmClient, addr: string, query: object): Promise<any> {
|
||||
return client.queryContractSmart(addr, query);
|
||||
}
|
||||
|
||||
// loadOrCreateMnemonic will try to load a mnemonic from the file.
|
||||
|
||||
@@ -23,7 +23,7 @@ import {
|
||||
} from "./testutils.spec";
|
||||
import { MsgSend, StdFee } from "./types";
|
||||
|
||||
const { fromAscii, fromHex, fromUtf8, toAscii, toBase64 } = Encoding;
|
||||
const { fromHex, fromUtf8, toAscii, toBase64 } = Encoding;
|
||||
|
||||
const guest = {
|
||||
address: "cosmos17d0jcz59jf68g52vq38tuuncmwwjk42u6mcxej",
|
||||
@@ -438,8 +438,8 @@ describe("CosmWasmClient", () => {
|
||||
assert(contract);
|
||||
|
||||
const client = new CosmWasmClient(wasmd.endpoint);
|
||||
const verifier = await client.queryContractSmart(contract.address, { verifier: {} });
|
||||
expect(fromAscii(verifier)).toEqual(contract.initMsg.verifier);
|
||||
const resultDocument = await client.queryContractSmart(contract.address, { verifier: {} });
|
||||
expect(resultDocument).toEqual({ verifier: contract.initMsg.verifier });
|
||||
});
|
||||
|
||||
it("errors for malformed query message", async () => {
|
||||
@@ -449,7 +449,7 @@ describe("CosmWasmClient", () => {
|
||||
const client = new CosmWasmClient(wasmd.endpoint);
|
||||
await client.queryContractSmart(contract.address, { broken: {} }).then(
|
||||
() => fail("must not succeed"),
|
||||
(error) => expect(error).toMatch(/Error parsing QueryMsg/i),
|
||||
(error) => expect(error).toMatch(/query wasm contract failed: parsing hackatom::contract::QueryMsg/i),
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Encoding } from "@iov/encoding";
|
||||
import { Log, parseLogs } from "./logs";
|
||||
import { decodeBech32Pubkey } from "./pubkey";
|
||||
import { BroadcastMode, RestClient } from "./restclient";
|
||||
import { Coin, CosmosSdkTx, PubKey, StdTx } from "./types";
|
||||
import { Coin, CosmosSdkTx, JsonObject, PubKey, StdTx } from "./types";
|
||||
|
||||
export interface GetNonceResult {
|
||||
readonly accountNumber: number;
|
||||
@@ -391,12 +391,13 @@ export class CosmWasmClient {
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a "smart query" on the contract, returns raw data
|
||||
* Makes a smart query on the contract, returns the parsed JSON document.
|
||||
*
|
||||
* Promise is rejected when contract does not exist.
|
||||
* Promise is rejected for invalid query format.
|
||||
* Promise is rejected for invalid response format.
|
||||
*/
|
||||
public async queryContractSmart(address: string, queryMsg: object): Promise<Uint8Array> {
|
||||
public async queryContractSmart(address: string, queryMsg: object): Promise<JsonObject> {
|
||||
try {
|
||||
return await this.restClient.queryContractSmart(address, queryMsg);
|
||||
} catch (error) {
|
||||
|
||||
@@ -1357,13 +1357,14 @@ describe("RestClient", () => {
|
||||
pendingWithoutWasmd();
|
||||
|
||||
// we can query the verifier properly
|
||||
const verifier = await client.queryContractSmart(contractAddress!, { verifier: {} });
|
||||
expect(fromAscii(verifier)).toEqual(faucet.address);
|
||||
const resultDocument = await client.queryContractSmart(contractAddress!, { verifier: {} });
|
||||
expect(resultDocument).toEqual({ verifier: faucet.address });
|
||||
|
||||
// invalid query syntax throws an error
|
||||
await client.queryContractSmart(contractAddress!, { nosuchkey: {} }).then(
|
||||
() => fail("shouldn't succeed"),
|
||||
(error) => expect(error).toMatch("Error parsing QueryMsg"),
|
||||
(error) =>
|
||||
expect(error).toMatch(/query wasm contract failed: parsing hackatom::contract::QueryMsg/),
|
||||
);
|
||||
|
||||
// invalid address throws an error
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Encoding, isNonNullObject } from "@iov/encoding";
|
||||
import axios, { AxiosError, AxiosInstance } from "axios";
|
||||
|
||||
import { Coin, CosmosSdkTx, Model, parseWasmData, StdTx, WasmData } from "./types";
|
||||
import { Coin, CosmosSdkTx, JsonObject, Model, parseWasmData, StdTx, WasmData } from "./types";
|
||||
|
||||
const { fromBase64, toHex, toUtf8 } = Encoding;
|
||||
const { fromBase64, fromUtf8, toHex, toUtf8 } = Encoding;
|
||||
|
||||
export interface CosmosSdkAccount {
|
||||
/** Bech32 account address */
|
||||
@@ -441,14 +441,16 @@ export class RestClient {
|
||||
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<Uint8Array> {
|
||||
/**
|
||||
* Makes a smart query on the contract and parses the reponse as JSON.
|
||||
* Throws error if no such contract exists, the query format is invalid or the response is invalid.
|
||||
*/
|
||||
public async queryContractSmart(address: string, query: object): Promise<JsonObject> {
|
||||
const encoded = toHex(toUtf8(JSON.stringify(query)));
|
||||
const path = `/wasm/contract/${address}/smart/${encoded}?encoding=hex`;
|
||||
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 fromBase64(result.smart);
|
||||
// By convention, smart queries must return a valid JSON document (see https://github.com/CosmWasm/cosmwasm/issues/144)
|
||||
return JSON.parse(fromUtf8(fromBase64(result.smart)));
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
File diff suppressed because one or more lines are too long
@@ -24,9 +24,9 @@ export const bech32AddressMatcher = /^[\x21-\x7e]{1,83}1[02-9ac-hj-np-z]{38}$/;
|
||||
/** Deployed as part of scripts/wasmd/init.sh */
|
||||
export const deployedErc20 = {
|
||||
codeId: 1,
|
||||
source: "https://crates.io/api/v1/crates/cw-erc20/0.3.0/download",
|
||||
source: "https://not-yet-published.cw-erc20",
|
||||
builder: "confio/cosmwasm-opt:0.7.3",
|
||||
checksum: "3dfa55f790a636c11ae2936473734a4d271d441f32d0cfcd7ac19c17b162f85b",
|
||||
checksum: "1f6285492e7ea00596ef472ba166cb96ac3f91d694cb8c8e15f7c023ac451947",
|
||||
instances: [
|
||||
"cosmos18vd8fpwxzck93qlwghaj6arh4p7c5n89uzcee5", // HASH
|
||||
"cosmos1hqrdl6wstt8qzshwc6mrumpjk9338k0lr4dqxd", // ISA
|
||||
|
||||
@@ -169,3 +169,9 @@ export function parseWasmData({ key, val }: WasmData): Model {
|
||||
val: fromBase64(val),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* An object containing a parsed JSON document. The result of JSON.parse().
|
||||
* This doen't privide any type safety over `any` but expresses intent in the code.
|
||||
*/
|
||||
export type JsonObject = any;
|
||||
|
||||
+4
-3
@@ -1,6 +1,6 @@
|
||||
import { Log } from "./logs";
|
||||
import { BroadcastMode, RestClient } from "./restclient";
|
||||
import { Coin, CosmosSdkTx, PubKey, StdTx } from "./types";
|
||||
import { Coin, CosmosSdkTx, JsonObject, PubKey, StdTx } from "./types";
|
||||
export interface GetNonceResult {
|
||||
readonly accountNumber: number;
|
||||
readonly sequence: number;
|
||||
@@ -163,11 +163,12 @@ export declare class CosmWasmClient {
|
||||
*/
|
||||
queryContractRaw(address: string, key: Uint8Array): Promise<Uint8Array | null>;
|
||||
/**
|
||||
* Makes a "smart query" on the contract, returns raw data
|
||||
* Makes a smart query on the contract, returns the parsed JSON document.
|
||||
*
|
||||
* Promise is rejected when contract does not exist.
|
||||
* Promise is rejected for invalid query format.
|
||||
* Promise is rejected for invalid response format.
|
||||
*/
|
||||
queryContractSmart(address: string, queryMsg: object): Promise<Uint8Array>;
|
||||
queryContractSmart(address: string, queryMsg: object): Promise<JsonObject>;
|
||||
private txsQuery;
|
||||
}
|
||||
|
||||
Vendored
+6
-2
@@ -1,4 +1,4 @@
|
||||
import { Coin, CosmosSdkTx, Model, StdTx } from "./types";
|
||||
import { Coin, CosmosSdkTx, JsonObject, Model, StdTx } from "./types";
|
||||
export interface CosmosSdkAccount {
|
||||
/** Bech32 account address */
|
||||
readonly address: string;
|
||||
@@ -221,6 +221,10 @@ export declare class RestClient {
|
||||
getContractInfo(address: string): Promise<ContractDetails | null>;
|
||||
getAllContractState(address: string): Promise<readonly Model[]>;
|
||||
queryContractRaw(address: string, key: Uint8Array): Promise<Uint8Array | null>;
|
||||
queryContractSmart(address: string, query: object): Promise<Uint8Array>;
|
||||
/**
|
||||
* Makes a smart query on the contract and parses the reponse as JSON.
|
||||
* Throws error if no such contract exists, the query format is invalid or the response is invalid.
|
||||
*/
|
||||
queryContractSmart(address: string, query: object): Promise<JsonObject>;
|
||||
}
|
||||
export {};
|
||||
|
||||
Vendored
+5
@@ -118,4 +118,9 @@ export interface Model {
|
||||
readonly val: Uint8Array;
|
||||
}
|
||||
export declare function parseWasmData({ key, val }: WasmData): Model;
|
||||
/**
|
||||
* An object containing a parsed JSON document. The result of JSON.parse().
|
||||
* This doen't privide any type safety over `any` but expresses intent in the code.
|
||||
*/
|
||||
export declare type JsonObject = any;
|
||||
export {};
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
3dfa55f790a636c11ae2936473734a4d271d441f32d0cfcd7ac19c17b162f85b cw-erc20.wasm
|
||||
d5dde423d321f7d3793a9b1667d06ac86c7f57dfbd2534a9c790963e1c2955ed cw-nameservice.wasm
|
||||
1f6285492e7ea00596ef472ba166cb96ac3f91d694cb8c8e15f7c023ac451947 cw-erc20.wasm
|
||||
7c0e964c9a46f53af8a4097fbf45edf9670c1813b99f4ecb1084ccadb30de2fe cw-nameservice.wasm
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -22,7 +22,7 @@ const guest = {
|
||||
};
|
||||
|
||||
const codeMeta = {
|
||||
source: "https://crates.io/api/v1/crates/cw-erc20/0.3.0/download",
|
||||
source: "https://not-yet-published.cw-erc20",
|
||||
builder: "confio/cosmwasm-opt:0.7.3",
|
||||
};
|
||||
|
||||
|
||||
@@ -12,8 +12,8 @@ const faucet = {
|
||||
};
|
||||
|
||||
const codeMeta = {
|
||||
source: "https://crates.io/api/v1/crates/cw-nameservice/0.2.0/download",
|
||||
builder: "confio/cosmwasm-opt:0.7.0",
|
||||
source: "https://not-yet-published.cw-nameservice",
|
||||
builder: "confio/cosmwasm-opt:0.7.3",
|
||||
};
|
||||
|
||||
const free = {
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
# Choose from https://hub.docker.com/r/cosmwasm/wasmd-demo/tags
|
||||
REPOSITORY="cosmwasm/wasmd-demo"
|
||||
VERSION="v0.7.1"
|
||||
VERSION="v0.8.0-alpha3"
|
||||
|
||||
CONTAINER_NAME="wasmd"
|
||||
|
||||
Reference in New Issue
Block a user