-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfaucet.js
210 lines (169 loc) · 6.79 KB
/
faucet.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
import express from 'express';
import * as path from 'path'
import { Wallet } from '@ethersproject/wallet'
import { pathToString } from '@cosmjs/crypto';
import { ethers } from 'ethers'
import { bech32 } from 'bech32';
import { DirectSecp256k1HdWallet } from "@cosmjs/proto-signing";
import { SigningStargateClient } from "@cosmjs/stargate";
import conf from './config.js'
import { FrequencyChecker } from './checker.js';
// load config
console.log("loaded config: ", conf)
const app = express()
app.set("view engine", "ejs");
const checker = new FrequencyChecker(conf)
app.get('/', (req, res) => {
res.render('index', conf);
})
app.get('/config.json', async (req, res) => {
const sample = {}
for(let i =0; i < conf.blockchains.length; i++) {
const chainConf = conf.blockchains[i]
const wallet = await DirectSecp256k1HdWallet.fromMnemonic(chainConf.sender.mnemonic, chainConf.sender.option);
const [firstAccount] = await wallet.getAccounts();
sample[chainConf.name] = firstAccount.address
const wallet2 = Wallet.fromMnemonic(chainConf.sender.mnemonic, pathToString(chainConf.sender.option.hdPaths[0]));
console.log('address:', firstAccount.address, wallet2.address)
}
const project = conf.project
project.sample = sample
project.blockchains = conf.blockchains.map(x => x.name)
project.txAmount = conf.blockchains[0].tx?.amount[0]?.amount / 1000000
res.send(project);
})
app.get('/balance/:chain', async (req, res) => {
const { chain }= req.params
let balance = {}
try{
const chainConf = conf.blockchains.find(x => x.name === chain)
if(chainConf) {
if(chainConf.type === 'Ethermint') {
const ethProvider = new ethers.providers.JsonRpcProvider(chainConf.endpoint.evm_endpoint);
const wallet = Wallet.fromMnemonic(chainConf.sender.mnemonic, pathToString(chainConf.sender.option.hdPaths[0])).connect(ethProvider);
await wallet.getBalance().then(ethBlance => {
balance = {
denom:chainConf.tx.amount.denom,
amount:ethBlance.toString()
}
}).catch(e => console.error(e))
}else{
const rpcEndpoint = chainConf.endpoint.rpc_endpoint;
const wallet = await DirectSecp256k1HdWallet.fromMnemonic(chainConf.sender.mnemonic, chainConf.sender.option);
const client = await SigningStargateClient.connectWithSigner(rpcEndpoint, wallet);
const [firstAccount] = await wallet.getAccounts();
await client.getBalance(firstAccount.address, chainConf.tx.amount[0].denom).then(x => {
balance = x
}).catch(e => console.error(e));
}
}
} catch(err) {
console.log(err)
}
res.send(balance);
})
app.get('/send/:chain/:address', async (req, res) => {
const {chain, address} = req.params;
const ip = req.headers['cf-connecting-ip'] || req.headers['x-real-ip'] || req.headers['X-Forwarded-For'] || req.ip;
console.log('request tokens to ', address, ip);
if (!chain || !address) {
return res.send({ result: 'chain and address are required' });
}
try {
const chainConf = conf.blockchains.find(x => x.name === chain);
if (!chainConf || !(address.startsWith(chainConf.sender.option.prefix) || address.startsWith('0x'))) {
return res.send({ result: `Address [${address}] is not supported.` });
}
const addressCheck = checker.checkAddress(address, chain);
const ipCheck = checker.checkIp(`${chain}${ip}`, chain);
const [addressResult, ipResult] = await Promise.all([addressCheck, ipCheck]);
console.log('Checking address:', addressResult);
console.log('Checking IP:', ipResult);
if (addressResult && ipResult) {
await checker.update(`${chain}${ip}`); // get ::1 on localhost
console.log('send tokens to ', address);
try {
const ret = await sendTx(address, chain);
await checker.update(address);
res.send({ result: ret });
} catch (err) {
res.send({ result: `err: ${err}` });
}
} else {
res.send({ result: "You requested too often" });
}
} catch (err) {
console.error(err);
res.send({ result: 'Failed, Please contact admin.' });
}
})
app.listen(conf.port, () => {
console.log(`Faucet app listening on port ${conf.port}`)
})
async function sendCosmosTx(recipient, chain) {
// const mnemonic = "surround miss nominee dream gap cross assault thank captain prosper drop duty group candy wealth weather scale put";
const chainConf = conf.blockchains.find(x => x.name === chain)
if(chainConf) {
const wallet = await DirectSecp256k1HdWallet.fromMnemonic(chainConf.sender.mnemonic, chainConf.sender.option);
const [firstAccount] = await wallet.getAccounts();
// console.log("sender", firstAccount);
const rpcEndpoint = chainConf.endpoint.rpc_endpoint;
const client = await SigningStargateClient.connectWithSigner(rpcEndpoint, wallet);
// const recipient = "cosmos1xv9tklw7d82sezh9haa573wufgy59vmwe6xxe5";
const amount = chainConf.tx.amount;
const fee = chainConf.tx.fee;
console.log("recipient", recipient, amount, fee);
return client.sendTokens(firstAccount.address, recipient, amount, fee);
}
throw new Error(`Blockchain Config [${chain}] not found`)
}
async function sendEvmosTx(recipient, chain) {
try{
const chainConf = conf.blockchains.find(x => x.name === chain)
const ethProvider = new ethers.providers.JsonRpcProvider(chainConf.endpoint.evm_endpoint);
const wallet = Wallet.fromMnemonic(chainConf.sender.mnemonic).connect(ethProvider);
let evmAddress = recipient;
if(recipient && !recipient.startsWith('0x')) {
let decode = bech32.decode(recipient);
let array = bech32.fromWords(decode.words);
evmAddress = "0x" + toHexString(array);
}
let result = await wallet.sendTransaction(
{
from:wallet.address,
to:evmAddress,
value:chainConf.tx.amount.amount
}
);
let repTx = {
"code":0,
"nonce":result["nonce"],
"value":result["value"].toString(),
"hash":result["hash"]
};
console.log("xxl result : ",repTx);
return repTx;
}catch(e){
console.log("xxl e ",e);
return e;
}
}
function toHexString(bytes) {
return bytes.reduce(
(str, byte) => str + byte.toString(16).padStart(2, '0'),
'');
}
async function sendTx(recipient, chain) {
const chainConf = conf.blockchains.find(x => x.name === chain)
if(chainConf.type === 'Ethermint') {
return sendEvmosTx(recipient, chain)
}
return sendCosmosTx(recipient, chain)
}
// write a function to send evmos transaction
async function sendEvmosTx2(recipient, chain) {
// use evmosjs to send transaction
const chainConf = conf.blockchains.find(x => x.name === chain)
// create a wallet instance
const wallet = Wallet.fromMnemonic(chainConf.sender.mnemonic).connect(chainConf.endpoint.evm_endpoint);
}