Skip to content

Commit

Permalink
Initial version
Browse files Browse the repository at this point in the history
  • Loading branch information
x100111010 committed Oct 14, 2024
0 parents commit 56b6f77
Show file tree
Hide file tree
Showing 109 changed files with 26,502 additions and 0 deletions.
25 changes: 25 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: Lint
on: [push, pull_request]

permissions:
checks: read
contents: read

jobs:
run-linters:
name: Run linters
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v4

- name: Set up Node.js
uses: actions/setup-node@v4

- name: Install Node.js dependencies
run: |
npm install
- name: Run Prettier to check formatting
run: |
npx prettier --config ./config/.prettierrc.json --check "**/*.js"
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
node_modules
package-lock.json
*.local.conf
bin/*
.seeds
test.js
116 changes: 116 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# Spectre Faucet

[![Lint Check](https://github.com/spectre-project/node-spectre-faucet/actions/workflows/lint.yml/badge.svg)](https://github.com/spectre-project/node-spectre-faucet/actions/workflows/lint.yml)

Miniature Spectre faucet website based on [Spectre Wallet](https://github.com/spectre-project/node-spectre-wallet)
framework. The faucet can be run on single or multiple networks.
In case you run it on multiple networks it will use the same
seed phrase for all together.

## Install Rust (if necessary)

```
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
rustc --version
```

## Setup rusty-spectre

```
git clone https://github.com/spectre-project/rusty-spectre
cd rusty-spectre
cargo build --release --bin spectred
cd target/release
```

## Run Spectred

```
spectred --utxoindex
```

## Configuration

You need to have a hCaptcha subscription. You can create a free one
at: https://www.hcaptcha.com/

Once you have created it copy the `sitekey` and `secret` into
`config/spectre-faucet.conf` file.

Lastly you need to create a file `.seeds` with the 12-word seed
phrase of a wallet to disable address derivation. This is optional
but recommended if you run the faucet on a secure and privately
owned system.

It is highly recommended to run the faucet behind a reverse proxy
like NGINX and add the following header into your proxy
configuration:

```
proxy_set_header X-Real-IP $remote_addr;
```

It will ensure that single IP addresses cannot empty the faucet and
limit their amount in the 24 hour timeframe.

## Running

```
git clone https://github.com/spectre-project/node-spectre-faucet
cd node-spectre-faucet
npm install
node spectre-faucet.js --mainnet --host 0.0.0.0 --limit 10 --rpc 127.0.0.1:18110
```

### Global Options:

- `--version`: Displays the current version of the Spectre Faucet.
- `--help`: Displays the help information for the command.

- `--log <level>`: Sets the log level for the application. Available log levels are:

- `error`
- `warn`
- `info`
- `verbose`
- `debug`

- `--verbose`: Logs additional wallet activity for verbose output.
- `--debug`: Logs detailed wallet activity for debugging purposes.

### Network Options:

- `--mainnet`: Uses the **mainnet** network for transactions.
- `--testnet`: Uses the **testnet** network for transactions.
- `--devnet`: Uses the **devnet** network for transactions.
- `--simnet`: Uses the **simnet** network for transactions.

### Host and Port Options:

- `--host <host>`: Sets the HTTP host for the faucet (default: `localhost`).
- `--port <port>`: Sets the HTTP port for the faucet (default: `3000`). You can specify a custom port if necessary.

### SPR/Day Limit Options:

- `--limit <limit>`: Sets the SPR/day limit per IP address. This limits how much SPR can be requested by a single IP within a 24-hour period.

- `--no-limit`: Disables the SPR/day limit entirely, allowing unlimited faucet requests.

### RPC Options:

- `--rpc <address>`: Specifies a custom RPC address in the format `host:port`. This option is useful when you want to use a different RPC server.

## Example Usage:

To run the faucet with specific options:

```bash
node spectre-faucet.js --mainnet --host 0.0.0.0 --limit 10 --rpc 127.0.0.1:18110
```

This will:

- Run the faucet on the **mainnet**.
- Bind the HTTP service to `0.0.0.0` (all available network interfaces).
- Set a limit of `10 SPR` per IP address per day.
- Use a custom RPC server at `127.0.0.1:18110`.
8 changes: 8 additions & 0 deletions config/.prettierrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"printWidth": 80,
"semi": true,
"trailingComma": "all",
"singleQuote": false,
"bracketSpacing": true,
"arrowParens": "always"
}
6 changes: 6 additions & 0 deletions config/spectre-faucet.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"captcha": {
"secret": "xxxx",
"key": "yyyy"
}
}
1 change: 1 addition & 0 deletions docs/.docs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.docs
170 changes: 170 additions & 0 deletions http/faucet-app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
import "/style/style.js";
import {
dpc,
camelCase,
html,
UID,
FlowApp,
FlowFormat,
} from "/flow/flow-ux/flow-ux.js";
import { buildhCaptcha } from "./faucet-form.js";
export * from "./faucet-form.js";
export * from "./faucet-info.js";
export * from "./faucet-balance.js";
export * from "./faucet-transactions.js";
export * from "./spectre-transaction.js";

class SpectreFaucetApp extends FlowApp {
static get properties() {
return {
network: { type: String },
networks: { type: Array },
addresses: { type: Object },
available: { type: Object },
limits: { type: Object },
captchaKey: { type: String },
};
}
constructor() {
super();

this.networks = ["spectre", "spectretest", "spectredev", "spectresim"];
this.network = "spectretest";
this.addresses = {};
this.available = {};
this.limits = {};
this.opt = {};

this.aliases = {
spectre: "MAINNET",
spectretest: "TESTNET",
spectredev: "DEVNET",
spectresim: "SIMNET",
};

this.initLog();
dpc(async () => this.init());
this.registerListener("popstate", (e) => {
let { menu = "home", args = [] } = e.state || {};
console.log(
`popstate: ${document.location}, state: ${JSON.stringify(e.state)}`,
);
this.setMenu(menu, args, true);
});
}

async init() {
await this.initSocketRPC({
timeout: 90,
args: {
transports: ["websocket"],
},
});
await this.initUI();
dpc(() => this.setLoading(false));
}

async initUI() {
this.bodyEl = document.body;
}

onlineCallback() {
const { rpc } = flow.app;
rpc.request("get-config", (err, config) => {
//console.log("config: err, config", err, config)
let { captchaKey = "" } = config || {};
this.captchaKey = captchaKey;
dpc(() => {
buildhCaptcha();
}, 500);
});
this.networkUpdates = rpc.subscribe(`networks`);
(async () => {
for await (const msg of this.networkUpdates) {
const { networks } = msg.data;
this.networks = networks;
if (!this.networks.includes(this.network))
this.network = this.networks[0];
console.log("available networks:", networks);
this.requestUpdate();
}
})().then();

this.addressUpdates = rpc.subscribe(`addresses`);
(async () => {
for await (const msg of this.addressUpdates) {
const { addresses } = msg.data;
this.addresses = addresses;
this.requestUpdate();
// this.networks = networks;
// console.log("available networks:",networks);
}
})().then();

this.limitUpdates = rpc.subscribe(`limit`);
(async () => {
for await (const msg of this.limitUpdates) {
const { network, limit, available } = msg.data;
console.log("limits", msg.data);
this.limits[network] = limit;
this.available[network] = available;
if (this.network == network) this.requestUpdate();
}
})().then();
}

offlineCallback() {
this.networkUpdates.stop();
this.addressUpdates.stop();
this.limitUpdates.stop();
}

render() {
let network = this.network;
let address = this.addresses?.[this.network] || "";
let limit = this.limits?.[this.network] || "";
let available = this.available?.[this.network] || "";

return html`
<flow-app-layout no-drawer no-header>
<div slot="main" class="main-area flex sbar" col>
<div for="home" row class="content">
<div class="divider"></div>
<div col class="balance-wrapper">
<faucet-balance network="${network}"></faucet-balance>
<faucet-transactions network="${network}"></faucet-transactions>
</div>
<div class="divider"></div>
<div col class="form-wrapper">
<faucet-info
limit="${limit}"
available="${available}"
address="${address}"
></faucet-info>
<faucet-form
network="${network}"
.networks="${this.networks}"
address="${address}"
@network-change="${this.onNetworkChange}"
>
<div
slot="captcha"
class="${this.captchaKey ? "h-captcha" : ""}"
data-sitekey="${this.captchaKey}"
></div>
</faucet-form>
</div>
<div class="divider"></div>
</div>
</div>
</flow-app-layout>
`;
}

onNetworkChange(e) {
console.log("on-network-change", e.detail);
this.network = e.detail.network;
}
}

SpectreFaucetApp.define("spectre-faucet-app");
Loading

0 comments on commit 56b6f77

Please sign in to comment.