Merge pull request #175 from CosmWasm/staking-demo
Add staking contract to deployment
This commit is contained in:
commit
33f803fe69
1
packages/demo-staking/.eslintignore
Symbolic link
1
packages/demo-staking/.eslintignore
Symbolic link
@ -0,0 +1 @@
|
||||
../../.eslintignore
|
||||
3
packages/demo-staking/.gitignore
vendored
Normal file
3
packages/demo-staking/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
build/
|
||||
dist/
|
||||
docs/
|
||||
8
packages/demo-staking/README.md
Normal file
8
packages/demo-staking/README.md
Normal file
@ -0,0 +1,8 @@
|
||||
# @cosmwasm/demo-staking
|
||||
|
||||
## License
|
||||
|
||||
This package is part of the cosmwasm-js repository, licensed under the Apache
|
||||
License 2.0 (see
|
||||
[NOTICE](https://github.com/confio/cosmwasm-js/blob/master/NOTICE) and
|
||||
[LICENSE](https://github.com/confio/cosmwasm-js/blob/master/LICENSE)).
|
||||
26
packages/demo-staking/jasmine-testrunner.js
Executable file
26
packages/demo-staking/jasmine-testrunner.js
Executable file
@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
require("source-map-support").install();
|
||||
const defaultSpecReporterConfig = require("../../jasmine-spec-reporter.config.json");
|
||||
|
||||
// setup Jasmine
|
||||
const Jasmine = require("jasmine");
|
||||
const jasmine = new Jasmine();
|
||||
jasmine.loadConfig({
|
||||
spec_dir: "build",
|
||||
spec_files: ["**/*.spec.js"],
|
||||
helpers: [],
|
||||
random: false,
|
||||
seed: null,
|
||||
stopSpecOnExpectationFailure: false,
|
||||
});
|
||||
jasmine.jasmine.DEFAULT_TIMEOUT_INTERVAL = 15 * 1000;
|
||||
|
||||
// setup reporter
|
||||
const { SpecReporter } = require("jasmine-spec-reporter");
|
||||
const reporter = new SpecReporter({ ...defaultSpecReporterConfig });
|
||||
|
||||
// initialize and execute
|
||||
jasmine.env.clearReporters();
|
||||
jasmine.addReporter(reporter);
|
||||
jasmine.execute();
|
||||
54
packages/demo-staking/karma.conf.js
Normal file
54
packages/demo-staking/karma.conf.js
Normal file
@ -0,0 +1,54 @@
|
||||
module.exports = function (config) {
|
||||
config.set({
|
||||
// base path that will be used to resolve all patterns (eg. files, exclude)
|
||||
basePath: ".",
|
||||
|
||||
// frameworks to use
|
||||
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
|
||||
frameworks: ["jasmine"],
|
||||
|
||||
// list of files / patterns to load in the browser
|
||||
files: ["dist/web/tests.js"],
|
||||
|
||||
client: {
|
||||
jasmine: {
|
||||
random: false,
|
||||
timeoutInterval: 15000,
|
||||
},
|
||||
},
|
||||
|
||||
// test results reporter to use
|
||||
// possible values: 'dots', 'progress'
|
||||
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
|
||||
reporters: ["progress", "kjhtml"],
|
||||
|
||||
// web server port
|
||||
port: 9876,
|
||||
|
||||
// enable / disable colors in the output (reporters and logs)
|
||||
colors: true,
|
||||
|
||||
// level of logging
|
||||
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
|
||||
logLevel: config.LOG_INFO,
|
||||
|
||||
// enable / disable watching file and executing tests whenever any file changes
|
||||
autoWatch: false,
|
||||
|
||||
// start these browsers
|
||||
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
|
||||
browsers: ["Firefox"],
|
||||
|
||||
browserNoActivityTimeout: 90000,
|
||||
|
||||
// Keep brower open for debugging. This is overridden by yarn scripts
|
||||
singleRun: false,
|
||||
|
||||
customLaunchers: {
|
||||
ChromeHeadlessInsecure: {
|
||||
base: "ChromeHeadless",
|
||||
flags: ["--disable-web-security"],
|
||||
},
|
||||
},
|
||||
});
|
||||
};
|
||||
1
packages/demo-staking/nonces/README.txt
Normal file
1
packages/demo-staking/nonces/README.txt
Normal file
@ -0,0 +1 @@
|
||||
Directory used to trigger lerna package updates for all packages
|
||||
48
packages/demo-staking/package.json
Normal file
48
packages/demo-staking/package.json
Normal file
@ -0,0 +1,48 @@
|
||||
{
|
||||
"name": "@cosmwasm/demo-staking",
|
||||
"version": "0.8.0-alpha.0",
|
||||
"description": "Demo interaction with the staking contract",
|
||||
"author": "Simon Warta <webmaster128@users.noreply.github.com>",
|
||||
"license": "Apache-2.0",
|
||||
"main": "build/index.js",
|
||||
"types": "types/index.d.ts",
|
||||
"files": [
|
||||
"build/",
|
||||
"types/",
|
||||
"*.md",
|
||||
"!*.spec.*",
|
||||
"!**/testdata/"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/confio/cosmwasm-js/tree/master/packages/demo-staking"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"scripts": {
|
||||
"docs": "shx rm -rf docs && typedoc --options typedoc.js",
|
||||
"format": "prettier --write --loglevel warn \"./src/**/*.ts\"",
|
||||
"lint": "eslint --max-warnings 0 \"**/*.{js,ts}\"",
|
||||
"lint-fix": "eslint --max-warnings 0 \"**/*.{js,ts}\" --fix",
|
||||
"move-types": "shx rm -rf ./types/* && shx mv build/types/* ./types && rm -rf ./types/testdata && shx rm -f ./types/*.spec.d.ts",
|
||||
"format-types": "prettier --write --loglevel warn \"./types/**/*.d.ts\"",
|
||||
"build": "shx rm -rf ./build && tsc && yarn move-types && yarn format-types",
|
||||
"build-or-skip": "[ -n \"$SKIP_BUILD\" ] || yarn build",
|
||||
"test-node": "node jasmine-testrunner.js",
|
||||
"test-firefox": "yarn pack-web && karma start --single-run --browsers Firefox",
|
||||
"test-chrome": "yarn pack-web && karma start --single-run --browsers ChromeHeadlessInsecure",
|
||||
"test": "yarn build-or-skip && yarn test-node",
|
||||
"pack-web": "yarn build-or-skip && webpack --mode development --config webpack.web.config.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@cosmwasm/sdk": "^0.8.0-alpha.0",
|
||||
"@iov/crypto": "^2.1.0",
|
||||
"@iov/encoding": "^2.1.0",
|
||||
"@iov/stream": "^2.0.2",
|
||||
"@iov/utils": "^2.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@iov/keycontrol": "^2.1.0"
|
||||
}
|
||||
}
|
||||
153
packages/demo-staking/src/index.spec.ts
Normal file
153
packages/demo-staking/src/index.spec.ts
Normal file
@ -0,0 +1,153 @@
|
||||
/* eslint-disable @typescript-eslint/camelcase */
|
||||
import { Coin, coins, makeCosmoshubPath, Secp256k1Pen, SigningCosmWasmClient } from "@cosmwasm/sdk";
|
||||
|
||||
import {
|
||||
BalanceResponse,
|
||||
HandleMsg,
|
||||
InitMsg,
|
||||
InvestmentResponse,
|
||||
QueryMsg,
|
||||
TokenInfoResponse,
|
||||
} from "./schema";
|
||||
|
||||
function pendingWithoutWasmd(): void {
|
||||
if (!process.env.WASMD_ENABLED) {
|
||||
return pending("Set WASMD_ENABLED to enable Cosmos node-based tests");
|
||||
}
|
||||
}
|
||||
|
||||
const httpUrl = "http://localhost:1317";
|
||||
const faucet = {
|
||||
mnemonic:
|
||||
"economy stock theory fatal elder harbor betray wasp final emotion task crumble siren bottom lizard educate guess current outdoor pair theory focus wife stone",
|
||||
address: "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6",
|
||||
};
|
||||
|
||||
/** Code info staking.wasm */
|
||||
const codeId = 3;
|
||||
|
||||
/** Instance parameters */
|
||||
const params = {
|
||||
name: "Bounty",
|
||||
symbol: "BOUNTY",
|
||||
decimals: 3,
|
||||
validator: "cosmosvaloper1ea5cpmcj2vf5d0xwurncx7zdnmkuc6eq696h9a",
|
||||
exitTax: "0.005", // 0.5 %
|
||||
minWithdrawal: "700",
|
||||
};
|
||||
|
||||
describe("Staking demo", () => {
|
||||
it("works", async () => {
|
||||
pendingWithoutWasmd();
|
||||
// The owner of the contract that will collect the tax
|
||||
const ownerPen = await Secp256k1Pen.fromMnemonic(faucet.mnemonic);
|
||||
const ownerAddress = ownerPen.address("cosmos");
|
||||
const ownerClient = new SigningCosmWasmClient(httpUrl, ownerAddress, (signBytes) =>
|
||||
ownerPen.sign(signBytes),
|
||||
);
|
||||
|
||||
// a user of the contract
|
||||
const userPen = await Secp256k1Pen.fromMnemonic(faucet.mnemonic, makeCosmoshubPath(1));
|
||||
const userAddress = userPen.address("cosmos");
|
||||
const userClient = new SigningCosmWasmClient(
|
||||
httpUrl,
|
||||
userAddress,
|
||||
(signBytes) => userPen.sign(signBytes),
|
||||
{
|
||||
exec: {
|
||||
amount: coins(5000, "ucosm"),
|
||||
gas: "300000", // 300k, needed for unbonding
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
const initMsg: InitMsg = {
|
||||
name: params.name,
|
||||
symbol: params.symbol,
|
||||
decimals: params.decimals,
|
||||
validator: params.validator,
|
||||
exit_tax: params.exitTax,
|
||||
min_withdrawal: params.minWithdrawal,
|
||||
};
|
||||
const { contractAddress } = await ownerClient.instantiate(
|
||||
codeId,
|
||||
initMsg,
|
||||
`Staking derivative BOUNTY ${new Date()}`,
|
||||
);
|
||||
|
||||
// Query token info (immutable)
|
||||
{
|
||||
const query: QueryMsg = { token_info: {} };
|
||||
const response: TokenInfoResponse = await ownerClient.queryContractSmart(contractAddress, query);
|
||||
expect(response).toEqual({
|
||||
decimals: params.decimals,
|
||||
name: params.name,
|
||||
symbol: params.symbol,
|
||||
});
|
||||
}
|
||||
|
||||
// Query investment info (changes with bonding/unbonding)
|
||||
{
|
||||
const query: QueryMsg = { investment: {} };
|
||||
const response: InvestmentResponse = await ownerClient.queryContractSmart(contractAddress, query);
|
||||
expect(response).toEqual({
|
||||
token_supply: "0",
|
||||
staked_tokens: { denom: "ustake", amount: "0" },
|
||||
nominal_value: "1",
|
||||
owner: ownerAddress,
|
||||
exit_tax: params.exitTax,
|
||||
validator: params.validator,
|
||||
min_withdrawal: params.minWithdrawal,
|
||||
});
|
||||
}
|
||||
|
||||
const bondMsg: HandleMsg = { bond: {} };
|
||||
const amount: Coin = {
|
||||
amount: "112233",
|
||||
denom: "ustake",
|
||||
};
|
||||
await userClient.execute(contractAddress, bondMsg, undefined, [amount]);
|
||||
|
||||
// Investment info changed
|
||||
{
|
||||
const quer: QueryMsg = { investment: {} };
|
||||
const response: InvestmentResponse = await ownerClient.queryContractSmart(contractAddress, quer);
|
||||
expect(response).toEqual({
|
||||
token_supply: "112233",
|
||||
staked_tokens: { denom: "ustake", amount: "112233" },
|
||||
nominal_value: "1",
|
||||
owner: ownerAddress,
|
||||
exit_tax: params.exitTax,
|
||||
validator: params.validator,
|
||||
min_withdrawal: params.minWithdrawal,
|
||||
});
|
||||
}
|
||||
|
||||
// Get balance
|
||||
{
|
||||
const query: QueryMsg = { balance: { address: userAddress } };
|
||||
const response: BalanceResponse = await ownerClient.queryContractSmart(contractAddress, query);
|
||||
expect(response).toEqual({
|
||||
balance: "112233",
|
||||
});
|
||||
}
|
||||
|
||||
const unbondMsg: HandleMsg = { unbond: { amount: "110000" } };
|
||||
// await ownerClient.execute(contractAddress, unbondMsg);
|
||||
await userClient.execute(contractAddress, unbondMsg);
|
||||
|
||||
// Get balance
|
||||
{
|
||||
const query: QueryMsg = { balance: { address: userAddress } };
|
||||
const response: BalanceResponse = await ownerClient.queryContractSmart(contractAddress, query);
|
||||
expect(response).toEqual({ balance: "2233" });
|
||||
}
|
||||
|
||||
// Check collected tax (0.5 % of 110000)
|
||||
{
|
||||
const query: QueryMsg = { balance: { address: ownerAddress } };
|
||||
const response: BalanceResponse = await ownerClient.queryContractSmart(contractAddress, query);
|
||||
expect(response).toEqual({ balance: "550" });
|
||||
}
|
||||
});
|
||||
});
|
||||
0
packages/demo-staking/src/index.ts
Normal file
0
packages/demo-staking/src/index.ts
Normal file
210
packages/demo-staking/src/schema.d.ts
vendored
Normal file
210
packages/demo-staking/src/schema.d.ts
vendored
Normal file
@ -0,0 +1,210 @@
|
||||
/*
|
||||
* This file was generated with ❤️ by wasm.glass and is licensed
|
||||
* for you under WTFPL OR 0BSD OR Unlicense OR MIT OR BSD-3-Clause.
|
||||
* Note that different terms apply for the contract's source code and schema.
|
||||
* Type generation powered by json-schema-to-typescript.
|
||||
*/
|
||||
|
||||
export interface BalanceResponse {
|
||||
balance: string;
|
||||
[k: string]: unknown;
|
||||
}
|
||||
|
||||
export interface ClaimsResponse {
|
||||
claims: string;
|
||||
[k: string]: unknown;
|
||||
}
|
||||
|
||||
export type HandleMsg =
|
||||
| {
|
||||
transfer: {
|
||||
amount: string;
|
||||
recipient: string;
|
||||
[k: string]: unknown;
|
||||
};
|
||||
[k: string]: unknown;
|
||||
}
|
||||
| {
|
||||
bond: {
|
||||
[k: string]: unknown;
|
||||
};
|
||||
[k: string]: unknown;
|
||||
}
|
||||
| {
|
||||
unbond: {
|
||||
amount: string;
|
||||
[k: string]: unknown;
|
||||
};
|
||||
[k: string]: unknown;
|
||||
}
|
||||
| {
|
||||
claim: {
|
||||
[k: string]: unknown;
|
||||
};
|
||||
[k: string]: unknown;
|
||||
}
|
||||
| {
|
||||
reinvest: {
|
||||
[k: string]: unknown;
|
||||
};
|
||||
[k: string]: unknown;
|
||||
}
|
||||
| {
|
||||
__bond_all_tokens: {
|
||||
[k: string]: unknown;
|
||||
};
|
||||
[k: string]: unknown;
|
||||
};
|
||||
|
||||
export interface InitMsg {
|
||||
/**
|
||||
* decimal places of the derivative token (for UI) TODO: does this make sense? Do we need to normalize on this? We don't even know the decimals of the native token
|
||||
*/
|
||||
decimals: number;
|
||||
/**
|
||||
* this is how much the owner takes as a cut when someone unbonds TODO
|
||||
*/
|
||||
exit_tax: string;
|
||||
/**
|
||||
* This is the minimum amount we will pull out to reinvest, as well as a minumum that can be unbonded (to avoid needless staking tx)
|
||||
*/
|
||||
min_withdrawal: string;
|
||||
/**
|
||||
* name of the derivative token (FIXME: auto-generate?)
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* symbol / ticker of the derivative token
|
||||
*/
|
||||
symbol: string;
|
||||
/**
|
||||
* This is the validator that all tokens will be bonded to
|
||||
*/
|
||||
validator: string;
|
||||
[k: string]: unknown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Investment info is fixed at initialization, and is used to control the function of the contract
|
||||
*/
|
||||
export interface InvestmentInfo {
|
||||
/**
|
||||
* this is the denomination we can stake (and only one we accept for payments)
|
||||
*/
|
||||
bond_denom: string;
|
||||
/**
|
||||
* this is how much the owner takes as a cut when someone unbonds
|
||||
*/
|
||||
exit_tax: string;
|
||||
/**
|
||||
* This is the minimum amount we will pull out to reinvest, as well as a minumum that can be unbonded (to avoid needless staking tx)
|
||||
*/
|
||||
min_withdrawal: string;
|
||||
/**
|
||||
* owner created the contract and takes a cut
|
||||
*/
|
||||
owner: string;
|
||||
/**
|
||||
* All tokens are bonded to this validator FIXME: humanize/canonicalize address doesn't work for validator addrresses
|
||||
*/
|
||||
validator: string;
|
||||
[k: string]: unknown;
|
||||
}
|
||||
|
||||
export interface InvestmentResponse {
|
||||
/**
|
||||
* this is how much the owner takes as a cut when someone unbonds
|
||||
*/
|
||||
exit_tax: string;
|
||||
/**
|
||||
* This is the minimum amount we will pull out to reinvest, as well as a minumum that can be unbonded (to avoid needless staking tx)
|
||||
*/
|
||||
min_withdrawal: string;
|
||||
/**
|
||||
* A fixed-point decimal value with 18 fractional digits, i.e. Decimal(1_000_000_000_000_000_000) == 1.0
|
||||
*
|
||||
* The greatest possible value that can be represented is 340282366920938463463.374607431768211455 (which is (2^128 - 1) / 10^18)
|
||||
*/
|
||||
nominal_value: string;
|
||||
/**
|
||||
* owner created the contract and takes a cut
|
||||
*/
|
||||
owner: string;
|
||||
staked_tokens: {
|
||||
amount: string;
|
||||
denom: string;
|
||||
[k: string]: unknown;
|
||||
};
|
||||
token_supply: string;
|
||||
/**
|
||||
* All tokens are bonded to this validator
|
||||
*/
|
||||
validator: string;
|
||||
[k: string]: unknown;
|
||||
}
|
||||
|
||||
export type QueryMsg =
|
||||
| {
|
||||
balance: {
|
||||
address: string;
|
||||
[k: string]: unknown;
|
||||
};
|
||||
[k: string]: unknown;
|
||||
}
|
||||
| {
|
||||
claims: {
|
||||
address: string;
|
||||
[k: string]: unknown;
|
||||
};
|
||||
[k: string]: unknown;
|
||||
}
|
||||
| {
|
||||
token_info: {
|
||||
[k: string]: unknown;
|
||||
};
|
||||
[k: string]: unknown;
|
||||
}
|
||||
| {
|
||||
investment: {
|
||||
[k: string]: unknown;
|
||||
};
|
||||
[k: string]: unknown;
|
||||
};
|
||||
|
||||
/**
|
||||
* Supply is dynamic and tracks the current supply of staked and ERC20 tokens.
|
||||
*/
|
||||
export interface Supply {
|
||||
/**
|
||||
* bonded is how many native tokens exist bonded to the validator
|
||||
*/
|
||||
bonded: string;
|
||||
/**
|
||||
* claims is how many tokens need to be reserved paying back those who unbonded
|
||||
*/
|
||||
claims: string;
|
||||
/**
|
||||
* issued is how many derivative tokens this contract has issued
|
||||
*/
|
||||
issued: string;
|
||||
[k: string]: unknown;
|
||||
}
|
||||
|
||||
/**
|
||||
* TokenInfoResponse is info to display the derivative token in a UI
|
||||
*/
|
||||
export interface TokenInfoResponse {
|
||||
/**
|
||||
* decimal places of the derivative token (for UI)
|
||||
*/
|
||||
decimals: number;
|
||||
/**
|
||||
* name of the derivative token
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* symbol / ticker of the derivative token
|
||||
*/
|
||||
symbol: string;
|
||||
[k: string]: unknown;
|
||||
}
|
||||
12
packages/demo-staking/tsconfig.json
Normal file
12
packages/demo-staking/tsconfig.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"outDir": "build",
|
||||
"declarationDir": "build/types",
|
||||
"rootDir": "src"
|
||||
},
|
||||
"include": [
|
||||
"src/**/*"
|
||||
]
|
||||
}
|
||||
14
packages/demo-staking/typedoc.js
Normal file
14
packages/demo-staking/typedoc.js
Normal file
@ -0,0 +1,14 @@
|
||||
const packageJson = require("./package.json");
|
||||
|
||||
module.exports = {
|
||||
src: ["./src"],
|
||||
out: "docs",
|
||||
exclude: "**/*.spec.ts",
|
||||
target: "es6",
|
||||
name: `${packageJson.name} Documentation`,
|
||||
readme: "README.md",
|
||||
mode: "file",
|
||||
excludeExternals: true,
|
||||
excludeNotExported: true,
|
||||
excludePrivate: true,
|
||||
};
|
||||
0
packages/demo-staking/types/index.d.ts
vendored
Normal file
0
packages/demo-staking/types/index.d.ts
vendored
Normal file
19
packages/demo-staking/webpack.web.config.js
Normal file
19
packages/demo-staking/webpack.web.config.js
Normal file
@ -0,0 +1,19 @@
|
||||
const glob = require("glob");
|
||||
const path = require("path");
|
||||
const webpack = require("webpack");
|
||||
|
||||
const target = "web";
|
||||
const distdir = path.join(__dirname, "dist", "web");
|
||||
|
||||
module.exports = [
|
||||
{
|
||||
// bundle used for Karma tests
|
||||
target: target,
|
||||
entry: glob.sync("./build/**/*.spec.js"),
|
||||
output: {
|
||||
path: distdir,
|
||||
filename: "tests.js",
|
||||
},
|
||||
plugins: [new webpack.EnvironmentPlugin(["WASMD_ENABLED"])],
|
||||
},
|
||||
];
|
||||
@ -28,7 +28,7 @@ describe("Sec256k1Pen", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("createSignature", () => {
|
||||
describe("sign", () => {
|
||||
it("creates correct signatures", async () => {
|
||||
const pen = await Secp256k1Pen.fromMnemonic(
|
||||
"special sign fit simple patrol salute grocery chicken wheat radar tonight ceiling",
|
||||
@ -44,4 +44,13 @@ describe("Sec256k1Pen", () => {
|
||||
expect(valid).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("address", () => {
|
||||
it("creates same address as Go imlementation", async () => {
|
||||
const pen = await Secp256k1Pen.fromMnemonic(
|
||||
"oyster design unusual machine spread century engine gravity focus cave carry slot",
|
||||
);
|
||||
expect(pen.address("cosmos")).toEqual("cosmos1cjsxept9rkggzxztslae9ndgpdyt2408lk850u");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -9,6 +9,7 @@ import {
|
||||
Slip10RawIndex,
|
||||
} from "@iov/crypto";
|
||||
|
||||
import { rawSecp256k1PubkeyToAddress } from "./address";
|
||||
import { encodeSecp256k1Signature } from "./signature";
|
||||
import { StdSignature } from "./types";
|
||||
|
||||
@ -84,4 +85,8 @@ export class Secp256k1Pen implements Pen {
|
||||
const fixedLengthSignature = new Uint8Array([...signature.r(32), ...signature.s(32)]);
|
||||
return encodeSecp256k1Signature(this.pubkey, fixedLengthSignature);
|
||||
}
|
||||
|
||||
public address(prefix: string): string {
|
||||
return rawSecp256k1PubkeyToAddress(this.pubkey, prefix);
|
||||
}
|
||||
}
|
||||
|
||||
1
packages/sdk/types/pen.d.ts
vendored
1
packages/sdk/types/pen.d.ts
vendored
@ -29,4 +29,5 @@ export declare class Secp256k1Pen implements Pen {
|
||||
* Creates and returns a signature
|
||||
*/
|
||||
sign(signBytes: Uint8Array, prehashType?: PrehashType): Promise<StdSignature>;
|
||||
address(prefix: string): string;
|
||||
}
|
||||
|
||||
@ -1,2 +1,3 @@
|
||||
1f6285492e7ea00596ef472ba166cb96ac3f91d694cb8c8e15f7c023ac451947 cw-erc20.wasm
|
||||
7c0e964c9a46f53af8a4097fbf45edf9670c1813b99f4ecb1084ccadb30de2fe cw-nameservice.wasm
|
||||
0f08a890443dbf644f61a7dc3aa7b2a03e9d142dd1b718aa8b7f8a80b886bff1 staking.wasm
|
||||
|
||||
BIN
scripts/wasmd/contracts/staking.wasm
Normal file
BIN
scripts/wasmd/contracts/staking.wasm
Normal file
Binary file not shown.
57
scripts/wasmd/deploy_staking.js
Executable file
57
scripts/wasmd/deploy_staking.js
Executable file
@ -0,0 +1,57 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/* eslint-disable @typescript-eslint/camelcase */
|
||||
const { SigningCosmWasmClient, Secp256k1Pen } = require("@cosmwasm/sdk");
|
||||
const fs = require("fs");
|
||||
|
||||
const httpUrl = "http://localhost:1317";
|
||||
const faucet = {
|
||||
mnemonic:
|
||||
"economy stock theory fatal elder harbor betray wasp final emotion task crumble siren bottom lizard educate guess current outdoor pair theory focus wife stone",
|
||||
address: "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6",
|
||||
};
|
||||
|
||||
const codeMeta = {
|
||||
source: "", // not intended to be published
|
||||
builder: "cosmwasm/rust-optimizer:0.8.0",
|
||||
};
|
||||
|
||||
// To get the proper validator address, run the demo chain (./scripts/wasmd/start.sh), then run:
|
||||
// curl http://localhost:1317/staking/validators | jq .result[0].operator_address
|
||||
const bounty = {
|
||||
label: "Bounty",
|
||||
initMsg: {
|
||||
name: "Bounty",
|
||||
symbol: "BOUNTY",
|
||||
decimals: 3,
|
||||
validator: "cosmosvaloper1ea5cpmcj2vf5d0xwurncx7zdnmkuc6eq696h9a",
|
||||
exit_tax: "0.005", // 0.5 %
|
||||
min_withdrawal: "7",
|
||||
},
|
||||
};
|
||||
|
||||
async function main() {
|
||||
const pen = await Secp256k1Pen.fromMnemonic(faucet.mnemonic);
|
||||
const client = new SigningCosmWasmClient(httpUrl, faucet.address, (signBytes) => pen.sign(signBytes));
|
||||
|
||||
const wasm = fs.readFileSync(__dirname + "/contracts/staking.wasm");
|
||||
const uploadReceipt = await client.upload(wasm, codeMeta, "Upload Staking code");
|
||||
console.info(`Upload succeeded. Receipt: ${JSON.stringify(uploadReceipt)}`);
|
||||
|
||||
for (const { label, initMsg } of [bounty]) {
|
||||
const memo = `Create an staking instance "${label}"`;
|
||||
const { contractAddress } = await client.instantiate(uploadReceipt.codeId, initMsg, label, memo);
|
||||
console.info(`Contract "${label}" instantiated at ${contractAddress}`);
|
||||
}
|
||||
}
|
||||
|
||||
main().then(
|
||||
() => {
|
||||
console.info("Done deploying staking instances.");
|
||||
process.exit(0);
|
||||
},
|
||||
(error) => {
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
},
|
||||
);
|
||||
@ -1,5 +1,5 @@
|
||||
# Choose from https://hub.docker.com/r/cosmwasm/wasmd-demo/tags
|
||||
REPOSITORY="cosmwasm/wasmd-demo"
|
||||
VERSION="v0.8.0-alpha3"
|
||||
VERSION="v0.8.0"
|
||||
|
||||
CONTAINER_NAME="wasmd"
|
||||
|
||||
@ -11,3 +11,4 @@ echo "Okay, thank you for your patience."
|
||||
SCRIPT_DIR="$(realpath "$(dirname "$0")")"
|
||||
"$SCRIPT_DIR/deploy_erc20.js"
|
||||
"$SCRIPT_DIR/deploy_nameservice.js"
|
||||
"$SCRIPT_DIR/deploy_staking.js"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user