Merge pull request #556 from cosmos/501-cw1-subkey-support

Add support for CW1 contracts
This commit is contained in:
Simon Warta 2020-11-30 15:18:45 +01:00 committed by GitHub
commit dec867e0fc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 832 additions and 17 deletions

View File

@ -0,0 +1,118 @@
/* eslint-disable @typescript-eslint/naming-convention */
import { coins, Secp256k1HdWallet } from "@cosmjs/launchpad";
import { Cw1CosmWasmClient } from "./cw1cosmwasmclient";
import {
alice,
deployedCw1,
launchpad,
makeRandomAddress,
pendingWithoutCw1,
pendingWithoutLaunchpad,
} from "./testutils.spec";
describe("Cw1CosmWasmClient", () => {
const contractAddress = deployedCw1.instances[0];
const defaultToAddress = makeRandomAddress();
const defaultMsg = {
bank: {
send: {
from_address: contractAddress,
to_address: defaultToAddress,
amount: coins(1, "ucosm"),
},
},
};
describe("constructor", () => {
it("can be constructed", async () => {
const wallet = await Secp256k1HdWallet.fromMnemonic(alice.mnemonic);
const client = new Cw1CosmWasmClient(launchpad.endpoint, alice.address0, wallet, contractAddress);
expect(client).toBeTruthy();
});
});
describe("canSend", () => {
it("returns true if client signer can send", async () => {
pendingWithoutLaunchpad();
pendingWithoutCw1();
const wallet = await Secp256k1HdWallet.fromMnemonic(alice.mnemonic);
const client = new Cw1CosmWasmClient(
launchpad.endpoint,
alice.address0,
wallet,
deployedCw1.instances[0],
);
const result = await client.canSend(defaultMsg);
expect(result).toEqual(true);
});
it("returns false if client signer cannot send", async () => {
pendingWithoutLaunchpad();
pendingWithoutCw1();
const wallet = await Secp256k1HdWallet.fromMnemonic(alice.mnemonic);
const client = new Cw1CosmWasmClient(
launchpad.endpoint,
alice.address1,
wallet,
deployedCw1.instances[0],
);
const result = await client.canSend(defaultMsg);
expect(result).toEqual(false);
});
it("returns true if supplied signer can send", async () => {
pendingWithoutLaunchpad();
pendingWithoutCw1();
const wallet = await Secp256k1HdWallet.fromMnemonic(alice.mnemonic);
const client = new Cw1CosmWasmClient(
launchpad.endpoint,
alice.address1,
wallet,
deployedCw1.instances[0],
);
const result = await client.canSend(defaultMsg, alice.address0);
expect(result).toEqual(true);
});
it("returns false if supplied signer cannot send", async () => {
pendingWithoutLaunchpad();
pendingWithoutCw1();
const wallet = await Secp256k1HdWallet.fromMnemonic(alice.mnemonic);
const client = new Cw1CosmWasmClient(
launchpad.endpoint,
alice.address0,
wallet,
deployedCw1.instances[0],
);
const result = await client.canSend(defaultMsg, alice.address1);
expect(result).toEqual(false);
});
});
describe("executeCw1", () => {
it("works", async () => {
pendingWithoutLaunchpad();
pendingWithoutCw1();
const wallet = await Secp256k1HdWallet.fromMnemonic(alice.mnemonic);
const client = new Cw1CosmWasmClient(
launchpad.endpoint,
alice.address0,
wallet,
deployedCw1.instances[0],
);
const result = await client.executeCw1([defaultMsg]);
expect(result.transactionHash).toBeTruthy();
});
});
});

View File

