coinbase-sdk 0.0.10 → 0.0.14
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 +80 -107
- data/lib/coinbase/address.rb +128 -0
- data/lib/coinbase/client/api/addresses_api.rb +1 -1
- data/lib/coinbase/client/api/assets_api.rb +3 -3
- data/lib/coinbase/client/api/contract_events_api.rb +121 -0
- data/lib/coinbase/client/api/external_addresses_api.rb +1 -1
- data/lib/coinbase/client/api/server_signers_api.rb +1 -1
- data/lib/coinbase/client/api/stake_api.rb +242 -1
- data/lib/coinbase/client/api/trades_api.rb +1 -1
- data/lib/coinbase/client/api/transfers_api.rb +1 -1
- data/lib/coinbase/client/api/users_api.rb +1 -1
- data/lib/coinbase/client/api/validators_api.rb +1 -1
- data/lib/coinbase/client/api/wallets_api.rb +1 -1
- data/lib/coinbase/client/api/webhooks_api.rb +286 -0
- data/lib/coinbase/client/api_client.rb +1 -1
- data/lib/coinbase/client/api_error.rb +1 -1
- data/lib/coinbase/client/configuration.rb +11 -1
- data/lib/coinbase/client/models/address.rb +1 -1
- data/lib/coinbase/client/models/address_balance_list.rb +1 -1
- data/lib/coinbase/client/models/address_list.rb +1 -1
- data/lib/coinbase/client/models/asset.rb +1 -1
- data/lib/coinbase/client/models/balance.rb +1 -1
- data/lib/coinbase/client/models/broadcast_staking_operation_request.rb +239 -0
- data/lib/coinbase/client/models/broadcast_trade_request.rb +1 -1
- data/lib/coinbase/client/models/broadcast_transfer_request.rb +1 -1
- data/lib/coinbase/client/models/build_staking_operation_request.rb +1 -1
- 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_address_request.rb +1 -1
- data/lib/coinbase/client/models/create_server_signer_request.rb +1 -1
- data/lib/coinbase/client/models/create_staking_operation_request.rb +274 -0
- data/lib/coinbase/client/models/create_trade_request.rb +1 -1
- data/lib/coinbase/client/models/create_transfer_request.rb +1 -1
- data/lib/coinbase/client/models/create_wallet_request.rb +1 -1
- data/lib/coinbase/client/models/create_wallet_request_wallet.rb +1 -1
- data/lib/coinbase/client/models/create_webhook_request.rb +282 -0
- data/lib/coinbase/client/models/error.rb +1 -1
- data/lib/coinbase/client/models/ethereum_validator_metadata.rb +1 -1
- data/lib/coinbase/client/models/faucet_transaction.rb +1 -1
- data/lib/coinbase/client/models/feature.rb +1 -1
- data/lib/coinbase/client/models/fetch_staking_rewards200_response.rb +1 -1
- data/lib/coinbase/client/models/fetch_staking_rewards_request.rb +1 -1
- data/lib/coinbase/client/models/get_staking_context_request.rb +1 -1
- data/lib/coinbase/client/models/native_eth_staking_context.rb +1 -1
- data/lib/coinbase/client/models/partial_eth_staking_context.rb +1 -1
- data/lib/coinbase/client/models/seed_creation_event.rb +1 -1
- data/lib/coinbase/client/models/seed_creation_event_result.rb +1 -1
- data/lib/coinbase/client/models/server_signer.rb +1 -1
- data/lib/coinbase/client/models/server_signer_event.rb +1 -1
- data/lib/coinbase/client/models/server_signer_event_event.rb +1 -1
- data/lib/coinbase/client/models/server_signer_event_list.rb +1 -1
- data/lib/coinbase/client/models/server_signer_list.rb +1 -1
- data/lib/coinbase/client/models/signature_creation_event.rb +1 -1
- data/lib/coinbase/client/models/signature_creation_event_result.rb +1 -1
- data/lib/coinbase/client/models/signed_voluntary_exit_message_metadata.rb +1 -1
- data/lib/coinbase/client/models/staking_context.rb +1 -1
- data/lib/coinbase/client/models/staking_context_context.rb +1 -1
- data/lib/coinbase/client/models/staking_operation.rb +16 -6
- data/lib/coinbase/client/models/staking_operation_metadata.rb +1 -1
- data/lib/coinbase/client/models/staking_reward.rb +1 -1
- data/lib/coinbase/client/models/staking_reward_format.rb +1 -1
- data/lib/coinbase/client/models/trade.rb +1 -1
- data/lib/coinbase/client/models/trade_list.rb +1 -1
- data/lib/coinbase/client/models/transaction.rb +1 -1
- data/lib/coinbase/client/models/transaction_type.rb +1 -1
- data/lib/coinbase/client/models/transfer.rb +5 -93
- data/lib/coinbase/client/models/transfer_list.rb +1 -1
- data/lib/coinbase/client/models/update_webhook_request.rb +289 -0
- data/lib/coinbase/client/models/user.rb +1 -1
- data/lib/coinbase/client/models/validator.rb +1 -1
- data/lib/coinbase/client/models/validator_details.rb +1 -1
- data/lib/coinbase/client/models/validator_list.rb +1 -1
- data/lib/coinbase/client/models/wallet.rb +1 -1
- data/lib/coinbase/client/models/wallet_list.rb +1 -1
- 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 +41 -0
- data/lib/coinbase/client/models/webhook_list.rb +244 -0
- data/lib/coinbase/client/version.rb +1 -1
- data/lib/coinbase/client.rb +13 -1
- data/lib/coinbase/constants.rb +3 -0
- data/lib/coinbase/destination.rb +51 -0
- data/lib/coinbase/errors.rb +14 -0
- data/lib/coinbase/middleware.rb +12 -0
- data/lib/coinbase/staking_operation.rb +106 -5
- data/lib/coinbase/trade.rb +87 -5
- data/lib/coinbase/transaction.rb +13 -2
- data/lib/coinbase/transfer.rb +86 -7
- data/lib/coinbase/wallet.rb +77 -4
- data/lib/coinbase.rb +3 -1
- metadata +29 -2
data/lib/coinbase/middleware.rb
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
require_relative 'authenticator'
|
4
4
|
require_relative 'client/configuration'
|
5
5
|
require 'faraday'
|
6
|
+
require 'faraday/retry'
|
6
7
|
|
7
8
|
module Coinbase
|
8
9
|
# A module for middleware that can be used with Faraday.
|
@@ -18,6 +19,17 @@ module Coinbase
|
|
18
19
|
config.host = uri.host + (uri.port ? ":#{uri.port}" : '')
|
19
20
|
config.scheme = uri.scheme if uri.scheme
|
20
21
|
config.request(:authenticator)
|
22
|
+
retry_options = {
|
23
|
+
max: Coinbase.configuration.max_network_tries,
|
24
|
+
interval: 0.05,
|
25
|
+
interval_randomness: 0.5,
|
26
|
+
backoff_factor: 2,
|
27
|
+
methods: %i[get],
|
28
|
+
retry_statuses: [500, 502, 503, 504]
|
29
|
+
}
|
30
|
+
config.configure_faraday_connection do |conn|
|
31
|
+
conn.request :retry, retry_options
|
32
|
+
end
|
21
33
|
end
|
22
34
|
end
|
23
35
|
end
|
@@ -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
|
data/lib/coinbase/trade.rb
CHANGED
@@ -9,6 +9,57 @@ module Coinbase
|
|
9
9
|
# The fee is assumed to be paid in the native Asset of the Network.
|
10
10
|
# Trades should be created through Wallet#trade or # Address#trade.
|
11
11
|
class Trade
|
12
|
+
class << self
|
13
|
+
# Creates a new Trade object.
|
14
|
+
# @param address_id [String] The Address ID of the sending Address
|
15
|
+
# @param from_asset_id [Symbol] The Asset ID of the Asset to trade from
|
16
|
+
# @param to_asset_id [Symbol] The Asset ID of the Asset to trade to
|
17
|
+
# @param amount [BigDecimal] The amount of the Asset to send
|
18
|
+
# @param network_id [Symbol] The Network ID of the Asset
|
19
|
+
# @param wallet_id [String] The Wallet ID of the sending Wallet
|
20
|
+
# @return [Send] The new pending Send object
|
21
|
+
def create(address_id:, from_asset_id:, to_asset_id:, amount:, network_id:, wallet_id:)
|
22
|
+
from_asset = Asset.fetch(network_id, from_asset_id)
|
23
|
+
to_asset = Asset.fetch(network_id, to_asset_id)
|
24
|
+
|
25
|
+
model = Coinbase.call_api do
|
26
|
+
trades_api.create_trade(
|
27
|
+
wallet_id,
|
28
|
+
address_id,
|
29
|
+
{
|
30
|
+
amount: from_asset.to_atomic_amount(amount).to_i.to_s,
|
31
|
+
from_asset_id: from_asset.primary_denomination.to_s,
|
32
|
+
to_asset_id: to_asset.primary_denomination.to_s
|
33
|
+
}
|
34
|
+
)
|
35
|
+
end
|
36
|
+
|
37
|
+
new(model)
|
38
|
+
end
|
39
|
+
|
40
|
+
# Enumerates the trades for a given address belonging to a wallet.
|
41
|
+
# The result is an enumerator that lazily fetches from the server, and can be iterated over,
|
42
|
+
# converted to an array, etc...
|
43
|
+
# @return [Enumerable<Coinbase::Trade>] Enumerator that returns trades
|
44
|
+
def list(wallet_id:, address_id:)
|
45
|
+
Coinbase::Pagination.enumerate(
|
46
|
+
->(page) { fetch_page(wallet_id, address_id, page) }
|
47
|
+
) do |trade|
|
48
|
+
new(trade)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def trades_api
|
55
|
+
Coinbase::Client::TradesApi.new(Coinbase.configuration.api_client)
|
56
|
+
end
|
57
|
+
|
58
|
+
def fetch_page(wallet_id, address_id, page)
|
59
|
+
trades_api.list_trades(wallet_id, address_id, { limit: DEFAULT_PAGE_LIMIT, page: page })
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
12
63
|
# Returns a new Trade object. Do not use this method directly. Instead, use Wallet#trade or
|
13
64
|
# Address#trade.
|
14
65
|
# @param model [Coinbase::Client::Trade] The underlying Trade object
|
@@ -76,12 +127,37 @@ module Coinbase
|
|
76
127
|
@approve_transaction ||= @model.approve_transaction ? Coinbase::Transaction.new(@model.approve_transaction) : nil
|
77
128
|
end
|
78
129
|
|
130
|
+
# Returns the list of Transactions for the Trade.
|
131
|
+
def transactions
|
132
|
+
[approve_transaction, transaction].compact
|
133
|
+
end
|
134
|
+
|
79
135
|
# Returns the status of the Trade.
|
80
136
|
# @return [Symbol] The status
|
81
137
|
def status
|
82
138
|
transaction.status
|
83
139
|
end
|
84
140
|
|
141
|
+
# Broadcasts the Trade to the Network.
|
142
|
+
# This raises an error if the Trade is not signed.
|
143
|
+
# @raise [RuntimeError] If the Trade is not signed
|
144
|
+
# @return [Trade] The Trade object
|
145
|
+
def broadcast!
|
146
|
+
raise TransactionNotSignedError unless transactions.all?(&:signed?)
|
147
|
+
|
148
|
+
payloads = { signed_payload: transaction.raw.hex }
|
149
|
+
|
150
|
+
payloads[:approve_transaction_signed_payload] = approve_transaction.raw.hex unless approve_transaction.nil?
|
151
|
+
|
152
|
+
@model = Coinbase.call_api do
|
153
|
+
trades_api.broadcast_trade(wallet_id, address_id, id, payloads)
|
154
|
+
end
|
155
|
+
|
156
|
+
update_transactions(@model)
|
157
|
+
|
158
|
+
self
|
159
|
+
end
|
160
|
+
|
85
161
|
# Waits until the Trade is completed or failed by polling the Network at the given interval. Raises a
|
86
162
|
# Timeout::Error if the Trade takes longer than the given timeout.
|
87
163
|
# @param interval_seconds [Integer] The interval at which to poll the Network, in seconds
|
@@ -114,11 +190,7 @@ module Coinbase
|
|
114
190
|
trades_api.get_trade(wallet_id, address_id, id)
|
115
191
|
end
|
116
192
|
|
117
|
-
|
118
|
-
@transaction = Coinbase::Transaction.new(@model.transaction)
|
119
|
-
|
120
|
-
# Update the memoized approve transaction if it exists.
|
121
|
-
@approve_transaction = @model.approve_transaction ? Coinbase::Transaction.new(@model.approve_transaction) : nil
|
193
|
+
update_transactions(@model)
|
122
194
|
|
123
195
|
self
|
124
196
|
end
|
@@ -140,6 +212,16 @@ module Coinbase
|
|
140
212
|
|
141
213
|
private
|
142
214
|
|
215
|
+
def update_transactions(model)
|
216
|
+
# Update the memoized transaction.
|
217
|
+
@transaction = Coinbase::Transaction.new(model.transaction)
|
218
|
+
|
219
|
+
return if model.approve_transaction.nil?
|
220
|
+
|
221
|
+
# Update the memoized approve transaction if it exists.
|
222
|
+
@approve_transaction = Coinbase::Transaction.new(model.approve_transaction)
|
223
|
+
end
|
224
|
+
|
143
225
|
def trades_api
|
144
226
|
@trades_api ||= Coinbase::Client::TradesApi.new(Coinbase.configuration.api_client)
|
145
227
|
end
|
data/lib/coinbase/transaction.rb
CHANGED
@@ -15,6 +15,9 @@ module Coinbase
|
|
15
15
|
# At this point, transaction hashes may not yet be assigned.
|
16
16
|
PENDING = 'pending'
|
17
17
|
|
18
|
+
# The Transaction has been signed, but has not been successfully broadcast yet.
|
19
|
+
SIGNED = 'signed'
|
20
|
+
|
18
21
|
# The Transaction has been broadcast to the Network.
|
19
22
|
# At this point, at least the transaction hash should be assigned.
|
20
23
|
BROADCAST = 'broadcast'
|
@@ -84,6 +87,14 @@ module Coinbase
|
|
84
87
|
def raw
|
85
88
|
return @raw unless @raw.nil?
|
86
89
|
|
90
|
+
# If the transaction is signed, decode the signed payload.
|
91
|
+
unless signed_payload.nil?
|
92
|
+
@raw = Eth::Tx::Eip1559.decode(signed_payload)
|
93
|
+
|
94
|
+
return @raw
|
95
|
+
end
|
96
|
+
|
97
|
+
# If the transaction is unsigned, parse the unsigned payload into an EIP-1559 transaction.
|
87
98
|
raw_payload = [unsigned_payload].pack('H*')
|
88
99
|
parsed_payload = JSON.parse(raw_payload)
|
89
100
|
|
@@ -93,8 +104,8 @@ module Coinbase
|
|
93
104
|
priority_fee: parsed_payload['maxPriorityFeePerGas'].to_i(16),
|
94
105
|
max_gas_fee: parsed_payload['maxFeePerGas'].to_i(16),
|
95
106
|
gas_limit: parsed_payload['gas'].to_i(16), # TODO: Handle multiple currencies.
|
96
|
-
from:
|
97
|
-
to:
|
107
|
+
from: from_address_id,
|
108
|
+
to: parsed_payload['to'],
|
98
109
|
value: parsed_payload['value'].to_i(16),
|
99
110
|
data: parsed_payload['input'] || ''
|
100
111
|
}
|
data/lib/coinbase/transfer.rb
CHANGED
@@ -11,6 +11,62 @@ module Coinbase
|
|
11
11
|
# in the native Asset of the Network. Transfers should be created through Wallet#transfer or
|
12
12
|
# Address#transfer.
|
13
13
|
class Transfer
|
14
|
+
class << self
|
15
|
+
# Creates a new Transfer object.
|
16
|
+
# @param address_id [String] The Address ID of the sending Address
|
17
|
+
# @param amount [BigDecimal] The amount of the Asset to send
|
18
|
+
# @param asset_id [Symbol] The Asset ID of the Asset to send
|
19
|
+
# @param destination [Coinbase::Destination, Coinbase::Wallet, Coinbase::Address, String]
|
20
|
+
# The destination of the transfer.
|
21
|
+
# If the destination is a Wallet, it uses the default Address of the Wallet.
|
22
|
+
# If the destination is an Address, it uses the Address's ID.
|
23
|
+
# If the destination is a String, it uses it as the Address ID.
|
24
|
+
# @param network_id [Symbol] The Network ID of the Asset
|
25
|
+
# @param wallet_id [String] The Wallet ID of the sending Wallet
|
26
|
+
# @return [Transfer] The new pending Transfer object
|
27
|
+
# @raise [Coinbase::ApiError] If the Transfer fails
|
28
|
+
def create(address_id:, amount:, asset_id:, destination:, network_id:, wallet_id:)
|
29
|
+
asset = Asset.fetch(network_id, asset_id)
|
30
|
+
|
31
|
+
model = Coinbase.call_api do
|
32
|
+
transfers_api.create_transfer(
|
33
|
+
wallet_id,
|
34
|
+
address_id,
|
35
|
+
{
|
36
|
+
amount: asset.to_atomic_amount(amount).to_i.to_s,
|
37
|
+
asset_id: asset.primary_denomination.to_s,
|
38
|
+
destination: Coinbase::Destination.new(destination, network_id: network_id).address_id,
|
39
|
+
network_id: Coinbase.normalize_network(network_id)
|
40
|
+
}
|
41
|
+
)
|
42
|
+
end
|
43
|
+
|
44
|
+
new(model)
|
45
|
+
end
|
46
|
+
|
47
|
+
# Enumerates the transfers for a given address belonging to a wallet.
|
48
|
+
# The result is an enumerator that lazily fetches from the server, and can be iterated over,
|
49
|
+
# converted to an array, etc...
|
50
|
+
# @return [Enumerable<Coinbase::Transfer>] Enumerator that returns transfers
|
51
|
+
def list(wallet_id:, address_id:)
|
52
|
+
Coinbase::Pagination.enumerate(
|
53
|
+
->(page) { fetch_page(wallet_id, address_id, page) }
|
54
|
+
) do |transfer|
|
55
|
+
new(transfer)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def transfers_api
|
62
|
+
Coinbase::Client::TransfersApi.new(Coinbase.configuration.api_client)
|
63
|
+
end
|
64
|
+
|
65
|
+
def fetch_page(wallet_id, address_id, page)
|
66
|
+
transfers_api.list_transfers(wallet_id, address_id, { limit: DEFAULT_PAGE_LIMIT, page: page })
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
14
70
|
# Returns a new Transfer object. Do not use this method directly. Instead, use Wallet#transfer or
|
15
71
|
# Address#transfer.
|
16
72
|
# @param model [Coinbase::Client::Transfer] The underlying Transfer object
|
@@ -69,20 +125,19 @@ module Coinbase
|
|
69
125
|
# Returns the link to the transaction on the blockchain explorer.
|
70
126
|
# @return [String] The link to the transaction on the blockchain explorer
|
71
127
|
def transaction_link
|
72
|
-
|
73
|
-
"https://sepolia.basescan.org/tx/#{transaction_hash}"
|
128
|
+
transaction.transaction_link
|
74
129
|
end
|
75
130
|
|
76
131
|
# Returns the Unsigned Payload of the Transfer.
|
77
132
|
# @return [String] The Unsigned Payload
|
78
133
|
def unsigned_payload
|
79
|
-
|
134
|
+
transaction.unsigned_payload
|
80
135
|
end
|
81
136
|
|
82
137
|
# Returns the Signed Payload of the Transfer.
|
83
138
|
# @return [String] The Signed Payload
|
84
139
|
def signed_payload
|
85
|
-
|
140
|
+
transaction.signed_payload
|
86
141
|
end
|
87
142
|
|
88
143
|
# Returns the Transfer transaction.
|
@@ -94,7 +149,7 @@ module Coinbase
|
|
94
149
|
# Returns the Transaction Hash of the Transfer.
|
95
150
|
# @return [String] The Transaction Hash
|
96
151
|
def transaction_hash
|
97
|
-
|
152
|
+
transaction.transaction_hash
|
98
153
|
end
|
99
154
|
|
100
155
|
# Returns the status of the Transfer.
|
@@ -103,6 +158,27 @@ module Coinbase
|
|
103
158
|
transaction.status
|
104
159
|
end
|
105
160
|
|
161
|
+
# Broadcasts the Transfer to the Network.
|
162
|
+
# This raises an error if the Transfer is not signed.
|
163
|
+
# @raise [RuntimeError] If the Transfer is not signed
|
164
|
+
# @return [Transfer] The Transfer object
|
165
|
+
def broadcast!
|
166
|
+
raise TransactionNotSignedError unless transaction.signed?
|
167
|
+
|
168
|
+
@model = Coinbase.call_api do
|
169
|
+
transfers_api.broadcast_transfer(
|
170
|
+
wallet_id,
|
171
|
+
from_address_id,
|
172
|
+
id,
|
173
|
+
{ signed_payload: transaction.raw.hex }
|
174
|
+
)
|
175
|
+
end
|
176
|
+
|
177
|
+
update_transaction(@model)
|
178
|
+
|
179
|
+
self
|
180
|
+
end
|
181
|
+
|
106
182
|
# Reload reloads the Transfer model with the latest version from the server side.
|
107
183
|
# @return [Transfer] The most recent version of Transfer from the server.
|
108
184
|
def reload
|
@@ -110,8 +186,7 @@ module Coinbase
|
|
110
186
|
transfers_api.get_transfer(wallet_id, from_address_id, id)
|
111
187
|
end
|
112
188
|
|
113
|
-
|
114
|
-
@transaction = Coinbase::Transaction.new(@model.transaction)
|
189
|
+
update_transaction(@model)
|
115
190
|
|
116
191
|
self
|
117
192
|
end
|
@@ -157,5 +232,9 @@ module Coinbase
|
|
157
232
|
def transfers_api
|
158
233
|
@transfers_api ||= Coinbase::Client::TransfersApi.new(Coinbase.configuration.api_client)
|
159
234
|
end
|
235
|
+
|
236
|
+
def update_transaction(model)
|
237
|
+
@transaction = Coinbase::Transaction.new(model.transaction)
|
238
|
+
end
|
160
239
|
end
|
161
240
|
end
|
data/lib/coinbase/wallet.rb
CHANGED
@@ -13,9 +13,6 @@ module Coinbase
|
|
13
13
|
# The maximum number of addresses in a Wallet.
|
14
14
|
MAX_ADDRESSES = 20
|
15
15
|
|
16
|
-
# The maximum number of wallets to fetch in a single page.
|
17
|
-
PAGE_LIMIT = 100
|
18
|
-
|
19
16
|
# A representation of ServerSigner status in a Wallet.
|
20
17
|
module ServerSignerStatus
|
21
18
|
# The Wallet is awaiting seed creation by the ServerSigner. At this point,
|
@@ -131,7 +128,7 @@ module Coinbase
|
|
131
128
|
end
|
132
129
|
|
133
130
|
def fetch_wallets_page(page)
|
134
|
-
wallets_api.list_wallets({ limit:
|
131
|
+
wallets_api.list_wallets({ limit: DEFAULT_PAGE_LIMIT, page: page })
|
135
132
|
end
|
136
133
|
end
|
137
134
|
|
@@ -297,6 +294,82 @@ module Coinbase
|
|
297
294
|
default_address.trade(amount, from_asset_id, to_asset_id)
|
298
295
|
end
|
299
296
|
|
297
|
+
# Stakes the given amount of the given Asset.
|
298
|
+
# Currently only the default_address is used to source the Stake.
|
299
|
+
# @param amount [Integer, Float, BigDecimal] The amount of the Asset to stake.
|
300
|
+
# @param asset_id [Symbol] The ID of the Asset to stake.
|
301
|
+
# @param mode [Symbol] (Optional) The staking mode. Defaults to :default.
|
302
|
+
# @param options [Hash] (Optional) Additional options for the staking operation.
|
303
|
+
# @return [Coinbase::StakingOperation] The stake operation
|
304
|
+
def stake(amount, asset_id, mode: :default, options: {})
|
305
|
+
default_address.stake(amount, asset_id, mode: mode, options: options)
|
306
|
+
end
|
307
|
+
|
308
|
+
# Unstakes the given amount of the given Asset.
|
309
|
+
# Currently only the default_address is used to source the Unstake.
|
310
|
+
# @param amount [Integer, Float, BigDecimal] The amount of the Asset to unstake.
|
311
|
+
# @param asset_id [Symbol] The ID of the Asset to unstake.
|
312
|
+
# @param mode [Symbol] (Optional) The staking mode. Defaults to :default.
|
313
|
+
# @param options [Hash] (Optional) Additional options for the unstaking operation.
|
314
|
+
# @return [Coinbase::StakingOperation] The unstake operation
|
315
|
+
def unstake(amount, asset_id, mode: :default, options: {})
|
316
|
+
default_address.unstake(amount, asset_id, mode: mode, options: options)
|
317
|
+
end
|
318
|
+
|
319
|
+
# Claims stake of the given amount of the given Asset.
|
320
|
+
# Currently only the default_address is used as the source for claim_stake.
|
321
|
+
# @param amount [Integer, Float, BigDecimal] The amount of the Asset to claim_stake.
|
322
|
+
# @param asset_id [Symbol] The ID of the Asset to claim_stake.
|
323
|
+
# @param mode [Symbol] (Optional) The staking mode. Defaults to :default.
|
324
|
+
# @param options [Hash] (Optional) Additional options for the unstaking operation.
|
325
|
+
# @return [Coinbase::StakingOperation] The claim_stake operation
|
326
|
+
def claim_stake(amount, asset_id, mode: :default, options: {})
|
327
|
+
default_address.claim_stake(amount, asset_id, mode: mode, options: options)
|
328
|
+
end
|
329
|
+
|
330
|
+
# Retrieves the balances used for staking for the supplied asset.
|
331
|
+
# Currently only the default_address is used to source the staking balances.
|
332
|
+
# @param asset_id [Symbol] The asset to retrieve staking balances for
|
333
|
+
# @param mode [Symbol] The staking mode. Defaults to :default.
|
334
|
+
# @param options [Hash] Additional options for the staking operation
|
335
|
+
# @return [Hash] The staking balances
|
336
|
+
# @return [BigDecimal] :stakeable_balance The amount of the asset that can be staked
|
337
|
+
# @return [BigDecimal] :unstakeable_balance The amount of the asset that is currently staked and cannot be unstaked
|
338
|
+
# @return [BigDecimal] :claimable_balance The amount of the asset that can be claimed
|
339
|
+
def staking_balances(asset_id, mode: :default, options: {})
|
340
|
+
default_address.staking_balances(asset_id, mode: mode, options: options)
|
341
|
+
end
|
342
|
+
|
343
|
+
# Retrieves the stakeable balance for the supplied asset.
|
344
|
+
# Currently only the default_address is used to source the stakeable balance.
|
345
|
+
# @param asset_id [Symbol] The asset to retrieve the stakeable balance for
|
346
|
+
# @param mode [Symbol] The staking mode. Defaults to :default.
|
347
|
+
# @param options [Hash] Additional options for the staking operation
|
348
|
+
# @return [BigDecimal] The stakeable balance
|
349
|
+
def stakeable_balance(asset_id, mode: :default, options: {})
|
350
|
+
default_address.stakeable_balance(asset_id, mode: mode, options: options)
|
351
|
+
end
|
352
|
+
|
353
|
+
# Retrieves the unstakeable balance for the supplied asset.
|
354
|
+
# Currently only the default_address is used to source the unstakeable balance.
|
355
|
+
# @param asset_id [Symbol] The asset to retrieve the unstakeable balance for
|
356
|
+
# @param mode [Symbol] The staking mode. Defaults to :default.
|
357
|
+
# @param options [Hash] Additional options for the staking operation
|
358
|
+
# @return [BigDecimal] The unstakeable balance
|
359
|
+
def unstakeable_balance(asset_id, mode: :default, options: {})
|
360
|
+
default_address.unstakeable_balance(asset_id, mode: mode, options: options)
|
361
|
+
end
|
362
|
+
|
363
|
+
# Retrieves the claimable balance for the supplied asset.
|
364
|
+
# Currently only the default_address is used to source the claimable balance.
|
365
|
+
# @param asset_id [Symbol] The asset to retrieve the claimable balance for
|
366
|
+
# @param mode [Symbol] The staking mode. Defaults to :default.
|
367
|
+
# @param options [Hash] Additional options for the staking operation
|
368
|
+
# @return [BigDecimal] The claimable balance
|
369
|
+
def claimable_balance(asset_id, mode: :default, options: {})
|
370
|
+
default_address.claimable_balance(asset_id, mode: mode, options: options)
|
371
|
+
end
|
372
|
+
|
300
373
|
# Exports the Wallet's data to a Data object.
|
301
374
|
# @return [Data] The Wallet data
|
302
375
|
def export
|
data/lib/coinbase.rb
CHANGED
@@ -9,6 +9,7 @@ require_relative 'coinbase/balance'
|
|
9
9
|
require_relative 'coinbase/balance_map'
|
10
10
|
require_relative 'coinbase/client'
|
11
11
|
require_relative 'coinbase/constants'
|
12
|
+
require_relative 'coinbase/destination'
|
12
13
|
require_relative 'coinbase/errors'
|
13
14
|
require_relative 'coinbase/faucet_transaction'
|
14
15
|
require_relative 'coinbase/middleware'
|
@@ -61,13 +62,14 @@ module Coinbase
|
|
61
62
|
|
62
63
|
# Configuration object for the Coinbase SDK.
|
63
64
|
class Configuration
|
64
|
-
attr_accessor :api_url, :api_key_name, :api_key_private_key, :debug_api, :use_server_signer
|
65
|
+
attr_accessor :api_url, :api_key_name, :api_key_private_key, :debug_api, :use_server_signer, :max_network_tries
|
65
66
|
|
66
67
|
# Initializes the configuration object.
|
67
68
|
def initialize
|
68
69
|
@api_url = 'https://api.cdp.coinbase.com'
|
69
70
|
@debug_api = false
|
70
71
|
@use_server_signer = false
|
72
|
+
@max_network_tries = 3
|
71
73
|
end
|
72
74
|
|
73
75
|
# Sets configuration values based on the provided CDP API Key JSON file.
|