Skip to content

Commit

Permalink
allow running the faucet backend without a working RPC endpoint (show…
Browse files Browse the repository at this point in the history
…ing error message)
  • Loading branch information
pk910 committed Jan 29, 2023
1 parent a9fed36 commit 4b2f3fa
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 10 deletions.
3 changes: 3 additions & 0 deletions faucet-config.example.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,9 @@ lowFundsWarning: "The faucet is running out of funds! Faucet Balance: {1}"
# empty faucet error message / false to disable the error
noFundsError: "Sorry, the faucet is out of funds :("

# RPC unreachable error message / true to show the generic message / false to disable the error
rpcConnectionError: "The Faucet is currently not working properly (RPC error)"

# prevent creation of new sessions (used for maintenance)
#denyNewSessions: "Sorry, the faucet is currently in maintenance mode. Please try again later."

Expand Down
2 changes: 2 additions & 0 deletions src/common/FaucetConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ export interface IFaucetConfig {
lowFundsBalance: number; // minimum balance to show the low funds warning
lowFundsWarning: string | boolean; // low faucet balance warning message / true to show the generic message / false to disable the warning
noFundsError: string | boolean; // empty faucet error message / true to show the generic message / false to disable the error
rpcConnectionError: string | boolean; // RPC unreachable error message / true to show the generic message / false to disable the error
denyNewSessions: string | boolean; // prevent creation of new sessions (used for maintenance)

ethRpcHost: string; // ETH execution layer RPC host
Expand Down Expand Up @@ -235,6 +236,7 @@ let defaultConfig: IFaucetConfig = {
lowFundsBalance: 10000000000000000000, // 10 ETH
lowFundsWarning: true,
noFundsError: true,
rpcConnectionError: true,
denyNewSessions: false,
ethRpcHost: "http://127.0.0.1:8545/",
ethWalletKey: "fc2d0a2d823f90e0599e1e9d9202204e42a5ed388000ab565a34e7cbb566274b",
Expand Down
46 changes: 36 additions & 10 deletions src/services/EthWeb3Manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { FaucetStore } from './FaucetStore';
import { PoWRewardLimiter } from './PoWRewardLimiter';

interface WalletState {
ready: boolean;
nonce: number;
balance: bigint;
}
Expand All @@ -34,7 +35,8 @@ enum FucetWalletState {
UNKNOWN = 0,
NORMAL = 1,
LOWFUNDS = 2,
NOFUNDS = 3
NOFUNDS = 3,
OFFLINE = 4,
}

interface ClaimTxEvents {
Expand Down Expand Up @@ -87,7 +89,6 @@ export class ClaimTx extends TypedEmitter<ClaimTxEvents> {

export class EthWeb3Manager {
private web3: Web3;
private web3ReadyPromise: Promise<void>;
private chainCommon: EthCom.default;
private walletKey: Buffer;
private walletAddr: string;
Expand Down Expand Up @@ -117,9 +118,6 @@ export class EthWeb3Manager {

this.loadWalletState().then(() => {
setInterval(() => this.processQueue(), 2000);
}, (err) => {
ServiceManager.GetService(PoWStatusLog).emitLog(PoWStatusLogLevel.ERROR, "Error loading wallet state for " + this.walletAddr + ": " + err.toString());
process.exit(0);
});
}

Expand Down Expand Up @@ -189,10 +187,19 @@ export class EthWeb3Manager {
}).then((res) => {
this.initChainCommon(res[2]);
this.walletState = {
ready: true,
balance: BigInt(res[0]),
nonce: res[1],
};
ServiceManager.GetService(PoWStatusLog).emitLog(PoWStatusLogLevel.INFO, "Wallet " + this.walletAddr + ": " + (Math.round(weiToEth(this.walletState.balance)*1000)/1000) + " ETH [Nonce: " + this.walletState.nonce + "]");
}, (err) => {
this.walletState = {
ready: false,
balance: 0n,
nonce: 0,
};
ServiceManager.GetService(PoWStatusLog).emitLog(PoWStatusLogLevel.ERROR, "Error loading wallet state for " + this.walletAddr + ": " + err.toString());
}).then(() => {
this.updateFaucetStatus();
});
}
Expand All @@ -201,7 +208,9 @@ export class EthWeb3Manager {
let newStatus = FucetWalletState.UNKNOWN;
if(this.walletState) {
newStatus = FucetWalletState.NORMAL;
if(this.walletState.balance <= faucetConfig.spareFundsAmount)
if(!this.walletState.ready)
newStatus = FucetWalletState.OFFLINE;
else if(this.walletState.balance <= faucetConfig.spareFundsAmount)
newStatus = FucetWalletState.NOFUNDS;
else if(this.walletState.balance <= faucetConfig.lowFundsBalance)
newStatus = FucetWalletState.LOWFUNDS;
Expand Down Expand Up @@ -229,6 +238,16 @@ export class EthWeb3Manager {
statusMessage = strFormatPlaceholder(statusMessage);
statusLevel = FaucetStatusLevel.ERROR;
break;
case FucetWalletState.OFFLINE:
if(typeof faucetConfig.rpcConnectionError === "string")
statusMessage = faucetConfig.rpcConnectionError;
else if(faucetConfig.rpcConnectionError)
statusMessage = "The faucet could not connect to the network RPC";
else
break;
statusMessage = strFormatPlaceholder(statusMessage);
statusLevel = FaucetStatusLevel.ERROR;
break;
}
ServiceManager.GetService(FaucetStatus).setFaucetStatus("wallet", statusMessage, statusLevel);
}
Expand Down Expand Up @@ -302,7 +321,7 @@ export class EthWeb3Manager {

try {
while(Object.keys(this.pendingTxQueue).length < faucetConfig.ethMaxPending && this.claimTxQueue.length > 0) {
if(faucetConfig.ethQueueNoFunds && this.walletState.balance - BigInt(faucetConfig.spareFundsAmount) < this.claimTxQueue[0].amount) {
if(faucetConfig.ethQueueNoFunds && (!this.walletState.ready || this.walletState.balance - BigInt(faucetConfig.spareFundsAmount) < this.claimTxQueue[0].amount)) {
break; // skip processing (out of funds)
}

Expand All @@ -311,11 +330,12 @@ export class EthWeb3Manager {
}

let now = Math.floor(new Date().getTime() / 1000);
if(Object.keys(this.pendingTxQueue).length === 0 && now - this.lastWalletRefresh > 600) {
let walletRefreshTime = this.walletState.ready ? 600 : 10;
if(Object.keys(this.pendingTxQueue).length === 0 && now - this.lastWalletRefresh > walletRefreshTime) {
await this.loadWalletState();
}

if(faucetConfig.ethRefillContract)
if(faucetConfig.ethRefillContract && this.walletState.ready)
await this.tryRefillWallet();
} catch(ex) {
let stack;
Expand All @@ -336,7 +356,13 @@ export class EthWeb3Manager {
}

private async processQueueTx(claimTx: ClaimTx) {
if(this.walletState.balance - BigInt(faucetConfig.spareFundsAmount) < claimTx.amount) {
if(!this.walletState.ready) {
claimTx.failReason = "Network RPC is currently unreachable.";
claimTx.status = ClaimTxStatus.FAILED;
claimTx.emit("failed");
return;
}
if(!this.walletState.ready || this.walletState.balance - BigInt(faucetConfig.spareFundsAmount) < claimTx.amount) {
claimTx.failReason = "Faucet wallet is out of funds.";
claimTx.status = ClaimTxStatus.FAILED;
claimTx.emit("failed");
Expand Down

0 comments on commit 4b2f3fa

Please sign in to comment.