coinbase-sdk 0.0.8 → 0.0.9

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.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/lib/coinbase/address/external_address.rb +173 -0
  3. data/lib/coinbase/address/wallet_address.rb +219 -0
  4. data/lib/coinbase/address.rb +32 -219
  5. data/lib/coinbase/asset.rb +1 -1
  6. data/lib/coinbase/authenticator.rb +2 -0
  7. data/lib/coinbase/client/api/addresses_api.rb +1 -1
  8. data/lib/coinbase/client/api/assets_api.rb +1 -1
  9. data/lib/coinbase/client/api/external_addresses_api.rb +1 -1
  10. data/lib/coinbase/client/api/server_signers_api.rb +1 -1
  11. data/lib/coinbase/client/api/stake_api.rb +1 -1
  12. data/lib/coinbase/client/api/trades_api.rb +1 -1
  13. data/lib/coinbase/client/api/transfers_api.rb +1 -1
  14. data/lib/coinbase/client/api/users_api.rb +1 -1
  15. data/lib/coinbase/client/api/wallets_api.rb +1 -1
  16. data/lib/coinbase/client/api_client.rb +3 -3
  17. data/lib/coinbase/client/api_error.rb +1 -1
  18. data/lib/coinbase/client/configuration.rb +1 -1
  19. data/lib/coinbase/client/models/address.rb +1 -1
  20. data/lib/coinbase/client/models/address_balance_list.rb +1 -1
  21. data/lib/coinbase/client/models/address_list.rb +1 -1
  22. data/lib/coinbase/client/models/asset.rb +1 -1
  23. data/lib/coinbase/client/models/balance.rb +1 -1
  24. data/lib/coinbase/client/models/broadcast_trade_request.rb +1 -1
  25. data/lib/coinbase/client/models/broadcast_transfer_request.rb +1 -1
  26. data/lib/coinbase/client/models/build_staking_operation_request.rb +1 -1
  27. data/lib/coinbase/client/models/create_address_request.rb +1 -1
  28. data/lib/coinbase/client/models/create_server_signer_request.rb +22 -5
  29. data/lib/coinbase/client/models/create_trade_request.rb +1 -1
  30. data/lib/coinbase/client/models/create_transfer_request.rb +1 -1
  31. data/lib/coinbase/client/models/create_wallet_request.rb +1 -1
  32. data/lib/coinbase/client/models/create_wallet_request_wallet.rb +1 -1
  33. data/lib/coinbase/client/models/error.rb +1 -1
  34. data/lib/coinbase/client/models/faucet_transaction.rb +23 -5
  35. data/lib/coinbase/client/models/feature.rb +1 -1
  36. data/lib/coinbase/client/models/fetch_staking_rewards200_response.rb +1 -1
  37. data/lib/coinbase/client/models/fetch_staking_rewards_request.rb +2 -15
  38. data/lib/coinbase/client/models/get_staking_context_request.rb +1 -1
  39. data/lib/coinbase/client/models/partial_eth_staking_context.rb +4 -7
  40. data/lib/coinbase/client/models/seed_creation_event.rb +1 -1
  41. data/lib/coinbase/client/models/seed_creation_event_result.rb +1 -1
  42. data/lib/coinbase/client/models/server_signer.rb +22 -5
  43. data/lib/coinbase/client/models/server_signer_event.rb +1 -1
  44. data/lib/coinbase/client/models/server_signer_event_event.rb +1 -1
  45. data/lib/coinbase/client/models/server_signer_event_list.rb +1 -1
  46. data/lib/coinbase/client/models/server_signer_list.rb +1 -1
  47. data/lib/coinbase/client/models/signature_creation_event.rb +1 -1
  48. data/lib/coinbase/client/models/signature_creation_event_result.rb +1 -1
  49. data/lib/coinbase/client/models/staking_context.rb +1 -1
  50. data/lib/coinbase/client/models/staking_context_context.rb +1 -1
  51. data/lib/coinbase/client/models/staking_operation.rb +15 -12
  52. data/lib/coinbase/client/models/staking_reward.rb +21 -5
  53. data/lib/coinbase/client/models/staking_reward_format.rb +40 -0
  54. data/lib/coinbase/client/models/trade.rb +1 -1
  55. data/lib/coinbase/client/models/trade_list.rb +1 -1
  56. data/lib/coinbase/client/models/transaction.rb +1 -1
  57. data/lib/coinbase/client/models/transaction_type.rb +1 -1
  58. data/lib/coinbase/client/models/transfer.rb +1 -1
  59. data/lib/coinbase/client/models/transfer_list.rb +1 -1
  60. data/lib/coinbase/client/models/user.rb +1 -1
  61. data/lib/coinbase/client/models/wallet.rb +1 -1
  62. data/lib/coinbase/client/models/wallet_list.rb +1 -1
  63. data/lib/coinbase/client/version.rb +1 -1
  64. data/lib/coinbase/client.rb +2 -1
  65. data/lib/coinbase/errors.rb +7 -0
  66. data/lib/coinbase/faucet_transaction.rb +5 -4
  67. data/lib/coinbase/pagination.rb +26 -0
  68. data/lib/coinbase/staking_operation.rb +29 -0
  69. data/lib/coinbase/staking_reward.rb +79 -0
  70. data/lib/coinbase/transaction.rb +6 -0
  71. data/lib/coinbase/user.rb +5 -51
  72. data/lib/coinbase/wallet.rb +95 -100
  73. data/lib/coinbase.rb +11 -0
  74. metadata +8 -19
  75. data/lib/coinbase/client/api/balances_api.rb +0 -97
  76. data/lib/coinbase/client/api/transfer_api.rb +0 -114
  77. data/lib/coinbase/client/models/request_faucet_funds200_response.rb +0 -222
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c52613ebb145609813f96508c0eff76721ee6afebf3f3207394dad4c91b51635
4
- data.tar.gz: d7f86c6cfbc02b6dd8866717cc9a89439b81da9ae8838dc34855dd10bf9f3fa9
3
+ metadata.gz: df442398edde68b8c97794f9b1f0a2bfd33304f02459962fe13a437c348aba37
4
+ data.tar.gz: e8fcd68e07c0d0012985c5046705d53137b3f7c6f1717f0ac2546f161cfadb0a
5
5
  SHA512:
