erpc-sdk 0.9.0 → 0.11.0
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/LICENSES/Apache-2.0.txt +201 -0
- data/LICENSES/BSD-3-Clause-Google-Protobuf.txt +29 -0
- data/README.md +50 -7
- data/THIRD_PARTY_NOTICES.md +41 -0
- data/lib/erpc_sdk/arbitrum.rb +62 -0
- data/lib/erpc_sdk/arc.rb +33 -0
- data/lib/erpc_sdk/base.rb +333 -0
- data/lib/erpc_sdk/bitcoin.rb +126 -0
- data/lib/erpc_sdk/bitcoin_codec.rb +574 -0
- data/lib/erpc_sdk/bitcoin_transport.rb +369 -0
- data/lib/erpc_sdk/bsc.rb +33 -0
- data/lib/erpc_sdk/client.rb +109 -1
- data/lib/erpc_sdk/config.rb +168 -5
- data/lib/erpc_sdk/errors.rb +31 -1
- data/lib/erpc_sdk/generated/rpc_network_contract.rb +3196 -0
- data/lib/erpc_sdk/hyperliquid.rb +33 -0
- data/lib/erpc_sdk/kaia.rb +33 -0
- data/lib/erpc_sdk/monad.rb +33 -0
- data/lib/erpc_sdk/near.rb +276 -0
- data/lib/erpc_sdk/near_transport.rb +345 -0
- data/lib/erpc_sdk/optimism.rb +33 -0
- data/lib/erpc_sdk/polygon.rb +33 -0
- data/lib/erpc_sdk/robinhood.rb +33 -0
- data/lib/erpc_sdk/soneium.rb +33 -0
- data/lib/erpc_sdk/sui.rb +5 -0
- data/lib/erpc_sdk/sui_grpc_web.rb +226 -0
- data/lib/erpc_sdk/sui_proto.rb +370 -0
- data/lib/erpc_sdk/transport.rb +28 -0
- data/lib/erpc_sdk/tron.rb +33 -0
- data/lib/erpc_sdk/version.rb +1 -1
- data/lib/erpc_sdk.rb +21 -0
- metadata +57 -7
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "bigdecimal"
|
|
4
|
+
require "json"
|
|
5
|
+
require "timeout"
|
|
6
|
+
require "uri"
|
|
7
|
+
|
|
8
|
+
require_relative "config"
|
|
9
|
+
require_relative "errors"
|
|
10
|
+
require_relative "transport"
|
|
11
|
+
|
|
12
|
+
module ERPC
|
|
13
|
+
NearTransportFacts = Struct.new(:hosted_target, :method_names, keyword_init: true) do
|
|
14
|
+
def initialize(hosted_target:, method_names:)
|
|
15
|
+
super(hosted_target: hosted_target.to_s.freeze, method_names: method_names.map { |name| name.to_s.dup.freeze }.freeze)
|
|
16
|
+
freeze
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
module NearContract
|
|
21
|
+
module_function
|
|
22
|
+
|
|
23
|
+
def facts_from_contract(contract)
|
|
24
|
+
client = contract.fetch("clientContracts").find { |value| value["clientContractId"] == "client-near-rpc" }
|
|
25
|
+
method_set_id = client.fetch("methodSetId")
|
|
26
|
+
hosted = client.fetch("endpointModes").find { |value| value["mode"] == "hosted" }
|
|
27
|
+
method_set = contract.fetch("methodSets").find { |value| value["methodSetId"] == method_set_id }
|
|
28
|
+
NearTransportFacts.new(
|
|
29
|
+
hosted_target: hosted.fetch("defaultTarget"),
|
|
30
|
+
method_names: method_set.fetch("capabilities").map { |item| item.fetch("wireOperation") }
|
|
31
|
+
)
|
|
32
|
+
rescue KeyError, NoMethodError, TypeError
|
|
33
|
+
raise ConfigError, "NEAR contract facts are unavailable", cause: nil
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
module NearTokenScanner
|
|
38
|
+
module_function
|
|
39
|
+
|
|
40
|
+
NUMBER = /\A-?(?:0|[1-9][0-9]*)(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?\z/.freeze
|
|
41
|
+
|
|
42
|
+
def known_integer_tokens!(text, method)
|
|
43
|
+
tokens = scan(text)
|
|
44
|
+
paths = case method
|
|
45
|
+
when "status"
|
|
46
|
+
[["result", "latest_protocol_version"], ["result", "protocol_version"], ["result", "sync_info", "latest_block_height"]]
|
|
47
|
+
when "block"
|
|
48
|
+
[["result", "header", "height"], ["result", "header", "timestamp"]]
|
|
49
|
+
when "query"
|
|
50
|
+
[["result", "storage_usage"], ["result", "block_height"], ["result", "storage_paid_at"], ["result", "bootstrap_nonce"]]
|
|
51
|
+
else
|
|
52
|
+
[]
|
|
53
|
+
end
|
|
54
|
+
paths.each do |path|
|
|
55
|
+
raw = tokens[path]
|
|
56
|
+
next if raw.nil?
|
|
57
|
+
unless raw.match?(/\A(?:0|[1-9][0-9]*)\z/) && raw.to_i <= 18_446_744_073_709_551_615
|
|
58
|
+
raise InvalidResponseError.new("ERPC returned an invalid NEAR response"), cause: nil
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
nil
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def scan(text)
|
|
65
|
+
scanner = Scanner.new(text)
|
|
66
|
+
scanner.run
|
|
67
|
+
rescue InvalidResponseError
|
|
68
|
+
raise
|
|
69
|
+
rescue StandardError
|
|
70
|
+
raise InvalidResponseError.new("ERPC returned an invalid NEAR response"), cause: nil
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
class Scanner
|
|
74
|
+
def initialize(text)
|
|
75
|
+
@text = text; @index = 0; @tokens = {}
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def run
|
|
79
|
+
skip; value([]); skip
|
|
80
|
+
raise_invalid! unless @index == @text.length
|
|
81
|
+
@tokens
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
private
|
|
85
|
+
|
|
86
|
+
def value(path)
|
|
87
|
+
@tokens.delete_if { |candidate, _| candidate.length >= path.length && candidate.first(path.length) == path }
|
|
88
|
+
skip; raise_invalid! if @index >= @text.length
|
|
89
|
+
case @text[@index]
|
|
90
|
+
when '"' then string
|
|
91
|
+
when "{" then object(path)
|
|
92
|
+
when "[" then array(path)
|
|
93
|
+
when "-", /[0-9]/ then number(path)
|
|
94
|
+
when "t" then literal("true")
|
|
95
|
+
when "f" then literal("false")
|
|
96
|
+
when "n" then literal("null")
|
|
97
|
+
else raise_invalid!
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def object(path)
|
|
102
|
+
@index += 1; skip
|
|
103
|
+
if @text[@index] == "}"
|
|
104
|
+
@index += 1; return
|
|
105
|
+
end
|
|
106
|
+
loop do
|
|
107
|
+
raise_invalid! unless @text[@index] == '"'
|
|
108
|
+
key_start = @index; string
|
|
109
|
+
key = JSON.parse(@text[key_start...@index], create_additions: false)
|
|
110
|
+
skip; raise_invalid! unless @text[@index] == ":"; @index += 1
|
|
111
|
+
value(path + [key]); skip
|
|
112
|
+
if @text[@index] == ","
|
|
113
|
+
@index += 1; skip
|
|
114
|
+
elsif @text[@index] == "}"
|
|
115
|
+
@index += 1; break
|
|
116
|
+
else
|
|
117
|
+
raise_invalid!
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def array(path)
|
|
123
|
+
@index += 1; skip; position = 0
|
|
124
|
+
if @text[@index] == "]"
|
|
125
|
+
@index += 1; return
|
|
126
|
+
end
|
|
127
|
+
loop do
|
|
128
|
+
value(path + [position]); position += 1; skip
|
|
129
|
+
if @text[@index] == ","
|
|
130
|
+
@index += 1; skip
|
|
131
|
+
elsif @text[@index] == "]"
|
|
132
|
+
@index += 1; break
|
|
133
|
+
else
|
|
134
|
+
raise_invalid!
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def string
|
|
140
|
+
raise_invalid! unless @text[@index] == '"'; @index += 1
|
|
141
|
+
while @index < @text.length
|
|
142
|
+
char = @text[@index]
|
|
143
|
+
if char == '"'
|
|
144
|
+
@index += 1; return
|
|
145
|
+
elsif char == "\\"
|
|
146
|
+
@index += 1; raise_invalid! if @index >= @text.length
|
|
147
|
+
if @text[@index] == "u"
|
|
148
|
+
4.times { @index += 1; raise_invalid! if @index >= @text.length || !@text[@index].match?(/[0-9A-Fa-f]/) }
|
|
149
|
+
elsif !%w[" \\ / b f n r t].include?(@text[@index])
|
|
150
|
+
raise_invalid!
|
|
151
|
+
end
|
|
152
|
+
elsif char.ord < 0x20
|
|
153
|
+
raise_invalid!
|
|
154
|
+
end
|
|
155
|
+
@index += 1
|
|
156
|
+
end
|
|
157
|
+
raise_invalid!
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def number(path)
|
|
161
|
+
start = @index
|
|
162
|
+
@index += 1 if @text[@index] == "-"
|
|
163
|
+
if @text[@index] == "0"
|
|
164
|
+
@index += 1; raise_invalid! if @text[@index]&.match?(/[0-9]/)
|
|
165
|
+
elsif @text[@index]&.match?(/[1-9]/)
|
|
166
|
+
@index += 1 while @text[@index]&.match?(/[0-9]/)
|
|
167
|
+
else
|
|
168
|
+
raise_invalid!
|
|
169
|
+
end
|
|
170
|
+
if @text[@index] == "."
|
|
171
|
+
@index += 1; start_fraction = @index; @index += 1 while @text[@index]&.match?(/[0-9]/); raise_invalid! if start_fraction == @index
|
|
172
|
+
end
|
|
173
|
+
if %w[e E].include?(@text[@index])
|
|
174
|
+
@index += 1; @index += 1 if %w[+ -].include?(@text[@index]); start_exp = @index
|
|
175
|
+
@index += 1 while @text[@index]&.match?(/[0-9]/); raise_invalid! if start_exp == @index
|
|
176
|
+
end
|
|
177
|
+
raw = @text[start...@index]
|
|
178
|
+
raise_invalid! unless raw.match?(NUMBER)
|
|
179
|
+
@tokens[path] = raw
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def literal(value)
|
|
183
|
+
raise_invalid! unless @text[@index, value.length] == value
|
|
184
|
+
@index += value.length
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def skip
|
|
188
|
+
@index += 1 while @index < @text.length && " \t\r\n".include?(@text[@index])
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def raise_invalid!
|
|
192
|
+
raise InvalidResponseError.new("ERPC returned an invalid NEAR response"), cause: nil
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
private_constant :Scanner
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
NEAR_TRANSPORT_FACTS = NearContract.facts_from_contract(RPC_NETWORK_CONTRACT)
|
|
199
|
+
NEAR_RPC_METHODS = NEAR_TRANSPORT_FACTS.method_names
|
|
200
|
+
private_constant :NEAR_TRANSPORT_FACTS
|
|
201
|
+
|
|
202
|
+
class NearHttpTransport
|
|
203
|
+
attr_reader :method_names
|
|
204
|
+
|
|
205
|
+
def initialize(facts:, api_key: nil, endpoint: nil, direct_endpoint: nil, headers: {}, timeout: DEFAULT_TIMEOUT,
|
|
206
|
+
adapter: NetHttpAdapter.new, namespace: "near.rpc")
|
|
207
|
+
@facts = facts
|
|
208
|
+
@method_names = facts.method_names
|
|
209
|
+
@api_key = api_key.is_a?(String) && !api_key.strip.empty? ? api_key.strip : nil
|
|
210
|
+
@timeout = timeout.to_f
|
|
211
|
+
raise ConfigError, "timeout must be positive", cause: nil unless @timeout.positive?
|
|
212
|
+
@adapter = adapter
|
|
213
|
+
@namespace = namespace.to_s.freeze
|
|
214
|
+
@mutex = Mutex.new
|
|
215
|
+
@next_id = 0
|
|
216
|
+
@available = false
|
|
217
|
+
@direct = !direct_endpoint.nil?
|
|
218
|
+
|
|
219
|
+
if direct_endpoint
|
|
220
|
+
unless direct_endpoint.is_a?(RpcEndpointConfig)
|
|
221
|
+
raise ConfigError, "near_rpc must use RpcEndpointConfig", cause: nil
|
|
222
|
+
end
|
|
223
|
+
raise ConfigError, "near_rpc does not support WebSocket URLs", cause: nil if direct_endpoint.websocket_url
|
|
224
|
+
@target = validate_url(direct_endpoint.http_url)
|
|
225
|
+
@headers = direct_endpoint.headers.dup
|
|
226
|
+
@redactions = Redaction.send(:direct_variants_with_path, http_url: direct_endpoint.http_url, headers: direct_endpoint.headers)
|
|
227
|
+
@available = true
|
|
228
|
+
elsif @api_key
|
|
229
|
+
@target = hosted_target(endpoint || facts.hosted_target)
|
|
230
|
+
@headers = headers.to_h.dup
|
|
231
|
+
@redactions = [@api_key]
|
|
232
|
+
@available = true
|
|
233
|
+
else
|
|
234
|
+
@target = nil
|
|
235
|
+
@headers = {}
|
|
236
|
+
@redactions = []
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
def endpoint
|
|
241
|
+
return "" unless @available
|
|
242
|
+
|
|
243
|
+
uri = URI.parse(@target)
|
|
244
|
+
uri.path = "/"
|
|
245
|
+
uri.query = nil
|
|
246
|
+
uri.fragment = nil
|
|
247
|
+
uri.to_s
|
|
248
|
+
rescue URI::InvalidURIError
|
|
249
|
+
""
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
def inspect
|
|
253
|
+
"#<#{self.class} endpoint=#{endpoint.inspect} header_names=#{safe_header_names.inspect}>"
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
def request(method, params)
|
|
257
|
+
raise ConfigError, "NEAR method is not in the accepted read contract", cause: nil unless @method_names.include?(method)
|
|
258
|
+
raise NotConfiguredError, @namespace unless @available
|
|
259
|
+
|
|
260
|
+
id = @mutex.synchronize { @next_id += 1 }
|
|
261
|
+
body = JSON.generate("jsonrpc" => "2.0", "id" => id, "method" => method, "params" => params)
|
|
262
|
+
response = nil
|
|
263
|
+
Timeout.timeout(@timeout) do
|
|
264
|
+
response = @adapter.request(method: :post, url: @target, headers: request_headers, body: body, timeout: @timeout)
|
|
265
|
+
end
|
|
266
|
+
raise HttpError, response.status unless response.respond_to?(:status) && response.status.to_i.between?(200, 299)
|
|
267
|
+
decode(response.body.to_s, id, method)
|
|
268
|
+
rescue ::Timeout::Error
|
|
269
|
+
raise TimeoutError, @timeout, cause: nil
|
|
270
|
+
rescue InvalidResponseError, JsonRpcError, HttpError, NotConfiguredError, ConfigError, TimeoutError, TransportError
|
|
271
|
+
raise
|
|
272
|
+
rescue JSON::ParserError, JSON::GeneratorError, ArgumentError, TypeError
|
|
273
|
+
raise InvalidResponseError.new("ERPC returned an invalid NEAR response"), cause: nil
|
|
274
|
+
rescue IOError, EOFError, SocketError, SystemCallError, Net::OpenTimeout, Net::ReadTimeout, Net::WriteTimeout
|
|
275
|
+
raise TransportError, "Unable to reach ERPC", cause: nil
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
private
|
|
279
|
+
|
|
280
|
+
def validate_url(value)
|
|
281
|
+
input = value.to_s
|
|
282
|
+
uri = URI.parse(input)
|
|
283
|
+
valid = uri.absolute? && uri.host && %w[http https].include?(uri.scheme) && !input.include?("#") && !input.match?(%r{://[^/?#]*@})
|
|
284
|
+
raise ConfigError, "HTTP endpoint must be an absolute HTTP(S) URL", cause: nil unless valid
|
|
285
|
+
input.freeze
|
|
286
|
+
rescue URI::InvalidURIError, ArgumentError
|
|
287
|
+
raise ConfigError, "HTTP endpoint must be an absolute HTTP(S) URL", cause: nil
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
def hosted_target(value)
|
|
291
|
+
uri = URI.parse(validate_url(value))
|
|
292
|
+
query = URI.decode_www_form(uri.query.to_s).reject { |key, _| key.casecmp?("api-key") }
|
|
293
|
+
query << ["api-key", @api_key]
|
|
294
|
+
uri.query = URI.encode_www_form(query)
|
|
295
|
+
uri.fragment = nil
|
|
296
|
+
uri.to_s
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
def request_headers
|
|
300
|
+
values = @headers.dup
|
|
301
|
+
values.delete_if { |key, _| %w[accept content-type].include?(key.to_s.downcase) }
|
|
302
|
+
values["accept"] = "application/json"
|
|
303
|
+
values["content-type"] = "application/json"
|
|
304
|
+
values
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
def safe_header_names
|
|
308
|
+
@headers.keys.map(&:to_s).sort
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
def decode(text, expected_id, method)
|
|
312
|
+
NearTokenScanner.known_integer_tokens!(text, method)
|
|
313
|
+
decimal_class = Class.new do
|
|
314
|
+
define_singleton_method(:new) do |raw|
|
|
315
|
+
value = BigDecimal(raw)
|
|
316
|
+
zero_token = raw.match?(/\A-?(?:0+\.?0*|0*\.0+)(?:[eE][+-]?\d+)?\z/)
|
|
317
|
+
raise InvalidResponseError.new("ERPC returned an invalid NEAR response"), cause: nil unless value.finite? && (zero_token || !value.zero?)
|
|
318
|
+
value
|
|
319
|
+
rescue InvalidResponseError
|
|
320
|
+
raise
|
|
321
|
+
rescue StandardError
|
|
322
|
+
raise InvalidResponseError.new("ERPC returned an invalid NEAR response"), cause: nil
|
|
323
|
+
end
|
|
324
|
+
end
|
|
325
|
+
response = JSON.parse(text, create_additions: false, allow_nan: false, decimal_class: decimal_class)
|
|
326
|
+
raise InvalidResponseError.new("ERPC returned an invalid NEAR response"), cause: nil unless response.is_a?(Hash) && response["id"] == expected_id
|
|
327
|
+
if response.key?("error") && !response["error"].nil?
|
|
328
|
+
error = response["error"]
|
|
329
|
+
unless error.is_a?(Hash) && error["code"].is_a?(Integer) && error["message"].is_a?(String)
|
|
330
|
+
raise InvalidResponseError.new("ERPC returned an invalid NEAR response"), cause: nil
|
|
331
|
+
end
|
|
332
|
+
data = error.key?("data") ? Redaction.value(error["data"], @redactions) : nil
|
|
333
|
+
raise JsonRpcError.new(error["code"], Redaction.text(error["message"], @redactions), data), cause: nil
|
|
334
|
+
end
|
|
335
|
+
raise InvalidResponseError.new("ERPC returned an invalid NEAR response"), cause: nil unless response.key?("result")
|
|
336
|
+
response["result"]
|
|
337
|
+
rescue InvalidResponseError, JsonRpcError
|
|
338
|
+
raise
|
|
339
|
+
rescue JSON::ParserError, JSON::NestingError, ArgumentError, TypeError, SystemStackError
|
|
340
|
+
raise InvalidResponseError.new("ERPC returned an invalid NEAR response"), cause: nil
|
|
341
|
+
end
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
private_constant :NearTransportFacts, :NearContract, :NearTokenScanner, :NearHttpTransport
|
|
345
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "base"
|
|
4
|
+
|
|
5
|
+
module ERPC
|
|
6
|
+
OPTIMISM_TRANSPORT_FACTS = SealedEvmContract.facts_from_contract(RPC_NETWORK_CONTRACT, "client-optimism-rpc")
|
|
7
|
+
OPTIMISM_RPC_METHODS = OPTIMISM_TRANSPORT_FACTS.method_names
|
|
8
|
+
private_constant :OPTIMISM_TRANSPORT_FACTS
|
|
9
|
+
|
|
10
|
+
class OptimismRpc < BaseRpc
|
|
11
|
+
alias_method :endpoint, :endpoint
|
|
12
|
+
alias_method :eth_chain_id, :eth_chain_id
|
|
13
|
+
alias_method :eth_get_balance, :eth_get_balance
|
|
14
|
+
alias_method :eth_call, :eth_call
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
class OptimismClient
|
|
18
|
+
attr_reader :rpc
|
|
19
|
+
|
|
20
|
+
def initialize(transport)
|
|
21
|
+
@rpc = OptimismRpc.new(transport)
|
|
22
|
+
freeze
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
module Optimism
|
|
27
|
+
module_function
|
|
28
|
+
|
|
29
|
+
def create_client(transport)
|
|
30
|
+
OptimismClient.new(transport)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "base"
|
|
4
|
+
|
|
5
|
+
module ERPC
|
|
6
|
+
POLYGON_TRANSPORT_FACTS = SealedEvmContract.facts_from_contract(RPC_NETWORK_CONTRACT, "client-polygon-rpc")
|
|
7
|
+
POLYGON_RPC_METHODS = POLYGON_TRANSPORT_FACTS.method_names
|
|
8
|
+
private_constant :POLYGON_TRANSPORT_FACTS
|
|
9
|
+
|
|
10
|
+
class PolygonRpc < BaseRpc
|
|
11
|
+
alias_method :endpoint, :endpoint
|
|
12
|
+
alias_method :eth_chain_id, :eth_chain_id
|
|
13
|
+
alias_method :eth_get_balance, :eth_get_balance
|
|
14
|
+
alias_method :eth_call, :eth_call
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
class PolygonClient
|
|
18
|
+
attr_reader :rpc
|
|
19
|
+
|
|
20
|
+
def initialize(transport)
|
|
21
|
+
@rpc = PolygonRpc.new(transport)
|
|
22
|
+
freeze
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
module Polygon
|
|
27
|
+
module_function
|
|
28
|
+
|
|
29
|
+
def create_client(transport)
|
|
30
|
+
PolygonClient.new(transport)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "base"
|
|
4
|
+
|
|
5
|
+
module ERPC
|
|
6
|
+
ROBINHOOD_TRANSPORT_FACTS = SealedEvmContract.facts_from_contract(RPC_NETWORK_CONTRACT, "client-robinhood-rpc")
|
|
7
|
+
ROBINHOOD_RPC_METHODS = ROBINHOOD_TRANSPORT_FACTS.method_names
|
|
8
|
+
private_constant :ROBINHOOD_TRANSPORT_FACTS
|
|
9
|
+
|
|
10
|
+
class RobinhoodRpc < BaseRpc
|
|
11
|
+
alias_method :endpoint, :endpoint
|
|
12
|
+
alias_method :eth_chain_id, :eth_chain_id
|
|
13
|
+
alias_method :eth_get_balance, :eth_get_balance
|
|
14
|
+
alias_method :eth_call, :eth_call
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
class RobinhoodClient
|
|
18
|
+
attr_reader :rpc
|
|
19
|
+
|
|
20
|
+
def initialize(transport)
|
|
21
|
+
@rpc = RobinhoodRpc.new(transport)
|
|
22
|
+
freeze
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
module Robinhood
|
|
27
|
+
module_function
|
|
28
|
+
|
|
29
|
+
def create_client(transport)
|
|
30
|
+
RobinhoodClient.new(transport)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "base"
|
|
4
|
+
|
|
5
|
+
module ERPC
|
|
6
|
+
SONEIUM_TRANSPORT_FACTS = SealedEvmContract.facts_from_contract(RPC_NETWORK_CONTRACT, "client-soneium-rpc")
|
|
7
|
+
SONEIUM_RPC_METHODS = SONEIUM_TRANSPORT_FACTS.method_names
|
|
8
|
+
private_constant :SONEIUM_TRANSPORT_FACTS
|
|
9
|
+
|
|
10
|
+
class SoneiumRpc < BaseRpc
|
|
11
|
+
alias_method :endpoint, :endpoint
|
|
12
|
+
alias_method :eth_chain_id, :eth_chain_id
|
|
13
|
+
alias_method :eth_get_balance, :eth_get_balance
|
|
14
|
+
alias_method :eth_call, :eth_call
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
class SoneiumClient
|
|
18
|
+
attr_reader :rpc
|
|
19
|
+
|
|
20
|
+
def initialize(transport)
|
|
21
|
+
@rpc = SoneiumRpc.new(transport)
|
|
22
|
+
freeze
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
module Soneium
|
|
27
|
+
module_function
|
|
28
|
+
|
|
29
|
+
def create_client(transport)
|
|
30
|
+
SoneiumClient.new(transport)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|