Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Online signer Prototype #403

Closed
wants to merge 11 commits into from
2 changes: 1 addition & 1 deletion packages/cli/examples/coralnet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const coralnetOptions: Options = {
const wallet = await Secp256k1Wallet.generate(12, coralnetOptions.hdPath, coralnetOptions.bech32prefix);
const [{ address }] = await wallet.getAccounts();

const client = new SigningCosmWasmClient(
const client = SigningCosmWasmClient.fromOfflineSigner(
coralnetOptions.httpUrl,
address,
wallet,
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/examples/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ const connect = async (
const wallet = await Secp256k1Wallet.fromMnemonic(mnemonic);
const [{ address }] = await wallet.getAccounts();

const client = new SigningCosmWasmClient(options.httpUrl, address, wallet, gasPrice);
const client = SigningCosmWasmClient.fromOfflineSigner(options.httpUrl, address, wallet, gasPrice);
return { client, address };
};

Expand Down
82 changes: 0 additions & 82 deletions packages/cli/examples/mask.ts

This file was deleted.

2 changes: 1 addition & 1 deletion packages/cosmwasm/src/cosmwasmclient.searchtx.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ describe("CosmWasmClient.searchTx", () => {
beforeAll(async () => {
if (wasmdEnabled()) {
const wallet = await Secp256k1Wallet.fromMnemonic(alice.mnemonic);
const client = new SigningCosmWasmClient(wasmd.endpoint, alice.address0, wallet);
const client = SigningCosmWasmClient.fromOfflineSigner(wasmd.endpoint, alice.address0, wallet);

{
const recipient = makeRandomAddress();
Expand Down
4 changes: 2 additions & 2 deletions packages/cosmwasm/src/cosmwasmclient.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,7 @@ describe("CosmWasmClient", () => {
if (wasmdEnabled()) {
pendingWithoutWasmd();
const wallet = await Secp256k1Wallet.fromMnemonic(alice.mnemonic);
const client = new SigningCosmWasmClient(wasmd.endpoint, alice.address0, wallet);
const client = SigningCosmWasmClient.fromOfflineSigner(wasmd.endpoint, alice.address0, wallet);
const { codeId } = await client.upload(getHackatom().data);
const initMsg = { verifier: makeRandomAddress(), beneficiary: makeRandomAddress() };
const { contractAddress } = await client.instantiate(codeId, initMsg, "random hackatom");
Expand Down Expand Up @@ -423,7 +423,7 @@ describe("CosmWasmClient", () => {
if (wasmdEnabled()) {
pendingWithoutWasmd();
const wallet = await Secp256k1Wallet.fromMnemonic(alice.mnemonic);
const client = new SigningCosmWasmClient(wasmd.endpoint, alice.address0, wallet);
const client = SigningCosmWasmClient.fromOfflineSigner(wasmd.endpoint, alice.address0, wallet);
const { codeId } = await client.upload(getHackatom().data);
const initMsg = { verifier: makeRandomAddress(), beneficiary: makeRandomAddress() };
const { contractAddress } = await client.instantiate(codeId, initMsg, "a different hackatom");
Expand Down
4 changes: 2 additions & 2 deletions packages/cosmwasm/src/lcdapi/wasm.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ async function uploadContract(
};

const firstAddress = (await signer.getAccounts())[0].address;
const client = new SigningCosmosClient(wasmd.endpoint, firstAddress, signer);
const client = SigningCosmosClient.fromOfflineSigner(wasmd.endpoint, firstAddress, signer);
return client.signAndBroadcast([theMsg], fee, memo);
}

Expand Down Expand Up @@ -99,7 +99,7 @@ async function instantiateContract(
};

const firstAddress = (await signer.getAccounts())[0].address;
const client = new SigningCosmosClient(wasmd.endpoint, firstAddress, signer);
const client = SigningCosmosClient.fromOfflineSigner(wasmd.endpoint, firstAddress, signer);
return client.signAndBroadcast([theMsg], fee, memo);
}

Expand Down
44 changes: 28 additions & 16 deletions packages/cosmwasm/src/signingcosmwasmclient.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,14 @@ describe("SigningCosmWasmClient", () => {
describe("makeReadOnly", () => {
it("can be constructed", async () => {
const wallet = await Secp256k1Wallet.fromMnemonic(alice.mnemonic);
const client = new SigningCosmWasmClient(httpUrl, alice.address0, wallet);
const client = SigningCosmWasmClient.fromOfflineSigner(httpUrl, alice.address0, wallet);
expect(client).toBeTruthy();
});

it("can be constructed with custom gas price", async () => {
const wallet = await Secp256k1Wallet.fromMnemonic(alice.mnemonic);
const gasPrice = GasPrice.fromString("3.14utest");
const client = new SigningCosmWasmClient(httpUrl, alice.address0, wallet, gasPrice);
const client = SigningCosmWasmClient.fromOfflineSigner(httpUrl, alice.address0, wallet, gasPrice);
const openedClient = (client as unknown) as PrivateSigningCosmWasmClient;
expect(openedClient.fees).toEqual({
upload: {
Expand Down Expand Up @@ -108,7 +108,13 @@ describe("SigningCosmWasmClient", () => {
const gasLimits = {
send: 160000,
};
const client = new SigningCosmWasmClient(httpUrl, alice.address0, wallet, undefined, gasLimits);
const client = SigningCosmWasmClient.fromOfflineSigner(
httpUrl,
alice.address0,
wallet,
undefined,
gasLimits,
);
const openedClient = (client as unknown) as PrivateSigningCosmWasmClient;
expect(openedClient.fees).toEqual({
upload: {
Expand Down Expand Up @@ -174,7 +180,13 @@ describe("SigningCosmWasmClient", () => {
const gasLimits = {
send: 160000,
};
const client = new SigningCosmWasmClient(httpUrl, alice.address0, wallet, gasPrice, gasLimits);
const client = SigningCosmWasmClient.fromOfflineSigner(
httpUrl,
alice.address0,
wallet,
gasPrice,
gasLimits,
);
const openedClient = (client as unknown) as PrivateSigningCosmWasmClient;
expect(openedClient.fees).toEqual({
upload: {
Expand Down Expand Up @@ -239,7 +251,7 @@ describe("SigningCosmWasmClient", () => {
it("always uses authAccount implementation", async () => {
pendingWithoutWasmd();
const wallet = await Secp256k1Wallet.fromMnemonic(alice.mnemonic);
const client = new SigningCosmWasmClient(httpUrl, alice.address0, wallet);
const client = SigningCosmWasmClient.fromOfflineSigner(httpUrl, alice.address0, wallet);

const openedClient = (client as unknown) as PrivateCosmWasmClient;
const blockLatestSpy = spyOn(openedClient.lcdClient, "blocksLatest").and.callThrough();
Expand All @@ -257,7 +269,7 @@ describe("SigningCosmWasmClient", () => {
it("works", async () => {
pendingWithoutWasmd();
const wallet = await Secp256k1Wallet.fromMnemonic(alice.mnemonic);
const client = new SigningCosmWasmClient(httpUrl, alice.address0, wallet);
const client = SigningCosmWasmClient.fromOfflineSigner(httpUrl, alice.address0, wallet);
const wasm = getHackatom().data;
const {
codeId,
Expand All @@ -276,7 +288,7 @@ describe("SigningCosmWasmClient", () => {
it("can set builder and source", async () => {
pendingWithoutWasmd();
const wallet = await Secp256k1Wallet.fromMnemonic(alice.mnemonic);
const client = new SigningCosmWasmClient(httpUrl, alice.address0, wallet);
const client = SigningCosmWasmClient.fromOfflineSigner(httpUrl, alice.address0, wallet);
const hackatom = getHackatom();

const meta: UploadMeta = {
Expand All @@ -295,7 +307,7 @@ describe("SigningCosmWasmClient", () => {
it("works with transfer amount", async () => {
pendingWithoutWasmd();
const wallet = await Secp256k1Wallet.fromMnemonic(alice.mnemonic);
const client = new SigningCosmWasmClient(httpUrl, alice.address0, wallet);
const client = SigningCosmWasmClient.fromOfflineSigner(httpUrl, alice.address0, wallet);
const { codeId } = await client.upload(getHackatom().data);

const transferAmount = [coin(1234, "ucosm"), coin(321, "ustake")];
Expand All @@ -321,7 +333,7 @@ describe("SigningCosmWasmClient", () => {
it("works with admin", async () => {
pendingWithoutWasmd();
const wallet = await Secp256k1Wallet.fromMnemonic(alice.mnemonic);
const client = new SigningCosmWasmClient(httpUrl, alice.address0, wallet);
const client = SigningCosmWasmClient.fromOfflineSigner(httpUrl, alice.address0, wallet);
const { codeId } = await client.upload(getHackatom().data);

const beneficiaryAddress = makeRandomAddress();
Expand All @@ -344,7 +356,7 @@ describe("SigningCosmWasmClient", () => {
it("can instantiate one code multiple times", async () => {
pendingWithoutWasmd();
const wallet = await Secp256k1Wallet.fromMnemonic(alice.mnemonic);
const client = new SigningCosmWasmClient(httpUrl, alice.address0, wallet);
const client = SigningCosmWasmClient.fromOfflineSigner(httpUrl, alice.address0, wallet);
const { codeId } = await client.upload(getHackatom().data);

const contractAddress1 = await client.instantiate(
Expand All @@ -371,7 +383,7 @@ describe("SigningCosmWasmClient", () => {
it("can update an admin", async () => {
pendingWithoutWasmd();
const wallet = await Secp256k1Wallet.fromMnemonic(alice.mnemonic);
const client = new SigningCosmWasmClient(httpUrl, alice.address0, wallet);
const client = SigningCosmWasmClient.fromOfflineSigner(httpUrl, alice.address0, wallet);
const { codeId } = await client.upload(getHackatom().data);

const beneficiaryAddress = makeRandomAddress();
Expand Down Expand Up @@ -404,7 +416,7 @@ describe("SigningCosmWasmClient", () => {
it("can clear an admin", async () => {
pendingWithoutWasmd();
const wallet = await Secp256k1Wallet.fromMnemonic(alice.mnemonic);
const client = new SigningCosmWasmClient(httpUrl, alice.address0, wallet);
const client = SigningCosmWasmClient.fromOfflineSigner(httpUrl, alice.address0, wallet);
const { codeId } = await client.upload(getHackatom().data);

const beneficiaryAddress = makeRandomAddress();
Expand Down Expand Up @@ -437,7 +449,7 @@ describe("SigningCosmWasmClient", () => {
it("can can migrate from one code ID to another", async () => {
pendingWithoutWasmd();
const wallet = await Secp256k1Wallet.fromMnemonic(alice.mnemonic);
const client = new SigningCosmWasmClient(httpUrl, alice.address0, wallet);
const client = SigningCosmWasmClient.fromOfflineSigner(httpUrl, alice.address0, wallet);
const { codeId: codeId1 } = await client.upload(getHackatom().data);
const { codeId: codeId2 } = await client.upload(getHackatom().data);

Expand Down Expand Up @@ -475,7 +487,7 @@ describe("SigningCosmWasmClient", () => {
it("works", async () => {
pendingWithoutWasmd();
const wallet = await Secp256k1Wallet.fromMnemonic(alice.mnemonic);
const client = new SigningCosmWasmClient(httpUrl, alice.address0, wallet);
const client = SigningCosmWasmClient.fromOfflineSigner(httpUrl, alice.address0, wallet);
const { codeId } = await client.upload(getHackatom().data);

// instantiate
Expand Down Expand Up @@ -516,7 +528,7 @@ describe("SigningCosmWasmClient", () => {
it("works", async () => {
pendingWithoutWasmd();
const wallet = await Secp256k1Wallet.fromMnemonic(alice.mnemonic);
const client = new SigningCosmWasmClient(httpUrl, alice.address0, wallet);
const client = SigningCosmWasmClient.fromOfflineSigner(httpUrl, alice.address0, wallet);

// instantiate
const transferAmount = coins(7890, "ucosm");
Expand All @@ -543,7 +555,7 @@ describe("SigningCosmWasmClient", () => {
it("works", async () => {
pendingWithoutWasmd();
const wallet = await Secp256k1Wallet.fromMnemonic(alice.mnemonic);
const client = new SigningCosmWasmClient(httpUrl, alice.address0, wallet);
const client = SigningCosmWasmClient.fromOfflineSigner(httpUrl, alice.address0, wallet);

const msg: MsgDelegate = {
type: "cosmos-sdk/MsgDelegate",
Expand Down
36 changes: 22 additions & 14 deletions packages/cosmwasm/src/signingcosmwasmclient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ import {
CosmosFeeTable,
GasLimits,
GasPrice,
InProcessOnlineSigner,
isBroadcastTxFailure,
makeSignBytes,
Msg,
MsgSend,
OfflineSigner,
OnlineSigner,
StdFee,
StdTx,
} from "@cosmjs/launchpad";
import { Uint53 } from "@cosmjs/math";
import pako from "pako";
Expand Down Expand Up @@ -151,9 +151,21 @@ export interface PrivateSigningCosmWasmClient {
export class SigningCosmWasmClient extends CosmWasmClient {
public readonly senderAddress: string;

private readonly signer: OfflineSigner;
private readonly signer: OnlineSigner;
private readonly fees: CosmWasmFeeTable;

public static fromOfflineSigner(
apiUrl: string,
senderAddress: string,
signer: OfflineSigner,
gasPrice: GasPrice = defaultGasPrice,
gasLimits: Partial<GasLimits<CosmosFeeTable>> = {},
broadcastMode = BroadcastMode.Block,
): SigningCosmWasmClient {
const online = new InProcessOnlineSigner(signer, apiUrl, broadcastMode);
return new SigningCosmWasmClient(apiUrl, senderAddress, online, gasPrice, gasLimits, broadcastMode);
}

/**
* Creates a new client with signing capability to interact with a CosmWasm blockchain. This is the bigger brother of CosmWasmClient.
*
Expand All @@ -170,7 +182,7 @@ export class SigningCosmWasmClient extends CosmWasmClient {
public constructor(
apiUrl: string,
senderAddress: string,
signer: OfflineSigner,
signer: OnlineSigner,
gasPrice: GasPrice = defaultGasPrice,
gasLimits: Partial<GasLimits<CosmWasmFeeTable>> = {},
broadcastMode = BroadcastMode.Block,
Expand Down Expand Up @@ -357,17 +369,13 @@ export class SigningCosmWasmClient extends CosmWasmClient {
* Gets account number and sequence from the API, creates a sign doc,
* creates a single signature, assembles the signed transaction and broadcasts it.
*/
public async signAndBroadcast(msgs: readonly Msg[], fee: StdFee, memo = ""): Promise<BroadcastTxResult> {
const { accountNumber, sequence } = await this.getSequence();
const chainId = await this.getChainId();
const signBytes = makeSignBytes(msgs, fee, chainId, memo, accountNumber, sequence);
const signature = await this.signer.sign(this.senderAddress, signBytes);
const signedTx: StdTx = {
msg: msgs,
fee: fee,
public async signAndBroadcast(msgs: readonly Msg[], fee?: StdFee, memo = ""): Promise<BroadcastTxResult> {
const request = {
msgs: msgs,
chainId: await this.getChainId(),
memo: memo,
signatures: [signature],
fee: fee,
};
return this.broadcastTx(signedTx);
return this.signer.signAndBroadcast(this.senderAddress, request);
}
}
Loading