coinbase-sdk 0.0.10 → 0.0.13
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/wallet_address.rb +44 -115
- data/lib/coinbase/constants.rb +3 -0
- data/lib/coinbase/destination.rb +51 -0
- data/lib/coinbase/errors.rb +14 -0
- data/lib/coinbase/trade.rb +87 -5
- data/lib/coinbase/transaction.rb +13 -2
- data/lib/coinbase/transfer.rb +82 -2
- data/lib/coinbase/wallet.rb +1 -4
- data/lib/coinbase.rb +1 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6ea6f3f49e4b03f6131d891a1e628b9bed3a60b40b0a640358b5cc85ff4075ab
|
4
|
+
data.tar.gz: 92d2b00b3dac22f12173f9b6a7860889b7d9e64966e55cf7ba175a3728f43be3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c4a96ebe5f58f569419d2911aab739706d4176fb403b2283d8b44d29f36768bcf2588088f1870cbabc7a7f4941d12a9d796565e60c126014c48b318725fb8d13
|
7
|
+
data.tar.gz: d97661b3ab9abb774561a307bb228c1d3795077777001ca5b6657f2205cf81f8674f68ef4bb9dff4b01623cfffa5c2835e26e58d26dbbf51a8bfcd70b13edc52
|
@@ -8,8 +8,6 @@ module Coinbase
|
|
8
8
|
# Addresses are used to send and receive Assets, and should be created using
|
9
9
|
# Wallet#create_address. Addresses require an Eth::Key to sign transaction data.
|
10
10
|
class WalletAddress < Address
|
11
|
-
PAGE_LIMIT = 100
|
12
|
-
|
13
11
|
# Returns a new Address object. Do not use this method directly. Instead, use Wallet#create_address, or use
|
14
12
|
# the Wallet's default_address.
|
15
13
|
# @param model [Coinbase::Client::Address] The underlying Address object
|
@@ -43,18 +41,25 @@ module Coinbase
|
|
43
41
|
# default address. If a String, interprets it as the address ID.
|
44
42
|
# @return [Coinbase::Transfer] The Transfer object.
|
45
43
|
def transfer(amount, asset_id, destination)
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
44
|
+
ensure_can_sign!
|
45
|
+
ensure_sufficient_balance!(amount, asset_id)
|
46
|
+
|
47
|
+
transfer = Transfer.create(
|
48
|
+
address_id: id,
|
49
|
+
amount: amount,
|
50
|
+
asset_id: asset_id,
|
51
|
+
destination: destination,
|
52
|
+
network_id: network_id,
|
53
|
+
wallet_id: wallet_id
|
54
|
+
)
|
53
55
|
|
54
56
|
# If a server signer is managing keys, it will sign and broadcast the underlying transfer transaction out of band.
|
55
57
|
return transfer if Coinbase.use_server_signer?
|
56
58
|
|
57
|
-
|
59
|
+
transfer.transaction.sign(@key)
|
60
|
+
|
61
|
+
transfer.broadcast!
|
62
|
+
transfer
|
58
63
|
end
|
59
64
|
|
60
65
|
# Trades the given amount of the given Asset for another Asset.
|
@@ -64,20 +69,27 @@ module Coinbase
|
|
64
69
|
# @param to_asset_id [Symbol] The ID of the Asset to trade to. For Ether, :eth, :gwei, and :wei are supported.
|
65
70
|
# @return [Coinbase::Trade] The Trade object.
|
66
71
|
def trade(amount, from_asset_id, to_asset_id)
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
72
|
+
ensure_can_sign!
|
73
|
+
ensure_sufficient_balance!(amount, from_asset_id)
|
74
|
+
|
75
|
+
trade = Trade.create(
|
76
|
+
address_id: id,
|
77
|
+
amount: amount,
|
78
|
+
from_asset_id: from_asset_id,
|
79
|
+
to_asset_id: to_asset_id,
|
80
|
+
network_id: network_id,
|
81
|
+
wallet_id: wallet_id
|
82
|
+
)
|
83
|
+
|
84
|
+
# If a server signer is managing keys, it will sign and broadcast the underlying trade transaction out of band.
|
85
|
+
return trade if Coinbase.use_server_signer?
|
86
|
+
|
87
|
+
trade.transactions.each do |tx|
|
88
|
+
tx.sign(@key)
|
89
|
+
end
|
79
90
|
|
80
|
-
|
91
|
+
trade.broadcast!
|
92
|
+
trade
|
81
93
|
end
|
82
94
|
|
83
95
|
# Returns whether the Address has a private key backing it to sign transactions.
|
@@ -99,9 +111,7 @@ module Coinbase
|
|
99
111
|
# converted to an array, etc...
|
100
112
|
# @return [Enumerable<Coinbase::Transfer>] Enumerator that returns the address's transfers
|
101
113
|
def transfers
|
102
|
-
|
103
|
-
Coinbase::Transfer.new(transfer)
|
104
|
-
end
|
114
|
+
Transfer.list(wallet_id: wallet_id, address_id: id)
|
105
115
|
end
|
106
116
|
|
107
117
|
# Enumerates the trades associated with the address.
|
@@ -109,9 +119,7 @@ module Coinbase
|
|
109
119
|
# converted to an array, etc...
|
110
120
|
# @return [Enumerable<Coinbase::Trade>] Enumerator that returns the address's trades
|
111
121
|
def trades
|
112
|
-
|
113
|
-
Coinbase::Trade.new(trade)
|
114
|
-
end
|
122
|
+
Trade.list(wallet_id: wallet_id, address_id: id)
|
115
123
|
end
|
116
124
|
|
117
125
|
# Returns a String representation of the WalletAddress.
|
@@ -122,98 +130,19 @@ module Coinbase
|
|
122
130
|
|
123
131
|
private
|
124
132
|
|
125
|
-
def
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
def fetch_trades_page(page)
|
130
|
-
trades_api.list_trades(wallet_id, id, { limit: PAGE_LIMIT, page: page })
|
131
|
-
end
|
132
|
-
|
133
|
-
def transfers_api
|
134
|
-
@transfers_api ||= Coinbase::Client::TransfersApi.new(Coinbase.configuration.api_client)
|
135
|
-
end
|
136
|
-
|
137
|
-
def trades_api
|
138
|
-
@trades_api ||= Coinbase::Client::TradesApi.new(Coinbase.configuration.api_client)
|
139
|
-
end
|
140
|
-
|
141
|
-
def destination_address_and_network(destination)
|
142
|
-
return [destination.default_address.id, destination.network_id] if destination.is_a?(Wallet)
|
143
|
-
return [destination.id, destination.network_id] if destination.is_a?(Address)
|
133
|
+
def ensure_can_sign!
|
134
|
+
return if Coinbase.use_server_signer?
|
135
|
+
return if can_sign?
|
144
136
|
|
145
|
-
|
137
|
+
raise AddressCannotSignError
|
146
138
|
end
|
147
139
|
|
148
|
-
def
|
149
|
-
|
150
|
-
|
151
|
-
raise ArgumentError, 'Transfer must be on the same Network' unless destination_network_id == network_id
|
152
|
-
|
153
|
-
current_balance = balance(asset.asset_id)
|
140
|
+
def ensure_sufficient_balance!(amount, asset_id)
|
141
|
+
current_balance = balance(asset_id)
|
154
142
|
|
155
143
|
return unless current_balance < amount
|
156
144
|
|
157
|
-
raise
|
158
|
-
end
|
159
|
-
|
160
|
-
def create_transfer(amount, asset, destination)
|
161
|
-
create_transfer_request = {
|
162
|
-
amount: asset.to_atomic_amount(amount).to_i.to_s,
|
163
|
-
network_id: Coinbase.normalize_network(network_id),
|
164
|
-
asset_id: asset.primary_denomination.to_s,
|
165
|
-
destination: destination
|
166
|
-
}
|
167
|
-
|
168
|
-
transfer_model = Coinbase.call_api do
|
169
|
-
transfers_api.create_transfer(wallet_id, id, create_transfer_request)
|
170
|
-
end
|
171
|
-
|
172
|
-
Coinbase::Transfer.new(transfer_model)
|
173
|
-
end
|
174
|
-
|
175
|
-
def broadcast_transfer(transfer, signed_payload)
|
176
|
-
transfer_model = Coinbase.call_api do
|
177
|
-
transfers_api.broadcast_transfer(wallet_id, id, transfer.id, { signed_payload: signed_payload })
|
178
|
-
end
|
179
|
-
|
180
|
-
Coinbase::Transfer.new(transfer_model)
|
181
|
-
end
|
182
|
-
|
183
|
-
def validate_can_trade!(amount, from_asset)
|
184
|
-
raise 'Cannot trade from address without private key loaded' unless can_sign?
|
185
|
-
|
186
|
-
current_balance = balance(from_asset.asset_id)
|
187
|
-
|
188
|
-
return unless current_balance < amount
|
189
|
-
|
190
|
-
raise ArgumentError, "Insufficient funds: #{amount} requested, but only #{current_balance} available"
|
191
|
-
end
|
192
|
-
|
193
|
-
def create_trade(amount, from_asset, to_asset)
|
194
|
-
create_trade_request = {
|
195
|
-
amount: from_asset.to_atomic_amount(amount).to_i.to_s,
|
196
|
-
from_asset_id: from_asset.primary_denomination.to_s,
|
197
|
-
to_asset_id: to_asset.primary_denomination.to_s
|
198
|
-
}
|
199
|
-
|
200
|
-
trade_model = Coinbase.call_api do
|
201
|
-
trades_api.create_trade(wallet_id, id, create_trade_request)
|
202
|
-
end
|
203
|
-
|
204
|
-
Coinbase::Trade.new(trade_model)
|
205
|
-
end
|
206
|
-
|
207
|
-
def broadcast_trade(trade, signed_payload:, approve_tx_signed_payload: nil)
|
208
|
-
req = { signed_payload: signed_payload }
|
209
|
-
|
210
|
-
req[:approve_transaction_signed_payload] = approve_tx_signed_payload unless approve_tx_signed_payload.nil?
|
211
|
-
|
212
|
-
trade_model = Coinbase.call_api do
|
213
|
-
trades_api.broadcast_trade(wallet_id, id, trade.id, req)
|
214
|
-
end
|
215
|
-
|
216
|
-
Coinbase::Trade.new(trade_model)
|
145
|
+
raise InsufficientFundsError.new(amount, current_balance)
|
217
146
|
end
|
218
147
|
end
|
219
148
|
end
|
data/lib/coinbase/constants.rb
CHANGED
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Coinbase
|
4
|
+
# A representation of the intended recipient of an onchain interaction. For example, a simple
|
5
|
+
# Transfer has a single destination, which is the address that will receive the transferred funds.
|
6
|
+
# This class is used to handle the several different types that we can use as a destination,
|
7
|
+
# namely a Coinbase::Wallet, a Coinbase::Address, a String.
|
8
|
+
# This also ensures that the destination is valid for the network that is being interacted with.
|
9
|
+
# If a Coinbase::Wallet is used, the default address of the wallet is used as the destination.
|
10
|
+
# If a Coinbase::Address is used, the address ID is used as the destination.
|
11
|
+
# If a String is used, the string is used as the destination.
|
12
|
+
# If an existing Coinbase::Destination is used, the same address ID is used as the destination.
|
13
|
+
class Destination
|
14
|
+
# Returns a new Destination object.
|
15
|
+
# @param model [Coinbase::Destination, Coinbase::Wallet, Coinbase::Address, String]
|
16
|
+
# The object which the `address_id` will be derived from.
|
17
|
+
# If the destination is a Destination, it uses the same address ID.
|
18
|
+
# If the destination is a Wallet, it uses the default Address of the Wallet.
|
19
|
+
# If the destination is an Address, it uses the Address's ID.
|
20
|
+
# If the destination is a String, it uses it as the Address ID.
|
21
|
+
# @param network_id [Symbol] The ID of the Network to which the Destination belongs
|
22
|
+
# @return [Destination] The Destination object
|
23
|
+
def initialize(model, network_id: nil)
|
24
|
+
case model
|
25
|
+
when Coinbase::Destination
|
26
|
+
raise ArgumentError, 'destination network must match destination' unless model.network_id == network_id
|
27
|
+
|
28
|
+
@address_id = model.address_id
|
29
|
+
@network_id = model.network_id
|
30
|
+
when Coinbase::Wallet
|
31
|
+
raise ArgumentError, 'destination network must match wallet' unless model.network_id == network_id
|
32
|
+
raise ArgumentError, 'destination wallet must have default address' if model.default_address.nil?
|
33
|
+
|
34
|
+
@address_id = model.default_address.id
|
35
|
+
@network_id = model.network_id
|
36
|
+
when Coinbase::Address
|
37
|
+
raise ArgumentError, 'destination network must match address' unless model.network_id == network_id
|
38
|
+
|
39
|
+
@address_id = model.id
|
40
|
+
@network_id = model.network_id
|
41
|
+
when String
|
42
|
+
@address_id = model
|
43
|
+
@network_id = network_id
|
44
|
+
else
|
45
|
+
raise ArgumentError, "unsupported destination type: #{model.class}"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
attr_reader :address_id, :network_id
|
50
|
+
end
|
51
|
+
end
|
data/lib/coinbase/errors.rb
CHANGED
@@ -63,6 +63,20 @@ module Coinbase
|
|
63
63
|
end
|
64
64
|
end
|
65
65
|
|
66
|
+
# An error raised when a transaction is not signed.
|
67
|
+
class TransactionNotSignedError < StandardError
|
68
|
+
def initialize(msg = 'Transaction must be signed')
|
69
|
+
super(msg)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# An error raised when an address attempts to sign a transaction without a private key.
|
74
|
+
class AddressCannotSignError < StandardError
|
75
|
+
def initialize(msg = 'Address cannot sign transaction without private key loaded')
|
76
|
+
super(msg)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
66
80
|
class UnimplementedError < APIError; end
|
67
81
|
class UnauthorizedError < APIError; end
|
68
82
|
class InternalError < APIError; 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_tx_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
|
@@ -103,6 +159,27 @@ module Coinbase
|
|
103
159
|
transaction.status
|
104
160
|
end
|
105
161
|
|
162
|
+
# Broadcasts the Transfer to the Network.
|
163
|
+
# This raises an error if the Transfer is not signed.
|
164
|
+
# @raise [RuntimeError] If the Transfer is not signed
|
165
|
+
# @return [Transfer] The Transfer object
|
166
|
+
def broadcast!
|
167
|
+
raise TransactionNotSignedError unless transaction.signed?
|
168
|
+
|
169
|
+
@model = Coinbase.call_api do
|
170
|
+
transfers_api.broadcast_transfer(
|
171
|
+
wallet_id,
|
172
|
+
from_address_id,
|
173
|
+
id,
|
174
|
+
{ signed_payload: transaction.raw.hex }
|
175
|
+
)
|
176
|
+
end
|
177
|
+
|
178
|
+
update_transaction(@model)
|
179
|
+
|
180
|
+
self
|
181
|
+
end
|
182
|
+
|
106
183
|
# Reload reloads the Transfer model with the latest version from the server side.
|
107
184
|
# @return [Transfer] The most recent version of Transfer from the server.
|
108
185
|
def reload
|
@@ -110,8 +187,7 @@ module Coinbase
|
|
110
187
|
transfers_api.get_transfer(wallet_id, from_address_id, id)
|
111
188
|
end
|
112
189
|
|
113
|
-
|
114
|
-
@transaction = Coinbase::Transaction.new(@model.transaction)
|
190
|
+
update_transaction(@model)
|
115
191
|
|
116
192
|
self
|
117
193
|
end
|
@@ -157,5 +233,9 @@ module Coinbase
|
|
157
233
|
def transfers_api
|
158
234
|
@transfers_api ||= Coinbase::Client::TransfersApi.new(Coinbase.configuration.api_client)
|
159
235
|
end
|
236
|
+
|
237
|
+
def update_transaction(model)
|
238
|
+
@transaction = Coinbase::Transaction.new(model.transaction)
|
239
|
+
end
|
160
240
|
end
|
161
241
|
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
|
|
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'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: coinbase-sdk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.13
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yuga Cohler
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-07-
|
11
|
+
date: 2024-07-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bigdecimal
|
@@ -301,6 +301,7 @@ files:
|
|
301
301
|
- lib/coinbase/client/models/wallet_list.rb
|
302
302
|
- lib/coinbase/client/version.rb
|
303
303
|
- lib/coinbase/constants.rb
|
304
|
+
- lib/coinbase/destination.rb
|
304
305
|
- lib/coinbase/errors.rb
|
305
306
|
- lib/coinbase/faucet_transaction.rb
|
306
307
|
- lib/coinbase/middleware.rb
|