cosmjs-util/packages/faucet/src/tokenmanager.ts
2020-02-10 14:19:34 +01:00

68 lines
2.6 KiB
TypeScript

import { TokenConfiguration } from "@cosmwasm/bcp";
import { Account, Amount, TokenTicker } from "@iov/bcp";
import { Decimal, Uint53 } from "@iov/encoding";
/** Send `factor` times credit amount on refilling */
const defaultRefillFactor = 20;
/** refill when balance gets below `factor` times credit amount */
const defaultRefillThresholdFactor = 8;
export class TokenManager {
private readonly config: TokenConfiguration;
public constructor(config: TokenConfiguration) {
this.config = config;
}
/** The amount of tokens that will be sent to the user */
public creditAmount(token: TokenTicker, factor: Uint53 = new Uint53(1)): Amount {
const amountFromEnv = process.env[`FAUCET_CREDIT_AMOUNT_${token}`];
const amount = amountFromEnv ? Uint53.fromString(amountFromEnv).toNumber() : 10;
const value = new Uint53(amount * factor.toNumber());
const fractionalDigits = this.getFractionalDigits(token);
return {
quantity: value.toString() + "0".repeat(fractionalDigits),
fractionalDigits: fractionalDigits,
tokenTicker: token,
};
}
public refillAmount(token: TokenTicker): Amount {
const factorFromEnv = Number.parseInt(process.env.FAUCET_REFILL_FACTOR || "0", 10) || undefined;
const factor = new Uint53(factorFromEnv || defaultRefillFactor);
return this.creditAmount(token, factor);
}
public refillThreshold(token: TokenTicker): Amount {
const factorFromEnv = Number.parseInt(process.env.FAUCET_REFILL_THRESHOLD || "0", 10) || undefined;
const factor = new Uint53(factorFromEnv || defaultRefillThresholdFactor);
return this.creditAmount(token, factor);
}
/** true iff the distributor account needs a refill */
public needsRefill(account: Account, token: TokenTicker): boolean {
const balanceAmount = account.balance.find(b => b.tokenTicker === token);
const balance = balanceAmount
? Decimal.fromAtomics(balanceAmount.quantity, balanceAmount.fractionalDigits)
: Decimal.fromAtomics("0", 0);
const thresholdAmount = this.refillThreshold(token);
const threshold = Decimal.fromAtomics(thresholdAmount.quantity, thresholdAmount.fractionalDigits);
// TODO: perform < operation on Decimal type directly
// https://github.com/iov-one/iov-core/issues/1375
return balance.toFloatApproximation() < threshold.toFloatApproximation();
}
private getFractionalDigits(ticker: TokenTicker): number {
const match = [...this.config.bankTokens, ...(this.config.erc20Tokens || [])].find(
token => token.ticker === ticker,
);
if (!match) throw new Error(`No token found for ticker symbol: ${ticker}`);
return match.fractionalDigits;
}
}