6
- metadata.gz: 6fa544e18af4ad42457ec8615e7a6e652fb15e1ae00cfa14924dcb86c53aab1ba90b21a8e1b7b29f193b1e0039d030cba1f45631b8dac23b287617105b88478b
7
- data.tar.gz: 3625e897b9681e208cd921e8118275bd012996c17fb62fc235eac8624e6742ce18cff8d8177a1d379bfb5fa71ebec3db02a70d2bb683aeb067ccac7f89345945
6
+ metadata.gz: e777794208415ac5797c445db30fb7e0b6e2fe5f53c1dc22323ba2411a7648d6ee971b94e594806d9738018e41888d04c5ae036457883f51e4eaa76de7875920
7
+ data.tar.gz: 8b5b812b286509fa1962b1f9c5098955de0d8a19d3f233b2205c9c85c8bb1c4869566915db7ca15dd2020e713f515b80499532b87a45f1e7ba7b80419c35c3e5
@@ -0,0 +1,173 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'date'
4
+
5
+ module Coinbase
6
+ # A representation of a blockchain Address that do not belong to a Coinbase::Wallet.
7
+ # External addresses can be used to fetch balances, request funds from the faucet, etc...,
8
+ # but cannot be used to sign transactions.
9
+ class ExternalAddress < Address
10
+ # Builds a stake operation for the supplied asset. The stake operation
11
+ # may take a few minutes to complete in the case when infrastructure is spun up.
12
+ # @param amount [Integer,String,BigDecimal] The amount of the asset to stake
13
+ # @param asset_id [Symbol] The asset to stake
14
+ # @param mode [Symbol] The staking mode. Defaults to :default.
15
+ # @param options [Hash] Additional options for the stake operation
16
+ # @return [Coinbase::StakingOperation] The stake operation
17
+ def build_stake_operation(amount, asset_id, mode: :default, options: {})
18
+ validate_can_stake!(amount, asset_id, mode, options)
19
+
20
+ build_staking_operation(amount, asset_id, 'stake', mode: mode, options: options)
21
+ end
22
+
23
+ # Builds an unstake operation for the supplied asset.
24
+ # @param amount [Integer,String,BigDecimal] The amount of the asset to unstake
25
+ # @param asset_id [Symbol] The asset to unstake
26
+ # @param mode [Symbol] The staking mode. Defaults to :default.
27
+ # @param options [Hash] Additional options for the unstake operation
28
+ # @return [Coinbase::StakingOperation] The unstake operation
29
+ def build_unstake_operation(amount, asset_id, mode: :default, options: {})
30
+ validate_can_unstake!(amount, asset_id, mode, options)
31
+
32
+ build_staking_operation(amount, asset_id, 'unstake', mode: mode, options: options)
33
+ end
34
+
35
+ # Builds an claim_stake operation for the supplied asset.
36
+ # @param amount [Integer,String,BigDecimal] The amount of the asset to claim
37
+ # @param asset_id [Symbol] The asset to claim
38
+ # @param mode [Symbol] The staking mode. Defaults to :default.
39
+ # @param options [Hash] Additional options for the claim_stake operation
40
+ # @return [Coinbase::StakingOperation] The claim_stake operation
41
+ def build_claim_stake_operation(amount, asset_id, mode: :default, options: {})
42
+ validate_can_claim_stake!(amount, asset_id, mode, options)
43
+
44
+ build_staking_operation(amount, asset_id, 'claim_stake', mode: mode, options: options)
45
+ end
46
+
47
+ # Retreives the balances used for staking for the supplied asset.
48
+ # @param asset_id [Symbol] The asset to retrieve staking balances for
49
+ # @param mode [Symbol] The staking mode. Defaults to :default.
50
+ # @param options [Hash] Additional options for the staking operation
51
+ # @return [Hash] The staking balances
52
+ # @return [BigDecimal] :stakeable_balance The amount of the asset that can be staked
53
+ # @return [BigDecimal] :unstakeable_balance The amount of the asset that is currently staked and cannot be unstaked
54
+ # @return [BigDecimal] :claimable_balance The amount of the asset that can be claimed
55
+ def staking_balances(asset_id, mode: :default, options: {})
56
+ context_model = Coinbase.call_api do
57
+ stake_api.get_staking_context(
58
+ {
59
+ asset_id: asset_id,
60
+ network_id: Coinbase.normalize_network(network_id),
61
+ address_id: id,
62
+ options: {
63
+ mode: mode
64
+ }.merge(options)
65
+ }
66
+ )
67
+ end.context
68
+
69
+ {
70
+ stakeable_balance: Coinbase::Balance.from_model_and_asset_id(
71
+ context_model.stakeable_balance,
72
+ asset_id
73
+ ).amount,
74
+ unstakeable_balance: Coinbase::Balance.from_model_and_asset_id(
75
+ context_model.unstakeable_balance,
76
+ asset_id
77
+ ).amount,
78
+ claimable_balance: Coinbase::Balance.from_model_and_asset_id(
79
+ context_model.claimable_balance,
80
+ asset_id
81
+ ).amount
82
+ }
83
+ end
84
+
85
+ # Retreives the stakeable balance for the supplied asset.
86
+ # @param asset_id [Symbol] The asset to retrieve the stakeable balance for
87
+ # @param mode [Symbol] The staking mode. Defaults to :default.
88
+ # @param options [Hash] Additional options for the staking operation
89
+ # @return [BigDecimal] The stakeable balance
90
+ def stakeable_balance(asset_id, mode: :default, options: {})
91
+ staking_balances(asset_id, mode: mode, options: options)[:stakeable_balance]
92
+ end
93
+
94
+ # Retreives the unstakeable balance for the supplied asset.
95
+ # @param asset_id [Symbol] The asset to retrieve the unstakeable balance for
96
+ # @param mode [Symbol] The staking mode. Defaults to :default.
97
+ # @param options [Hash] Additional options for the staking operation
98
+ # @return [BigDecimal] The unstakeable balance
99
+ def unstakeable_balance(asset_id, mode: :default, options: {})
100
+ staking_balances(asset_id, mode: mode, options: options)[:unstakeable_balance]
101
+ end
102
+
103
+ # Retreives the claimable balance for the supplied asset.
104
+ # @param asset_id [Symbol] The asset to retrieve the claimable balance for
105
+ # @param mode [Symbol] The staking mode. Defaults to :default.
106
+ # @param options [Hash] Additional options for the staking operation
107
+ # @return [BigDecimal] The claimable balance
108
+ def claimable_balance(asset_id, mode: :default, options: {})
109
+ staking_balances(asset_id, mode: mode, options: options)[:claimable_balance]
110
+ end
111
+
112
+ # Lists the staking rewards for the address.
113
+ # @param asset_id [Symbol] The asset to retrieve staking rewards for
114
+ # @param start_time [Time] The start time for the rewards. Defaults to 1 month ago.
115
+ # @param end_time [Time] The end time for the rewards. Defaults to the current time.
116
+ # @param format [Symbol] The format to return the rewards in. Defaults to :usd.
117
+ # @return [Enumerable<Coinbase::StakingReward>] The staking rewards
118
+ def staking_rewards(asset_id, start_time: DateTime.now.prev_month(1), end_time: DateTime.now, format: :usd)
119
+ StakingReward.list(
120
+ network_id,
121
+ asset_id,
122
+ [id],
123
+ start_time: start_time,
124
+ end_time: end_time,
125
+ format: format
126
+ )
127
+ end
128
+
129
+ private
130
+
131
+ def validate_can_stake!(amount, asset_id, mode, options)
132
+ stakeable_balance = stakeable_balance(asset_id, mode: mode, options: options)
133
+
134
+ raise InsufficientFundsError.new(amount, stakeable_balance) unless stakeable_balance >= amount
135
+ end
136
+
137
+ def validate_can_unstake!(amount, asset_id, mode, options)
138
+ unstakeable_balance = unstakeable_balance(asset_id, mode: mode, options: options)
139
+
140
+ raise InsufficientFundsError.new(amount, unstakeable_balance) unless unstakeable_balance >= amount
141
+ end
142
+
143
+ def validate_can_claim_stake!(amount, asset_id, mode, options)
144
+ claimable_balance = claimable_balance(asset_id, mode: mode, options: options)
145
+
146
+ raise InsufficientFundsError.new(amount, claimable_balance) unless claimable_balance >= amount
147
+ end
148
+
149
+ def build_staking_operation(amount, asset_id, action, mode: :default, options: {})
150
+ operation_model = Coinbase.call_api do
151
+ asset = Coinbase::Asset.fetch(network_id, asset_id)
152
+ stake_api.build_staking_operation(
153
+ {
154
+ asset_id: asset.primary_denomination.to_s,
155
+ address_id: id,
156
+ action: action,
157
+ network_id: Coinbase.normalize_network(network_id),
158
+ options: {
159
+ amount: asset.to_atomic_amount(amount).to_i.to_s,
160
+ mode: mode
161
+ }.merge(options)
162
+ }
163
+ )
164
+ end
165
+
166
+ StakingOperation.new(operation_model)
167
+ end
168
+
169
+ def stake_api
170
+ @stake_api ||= Coinbase::Client::StakeApi.new(Coinbase.configuration.api_client)
171
+ end
172
+ end
173
+ end
@@ -0,0 +1,219 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bigdecimal'
4
+ require 'eth'
5
+
6
+ module Coinbase
7
+ # A representation of a blockchain Address that belongs to a Coinbase::Wallet.
8
+ # Addresses are used to send and receive Assets, and should be created using
9
+ # Wallet#create_address. Addresses require an Eth::Key to sign transaction data.
10
+ class WalletAddress < Address
11
+ PAGE_LIMIT = 100
12
+
13
+ # Returns a new Address object. Do not use this method directly. Instead, use Wallet#create_address, or use
14
+ # the Wallet's default_address.
15
+ # @param model [Coinbase::Client::Address] The underlying Address object
16
+ # @param key [Eth::Key] The key backing the Address. Can be nil.
17
+ def initialize(model, key)
18
+ @model = model
19
+ @key = key
20
+
21
+ super(model.network_id, model.address_id)
22
+ end
23
+
24
+ # Returns the Wallet ID of the Address.
25
+ # @return [String] The Wallet ID
26
+ def wallet_id
27
+ @model.wallet_id
28
+ end
29
+
30
+ # Sets the private key backing the Address. This key is used to sign transactions.
31
+ # @param key [Eth::Key] The key backing the Address
32
+ def key=(key)
33
+ raise 'Private key is already set' unless @key.nil?
34
+
35
+ @key = key
36
+ end
37
+
38
+ # Transfers the given amount of the given Asset to the specified address or wallet.
39
+ # Only same-network Transfers are supported.
40
+ # @param amount [Integer, Float, BigDecimal] The amount of the Asset to send.
41
+ # @param asset_id [Symbol] The ID of the Asset to send. For Ether, :eth, :gwei, and :wei are supported.
42
+ # @param destination [Wallet | Address | String] The destination of the transfer. If a Wallet, sends to the Wallet's
43
+ # default address. If a String, interprets it as the address ID.
44
+ # @return [Coinbase::Transfer] The Transfer object.
45
+ def transfer(amount, asset_id, destination)
46
+ asset = Asset.fetch(network_id, asset_id)
47
+
48
+ destination_address, destination_network = destination_address_and_network(destination)
49
+
50
+ validate_can_transfer!(amount, asset, destination_network)
51
+
52
+ transfer = create_transfer(amount, asset, destination_address)
53
+
54
+ # If a server signer is managing keys, it will sign and broadcast the underlying transfer transaction out of band.
55
+ return transfer if Coinbase.use_server_signer?
56
+
57
+ broadcast_transfer(transfer, transfer.transaction.sign(@key))
58
+ end
59
+
60
+ # Trades the given amount of the given Asset for another Asset.
61
+ # Only same-network Trades are supported.
62
+ # @param amount [Integer, Float, BigDecimal] The amount of the Asset to send.
63
+ # @param from_asset_id [Symbol] The ID of the Asset to trade from. For Ether, :eth, :gwei, and :wei are supported.
64
+ # @param to_asset_id [Symbol] The ID of the Asset to trade to. For Ether, :eth, :gwei, and :wei are supported.
65
+ # @return [Coinbase::Trade] The Trade object.
66
+ def trade(amount, from_asset_id, to_asset_id)
67
+ from_asset = Asset.fetch(network_id, from_asset_id)
68
+ to_asset = Asset.fetch(network_id, to_asset_id)
69
+
70
+ validate_can_trade!(amount, from_asset)
71
+
72
+ trade = create_trade(amount, from_asset, to_asset)
73
+
74
+ # NOTE: Trading does not yet support server signers at this point.
75
+
76
+ payloads = { signed_payload: trade.transaction.sign(@key) }
77
+
78
+ payloads[:approve_tx_signed_payload] = trade.approve_transaction.sign(@key) unless trade.approve_transaction.nil?
79
+
80
+ broadcast_trade(trade, **payloads)
81
+ end
82
+
83
+ # Returns whether the Address has a private key backing it to sign transactions.
84
+ # @return [Boolean] Whether the Address has a private key backing it to sign transactions.
85
+ def can_sign?
86
+ !@key.nil?
87
+ end
88
+
89
+ # Exports the Address's private key to a hex string.
90
+ # @return [String] The Address's private key as a hex String
91
+ def export
92
+ raise 'Cannot export key without private key loaded' if @key.nil?
93
+
94
+ @key.private_hex
95
+ end
96
+
97
+ # Enumerates the transfers associated with the address.
98
+ # The result is an enumerator that lazily fetches from the server, and can be iterated over,
99
+ # converted to an array, etc...
100
+ # @return [Enumerable<Coinbase::Transfer>] Enumerator that returns the address's transfers
101
+ def transfers
102
+ Coinbase::Pagination.enumerate(lambda(&method(:fetch_transfers_page))) do |transfer|
103
+ Coinbase::Transfer.new(transfer)
104
+ end
105
+ end
106
+
107
+ # Enumerates the trades associated with the address.
108
+ # The result is an enumerator that lazily fetches from the server, and can be iterated over,
109
+ # converted to an array, etc...
110
+ # @return [Enumerable<Coinbase::Trade>] Enumerator that returns the address's trades
111
+ def trades
112
+ Coinbase::Pagination.enumerate(lambda(&method(:fetch_trades_page))) do |trade|
113
+ Coinbase::Trade.new(trade)
114
+ end
115
+ end
116
+
117
+ # Returns a String representation of the WalletAddress.
118
+ # @return [String] a String representation of the WalletAddress
119
+ def to_s
120
+ "Coinbase::Address{id: '#{id}', network_id: '#{network_id}', wallet_id: '#{wallet_id}'}"
121
+ end
122
+
123
+ private
124
+
125
+ def fetch_transfers_page(page)
126
+ transfers_api.list_transfers(wallet_id, id, { limit: PAGE_LIMIT, page: page })
127
+ end
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)
144
+
145
+ [destination, network_id]
146
+ end
147
+
148
+ def validate_can_transfer!(amount, asset, destination_network_id)
149
+ raise 'Cannot transfer from address without private key loaded' unless can_sign? || Coinbase.use_server_signer?
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)
154
+
155
+ return unless current_balance < amount
156
+
157
+ raise ArgumentError, "Insufficient funds: #{amount} requested, but only #{current_balance} available"
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)
217
+ end
218
+ end
219
+ end