Remove remaining token tickers and fractional digits

This commit is contained in:
Simon Warta 2020-09-17 16:00:19 +02:00
parent 97f0949ee2
commit 4fd4b014d2
12 changed files with 40 additions and 127 deletions

View File

@ -19,8 +19,8 @@ yarn dev-start
Advanced users that want to provide their custom config can start as follows:
```
FAUCET_CREDIT_AMOUNT_COSM=10 \
FAUCET_CREDIT_AMOUNT_STAKE=5 \
FAUCET_CREDIT_AMOUNT_UCOSM=10000000 \
FAUCET_CREDIT_AMOUNT_USTAKE=5000000 \
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/cosmos-faucet start "http://localhost:1317"
@ -53,11 +53,10 @@ FAUCET_GAS_LIMIT Gas limit for send transactions. Defaults to 80000.
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_TOKENS A comma separated list of token denoms, e.g.
"uatom" or "ucosm, mstake".
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.
a placeholder for the token's denom. Defaults to 10.
FAUCET_REFILL_FACTOR Send factor times credit amount on refilling. Defauls to 8.
FAUCET_REFILL_THRESHOLD Refill when balance gets below factor times credit amount.
Defaults to 20.

View File

@ -37,7 +37,7 @@
"test": "yarn build-or-skip && yarn test-node",
"coverage": "nyc --reporter=text --reporter=lcov yarn test --quiet",
"start-dev": "FAUCET_CREDIT_AMOUNT_UCOSM=10000000 FAUCET_CREDIT_AMOUNT_USTAKE=5000000 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/cosmos-faucet start \"http://localhost:1317\"",
"start-coralnet": "FAUCET_ADDRESS_PREFIX=coral FAUCET_TOKENS=\"SHELL=10^6ushell, REEF=10^6ureef\" FAUCET_CREDIT_AMOUNT_USHELL=10000000 FAUCET_CREDIT_AMOUNT_UREEF=2000000 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/cosmos-faucet start \"https://lcd.coralnet.cosmwasm.com\""
"start-coralnet": "FAUCET_ADDRESS_PREFIX=coral FAUCET_TOKENS=\"ushell,ureef\" FAUCET_CREDIT_AMOUNT_USHELL=10000000 FAUCET_CREDIT_AMOUNT_UREEF=2000000 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/cosmos-faucet start \"https://lcd.coralnet.cosmwasm.com\""
},
"dependencies": {
"@cosmjs/crypto": "^0.22.3",

View File

@ -26,11 +26,10 @@ FAUCET_GAS_LIMIT Gas limit for send transactions. Defaults to 80000.
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_TOKENS A comma separated list of token denoms, e.g.
"uatom" or "ucosm, mstake".
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.
a placeholder for the token's denom. Defaults to 10.
FAUCET_REFILL_FACTOR Send factor times credit amount on refilling. Defauls to 8.
FAUCET_REFILL_THRESHOLD Refill when balance gets below factor times credit amount.
Defaults to 20.

View File

@ -28,7 +28,7 @@ export async function start(args: readonly string[]): Promise<void> {
constants.concurrency,
true,
);
const chainTokens = faucet.loadTokenTickers();
const chainTokens = faucet.configuredTokens();
console.info("Chain tokens:", chainTokens);
const accounts = await faucet.loadAccounts();
logAccountsState(accounts, constants.tokenConfig);

View File

@ -35,7 +35,7 @@ export class Webserver {
case "/status": {
const [holder, ...distributors] = await faucet.loadAccounts();
const availableTokens = await faucet.availableTokens();
const chainTokens = faucet.loadTokenTickers();
const chainTokens = faucet.configuredTokens();
context.response.body = {
status: "ok",
...chainConstants,
@ -66,14 +66,13 @@ export class Webserver {
}
const availableTokens = await faucet.availableTokens();
const matchingToken = availableTokens.find((token) => token.denom === denom);
if (matchingToken === undefined) {
const tokens = JSON.stringify(availableTokens);
throw new HttpError(422, `Token is not available. Available tokens are: ${tokens}`);
const matchingDenom = availableTokens.find((availableDenom) => availableDenom === denom);
if (matchingDenom === undefined) {
throw new HttpError(422, `Token is not available. Available tokens are: ${availableTokens}`);
}
try {
await faucet.credit(address, matchingToken.denom);
await faucet.credit(address, matchingDenom);
} catch (e) {
console.error(e);
throw new HttpError(500, "Sending tokens failed");

View File

@ -14,5 +14,5 @@ export const port: number = Number.parseInt(process.env.FAUCET_PORT || "", 10) |
export const mnemonic: string | undefined = process.env.FAUCET_MNEMONIC;
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"),
bankTokens: parseBankTokens(process.env.FAUCET_TOKENS || "ucosm, ustake"),
};

View File

@ -16,13 +16,9 @@ const httpUrl = "http://localhost:1317";
const defaultTokenConfig: TokenConfiguration = {
bankTokens: [
{
fractionalDigits: 6,
tickerSymbol: "COSM",
denom: "ucosm",
},
{
fractionalDigits: 6,
tickerSymbol: "STAKE",
denom: "ustake",
},
],
@ -57,10 +53,7 @@ describe("Faucet", () => {
pendingWithoutWasmd();
const faucet = await Faucet.make(httpUrl, defaultAddressPrefix, defaultTokenConfig, faucetMnemonic, 3);
const tickers = await faucet.availableTokens();
expect(tickers).toEqual([
{ denom: "ucosm", tickerSymbol: "COSM", fractionalDigits: 6 },
{ denom: "ustake", tickerSymbol: "STAKE", fractionalDigits: 6 },
]);
expect(tickers).toEqual(["ucosm", "ustake"]);
});
});
@ -147,12 +140,12 @@ describe("Faucet", () => {
});
});
describe("loadTokenTickers", () => {
describe("configuredTokens", () => {
it("works", async () => {
pendingWithoutWasmd();
const faucet = await Faucet.make(httpUrl, defaultAddressPrefix, defaultTokenConfig, faucetMnemonic, 3);
const tickers = faucet.loadTokenTickers();
expect(tickers).toEqual(["COSM", "STAKE"]);
const tickers = faucet.configuredTokens();
expect(tickers).toEqual(["ucosm", "ustake"]);
});
});

View File

@ -10,7 +10,6 @@ import * as constants from "./constants";
import { debugAccount, logAccountsState, logSendJob } from "./debugging";
import { createWallets } from "./profile";
import { TokenConfiguration, TokenManager } from "./tokenmanager";
import { BankTokenMeta } from "./tokens";
import { MinimalAccount, SendJob } from "./types";
function isDefined<X>(value: X | undefined): value is X {
@ -73,16 +72,17 @@ export class Faucet {
}
/**
* Returns a list of ticker symbols of tokens owned by the the holder and configured in the faucet
* Returns a list of denoms of tokens owned by the the holder and configured in the faucet
*/
public async availableTokens(): Promise<readonly BankTokenMeta[]> {
public async availableTokens(): Promise<string[]> {
const holderAccount = await this.readOnlyClient.getAccount(this.holderAddress);
const balance = holderAccount ? holderAccount.balance : [];
return balance
.filter((b) => b.amount !== "0")
.map((b) => this.tokenConfig.bankTokens.find((token) => token.denom == b.denom))
.filter(isDefined);
.filter(isDefined)
.map((token) => token.denom);
}
/**
@ -107,8 +107,9 @@ export class Faucet {
await this.send(job);
}
public loadTokenTickers(): readonly string[] {
return this.tokenConfig.bankTokens.map((token) => token.tickerSymbol);
/** Returns a list to token denoms which are configured */
public configuredTokens(): readonly string[] {
return this.tokenConfig.bankTokens.map((token) => token.denom);
}
public async loadAccounts(): Promise<readonly MinimalAccount[]> {
@ -134,14 +135,14 @@ export class Faucet {
public async refill(): Promise<void> {
if (this.logging) {
console.info(`Connected to network: ${await this.readOnlyClient.getChainId()}`);
console.info(`Tokens on network: ${this.loadTokenTickers().join(", ")}`);
console.info(`Tokens on network: ${this.configuredTokens().join(", ")}`);
}
const accounts = await this.loadAccounts();
if (this.logging) logAccountsState(accounts, this.tokenConfig);
const [_, ...distributorAccounts] = accounts;
const availableTokenDenoms = (await this.availableTokens()).map((token) => token.denom);
const availableTokenDenoms = await this.availableTokens();
if (this.logging) console.info("Available tokens:", availableTokenDenoms);
const jobs: SendJob[] = [];

View File

@ -2,18 +2,7 @@ import { TokenConfiguration, TokenManager } from "./tokenmanager";
import { MinimalAccount } from "./types";
const dummyConfig: TokenConfiguration = {
bankTokens: [
{
tickerSymbol: "TOKENZ",
fractionalDigits: 6,
denom: "utokenz",
},
{
tickerSymbol: "TRASH",
fractionalDigits: 3,
denom: "mtrash",
},
],
bankTokens: [{ denom: "utokenz" }, { denom: "mtrash" }],
};
describe("TokenManager", () => {

View File

@ -55,9 +55,9 @@ export class TokenManager {
const balanceAmount = account.balance.find((b) => b.denom === meta.denom);
const balance = Decimal.fromAtomics(balanceAmount ? balanceAmount.amount : "0", meta.fractionalDigits);
const balance = Decimal.fromAtomics(balanceAmount ? balanceAmount.amount : "0", 0);
const thresholdAmount = this.refillThreshold(denom);
const threshold = Decimal.fromAtomics(thresholdAmount.amount, meta.fractionalDigits);
const threshold = Decimal.fromAtomics(thresholdAmount.amount, 0);
return balance.isLessThan(threshold);
}
@ -67,10 +67,4 @@ export class TokenManager {
if (!match) throw new Error(`No token found for denom: ${denom}`);
return match;
}
private getTokenMetaForTicker(ticker: string): BankTokenMeta {
const match = this.config.bankTokens.find((token) => token.tickerSymbol === ticker);
if (!match) throw new Error(`No token found for ticker: ${ticker}`);
return match;
}
}

View File

@ -3,17 +3,13 @@ import { parseBankToken, parseBankTokens } from "./tokens";
describe("tokens", () => {
describe("parseBankToken", () => {
it("works", () => {
expect(parseBankToken("COSM=10^6ucosm")).toEqual({
tickerSymbol: "COSM",
fractionalDigits: 6,
expect(parseBankToken("ucosm")).toEqual({
denom: "ucosm",
});
});
it("allows using whitespace", () => {
expect(parseBankToken("COSM = 10^6 ucosm")).toEqual({
tickerSymbol: "COSM",
fractionalDigits: 6,
expect(parseBankToken(" ucosm\n")).toEqual({
denom: "ucosm",
});
});
@ -21,58 +17,19 @@ describe("tokens", () => {
describe("parseBankTokens", () => {
it("works for one", () => {
expect(parseBankTokens("COSM=10^6ucosm")).toEqual([
{
tickerSymbol: "COSM",
fractionalDigits: 6,
denom: "ucosm",
},
]);
expect(parseBankTokens("ucosm")).toEqual([{ 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",
},
]);
expect(parseBankTokens("ucosm,mstake")).toEqual([{ denom: "ucosm" }, { 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",
},
]);
expect(parseBankTokens("ucosm, mstake\n")).toEqual([{ denom: "ucosm" }, { 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",
},
]);
expect(parseBankTokens("ucosm,mstake,")).toEqual([{ denom: "ucosm" }, { denom: "mstake" }]);
});
});
});

View File

@ -1,24 +1,8 @@
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})$/;
const parseBankTokenPattern = /^([a-zA-Z]{2,20})$/;
export function parseBankToken(input: string): BankTokenMeta {
const match = input.replace(/\s/g, "").match(parseBankTokenPattern);
@ -26,9 +10,7 @@ export function parseBankToken(input: string): BankTokenMeta {
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],
denom: match[1],
};
}