Skip to content

Commit c6d3e91

Browse files
author
Cashmaney
authored
Merge pull request #961 from scrtlabs/feature/node_faucet
Feature/node faucet
2 parents efa4f3c + a660421 commit c6d3e91

File tree

5 files changed

+157
-102
lines changed

5 files changed

+157
-102
lines changed

deployment/docker/devimage/bootstrap_init_no_stop.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ perl -i -pe 's/enable-unsafe-cors = false/enable-unsafe-cors = true/' .secretd/c
6565
lcp --proxyUrl http://localhost:1316 --port 1317 --proxyPartial '' &
6666

6767
# Setup faucet
68-
gunicorn --bind 0.0.0.0:5000 svc &
68+
setsid node faucet_server.js &
6969

7070
# Setup secretcli
7171
cp $(which secretd) $(dirname $(which secretd))/secretcli
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
const http = require("http");
2+
const querystring = require("querystring");
3+
const exec = require("child_process").exec;
4+
5+
const FAUCET_WALLET_NAME = process.env.FAUCET_WALLET_NAME || "a";
6+
const FAUCET_AMOUNT = process.env.FAUCET_AMOUNT || "1000000000";
7+
const DENOM = process.env.DENOM || "uscrt";
8+
9+
let faucet_address;
10+
11+
/**
12+
* Execute a shell command and return it as a Promise.
13+
* @param cmd {string}
14+
* @return {Promise<string>}
15+
*/
16+
function execShellCommand(cmd) {
17+
return new Promise((resolve, reject) => {
18+
exec(cmd, (error, stdout, stderr) => {
19+
if (error) {
20+
console.error("error in execShellCommand", error);
21+
reject(error);
22+
} else if (stderr) {
23+
console.error("stderr in execShellCommand", stderr);
24+
reject(stderr);
25+
} else {
26+
resolve(JSON.parse(stdout));
27+
}
28+
});
29+
});
30+
}
31+
32+
/**
33+
* Command to send coins.
34+
* @param src_key_name source account key name, default 'a'
35+
* @param src_address source account's secret address
36+
* @param dest_address destination address
37+
* @param amount amount to send
38+
* @returns result of executing the command.
39+
*/
40+
async function send_command(src_key_name, src_address, dest_address, amount) {
41+
const send_message = `secretd tx bank send ${src_address} ${dest_address} ${amount}${DENOM} --from ${src_key_name} --gas-prices 0.25uscrt -y`;
42+
console.log(`send_message: \n ${send_message}`);
43+
44+
const result = await execShellCommand(send_message);
45+
console.log(`Sent tokens with txhash: ${result.txhash}`);
46+
return result.txhash;
47+
}
48+
49+
/**
50+
* Returns the address for the requested account key.
51+
* @param key_name faucet account key to use, default 'a'
52+
* @returns address
53+
*/
54+
async function get_address(key_name) {
55+
// Already looked up, won't change while running
56+
if (faucet_address !== undefined) {
57+
return faucet_address;
58+
}
59+
60+
const list_keys = "secretd keys list";
61+
const result = await execShellCommand(list_keys);
62+
63+
for (index in result) {
64+
const key = result[index];
65+
if (key["name"] == key_name) {
66+
console.log(`Found key with address: ${key["address"]}`);
67+
faucet_address = key["address"];
68+
break;
69+
}
70+
}
71+
72+
return faucet_address;
73+
}
74+
75+
// Start the http server
76+
const server = http.createServer();
77+
server.on("request", async (req, res) => {
78+
try {
79+
// for root or status, return the configured faucet address and amount sent
80+
if (req.url === "/" || req.url === "/status") {
81+
const faucet_address = await get_address(FAUCET_WALLET_NAME);
82+
83+
if (faucet_address === undefined) {
84+
console.error(
85+
`No key account with required name: ${FAUCET_WALLET_NAME}`
86+
);
87+
88+
res.writeHead(500, { "Content-Type": "application/json" });
89+
res.write(
90+
JSON.stringify({
91+
error: `No key account with required name: ${FAUCET_WALLET_NAME}`,
92+
})
93+
);
94+
res.end();
95+
return;
96+
} else {
97+
res.writeHead(200, { "Content-Type": "application/json" });
98+
res.write(
99+
JSON.stringify({
100+
faucet_address: faucet_address,
101+
amount: FAUCET_AMOUNT,
102+
})
103+
);
104+
res.end();
105+
}
106+
} else if (req.url.startsWith("/faucet")) {
107+
// ensure address is present, not necessarily valid checksum
108+
if (!req.url.startsWith("/faucet?address=")) {
109+
res.writeHead(400, { "Content-Type": "application/json" });
110+
res.write(JSON.stringify({ error: "address is required" }));
111+
res.end();
112+
return;
113+
}
114+
115+
const address = querystring.parse(req.url)["/faucet?address"];
116+
const faucet_address = await get_address(FAUCET_WALLET_NAME);
117+
118+
if (faucet_address === undefined) {
119+
console.error(
120+
`No key account with required name: ${FAUCET_WALLET_NAME}`
121+
);
122+
123+
res.writeHead(500, { "Content-Type": "application/json" });
124+
res.write(
125+
JSON.stringify({
126+
error: `No key account with required name: ${FAUCET_WALLET_NAME}`,
127+
})
128+
);
129+
res.end();
130+
return;
131+
} else {
132+
const txhash = await send_command(
133+
FAUCET_WALLET_NAME,
134+
faucet_address,
135+
address,
136+
FAUCET_AMOUNT
137+
);
138+
139+
res.writeHead(200, { "Content-Type": "application/json" });
140+
res.write(JSON.stringify({ txhash: txhash }));
141+
res.end();
142+
}
143+
} else {
144+
res.end("Invalid Request!");
145+
}
146+
} catch (err) {
147+
res.writeHead(500, { "Content-Type": "application/json" });
148+
res.write(JSON.stringify({ error: `${err.message}` }));
149+
res.end();
150+
}
151+
});
152+
153+
server.listen(5000);
154+
155+
console.log("Secret Faucet is running on port 5000 ...");

deployment/docker/devimage/faucet/requirements.txt

Lines changed: 0 additions & 4 deletions
This file was deleted.

deployment/docker/devimage/faucet/svc.py

Lines changed: 0 additions & 86 deletions
This file was deleted.
Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,7 @@
11
# Final image
22
FROM build-release
33

4-
RUN apt-get update && \
5-
apt-get install -y --no-install-recommends \
6-
#### Base utilities ####
7-
python3.8 \
8-
python3-pip
9-
10-
COPY deployment/docker/devimage/faucet/requirements.txt .
11-
12-
RUN pip install -r requirements.txt
13-
144
COPY deployment/docker/devimage/bootstrap_init_no_stop.sh bootstrap_init.sh
15-
COPY deployment/docker/devimage/faucet/svc.py .
5+
COPY deployment/docker/devimage/faucet/faucet_server.js .
166

177
ENTRYPOINT ["./bootstrap_init.sh"]

0 commit comments

Comments
 (0)