Download wasm code by id works

This commit is contained in:
Ethan Frey 2020-02-10 12:18:19 +01:00
parent f1e1c76baa
commit efcca8a769
3 changed files with 49 additions and 22 deletions

View File

@ -1,5 +1,5 @@
/* eslint-disable @typescript-eslint/camelcase */
import { Random } from "@iov/crypto";
import { Random, Sha256 } from "@iov/crypto";
import { Bech32, Encoding } from "@iov/encoding";
import { encodeSecp256k1Signature, makeSignBytes, marshalTx } from "./encoding";
@ -85,13 +85,17 @@ function makeRandomAddress(): string {
return Bech32.encode("cosmos", Random.getBytes(20));
}
async function uploadContract(client: RestClient, pen: Pen): Promise<PostTxsResponse> {
async function uploadCustomContract(
client: RestClient,
pen: Pen,
wasmCode: Uint8Array,
): Promise<PostTxsResponse> {
const memo = "My first contract on chain";
const theMsg: MsgStoreCode = {
type: "wasm/store-code",
value: {
sender: faucet.address,
wasm_byte_code: toBase64(getRandomizedContract()),
wasm_byte_code: toBase64(wasmCode),
source: "https://github.com/confio/cosmwasm/raw/0.7/lib/vm/testdata/contract_0.6.wasm",
builder: "cosmwasm-opt:0.6.2",
},
@ -113,6 +117,10 @@ async function uploadContract(client: RestClient, pen: Pen): Promise<PostTxsResp
return client.postTx(marshalTx(signedTx));
}
async function uploadContract(client: RestClient, pen: Pen): Promise<PostTxsResponse> {
return uploadCustomContract(client, pen, getRandomizedContract());
}
async function instantiateContract(
client: RestClient,
pen: Pen,
@ -223,9 +231,8 @@ describe("RestClient", () => {
});
});
// TODO: re-enable when stable
// this is failing for me on first run (faucet has not signed anything)
xit("has correct pubkey for faucet", async () => {
it("has correct pubkey for faucet", async () => {
pendingWithoutCosmos();
const client = new RestClient(httpUrl);
const { result } = await client.authAccounts(faucet.address);
@ -364,7 +371,8 @@ describe("RestClient", () => {
const numExisting = existingInfos.length;
// upload data
const result = await uploadContract(client, pen);
const wasmCode = getRandomizedContract();
const result = await uploadCustomContract(client, pen, wasmCode);
expect(result.code).toBeFalsy();
const logs = parseLogs(result.logs);
const codeIdAttr = findAttribute(logs, "message", "code_id");
@ -377,10 +385,13 @@ describe("RestClient", () => {
expect(lastInfo.id).toEqual(codeId);
expect(lastInfo.creator).toEqual(faucet.address);
// TODO: check code hash matches expectation
// expect(lastInfo.code_hash).toEqual(faucet.address);
// check code hash matches expectation
const wasmHash = new Sha256(wasmCode).digest();
expect(lastInfo.code_hash.toLowerCase()).toEqual(toHex(wasmHash));
// TODO: download code and check against auto-gen
// download code and check against auto-gen
const download = await client.getCode(codeId);
expect(download).toEqual(wasmCode);
});
it("can list contracts and get info", async () => {

View File

@ -45,11 +45,11 @@ interface AuthAccountsResponse {
// Currently all wasm query responses return json-encoded strings...
// later deprecate this and use the specific types for result
// (assuming it is inlined, no second parse needed)
type WasmResponse = WasmSuccess | WasmError;
type WasmResponse<T = string> = WasmSuccess<T> | WasmError;
interface WasmSuccess {
interface WasmSuccess<T = string> {
readonly height: string;
readonly result: string;
readonly result: T;
}
interface WasmError {
@ -92,6 +92,11 @@ interface EncodeTxResponse {
readonly tx: string;
}
interface GetCodeResult {
// base64 encoded wasm
readonly code: string;
}
type RestClientResponse =
| NodeInfoResponse
| BlocksResponse
@ -100,15 +105,23 @@ type RestClientResponse =
| SearchTxsResponse
| PostTxsResponse
| EncodeTxResponse
| WasmResponse;
| WasmResponse<string>
| WasmResponse<GetCodeResult>;
type BroadcastMode = "block" | "sync" | "async";
function isWasmError(resp: WasmResponse): resp is WasmError {
function isWasmError<T>(resp: WasmResponse<T>): resp is WasmError {
return (resp as WasmError).error !== undefined;
}
function parseWasmResponse(response: WasmResponse): any {
function unwrapWasmResponse<T>(response: WasmResponse<T>): T {
if (isWasmError(response)) {
throw new Error(response.error);
}
return response.result;
}
function parseWasmResponse(response: WasmResponse<string>): any {
if (isWasmError(response)) {
throw new Error(response.error);
}
@ -237,10 +250,9 @@ export class RestClient {
// this will download the original wasm bytecode by code id
// throws error if no code with this id
public async getCode(id: number): Promise<Uint8Array> {
// TODO: broken currently
const path = `/wasm/code/${id}`;
const responseData = await this.get(path);
const { code } = parseWasmResponse(responseData as WasmResponse);
const responseData = (await this.get(path)) as WasmResponse<GetCodeResult>;
const { code } = unwrapWasmResponse(responseData);
return fromBase64(code);
}

View File

@ -30,10 +30,10 @@ interface AuthAccountsResponse {
readonly value: CosmosSdkAccount;
};
}
declare type WasmResponse = WasmSuccess | WasmError;
interface WasmSuccess {
declare type WasmResponse<T = string> = WasmSuccess<T> | WasmError;
interface WasmSuccess<T = string> {
readonly height: string;
readonly result: string;
readonly result: T;
}
interface WasmError {
readonly error: string;
@ -68,6 +68,9 @@ export interface PostTxsResponse {
interface EncodeTxResponse {
readonly tx: string;
}
interface GetCodeResult {
readonly code: string;
}
declare type RestClientResponse =
| NodeInfoResponse
| BlocksResponse
@ -76,7 +79,8 @@ declare type RestClientResponse =
| SearchTxsResponse
| PostTxsResponse
| EncodeTxResponse
| WasmResponse;
| WasmResponse<string>
| WasmResponse<GetCodeResult>;
declare type BroadcastMode = "block" | "sync" | "async";
export declare class RestClient {
private readonly client;