coinbase-sdk 0.0.13 → 0.0.16
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/lib/coinbase/address/external_address.rb +3 -166
- data/lib/coinbase/address/wallet_address.rb +51 -4
- data/lib/coinbase/address.rb +164 -0
- data/lib/coinbase/client/api/assets_api.rb +2 -2
- data/lib/coinbase/client/api/contract_events_api.rb +121 -0
- data/lib/coinbase/client/api/external_addresses_api.rb +85 -0
- data/lib/coinbase/client/api/networks_api.rb +85 -0
- data/lib/coinbase/client/api/stake_api.rb +361 -0
- data/lib/coinbase/client/api/webhooks_api.rb +286 -0
- data/lib/coinbase/client/models/address_historical_balance_list.rb +258 -0
- data/lib/coinbase/client/models/broadcast_staking_operation_request.rb +239 -0
- data/lib/coinbase/client/models/contract_event.rb +336 -0
- data/lib/coinbase/client/models/contract_event_list.rb +259 -0
- data/lib/coinbase/client/models/create_staking_operation_request.rb +274 -0
- data/lib/coinbase/client/models/create_transfer_request.rb +14 -4
- data/lib/coinbase/client/models/create_webhook_request.rb +282 -0
- data/lib/coinbase/client/models/ethereum_validator.rb +374 -0
- data/lib/coinbase/client/models/feature_set.rb +307 -0
- data/lib/coinbase/client/models/fetch_historical_staking_balances200_response.rb +258 -0
- data/lib/coinbase/client/models/get_validator200_response.rb +221 -0
- data/lib/coinbase/client/models/get_validator200_response_validator.rb +214 -0
- data/lib/coinbase/client/models/historical_balance.rb +273 -0
- data/lib/coinbase/client/models/network.rb +355 -0
- data/lib/coinbase/client/models/network_identifier.rb +44 -0
- data/lib/coinbase/client/models/sponsored_send.rb +338 -0
- data/lib/coinbase/client/models/staking_balance.rb +289 -0
- data/lib/coinbase/client/models/staking_context_context.rb +222 -74
- data/lib/coinbase/client/models/staking_operation.rb +15 -5
- data/lib/coinbase/client/models/staking_reward.rb +22 -6
- data/lib/coinbase/client/models/staking_reward_format.rb +2 -1
- data/lib/coinbase/client/models/staking_reward_usd_value.rb +257 -0
- data/lib/coinbase/client/models/transaction.rb +2 -2
- data/lib/coinbase/client/models/transaction_type.rb +2 -1
- data/lib/coinbase/client/models/transfer.rb +29 -24
- data/lib/coinbase/client/models/update_webhook_request.rb +289 -0
- data/lib/coinbase/client/models/validator_list_data.rb +216 -0
- data/lib/coinbase/client/models/wallet.rb +13 -16
- data/lib/coinbase/client/models/webhook.rb +299 -0
- data/lib/coinbase/client/models/webhook_event_filter.rb +236 -0
- data/lib/coinbase/client/models/webhook_event_type.rb +42 -0
- data/lib/coinbase/client/models/webhook_list.rb +244 -0
- data/lib/coinbase/client.rb +22 -3
- data/lib/coinbase/errors.rb +7 -0
- data/lib/coinbase/historical_balance.rb +53 -0
- data/lib/coinbase/middleware.rb +12 -0
- data/lib/coinbase/server_signer.rb +14 -3
- data/lib/coinbase/sponsored_send.rb +110 -0
- data/lib/coinbase/staking_balance.rb +86 -0
- data/lib/coinbase/staking_operation.rb +106 -5
- data/lib/coinbase/staking_reward.rb +18 -0
- data/lib/coinbase/trade.rb +1 -1
- data/lib/coinbase/transaction.rb +7 -3
- data/lib/coinbase/transfer.rb +56 -29
- data/lib/coinbase/wallet/data.rb +31 -0
- data/lib/coinbase/wallet.rb +91 -46
- data/lib/coinbase.rb +17 -4
- metadata +74 -2
@@ -9,6 +9,67 @@ module Coinbase
|
|
9
9
|
class StakingOperation
|
10
10
|
attr_reader :transactions
|
11
11
|
|
12
|
+
# Builds an ephemeral staking operation this is intended to be called via an Address or Wallet.
|
13
|
+
# @param amount [BigDecimal] The amount to stake, in the primary denomination of the asset
|
14
|
+
# @param network_id [Symbol] The Network ID
|
15
|
+
# @param asset_id [Symbol] The Asset ID
|
16
|
+
# @param address_id [String] The Address ID
|
17
|
+
# @param action [Symbol] The action to perform
|
18
|
+
# @param mode [Symbol] The staking mode
|
19
|
+
# @param options [Hash] Additional options
|
20
|
+
# @return [Coinbase::StakingOperation] The staking operation
|
21
|
+
def self.build(amount, network_id, asset_id, address_id, action, mode, options)
|
22
|
+
model = Coinbase.call_api do
|
23
|
+
asset = Coinbase::Asset.fetch(network_id, asset_id)
|
24
|
+
stake_api.build_staking_operation(
|
25
|
+
{
|
26
|
+
asset_id: asset.primary_denomination.to_s,
|
27
|
+
address_id: address_id,
|
28
|
+
action: action,
|
29
|
+
network_id: Coinbase.normalize_network(network_id),
|
30
|
+
options: {
|
31
|
+
amount: asset.to_atomic_amount(amount).to_i.to_s,
|
32
|
+
mode: mode
|
33
|
+
}.merge(options)
|
34
|
+
}
|
35
|
+
)
|
36
|
+
end
|
37
|
+
|
38
|
+
new(model)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Creates a persisted staking operation this is intended to be called via an Address or Wallet.
|
42
|
+
# @param amount [BigDecimal] The amount to stake, in the primary denomination of the asset
|
43
|
+
# @param network_id [Symbol] The Network ID
|
44
|
+
# @param asset_id [Symbol] The Asset ID
|
45
|
+
# @param address_id [String] The Address ID
|
46
|
+
# @param wallet_id [String] The Wallet ID
|
47
|
+
# @param action [Symbol] The action to perform
|
48
|
+
# @param mode [Symbol] The staking mode
|
49
|
+
# @param options [Hash] Additional options
|
50
|
+
# @return [Coinbase::StakingOperation] The staking operation
|
51
|
+
def self.create(amount, network_id, asset_id, address_id, wallet_id, action, mode, options)
|
52
|
+
model = Coinbase.call_api do
|
53
|
+
asset = Coinbase::Asset.fetch(network_id, asset_id)
|
54
|
+
stake_api.create_staking_operation(
|
55
|
+
wallet_id,
|
56
|
+
address_id,
|
57
|
+
{
|
58
|
+
asset_id: asset.primary_denomination.to_s,
|
59
|
+
address_id: address_id,
|
60
|
+
action: action,
|
61
|
+
network_id: Coinbase.normalize_network(network_id),
|
62
|
+
options: {
|
63
|
+
amount: asset.to_atomic_amount(amount).to_i.to_s,
|
64
|
+
mode: mode
|
65
|
+
}.merge(options)
|
66
|
+
}
|
67
|
+
)
|
68
|
+
end
|
69
|
+
|
70
|
+
new(model)
|
71
|
+
end
|
72
|
+
|
12
73
|
# Returns a new StakingOperation object.
|
13
74
|
# @param model [Coinbase::Client::StakingOperation] The underlying StakingOperation object
|
14
75
|
def initialize(model)
|
@@ -39,6 +100,12 @@ module Coinbase
|
|
39
100
|
@model.status
|
40
101
|
end
|
41
102
|
|
103
|
+
# Returns the Wallet ID of the Staking Operation.
|
104
|
+
# @return [String] The Wallet ID
|
105
|
+
def wallet_id
|
106
|
+
@model.wallet_id
|
107
|
+
end
|
108
|
+
|
42
109
|
# Waits until the Staking Operation is completed or failed by polling its status at the given interval. Raises a
|
43
110
|
# Timeout::Error if the Staking Operation takes longer than the given timeout.
|
44
111
|
# @param interval_seconds [Integer] The interval at which to poll, in seconds
|
@@ -66,13 +133,18 @@ module Coinbase
|
|
66
133
|
# @param network_id [Symbol] The Network ID
|
67
134
|
# @param address_id [Symbol] The Address ID
|
68
135
|
# @param id [String] The ID of the StakingOperation
|
136
|
+
# @param wallet_id [String] The optional Wallet ID
|
69
137
|
# @return [Coinbase::StakingOperation] The staking operation
|
70
|
-
def self.fetch(network_id, address_id, id)
|
138
|
+
def self.fetch(network_id, address_id, id, wallet_id: nil)
|
71
139
|
staking_operation_model = Coinbase.call_api do
|
72
|
-
|
140
|
+
if wallet_id.nil?
|
141
|
+
stake_api.get_external_staking_operation(network_id, address_id, id)
|
142
|
+
else
|
143
|
+
stake_api.get_staking_operation(wallet_id, address_id, id)
|
144
|
+
end
|
73
145
|
end
|
74
146
|
|
75
|
-
|
147
|
+
new(staking_operation_model)
|
76
148
|
end
|
77
149
|
|
78
150
|
# Signs the Open Transactions with the provided key
|
@@ -87,7 +159,11 @@ module Coinbase
|
|
87
159
|
# @return [Coinbase::StakingOperation] The updated staking operation
|
88
160
|
def reload
|
89
161
|
@model = Coinbase.call_api do
|
90
|
-
|
162
|
+
if wallet_id.nil?
|
163
|
+
stake_api.get_external_staking_operation(network_id, address_id, id)
|
164
|
+
else
|
165
|
+
stake_api.get_staking_operation(wallet_id, address_id, id)
|
166
|
+
end
|
91
167
|
end
|
92
168
|
|
93
169
|
from_model(@model)
|
@@ -108,10 +184,33 @@ module Coinbase
|
|
108
184
|
signed_voluntary_exit_messages
|
109
185
|
end
|
110
186
|
|
187
|
+
# Broadcasts the Staking Operation transactions to the network
|
188
|
+
# @return [Coinbase::StakingOperation]
|
189
|
+
def broadcast!
|
190
|
+
transactions.each_with_index do |transaction, i|
|
191
|
+
raise TransactionNotSignedError unless transaction.signed?
|
192
|
+
|
193
|
+
Coinbase.call_api do
|
194
|
+
stake_api.broadcast_staking_operation(
|
195
|
+
wallet_id,
|
196
|
+
address_id,
|
197
|
+
id,
|
198
|
+
{ signed_payload: transaction.raw.hex, transaction_index: i }
|
199
|
+
)
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
self
|
204
|
+
end
|
205
|
+
|
206
|
+
def self.stake_api
|
207
|
+
Coinbase::Client::StakeApi.new(Coinbase.configuration.api_client)
|
208
|
+
end
|
209
|
+
|
111
210
|
private
|
112
211
|
|
113
212
|
def stake_api
|
114
|
-
@stake_api ||=
|
213
|
+
@stake_api ||= self.class.stake_api
|
115
214
|
end
|
116
215
|
|
117
216
|
def from_model(model)
|
@@ -120,6 +219,8 @@ module Coinbase
|
|
120
219
|
@transactions = model.transactions.map do |transaction_model|
|
121
220
|
Transaction.new(transaction_model)
|
122
221
|
end
|
222
|
+
|
223
|
+
self
|
123
224
|
end
|
124
225
|
end
|
125
226
|
end
|
@@ -53,6 +53,24 @@ module Coinbase
|
|
53
53
|
@model.address_id
|
54
54
|
end
|
55
55
|
|
56
|
+
# Returns the USD value of the StakingReward.
|
57
|
+
# @return [BigDecimal] The USD value
|
58
|
+
def usd_value
|
59
|
+
BigDecimal(@model.usd_value.amount.to_i) / BigDecimal(100)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Returns the USD conversion price of the StakingReward.
|
63
|
+
# @return [BigDecimal] The USD conversion price
|
64
|
+
def usd_conversion_price
|
65
|
+
BigDecimal(@model.usd_value.conversion_price.to_i) / BigDecimal(100)
|
66
|
+
end
|
67
|
+
|
68
|
+
# Returns the USD conversion time of the StakingReward.
|
69
|
+
# @return [Time] The USD conversion time
|
70
|
+
def usd_conversion_time
|
71
|
+
@model.usd_value.conversion_time
|
72
|
+
end
|
73
|
+
|
56
74
|
# Returns a string representation of the StakingReward.
|
57
75
|
# @return [String] a string representation of the StakingReward
|
58
76
|
def to_s
|
data/lib/coinbase/trade.rb
CHANGED
@@ -147,7 +147,7 @@ module Coinbase
|
|
147
147
|
|
148
148
|
payloads = { signed_payload: transaction.raw.hex }
|
149
149
|
|
150
|
-
payloads[:
|
150
|
+
payloads[:approve_transaction_signed_payload] = approve_transaction.raw.hex unless approve_transaction.nil?
|
151
151
|
|
152
152
|
@model = Coinbase.call_api do
|
153
153
|
trades_api.broadcast_trade(wallet_id, address_id, id, payloads)
|
data/lib/coinbase/transaction.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative 'constants'
|
4
|
-
require 'bigdecimal'
|
5
3
|
require 'eth'
|
6
4
|
require 'json'
|
7
5
|
|
@@ -113,12 +111,18 @@ module Coinbase
|
|
113
111
|
@raw = Eth::Tx::Eip1559.new(Eth::Tx.validate_eip1559_params(params))
|
114
112
|
end
|
115
113
|
|
114
|
+
# Returns the signature of the Transaction.
|
115
|
+
# @return [String] The hex-encode signature
|
116
|
+
def signature
|
117
|
+
raw.hex
|
118
|
+
end
|
119
|
+
|
116
120
|
# Signs the Transaction with the provided key and returns the hex signing payload.
|
117
121
|
# @return [String] The hex-encoded signed payload
|
118
122
|
def sign(key)
|
119
123
|
raw.sign(key)
|
120
124
|
|
121
|
-
|
125
|
+
signature
|
122
126
|
end
|
123
127
|
|
124
128
|
# Returns whether the Transaction has been signed.
|
data/lib/coinbase/transfer.rb
CHANGED
@@ -3,7 +3,6 @@
|
|
3
3
|
require_relative 'constants'
|
4
4
|
require 'bigdecimal'
|
5
5
|
require 'eth'
|
6
|
-
require 'json'
|
7
6
|
|
8
7
|
module Coinbase
|
9
8
|
# A representation of a Transfer, which moves an amount of an Asset from
|
@@ -25,7 +24,7 @@ module Coinbase
|
|
25
24
|
# @param wallet_id [String] The Wallet ID of the sending Wallet
|
26
25
|
# @return [Transfer] The new pending Transfer object
|
27
26
|
# @raise [Coinbase::ApiError] If the Transfer fails
|
28
|
-
def create(address_id:, amount:, asset_id:, destination:, network_id:, wallet_id:)
|
27
|
+
def create(address_id:, amount:, asset_id:, destination:, network_id:, wallet_id:, gasless: false)
|
29
28
|
asset = Asset.fetch(network_id, asset_id)
|
30
29
|
|
31
30
|
model = Coinbase.call_api do
|
@@ -36,7 +35,8 @@ module Coinbase
|
|
36
35
|
amount: asset.to_atomic_amount(amount).to_i.to_s,
|
37
36
|
asset_id: asset.primary_denomination.to_s,
|
38
37
|
destination: Coinbase::Destination.new(destination, network_id: network_id).address_id,
|
39
|
-
network_id: Coinbase.normalize_network(network_id)
|
38
|
+
network_id: Coinbase.normalize_network(network_id),
|
39
|
+
gasless: gasless
|
40
40
|
}
|
41
41
|
)
|
42
42
|
end
|
@@ -122,41 +122,52 @@ module Coinbase
|
|
122
122
|
BigDecimal(@model.amount) / BigDecimal(10).power(@model.asset.decimals)
|
123
123
|
end
|
124
124
|
|
125
|
-
#
|
126
|
-
# @
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
125
|
+
# Signs the Transfer with the given key. This is required before broadcasting the Transfer.
|
126
|
+
# @param key [Eth::Key] The key to sign the Transfer with
|
127
|
+
# @raise [RuntimeError] If the key is not an Eth::Key
|
128
|
+
# @return [Transfer] The Transfer object
|
129
|
+
def sign(key)
|
130
|
+
raise unless key.is_a?(Eth::Key)
|
131
131
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
132
|
+
unless sponsored_send.nil?
|
133
|
+
sponsored_send.sign(key)
|
134
|
+
|
135
|
+
return
|
136
|
+
end
|
137
137
|
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
@model.signed_payload
|
138
|
+
transaction.sign(key)
|
139
|
+
|
140
|
+
self
|
142
141
|
end
|
143
142
|
|
144
143
|
# Returns the Transfer transaction.
|
145
144
|
# @return [Coinbase::Transaction] The Transfer transaction
|
146
145
|
def transaction
|
147
|
-
@transaction ||= Coinbase::Transaction.new(@model.transaction)
|
146
|
+
@transaction ||= @model.transaction.nil? ? nil : Coinbase::Transaction.new(@model.transaction)
|
148
147
|
end
|
149
148
|
|
150
|
-
# Returns the
|
151
|
-
# @return [
|
152
|
-
def
|
153
|
-
@model.
|
149
|
+
# Returns the SponsoredSend of the Transfer, if the transfer is gasless.
|
150
|
+
# @return [Coinbase::SponsoredSend] The SponsoredSend object
|
151
|
+
def sponsored_send
|
152
|
+
@sponsored_send ||= @model.sponsored_send.nil? ? nil : Coinbase::SponsoredSend.new(@model.sponsored_send)
|
154
153
|
end
|
155
154
|
|
156
155
|
# Returns the status of the Transfer.
|
157
156
|
# @return [Symbol] The status
|
158
157
|
def status
|
159
|
-
|
158
|
+
send_tx_delegate.status
|
159
|
+
end
|
160
|
+
|
161
|
+
# Returns the link to the transaction on the blockchain explorer.
|
162
|
+
# @return [String] The link to the transaction on the blockchain explorer
|
163
|
+
def transaction_link
|
164
|
+
send_tx_delegate.transaction_link
|
165
|
+
end
|
166
|
+
|
167
|
+
# Returns the Transaction Hash of the Transfer.
|
168
|
+
# @return [String] The Transaction Hash
|
169
|
+
def transaction_hash
|
170
|
+
send_tx_delegate.transaction_hash
|
160
171
|
end
|
161
172
|
|
162
173
|
# Broadcasts the Transfer to the Network.
|
@@ -164,18 +175,19 @@ module Coinbase
|
|
164
175
|
# @raise [RuntimeError] If the Transfer is not signed
|
165
176
|
# @return [Transfer] The Transfer object
|
166
177
|
def broadcast!
|
167
|
-
raise TransactionNotSignedError unless
|
178
|
+
raise TransactionNotSignedError unless send_tx_delegate.signed?
|
168
179
|
|
169
180
|
@model = Coinbase.call_api do
|
170
181
|
transfers_api.broadcast_transfer(
|
171
182
|
wallet_id,
|
172
183
|
from_address_id,
|
173
184
|
id,
|
174
|
-
{ signed_payload:
|
185
|
+
{ signed_payload: send_tx_delegate.signature }
|
175
186
|
)
|
176
187
|
end
|
177
188
|
|
178
|
-
update_transaction(@model)
|
189
|
+
update_transaction(@model) unless @model.transaction.nil?
|
190
|
+
update_sponsored_send(@model) unless @model.sponsored_send.nil?
|
179
191
|
|
180
192
|
self
|
181
193
|
end
|
@@ -187,7 +199,8 @@ module Coinbase
|
|
187
199
|
transfers_api.get_transfer(wallet_id, from_address_id, id)
|
188
200
|
end
|
189
201
|
|
190
|
-
update_transaction(@model)
|
202
|
+
update_transaction(@model) unless @model.transaction.nil?
|
203
|
+
update_sponsored_send(@model) unless @model.sponsored_send.nil?
|
191
204
|
|
192
205
|
self
|
193
206
|
end
|
@@ -203,7 +216,7 @@ module Coinbase
|
|
203
216
|
loop do
|
204
217
|
reload
|
205
218
|
|
206
|
-
return self if
|
219
|
+
return self if terminal_state?
|
207
220
|
|
208
221
|
raise Timeout::Error, 'Transfer timed out' if Time.now - start_time > timeout_seconds
|
209
222
|
|
@@ -230,6 +243,16 @@ module Coinbase
|
|
230
243
|
|
231
244
|
private
|
232
245
|
|
246
|
+
def terminal_state?
|
247
|
+
send_tx_delegate.terminal_state?
|
248
|
+
end
|
249
|
+
|
250
|
+
def send_tx_delegate
|
251
|
+
return sponsored_send unless sponsored_send.nil?
|
252
|
+
|
253
|
+
transaction
|
254
|
+
end
|
255
|
+
|
233
256
|
def transfers_api
|
234
257
|
@transfers_api ||= Coinbase::Client::TransfersApi.new(Coinbase.configuration.api_client)
|
235
258
|
end
|
@@ -237,5 +260,9 @@ module Coinbase
|
|
237
260
|
def update_transaction(model)
|
238
261
|
@transaction = Coinbase::Transaction.new(model.transaction)
|
239
262
|
end
|
263
|
+
|
264
|
+
def update_sponsored_send(model)
|
265
|
+
@sponsored_send = Coinbase::SponsoredSend.new(model.sponsored_send)
|
266
|
+
end
|
240
267
|
end
|
241
268
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Coinbase
|
4
|
+
class Wallet
|
5
|
+
# The data required to recreate a Wallet.
|
6
|
+
class Data
|
7
|
+
attr_reader :wallet_id, :seed
|
8
|
+
|
9
|
+
# Returns a new Data object.
|
10
|
+
# @param wallet_id [String] The ID of the Wallet
|
11
|
+
# @param seed [String] The seed of the Wallet
|
12
|
+
def initialize(wallet_id:, seed:)
|
13
|
+
@wallet_id = wallet_id
|
14
|
+
@seed = seed
|
15
|
+
end
|
16
|
+
|
17
|
+
# Converts the Data object to a Hash.
|
18
|
+
# @return [Hash] The Hash representation of the Data object
|
19
|
+
def to_hash
|
20
|
+
{ wallet_id: wallet_id, seed: seed }
|
21
|
+
end
|
22
|
+
|
23
|
+
# Creates a Data object from the given Hash.
|
24
|
+
# @param data [Hash] The Hash to create the Data object from
|
25
|
+
# @return [Data] The new Data object
|
26
|
+
def self.from_hash(data)
|
27
|
+
Data.new(wallet_id: data['wallet_id'], seed: data['seed'])
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/coinbase/wallet.rb
CHANGED
@@ -5,6 +5,8 @@ require 'json'
|
|
5
5
|
require 'money-tree'
|
6
6
|
require 'securerandom'
|
7
7
|
|
8
|
+
require_relative 'wallet/data'
|
9
|
+
|
8
10
|
module Coinbase
|
9
11
|
# A representation of a Wallet. Wallets come with a single default Address, but can expand to have a set of Addresses,
|
10
12
|
# each of which can hold a balance of one or more Assets. Wallets can create new Addresses, list their addresses,
|
@@ -13,17 +15,6 @@ module Coinbase
|
|
13
15
|
# The maximum number of addresses in a Wallet.
|
14
16
|
MAX_ADDRESSES = 20
|
15
17
|
|
16
|
-
# A representation of ServerSigner status in a Wallet.
|
17
|
-
module ServerSignerStatus
|
18
|
-
# The Wallet is awaiting seed creation by the ServerSigner. At this point,
|
19
|
-
# the Wallet cannot create addresses or sign transactions.
|
20
|
-
PENDING = 'pending_seed_creation'
|
21
|
-
|
22
|
-
# The Wallet has an associated seed created by the ServerSigner. It is ready
|
23
|
-
# to create addresses and sign transactions.
|
24
|
-
ACTIVE = 'active_seed'
|
25
|
-
end
|
26
|
-
|
27
18
|
class << self
|
28
19
|
# Imports a Wallet from previously exported wallet data.
|
29
20
|
# @param data [Coinbase::Wallet::Data] the Wallet data to import
|
@@ -43,7 +34,7 @@ module Coinbase
|
|
43
34
|
# converted to an array, etc...
|
44
35
|
# @return [Enumerable<Coinbase::Wallet>] Enumerator that returns wallets
|
45
36
|
def list
|
46
|
-
Coinbase::Pagination.enumerate(
|
37
|
+
Coinbase::Pagination.enumerate(method(:fetch_wallets_page)) do |wallet|
|
47
38
|
Coinbase::Wallet.new(wallet, seed: '')
|
48
39
|
end
|
49
40
|
end
|
@@ -107,7 +98,7 @@ module Coinbase
|
|
107
98
|
wallets_api.get_wallet(wallet_id)
|
108
99
|
end
|
109
100
|
|
110
|
-
return self if model.server_signer_status ==
|
101
|
+
return self if model.server_signer_status == ServerSigner::Status::ACTIVE
|
111
102
|
|
112
103
|
if Time.now - start_time > timeout_seconds
|
113
104
|
raise Timeout::Error, 'Wallet creation timed out. Check status of your Server-Signer'
|
@@ -278,9 +269,15 @@ module Coinbase
|
|
278
269
|
# @param asset_id [Symbol] The ID of the Asset to send
|
279
270
|
# @param destination [Wallet | Address | String] The destination of the transfer. If a Wallet, sends to the Wallet's
|
280
271
|
# default address. If a String, interprets it as the address ID.
|
272
|
+
# @param gasless [Boolean] Whether gas fee for the transfer should be covered by Coinbase.
|
273
|
+
# Defaults to false. Check the API documentation for network and asset support.
|
281
274
|
# @return [Coinbase::Transfer] The Transfer object.
|
282
|
-
def transfer(amount, asset_id, destination)
|
283
|
-
|
275
|
+
def transfer(amount, asset_id, destination, options = {})
|
276
|
+
# For ruby 2.7 compatibility we cannot pass in keyword args when the create wallet
|
277
|
+
# options is empty
|
278
|
+
return default_address.transfer(amount, asset_id, destination) if options.empty?
|
279
|
+
|
280
|
+
default_address.transfer(amount, asset_id, destination, **options)
|
284
281
|
end
|
285
282
|
|
286
283
|
# Trades the given amount of the given Asset for another Asset.
|
@@ -294,8 +291,84 @@ module Coinbase
|
|
294
291
|
default_address.trade(amount, from_asset_id, to_asset_id)
|
295
292
|
end
|
296
293
|
|
294
|
+
# Stakes the given amount of the given Asset.
|
295
|
+
# Currently only the default_address is used to source the Stake.
|
296
|
+
# @param amount [Integer, Float, BigDecimal] The amount of the Asset to stake.
|
297
|
+
# @param asset_id [Symbol] The ID of the Asset to stake.
|
298
|
+
# @param mode [Symbol] (Optional) The staking mode. Defaults to :default.
|
299
|
+
# @param options [Hash] (Optional) Additional options for the staking operation.
|
300
|
+
# @return [Coinbase::StakingOperation] The stake operation
|
301
|
+
def stake(amount, asset_id, mode: :default, options: {})
|
302
|
+
default_address.stake(amount, asset_id, mode: mode, options: options)
|
303
|
+
end
|
304
|
+
|
305
|
+
# Unstakes the given amount of the given Asset.
|
306
|
+
# Currently only the default_address is used to source the Unstake.
|
307
|
+
# @param amount [Integer, Float, BigDecimal] The amount of the Asset to unstake.
|
308
|
+
# @param asset_id [Symbol] The ID of the Asset to unstake.
|
309
|
+
# @param mode [Symbol] (Optional) The staking mode. Defaults to :default.
|
310
|
+
# @param options [Hash] (Optional) Additional options for the unstaking operation.
|
311
|
+
# @return [Coinbase::StakingOperation] The unstake operation
|
312
|
+
def unstake(amount, asset_id, mode: :default, options: {})
|
313
|
+
default_address.unstake(amount, asset_id, mode: mode, options: options)
|
314
|
+
end
|
315
|
+
|
316
|
+
# Claims stake of the given amount of the given Asset.
|
317
|
+
# Currently only the default_address is used as the source for claim_stake.
|
318
|
+
# @param amount [Integer, Float, BigDecimal] The amount of the Asset to claim_stake.
|
319
|
+
# @param asset_id [Symbol] The ID of the Asset to claim_stake.
|
320
|
+
# @param mode [Symbol] (Optional) The staking mode. Defaults to :default.
|
321
|
+
# @param options [Hash] (Optional) Additional options for the unstaking operation.
|
322
|
+
# @return [Coinbase::StakingOperation] The claim_stake operation
|
323
|
+
def claim_stake(amount, asset_id, mode: :default, options: {})
|
324
|
+
default_address.claim_stake(amount, asset_id, mode: mode, options: options)
|
325
|
+
end
|
326
|
+
|
327
|
+
# Retrieves the balances used for staking for the supplied asset.
|
328
|
+
# Currently only the default_address is used to source the staking balances.
|
329
|
+
# @param asset_id [Symbol] The asset to retrieve staking balances for
|
330
|
+
# @param mode [Symbol] The staking mode. Defaults to :default.
|
331
|
+
# @param options [Hash] Additional options for the staking operation
|
332
|
+
# @return [Hash] The staking balances
|
333
|
+
# @return [BigDecimal] :stakeable_balance The amount of the asset that can be staked
|
334
|
+
# @return [BigDecimal] :unstakeable_balance The amount of the asset that is currently staked and cannot be unstaked
|
335
|
+
# @return [BigDecimal] :claimable_balance The amount of the asset that can be claimed
|
336
|
+
def staking_balances(asset_id, mode: :default, options: {})
|
337
|
+
default_address.staking_balances(asset_id, mode: mode, options: options)
|
338
|
+
end
|
339
|
+
|
340
|
+
# Retrieves the stakeable balance for the supplied asset.
|
341
|
+
# Currently only the default_address is used to source the stakeable balance.
|
342
|
+
# @param asset_id [Symbol] The asset to retrieve the stakeable balance for
|
343
|
+
# @param mode [Symbol] The staking mode. Defaults to :default.
|
344
|
+
# @param options [Hash] Additional options for the staking operation
|
345
|
+
# @return [BigDecimal] The stakeable balance
|
346
|
+
def stakeable_balance(asset_id, mode: :default, options: {})
|
347
|
+
default_address.stakeable_balance(asset_id, mode: mode, options: options)
|
348
|
+
end
|
349
|
+
|
350
|
+
# Retrieves the unstakeable balance for the supplied asset.
|
351
|
+
# Currently only the default_address is used to source the unstakeable balance.
|
352
|
+
# @param asset_id [Symbol] The asset to retrieve the unstakeable balance for
|
353
|
+
# @param mode [Symbol] The staking mode. Defaults to :default.
|
354
|
+
# @param options [Hash] Additional options for the staking operation
|
355
|
+
# @return [BigDecimal] The unstakeable balance
|
356
|
+
def unstakeable_balance(asset_id, mode: :default, options: {})
|
357
|
+
default_address.unstakeable_balance(asset_id, mode: mode, options: options)
|
358
|
+
end
|
359
|
+
|
360
|
+
# Retrieves the claimable balance for the supplied asset.
|
361
|
+
# Currently only the default_address is used to source the claimable balance.
|
362
|
+
# @param asset_id [Symbol] The asset to retrieve the claimable balance for
|
363
|
+
# @param mode [Symbol] The staking mode. Defaults to :default.
|
364
|
+
# @param options [Hash] Additional options for the staking operation
|
365
|
+
# @return [BigDecimal] The claimable balance
|
366
|
+
def claimable_balance(asset_id, mode: :default, options: {})
|
367
|
+
default_address.claimable_balance(asset_id, mode: mode, options: options)
|
368
|
+
end
|
369
|
+
|
297
370
|
# Exports the Wallet's data to a Data object.
|
298
|
-
# @return [Data] The Wallet data
|
371
|
+
# @return [Coinbase::Wallet::Data] The Wallet data
|
299
372
|
def export
|
300
373
|
# TODO: Improve this check by relying on the backend data to decide whether a wallet is server-signer backed.
|
301
374
|
raise 'Cannot export data for Server-Signer backed Wallet' if Coinbase.use_server_signer?
|
@@ -357,9 +430,7 @@ module Coinbase
|
|
357
430
|
iv: iv
|
358
431
|
}
|
359
432
|
|
360
|
-
File.
|
361
|
-
file.write(JSON.pretty_generate(existing_seeds_in_store))
|
362
|
-
end
|
433
|
+
File.write(file_path, JSON.pretty_generate(existing_seeds_in_store))
|
363
434
|
|
364
435
|
"Successfully saved seed for wallet #{id} to #{file_path}."
|
365
436
|
end
|
@@ -416,32 +487,6 @@ module Coinbase
|
|
416
487
|
to_s
|
417
488
|
end
|
418
489
|
|
419
|
-
# The data required to recreate a Wallet.
|
420
|
-
class Data
|
421
|
-
attr_reader :wallet_id, :seed
|
422
|
-
|
423
|
-
# Returns a new Data object.
|
424
|
-
# @param wallet_id [String] The ID of the Wallet
|
425
|
-
# @param seed [String] The seed of the Wallet
|
426
|
-
def initialize(wallet_id:, seed:)
|
427
|
-
@wallet_id = wallet_id
|
428
|
-
@seed = seed
|
429
|
-
end
|
430
|
-
|
431
|
-
# Converts the Data object to a Hash.
|
432
|
-
# @return [Hash] The Hash representation of the Data object
|
433
|
-
def to_hash
|
434
|
-
{ wallet_id: wallet_id, seed: seed }
|
435
|
-
end
|
436
|
-
|
437
|
-
# Creates a Data object from the given Hash.
|
438
|
-
# @param data [Hash] The Hash to create the Data object from
|
439
|
-
# @return [Data] The new Data object
|
440
|
-
def self.from_hash(data)
|
441
|
-
Data.new(wallet_id: data['wallet_id'], seed: data['seed'])
|
442
|
-
end
|
443
|
-
end
|
444
|
-
|
445
490
|
private
|
446
491
|
|
447
492
|
# Reloads the Wallet with the latest data.
|
@@ -464,7 +509,7 @@ module Coinbase
|
|
464
509
|
def address_path_prefix
|
465
510
|
# TODO: Push this logic to the backend.
|
466
511
|
@address_path_prefix ||= case network_id.to_s.split('_').first
|
467
|
-
when 'base', 'ethereum'
|
512
|
+
when 'base', 'ethereum', 'polygon'
|
468
513
|
"m/44'/60'/0'/0"
|
469
514
|
else
|
470
515
|
raise ArgumentError, "Unsupported network ID: #{network_id}"
|
data/lib/coinbase.rb
CHANGED
@@ -7,6 +7,7 @@ require_relative 'coinbase/asset'
|
|
7
7
|
require_relative 'coinbase/authenticator'
|
8
8
|
require_relative 'coinbase/balance'
|
9
9
|
require_relative 'coinbase/balance_map'
|
10
|
+
require_relative 'coinbase/historical_balance'
|
10
11
|
require_relative 'coinbase/client'
|
11
12
|
require_relative 'coinbase/constants'
|
12
13
|
require_relative 'coinbase/destination'
|
@@ -21,6 +22,8 @@ require_relative 'coinbase/transaction'
|
|
21
22
|
require_relative 'coinbase/user'
|
22
23
|
require_relative 'coinbase/wallet'
|
23
24
|
require_relative 'coinbase/server_signer'
|
25
|
+
require_relative 'coinbase/sponsored_send'
|
26
|
+
require_relative 'coinbase/staking_balance'
|
24
27
|
require_relative 'coinbase/staking_operation'
|
25
28
|
require_relative 'coinbase/staking_reward'
|
26
29
|
require_relative 'coinbase/validator'
|
@@ -62,13 +65,14 @@ module Coinbase
|
|
62
65
|
|
63
66
|
# Configuration object for the Coinbase SDK.
|
64
67
|
class Configuration
|
65
|
-
attr_accessor :api_url, :api_key_name, :api_key_private_key, :debug_api, :use_server_signer
|
68
|
+
attr_accessor :api_url, :api_key_name, :api_key_private_key, :debug_api, :use_server_signer, :max_network_tries
|
66
69
|
|
67
70
|
# Initializes the configuration object.
|
68
71
|
def initialize
|
69
72
|
@api_url = 'https://api.cdp.coinbase.com'
|
70
73
|
@debug_api = false
|
71
74
|
@use_server_signer = false
|
75
|
+
@max_network_tries = 3
|
72
76
|
end
|
73
77
|
|
74
78
|
# Sets configuration values based on the provided CDP API Key JSON file.
|
@@ -110,7 +114,7 @@ module Coinbase
|
|
110
114
|
# @param network_sym [Symbol] the network symbol to convert
|
111
115
|
# @return [String] the converted string
|
112
116
|
def self.normalize_network(network_sym)
|
113
|
-
network_sym.to_s.gsub(
|
117
|
+
network_sym.to_s.gsub('_', '-')
|
114
118
|
end
|
115
119
|
|
116
120
|
# Loads the default user.
|
@@ -127,8 +131,17 @@ module Coinbase
|
|
127
131
|
yield
|
128
132
|
rescue Coinbase::Client::ApiError => e
|
129
133
|
raise Coinbase::APIError.from_error(e), cause: nil
|
130
|
-
|
131
|
-
|
134
|
+
end
|
135
|
+
|
136
|
+
# Returns a pretty-printed object string that contains the object's class name and
|
137
|
+
# the details of the object, filtering out nil values.
|
138
|
+
# @param klass [Class] the class of the object
|
139
|
+
# @param details [Hash] the details of the object
|
140
|
+
# @return [String] the pretty-printed object string
|
141
|
+
def self.pretty_print_object(klass, **details)
|
142
|
+
filtered_details = details.filter { |_, v| !v.nil? }.map { |k, v| "#{k}: '#{v}'" }
|
143
|
+
|
144
|
+
"#{klass}{#{filtered_details.join(', ')}}"
|
132
145
|
end
|
133
146
|
|
134
147
|
# Returns whether to use a server signer to manage private keys.
|