eth-rb 0.1.6 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/eth.rb +74 -6
- metadata +6 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7cad4ab46c86f240e38bf48d77832f0c067582133d1bbdb4e1690cd5b52afa77
|
|
4
|
+
data.tar.gz: 54bafb01cd2fa6c8cf5dbbd50ec9e1831de9b1aee9dbc2a1b8c6a96eb59a113c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8c851f58edc21271766a2e9da90a14a47b90cde4ef48bcd9d99f0a178e7c4c5b9b74f3776e8c6660d5b477d38690c288ccff584c3839e27549ab6fc51c72dcde
|
|
7
|
+
data.tar.gz: ccc8efb8c5b74378088eca855d613320049a5abdaa7efe52f20847fb784928a653399a5b0f0ffce2f000afb884e0acb74709255b2e35730dfcd8892a4cf5a4ff
|
data/lib/eth.rb
CHANGED
|
@@ -6,10 +6,13 @@
|
|
|
6
6
|
# Usage:
|
|
7
7
|
# ./eth.rb — show latest block number
|
|
8
8
|
# ./eth.rb <address> — show ETH balance of <address>
|
|
9
|
+
# ./eth.rb <private_key> — derive public key + address, show its balance
|
|
9
10
|
# ./eth.rb --price — show current ETH/USD price
|
|
11
|
+
# ./eth.rb --genkey or -g — generate a new private key + address
|
|
12
|
+
# ./eth.rb --pubkey <key> — derive public key + address from <key>
|
|
10
13
|
# ./eth.rb --version or -v — show version
|
|
11
|
-
# ./eth.rb send <key> <to> <amount>
|
|
12
|
-
# ./eth.rb send <key> <to> \$<amount>
|
|
14
|
+
# ./eth.rb --send <key> <to> <amount> — send ETH (amount in ETH)
|
|
15
|
+
# ./eth.rb --send <key> <to> \$<amount> — send ETH (amount in USD, converted at current price)
|
|
13
16
|
# ./eth.rb --help — show this usage info
|
|
14
17
|
|
|
15
18
|
require "net/http"
|
|
@@ -22,7 +25,7 @@ require "digest/keccak"
|
|
|
22
25
|
ALCHEMY_URL = "https://eth-mainnet.g.alchemy.com/v2/alch_PhpVkmsabZhYV69otj1rF"
|
|
23
26
|
COINGECKO_URL = "https://api.coingecko.com/api/v3/simple/price?ids=ethereum&vs_currencies=usd"
|
|
24
27
|
CHAIN_ID = 1 # Ethereum mainnet
|
|
25
|
-
VERSION = "0.1.
|
|
28
|
+
VERSION = "0.1.8"
|
|
26
29
|
|
|
27
30
|
# ── JSON-RPC ────────────────────────────────────────────────────────────────
|
|
28
31
|
|
|
@@ -144,12 +147,52 @@ def private_key_to_address(priv_hex)
|
|
|
144
147
|
hash.byteslice(12, 20)
|
|
145
148
|
end
|
|
146
149
|
|
|
150
|
+
# Derive the uncompressed public key (04 || x || y, 64 bytes) from a
|
|
151
|
+
# private key hex string (with or without 0x)
|
|
152
|
+
def private_key_to_pubkey(priv_hex)
|
|
153
|
+
priv_int = normalize_hex(priv_hex).to_i(16)
|
|
154
|
+
pub_point = GROUP.generator.multiply_by_scalar(priv_int)
|
|
155
|
+
|
|
156
|
+
pad32 = ->(b) { b.bytesize >= 32 ? b : "\x00" * (32 - b.bytesize) + b }
|
|
157
|
+
"\x04" + pad32.call(to_big_endian(pub_point.x)) + pad32.call(to_big_endian(pub_point.y))
|
|
158
|
+
end
|
|
159
|
+
|
|
147
160
|
def normalize_hex(str)
|
|
148
161
|
hex = str.start_with?("0x") || str.start_with?("0X") ? str[2..] : str
|
|
149
162
|
hex = "0#{hex}" if hex.bytesize.odd?
|
|
150
163
|
hex
|
|
151
164
|
end
|
|
152
165
|
|
|
166
|
+
# Generate a random private key: a scalar in [1, n-1] where n is the
|
|
167
|
+
# order of the secp256k1 curve group
|
|
168
|
+
def generate_private_key
|
|
169
|
+
SecureRandom.random_number(GROUP.order - 1) + 1
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def show_new_key
|
|
173
|
+
priv = generate_private_key
|
|
174
|
+
priv_hex = "0x%064x" % priv
|
|
175
|
+
addr = "0x#{private_key_to_address(priv_hex).unpack1('H*')}"
|
|
176
|
+
puts "Private Key: #{priv_hex}"
|
|
177
|
+
puts "Address: #{addr}"
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def cmd_pubkey(args)
|
|
181
|
+
if args.empty?
|
|
182
|
+
puts "Usage: ./eth.rb --pubkey <private_key_hex>"
|
|
183
|
+
exit 1
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
priv_hex = normalize_hex(args[0])
|
|
187
|
+
priv = priv_hex.to_i(16)
|
|
188
|
+
pub_hex = "0x#{private_key_to_pubkey(args[0]).unpack1('H*')}"
|
|
189
|
+
addr = "0x#{private_key_to_address(args[0]).unpack1('H*')}"
|
|
190
|
+
|
|
191
|
+
puts "Private Key: 0x%064x" % priv
|
|
192
|
+
puts "Public Key: #{pub_hex}"
|
|
193
|
+
puts "Address: #{addr}"
|
|
194
|
+
end
|
|
195
|
+
|
|
153
196
|
# ── Transaction signing ─────────────────────────────────────────────────────
|
|
154
197
|
|
|
155
198
|
def build_and_sign_tx(private_key_hex, to_address, amount_wei)
|
|
@@ -231,7 +274,7 @@ end
|
|
|
231
274
|
def cmd_send(args)
|
|
232
275
|
# p args
|
|
233
276
|
if args.length < 3
|
|
234
|
-
puts "Usage: ./eth.rb send <private_key_hex> <to_address> <amount>"
|
|
277
|
+
puts "Usage: ./eth.rb --send <private_key_hex> <to_address> <amount>"
|
|
235
278
|
puts " amount: number (ETH) or $number (USD, converted to ETH at current price)"
|
|
236
279
|
exit 1
|
|
237
280
|
end
|
|
@@ -272,6 +315,22 @@ def show_block_number
|
|
|
272
315
|
puts "Hex: #{hex_block}"
|
|
273
316
|
end
|
|
274
317
|
|
|
318
|
+
# True if str is a 64-hex-digit private key (0x prefix optional)
|
|
319
|
+
def private_key?(str)
|
|
320
|
+
normalize_hex(str).match?(/\A[0-9a-fA-F]{64}\z/)
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
# Derive the public key and address from a private key, then show the balance
|
|
324
|
+
def show_balance_from_key(priv_hex)
|
|
325
|
+
pub_hex = "0x#{private_key_to_pubkey(priv_hex).unpack1('H*')}"
|
|
326
|
+
addr = "0x#{private_key_to_address(priv_hex).unpack1('H*')}"
|
|
327
|
+
|
|
328
|
+
puts "Public Key: #{pub_hex}"
|
|
329
|
+
puts "Address: #{addr}"
|
|
330
|
+
puts ""
|
|
331
|
+
show_balance(addr)
|
|
332
|
+
end
|
|
333
|
+
|
|
275
334
|
def show_balance(address)
|
|
276
335
|
hex_wei = rpc_call("eth_getBalance", [address, "latest"])
|
|
277
336
|
wei = hex_wei.to_i(16)
|
|
@@ -323,6 +382,7 @@ def show_version
|
|
|
323
382
|
end
|
|
324
383
|
|
|
325
384
|
def print_usage
|
|
385
|
+
puts "eth.rb v#{VERSION}"
|
|
326
386
|
puts File.read(__FILE__)[/^#\sUsage:.*?(?=\n\n)/m]
|
|
327
387
|
end
|
|
328
388
|
|
|
@@ -333,14 +393,22 @@ def run_cli(args)
|
|
|
333
393
|
show_block_number
|
|
334
394
|
elsif args[0] == "--price"
|
|
335
395
|
show_price
|
|
396
|
+
elsif args[0] == "--genkey" || args[0] == "-g"
|
|
397
|
+
show_new_key
|
|
398
|
+
elsif args[0] == "--pubkey" || args[0] == "pubkey"
|
|
399
|
+
cmd_pubkey(args[1..])
|
|
336
400
|
elsif args[0] == "--version" || args[0] == "-v"
|
|
337
401
|
show_version
|
|
338
402
|
elsif args[0] == "--help" || args[0] == "-h"
|
|
339
403
|
print_usage
|
|
340
|
-
elsif args[0] == "send"
|
|
404
|
+
elsif args[0] == "--send" || args[0] == "send"
|
|
341
405
|
cmd_send(args[1..])
|
|
342
406
|
else
|
|
343
|
-
|
|
407
|
+
if private_key?(args[0])
|
|
408
|
+
show_balance_from_key(args[0])
|
|
409
|
+
else
|
|
410
|
+
show_balance(args[0])
|
|
411
|
+
end
|
|
344
412
|
end
|
|
345
413
|
end
|
|
346
414
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: eth-rb
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.8
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Khalid Shaikh
|
|
@@ -37,8 +37,9 @@ dependencies:
|
|
|
37
37
|
- - "~>"
|
|
38
38
|
- !ruby/object:Gem::Version
|
|
39
39
|
version: '1.3'
|
|
40
|
-
description: A lightweight CLI tool for
|
|
41
|
-
ETH/USD prices, and sending transactions via
|
|
40
|
+
description: A lightweight CLI tool for generating Ethereum private keys and addresses,
|
|
41
|
+
querying balances, block numbers, and ETH/USD prices, and sending transactions via
|
|
42
|
+
Alchemy JSON-RPC.
|
|
42
43
|
email:
|
|
43
44
|
- k@iai.lol
|
|
44
45
|
executables:
|
|
@@ -68,5 +69,6 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
68
69
|
requirements: []
|
|
69
70
|
rubygems_version: 4.0.17
|
|
70
71
|
specification_version: 4
|
|
71
|
-
summary: Ethereum
|
|
72
|
+
summary: 'Ethereum CLI: balances, prices, key generation, and transactions via Alchemy
|
|
73
|
+
JSON-RPC'
|
|
72
74
|
test_files: []
|