mirror of
https://github.com/cosmos/cosmjs.git
synced 2025-03-10 21:49:15 +00:00
Merge branch 'make-faucet-configurable' into 0.22
This commit is contained in:
commit
332ad4e98e
@ -7,6 +7,9 @@
|
||||
- @cosmjs/launchpad: Add ed25519 support to `encodeBech32Pubkey`.
|
||||
- @cosmjs/launchpad: Add `encodeAminoPubkey` and `decodeAminoPubkey`.
|
||||
- @cosmjs/utils: Add `arrayContentEquals`.
|
||||
- @cosmjs/faucet: Add config variables `FAUCET_ADDRESS_PREFIX` and
|
||||
`FAUCET_TOKENS`.
|
||||
- @cosmjs/faucet: Remove broken chain ID from `cosmwasm-faucet generate`.
|
||||
|
||||
## 0.22.0 (2020-08-03)
|
||||
|
||||
|
@ -38,7 +38,6 @@ help Shows a help text and exits
|
||||
version Prints the version and exits
|
||||
|
||||
generate Generates a random mnemonic, shows derived faucet addresses and exits
|
||||
1 Chain ID
|
||||
|
||||
start Starts the faucet
|
||||
1 Node base URL, e.g. http://localhost:1317
|
||||
@ -49,6 +48,10 @@ FAUCET_CONCURRENCY Number of distributor accounts. Defaults to 5.
|
||||
FAUCET_PORT Port of the webserver. Defaults to 8000.
|
||||
FAUCET_MNEMONIC Secret mnemonic that serves as the base secret for the
|
||||
faucet HD accounts
|
||||
FAUCET_ADDRESS_PREFIX The bech32 address prefix. Defaults to "cosmos".
|
||||
FAUCET_TOKENS A comma separated list of tokens configs in the format
|
||||
{DISPLAY}=10^{DIGITS}{base}, e.g.
|
||||
"ATOM=10^6uatom" or "COSM = 10^6ucosm, STAKE = 10^3mstake".
|
||||
FAUCET_CREDIT_AMOUNT_TKN Send this amount of TKN to a user requesting TKN. TKN is
|
||||
a placeholder for the token ticker. Defaults to 10.
|
||||
FAUCET_REFILL_FACTOR Send factor times credit amount on refilling. Defauls to 8.
|
||||
|
@ -22,7 +22,7 @@
|
||||
"access": "public"
|
||||
},
|
||||
"scripts": {
|
||||
"dev-start": "FAUCET_CREDIT_AMOUNT_COSM=10 FAUCET_CREDIT_AMOUNT_STAKE=5 FAUCET_CONCURRENCY=3 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\" ./bin/cosmwasm-faucet start \"http://localhost:1317\"",
|
||||
"dev-start": "yarn start-dev",
|
||||
"format": "prettier --write --loglevel warn \"./src/**/*.ts\"",
|
||||
"format-text": "prettier --write --prose-wrap always --print-width 80 \"./*.md\"",
|
||||
"lint": "eslint --max-warnings 0 \"**/*.{js,ts}\"",
|
||||
@ -31,7 +31,9 @@
|
||||
"build-or-skip": "[ -n \"$SKIP_BUILD\" ] || yarn build",
|
||||
"test-node": "node jasmine-testrunner.js",
|
||||
"test": "yarn build-or-skip && yarn test-node",
|
||||
"coverage": "nyc --reporter=text --reporter=lcov yarn test --quiet"
|
||||
"coverage": "nyc --reporter=text --reporter=lcov yarn test --quiet",
|
||||
"start-dev": "FAUCET_CREDIT_AMOUNT_COSM=10 FAUCET_CREDIT_AMOUNT_STAKE=5 FAUCET_CONCURRENCY=3 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\" ./bin/cosmwasm-faucet start \"http://localhost:1317\"",
|
||||
"start-coralnet": "FAUCET_ADDRESS_PREFIX=coral FAUCET_TOKENS=\"SHELL=10^6ushell, REEF=10^6ureef\" FAUCET_CREDIT_AMOUNT_SHELL=10 FAUCET_CREDIT_AMOUNT_REEF=2 FAUCET_CONCURRENCY=3 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\" ./bin/cosmwasm-faucet start \"https://lcd.coralnet.cosmwasm.com\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@cosmjs/crypto": "^0.22.0",
|
||||
|
@ -4,17 +4,15 @@ import * as constants from "../constants";
|
||||
import { createWallets } from "../profile";
|
||||
|
||||
export async function generate(args: readonly string[]): Promise<void> {
|
||||
if (args.length < 1) {
|
||||
throw Error(
|
||||
`Not enough arguments for action 'generate'. See '${constants.binaryName} help' or README for arguments.`,
|
||||
if (args.length > 0) {
|
||||
console.warn(
|
||||
`Warning: ${constants.binaryName} generate does not require positional arguments anymore. Use env variables FAUCET_ADDRESS_PREFIX or FAUCET_CONCURRENCY to configure how accounts are created.`,
|
||||
);
|
||||
}
|
||||
|
||||
const chainId = args[0];
|
||||
|
||||
const mnemonic = Bip39.encode(Random.getBytes(16)).toString();
|
||||
console.info(`FAUCET_MNEMONIC="${mnemonic}"`);
|
||||
|
||||
// Log the addresses
|
||||
await createWallets(mnemonic, chainId, constants.concurrency, true);
|
||||
await createWallets(mnemonic, constants.addressPrefix, constants.concurrency, true);
|
||||
}
|
||||
|
@ -11,7 +11,6 @@ help Shows a help text and exits
|
||||
version Prints the version and exits
|
||||
|
||||
generate Generates a random mnemonic, shows derived faucet addresses and exits
|
||||
1 Chain ID
|
||||
|
||||
start Starts the faucet
|
||||
1 Node base URL, e.g. http://localhost:1317
|
||||
@ -22,6 +21,10 @@ FAUCET_CONCURRENCY Number of distributor accounts. Defaults to 5.
|
||||
FAUCET_PORT Port of the webserver. Defaults to 8000.
|
||||
FAUCET_MNEMONIC Secret mnemonic that serves as the base secret for the
|
||||
faucet HD accounts
|
||||
FAUCET_ADDRESS_PREFIX The bech32 address prefix. Defaults to "cosmos".
|
||||
FAUCET_TOKENS A comma separated list of tokens configs in the format
|
||||
{DISPLAY}=10^{DIGITS}{base}, e.g.
|
||||
"ATOM=10^6uatom" or "COSM = 10^6ucosm, STAKE = 10^3mstake".
|
||||
FAUCET_CREDIT_AMOUNT_TKN Send this amount of TKN to a user requesting TKN. TKN is
|
||||
a placeholder for the token ticker. Defaults to 10.
|
||||
FAUCET_REFILL_FACTOR Send factor times credit amount on refilling. Defauls to 8.
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { CosmosClient } from "@cosmjs/launchpad";
|
||||
|
||||
import { Webserver } from "../../api/webserver";
|
||||
import * as constants from "../../constants";
|
||||
import { logAccountsState } from "../../debugging";
|
||||
import { Faucet } from "../../faucet";
|
||||
import { Webserver } from "../api/webserver";
|
||||
import * as constants from "../constants";
|
||||
import { logAccountsState } from "../debugging";
|
||||
import { Faucet } from "../faucet";
|
||||
|
||||
export async function start(args: readonly string[]): Promise<void> {
|
||||
if (args.length < 1) {
|
||||
@ -23,7 +23,7 @@ export async function start(args: readonly string[]): Promise<void> {
|
||||
const faucet = await Faucet.make(
|
||||
blockchainBaseUrl,
|
||||
constants.addressPrefix,
|
||||
constants.developmentTokenConfig,
|
||||
constants.tokenConfig,
|
||||
constants.mnemonic,
|
||||
constants.concurrency,
|
||||
true,
|
||||
@ -31,7 +31,7 @@ export async function start(args: readonly string[]): Promise<void> {
|
||||
const chainTokens = faucet.loadTokenTickers();
|
||||
console.info("Chain tokens:", chainTokens);
|
||||
const accounts = await faucet.loadAccounts();
|
||||
logAccountsState(accounts, constants.developmentTokenConfig);
|
||||
logAccountsState(accounts, constants.tokenConfig);
|
||||
let availableTokens = await faucet.availableTokens();
|
||||
console.info("Available tokens:", availableTokens);
|
||||
setInterval(async () => {
|
||||
@ -45,4 +45,5 @@ export async function start(args: readonly string[]): Promise<void> {
|
||||
console.info("Creating webserver ...");
|
||||
const server = new Webserver(faucet, { nodeUrl: blockchainBaseUrl, chainId: chainId });
|
||||
server.start(constants.port);
|
||||
console.info(`Try "curl -sS http://localhost:${constants.port}/status | jq" to check the status.`);
|
||||
}
|
@ -1 +0,0 @@
|
||||
export { start } from "./start";
|
@ -1,24 +1,11 @@
|
||||
import { TokenConfiguration } from "./types";
|
||||
import { TokenConfiguration } from "./tokenmanager";
|
||||
import { parseBankTokens } from "./tokens";
|
||||
|
||||
export const binaryName = "cosmwasm-faucet";
|
||||
export const concurrency: number = Number.parseInt(process.env.FAUCET_CONCURRENCY || "", 10) || 5;
|
||||
export const port: number = Number.parseInt(process.env.FAUCET_PORT || "", 10) || 8000;
|
||||
export const mnemonic: string | undefined = process.env.FAUCET_MNEMONIC;
|
||||
|
||||
export const addressPrefix = "cosmos";
|
||||
|
||||
/** For the local development chain */
|
||||
export const developmentTokenConfig: TokenConfiguration = {
|
||||
bankTokens: [
|
||||
{
|
||||
fractionalDigits: 6,
|
||||
tickerSymbol: "COSM",
|
||||
denom: "ucosm",
|
||||
},
|
||||
{
|
||||
fractionalDigits: 6,
|
||||
tickerSymbol: "STAKE",
|
||||
denom: "ustake",
|
||||
},
|
||||
],
|
||||
export const addressPrefix = process.env.FAUCET_ADDRESS_PREFIX || "cosmos";
|
||||
export const tokenConfig: TokenConfiguration = {
|
||||
bankTokens: parseBankTokens(process.env.FAUCET_TOKENS || "COSM=10^6ucosm, STAKE=10^6ustake"),
|
||||
};
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { Coin } from "@cosmjs/launchpad";
|
||||
import { Decimal } from "@cosmjs/math";
|
||||
|
||||
import { MinimalAccount, SendJob, TokenConfiguration } from "./types";
|
||||
import { TokenConfiguration } from "./tokenmanager";
|
||||
import { MinimalAccount, SendJob } from "./types";
|
||||
|
||||
/** A string representation of a coin in a human-readable format that can change at any time */
|
||||
function debugCoin(coin: Coin, tokens: TokenConfiguration): string {
|
||||
|
@ -4,7 +4,7 @@ import { CosmosClient } from "@cosmjs/launchpad";
|
||||
import { assert } from "@cosmjs/utils";
|
||||
|
||||
import { Faucet } from "./faucet";
|
||||
import { TokenConfiguration } from "./types";
|
||||
import { TokenConfiguration } from "./tokenmanager";
|
||||
|
||||
function pendingWithoutWasmd(): void {
|
||||
if (!process.env.WASMD_ENABLED) {
|
||||
|
@ -3,8 +3,8 @@ import { sleep } from "@cosmjs/utils";
|
||||
|
||||
import { debugAccount, logAccountsState, logSendJob } from "./debugging";
|
||||
import { createWallets } from "./profile";
|
||||
import { TokenManager } from "./tokenmanager";
|
||||
import { MinimalAccount, SendJob, TokenConfiguration } from "./types";
|
||||
import { TokenConfiguration, TokenManager } from "./tokenmanager";
|
||||
import { MinimalAccount, SendJob } from "./types";
|
||||
|
||||
function isDefined<X>(value: X | undefined): value is X {
|
||||
return value !== undefined;
|
||||
@ -119,7 +119,7 @@ export class Faucet {
|
||||
|
||||
public async refill(): Promise<void> {
|
||||
if (this.logging) {
|
||||
console.info(`Connected to network: ${this.readOnlyClient.getChainId()}`);
|
||||
console.info(`Connected to network: ${await this.readOnlyClient.getChainId()}`);
|
||||
console.info(`Tokens on network: ${this.loadTokenTickers().join(", ")}`);
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { TokenManager } from "./tokenmanager";
|
||||
import { MinimalAccount, TokenConfiguration } from "./types";
|
||||
import { TokenConfiguration, TokenManager } from "./tokenmanager";
|
||||
import { MinimalAccount } from "./types";
|
||||
|
||||
const dummyConfig: TokenConfiguration = {
|
||||
bankTokens: [
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { Coin } from "@cosmjs/launchpad";
|
||||
import { Decimal, Uint53 } from "@cosmjs/math";
|
||||
|
||||
import { BankTokenMeta, MinimalAccount, TokenConfiguration } from "./types";
|
||||
import { BankTokenMeta } from "./tokens";
|
||||
import { MinimalAccount } from "./types";
|
||||
|
||||
/** Send `factor` times credit amount on refilling */
|
||||
const defaultRefillFactor = 20;
|
||||
@ -9,6 +10,11 @@ const defaultRefillFactor = 20;
|
||||
/** refill when balance gets below `factor` times credit amount */
|
||||
const defaultRefillThresholdFactor = 8;
|
||||
|
||||
export interface TokenConfiguration {
|
||||
/** Supported tokens of the Cosmos SDK bank module */
|
||||
readonly bankTokens: readonly BankTokenMeta[];
|
||||
}
|
||||
|
||||
export class TokenManager {
|
||||
private readonly config: TokenConfiguration;
|
||||
|
||||
|
78
packages/faucet/src/tokens.spec.ts
Normal file
78
packages/faucet/src/tokens.spec.ts
Normal file
@ -0,0 +1,78 @@
|
||||
import { parseBankToken, parseBankTokens } from "./tokens";
|
||||
|
||||
describe("tokens", () => {
|
||||
describe("parseBankToken", () => {
|
||||
it("works", () => {
|
||||
expect(parseBankToken("COSM=10^6ucosm")).toEqual({
|
||||
tickerSymbol: "COSM",
|
||||
fractionalDigits: 6,
|
||||
denom: "ucosm",
|
||||
});
|
||||
});
|
||||
|
||||
it("allows using whitespace", () => {
|
||||
expect(parseBankToken("COSM = 10^6 ucosm")).toEqual({
|
||||
tickerSymbol: "COSM",
|
||||
fractionalDigits: 6,
|
||||
denom: "ucosm",
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("parseBankTokens", () => {
|
||||
it("works for one", () => {
|
||||
expect(parseBankTokens("COSM=10^6ucosm")).toEqual([
|
||||
{
|
||||
tickerSymbol: "COSM",
|
||||
fractionalDigits: 6,
|
||||
denom: "ucosm",
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it("works for two", () => {
|
||||
expect(parseBankTokens("COSM=10^6ucosm,STAKE=10^3mstake")).toEqual([
|
||||
{
|
||||
tickerSymbol: "COSM",
|
||||
fractionalDigits: 6,
|
||||
denom: "ucosm",
|
||||
},
|
||||
{
|
||||
tickerSymbol: "STAKE",
|
||||
fractionalDigits: 3,
|
||||
denom: "mstake",
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it("ignores whitespace", () => {
|
||||
expect(parseBankTokens("COSM=10^6ucosm, STAKE=10^3mstake\n")).toEqual([
|
||||
{
|
||||
tickerSymbol: "COSM",
|
||||
fractionalDigits: 6,
|
||||
denom: "ucosm",
|
||||
},
|
||||
{
|
||||
tickerSymbol: "STAKE",
|
||||
fractionalDigits: 3,
|
||||
denom: "mstake",
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it("ignores empty elements", () => {
|
||||
expect(parseBankTokens("COSM=10^6ucosm,STAKE=10^3mstake,")).toEqual([
|
||||
{
|
||||
tickerSymbol: "COSM",
|
||||
fractionalDigits: 6,
|
||||
denom: "ucosm",
|
||||
},
|
||||
{
|
||||
tickerSymbol: "STAKE",
|
||||
fractionalDigits: 3,
|
||||
denom: "mstake",
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
41
packages/faucet/src/tokens.ts
Normal file
41
packages/faucet/src/tokens.ts
Normal file
@ -0,0 +1,41 @@
|
||||
import { Uint53 } from "@cosmjs/math";
|
||||
|
||||
export interface BankTokenMeta {
|
||||
readonly denom: string;
|
||||
/**
|
||||
* The token ticker symbol, e.g. ATOM or ETH.
|
||||
*/
|
||||
readonly tickerSymbol: string;
|
||||
/**
|
||||
* The number of fractional digits the token supports.
|
||||
*
|
||||
* A quantity is expressed as atomic units. 10^fractionalDigits of those
|
||||
* atomic units make up 1 token.
|
||||
*
|
||||
* E.g. in Ethereum 10^18 wei are 1 ETH and from the quantity 123000000000000000000
|
||||
* the last 18 digits are the fractional part and the rest the wole part.
|
||||
*/
|
||||
readonly fractionalDigits: number;
|
||||
}
|
||||
|
||||
const parseBankTokenPattern = /^([a-zA-Z]{2,20})=10\^([0-9]+)([a-zA-Z]{2,20})$/;
|
||||
|
||||
export function parseBankToken(input: string): BankTokenMeta {
|
||||
const match = input.replace(/\s/g, "").match(parseBankTokenPattern);
|
||||
if (!match) {
|
||||
throw new Error("Token could not be parsed. Format: {DISPLAY}=10^{DIGITS}{base}, e.g. ATOM=10^6uatom");
|
||||
}
|
||||
return {
|
||||
tickerSymbol: match[1],
|
||||
fractionalDigits: Uint53.fromString(match[2]).toNumber(),
|
||||
denom: match[3],
|
||||
};
|
||||
}
|
||||
|
||||
export function parseBankTokens(input: string): BankTokenMeta[] {
|
||||
return input
|
||||
.trim()
|
||||
.split(",")
|
||||
.filter((part) => part.trim() !== "")
|
||||
.map((part) => parseBankToken(part));
|
||||
}
|
@ -6,27 +6,4 @@ export interface SendJob {
|
||||
readonly amount: Coin;
|
||||
}
|
||||
|
||||
export interface BankTokenMeta {
|
||||
readonly denom: string;
|
||||
/**
|
||||
* The token ticker symbol, e.g. ATOM or ETH.
|
||||
*/
|
||||
readonly tickerSymbol: string;
|
||||
/**
|
||||
* The number of fractional digits the token supports.
|
||||
*
|
||||
* A quantity is expressed as atomic units. 10^fractionalDigits of those
|
||||
* atomic units make up 1 token.
|
||||
*
|
||||
* E.g. in Ethereum 10^18 wei are 1 ETH and from the quantity 123000000000000000000
|
||||
* the last 18 digits are the fractional part and the rest the wole part.
|
||||
*/
|
||||
readonly fractionalDigits: number;
|
||||
}
|
||||
|
||||
export interface TokenConfiguration {
|
||||
/** Supported tokens of the Cosmos SDK bank module */
|
||||
readonly bankTokens: readonly BankTokenMeta[];
|
||||
}
|
||||
|
||||
export type MinimalAccount = Pick<Account, "address" | "balance">;
|
||||
|
Loading…
x
Reference in New Issue
Block a user