coinbase 0.0.1 → 4.0.7
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of coinbase might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/.gitignore +2 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +611 -0
- data/Rakefile +7 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/coinbase.gemspec +27 -0
- data/lib/coinbase/wallet/adapters/em_http.rb +78 -0
- data/lib/coinbase/wallet/adapters/net_http.rb +68 -0
- data/lib/coinbase/wallet/api_client.rb +692 -0
- data/lib/coinbase/wallet/api_errors.rb +120 -0
- data/lib/coinbase/wallet/api_response.rb +41 -0
- data/lib/coinbase/wallet/ca-coinbase.crt +629 -0
- data/lib/coinbase/wallet/client.rb +101 -0
- data/lib/coinbase/wallet/models/account.rb +187 -0
- data/lib/coinbase/wallet/models/address.rb +12 -0
- data/lib/coinbase/wallet/models/api_object.rb +46 -0
- data/lib/coinbase/wallet/models/checkout.rb +19 -0
- data/lib/coinbase/wallet/models/order.rb +12 -0
- data/lib/coinbase/wallet/models/transaction.rb +21 -0
- data/lib/coinbase/wallet/models/transfer.rb +13 -0
- data/lib/coinbase/wallet/models/user.rb +15 -0
- data/lib/coinbase/wallet/version.rb +5 -0
- data/lib/coinbase/wallet.rb +23 -156
- data/spec/account_spec.rb +193 -0
- data/spec/clients/client_spec.rb +34 -0
- data/spec/clients/oauth_client_spec.rb +56 -0
- data/spec/endpoints_spec.rb +352 -0
- data/spec/error_spec.rb +137 -0
- data/spec/models/address_spec.rb +26 -0
- data/spec/models/api_object_spec.rb +63 -0
- data/spec/models/checkout_spec.rb +52 -0
- data/spec/models/current_user_spec.rb +29 -0
- data/spec/models/order_spec.rb +52 -0
- data/spec/models/request_spec.rb +47 -0
- data/spec/models/transfer_spec.rb +64 -0
- data/spec/models/user_spec.rb +24 -0
- data/spec/spec_helper.rb +13 -0
- metadata +62 -98
- data/lib/coinbase/address.rb +0 -127
- data/lib/coinbase/asset.rb +0 -20
- data/lib/coinbase/balance_map.rb +0 -48
- data/lib/coinbase/constants.rb +0 -38
- data/lib/coinbase/network.rb +0 -55
- data/lib/coinbase/transfer.rb +0 -153
- data/lib/coinbase.rb +0 -18
metadata
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: coinbase
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 4.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
7
|
+
- John Duhamel
|
8
|
+
- Jori Lallo
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date:
|
12
|
+
date: 2015-07-28 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
15
|
name: bigdecimal
|
@@ -25,55 +26,13 @@ dependencies:
|
|
25
26
|
- !ruby/object:Gem::Version
|
26
27
|
version: '0'
|
27
28
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - '='
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: 2.8.1
|
34
|
-
type: :runtime
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - '='
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: 2.8.1
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: eth
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - ">="
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '0'
|
48
|
-
type: :runtime
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - ">="
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '0'
|
55
|
-
- !ruby/object:Gem::Dependency
|
56
|
-
name: jimson
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
58
|
-
requirements:
|
59
|
-
- - ">="
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '0'
|
62
|
-
type: :runtime
|
63
|
-
prerelease: false
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
65
|
-
requirements:
|
66
|
-
- - ">="
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: '0'
|
69
|
-
- !ruby/object:Gem::Dependency
|
70
|
-
name: money-tree
|
29
|
+
name: rake
|
71
30
|
requirement: !ruby/object:Gem::Requirement
|
72
31
|
requirements:
|
73
32
|
- - ">="
|
74
33
|
- !ruby/object:Gem::Version
|
75
34
|
version: '0'
|
76
|
-
type: :
|
35
|
+
type: :development
|
77
36
|
prerelease: false
|
78
37
|
version_requirements: !ruby/object:Gem::Requirement
|
79
38
|
requirements:
|
@@ -81,13 +40,13 @@ dependencies:
|
|
81
40
|
- !ruby/object:Gem::Version
|
82
41
|
version: '0'
|
83
42
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
43
|
+
name: rspec
|
85
44
|
requirement: !ruby/object:Gem::Requirement
|
86
45
|
requirements:
|
87
46
|
- - ">="
|
88
47
|
- !ruby/object:Gem::Version
|
89
48
|
version: '0'
|
90
|
-
type: :
|
49
|
+
type: :development
|
91
50
|
prerelease: false
|
92
51
|
version_requirements: !ruby/object:Gem::Requirement
|
93
52
|
requirements:
|
@@ -95,7 +54,7 @@ dependencies:
|
|
95
54
|
- !ruby/object:Gem::Version
|
96
55
|
version: '0'
|
97
56
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
57
|
+
name: webmock
|
99
58
|
requirement: !ruby/object:Gem::Requirement
|
100
59
|
requirements:
|
101
60
|
- - ">="
|
@@ -109,7 +68,7 @@ dependencies:
|
|
109
68
|
- !ruby/object:Gem::Version
|
110
69
|
version: '0'
|
111
70
|
- !ruby/object:Gem::Dependency
|
112
|
-
name:
|
71
|
+
name: timecop
|
113
72
|
requirement: !ruby/object:Gem::Requirement
|
114
73
|
requirements:
|
115
74
|
- - ">="
|
@@ -123,7 +82,7 @@ dependencies:
|
|
123
82
|
- !ruby/object:Gem::Version
|
124
83
|
version: '0'
|
125
84
|
- !ruby/object:Gem::Dependency
|
126
|
-
name:
|
85
|
+
name: pry
|
127
86
|
requirement: !ruby/object:Gem::Requirement
|
128
87
|
requirements:
|
129
88
|
- - ">="
|
@@ -136,53 +95,57 @@ dependencies:
|
|
136
95
|
- - ">="
|
137
96
|
- !ruby/object:Gem::Version
|
138
97
|
version: '0'
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
version: 1.63.1
|
146
|
-
type: :development
|
147
|
-
prerelease: false
|
148
|
-
version_requirements: !ruby/object:Gem::Requirement
|
149
|
-
requirements:
|
150
|
-
- - '='
|
151
|
-
- !ruby/object:Gem::Version
|
152
|
-
version: 1.63.1
|
153
|
-
- !ruby/object:Gem::Dependency
|
154
|
-
name: yard
|
155
|
-
requirement: !ruby/object:Gem::Requirement
|
156
|
-
requirements:
|
157
|
-
- - '='
|
158
|
-
- !ruby/object:Gem::Version
|
159
|
-
version: 0.9.36
|
160
|
-
type: :development
|
161
|
-
prerelease: false
|
162
|
-
version_requirements: !ruby/object:Gem::Requirement
|
163
|
-
requirements:
|
164
|
-
- - '='
|
165
|
-
- !ruby/object:Gem::Version
|
166
|
-
version: 0.9.36
|
167
|
-
description: Coinbase Ruby SDK for accessing Coinbase Platform APIs
|
168
|
-
email: yuga.cohler@coinbase.com
|
169
|
-
executables: []
|
98
|
+
description: Client library for Coinbase Wallet API v2
|
99
|
+
email:
|
100
|
+
- jjd@coinbase.com
|
101
|
+
executables:
|
102
|
+
- console
|
103
|
+
- setup
|
170
104
|
extensions: []
|
171
105
|
extra_rdoc_files: []
|
172
106
|
files:
|
173
|
-
-
|
174
|
-
-
|
175
|
-
-
|
176
|
-
-
|
177
|
-
-
|
178
|
-
-
|
179
|
-
-
|
107
|
+
- ".gitignore"
|
108
|
+
- Gemfile
|
109
|
+
- LICENSE.txt
|
110
|
+
- README.md
|
111
|
+
- Rakefile
|
112
|
+
- bin/console
|
113
|
+
- bin/setup
|
114
|
+
- coinbase.gemspec
|
180
115
|
- lib/coinbase/wallet.rb
|
181
|
-
|
182
|
-
|
183
|
-
-
|
184
|
-
|
185
|
-
|
116
|
+
- lib/coinbase/wallet/adapters/em_http.rb
|
117
|
+
- lib/coinbase/wallet/adapters/net_http.rb
|
118
|
+
- lib/coinbase/wallet/api_client.rb
|
119
|
+
- lib/coinbase/wallet/api_errors.rb
|
120
|
+
- lib/coinbase/wallet/api_response.rb
|
121
|
+
- lib/coinbase/wallet/ca-coinbase.crt
|
122
|
+
- lib/coinbase/wallet/client.rb
|
123
|
+
- lib/coinbase/wallet/models/account.rb
|
124
|
+
- lib/coinbase/wallet/models/address.rb
|
125
|
+
- lib/coinbase/wallet/models/api_object.rb
|
126
|
+
- lib/coinbase/wallet/models/checkout.rb
|
127
|
+
- lib/coinbase/wallet/models/order.rb
|
128
|
+
- lib/coinbase/wallet/models/transaction.rb
|
129
|
+
- lib/coinbase/wallet/models/transfer.rb
|
130
|
+
- lib/coinbase/wallet/models/user.rb
|
131
|
+
- lib/coinbase/wallet/version.rb
|
132
|
+
- spec/account_spec.rb
|
133
|
+
- spec/clients/client_spec.rb
|
134
|
+
- spec/clients/oauth_client_spec.rb
|
135
|
+
- spec/endpoints_spec.rb
|
136
|
+
- spec/error_spec.rb
|
137
|
+
- spec/models/address_spec.rb
|
138
|
+
- spec/models/api_object_spec.rb
|
139
|
+
- spec/models/checkout_spec.rb
|
140
|
+
- spec/models/current_user_spec.rb
|
141
|
+
- spec/models/order_spec.rb
|
142
|
+
- spec/models/request_spec.rb
|
143
|
+
- spec/models/transfer_spec.rb
|
144
|
+
- spec/models/user_spec.rb
|
145
|
+
- spec/spec_helper.rb
|
146
|
+
homepage: https://developers.coinbase.com/api/v2
|
147
|
+
licenses: []
|
148
|
+
metadata: {}
|
186
149
|
post_install_message:
|
187
150
|
rdoc_options: []
|
188
151
|
require_paths:
|
@@ -191,15 +154,16 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
191
154
|
requirements:
|
192
155
|
- - ">="
|
193
156
|
- !ruby/object:Gem::Version
|
194
|
-
version:
|
157
|
+
version: '0'
|
195
158
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
196
159
|
requirements:
|
197
160
|
- - ">="
|
198
161
|
- !ruby/object:Gem::Version
|
199
162
|
version: '0'
|
200
163
|
requirements: []
|
201
|
-
|
164
|
+
rubyforge_project:
|
165
|
+
rubygems_version: 2.2.2
|
202
166
|
signing_key:
|
203
167
|
specification_version: 4
|
204
|
-
summary: Coinbase
|
168
|
+
summary: Client library for Coinbase Wallet API v2
|
205
169
|
test_files: []
|
data/lib/coinbase/address.rb
DELETED
@@ -1,127 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative 'balance_map'
|
4
|
-
require_relative 'constants'
|
5
|
-
require 'bigdecimal'
|
6
|
-
require 'eth'
|
7
|
-
require 'jimson'
|
8
|
-
|
9
|
-
module Coinbase
|
10
|
-
# A representation of a blockchain Address, which is a user-controlled account on a Network. Addresses are used to
|
11
|
-
# send and receive Assets, and should be created using {link:Wallet#create_address}. Addresses require a
|
12
|
-
# {link:Eth::Key} to sign transaction data.
|
13
|
-
class Address
|
14
|
-
attr_reader :network_id, :address_id, :wallet_id
|
15
|
-
|
16
|
-
# Returns a new Address object.
|
17
|
-
# @param network_id [Symbol] The ID of the Network on which the Address exists
|
18
|
-
# @param address_id [String] The ID of the Address. On EVM Networks, for example, this is a hash of the public key.
|
19
|
-
# @param wallet_id [String] The ID of the Wallet to which the Address belongs
|
20
|
-
# @param key [Eth::Key] The key backing the Address
|
21
|
-
# @param client [Jimson::Client] (Optional) The JSON RPC client to use for interacting with the Network
|
22
|
-
def initialize(network_id, address_id, wallet_id, key,
|
23
|
-
client: Jimson::Client.new(ENV.fetch('BASE_SEPOLIA_RPC_URL', nil)))
|
24
|
-
# TODO: Don't require key.
|
25
|
-
@network_id = network_id
|
26
|
-
@address_id = address_id
|
27
|
-
@wallet_id = wallet_id
|
28
|
-
@key = key
|
29
|
-
@client = client
|
30
|
-
end
|
31
|
-
|
32
|
-
# Returns the balances of the Address. Currently only ETH balances are supported.
|
33
|
-
# @return [BalanceMap] The balances of the Address, keyed by asset ID. Ether balances are denominated
|
34
|
-
# in ETH.
|
35
|
-
def list_balances
|
36
|
-
# TODO: Handle multiple currencies.
|
37
|
-
eth_balance_in_wei = BigDecimal(@client.eth_getBalance(@address_id, 'latest').to_i(16).to_s)
|
38
|
-
eth_balance = BigDecimal(eth_balance_in_wei / BigDecimal(Coinbase::WEI_PER_ETHER.to_s))
|
39
|
-
|
40
|
-
BalanceMap.new({ eth: eth_balance })
|
41
|
-
end
|
42
|
-
|
43
|
-
# Returns the balance of the provided Asset. Currently only ETH is supported.
|
44
|
-
# @param asset_id [Symbol] The Asset to retrieve the balance for
|
45
|
-
# @return [BigDecimal] The balance of the Asset
|
46
|
-
def get_balance(asset_id)
|
47
|
-
normalized_asset_id = if %i[wei gwei].include?(asset_id)
|
48
|
-
:eth
|
49
|
-
else
|
50
|
-
asset_id
|
51
|
-
end
|
52
|
-
|
53
|
-
eth_balance = list_balances[normalized_asset_id] || BigDecimal(0)
|
54
|
-
|
55
|
-
case asset_id
|
56
|
-
when :eth
|
57
|
-
eth_balance
|
58
|
-
when :gwei
|
59
|
-
eth_balance * Coinbase::GWEI_PER_ETHER
|
60
|
-
when :wei
|
61
|
-
eth_balance * Coinbase::WEI_PER_ETHER
|
62
|
-
else
|
63
|
-
BigDecimal(0)
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
# Transfers the given amount of the given Asset to the given address. Only same-Network Transfers are supported.
|
68
|
-
# @param amount [Integer, Float, BigDecimal] The amount of the Asset to send.
|
69
|
-
# @param asset_id [Symbol] The ID of the Asset to send. For Ether, :eth, :gwei, and :wei are supported.
|
70
|
-
# @param destination [Wallet | Address | String] The destination of the transfer. If a Wallet, sends to the Wallet's
|
71
|
-
# default address. If a String, interprets it as the address ID.
|
72
|
-
# @return [String] The hash of the Transfer transaction.
|
73
|
-
def transfer(amount, asset_id, destination)
|
74
|
-
# TODO: Handle multiple currencies.
|
75
|
-
raise ArgumentError, "Unsupported asset: #{asset_id}" unless Coinbase::SUPPORTED_ASSET_IDS[asset_id]
|
76
|
-
|
77
|
-
if destination.is_a?(Wallet)
|
78
|
-
raise ArgumentError, 'Transfer must be on the same Network' if destination.network_id != @network_id
|
79
|
-
|
80
|
-
destination = destination.default_address.address_id
|
81
|
-
elsif destination.is_a?(Address)
|
82
|
-
raise ArgumentError, 'Transfer must be on the same Network' if destination.network_id != @network_id
|
83
|
-
|
84
|
-
destination = destination.address_id
|
85
|
-
end
|
86
|
-
|
87
|
-
current_balance = get_balance(asset_id)
|
88
|
-
if current_balance < amount
|
89
|
-
raise ArgumentError, "Insufficient funds: #{amount} requested, but only #{current_balance} available"
|
90
|
-
end
|
91
|
-
|
92
|
-
transfer = Coinbase::Transfer.new(@network_id, @wallet_id, @address_id, amount, asset_id, destination,
|
93
|
-
client: @client)
|
94
|
-
|
95
|
-
transaction = transfer.transaction
|
96
|
-
transaction.sign(@key)
|
97
|
-
@client.eth_sendRawTransaction("0x#{transaction.hex}")
|
98
|
-
|
99
|
-
transfer
|
100
|
-
end
|
101
|
-
|
102
|
-
# Returns the address as a string.
|
103
|
-
# @return [String] The address
|
104
|
-
def to_s
|
105
|
-
@address_id
|
106
|
-
end
|
107
|
-
|
108
|
-
private
|
109
|
-
|
110
|
-
# Normalizes the amount of ETH to send based on the asset ID.
|
111
|
-
# @param amount [Integer, Float, BigDecimal] The amount to normalize
|
112
|
-
# @param asset_id [Symbol] The ID of the Asset being transferred
|
113
|
-
# @return [BigDecimal] The normalized amount in units of ETH
|
114
|
-
def normalize_eth_amount(amount, asset_id)
|
115
|
-
case asset_id
|
116
|
-
when :eth
|
117
|
-
amount.is_a?(BigDecimal) ? amount : BigDecimal(amount.to_s)
|
118
|
-
when :gwei
|
119
|
-
BigDecimal(amount / Coinbase::GWEI_PER_ETHER)
|
120
|
-
when :wei
|
121
|
-
BigDecimal(amount / Coinbase::WEI_PER_ETHER)
|
122
|
-
else
|
123
|
-
raise ArgumentError, "Unsupported asset: #{asset_id}"
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end
|
127
|
-
end
|
data/lib/coinbase/asset.rb
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Coinbase
|
4
|
-
# A representation of an Asset.
|
5
|
-
class Asset
|
6
|
-
attr_reader :network_id, :asset_id, :display_name, :address_id
|
7
|
-
|
8
|
-
# Returns a new Asset object.
|
9
|
-
# @param network_id [Symbol] The ID of the Network to which the Asset belongs
|
10
|
-
# @param asset_id [Symbol] The Asset ID
|
11
|
-
# @param display_name [String] The Asset's display name
|
12
|
-
# @param address_id [String] (Optional) The Asset's address ID, if one exists
|
13
|
-
def initialize(network_id:, asset_id:, display_name:, address_id: nil)
|
14
|
-
@network_id = network_id
|
15
|
-
@asset_id = asset_id
|
16
|
-
@display_name = display_name
|
17
|
-
@address_id = address_id
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
data/lib/coinbase/balance_map.rb
DELETED
@@ -1,48 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'bigdecimal'
|
4
|
-
|
5
|
-
module Coinbase
|
6
|
-
# A convenience class for printing out crypto asset balances in a human-readable format.
|
7
|
-
class BalanceMap < Hash
|
8
|
-
# Returns a new BalanceMap object.
|
9
|
-
# @param hash [Map<Symbol, BigDecimal>] The hash to initialize with
|
10
|
-
def initialize(hash = {})
|
11
|
-
super()
|
12
|
-
hash.each do |key, value|
|
13
|
-
self[key] = value
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
# Returns a string representation of the balance map.
|
18
|
-
# @return [String] The string representation of the balance
|
19
|
-
def to_s
|
20
|
-
to_string
|
21
|
-
end
|
22
|
-
|
23
|
-
# Returns a string representation of the balance map.
|
24
|
-
# @return [String] The string representation of the balance
|
25
|
-
def inspect
|
26
|
-
to_string
|
27
|
-
end
|
28
|
-
|
29
|
-
private
|
30
|
-
|
31
|
-
# Returns a string representation of the balance.
|
32
|
-
# @return [String] The string representation of the balance
|
33
|
-
def to_string
|
34
|
-
result = {}
|
35
|
-
|
36
|
-
each do |asset_id, balance|
|
37
|
-
# Convert to floating-point number (not scientific notation)
|
38
|
-
str = balance.to_s('F')
|
39
|
-
|
40
|
-
str = balance.to_i.to_s if balance.frac.zero?
|
41
|
-
|
42
|
-
result[asset_id] = str
|
43
|
-
end
|
44
|
-
|
45
|
-
result
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
data/lib/coinbase/constants.rb
DELETED
@@ -1,38 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative 'asset'
|
4
|
-
require_relative 'network'
|
5
|
-
|
6
|
-
module Coinbase
|
7
|
-
# The Assets supported on Base Sepolia by the Coinbase SDK.
|
8
|
-
ETH = Asset.new(network_id: :base_sepolia, asset_id: :eth, display_name: 'Ether')
|
9
|
-
USDC = Asset.new(network_id: :base_sepolia, asset_id: :usdc, display_name: 'USD Coin',
|
10
|
-
address_id: '0x036CbD53842c5426634e7929541eC2318f3dCF7e')
|
11
|
-
|
12
|
-
# The Base Sepolia Network.
|
13
|
-
BASE_SEPOLIA = Network.new(
|
14
|
-
network_id: :base_sepolia,
|
15
|
-
display_name: 'Base Sepolia',
|
16
|
-
protocol_family: :evm,
|
17
|
-
is_testnet: true,
|
18
|
-
assets: [ETH, USDC],
|
19
|
-
native_asset_id: :eth,
|
20
|
-
chain_id: 84_532
|
21
|
-
)
|
22
|
-
|
23
|
-
# The amount of Wei per Ether.
|
24
|
-
WEI_PER_ETHER = 1_000_000_000_000_000_000
|
25
|
-
|
26
|
-
# The amount of Wei per Gwei.
|
27
|
-
WEI_PER_GWEI = 1_000_000_000
|
28
|
-
|
29
|
-
# The amount of Gwei per Ether.
|
30
|
-
GWEI_PER_ETHER = 1_000_000_000
|
31
|
-
|
32
|
-
# A map of supported Asset IDs.
|
33
|
-
SUPPORTED_ASSET_IDS = {
|
34
|
-
eth: true, # Ether, the native asset of most EVM networks.
|
35
|
-
gwei: true, # A medium denomination of Ether, typically used in gas prices.
|
36
|
-
wei: true # The smallest denomination of Ether.
|
37
|
-
}.freeze
|
38
|
-
end
|
data/lib/coinbase/network.rb
DELETED
@@ -1,55 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Coinbase
|
4
|
-
# A blockchain network.
|
5
|
-
class Network
|
6
|
-
attr_reader :chain_id
|
7
|
-
|
8
|
-
# Returns a new Network object.
|
9
|
-
#
|
10
|
-
# @param network_id [Symbol] The Network ID
|
11
|
-
# @param display_name [String] The Network's display name
|
12
|
-
# @param protocol_family [String] The protocol family to which the Network belongs
|
13
|
-
# (e.g., "evm")
|
14
|
-
# @param is_testnet [Boolean] Whether the Network is a testnet
|
15
|
-
# @param assets [Array<Asset>] The Assets supported by the Network
|
16
|
-
# @param native_asset_id [String] The ID of the Network's native Asset
|
17
|
-
# @param chain_id [Integer] The Chain ID of the Network
|
18
|
-
def initialize(network_id:, display_name:, protocol_family:, is_testnet:, assets:, native_asset_id:, chain_id:)
|
19
|
-
@network_id = network_id
|
20
|
-
@display_name = display_name
|
21
|
-
@protocol_family = protocol_family
|
22
|
-
@is_testnet = is_testnet
|
23
|
-
@chain_id = chain_id
|
24
|
-
|
25
|
-
@asset_map = {}
|
26
|
-
assets.each do |asset|
|
27
|
-
@asset_map[asset.asset_id] = asset
|
28
|
-
end
|
29
|
-
|
30
|
-
raise ArgumentError, 'Native Asset not found' unless @asset_map.key?(native_asset_id)
|
31
|
-
|
32
|
-
@native_asset = @asset_map[native_asset_id]
|
33
|
-
end
|
34
|
-
|
35
|
-
# Lists the Assets supported by the Network.
|
36
|
-
#
|
37
|
-
# @return [Array<Asset>] The Assets supported by the Network
|
38
|
-
def list_assets
|
39
|
-
@asset_map.values
|
40
|
-
end
|
41
|
-
|
42
|
-
# Gets the Asset with the given ID.
|
43
|
-
#
|
44
|
-
# @param asset_id [Symbol] The ID of the Asset
|
45
|
-
# @return [Asset] The Asset with the given ID
|
46
|
-
def get_asset(asset_id)
|
47
|
-
@asset_map[asset_id]
|
48
|
-
end
|
49
|
-
|
50
|
-
# Gets the native Asset of the Network.
|
51
|
-
#
|
52
|
-
# @return [Asset] The native Asset of the Network
|
53
|
-
attr_reader :native_asset
|
54
|
-
end
|
55
|
-
end
|
data/lib/coinbase/transfer.rb
DELETED
@@ -1,153 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative 'constants'
|
4
|
-
require 'bigdecimal'
|
5
|
-
require 'eth'
|
6
|
-
|
7
|
-
module Coinbase
|
8
|
-
# A representation of a Transfer, which moves an amount of an Asset from
|
9
|
-
# a user-controlled Wallet to another address. The fee is assumed to be paid
|
10
|
-
# in the native Asset of the Network. Currently only ETH transfers are supported. Transfers
|
11
|
-
# should be created through {link:Wallet#transfer} or {link:Address#transfer}.
|
12
|
-
class Transfer
|
13
|
-
attr_reader :network_id, :wallet_id, :from_address_id, :amount, :asset_id, :to_address_id
|
14
|
-
|
15
|
-
# A representation of a Transfer status.
|
16
|
-
module Status
|
17
|
-
# The Transfer is awaiting being broadcast to the Network. At this point, transaction
|
18
|
-
# hashes may not yet be assigned.
|
19
|
-
PENDING = :pending
|
20
|
-
|
21
|
-
# The Transfer has been broadcast to the Network. At this point, at least the transaction hash
|
22
|
-
# should be assigned.
|
23
|
-
BROADCAST = :broadcast
|
24
|
-
|
25
|
-
# The Transfer is complete, and has confirmed on the Network.
|
26
|
-
COMPLETE = :complete
|
27
|
-
|
28
|
-
# The Transfer has failed for some reason.
|
29
|
-
FAILED = :failed
|
30
|
-
end
|
31
|
-
|
32
|
-
# Returns a new Transfer object.
|
33
|
-
# @param network_id [Symbol] The ID of the Network on which the Transfer originated
|
34
|
-
# @param wallet_id [String] The ID of the Wallet from which the Transfer originated
|
35
|
-
# @param from_address_id [String] The ID of the address from which the Transfer originated
|
36
|
-
# @param amount [Integer, Float, BigDecimal] The amount of the Asset to send. Integers are interpreted as
|
37
|
-
# the smallest denomination of the Asset (e.g. Wei for Ether). Floats and BigDecimals are interpreted as the Asset
|
38
|
-
# itself (e.g. Ether).
|
39
|
-
# @param asset_id [Symbol] The ID of the Asset being transferred. Currently only ETH is supported.
|
40
|
-
# @param to_address_id [String] The address to which the Transfer is being sent
|
41
|
-
# @param client [Jimson::Client] (Optional) The JSON RPC client to use for interacting with the Network
|
42
|
-
def initialize(network_id, wallet_id, from_address_id, amount, asset_id, to_address_id,
|
43
|
-
client: Jimson::Client.new(ENV.fetch('BASE_SEPOLIA_RPC_URL', nil)))
|
44
|
-
|
45
|
-
raise ArgumentError, "Unsupported asset: #{asset_id}" if asset_id != :eth
|
46
|
-
|
47
|
-
@network_id = network_id
|
48
|
-
@wallet_id = wallet_id
|
49
|
-
@from_address_id = from_address_id
|
50
|
-
@amount = normalize_eth_amount(amount)
|
51
|
-
@asset_id = asset_id
|
52
|
-
@to_address_id = to_address_id
|
53
|
-
@client = client
|
54
|
-
end
|
55
|
-
|
56
|
-
# Returns the underlying Transfer transaction, creating it if it has not been yet.
|
57
|
-
# @return [Eth::Tx::Eip1559] The Transfer transaction
|
58
|
-
def transaction
|
59
|
-
return @transaction unless @transaction.nil?
|
60
|
-
|
61
|
-
nonce = @client.eth_getTransactionCount(@from_address_id.to_s, 'latest').to_i(16)
|
62
|
-
gas_price = @client.eth_gasPrice.to_i(16)
|
63
|
-
|
64
|
-
params = {
|
65
|
-
chain_id: BASE_SEPOLIA.chain_id, # TODO: Don't hardcode Base Sepolia.
|
66
|
-
nonce: nonce,
|
67
|
-
priority_fee: gas_price, # TODO: Optimize this.
|
68
|
-
max_gas_fee: gas_price,
|
69
|
-
gas_limit: 21_000, # TODO: Handle multiple currencies.
|
70
|
-
from: Eth::Address.new(@from_address_id),
|
71
|
-
to: Eth::Address.new(@to_address_id),
|
72
|
-
value: (@amount * Coinbase::WEI_PER_ETHER).to_i
|
73
|
-
}
|
74
|
-
|
75
|
-
@transaction = Eth::Tx::Eip1559.new(Eth::Tx.validate_eip1559_params(params))
|
76
|
-
@transaction
|
77
|
-
end
|
78
|
-
|
79
|
-
# Returns the status of the Transfer.
|
80
|
-
# @return [Symbol] The status
|
81
|
-
def status
|
82
|
-
begin
|
83
|
-
# Create the transaction, and attempt to get the hash to see if it has been signed.
|
84
|
-
transaction.hash
|
85
|
-
rescue Eth::Signature::SignatureError
|
86
|
-
# If the transaction has not been signed, it is still pending.
|
87
|
-
return Status::PENDING
|
88
|
-
end
|
89
|
-
|
90
|
-
onchain_transaction = @client.eth_getTransactionByHash(transaction_hash)
|
91
|
-
|
92
|
-
if onchain_transaction.nil?
|
93
|
-
# If the transaction has not been broadcast, it is still pending.
|
94
|
-
Status::PENDING
|
95
|
-
elsif onchain_transaction['blockHash'].nil?
|
96
|
-
# If the transaction has been broadcast but hasn't been included in a block, it is
|
97
|
-
# broadcast.
|
98
|
-
Status::BROADCAST
|
99
|
-
else
|
100
|
-
transaction_receipt = @client.eth_getTransactionReceipt(transaction_hash)
|
101
|
-
|
102
|
-
if transaction_receipt['status'].to_i(16) == 1
|
103
|
-
Status::COMPLETE
|
104
|
-
else
|
105
|
-
Status::FAILED
|
106
|
-
end
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
# Waits until the Transfer is completed or failed by polling the Network at the given interval. Raises a
|
111
|
-
# Timeout::Error if the Transfer takes longer than the given timeout.
|
112
|
-
# @param interval_seconds [Integer] The interval at which to poll the Network, in seconds
|
113
|
-
# @param timeout_seconds [Integer] The maximum amount of time to wait for the Transfer to complete, in seconds
|
114
|
-
# @return [Transfer] The completed Transfer object
|
115
|
-
def wait!(interval_seconds = 0.2, timeout_seconds = 10)
|
116
|
-
start_time = Time.now
|
117
|
-
|
118
|
-
loop do
|
119
|
-
return self if status == Status::COMPLETE || status == Status::FAILED
|
120
|
-
|
121
|
-
raise Timeout::Error, 'Transfer timed out' if Time.now - start_time > timeout_seconds
|
122
|
-
|
123
|
-
self.sleep interval_seconds
|
124
|
-
end
|
125
|
-
|
126
|
-
self
|
127
|
-
end
|
128
|
-
|
129
|
-
# Returns the transaction hash of the Transfer, or nil if not yet available.
|
130
|
-
# @return [String] The transaction hash
|
131
|
-
def transaction_hash
|
132
|
-
"0x#{transaction.hash}"
|
133
|
-
rescue Eth::Signature::SignatureError
|
134
|
-
nil
|
135
|
-
end
|
136
|
-
|
137
|
-
private
|
138
|
-
|
139
|
-
# Normalizes the given Ether amount into a BigDecimal.
|
140
|
-
# @param amount [Integer, Float, BigDecimal] The amount to normalize
|
141
|
-
# @return [BigDecimal] The normalized amount
|
142
|
-
def normalize_eth_amount(amount)
|
143
|
-
case amount
|
144
|
-
when BigDecimal
|
145
|
-
amount
|
146
|
-
when Integer, Float
|
147
|
-
BigDecimal(amount.to_s)
|
148
|
-
else
|
149
|
-
raise ArgumentError, "Invalid amount: #{amount}"
|
150
|
-
end
|
151
|
-
end
|
152
|
-
end
|
153
|
-
end
|