@ -0,0 +1,45 @@
/* eslint-disable @typescript-eslint/naming-convention */
import { Account, BroadcastMode, GasLimits, GasPrice, OfflineSigner } from "@cosmjs/launchpad";
import { CosmosMsg } from "./cosmosmsg";
import { CosmWasmFeeTable, ExecuteResult, SigningCosmWasmClient } from "./signingcosmwasmclient";
export class Cw1CosmWasmClient extends SigningCosmWasmClient {
public readonly cw1ContractAddress: string;
public constructor(
apiUrl: string,
signerAddress: string,
signer: OfflineSigner,
cw1ContractAddress: string,
gasPrice?: GasPrice,
gasLimits?: Partial<GasLimits<CosmWasmFeeTable>>,
broadcastMode?: BroadcastMode,
) {
super(apiUrl, signerAddress, signer, gasPrice, gasLimits, broadcastMode);
this.cw1ContractAddress = cw1ContractAddress;
}
public async getAccount(address?: string): Promise<Account | undefined> {
return super.getAccount(address || this.cw1ContractAddress);
}
public async canSend(msg: CosmosMsg, address = this.senderAddress): Promise<boolean> {
const result = await this.queryContractSmart(this.cw1ContractAddress, {
can_send: {
sender: address,
msg: msg,
},
});
return result.can_send;
}
public async executeCw1(msgs: readonly CosmosMsg[], memo = ""): Promise<ExecuteResult> {
const handleMsg = {
execute: {
msgs: msgs,
},
};
return this.execute(this.cw1ContractAddress, handleMsg, memo);
}
}

View File

