ethlite 0.2.3 → 0.2.5
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/Manifest.txt +0 -1
- data/README.md +170 -2
- data/Rakefile +1 -1
- data/lib/ethlite/abi/utils.rb +46 -42
- data/lib/ethlite/constant.rb +13 -26
- data/lib/ethlite/contract.rb +3 -5
- data/lib/ethlite/version.rb +1 -1
- data/lib/ethlite.rb +1 -2
- data/lib/jsonrpc/jsonrpc.rb +18 -24
- metadata +3 -4
- data/lib/ethlite/utility.rb +0 -23
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3cd659223f8049ca63302c5bb595da6faf483d29d776ed747b5970dde11b415e
|
4
|
+
data.tar.gz: fde6fca03683dac98d474d82bc520a82dc45e74b08eaabbc0c521e2635ca3d3b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 050226ff51c20a38cb8f1db254e246a555d07baf8a6e12766985850400749a463698e89818780cd031e5ed3cab6bb05e2afae37588149084160138d5e6783e0f
|
7
|
+
data.tar.gz: 0d16770efc489cf88f08ec8ef471563905b2197c1d8330c58558348f1a9076dd717f654b5c221ea78052d31855bb458105c79f2f7ec1021a04451a202088b722
|
data/Manifest.txt
CHANGED
data/README.md
CHANGED
@@ -11,10 +11,178 @@ ethlite - light-weight machinery to query / call ethereum (blockchain contract)
|
|
11
11
|
|
12
12
|
|
13
13
|
|
14
|
-
|
15
14
|
## Usage
|
16
15
|
|
17
|
-
|
16
|
+
|
17
|
+
### Step 0: Setup JSON RPC Client
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
## let's use a simple JSON RPC client
|
21
|
+
## get the eth node uri via the INFURA_URI enviroment variable / key
|
22
|
+
## e.g. https://mainnet.infura.io/v3/<YOUR_KEY_HERE>
|
23
|
+
ETH_NODE = JsonRpc.new( ENV['INFURA_URI'] )
|
24
|
+
```
|
25
|
+
|
26
|
+
|
27
|
+
|
28
|
+
### Do-It-Yourself (DIY) JSON RPC eth_call With "Hand-Coded" To-The-Metal ABI Encoding/Decoding
|
29
|
+
|
30
|
+
|
31
|
+
Let's try to build a JSON-RPC request from scratch calling
|
32
|
+
a (constant/read-only/view) blockchain contract method via `eth_call`.
|
33
|
+
|
34
|
+
Let's try `function tokenURI(uint256 tokenId) returns (string)`
|
35
|
+
that lets you request the metdata uri for a (non-fungible) token.
|
36
|
+
|
37
|
+
Let's try the Moonbirds contract @ [0x23581767a106ae21c074b2276d25e5c3e136a68b](https://etherscan.io/address/0x23581767a106ae21c074b2276d25e5c3e136a68b):
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
## contract address - let's try moonbirds
|
41
|
+
contract_address = '0x23581767a106ae21c074b2276d25e5c3e136a68b'
|
42
|
+
|
43
|
+
token_ids = (0..9)
|
44
|
+
token_ids.each do |token_id|
|
45
|
+
|
46
|
+
puts "==> calling tokenURI(#{token_id})..."
|
47
|
+
tokenURI = eth_call( contract_address,
|
48
|
+
'tokenURI', ['uint256'], ['string'],
|
49
|
+
[token_id] )
|
50
|
+
puts " ...returns: #{tokenURI}"
|
51
|
+
end
|
52
|
+
```
|
53
|
+
|
54
|
+
|
55
|
+
And the "magic" hand-coded to-the-metal `eth_call` machinery:
|
56
|
+
|
57
|
+
```ruby
|
58
|
+
## construct a json-rpc call from scratch
|
59
|
+
def eth_call( contract_address,
|
60
|
+
name, inputs, outputs,
|
61
|
+
args )
|
62
|
+
|
63
|
+
## binary encode method sig(nature)
|
64
|
+
signature = "#{name}(#{inputs.join(',')})"
|
65
|
+
signature_hash = Ethlite::Abi::Utils.encode_hex(
|
66
|
+
Ethlite::Abi::Utils.keccak256(signature))[0..7]
|
67
|
+
|
68
|
+
pp signature
|
69
|
+
# => "tokenURI(uint256)"
|
70
|
+
pp signature_hash
|
71
|
+
# => "c87b56dd"
|
72
|
+
|
73
|
+
## binary encode method arg(ument)s
|
74
|
+
args_encoded = Ethlite::Abi::Utils.encode_hex(
|
75
|
+
Ethlite::Abi::AbiCoder.encode_abi( inputs, args) )
|
76
|
+
|
77
|
+
data = '0x' + signature_hash + args_encoded
|
78
|
+
|
79
|
+
## json-rpc method and params
|
80
|
+
method = 'eth_call'
|
81
|
+
params = [{ to: contract_address,
|
82
|
+
data: data},
|
83
|
+
'latest'
|
84
|
+
]
|
85
|
+
|
86
|
+
## do the json-rpc request
|
87
|
+
response = ETH_NODE.request( method, params )
|
88
|
+
|
89
|
+
puts "response:"
|
90
|
+
pp response
|
91
|
+
|
92
|
+
## decode binary result
|
93
|
+
string_data = Ethlite::Abi::Utils.decode_hex(
|
94
|
+
Ethlite::Abi::Utils.remove_0x_head(response))
|
95
|
+
result = Ethlite::Abi::AbiCoder.decode_abi( outputs, string_data )
|
96
|
+
result.length == 1 ? result[0] : result
|
97
|
+
end
|
98
|
+
```
|
99
|
+
|
100
|
+
resulting in (with debug json rpc request/reponse output):
|
101
|
+
|
102
|
+
|
103
|
+
calling `tokenURI(0)`... json_rpc POST payload request:
|
104
|
+
|
105
|
+
``` json
|
106
|
+
{"jsonrpc":"2.0",
|
107
|
+
"method":"eth_call",
|
108
|
+
"params":[
|
109
|
+
{"to":"0x23581767a106ae21c074b2276d25e5c3e136a68b",
|
110
|
+
"data":"0xc87b56dd0000000000000000000000000000000000000000000000000000000000000000"},
|
111
|
+
"latest"],
|
112
|
+
"id":1
|
113
|
+
}
|
114
|
+
```
|
115
|
+
|
116
|
+
json_rpc response:
|
117
|
+
|
118
|
+
``` json
|
119
|
+
{"jsonrpc":"2.0",
|
120
|
+
"id":1,"result":"0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003a68747470733a2f2f6c6976652d2d2d6d657461646174612d35636f767071696a61612d75632e612e72756e2e6170702f6d657461646174612f30000000000000"
|
121
|
+
}
|
122
|
+
```
|
123
|
+
|
124
|
+
...returns: `https://live---metadata-5covpqijaa-uc.a.run.app/metadata/0`
|
125
|
+
|
126
|
+
|
127
|
+
calling `tokenURI(1)...` json_rpc POST payload request:
|
128
|
+
|
129
|
+
``` json
|
130
|
+
{"jsonrpc":"2.0",
|
131
|
+
"method":"eth_call",
|
132
|
+
"params":[
|
133
|
+
{"to":"0x23581767a106ae21c074b2276d25e5c3e136a68b",
|
134
|
+
"data":"0xc87b56dd0000000000000000000000000000000000000000000000000000000000000001"},
|
135
|
+
"latest"],
|
136
|
+
"id":2
|
137
|
+
}
|
138
|
+
```
|
139
|
+
|
140
|
+
json_rpc response:
|
141
|
+
|
142
|
+
``` json
|
143
|
+
{"jsonrpc":"2.0",
|
144
|
+
"id":2,"result":"0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003a68747470733a2f2f6c6976652d2d2d6d657461646174612d35636f767071696a61612d75632e612e72756e2e6170702f6d657461646174612f31000000000000"
|
145
|
+
}
|
146
|
+
```
|
147
|
+
|
148
|
+
...returns: `https://live---metadata-5covpqijaa-uc.a.run.app/metadata/1`
|
149
|
+
|
150
|
+
|
151
|
+
|
152
|
+
### JSON RPC eth_call With ContractMethod Helper
|
153
|
+
|
154
|
+
Let's retry using the convenience builtin
|
155
|
+
`ContractMethod` helper:
|
156
|
+
|
157
|
+
```ruby
|
158
|
+
## contract address - let's try moonbirds
|
159
|
+
contract_address = '0x23581767a106ae21c074b2276d25e5c3e136a68b'
|
160
|
+
|
161
|
+
ETH_tokenURI = Ethlite::ContractMethod.new( 'tokenURI',
|
162
|
+
inputs: ['uint256'],
|
163
|
+
outputs: ['string'] )
|
164
|
+
|
165
|
+
token_ids = (0..9)
|
166
|
+
token_ids.each do |token_id|
|
167
|
+
puts "==> tokenURI(#{token_id}) returns:"
|
168
|
+
pp ETH_tokenURI.do_call( ETH_NODE, contract_address, [token_id] )
|
169
|
+
end
|
170
|
+
```
|
171
|
+
|
172
|
+
resulting in:
|
173
|
+
|
174
|
+
```
|
175
|
+
==> tokenURI(0) returns:
|
176
|
+
"https://live---metadata-5covpqijaa-uc.a.run.app/metadata/0"
|
177
|
+
==> tokenURI(1) returns:
|
178
|
+
"https://live---metadata-5covpqijaa-uc.a.run.app/metadata/1"
|
179
|
+
==> tokenURI(2) returns:
|
180
|
+
"https://live---metadata-5covpqijaa-uc.a.run.app/metadata/3"
|
181
|
+
...
|
182
|
+
```
|
183
|
+
|
184
|
+
|
185
|
+
And so on and so forth.
|
18
186
|
|
19
187
|
|
20
188
|
|
data/Rakefile
CHANGED
data/lib/ethlite/abi/utils.rb
CHANGED
@@ -56,44 +56,50 @@ module Abi
|
|
56
56
|
end
|
57
57
|
|
58
58
|
def to_signed(i)
|
59
|
-
i >
|
59
|
+
i > INT_MAX ? (i-TT256) : i
|
60
60
|
end
|
61
61
|
|
62
|
-
def base58_check_to_bytes(s)
|
63
|
-
leadingzbytes = s.match(/\A1*/)[0]
|
64
|
-
data = Constant::BYTE_ZERO * leadingzbytes.size + BaseConvert.convert(s, 58, 256)
|
65
|
-
|
66
|
-
raise ChecksumError, "double sha256 checksum doesn't match" unless double_sha256(data[0...-4])[0,4] == data[-4..-1]
|
67
|
-
data[1...-4]
|
68
|
-
end
|
69
|
-
|
70
|
-
def bytes_to_base58_check(bytes, magicbyte=0)
|
71
|
-
bs = "#{magicbyte.chr}#{bytes}"
|
72
|
-
leadingzbytes = bs.match(/\A#{Constant::BYTE_ZERO}*/)[0]
|
73
|
-
checksum = double_sha256(bs)[0,4]
|
74
|
-
'1'*leadingzbytes.size + BaseConvert.convert("#{bs}#{checksum}", 256, 58)
|
75
|
-
end
|
76
62
|
|
77
63
|
def ceil32(x)
|
78
64
|
x % 32 == 0 ? x : (x + 32 - x%32)
|
79
65
|
end
|
80
66
|
|
81
67
|
def encode_hex(b)
|
82
|
-
|
68
|
+
raise TypeError, "Value must be an instance of String" unless b.instance_of?(String)
|
69
|
+
b.unpack("H*").first
|
70
|
+
end
|
71
|
+
|
72
|
+
def decode_hex(str)
|
73
|
+
raise TypeError, "Value must be an instance of string" unless str.instance_of?(String)
|
74
|
+
raise TypeError, 'Non-hexadecimal digit found' unless str =~ /\A[0-9a-fA-F]*\z/
|
75
|
+
[str].pack("H*")
|
83
76
|
end
|
84
77
|
|
85
|
-
|
86
|
-
|
78
|
+
|
79
|
+
|
80
|
+
|
81
|
+
def int_to_big_endian(n)
|
82
|
+
RLP::Sedes.big_endian_int.serialize n
|
87
83
|
end
|
88
84
|
|
89
85
|
def big_endian_to_int(s)
|
90
86
|
RLP::Sedes.big_endian_int.deserialize s.sub(/\A(\x00)+/, '')
|
91
87
|
end
|
92
88
|
|
93
|
-
|
94
|
-
|
89
|
+
|
90
|
+
def encode_int(n)
|
91
|
+
raise ArgumentError, "Integer invalid or out of range: #{n}" unless n.is_a?(Integer) && n >= 0 && n <= UINT_MAX
|
92
|
+
int_to_big_endian n
|
93
|
+
end
|
94
|
+
|
95
|
+
def decode_int(v)
|
96
|
+
raise ArgumentError, "No leading zero bytes allowed for integers" if v.size > 0 && (v[0] == BYTE_ZERO || v[0] == 0)
|
97
|
+
big_endian_to_int v
|
95
98
|
end
|
96
99
|
|
100
|
+
|
101
|
+
|
102
|
+
|
97
103
|
def lpad(x, symbol, l)
|
98
104
|
return x if x.size >= l
|
99
105
|
symbol * (l - x.size) + x
|
@@ -124,15 +130,6 @@ module Abi
|
|
124
130
|
zpad_int x, 20
|
125
131
|
end
|
126
132
|
|
127
|
-
def encode_int(n)
|
128
|
-
raise ArgumentError, "Integer invalid or out of range: #{n}" unless n.is_a?(Integer) && n >= 0 && n <= UINT_MAX
|
129
|
-
int_to_big_endian n
|
130
|
-
end
|
131
|
-
|
132
|
-
def decode_int(v)
|
133
|
-
raise ArgumentError, "No leading zero bytes allowed for integers" if v.size > 0 && (v[0] == Constant::BYTE_ZERO || v[0] == 0)
|
134
|
-
big_endian_to_int v
|
135
|
-
end
|
136
133
|
|
137
134
|
def bytearray_to_int(arr)
|
138
135
|
o = 0
|
@@ -148,6 +145,7 @@ module Abi
|
|
148
145
|
bytes.unpack('C*')
|
149
146
|
end
|
150
147
|
|
148
|
+
|
151
149
|
def coerce_to_int(x)
|
152
150
|
if x.is_a?(Numeric)
|
153
151
|
x
|
@@ -178,19 +176,6 @@ module Abi
|
|
178
176
|
end
|
179
177
|
end
|
180
178
|
|
181
|
-
def normalize_address(x, allow_blank: false)
|
182
|
-
address = Address.new(x)
|
183
|
-
raise ValueError, "address is blank" if !allow_blank && address.blank?
|
184
|
-
address.to_bytes
|
185
|
-
end
|
186
|
-
|
187
|
-
def mk_contract_address(sender, nonce)
|
188
|
-
keccak256_rlp([normalize_address(sender), nonce])[12..-1]
|
189
|
-
end
|
190
|
-
|
191
|
-
def mk_metropolis_contract_address(sender, initcode)
|
192
|
-
keccak256(normalize_address(sender) + initcode)[12..-1]
|
193
|
-
end
|
194
179
|
|
195
180
|
|
196
181
|
def parse_int_or_hex(s)
|
@@ -203,6 +188,24 @@ module Abi
|
|
203
188
|
end
|
204
189
|
end
|
205
190
|
|
191
|
+
|
192
|
+
=begin
|
193
|
+
## add? moved over from the old module Utility
|
194
|
+
def hex( num )
|
195
|
+
'0x' + num.to_s(16)
|
196
|
+
end
|
197
|
+
|
198
|
+
def from_hex( h )
|
199
|
+
h.nil? ? 0 : (h.kind_of?(String) ? h.to_i(16) : h)
|
200
|
+
end
|
201
|
+
=end
|
202
|
+
|
203
|
+
|
204
|
+
def remove_0x_head( s )
|
205
|
+
return s if !s || s.length<2
|
206
|
+
s[0,2] == '0x' ? s[2..-1] : s
|
207
|
+
end
|
208
|
+
|
206
209
|
def normalize_hex_without_prefix(s)
|
207
210
|
if s[0,2] == '0x'
|
208
211
|
(s.size % 2 == 1 ? '0' : '') + s[2..-1]
|
@@ -211,6 +214,7 @@ module Abi
|
|
211
214
|
end
|
212
215
|
end
|
213
216
|
|
217
|
+
|
214
218
|
def function_signature method_name, arg_types
|
215
219
|
"#{method_name}(#{arg_types.join(',')})"
|
216
220
|
end
|
data/lib/ethlite/constant.rb
CHANGED
@@ -2,9 +2,15 @@
|
|
2
2
|
module Ethlite
|
3
3
|
module Constant
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
|
6
|
+
## todo/check - use encoding -ascii-8bit for source file or ? - why? why not?
|
7
|
+
## use #b/.b to ensure binary encoding? - why? why not?
|
8
|
+
|
9
|
+
## todo/check: use auto-freeze string literals magic comment - why? why not?
|
10
|
+
BYTE_EMPTY = "".b.freeze
|
11
|
+
BYTE_ZERO = "\x00".b.freeze
|
12
|
+
BYTE_ONE = "\x01".b.freeze
|
13
|
+
|
8
14
|
|
9
15
|
TT32 = 2**32
|
10
16
|
TT40 = 2**40
|
@@ -17,35 +23,16 @@ module Ethlite
|
|
17
23
|
INT_MAX = 2**255 - 1
|
18
24
|
INT_MIN = -2**255
|
19
25
|
|
20
|
-
HASH_ZERO = ("\x00"*32).freeze
|
26
|
+
HASH_ZERO = ("\x00"*32).b.freeze
|
21
27
|
|
22
28
|
|
23
|
-
PUBKEY_ZERO = ("\x00"*32).freeze
|
24
|
-
PRIVKEY_ZERO = ("\x00"*32).freeze
|
29
|
+
PUBKEY_ZERO = ("\x00"*32).b.freeze
|
30
|
+
PRIVKEY_ZERO = ("\x00"*32).b.freeze
|
31
|
+
|
25
32
|
PRIVKEY_ZERO_HEX = ('0'*64).freeze
|
26
33
|
|
27
34
|
CONTRACT_CODE_SIZE_LIMIT = 0x6000
|
28
35
|
|
29
36
|
|
30
|
-
=begin
|
31
|
-
# The RLP short length limit.
|
32
|
-
SHORT_LENGTH_LIMIT = 56.freeze
|
33
|
-
|
34
|
-
# The RLP long length limit.
|
35
|
-
LONG_LENGTH_LIMIT = (256 ** 8).freeze
|
36
|
-
|
37
|
-
# The RLP primitive type offset.
|
38
|
-
PRIMITIVE_PREFIX_OFFSET = 0x80.freeze
|
39
|
-
|
40
|
-
# The RLP array type offset.
|
41
|
-
LIST_PREFIX_OFFSET = 0xc0.freeze
|
42
|
-
|
43
|
-
# The binary encoding is ASCII (8-bit).
|
44
|
-
BINARY_ENCODING = "ASCII-8BIT".freeze
|
45
|
-
|
46
|
-
# Infinity as constant for convenience.
|
47
|
-
INFINITY = (1.0 / 0.0).freeze
|
48
|
-
|
49
|
-
=end
|
50
37
|
end # module Constant
|
51
38
|
end # module Ethlite
|
data/lib/ethlite/contract.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
module Ethlite
|
2
2
|
class ContractMethod
|
3
|
-
include Utility
|
4
|
-
|
5
3
|
|
6
4
|
def self.parse_abi( abi )
|
7
5
|
## convenience helper - auto-convert to json if string passed in
|
@@ -31,8 +29,7 @@
|
|
31
29
|
|
32
30
|
|
33
31
|
|
34
|
-
attr_reader :
|
35
|
-
:signature,
|
32
|
+
attr_reader :signature,
|
36
33
|
:name,
|
37
34
|
:signature_hash,
|
38
35
|
:input_types,
|
@@ -66,7 +63,8 @@
|
|
66
63
|
puts "response:"
|
67
64
|
pp response
|
68
65
|
|
69
|
-
string_data =
|
66
|
+
string_data = Abi::Utils.decode_hex(
|
67
|
+
Abi::Utils.remove_0x_head(response))
|
70
68
|
return nil if string_data.empty?
|
71
69
|
|
72
70
|
result = Abi::AbiCoder.decode_abi( @output_types, string_data )
|
data/lib/ethlite/version.rb
CHANGED
data/lib/ethlite.rb
CHANGED
@@ -10,7 +10,7 @@ require 'openssl'
|
|
10
10
|
require 'digest'
|
11
11
|
|
12
12
|
## 3rd party gems
|
13
|
-
require 'rlp'
|
13
|
+
require 'rlp-lite'
|
14
14
|
|
15
15
|
## bundled require 'digest/keccak' ## gem keccak - see https://rubygems.org/gems/keccak
|
16
16
|
require_relative 'digest/keccak'
|
@@ -31,7 +31,6 @@ require_relative 'ethlite/abi/utils'
|
|
31
31
|
require_relative 'ethlite/abi/abi_coder'
|
32
32
|
|
33
33
|
|
34
|
-
require_relative 'ethlite/utility'
|
35
34
|
require_relative 'ethlite/contract'
|
36
35
|
|
37
36
|
|
data/lib/jsonrpc/jsonrpc.rb
CHANGED
@@ -9,49 +9,43 @@
|
|
9
9
|
|
10
10
|
class JsonRpc
|
11
11
|
def initialize( uri )
|
12
|
-
@
|
13
|
-
|
14
|
-
@uri = URI.parse( uri )
|
12
|
+
@uri = uri ## assume uri always as string for now
|
13
|
+
@request_id = 1
|
15
14
|
end
|
16
15
|
|
17
16
|
|
18
17
|
def request( method, params=[] )
|
19
|
-
opts = {}
|
20
|
-
if @uri.instance_of?( URI::HTTPS )
|
21
|
-
opts[:use_ssl] = true
|
22
|
-
opts[:verify_mode] = OpenSSL::SSL::VERIFY_NONE
|
23
|
-
end
|
24
|
-
|
25
|
-
Net::HTTP.start( @uri.host, @uri.port, **opts ) do |http|
|
26
|
-
headers = {"Content-Type" => "application/json"}
|
27
|
-
request = Net::HTTP::Post.new( @uri.request_uri, headers )
|
28
18
|
|
29
|
-
|
19
|
+
data = { jsonrpc: '2.0',
|
30
20
|
method: method,
|
31
21
|
params: params,
|
32
|
-
id: @
|
22
|
+
id: @request_id }
|
23
|
+
|
24
|
+
@request_id += 1
|
33
25
|
|
34
|
-
puts "
|
35
|
-
puts
|
26
|
+
puts "json_rpc POST payload:"
|
27
|
+
puts data.to_json
|
36
28
|
|
37
|
-
|
38
|
-
response = http.request( request )
|
29
|
+
response = Webclient.post( @uri, json: data )
|
39
30
|
|
40
|
-
|
41
|
-
|
31
|
+
|
32
|
+
if response.status.nok?
|
33
|
+
raise "Error code #{response.status.code} on request #{@uri} #{data}"
|
42
34
|
end
|
43
35
|
|
36
|
+
puts "json_rpc response.body:"
|
37
|
+
puts response.body
|
38
|
+
|
44
39
|
|
45
40
|
body = JSON.parse( response.body, max_nesting: 1500 )
|
46
41
|
|
47
42
|
if body['result']
|
48
43
|
body['result']
|
49
44
|
elsif body['error']
|
50
|
-
raise "Error #{@uri
|
45
|
+
raise "Error #{@uri} #{body['error']} on request #{@uri} #{data}"
|
51
46
|
else
|
52
|
-
raise "No response on request #{@uri
|
47
|
+
raise "No response on request #{@uri} #{data}"
|
53
48
|
end
|
54
|
-
|
55
|
-
end
|
49
|
+
end # method request
|
56
50
|
end # class JsonRpc
|
57
51
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ethlite
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gerald Bauer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-11-
|
11
|
+
date: 2022-11-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: cocos
|
@@ -25,7 +25,7 @@ dependencies:
|
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name: rlp
|
28
|
+
name: rlp-lite
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
@@ -94,7 +94,6 @@ files:
|
|
94
94
|
- lib/ethlite/abi/utils.rb
|
95
95
|
- lib/ethlite/constant.rb
|
96
96
|
- lib/ethlite/contract.rb
|
97
|
-
- lib/ethlite/utility.rb
|
98
97
|
- lib/ethlite/version.rb
|
99
98
|
- lib/jsonrpc/jsonrpc.rb
|
100
99
|
homepage: https://github.com/pixelartexchange/artbase
|
data/lib/ethlite/utility.rb
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
module Ethlite
|
2
|
-
|
3
|
-
module Utility
|
4
|
-
|
5
|
-
def hex( num )
|
6
|
-
'0x' + num.to_s(16)
|
7
|
-
end
|
8
|
-
|
9
|
-
def from_hex( h )
|
10
|
-
h.nil? ? 0 : (h.kind_of?(String) ? h.to_i(16) : h)
|
11
|
-
end
|
12
|
-
|
13
|
-
def remove_0x_head( s )
|
14
|
-
return s if !s || s.length<2
|
15
|
-
s[0,2] == '0x' ? s[2..-1] : s
|
16
|
-
end
|
17
|
-
|
18
|
-
|
19
|
-
def wei_to_ether( wei )
|
20
|
-
1.0 * wei / 10**18
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end # module Ethlite
|