Skip to content

Commit

Permalink
PE-118-faucet-retries-and-timeout-adjustments (#19)
Browse files Browse the repository at this point in the history
* added dotenv and updated readme

* Code cleanup and formatting

* Added env variables for SERVER_PORT and SERVER_TIMEOUT

* added prom counters around getChainId method, and a try catch when it is called in faucet.ts

* reverted www
  • Loading branch information
flavioespinoza authored Mar 7, 2022
1 parent a9f566a commit e02e385
Show file tree
Hide file tree
Showing 10 changed files with 373 additions and 75 deletions.
22 changes: 14 additions & 8 deletions .env.sample → .env.example
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
POSTGRES_HOST=postgres
POSTGRES_PORT=5432
POSTGRES_DB=faucet
POSTGRES_USER=postgres
POSTGRES_PASSWORD=password
PROM_USER=prom
PROM_PASSWORD=client
NETWORK_RPC_NODE="https://rpc.akash.beyno.de:443"
FAUCET_WAIT_PERIOD=1d
FAUCET_DISTRIBUTION_AMOUNT=1000
FAUCET_DENOM=uakt
FAUCET_FEES=5000
FAUCET_GAS=180000
FAUCET_MEMO="Sent from Faucet"
FAUCET_MNEMONIC="secret words"
# uncomment line below for local dev
# INLINE_UI=true

# comment out all lines below for local dev
POSTGRES_HOST=postgres
POSTGRES_PORT=5432
POSTGRES_DB=faucet
POSTGRES_USER=postgres
POSTGRES_PASSWORD=password

PROM_USER=prom
PROM_PASSWORD=client

AUTH0_DOMAIN="mydomain.us.auth0.com"
AUTH0_AUDIENCE="https=//mydomain.com"
FAUCET_MNEMONIC="secret words"
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -119,3 +119,6 @@ dist
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*

# local
local-*
4 changes: 2 additions & 2 deletions app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const PROM_PASSWORD = process.env.PROM_PASSWORD;
const DOMAIN = process.env.AUTH0_DOMAIN;

async function init() {
// var app = express();

const app = fastify({
logger: true,
});
Expand Down Expand Up @@ -72,7 +72,7 @@ async function init() {

await app.register(fastifyExpress);

// this cors module is needed for expressjs methods
// this cors module is needed for express-js methods
app.use(require("cors")());
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
Expand Down
17 changes: 11 additions & 6 deletions bin/www
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
#!/usr/bin/env node

require('dotenv').config();
require("ts-node").register();
let { init } = require("../app");
let http = require("http");

const log = require('ololog');
const { init } = require("../app");
const http = require("http");

const SERVER_PORT = process.env.SERVER_PORT || "3000";

(async () => {
const app = await init();
let port = process.env.PORT || "3000";


// Run the server!
app.listen(port, "0.0.0.0", function (err, address) {
app.listen(SERVER_PORT, (err, address) => {
if (err) {
app.log.error(err);
process.exit(1);
}
log.yellow(`server listening on SERVER_PORT: ${SERVER_PORT}`)
app.log.info(`server listening on ${address}`);
});

})();
50 changes: 37 additions & 13 deletions faucet.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,36 @@
import { DirectSecp256k1HdWallet } from "@cosmjs/proto-signing";
import { SigningStargateClient, coins } from "@cosmjs/stargate";
import parse from "parse-duration";
import 'dotenv/config';

import { DirectSecp256k1HdWallet } from '@cosmjs/proto-signing';
import { SigningStargateClient, coins } from '@cosmjs/stargate';
import parse from 'parse-duration';
import client from "prom-client";

const NETWORK_RPC_NODE = process.env.NETWORK_RPC_NODE;
const FAUCET_MNEMONIC = process.env.FAUCET_MNEMONIC;
const FAUCET_WAIT_PERIOD = process.env.FAUCET_WAIT_PERIOD || "24h";
const FAUCET_WAIT_PERIOD = process.env.FAUCET_WAIT_PERIOD || '24h';
const FAUCET_DISTRIBUTION_AMOUNT =
process.env.FAUCET_DISTRIBUTION_AMOUNT || 1000;
const FAUCET_DENOM = process.env.FAUCET_DENOM || "uakt";
const FAUCET_DENOM = process.env.FAUCET_DENOM || 'uakt';
const FAUCET_FEES = process.env.FAUCET_FEES || 5000;
const FAUCET_GAS = process.env.FAUCET_GAS || 180000;
const FAUCET_MEMO = process.env.FAUCET_MEMO;

const counterGetChainIdCount = new client.Counter({
name: "faucet_getChainId_count",
help: "faucet_getChainId_count is the number of times getChainId is being called",
});
const counterGetChainIdCountPost = new client.Counter({
name: "faucet_getChainId_post_count",
help: "faucet_getChainId_post_count is the number of times getChainId is being called",
});
const counterGetChainIdCountRes = new client.Counter({
name: "faucet_getChainId_res_count",
help: "faucet_getChainId_res_count is the number of times getChainId is being called",
});

export const getWallet = () => {
return DirectSecp256k1HdWallet.fromMnemonic(FAUCET_MNEMONIC as any, {
prefix: "akash",
prefix: 'akash',
});
};

Expand All @@ -31,36 +47,44 @@ export const getDistributionAmount = () => {
};

export const getChainId = async () => {
counterGetChainIdCount.inc();
const wallet = await getWallet();
const client = await SigningStargateClient.connectWithSigner(
const chaiIdClient = await SigningStargateClient.connectWithSigner(
NETWORK_RPC_NODE as any,
wallet
);
return await client.getChainId();
counterGetChainIdCountPost.inc();
const res = await chaiIdClient.getChainId();
counterGetChainIdCountRes.inc();
return res;
};

export const sendTokens = async (recipient: any, amount: any) => {
const wallet = await getWallet();
const [account] = await wallet.getAccounts();
const client = await SigningStargateClient.connectWithSigner(
const tokenClient = await SigningStargateClient.connectWithSigner(
NETWORK_RPC_NODE as any,
wallet
);
if (!amount) amount = getDistributionAmount();

if (!amount) {
amount = getDistributionAmount();
}

const sendMsg = {
typeUrl: "/cosmos.bank.v1beta1.MsgSend",
typeUrl: '/cosmos.bank.v1beta1.MsgSend',
value: {
fromAddress: account.address,
toAddress: recipient,
amount: coins(parseInt(amount), FAUCET_DENOM),
},
};

const fee = {
amount: coins(parseInt(FAUCET_FEES as any), FAUCET_DENOM),
gas: FAUCET_GAS,
};
return await client.signAndBroadcast(

return await tokenClient.signAndBroadcast(
account.address,
[sendMsg],
fee as any,
Expand Down
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@
"@cosmjs/proto-signing": "^0.26.0",
"@cosmjs/stargate": "^0.26.0",
"@types/cors": "^2.8.12",
"axios": "^0.26.0",
"cors": "^2.8.5",
"debug": "~2.6.9",
"dotenv": "^16.0.0",
"express-jwt": "^6.0.0",
"express-jwt-authz": "^2.4.1",
"fastify": "^3.20.2",
Expand All @@ -25,6 +27,7 @@
"handlebars": "^4.7.7",
"jwks-rsa": "^2.0.4",
"nodemon": "^2.0.12",
"ololog": "^1.1.175",
"parse-duration": "^1.0.0",
"pg": "^8.7.1",
"point-of-view": "^5.0.0",
Expand Down
73 changes: 43 additions & 30 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,48 @@ Faucet server for the [Akash Network](https://akash.network)

## How to use

The faucet is authenticated using Auth0 and the
[SPA with API](https://auth0.com/docs/architecture-scenarios/spa-api) architecture.
The faucet is authenticated using `Auth0` and the [SPA API](https://auth0.com/docs/architecture-scenarios/spa-api) architecture.

A good example of this setup is the [Akash faucet UI]().

Users have rate-limited access to the faucet with a configurable wait period.
If the `manage:faucet` permission is given to a user in Auth0, additional
endpoints are accessible to view transaction and user history, and manage
a list of blocked addresses.
Users have rate-limited access to the faucet with a configurable wait period. If the `manage:faucet` permission is given to a user in Auth0, additional endpoints are accessible to view transaction and user history, and manage a list of blocked addresses.

This faucet is configured to work with Akash but will work with any Tendermint SDK based chain.

## Configuration
## Environment Variables

Create a local `.env` file from the `.env.example` file

```bash
cp .env.example .env
```
POSTGRES_HOST: postgres
POSTGRES_PORT: 5432
POSTGRES_DB: faucet
POSTGRES_USER: postgres
POSTGRES_PASSWORD: password
NETWORK_RPC_NODE: https://rpc.akash.beyno.de:443
FAUCET_WAIT_PERIOD: 1d
FAUCET_DISTRIBUTION_AMOUNT: 1000
FAUCET_DENOM: uakt
FAUCET_FEES: 5000
FAUCET_GAS: 180000
FAUCET_MEMO: Sent from Faucet
AUTH0_DOMAIN: mydomain.us.auth0.com
AUTH0_AUDIENCE: https://mydomain.com
FAUCET_MNEMONIC: some secret words here

Open the `.env` file and add required values

```bash
NETWORK_RPC_NODE="https://rpc.akash.beyno.de:443"
FAUCET_WAIT_PERIOD=1d
FAUCET_DISTRIBUTION_AMOUNT=1000
FAUCET_DENOM=uakt
FAUCET_FEES=5000
FAUCET_GAS=180000
FAUCET_MEMO="Sent from Faucet"
FAUCET_MNEMONIC="secret words"
# uncomment line below for local dev
# INLINE_UI=true

# comment out all lines below for local dev
POSTGRES_HOST=postgres
POSTGRES_PORT=5432
POSTGRES_DB=faucet
POSTGRES_USER=postgres
POSTGRES_PASSWORD=password

PROM_USER=prom
PROM_PASSWORD=client

AUTH0_DOMAIN="mydomain.us.auth0.com"
AUTH0_AUDIENCE="https=//mydomain.com"
```

## Endpoints
Expand All @@ -46,7 +59,7 @@ Returns status about the faucet

#### Response

```
```bash
{
'faucetAddress': 'akash1...',
'unlockDate': '2020-10-10T14:48:00',
Expand All @@ -61,15 +74,15 @@ Request funds from the faucet. Requires an access token.

#### Params

```
```bash
{
'address': 'akash1...'
}
```

#### Response

```
```bash
{
'transactionHash': 'A5BE0243169DAF5A...'
}
Expand All @@ -82,7 +95,7 @@ Returns an array of users who have used the faucet. Requires an access token wit

#### Response

```
```bash
[{
'id': 1,
'sub': 'github|1',
Expand All @@ -102,7 +115,7 @@ Returns an array of transactions sent from the faucet. Requires an access token

#### Response

```
```bash
[{
'id': 1,
'userId': 1,
Expand All @@ -124,7 +137,7 @@ Returns an array of blocked addresses. Requires an access token with the

#### Response

```
```bash
[{
'id': 1,
'address': 'akash1...',
Expand All @@ -139,15 +152,15 @@ Create a blocked addresses. Requires an access token with the `manage:faucet` pe

#### Params

```
```bash
{
address: 'akash1...'
}
```

#### Response

```
```bash
{}
```

Expand Down
1 change: 1 addition & 0 deletions routes/faucet.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import express from "express";
import log from "ololog";
const router = express.Router();

import got from "got";
Expand Down
23 changes: 16 additions & 7 deletions routes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,27 @@ const INLINE_UI = process.env.INLINE_UI;

/* GET home page. */
router.get("/", async (req: any, res: any, next: any) => {
let unlockDate;

const wallet = await faucet.getWallet();
const chainId = await faucet.getChainId();

let chainId;
try {
chainId = await faucet.getChainId();
} catch (error) {
console.log('ERROR: faucet.getChainId()', error)
}

const distributionAmount = faucet.getDistributionAmount();
const distrbutionDenom = faucet.getDenom();
const distributionDenom = faucet.getDenom();

const [{ address }] = await wallet.getAccounts();
var unlockDate;


if (req.user && req.user.id) {
let cooldownDate = new Date(
let coolDownDate = new Date(
(new Date() as any) - (faucet.getWaitPeriod() as any)
);
let transaction: any = await latestTransactionSince(req.user, cooldownDate);
let transaction: any = await latestTransactionSince(req.user, coolDownDate);
if (transaction)
unlockDate = new Date(
transaction.createdAt.getTime() + faucet.getWaitPeriod()
Expand All @@ -42,7 +51,7 @@ router.get("/", async (req: any, res: any, next: any) => {
unlockDate,
chainId,
distributionAmount,
distrbutionDenom,
distributionDenom,
})
);
} else {
Expand Down
Loading

0 comments on commit e02e385

Please sign in to comment.