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.
@@ -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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ERPC
4
- VERSION = "0.5.0"
4
+ VERSION = "0.7.0"
5
5
  end
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.5.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-04 00:00:00.000000000 Z
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