@@ -38,46 +38,18 @@ const val ADDRESS_KEY = "address"
38
38
val keystoreFile = File (" fauceth_keystore.json" )
39
39
val ens = ENS (getMin3RPC())
40
40
41
- val config = systemProperties() overriding
42
- EnvironmentVariables () overriding
43
- ConfigurationProperties .fromOptionalFile(File (" fauceth.properties" ))
44
-
45
-
46
41
fun main (args : Array <String >) = io.ktor.server.netty.EngineMain .main(args)
47
42
48
43
fun Application.module () {
49
- var keyPair: ECKeyPair ? = config.getOrNull(Key (" app.ethkey" , stringType))?.let {
50
- PrivateKey (it.toBigInteger(16 )).toECKeyPair()
51
- }
52
44
53
- val hcaptchaSecret = config[Key (" hcaptcha.secret" , stringType)]
54
- val hcaptchaSiteKey = config[Key (" hcaptcha.sitekey" , stringType)]
45
+ val config = FaucethConfig ()
55
46
56
- val appTitle = config.getOrElse(Key (" app.title" , stringType), " FaucETH" )
57
- val appHeroImage = config.getOrNull(Key (" app.imageURL" , stringType))
58
- val amount = BigInteger (config.getOrNull(Key (" app.amount" , stringType)) ? : " $ETH_IN_WEI " )
47
+ val rpc = HttpEthereumRPC (config.chainRPCURL)
59
48
60
- val chainRPCURL = config[Key (" chain.rpc" , stringType)]
61
- val chainExplorer = config.getOrNull(Key (" chain.explorer" , stringType))
62
- val chainId = BigInteger (config[Key (" chain.id" , stringType)])
63
-
64
- if (keyPair == null ) {
65
- if (! keystoreFile.exists()) {
66
- keyPair = createEthereumKeyPair()
67
- keystoreFile.createNewFile()
68
- keystoreFile.writeText(keyPair.privateKey.key.toString())
69
- } else {
70
- keyPair = PrivateKey (keystoreFile.readText().toBigInteger()).toECKeyPair()
71
- }
72
- }
73
-
74
- val rpc = HttpEthereumRPC (chainRPCURL)
75
-
76
- val initialNonce = rpc.getTransactionCount(keyPair.toAddress())
49
+ val initialNonce = rpc.getTransactionCount(config.keyPair.toAddress())
77
50
78
51
val atomicNonce = AtomicNonce (initialNonce!! )
79
52
80
-
81
53
routing {
82
54
static(" /static" ) {
83
55
staticRootFolder
@@ -88,7 +60,7 @@ fun Application.module() {
88
60
89
61
call.respondHtml {
90
62
head {
91
- title { + appTitle }
63
+ title { + config. appTitle }
92
64
93
65
script(src = " https://js.hcaptcha.com/1/api.js" ) {}
94
66
@@ -121,9 +93,9 @@ fun Application.module() {
121
93
id = " mainForm"
122
94
123
95
h1(classes = " center" ) {
124
- + appTitle
96
+ + config. appTitle
125
97
}
126
- appHeroImage?.let { url ->
98
+ config. appHeroImage?.let { url ->
127
99
div(classes = " center" ) {
128
100
img(src = url, classes = " image" )
129
101
}
@@ -134,7 +106,7 @@ fun Application.module() {
134
106
placeholder = " Please enter some address or ENS name"
135
107
}
136
108
div(classes = " h-captcha center" ) {
137
- attributes[" data-sitekey" ] = hcaptchaSiteKey
109
+ attributes[" data-sitekey" ] = config. hcaptchaSiteKey
138
110
}
139
111
}
140
112
div(classes = " center" ) {
@@ -155,7 +127,7 @@ fun Application.module() {
155
127
b {
156
128
+ " Address: "
157
129
}
158
- + keyPair.toAddress().toString()
130
+ + config. keyPair.toAddress().toString()
159
131
br
160
132
b {
161
133
+ " Nonce: "
@@ -168,7 +140,7 @@ fun Application.module() {
168
140
post(" /request" ) {
169
141
val receiveParameters = call.receiveParameters()
170
142
171
- val captchaResult: Boolean = verifyCaptcha(receiveParameters[" h-captcha-response" ] ? : " " , hcaptchaSecret)
143
+ val captchaResult: Boolean = verifyCaptcha(receiveParameters[" h-captcha-response" ] ? : " " , config. hcaptchaSecret)
172
144
var address = Address (receiveParameters[ADDRESS_KEY ] ? : " " )
173
145
val ensName = receiveParameters[ADDRESS_KEY ]?.let { name -> ENSName (name) }
174
146
if (ensName?.isPotentialENSDomain() == true ) {
@@ -190,10 +162,10 @@ fun Application.module() {
190
162
191
163
val tx = createEmptyTransaction().apply {
192
164
to = address
193
- value = amount
165
+ value = config. amount
194
166
nonce = atomicNonce.getAndIncrement()
195
167
gasLimit = DEFAULT_GAS_LIMIT
196
- chain = chainId
168
+ chain = config. chainId
197
169
}
198
170
199
171
val feeSuggestionResult = retry(decorrelatedJitterBackoff(base = 10L , max = 5000L )) {
@@ -207,17 +179,17 @@ fun Application.module() {
207
179
tx.maxPriorityFeePerGas = feeSuggestionResult!! .maxPriorityFeePerGas
208
180
tx.maxFeePerGas = feeSuggestionResult.maxFeePerGas
209
181
210
- val signature = tx.signViaEIP1559(keyPair)
182
+ val signature = tx.signViaEIP1559(config. keyPair)
211
183
212
184
val txHash: String = retry(decorrelatedJitterBackoff(base = 10L , max = 5000L )) {
213
185
val res = rpc.sendRawTransaction(tx.encode(signature).toHexString())
214
186
if (res?.startsWith(" 0x" ) != true ) throw IllegalStateException (" Got no hash from RPC for tx" )
215
187
res
216
188
}
217
189
218
- val amountString = BigDecimal (amount).divide(BigDecimal (ETH_IN_WEI ))
219
- val msg = if (chainExplorer != null ) {
220
- " send $amountString ETH (<a href='${chainExplorer} /tx/$txHash '>view here</a>)"
190
+ val amountString = BigDecimal (config. amount).divide(BigDecimal (ETH_IN_WEI ))
191
+ val msg = if (config. chainExplorer != null ) {
192
+ " send $amountString ETH (<a href='${config. chainExplorer} /tx/$txHash '>view here</a>)"
221
193
} else {
222
194
" send $amountString ETH (transaction: $txHash )"
223
195
}
0 commit comments