Compare commits

..

2 Commits

Author SHA1 Message Date
3649cfb2fa Update config with alnt token denom (#3)
Part of [laconicd testnet validator enrollment](https://www.notion.so/laconicd-testnet-validator-enrollment-6fc1d3cafcc64fef8c5ed3affa27c675)

Co-authored-by: IshaVenikar <ishavenikar7@gmail.com>
Co-authored-by: Shreerang Kale <shreerangkale@gmail.com>
Reviewed-on: cerc-io/laconic-faucet#3
Co-authored-by: Prathamesh Musale <prathamesh@noreply.git.vdb.to>
Co-committed-by: Prathamesh Musale <prathamesh@noreply.git.vdb.to>
2024-07-30 11:40:36 +00:00
fd27cd141c Add netcat installation in Dockerfile (#2)
Part of [laconicd testnet validator enrollment](https://www.notion.so/laconicd-testnet-validator-enrollment-6fc1d3cafcc64fef8c5ed3affa27c675)

Reviewed-on: cerc-io/laconic-faucet#2
Co-authored-by: Prathamesh Musale <prathamesh.musale0@gmail.com>
Co-committed-by: Prathamesh Musale <prathamesh.musale0@gmail.com>
2024-07-26 12:23:30 +00:00
3 changed files with 22 additions and 45 deletions

View File

@ -2,6 +2,8 @@ FROM node:20-bullseye
WORKDIR /app
RUN apt-get update && apt-get install -y netcat
# Copy the application code
COPY . .

View File

@ -1,14 +1,13 @@
[registry]
[upstream]
rpcEndpoint = "http://localhost:26657"
chainId = "laconic_9000-1"
denom = "photon"
denom = "alnt"
prefix = "laconic"
gasPrice = "0.01"
gasPrice = "1"
faucetKey = ""
[server]
port = 3000
periodInSecs = 60
transferAmount = 1000000
periodTransferLimit = 3000000
transferAmount = 10000000000 # 1 * 10^10 alnt
periodTransferLimit = 30000000000 # 3 * 10^10 alnt
dbDir = "db"

View File

@ -12,10 +12,10 @@ import KeyvSqlite from '@keyv/sqlite';
const CONFIG_PATH = 'environments/local.toml';
const FAUCET_DATA_FILE = 'faucet_data.sqlite';
const TTL_MULTIPLIER = 1.5; // 1.5 times the configured period
const FAUCET_DATA_TTL = 86400000; // 24 hrs
interface Config {
registry: {
upstream: {
rpcEndpoint: string
chainId: string
denom: string
@ -25,18 +25,12 @@ interface Config {
},
server: {
port: number
periodInSecs: number
transferAmount: string
periodTransferLimit: string
dbDir: string
}
}
interface FaucetStoreValue {
periodStart: string
amountSent: string
}
async function main (): Promise<void> {
// Read and parse the configuration
const configFile = fs.readFileSync(CONFIG_PATH, 'utf-8');
@ -56,32 +50,18 @@ async function main (): Promise<void> {
return res.status(400).json({ error: 'address is required' });
}
if (!isValidAddress(accountAddress, config.registry.prefix)) {
if (!isValidAddress(accountAddress, config.upstream.prefix)) {
return res.status(400).json({ error: 'invalid address' });
}
const currentTimeInSeconds = Math.floor(Date.now() / 1000);
let amountSentToAccount = BigInt(0);
let accountPeriodStart = currentTimeInSeconds;
// Get accounts data from faucet data store
const accountFaucetData: FaucetStoreValue = await faucetDataStore.get(accountAddress);
// Check rate limit
if (accountFaucetData !== undefined) {
const elapsedTime = currentTimeInSeconds - Number(accountFaucetData.periodStart);
const now = Date.now();
const today = new Date(now).toISOString().split('T')[0];
const faucetStoreKey = `${accountAddress}:${today}`;
const amountSentToAddress = await faucetDataStore.get(faucetStoreKey) || '0';
// Check if saved entry is still within configured period
// Else, create a fresh entry
if (elapsedTime < config.server.periodInSecs) {
amountSentToAccount = BigInt(accountFaucetData.amountSent);
accountPeriodStart = Number(accountFaucetData.periodStart);
// Check if limit has been reached
if (amountSentToAccount + BigInt(config.server.transferAmount) > BigInt(config.server.periodTransferLimit)) {
return res.status(429).json({ error: 'Limit exceeded' });
}
}
if (BigInt(amountSentToAddress) + BigInt(config.server.transferAmount) > BigInt(config.server.periodTransferLimit)) {
return res.status(429).json({ error: 'Limit exceeded' });
}
try {
@ -89,11 +69,7 @@ async function main (): Promise<void> {
console.log(`Sent tokens to address: ${accountAddress}, txHash: ${txHash}`);
// Update rate limit
const updatedAccountFaucetData: FaucetStoreValue = {
periodStart: accountPeriodStart.toString(),
amountSent: amountSentToAccount.toString()
};
await faucetDataStore.set(accountAddress, updatedAccountFaucetData, config.server.periodInSecs * TTL_MULTIPLIER * 1000);
await faucetDataStore.set(faucetStoreKey, (BigInt(amountSentToAddress) + BigInt(config.server.transferAmount)).toString(), FAUCET_DATA_TTL);
res.json({ success: true, txHash });
} catch (error) {
@ -132,27 +108,27 @@ async function initKVStore (dbDir: string): Promise<Keyv> {
}
async function sendTokens (config: Config, recipientAddress: string, amount: string): Promise<string> {
let faucetKey = config.registry.faucetKey;
let faucetKey = config.upstream.faucetKey;
if (faucetKey.startsWith('0x')) {
faucetKey = faucetKey.slice(2);
}
const wallet = await DirectSecp256k1Wallet.fromKey(
Buffer.from(faucetKey, 'hex'),
config.registry.prefix
config.upstream.prefix
);
const [faucetAccount] = await wallet.getAccounts();
const client = await SigningStargateClient.connectWithSigner(
config.registry.rpcEndpoint,
config.upstream.rpcEndpoint,
wallet,
{ gasPrice: GasPrice.fromString(`${config.registry.gasPrice}${config.registry.denom}`) }
{ gasPrice: GasPrice.fromString(`${config.upstream.gasPrice}${config.upstream.denom}`) }
);
const result = await client.sendTokens(
faucetAccount.address,
recipientAddress,
[{ denom: config.registry.denom, amount: amount }],
[{ denom: config.upstream.denom, amount: amount }],
'auto',
'Faucet transfer'
);