erpc-sdk 0.5.0 → 0.7.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/README.md +142 -3
- data/lib/erpc_sdk/client.rb +75 -2
- data/lib/erpc_sdk/dex_catalog.rb +207 -0
- data/lib/erpc_sdk/generated/dex_catalog.rb +28 -0
- data/lib/erpc_sdk/generated/token_catalog.rb +216 -0
- data/lib/erpc_sdk/generated/token_rankings.rb +25 -0
- data/lib/erpc_sdk/rpc.rb +94 -6
- data/lib/erpc_sdk/swap.rb +688 -0
- data/lib/erpc_sdk/token_catalog.rb +170 -0
- data/lib/erpc_sdk/token_rankings.rb +50 -0
- data/lib/erpc_sdk/version.rb +1 -1
- data/lib/erpc_sdk.rb +4 -0
- metadata +9 -2
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "generated/token_catalog"
|
|
4
|
+
|
|
5
|
+
module ERPC
|
|
6
|
+
# Canonical CAIP-2 chain identifiers used by the bundled token catalog.
|
|
7
|
+
module TokenChainIDs
|
|
8
|
+
ETHEREUM_MAINNET = TokenCatalogData::TOKEN_CHAIN_IDS.fetch(:ethereum)
|
|
9
|
+
SOLANA_MAINNET = TokenCatalogData::TOKEN_CHAIN_IDS.fetch(:solana)
|
|
10
|
+
AVALANCHE_C_MAINNET = TokenCatalogData::TOKEN_CHAIN_IDS.fetch(:avalanche_c)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# Offline access to the generated token and deployment catalog.
|
|
14
|
+
#
|
|
15
|
+
# All records are static, frozen Ruby values generated from the canonical
|
|
16
|
+
# registry. These methods never create a client, read a file, parse JSON, or
|
|
17
|
+
# access the network.
|
|
18
|
+
module TokenCatalog
|
|
19
|
+
TOKEN_CATALOG_VERSION = TokenCatalogData::TOKEN_CATALOG_VERSION
|
|
20
|
+
TOKEN_CATALOG_AS_OF_DATE = TokenCatalogData::TOKEN_CATALOG_AS_OF_DATE
|
|
21
|
+
TOKEN_CATALOG_CONTENT_DIGEST = TokenCatalogData::TOKEN_CATALOG_CONTENT_DIGEST
|
|
22
|
+
AS_OF_DATE = TOKEN_CATALOG_AS_OF_DATE
|
|
23
|
+
CONTENT_DIGEST = TOKEN_CATALOG_CONTENT_DIGEST
|
|
24
|
+
|
|
25
|
+
TOKEN_CHAIN_IDS = TokenCatalogData::TOKEN_CHAIN_IDS
|
|
26
|
+
TOKEN_ASSETS = TokenCatalogData::TOKEN_ASSETS
|
|
27
|
+
TOKEN_DEPLOYMENTS = TokenCatalogData::TOKEN_DEPLOYMENTS
|
|
28
|
+
TOKEN_ALIASES = TokenCatalogData::TOKEN_ALIASES
|
|
29
|
+
|
|
30
|
+
EMPTY_DEPLOYMENTS = [].freeze
|
|
31
|
+
|
|
32
|
+
ASSETS_BY_ID = TOKEN_ASSETS.each_with_object({}) do |asset, index|
|
|
33
|
+
index[asset.fetch(:asset_id)] = asset
|
|
34
|
+
end.freeze
|
|
35
|
+
|
|
36
|
+
DEPLOYMENTS_BY_ID = TOKEN_DEPLOYMENTS.each_with_object({}) do |deployment, index|
|
|
37
|
+
index[deployment.fetch(:deployment_id)] = deployment
|
|
38
|
+
end.freeze
|
|
39
|
+
|
|
40
|
+
DEPLOYMENTS_BY_SYMBOL = begin
|
|
41
|
+
grouped = Hash.new { |hash, key| hash[key] = [] }
|
|
42
|
+
TOKEN_DEPLOYMENTS.each do |deployment|
|
|
43
|
+
key = [deployment.fetch(:chain_id), deployment.fetch(:symbol)].freeze
|
|
44
|
+
grouped[key] << deployment
|
|
45
|
+
end
|
|
46
|
+
grouped.each_with_object({}) do |(key, deployments), index|
|
|
47
|
+
index[key] = deployments.sort_by { |deployment| deployment.fetch(:deployment_id) }.freeze
|
|
48
|
+
end.freeze
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
DEPLOYMENTS_BY_ADDRESS = begin
|
|
52
|
+
indexed = {}
|
|
53
|
+
TOKEN_DEPLOYMENTS.each do |deployment|
|
|
54
|
+
address = deployment[:address]
|
|
55
|
+
next unless address.is_a?(String) && !address.empty?
|
|
56
|
+
|
|
57
|
+
evm_chain = [TokenChainIDs::ETHEREUM_MAINNET, TokenChainIDs::AVALANCHE_C_MAINNET].include?(deployment.fetch(:chain_id))
|
|
58
|
+
normalized = evm_chain ? address.downcase : address
|
|
59
|
+
key = [deployment.fetch(:chain_id), normalized].freeze
|
|
60
|
+
indexed[key] ||= deployment
|
|
61
|
+
end
|
|
62
|
+
indexed.freeze
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
class << self
|
|
66
|
+
# Return the asset with the exact opaque asset ID.
|
|
67
|
+
def get_token_asset(asset_id)
|
|
68
|
+
return nil unless asset_id.is_a?(String) && !asset_id.empty?
|
|
69
|
+
|
|
70
|
+
ASSETS_BY_ID[asset_id]
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Return the deployment with the exact opaque deployment ID.
|
|
74
|
+
def get_token_deployment(deployment_id)
|
|
75
|
+
return nil unless deployment_id.is_a?(String) && !deployment_id.empty?
|
|
76
|
+
|
|
77
|
+
DEPLOYMENTS_BY_ID[deployment_id]
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# List all deployments, optionally restricted by chain and stable
|
|
81
|
+
# currency. Every lifecycle status remains visible.
|
|
82
|
+
#
|
|
83
|
+
# The canonical Ruby form uses keywords:
|
|
84
|
+
# list_token_deployments(chain_id: ..., stable_currency: ...)
|
|
85
|
+
# Positional values are also accepted for callers that prefer the
|
|
86
|
+
# compact form: list_token_deployments(chain_id, stable_currency).
|
|
87
|
+
def list_token_deployments(chain_id = nil, stable_currency = nil, **filters)
|
|
88
|
+
unless filters.empty?
|
|
89
|
+
return EMPTY_DEPLOYMENTS unless filters.keys.all? { |key| %i[chain_id stable_currency].include?(key) }
|
|
90
|
+
return EMPTY_DEPLOYMENTS if filters.key?(:chain_id) && !chain_id.nil?
|
|
91
|
+
return EMPTY_DEPLOYMENTS if filters.key?(:stable_currency) && !stable_currency.nil?
|
|
92
|
+
|
|
93
|
+
chain_id = filters[:chain_id] if filters.key?(:chain_id)
|
|
94
|
+
stable_currency = filters[:stable_currency] if filters.key?(:stable_currency)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
return EMPTY_DEPLOYMENTS if !chain_id.nil? && !known_chain_id?(chain_id)
|
|
98
|
+
return EMPTY_DEPLOYMENTS if !stable_currency.nil? && !stable_currency?(stable_currency)
|
|
99
|
+
|
|
100
|
+
filtered = TOKEN_DEPLOYMENTS.select do |deployment|
|
|
101
|
+
(chain_id.nil? || deployment.fetch(:chain_id) == chain_id) &&
|
|
102
|
+
(stable_currency.nil? || deployment[:stable_currency] == stable_currency)
|
|
103
|
+
end
|
|
104
|
+
filtered.empty? ? EMPTY_DEPLOYMENTS : filtered.freeze
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Find every exact-case symbol match on a known chain, ordered by
|
|
108
|
+
# deployment ID.
|
|
109
|
+
def find_token_deployments_by_symbol(chain_id, symbol)
|
|
110
|
+
return EMPTY_DEPLOYMENTS unless known_chain_id?(chain_id)
|
|
111
|
+
return EMPTY_DEPLOYMENTS unless symbol.is_a?(String) && !symbol.empty?
|
|
112
|
+
|
|
113
|
+
DEPLOYMENTS_BY_SYMBOL.fetch([chain_id, symbol], EMPTY_DEPLOYMENTS)
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# Find a non-native deployment by address. EVM addresses are strict
|
|
117
|
+
# ASCII hexadecimal and matched case-insensitively; Solana addresses are
|
|
118
|
+
# matched exactly.
|
|
119
|
+
def find_token_deployment_by_address(chain_id, address)
|
|
120
|
+
return nil unless known_chain_id?(chain_id)
|
|
121
|
+
return nil unless address.is_a?(String) && !address.empty?
|
|
122
|
+
|
|
123
|
+
if evm_chain_id?(chain_id)
|
|
124
|
+
return nil unless valid_evm_address?(address)
|
|
125
|
+
|
|
126
|
+
normalized = address.downcase
|
|
127
|
+
return nil if zero_evm_address?(normalized)
|
|
128
|
+
else
|
|
129
|
+
normalized = address
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
DEPLOYMENTS_BY_ADDRESS[[chain_id, normalized]]
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# Return the native deployment for a known chain. Native deployments use
|
|
136
|
+
# a nil address and are intentionally not address-lookup candidates.
|
|
137
|
+
def get_native_token_deployment(chain_id)
|
|
138
|
+
return nil unless known_chain_id?(chain_id)
|
|
139
|
+
|
|
140
|
+
TOKEN_DEPLOYMENTS.find do |deployment|
|
|
141
|
+
deployment.fetch(:chain_id) == chain_id &&
|
|
142
|
+
deployment.fetch(:standard) == "native" && deployment[:address].nil?
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
private
|
|
147
|
+
|
|
148
|
+
def known_chain_id?(chain_id)
|
|
149
|
+
chain_id.is_a?(String) &&
|
|
150
|
+
[TokenChainIDs::ETHEREUM_MAINNET, TokenChainIDs::SOLANA_MAINNET, TokenChainIDs::AVALANCHE_C_MAINNET].include?(chain_id)
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def evm_chain_id?(chain_id)
|
|
154
|
+
chain_id == TokenChainIDs::ETHEREUM_MAINNET || chain_id == TokenChainIDs::AVALANCHE_C_MAINNET
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def stable_currency?(value)
|
|
158
|
+
value.is_a?(String) && %w[USD EUR JPY].include?(value)
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def valid_evm_address?(address)
|
|
162
|
+
address.match?(/\A0x[0-9A-Fa-f]{40}\z/)
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def zero_evm_address?(address)
|
|
166
|
+
address == "0x#{"0" * 40}"
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "generated/token_rankings"
|
|
4
|
+
|
|
5
|
+
module ERPC
|
|
6
|
+
# Offline access to the generated token ranking snapshot.
|
|
7
|
+
#
|
|
8
|
+
# Ranking records are immutable values generated from the canonical registry.
|
|
9
|
+
# Lookups use exact chain IDs and never access a client, clock, file, or
|
|
10
|
+
# network. The current canonical snapshot is intentionally unconfigured, so
|
|
11
|
+
# its known-chain results are empty until a reviewed snapshot is published.
|
|
12
|
+
module TokenRankings
|
|
13
|
+
TOKEN_RANKINGS_METADATA = TokenRankingsData::TOKEN_RANKINGS_METADATA
|
|
14
|
+
TOKEN_RANKINGS = TokenRankingsData::TOKEN_RANKINGS
|
|
15
|
+
TOKEN_RANKINGS_CONTENT_DIGEST = TokenRankingsData::TOKEN_RANKINGS_CONTENT_DIGEST
|
|
16
|
+
|
|
17
|
+
TOKEN_RANKINGS_SCHEMA_VERSION = TOKEN_RANKINGS_METADATA.fetch(:schema_version)
|
|
18
|
+
TOKEN_RANKINGS_METRIC = TOKEN_RANKINGS_METADATA.fetch(:metric)
|
|
19
|
+
TOKEN_RANKINGS_AS_OF = TOKEN_RANKINGS_METADATA.fetch(:as_of)
|
|
20
|
+
TOKEN_RANKINGS_STATUS = TOKEN_RANKINGS_METADATA.fetch(:status)
|
|
21
|
+
TOKEN_RANKINGS_COVERAGE = TOKEN_RANKINGS_METADATA.fetch(:coverage)
|
|
22
|
+
TOKEN_RANKINGS_SOURCE_IDS = TOKEN_RANKINGS_METADATA.fetch(:source_ids)
|
|
23
|
+
|
|
24
|
+
EMPTY_RANKINGS = [].freeze
|
|
25
|
+
|
|
26
|
+
TOKEN_RANKINGS_BY_CHAIN = begin
|
|
27
|
+
grouped = {}
|
|
28
|
+
TOKEN_RANKINGS.each do |ranking|
|
|
29
|
+
chain_id = ranking.fetch(:chain_id)
|
|
30
|
+
grouped[chain_id] ||= []
|
|
31
|
+
grouped[chain_id] << ranking
|
|
32
|
+
end
|
|
33
|
+
grouped.each_with_object({}) do |(chain_id, rows), index|
|
|
34
|
+
index[chain_id] = rows.freeze
|
|
35
|
+
end.freeze
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
class << self
|
|
39
|
+
# Return rankings for one exact chain ID.
|
|
40
|
+
#
|
|
41
|
+
# Empty, unknown, and special string inputs return the same immutable
|
|
42
|
+
# empty array. No aliases or live data are inferred.
|
|
43
|
+
def list_token_rankings(chain_id)
|
|
44
|
+
return EMPTY_RANKINGS unless chain_id.is_a?(String) && !chain_id.empty?
|
|
45
|
+
|
|
46
|
+
TOKEN_RANKINGS_BY_CHAIN.fetch(chain_id, EMPTY_RANKINGS)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
data/lib/erpc_sdk/version.rb
CHANGED
data/lib/erpc_sdk.rb
CHANGED
|
@@ -7,4 +7,8 @@ require_relative "erpc_sdk/transport"
|
|
|
7
7
|
require_relative "erpc_sdk/rpc"
|
|
8
8
|
require_relative "erpc_sdk/rest"
|
|
9
9
|
require_relative "erpc_sdk/websocket"
|
|
10
|
+
require_relative "erpc_sdk/dex_catalog"
|
|
11
|
+
require_relative "erpc_sdk/swap"
|
|
10
12
|
require_relative "erpc_sdk/client"
|
|
13
|
+
require_relative "erpc_sdk/token_catalog"
|
|
14
|
+
require_relative "erpc_sdk/token_rankings"
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: erpc-sdk
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.7.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- ELSOUL LABO B.V.
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-09-
|
|
11
|
+
date: 2026-09-16 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: minitest
|
|
@@ -62,9 +62,16 @@ files:
|
|
|
62
62
|
- lib/erpc_sdk.rb
|
|
63
63
|
- lib/erpc_sdk/client.rb
|
|
64
64
|
- lib/erpc_sdk/config.rb
|
|
65
|
+
- lib/erpc_sdk/dex_catalog.rb
|
|
65
66
|
- lib/erpc_sdk/errors.rb
|
|
67
|
+
- lib/erpc_sdk/generated/dex_catalog.rb
|
|
68
|
+
- lib/erpc_sdk/generated/token_catalog.rb
|
|
69
|
+
- lib/erpc_sdk/generated/token_rankings.rb
|
|
66
70
|
- lib/erpc_sdk/rest.rb
|
|
67
71
|
- lib/erpc_sdk/rpc.rb
|
|
72
|
+
- lib/erpc_sdk/swap.rb
|
|
73
|
+
- lib/erpc_sdk/token_catalog.rb
|
|
74
|
+
- lib/erpc_sdk/token_rankings.rb
|
|
68
75
|
- lib/erpc_sdk/transport.rb
|
|
69
76
|
- lib/erpc_sdk/version.rb
|
|
70
77
|
- lib/erpc_sdk/websocket.rb
|