coinbase-sdk 0.0.13 → 0.0.16
Sign up to get free protection for your applications and to get access to all the features.
- 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.
|