Skip to content

Commit

Permalink
feat: add redirect and autoClose features (#73)
Browse files Browse the repository at this point in the history
  • Loading branch information
luizstacio authored Aug 7, 2024
1 parent 298d9ac commit 03ec0dd
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 21 deletions.
42 changes: 30 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,25 +1,27 @@
Faucet App
===
# Faucet App

[![build](https://github.com/FuelLabs/faucet/actions/workflows/ci.yml/badge.svg)](https://github.com/FuelLabs/faucet/actions/workflows/ci.yml)
[![discord](https://img.shields.io/badge/chat%20on-discord-orange?&logo=discord&logoColor=ffffff&color=7389D8&labelColor=6A7EC2)](https://discord.gg/xfpK4Pe)

A simple faucet app for dispensing tokens on a fuel network. It uses Google captcha for spam resistance
without requiring any social media based identification.

## Configuration

The faucet makes use of environment variables for configuration.

| Environment Variable | Description |
|----------------------|-------------------------------------------------------------------------|
| RUST_LOG | EnvFilter configuration for adjusting logging granularity. |
| HUMAN_LOGGING | If false, logs will be output as machine readable JSON. |
| CAPTCHA_SECRET | The secret key used for enabling Google captcha authentication. |
| CAPTCHA_KEY | The website key used for enabling Google captcha authentication. |
| WALLET_SECRET_KEY | A hex formatted string of the wallet private key that owns some tokens. |
| FUEL_NODE_URL | The GraphQL endpoint for connecting to fuel-core. |
| Environment Variable | Description |
| -------------------- | ----------------------------------------------------------------------------------------------- |
| RUST_LOG | EnvFilter configuration for adjusting logging granularity. |
| HUMAN_LOGGING | If false, logs will be output as machine readable JSON. |
| CAPTCHA_SECRET | The secret key used for enabling Google captcha authentication. |
| CAPTCHA_KEY | The website key used for enabling Google captcha authentication. |
| WALLET_SECRET_KEY | A hex formatted string of the wallet private key that owns some tokens. |
| FUEL_NODE_URL | The GraphQL endpoint for connecting to fuel-core. |
| PUBLIC_FUEL_NODE_URL | The public GraphQL endpoint for connecting to fuel-core. Ex.: https://node.fuel.network/graphql |
| SERVICE_PORT | The port the service will listen for http connections on. |
| DISPENSE_AMOUNT | Dispense amount on each faucet |
| SERVICE_PORT | The port the service will listen for http connections on. |
| DISPENSE_AMOUNT | Dispense amount on each faucet |
| MIN_GAS_PRICE | The minimum gas price to use in each transfer |

## Build and Run

Expand All @@ -28,3 +30,19 @@ To run locally, assuming environment variables have already been set:
```sh
cargo run
```

## Query Params

When integrating the faucet you can use the following query params to enhance the user experience:

| Name | Type | Description |
| ----------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| address | Address | Auto-fill the address field using the provided value |
| redirectUrl | String | If provided with a valid url, once the faucet is complete, the user will be redirected back to the url with tx_id as a query param |
| autoClose | String | If provided empty or true will close automatically the window after the transaction is finished |

### Example - Redirect
- `http://localhost:3000/?address=fuel134ddh9pfsspar086htdldwxq2jsr3yvqtj5w456kkrz3s653la5q347kmc&redirectUrl=http://localhost:4000`

### Example - Auto Close
- `http://localhost:3000/?address=fuel134ddh9pfsspar086htdldwxq2jsr3yvqtj5w456kkrz3s653la5q347kmc&autoClose`
65 changes: 57 additions & 8 deletions static/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,11 @@
color: #949494;
}

.provider-url a {
color: #949494;
text-decoration: underline;
}

.agreements {
text-align: left;
margin-top: 25px;
Expand All @@ -146,7 +151,7 @@
font-size: 14px;
}

.queued {
.queued, .redirect-container {
display: flex;
flex-direction: column;
align-items: center;
Expand Down Expand Up @@ -183,6 +188,10 @@
.hidden {
display: none;
}

.footer {
z-index: 9;
}
</style>

<body>
Expand Down Expand Up @@ -241,15 +250,27 @@
</form>
<div id="response">
<h2 class="response-title">Test Ether sent to the wallet</h2>
<div id="redirect-container" class="redirect-container hidden">
<div class="loader"></div>
<div id="redirect-text"></div>
</div>
<a href="#" id="explorer-link" class="button">See on Fuel Explorer</a>
</div>
</div>
<div class="provider-url">Node url: {{ public_node_url }}</div>
<div class="footer">
<div class="provider-url">Node url: {{ public_node_url }}</div>
<div class="provider-url"><a target="_blank" href="https://github.com/FuelLabs/faucet">GitHub</a></div>
</div>
<script>
const faucetApp = (function () {
let providerUrl = "{{ public_node_url }}";
let blockExplorer = "https://app.fuel.network";
let query = params = new URLSearchParams(document.location.search);
let address = query.get('address');
let redirectUrl = query.get('redirectUrl');
let autoClose = query.get('autoClose');
let buttonSubmit = form.querySelector("input[type=submit]");
let shouldAutoClose = (autoClose === "" || autoClose === "true");

if (address) {
let $address = document.getElementById('address');
Expand All @@ -266,7 +287,7 @@ <h2 class="response-title">Test Ether sent to the wallet</h2>
}

agreements.onchange = function() {
form.querySelector("input[type=submit]").disabled = !hasAgreed();
buttonSubmit.disabled = !hasAgreed();
};

function hasCaptcha() {
Expand All @@ -278,15 +299,15 @@ <h2 class="response-title">Test Ether sent to the wallet</h2>
document.getElementsByClassName("captcha-container")[0].classList.add("hidden");
}
document.getElementsByClassName("queued")[0].classList.remove("hidden");
form.querySelector("input[type=submit]").disabled = true;
buttonSubmit.disabled = true;
}

function hideWaiting() {
if (hasCaptcha()) {
document.getElementsByClassName("captcha-container")[0].classList.remove("hidden");
}
document.getElementsByClassName("queued")[0].classList.add("hidden");
form.querySelector("input[type=submit]").disabled = !hasAgreed();
buttonSubmit.disabled = !hasAgreed();
}

function give_me_coins(form) {
Expand Down Expand Up @@ -316,11 +337,39 @@ <h2 class="response-title">Test Ether sent to the wallet</h2>
function handle_response(address) {
return function (data) {
if (!data.error) {
const tx_id = `0x${data.tx_id}`;
const link = document.getElementById(
"explorer-link"
);
document.getElementById("form").hidden = true;
document.getElementById("response").style.display = "block";
document.getElementById(
"explorer-link"
).href = `${blockExplorer}/tx/0x${data.tx_id}`;
link.href = `${blockExplorer}/tx/${tx_id}`;

if (shouldAutoClose) {
window.close();
}

if (redirectUrl) {
try {
const refUrl = new URL(decodeURIComponent(redirectUrl));
const redirectText = `Redirecting you back to ${refUrl.origin}...`;

// Add tx_id to query params
refUrl.searchParams.set('tx_id', tx_id);

link.classList.add('hidden');
const $redirectContainer = document.getElementById('redirect-container');
const $redirectText = document.getElementById('redirect-text');
$redirectContainer.classList.remove('hidden');
$redirectText.innerText = redirectText;
setTimeout(() => {
location.href = refUrl.toString();
}, 2000);
} catch (e) {
console.error(e);
// Do nothing if url is invalid
}
}
} else {
document.getElementById("response-failure").innerText = data.error;
hideWaiting();
Expand Down
1 change: 0 additions & 1 deletion tests/dispense.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ use serde_json::json;
use std::net::SocketAddr;
use std::sync::{Arc, Mutex};
use std::time::Duration;
use std::usize;

#[derive(Debug, Clone)]
struct MockClock {
Expand Down

0 comments on commit 03ec0dd

Please sign in to comment.