@ -0,0 +1,323 @@
/* eslint-disable @typescript-eslint/naming-convention */
import { coin, coins, Secp256k1HdWallet } from "@cosmjs/launchpad";
import { Cw1SubkeyCosmWasmClient } from "./cw1subkeycosmwasmclient";
import {
alice,
deployedCw1,
launchpad,
makeRandomAddress,
pendingWithoutCw1,
pendingWithoutLaunchpad,
} from "./testutils.spec";
describe("Cw1SubkeyCosmWasmClient", () => {
describe("getAdmins", () => {
it("works", async () => {
pendingWithoutLaunchpad();
pendingWithoutCw1();
const wallet = await Secp256k1HdWallet.fromMnemonic(alice.mnemonic);
const client = new Cw1SubkeyCosmWasmClient(
launchpad.endpoint,
alice.address0,
wallet,
deployedCw1.instances[0],
);
const result = await client.getAdmins();
expect(result).toEqual([alice.address0]);
});
});
describe("isAdmin", () => {
it("returns true if client signer is admin", async () => {
pendingWithoutLaunchpad();
pendingWithoutCw1();
const wallet = await Secp256k1HdWallet.fromMnemonic(alice.mnemonic);
const client = new Cw1SubkeyCosmWasmClient(
launchpad.endpoint,
alice.address0,
wallet,
deployedCw1.instances[0],
);
const result = await client.isAdmin();
expect(result).toEqual(true);
});
it("returns false if client signer is not admin", async () => {
pendingWithoutLaunchpad();
pendingWithoutCw1();
const wallet = await Secp256k1HdWallet.fromMnemonic(alice.mnemonic);
const client = new Cw1SubkeyCosmWasmClient(
launchpad.endpoint,
alice.address1,
wallet,
deployedCw1.instances[0],
);
const result = await client.isAdmin();
expect(result).toEqual(false);
});
it("returns true if supplied signer is admin", async () => {
pendingWithoutLaunchpad();
pendingWithoutCw1();
const wallet = await Secp256k1HdWallet.fromMnemonic(alice.mnemonic);
const client = new Cw1SubkeyCosmWasmClient(
launchpad.endpoint,
alice.address1,
wallet,
deployedCw1.instances[0],
);
const result = await client.isAdmin(alice.address0);
expect(result).toEqual(true);
});
it("returns false if supplied signer is not admin", async () => {
pendingWithoutLaunchpad();
pendingWithoutCw1();
const wallet = await Secp256k1HdWallet.fromMnemonic(alice.mnemonic);
const client = new Cw1SubkeyCosmWasmClient(
launchpad.endpoint,
alice.address0,
wallet,
deployedCw1.instances[0],
);
const result = await client.isAdmin(alice.address1);
expect(result).toEqual(false);
});
});
describe("getAllAllowances", () => {
it("works", async () => {
pendingWithoutLaunchpad();
pendingWithoutCw1();
const wallet = await Secp256k1HdWallet.fromMnemonic(alice.mnemonic);
const client = new Cw1SubkeyCosmWasmClient(
launchpad.endpoint,
alice.address0,
wallet,
deployedCw1.instances[0],
);
const result = await client.getAllAllowances();
expect(result).toBeTruthy();
});
});
describe("getAllowance", () => {
it("works for client signer", async () => {
pendingWithoutLaunchpad();
pendingWithoutCw1();
const wallet = await Secp256k1HdWallet.fromMnemonic(alice.mnemonic);
const client = new Cw1SubkeyCosmWasmClient(
launchpad.endpoint,
alice.address0,
wallet,
deployedCw1.instances[0],
);
const result = await client.getAllowance();
expect(result).toEqual({ balance: [], expires: { never: {} } });
});
});
describe("getAllPermissions", () => {
it("works", async () => {
pendingWithoutLaunchpad();
pendingWithoutCw1();
const wallet = await Secp256k1HdWallet.fromMnemonic(alice.mnemonic);
const client = new Cw1SubkeyCosmWasmClient(
launchpad.endpoint,
alice.address0,
wallet,
deployedCw1.instances[0],
);
const result = await client.getAllPermissions();
expect(result.length).toEqual(1);
// TODO: test content of permissions
});
});
describe("getPermissions", () => {
it("works for client signer", async () => {
pendingWithoutLaunchpad();
pendingWithoutCw1();
const wallet = await Secp256k1HdWallet.fromMnemonic(alice.mnemonic);
const client = new Cw1SubkeyCosmWasmClient(
launchpad.endpoint,
alice.address0,
wallet,
deployedCw1.instances[0],
);
const result = await client.getPermissions();
expect(result).toEqual({
delegate: false,
redelegate: false,
undelegate: false,
withdraw: false,
});
});
it("works for supplied signer", async () => {
pendingWithoutLaunchpad();
pendingWithoutCw1();
const wallet = await Secp256k1HdWallet.fromMnemonic(alice.mnemonic);
const client = new Cw1SubkeyCosmWasmClient(
launchpad.endpoint,
alice.address0,
wallet,
deployedCw1.instances[0],
);
const result = await client.getPermissions(alice.address1);
expect(result).toEqual({
delegate: false,
redelegate: false,
undelegate: false,
withdraw: false,
});
});
});
describe("addAdmin and removeAdmin", () => {
it("works", async () => {
pendingWithoutLaunchpad();
pendingWithoutCw1();
const wallet = await Secp256k1HdWallet.fromMnemonic(alice.mnemonic);
const client = new Cw1SubkeyCosmWasmClient(
launchpad.endpoint,
alice.address0,
wallet,
deployedCw1.instances[0],
);
const newAdmin = makeRandomAddress();
expect(await client.isAdmin(newAdmin)).toBeFalse();
const addResult = await client.addAdmin(newAdmin);
expect(addResult.transactionHash).toBeTruthy();
expect(await client.isAdmin(newAdmin)).toBeTrue();
const removeResult = await client.removeAdmin(newAdmin);
expect(removeResult.transactionHash).toBeTruthy();
expect(await client.isAdmin(newAdmin)).toBeFalse();
});
});
describe("increaseAllowance and decreaseAllowance", () => {
it("works", async () => {
pendingWithoutLaunchpad();
pendingWithoutCw1();
const wallet = await Secp256k1HdWallet.fromMnemonic(alice.mnemonic);
const client = new Cw1SubkeyCosmWasmClient(
launchpad.endpoint,
alice.address0,
wallet,
deployedCw1.instances[0],
);
const spender = makeRandomAddress();
expect(await client.getAllowance(spender)).toEqual({ balance: [], expires: { never: {} } });
const increaseAmount = coin(100, "ucosm");
const increaseResult = await client.increaseAllowance(spender, increaseAmount);
expect(increaseResult.transactionHash).toBeTruthy();
expect(await client.getAllowance(spender)).toEqual({
balance: [increaseAmount],
expires: { never: {} },
});
const decreaseAmount = coin(20, "ucosm");
const decreaseResult = await client.decreaseAllowance(spender, decreaseAmount);
expect(decreaseResult.transactionHash).toBeTruthy();
expect(await client.getAllowance(spender)).toEqual({
balance: coins(80, "ucosm"),
expires: { never: {} },
});
});
it("works with expiration", async () => {
pendingWithoutLaunchpad();
pendingWithoutCw1();
const wallet = await Secp256k1HdWallet.fromMnemonic(alice.mnemonic);
const client = new Cw1SubkeyCosmWasmClient(
launchpad.endpoint,
alice.address0,
wallet,
deployedCw1.instances[0],
);
const spender = makeRandomAddress();
expect(await client.getAllowance(spender)).toEqual({ balance: [], expires: { never: {} } });
const increaseAmount = coin(100, "ucosm");
const increaseExpiration = { at_height: 88888888888 };
const increaseResult = await client.increaseAllowance(spender, increaseAmount, increaseExpiration);
expect(increaseResult.transactionHash).toBeTruthy();
expect(await client.getAllowance(spender)).toEqual({
balance: [increaseAmount],
expires: increaseExpiration,
});
const decreaseAmount = coin(20, "ucosm");
const decreaseExpiration = { at_height: 99999999999 };
const decreaseResult = await client.decreaseAllowance(spender, decreaseAmount, decreaseExpiration);
expect(decreaseResult.transactionHash).toBeTruthy();
expect(await client.getAllowance(spender)).toEqual({
balance: coins(80, "ucosm"),
expires: decreaseExpiration,
});
});
});
describe("setPermissions", () => {
it("works", async () => {
pendingWithoutLaunchpad();
pendingWithoutCw1();
const wallet = await Secp256k1HdWallet.fromMnemonic(alice.mnemonic);
const client = new Cw1SubkeyCosmWasmClient(
launchpad.endpoint,
alice.address0,
wallet,
deployedCw1.instances[0],
);
const spender = makeRandomAddress();
const defaultPermissions = {
delegate: false,
redelegate: false,
undelegate: false,
withdraw: false,
};
expect(await client.getPermissions(spender)).toEqual(defaultPermissions);
const newPermissions = {
delegate: true,
redelegate: true,
undelegate: true,
withdraw: false,
};
const setPermissionsResult = await client.setPermissions(spender, newPermissions);
expect(setPermissionsResult.transactionHash).toBeTruthy();
expect(await client.getPermissions(spender)).toEqual(newPermissions);
const resetPermissionsResult = await client.setPermissions(spender, defaultPermissions);
expect(resetPermissionsResult.transactionHash).toBeTruthy();
expect(await client.getPermissions(spender)).toEqual(defaultPermissions);
});
});
});

