etherscan-lite 0.0.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 8268ce22467ea0136543b35e4595ff60b51e009dd7d60559f3cf858541ed1e24
4
+ data.tar.gz: 66da1fc606dd316d7640e8e45dc99fc0ea7bd81a4c61cbfa6003707ac3a4b334
5
+ SHA512:
6
+ metadata.gz: 3a2ce94118461adce95f7fd3b3992f44c89f0f479b28e145eb2cc0c0d76e4a5fa78d11a3e603b6a4f871a548c9e1349c5908d0931e3a2067ee5082faf730a88c
7
+ data.tar.gz: 26c59cb4af1fcfd8b0454964748762d60ea466d3b9fd2e9736789564f841e4fef054a353ed5b2ebabc10bc5e06f116f61db75f362b1a91a1a7de4b15c3489f86
data/CHANGELOG.md ADDED
@@ -0,0 +1,3 @@
1
+ ### 0.0.1 / 2022-12-15
2
+
3
+ * Everything is new. First release
data/Manifest.txt ADDED
@@ -0,0 +1,8 @@
1
+ CHANGELOG.md
2
+ Manifest.txt
3
+ README.md
4
+ Rakefile
5
+ lib/etherscan-lite.rb
6
+ lib/etherscan-lite/account.rb
7
+ lib/etherscan-lite/base.rb
8
+ lib/etherscan-lite/version.rb
data/README.md ADDED
@@ -0,0 +1,355 @@
1
+ # Etherscan Lite
2
+
3
+ etherscan-lite - light-weight machinery / helper for the Etherscan (blockchain) JSON HTTP API / web services (note: API key sign-up required)
4
+
5
+ * home :: [github.com/rubycocos/blockchain](https://github.com/rubycocos/blockchain)
6
+ * bugs :: [github.com/rubycocos/blockchain/issues](https://github.com/rubycocos/blockchain/issues)
7
+ * gem :: [rubygems.org/gems/etherscan-lite](https://rubygems.org/gems/etherscan-lite)
8
+ * rdoc :: [rubydoc.info/gems/etherscan-lite](http://rubydoc.info/gems/etherscan-lite)
9
+
10
+
11
+
12
+ ## Usage
13
+
14
+
15
+ ### Step 0 - Setup - Configure ETHERSCAN API Key
16
+
17
+
18
+ The etherscan lite machinery will (auto-magically) lookup
19
+ the `ETHERSCAN_KEY` environment variable
20
+ or will load a dotenv file (`.env`) in the working / current directory
21
+ or use in your script:
22
+
23
+ ``` ruby
24
+ Etherscan.config.key = 'YOUR_API_KEY_HERE'
25
+
26
+ # or
27
+
28
+ Etherscan.configure do |config|
29
+ config.key = 'YOUR_API_KEY_HERE'
30
+ end
31
+ ```
32
+
33
+
34
+ ### Etherscan API Recipes
35
+
36
+ Let's try the "official" recipes from the Eherscan API docu
37
+
38
+ - Get All USDT Transfers from Binance
39
+ - Get the Latest Moonbird Non-Fungible Token (NFT) Transfers
40
+ - List ETH deposits to Arbitrum Bridge
41
+
42
+
43
+ ### Get All USDT Transfers from Binance
44
+
45
+ see <https://docs.etherscan.io/recipes/get-all-usdt-transfers-from-binance>
46
+
47
+
48
+ ``` ruby
49
+ require 'etherscan-lite'
50
+
51
+ USDT_ADDRESS = '0xdac17f958d2ee523a2206206994597c13d831ec7'
52
+ BINANCE_HOT_WALLET = '0xdfd5293d8e347dfe59e90efd55b2956a1343963d'
53
+
54
+ data = Etherscan.tokentx( address: BINANCE_HOT_WALLET,
55
+ contractaddress: USDT_ADDRESS )
56
+ pp data
57
+ ```
58
+
59
+ resulting in:
60
+
61
+ ``` json
62
+ [{"blockNumber"=>"16191306",
63
+ "timeStamp"=>"1671121931",
64
+ "hash"=>"0x77361870fdc3046f7c24cabafa7185a84d60f4fa12aef8363e8520fbdd003cc7",
65
+ "nonce"=>"4866500",
66
+ "blockHash"=>"0x1f5d2e10774bd5473257ad0f47d08b3e523e3baace6f0218bce8aab62e90ec67",
67
+ "from"=>"0xdfd5293d8e347dfe59e90efd55b2956a1343963d",
68
+ "contractAddress"=>"0xdac17f958d2ee523a2206206994597c13d831ec7",
69
+ "to"=>"0x40fbc37ff0e4d3f900b867f2ca48ae6aba77c854",
70
+ "value"=>"495264069",
71
+ "tokenName"=>"Tether USD",
72
+ "tokenSymbol"=>"USDT",
73
+ "tokenDecimal"=>"6",
74
+ "transactionIndex"=>"44",
75
+ "gas"=>"207128",
76
+ "gasPrice"=>"31567202036",
77
+ "gasUsed"=>"63197",
78
+ "cumulativeGasUsed"=>"5207555",
79
+ "input"=>"deprecated",
80
+ "confirmations"=>"3"},
81
+ {"blockNumber"=>"16191304",
82
+ "timeStamp"=>"1671121907",
83
+ "hash"=>"0xd3d529d0d420e38680ad9066a5d62434a04b01e94b00b81fc5fea303afbda076",
84
+ "nonce"=>"4866498",
85
+ "blockHash"=>"0x9b2dfbfd068c90546c7572bc059cd790e12eb6b9f9b21a3c7c33e0abd8d69d6c",
86
+ "from"=>"0xdfd5293d8e347dfe59e90efd55b2956a1343963d",
87
+ "contractAddress"=>"0xdac17f958d2ee523a2206206994597c13d831ec7",
88
+ "to"=>"0xf7140bb010da74a191e3c98f801e596937f177fb",
89
+ "value"=>"4496800000",
90
+ "tokenName"=>"Tether USD",
91
+ "tokenSymbol"=>"USDT",
92
+ "tokenDecimal"=>"6",
93
+ "transactionIndex"=>"57",
94
+ "gas"=>"207128",
95
+ "gasPrice"=>"32759178674",
96
+ "gasUsed"=>"46109",
97
+ "cumulativeGasUsed"=>"3775818",
98
+ "input"=>"deprecated",
99
+ "confirmations"=>"5"},
100
+ ...
101
+ ]
102
+ ```
103
+
104
+ and let's pretty print the data (records):
105
+
106
+ ``` ruby
107
+ data.each_with_index do |h,i|
108
+ timestamp = Time.at( h['timeStamp'].to_i ).utc
109
+
110
+ decimal = h['tokenDecimal'].to_i
111
+ value = h['value'].to_i
112
+
113
+ major = value / (10**decimal)
114
+ minor = value % (10**decimal)
115
+
116
+ print " [#{i}] #{timestamp} - "
117
+ print "#{h['tokenName']} (#{h['tokenSymbol']}) "
118
+ print "%6d.%0#{decimal}d" % [major, minor]
119
+ print " (#{value}) - "
120
+ print "from: #{h['from'][0..10]} "
121
+ print "to: #{h['to'][0..10]} - "
122
+ print "txid: #{h['hash'][0..8]}"
123
+ print "\n"
124
+ end
125
+ ```
126
+
127
+ resulting in:
128
+
129
+ ```
130
+ [0] 2022-12-15 16:32:11 UTC - Tether USD (USDT) 495.264069 (495264069) - from: 0xdfd5293d8 to: 0x40fbc37ff - txid: 0x7736187
131
+ [1] 2022-12-15 16:31:47 UTC - Tether USD (USDT) 4496.800000 (4496800000) - from: 0xdfd5293d8 to: 0xf7140bb01 - txid: 0xd3d529d
132
+ [2] 2022-12-15 16:31:11 UTC - Tether USD (USDT) 1496.800000 (1496800000) - from: 0xdfd5293d8 to: 0xcab0e46b1 - txid: 0x0b7986d
133
+ [3] 2022-12-15 16:31:11 UTC - Tether USD (USDT) 122.800000 (122800000) - from: 0xdfd5293d8 to: 0xcc38c0e6f - txid: 0x8894af7
134
+ [4] 2022-12-15 16:30:35 UTC - Tether USD (USDT) 22953.971400 (22953971400) - from: 0xdfd5293d8 to: 0xccb95ec69 - txid: 0x0bb6b75
135
+ [5] 2022-12-15 16:30:11 UTC - Tether USD (USDT) 254.743920 (254743920) - from: 0xdfd5293d8 to: 0x68f2a6311 - txid: 0xf691bed
136
+ [6] 2022-12-15 16:29:35 UTC - Tether USD (USDT) 548.950317 (548950317) - from: 0xdfd5293d8 to: 0xaa00cd50e - txid: 0x847854b
137
+ [7] 2022-12-15 16:29:11 UTC - Tether USD (USDT) 33667.697868 (33667697868) - from: 0xdfd5293d8 to: 0xcfb27a23f - txid: 0x7a2390d
138
+ [8] 2022-12-15 16:28:59 UTC - Tether USD (USDT) 48126.270731 (48126270731) - from: 0xdfd5293d8 to: 0x09857b83a - txid: 0x0653035
139
+ [9] 2022-12-15 16:28:35 UTC - Tether USD (USDT) 15996.800000 (15996800000) - from: 0xdfd5293d8 to: 0xd8d6ffe34 - txid: 0xb02d04b
140
+ ```
141
+
142
+
143
+ ### Get the Latest Moonbird Non-Fungible Token (NFT) Transfers
144
+
145
+ see <https://docs.etherscan.io/recipes/get-the-latest-moonbird-nft-transfers>
146
+
147
+ ``` ruby
148
+ require 'etherscan-lite'
149
+
150
+ MOONBIRDS_ADDRESS = '0x23581767a106ae21c074b2276D25e5C3e136a68b'
151
+
152
+ data = Etherscan.tokennfttx( contractaddress: MOONBIRDS_ADDRESS )
153
+ pp data
154
+ ```
155
+
156
+ resulting in:
157
+
158
+ ``` json
159
+ [{"blockNumber"=>"16191303",
160
+ "timeStamp"=>"1671121895",
161
+ "hash"=>"0xf049e3247e19e2eca1971f6daa38e7310bf2705b7da6347b9801122eef57f30e",
162
+ "nonce"=>"16348",
163
+ "blockHash"=>"0x2ec6abfc229cb61b7a851d9e078e93681634cf0b2b3390a54f6fa21e8d10cd04",
164
+ "from"=>"0x8ae57a027c63fca8070d1bf38622321de8004c67",
165
+ "contractAddress"=>"0x23581767a106ae21c074b2276d25e5c3e136a68b",
166
+ "to"=>"0xdc3276739390e3fdf7929056593d2ce316ebcfa8",
167
+ "tokenID"=>"2934",
168
+ "tokenName"=>"Moonbirds",
169
+ "tokenSymbol"=>"MOONBIRD",
170
+ "tokenDecimal"=>"0",
171
+ "transactionIndex"=>"150",
172
+ "gas"=>"168819",
173
+ "gasPrice"=>"30350829601",
174
+ "gasUsed"=>"64019",
175
+ "cumulativeGasUsed"=>"16664047",
176
+ "input"=>"deprecated",
177
+ "confirmations"=>"25"},
178
+ {"blockNumber"=>"16191297",
179
+ "timeStamp"=>"1671121823",
180
+ "hash"=>"0xb341b32b2c8904733c05648f67c09c99602a22b454f6f99b68746eb204c8f235",
181
+ "nonce"=>"4310",
182
+ "blockHash"=>"0x8774a12b660e59586ae94af1670362d2c73d09c94230f236859548ae0768f387",
183
+ "from"=>"0x8bc110db7029197c3621bea8092ab1996d5dd7be",
184
+ "contractAddress"=>"0x23581767a106ae21c074b2276d25e5c3e136a68b",
185
+ "to"=>"0x6ce2eb1c3006850ebbb97499f1a25b8ce6c01a44",
186
+ "tokenID"=>"9836",
187
+ "tokenName"=>"Moonbirds",
188
+ "tokenSymbol"=>"MOONBIRD",
189
+ "tokenDecimal"=>"0",
190
+ "transactionIndex"=>"15",
191
+ "gas"=>"3576346",
192
+ "gasPrice"=>"35958543341",
193
+ "gasUsed"=>"2751035",
194
+ "cumulativeGasUsed"=>"3999647",
195
+ "input"=>"deprecated",
196
+ "confirmations"=>"31"},
197
+ ...
198
+ ]
199
+ ```
200
+
201
+ and let's pretty print the data (records):
202
+
203
+
204
+ ``` ruby
205
+ data.each_with_index do |h,i|
206
+ timestamp = Time.at( h['timeStamp'].to_i ).utc
207
+
208
+ print " [#{i}] #{timestamp} - "
209
+ print "#{h['tokenName']} #{h['tokenID']} - "
210
+ print "from: #{h['from'][0..10]} "
211
+ print "to: #{h['to'][0..10]} - "
212
+ print "txid: #{h['hash'][0..8]}"
213
+ print "\n"
214
+ end
215
+ ```
216
+
217
+ resulting in:
218
+
219
+ ```
220
+ [0] 2022-12-15 16:31:35 UTC - Moonbirds 2934 - from: 0x8ae57a027 to: 0xdc3276739 - txid: 0xf049e32
221
+ [1] 2022-12-15 16:30:23 UTC - Moonbirds 9836 - from: 0x8bc110db7 to: 0x6ce2eb1c3 - txid: 0xb341b32
222
+ [2] 2022-12-15 16:30:23 UTC - Moonbirds 9378 - from: 0x8bc110db7 to: 0x6ce2eb1c3 - txid: 0xb341b32
223
+ [3] 2022-12-15 16:30:23 UTC - Moonbirds 9059 - from: 0x8bc110db7 to: 0x6ce2eb1c3 - txid: 0xb341b32
224
+ [4] 2022-12-15 16:30:23 UTC - Moonbirds 8199 - from: 0x8bc110db7 to: 0x6ce2eb1c3 - txid: 0xb341b32
225
+ [5] 2022-12-15 16:30:23 UTC - Moonbirds 7800 - from: 0x8bc110db7 to: 0x6ce2eb1c3 - txid: 0xb341b32
226
+ [6] 2022-12-15 16:30:23 UTC - Moonbirds 5952 - from: 0x8bc110db7 to: 0x6ce2eb1c3 - txid: 0xb341b32
227
+ [7] 2022-12-15 16:30:23 UTC - Moonbirds 5868 - from: 0x8bc110db7 to: 0x6ce2eb1c3 - txid: 0xb341b32
228
+ [8] 2022-12-15 16:30:23 UTC - Moonbirds 5853 - from: 0x8bc110db7 to: 0x6ce2eb1c3 - txid: 0xb341b32
229
+ [9] 2022-12-15 16:30:23 UTC - Moonbirds 501 - from: 0x8bc110db7 to: 0x6ce2eb1c3 - txid: 0xb341b32
230
+ ```
231
+
232
+
233
+
234
+ ### List ETH deposits to Arbitrum Bridge
235
+
236
+ see <https://docs.etherscan.io/recipes/list-eth-deposits-to-arbitrum-bridge>
237
+
238
+
239
+ ``` ruby
240
+ require 'etherscan-lite'
241
+
242
+ ARBITRUM_DELAYED_INBOX = '0x4dbd4fc535ac27206064b68ffcf827b0a60bab3f'
243
+
244
+ data = Etherscan.txlist( address: ARBITRUM_DELAYED_INBOX )
245
+ pp data
246
+ ```
247
+
248
+ resulting in:
249
+
250
+
251
+ ``` json
252
+ [{"blockNumber"=>"16191330",
253
+ "timeStamp"=>"1671122219",
254
+ "hash"=>"0xea692b153ec048322dd6dc0a42fba45a0f06b2bd0e6888c7e42edbc629689f00",
255
+ "nonce"=>"998",
256
+ "blockHash"=>"0x3c3a23b78fd1522f9f9ed5a1fc45d5a7d1d71327961c77d164c0eeb1e72b4322",
257
+ "transactionIndex"=>"244",
258
+ "from"=>"0xae4705dc0816ee6d8a13f1c72780ec5021915fed",
259
+ "to"=>"0x4dbd4fc535ac27206064b68ffcf827b0a60bab3f",
260
+ "value"=>"420690000000000000",
261
+ "gas"=>"92219",
262
+ "gasPrice"=>"26218969764",
263
+ "isError"=>"0",
264
+ "txreceipt_status"=>"1",
265
+ "input"=>"0x439370b1",
266
+ "contractAddress"=>"",
267
+ "cumulativeGasUsed"=>"18496407",
268
+ "gasUsed"=>"91261",
269
+ "confirmations"=>"16",
270
+ "methodId"=>"0x439370b1",
271
+ "functionName"=>"depositEth()"},
272
+ {"blockNumber"=>"16191327",
273
+ "timeStamp"=>"1671122183",
274
+ "hash"=>"0x8a82fc0e7ac1fb588f1ee248810d518bc03dfb4e938160c6502f949fcc16054c",
275
+ "nonce"=>"2",
276
+ "blockHash"=>"0xb533b2cd157369414839c58b74319bf32400dd6521b5d945eb7ac405d0600203",
277
+ "transactionIndex"=>"78",
278
+ "from"=>"0x338b8d83e644689a0ea90f04e0efa144fccfb3c7",
279
+ "to"=>"0x4dbd4fc535ac27206064b68ffcf827b0a60bab3f",
280
+ "value"=>"19000000000000000",
281
+ "gas"=>"92219",
282
+ "gasPrice"=>"29492008048",
283
+ "isError"=>"0",
284
+ "txreceipt_status"=>"1",
285
+ "input"=>"0x439370b1",
286
+ "contractAddress"=>"",
287
+ "cumulativeGasUsed"=>"7020870",
288
+ "gasUsed"=>"91261",
289
+ "confirmations"=>"19",
290
+ "methodId"=>"0x439370b1",
291
+ "functionName"=>"depositEth()"},
292
+ ...
293
+ ]
294
+ ```
295
+
296
+ and let's pretty print the data (records):
297
+
298
+
299
+ ``` ruby
300
+ data.each_with_index do |h,i|
301
+ timestamp = Time.at( h['timeStamp'].to_i ).utc
302
+
303
+ ## note: ether (ETH) uses 18 decimal
304
+ ## e.g. 0.000000000000000001 (= 1 wei)
305
+ decimal = 18
306
+ value = h['value'].to_i
307
+
308
+ major = value / (10**decimal)
309
+ minor = value % (10**decimal)
310
+
311
+ print " [#{i}] #{timestamp} - "
312
+ print "#{h['functionName']} "
313
+ print "%3d.%0#{decimal}d" % [major, minor]
314
+ print " (#{value}) - "
315
+ print "from: #{h['from'][0..10]} "
316
+ print "to: #{h['to'][0..10]} - "
317
+ print "txid: #{h['hash'][0..8]}"
318
+ print "\n"
319
+ end
320
+ ```
321
+
322
+ resulting in:
323
+
324
+ ```
325
+ [0] 2022-12-15 16:36:59 UTC - depositEth() 0.420690000000000000 (420690000000000000) - from: 0xae4705dc0 to: 0x4dbd4fc53 - txid: 0xea692b1
326
+ [1] 2022-12-15 16:36:23 UTC - depositEth() 0.019000000000000000 (19000000000000000) - from: 0x338b8d83e to: 0x4dbd4fc53 - txid: 0x8a82fc0
327
+ [2] 2022-12-15 16:35:23 UTC - depositEth() 0.040000000000000000 (40000000000000000) - from: 0x63e1c7edc to: 0x4dbd4fc53 - txid: 0x46bc422
328
+ [3] 2022-12-15 16:34:23 UTC - depositEth() 0.003330000000000000 (3330000000000000) - from: 0xe29abe7f8 to: 0x4dbd4fc53 - txid: 0x2fbd49e
329
+ [4] 2022-12-15 16:34:23 UTC - depositEth() 0.022398548608559353 (22398548608559353) - from: 0x3dbcf6a3d to: 0x4dbd4fc53 - txid: 0xc311e3f
330
+ [5] 2022-12-15 16:32:23 UTC - depositEth() 0.195713000000000000 (195713000000000000) - from: 0xc7099c3ed to: 0x4dbd4fc53 - txid: 0x4a2f2e4
331
+ [6] 2022-12-15 16:31:23 UTC - depositEth() 0.100000000000000000 (100000000000000000) - from: 0x78cea29ac to: 0x4dbd4fc53 - txid: 0xedc3793
332
+ [7] 2022-12-15 16:28:35 UTC - depositEth() 2.406000000000000000 (2406000000000000000) - from: 0xa59192967 to: 0x4dbd4fc53 - txid: 0xde20917
333
+ [8] 2022-12-15 16:28:23 UTC - depositEth() 0.030000000000000000 (30000000000000000) - from: 0x03a64c941 to: 0x4dbd4fc53 - txid: 0xc813c01
334
+ [9] 2022-12-15 16:27:35 UTC - depositEth() 0.004000000000000000 (4000000000000000) - from: 0x614d071bf to: 0x4dbd4fc53 - txid: 0xb24df57
335
+ ```
336
+
337
+ and so on.
338
+
339
+
340
+
341
+
342
+
343
+
344
+ ## License
345
+
346
+ The scripts are dedicated to the public domain.
347
+ Use it as you please with no restrictions whatsoever.
348
+
349
+
350
+ ## Questions? Comments?
351
+
352
+
353
+ Post them on the [D.I.Y. Punk (Pixel) Art reddit](https://old.reddit.com/r/DIYPunkArt). Thanks.
354
+
355
+
data/Rakefile ADDED
@@ -0,0 +1,32 @@
1
+ require 'hoe'
2
+ require './lib/etherscan-lite/version.rb'
3
+
4
+
5
+ Hoe.spec 'etherscan-lite' do
6
+
7
+ self.version = EtherscanLite::VERSION
8
+
9
+ self.summary = "etherscan-lite - light-weight machinery / helper for the Etherscan (blockchain) JSON HTTP API / web services (note: API key sign-up required)"
10
+ self.description = summary
11
+
12
+ self.urls = { home: 'https://github.com/rubycocos/blockchain' }
13
+
14
+ self.author = 'Gerald Bauer'
15
+ self.email = 'wwwmake@googlegroups.com'
16
+
17
+ # switch extension to .markdown for gihub formatting
18
+ self.readme_file = 'README.md'
19
+ self.history_file = 'CHANGELOG.md'
20
+
21
+ self.extra_deps = [
22
+ ['cocos'],
23
+ ]
24
+
25
+ self.licenses = ['Public Domain']
26
+
27
+ self.spec_extras = {
28
+ required_ruby_version: '>= 2.3'
29
+ }
30
+
31
+ end
32
+
@@ -0,0 +1,100 @@
1
+ module Etherscan
2
+
3
+ ## Get a list of 'Normal' Transactions By Address
4
+ ## Returns the list of transactions performed by an address,
5
+ ## with optional pagination.
6
+ ## see https://docs.etherscan.io/api-endpoints/accounts#get-a-list-of-normal-transactions-by-address
7
+ def self.txlist_url( address:,
8
+ startblock: 0,
9
+ endblock: 99999999,
10
+ page: 1,
11
+ offset: 10,
12
+ sort: 'desc' )
13
+
14
+ src = "#{BASE}?module=account&action=txlist" +
15
+ "&address=#{address}" +
16
+ "&startblock=#{startblock}" +
17
+ "&endblock=#{endblock}" +
18
+ "&page=#{page}" +
19
+ "&offset=#{offset}" +
20
+ "&sort=#{sort}" +
21
+ "&apikey=#{config.key}"
22
+ src
23
+ end
24
+
25
+ def self.txlist( **kwargs )
26
+ call( txlist_url( **kwargs ) )
27
+ end
28
+
29
+
30
+ ## Get a list of 'ERC20 - Token Transfer Events' by Address
31
+ ## Returns the list of ERC-20 tokens transferred by an address,
32
+ ## with optional filtering by token contract.
33
+ ## Usage:
34
+ ## - ERC-20 transfers from an address, specify the address parameter
35
+ ## - ERC-20 transfers from a contract address, specify the contract address parameter
36
+ ## - ERC-20 transfers from an address filtered by a token contract, specify both address and contract address parameters.
37
+ ##
38
+ ## see https://docs.etherscan.io/api-endpoints/accounts#get-a-list-of-erc20-token-transfer-events-by-address
39
+ def self.tokentx_url( address: nil,
40
+ contractaddress: nil,
41
+ startblock: 0,
42
+ endblock: 99999999,
43
+ page: 1,
44
+ offset: 10,
45
+ sort: 'desc' )
46
+
47
+ src = "#{BASE}?module=account&action=tokentx" +
48
+ "&startblock=#{startblock}" +
49
+ "&endblock=#{endblock}" +
50
+ "&page=#{page}" +
51
+ "&offset=#{offset}" +
52
+ "&sort=#{sort}" +
53
+ "&apikey=#{config.key}"
54
+
55
+ ## optional
56
+ src += "&address=#{address}" if address
57
+ src += "&contractaddress=#{contractaddress}" if contractaddress
58
+ src
59
+ end
60
+
61
+ def self.tokentx( **kwargs )
62
+ call( tokentx_url( **kwargs ) )
63
+ end
64
+
65
+
66
+ ## Get a list of 'ERC721 - Token Transfer Events' by Address
67
+ ## Returns the list of ERC-721 ( NFT ) tokens transferred by an address,
68
+ ## with optional filtering by token contract.
69
+ ## Usage:
70
+ ## - ERC-721 transfers from an address, specify the address parameter
71
+ ## - ERC-721 transfers from a contract address, specify the contract address parameter
72
+ ## - ERC-721 transfers from an address filtered by a token contract, specify both address and contract address parameters.
73
+ ##
74
+ ## see https://docs.etherscan.io/api-endpoints/accounts#get-a-list-of-erc721-token-transfer-events-by-address
75
+ def self.tokennfttx_url( address: nil,
76
+ contractaddress: nil,
77
+ startblock: 0,
78
+ endblock: 99999999,
79
+ page: 1,
80
+ offset: 10,
81
+ sort: 'desc' )
82
+
83
+ src = "#{BASE}?module=account&action=tokennfttx" +
84
+ "&startblock=#{startblock}" +
85
+ "&endblock=#{endblock}" +
86
+ "&page=#{page}" +
87
+ "&offset=#{offset}" +
88
+ "&sort=#{sort}" +
89
+ "&apikey=#{config.key}"
90
+
91
+ ## optional
92
+ src += "&address=#{address}" if address
93
+ src += "&contractaddress=#{contractaddress}" if contractaddress
94
+ src
95
+ end
96
+
97
+ def self.tokennfttx( **kwargs )
98
+ call( tokennfttx_url( **kwargs ) )
99
+ end
100
+ end # module Etherscan
@@ -0,0 +1,57 @@
1
+ module Etherscan
2
+ BASE = 'https://api.etherscan.io/api'
3
+
4
+
5
+
6
+
7
+ def self.call( src ) ## get response as (parsed) json (hash table)
8
+ uri = URI.parse( src )
9
+
10
+ http = Net::HTTP.new( uri.host, uri.port )
11
+
12
+ puts "[debug] GET #{uri.request_uri} uri=#{uri}"
13
+
14
+ headers = {
15
+ # 'User-Agent' => "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36",
16
+ 'User-Agent' => "ruby v#{RUBY_VERSION}",
17
+ }
18
+
19
+
20
+ request = Net::HTTP::Get.new( uri.request_uri, headers )
21
+ if uri.instance_of? URI::HTTPS
22
+ http.use_ssl = true
23
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
24
+ end
25
+
26
+ response = http.request( request )
27
+
28
+ if response.code == '200'
29
+ puts "#{response.code} #{response.message} - content_type: #{response.content_type}, content_length: #{response.content_length}"
30
+
31
+ text = response.body.to_s
32
+ text = text.force_encoding( Encoding::UTF_8 )
33
+
34
+ data = JSON.parse( text )
35
+ data
36
+
37
+ ## note: "unwrap" result - and auto-check status/message e.g.
38
+ ## {"status"=>"1",
39
+ ## "message"=>"OK",
40
+ ## "result"=> ..
41
+ ## }
42
+ if data['status'] == '1' && data['message'] == 'OK'
43
+ puts "#{data['status']} #{data['message']}"
44
+ data['result']
45
+ else
46
+ puts "!! ETHERSCAN API ERROR:"
47
+ puts "#{data['status']} #{data['message']}"
48
+ exit 1
49
+ end
50
+ else
51
+ puts "!! ERROR:"
52
+ puts "#{response.code} #{response.message}"
53
+ exit 1
54
+ end
55
+ end
56
+
57
+ end # module Etherscan
@@ -0,0 +1,22 @@
1
+
2
+
3
+ module EtherscanLite
4
+ MAJOR = 0
5
+ MINOR = 0
6
+ PATCH = 1
7
+ VERSION = [MAJOR,MINOR,PATCH].join('.')
8
+
9
+ def self.version
10
+ VERSION
11
+ end
12
+
13
+ def self.banner
14
+ "etherscan-lite/#{VERSION} on Ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}] in (#{root})"
15
+ end
16
+
17
+ def self.root
18
+ File.expand_path( File.dirname(File.dirname(File.dirname(__FILE__))) )
19
+ end
20
+
21
+ end # module EtherscanLite
22
+
@@ -0,0 +1,53 @@
1
+ require 'cocos'
2
+
3
+
4
+ ### todo/fix:
5
+ ## move .env loader to
6
+ ## cocos - why? why not?
7
+ def load_env( path='./.env' )
8
+ if File.exist?( path )
9
+ puts "==> loading .env settings..."
10
+ env = read_yaml( path )
11
+ puts " applying .env settings... (merging into ENV)"
12
+ pp env
13
+ env.each do |k,v|
14
+ ENV[k] ||= v
15
+ end
16
+ end
17
+ end
18
+
19
+ load_env
20
+
21
+
22
+
23
+ ## our own code
24
+ require_relative 'etherscan-lite/version'
25
+
26
+ ### add (shared) "global" config
27
+ module Etherscan
28
+ class Configuration
29
+
30
+ #######################
31
+ ## accessors
32
+ ## todo/check - change to apikey or api_key or such - why? why not?
33
+ def key() @key ||= ENV['ETHERSCAN_KEY']; end
34
+ def key=(value) @key = value; end
35
+ end # class Configuration
36
+
37
+
38
+ ## lets you use
39
+ ## Ethersan.configure do |config|
40
+ ## config.key = 'xxxx'
41
+ ## end
42
+ def self.configure() yield( config ); end
43
+ def self.config() @config ||= Configuration.new; end
44
+ end # module Etherscan
45
+
46
+
47
+ require_relative 'etherscan-lite/base'
48
+ require_relative 'etherscan-lite/account'
49
+
50
+
51
+
52
+ puts EtherscanLite.banner # say hello
53
+
metadata ADDED
@@ -0,0 +1,105 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: etherscan-lite
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Gerald Bauer
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-12-15 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: cocos
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rdoc
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '4.0'
34
+ - - "<"
35
+ - !ruby/object:Gem::Version
36
+ version: '7'
37
+ type: :development
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: '4.0'
44
+ - - "<"
45
+ - !ruby/object:Gem::Version
46
+ version: '7'
47
+ - !ruby/object:Gem::Dependency
48
+ name: hoe
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '3.23'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '3.23'
61
+ description: 'etherscan-lite - light-weight machinery / helper for the Etherscan (blockchain)
62
+ JSON HTTP API / web services (note: API key sign-up required)'
63
+ email: wwwmake@googlegroups.com
64
+ executables: []
65
+ extensions: []
66
+ extra_rdoc_files:
67
+ - CHANGELOG.md
68
+ - Manifest.txt
69
+ - README.md
70
+ files:
71
+ - CHANGELOG.md
72
+ - Manifest.txt
73
+ - README.md
74
+ - Rakefile
75
+ - lib/etherscan-lite.rb
76
+ - lib/etherscan-lite/account.rb
77
+ - lib/etherscan-lite/base.rb
78
+ - lib/etherscan-lite/version.rb
79
+ homepage: https://github.com/rubycocos/blockchain
80
+ licenses:
81
+ - Public Domain
82
+ metadata: {}
83
+ post_install_message:
84
+ rdoc_options:
85
+ - "--main"
86
+ - README.md
87
+ require_paths:
88
+ - lib
89
+ required_ruby_version: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: '2.3'
94
+ required_rubygems_version: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ requirements: []
100
+ rubygems_version: 3.3.7
101
+ signing_key:
102
+ specification_version: 4
103
+ summary: 'etherscan-lite - light-weight machinery / helper for the Etherscan (blockchain)
104
+ JSON HTTP API / web services (note: API key sign-up required)'
105
+ test_files: []