View File

@ -0,0 +1,152 @@
/* eslint-disable @typescript-eslint/naming-convention */
import { Coin } from "@cosmjs/launchpad";
import { Cw1CosmWasmClient } from "./cw1cosmwasmclient";
import { Expiration } from "./interfaces";
import { ExecuteResult } from "./signingcosmwasmclient";
/**
* @see https://github.com/CosmWasm/cosmwasm-plus/blob/v0.3.2/contracts/cw1-subkeys/src/msg.rs#L88
*/
export interface Cw1SubkeyAllowanceInfo {
readonly balance: readonly Coin[];
readonly expires: Expiration;
}
/**
* @see https://github.com/CosmWasm/cosmwasm-plus/blob/v0.3.2/contracts/cw1-subkeys/src/msg.rs#L83
*/
interface AllAllowancesResponse {
readonly allowances: readonly Cw1SubkeyAllowanceInfo[];
}
/**
* @see https://github.com/CosmWasm/cosmwasm-plus/blob/v0.3.2/contracts/cw1-subkeys/src/state.rs#L15
*/
export interface Cw1SubkeyPermissions {
readonly delegate: boolean;
readonly redelegate: boolean;
readonly undelegate: boolean;
readonly withdraw: boolean;
}
/**
* @see https://github.com/CosmWasm/cosmwasm-plus/blob/v0.3.2/contracts/cw1-subkeys/src/msg.rs#L95
*/
export interface Cw1SubkeyPermissionsInfo {
/** Spender address */
readonly spender: string;
readonly permissions: readonly Cw1SubkeyPermissions[];
}
/**
* @see https://github.com/CosmWasm/cosmwasm-plus/blob/v0.3.2/contracts/cw1-subkeys/src/msg.rs#L101
*/
interface AllPermissionsResponse {
readonly permissions: readonly Cw1SubkeyPermissionsInfo[];
}
export class Cw1SubkeyCosmWasmClient extends Cw1CosmWasmClient {
private async setAdmins(admins: readonly string[], memo = ""): Promise<ExecuteResult> {
const handleMsg = {
update_admins: {
admins: admins,
},
};
return this.execute(this.cw1ContractAddress, handleMsg, memo);
}
public async getAdmins(): Promise<readonly string[]> {
const { admins } = await this.queryContractSmart(this.cw1ContractAddress, { admin_list: {} });
return admins;
}
public async isAdmin(address = this.senderAddress): Promise<boolean> {
const admins = await this.getAdmins();
return admins.includes(address);
}
public async getAllAllowances(): Promise<readonly Cw1SubkeyAllowanceInfo[]> {
const response: AllAllowancesResponse = await this.queryContractSmart(this.cw1ContractAddress, {
all_allowances: {},
});
return response.allowances;
}
public async getAllowance(address = this.senderAddress): Promise<Cw1SubkeyAllowanceInfo> {
return this.queryContractSmart(this.cw1ContractAddress, {
allowance: { spender: address },
});
}
public async getAllPermissions(): Promise<readonly Cw1SubkeyPermissionsInfo[]> {
const response: AllPermissionsResponse = await this.queryContractSmart(this.cw1ContractAddress, {
all_permissions: {},
});
return response.permissions;
}
public async getPermissions(address = this.senderAddress): Promise<Cw1SubkeyPermissions> {
return this.queryContractSmart(this.cw1ContractAddress, {
permissions: { spender: address },
});
}
public async addAdmin(address: string, memo = ""): Promise<ExecuteResult> {
const admins = await this.getAdmins();
const newAdmins = admins.includes(address) ? admins : [...admins, address];
return this.setAdmins(newAdmins, memo);
}
public async removeAdmin(address: string, memo = ""): Promise<ExecuteResult> {
const admins = await this.getAdmins();
const newAdmins = admins.filter((admin) => admin !== address);
return this.setAdmins(newAdmins, memo);
}
public async increaseAllowance(
address: string,
amount: Coin,
expires?: Expiration,
memo = "",
): Promise<ExecuteResult> {
const handleMsg = {
increase_allowance: {
spender: address,
amount: amount,
expires: expires,
},
};
return this.execute(this.cw1ContractAddress, handleMsg, memo);
}
public async decreaseAllowance(
address: string,
amount: Coin,
expires?: Expiration,
memo = "",
): Promise<ExecuteResult> {
const handleMsg = {
decrease_allowance: {
spender: address,
amount: amount,
expires: expires,
},
};
return this.execute(this.cw1ContractAddress, handleMsg, memo);
}
public async setPermissions(
address: string,
permissions: Cw1SubkeyPermissions,
memo = "",
): Promise<ExecuteResult> {
const handleMsg = {
set_permissions: {
spender: address,
permissions: permissions,
},
};
return this.execute(this.cw1ContractAddress, handleMsg, memo);
}
}

View File

@ -3,16 +3,12 @@ import { BroadcastMode, GasLimits, GasPrice, OfflineSigner } from "@cosmjs/launc
import { CosmosMsg } from "./cosmosmsg";
import { Account } from "./cosmwasmclient";
import { Expiration } from "./interfaces";
import { CosmWasmFeeTable, ExecuteResult, SigningCosmWasmClient } from "./signingcosmwasmclient";
export type Expiration =
| {
readonly at_height: number;
}
| {
readonly at_time: number;
};
/**
* @see https://github.com/CosmWasm/cosmwasm-plus/blob/v0.3.2/packages/cw3/src/msg.rs#L35
*/
export enum Vote {
Yes = "yes",
No = "no",

View File

@ -1,4 +1,6 @@
export { Expiration } from "./interfaces";
export { setupWasmExtension, WasmExtension } from "./lcdapi/wasm";
export { BankMsg, CosmosMsg, CustomMsg, StakingMsg, WasmMsg } from "./cosmosmsg";
export {
Account,
@ -17,9 +19,9 @@ export {
SearchTxQuery,
SearchTxFilter,
} from "./cosmwasmclient";
export { Cw1CosmWasmClient } from "./cw1cosmwasmclient";
export {
Cw3CosmWasmClient,
Expiration,
ProposalResult,
ProposalsResult,
ThresholdResult,

View File

@ -0,0 +1,15 @@
/* eslint-disable @typescript-eslint/naming-convention */
/**
* @see https://github.com/CosmWasm/cosmwasm-plus/blob/v0.3.2/packages/cw0/src/expiration.rs#L14
*/
export type Expiration =
| {
readonly at_height: number;
}
| {
readonly at_time: number;
}
| {
readonly never: Record<any, never>;
};

View File

@ -0,0 +1 @@
export { Expiration } from "./cw0";

View File

@ -103,6 +103,14 @@ export const deployedCw3 = {
],
};
/** Deployed as part of scripts/launchpad/init.sh */
export const deployedCw1 = {
codeId: 4,
source: "https://crates.io/api/v1/crates/cw1-subkeys/0.3.1/download",
builder: "cosmwasm/rust-optimizer:0.10.4",
instances: ["cosmos1vs2vuks65rq7xj78mwtvn7vvnm2gn7ad5me0d2"],
};
export const launchpad = {
endpoint: "http://localhost:1317",
chainId: "testing",
@ -141,6 +149,16 @@ export function pendingWithoutCw3(): void {
}
}
export function cw1Enabled(): boolean {
return !!process.env.CW1_ENABLED;
}
export function pendingWithoutCw1(): void {
if (!cw1Enabled()) {
return pending("Set CW1_ENABLED to enable CW1-based tests");
}
}
/** Returns first element. Throws if array has a different length than 1. */
export function fromOneElementArray<T>(elements: ArrayLike<T>): T {
if (elements.length !== 1) throw new Error(`Expected exactly one element but got ${elements.length}`);

View File

@ -0,0 +1,18 @@
import { Account, BroadcastMode, GasLimits, GasPrice, OfflineSigner } from "@cosmjs/launchpad";
import { CosmosMsg } from "./cosmosmsg";
import { CosmWasmFeeTable, ExecuteResult, SigningCosmWasmClient } from "./signingcosmwasmclient";
export declare class Cw1CosmWasmClient extends SigningCosmWasmClient {
readonly cw1ContractAddress: string;
constructor(
apiUrl: string,
signerAddress: string,
signer: OfflineSigner,
cw1ContractAddress: string,
gasPrice?: GasPrice,
gasLimits?: Partial<GasLimits<CosmWasmFeeTable>>,
broadcastMode?: BroadcastMode,
);
getAccount(address?: string): Promise<Account | undefined>;
canSend(msg: CosmosMsg, address?: string): Promise<boolean>;
executeCw1(msgs: readonly CosmosMsg[], memo?: string): Promise<ExecuteResult>;
}

View File

@ -0,0 +1,52 @@
import { Coin } from "@cosmjs/launchpad";
import { Cw1CosmWasmClient } from "./cw1cosmwasmclient";
import { Expiration } from "./interfaces";
import { ExecuteResult } from "./signingcosmwasmclient";
/**
* @see https://github.com/CosmWasm/cosmwasm-plus/blob/v0.3.2/contracts/cw1-subkeys/src/msg.rs#L88
*/
export interface Cw1SubkeyAllowanceInfo {
readonly balance: readonly Coin[];
readonly expires: Expiration;
}
/**
* @see https://github.com/CosmWasm/cosmwasm-plus/blob/v0.3.2/contracts/cw1-subkeys/src/state.rs#L15
*/
export interface Cw1SubkeyPermissions {
readonly delegate: boolean;
readonly redelegate: boolean;
readonly undelegate: boolean;
readonly withdraw: boolean;
}
/**
* @see https://github.com/CosmWasm/cosmwasm-plus/blob/v0.3.2/contracts/cw1-subkeys/src/msg.rs#L95
*/
export interface Cw1SubkeyPermissionsInfo {
/** Spender address */
readonly spender: string;
readonly permissions: readonly Cw1SubkeyPermissions[];
}
export declare class Cw1SubkeyCosmWasmClient extends Cw1CosmWasmClient {
private setAdmins;
getAdmins(): Promise<readonly string[]>;
isAdmin(address?: string): Promise<boolean>;
getAllAllowances(): Promise<readonly Cw1SubkeyAllowanceInfo[]>;
getAllowance(address?: string): Promise<Cw1SubkeyAllowanceInfo>;
getAllPermissions(): Promise<readonly Cw1SubkeyPermissionsInfo[]>;
getPermissions(address?: string): Promise<Cw1SubkeyPermissions>;
addAdmin(address: string, memo?: string): Promise<ExecuteResult>;
removeAdmin(address: string, memo?: string): Promise<ExecuteResult>;
increaseAllowance(
address: string,
amount: Coin,
expires?: Expiration,
memo?: string,
): Promise<ExecuteResult>;
decreaseAllowance(
address: string,
amount: Coin,
expires?: Expiration,
memo?: string,
): Promise<ExecuteResult>;
setPermissions(address: string, permissions: Cw1SubkeyPermissions, memo?: string): Promise<ExecuteResult>;
}

View File

@ -1,14 +1,11 @@
import { BroadcastMode, GasLimits, GasPrice, OfflineSigner } from "@cosmjs/launchpad";
import { CosmosMsg } from "./cosmosmsg";
import { Account } from "./cosmwasmclient";
import { Expiration } from "./interfaces";
import { CosmWasmFeeTable, ExecuteResult, SigningCosmWasmClient } from "./signingcosmwasmclient";
export declare type Expiration =
| {
readonly at_height: number;
}
| {
readonly at_time: number;
};
/**
* @see https://github.com/CosmWasm/cosmwasm-plus/blob/v0.3.2/packages/cw3/src/msg.rs#L35
*/
export declare enum Vote {
Yes = "yes",
No = "no",

View File

@ -1,3 +1,4 @@
export { Expiration } from "./interfaces";
export { setupWasmExtension, WasmExtension } from "./lcdapi/wasm";
export { BankMsg, CosmosMsg, CustomMsg, StakingMsg, WasmMsg } from "./cosmosmsg";
export {
@ -17,9 +18,9 @@ export {
SearchTxQuery,
SearchTxFilter,
} from "./cosmwasmclient";
export { Cw1CosmWasmClient } from "./cw1cosmwasmclient";
export {
Cw3CosmWasmClient,
Expiration,
ProposalResult,
ProposalsResult,
ThresholdResult,

View File

@ -0,0 +1,13 @@
/**
* @see https://github.com/CosmWasm/cosmwasm-plus/blob/v0.3.2/packages/cw0/src/expiration.rs#L14
*/
export declare type Expiration =
| {
readonly at_height: number;
}
| {
readonly at_time: number;
}
| {
readonly never: Record<any, never>;
};

View File

@ -0,0 +1 @@
export { Expiration } from "./cw0";

View File

@ -1,3 +1,4 @@
c478a6d9d6303e67f28d7863ea6e07426e9f0082744557d503e723bc1c46ccf8 cw1_subkeys.wasm
1a4a376ef1099ad3edc33aa1d3105e4621bc49e44b1ac0a449d7b6912e40fb0a cw3_fixed_multisig.wasm
ebc2b11e2afa50d5dcd4234840cd581e948a59d888bb8d651598bba3732cd8ee cw-nameservice.wasm
d04368320ad55089384adb171aaea39e43d710d7608829adba0300ed30aa2988 cw_erc20.wasm

BIN
scripts/launchpad/contracts/cw1_subkeys.wasm (Stored with Git LFS) Normal file

Binary file not shown.

58
scripts/launchpad/deploy_cw1.js Executable file
View File

@ -0,0 +1,58 @@
#!/usr/bin/env node
/* eslint-disable @typescript-eslint/naming-convention */
const { SigningCosmWasmClient } = require("@cosmjs/cosmwasm");
const { Secp256k1HdWallet } = require("@cosmjs/launchpad");
const fs = require("fs");
const httpUrl = "http://localhost:1317";
const alice = {
mnemonic: "enlist hip relief stomach skate base shallow young switch frequent cry park",
address0: "cosmos14qemq0vw6y3gc3u3e0aty2e764u4gs5le3hada",
// address1: "cosmos1hhg2rlu9jscacku2wwckws7932qqqu8x3gfgw0",
// address2: "cosmos1xv9tklw7d82sezh9haa573wufgy59vmwe6xxe5",
// address3: "cosmos17yg9mssjenmc3jkqth6ulcwj9cxujrxxzezwta",
// address4: "cosmos1f7j7ryulwjfe9ljplvhtcaxa6wqgula3etktce",
};
const codeMeta = {
source: "https://crates.io/api/v1/crates/cw1-subkeys/0.3.1/download",
builder: "cosmwasm/rust-optimizer:0.10.4",
};
async function main() {
const wallet = await Secp256k1HdWallet.fromMnemonic(alice.mnemonic);
const client = new SigningCosmWasmClient(httpUrl, alice.address0, wallet);
const wasm = fs.readFileSync(__dirname + "/contracts/cw1_subkeys.wasm");
const uploadReceipt = await client.upload(wasm, codeMeta, "Upload CW1 subkeys contract");
console.info(`Upload succeeded. Receipt: ${JSON.stringify(uploadReceipt)}`);
const initMsg = {
admins: [alice.address0],
mutable: true,
};
const label = "Subkey test";
const { contractAddress } = await client.instantiate(uploadReceipt.codeId, initMsg, label, {
memo: `Create a CW1 instance for ${alice.address0}`,
admin: alice.address0,
});
await client.sendTokens(contractAddress, [
{
amount: "1000",
denom: "ucosm",
},
]);
console.info(`Contract instantiated for ${alice.address0} subkey at ${contractAddress}`);
}
main().then(
() => {
console.info("All done, let the coins flow.");
process.exit(0);
},
(error) => {
console.error(error);
process.exit(1);
},
);

View File

@ -27,4 +27,5 @@ SCRIPT_DIR="$(realpath "$(dirname "$0")")"
"$SCRIPT_DIR/deploy_hackatom.js"
"$SCRIPT_DIR/deploy_erc20.js"
"$SCRIPT_DIR/deploy_cw3.js"
"$SCRIPT_DIR/deploy_cw1.js"
# "$SCRIPT_DIR/deploy_nameservice.js"