coinbase 0.0.1 → 4.2.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.travis.yml +7 -0
  4. data/CONTRIBUTING.md +53 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE +201 -0
  7. data/README.md +621 -0
  8. data/Rakefile +6 -0
  9. data/bin/console +14 -0
  10. data/bin/setup +7 -0
  11. data/coinbase.gemspec +26 -0
  12. data/lib/coinbase/util.rb +16 -0
  13. data/lib/coinbase/wallet/adapters/em_http.rb +78 -0
  14. data/lib/coinbase/wallet/adapters/net_http.rb +68 -0
  15. data/lib/coinbase/wallet/api_client.rb +755 -0
  16. data/lib/coinbase/wallet/api_errors.rb +120 -0
  17. data/lib/coinbase/wallet/api_response.rb +41 -0
  18. data/lib/coinbase/wallet/ca-coinbase.crt +101 -0
  19. data/lib/coinbase/wallet/client.rb +101 -0
  20. data/lib/coinbase/wallet/coinbase-callback.pub +14 -0
  21. data/lib/coinbase/wallet/models/account.rb +193 -0
  22. data/lib/coinbase/wallet/models/address.rb +12 -0
  23. data/lib/coinbase/wallet/models/api_object.rb +46 -0
  24. data/lib/coinbase/wallet/models/checkout.rb +19 -0
  25. data/lib/coinbase/wallet/models/order.rb +12 -0
  26. data/lib/coinbase/wallet/models/transaction.rb +21 -0
  27. data/lib/coinbase/wallet/models/transfer.rb +13 -0
  28. data/lib/coinbase/wallet/models/user.rb +15 -0
  29. data/lib/coinbase/wallet/version.rb +5 -0
  30. data/lib/coinbase/wallet.rb +24 -156
  31. data/spec/account_spec.rb +199 -0
  32. data/spec/callback_signature_verification_spec.rb +16 -0
  33. data/spec/clients/client_spec.rb +34 -0
  34. data/spec/clients/oauth_client_spec.rb +56 -0
  35. data/spec/endpoints_spec.rb +352 -0
  36. data/spec/error_spec.rb +137 -0
  37. data/spec/models/address_spec.rb +26 -0
  38. data/spec/models/api_object_spec.rb +70 -0
  39. data/spec/models/checkout_spec.rb +52 -0
  40. data/spec/models/current_user_spec.rb +29 -0
  41. data/spec/models/order_spec.rb +52 -0
  42. data/spec/models/request_spec.rb +47 -0
  43. data/spec/models/transfer_spec.rb +64 -0
  44. data/spec/models/user_spec.rb +24 -0
  45. data/spec/spec_helper.rb +13 -0
  46. metadata +67 -112
  47. data/lib/coinbase/address.rb +0 -127
  48. data/lib/coinbase/asset.rb +0 -20
  49. data/lib/coinbase/balance_map.rb +0 -48
  50. data/lib/coinbase/constants.rb +0 -38
  51. data/lib/coinbase/network.rb +0 -55
  52. data/lib/coinbase/transfer.rb +0 -153
  53. data/lib/coinbase.rb +0 -18
@@ -1,38 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'asset'
4
- require_relative 'network'
5
-
6
- module Coinbase
7
- # The Assets supported on Base Sepolia by the Coinbase SDK.
8
- ETH = Asset.new(network_id: :base_sepolia, asset_id: :eth, display_name: 'Ether')
9
- USDC = Asset.new(network_id: :base_sepolia, asset_id: :usdc, display_name: 'USD Coin',
10
- address_id: '0x036CbD53842c5426634e7929541eC2318f3dCF7e')
11
-
12
- # The Base Sepolia Network.
13
- BASE_SEPOLIA = Network.new(
14
- network_id: :base_sepolia,
15
- display_name: 'Base Sepolia',
16
- protocol_family: :evm,
17
- is_testnet: true,
18
- assets: [ETH, USDC],
19
- native_asset_id: :eth,
20
- chain_id: 84_532
21
- )
22
-
23
- # The amount of Wei per Ether.
24
- WEI_PER_ETHER = 1_000_000_000_000_000_000
25
-
26
- # The amount of Wei per Gwei.
27
- WEI_PER_GWEI = 1_000_000_000
28
-
29
- # The amount of Gwei per Ether.
30
- GWEI_PER_ETHER = 1_000_000_000
31
-
32
- # A map of supported Asset IDs.
33
- SUPPORTED_ASSET_IDS = {
34
- eth: true, # Ether, the native asset of most EVM networks.
35
- gwei: true, # A medium denomination of Ether, typically used in gas prices.
36
- wei: true # The smallest denomination of Ether.
37
- }.freeze
38
- end
@@ -1,55 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Coinbase
4
- # A blockchain network.
5
- class Network
6
- attr_reader :chain_id
7
-
8
- # Returns a new Network object.
9
- #
10
- # @param network_id [Symbol] The Network ID
11
- # @param display_name [String] The Network's display name
12
- # @param protocol_family [String] The protocol family to which the Network belongs
13
- # (e.g., "evm")
14
- # @param is_testnet [Boolean] Whether the Network is a testnet
15
- # @param assets [Array<Asset>] The Assets supported by the Network
16
- # @param native_asset_id [String] The ID of the Network's native Asset
17
- # @param chain_id [Integer] The Chain ID of the Network
18
- def initialize(network_id:, display_name:, protocol_family:, is_testnet:, assets:, native_asset_id:, chain_id:)
19
- @network_id = network_id
20
- @display_name = display_name
21
- @protocol_family = protocol_family
22
- @is_testnet = is_testnet
23
- @chain_id = chain_id
24
-
25
- @asset_map = {}
26
- assets.each do |asset|
27
- @asset_map[asset.asset_id] = asset
28
- end
29
-
30
- raise ArgumentError, 'Native Asset not found' unless @asset_map.key?(native_asset_id)
31
-
32
- @native_asset = @asset_map[native_asset_id]
33
- end
34
-
35
- # Lists the Assets supported by the Network.
36
- #
37
- # @return [Array<Asset>] The Assets supported by the Network
38
- def list_assets
39
- @asset_map.values
40
- end
41
-
42
- # Gets the Asset with the given ID.
43
- #
44
- # @param asset_id [Symbol] The ID of the Asset
45
- # @return [Asset] The Asset with the given ID
46
- def get_asset(asset_id)
47
- @asset_map[asset_id]
48
- end
49
-
50
- # Gets the native Asset of the Network.
51
- #
52
- # @return [Asset] The native Asset of the Network
53
- attr_reader :native_asset
54
- end
55
- end
@@ -1,153 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'constants'
4
- require 'bigdecimal'
5
- require 'eth'
6
-
7
- module Coinbase
8
- # A representation of a Transfer, which moves an amount of an Asset from
9
- # a user-controlled Wallet to another address. The fee is assumed to be paid
10
- # in the native Asset of the Network. Currently only ETH transfers are supported. Transfers
11
- # should be created through {link:Wallet#transfer} or {link:Address#transfer}.
12
- class Transfer
13
- attr_reader :network_id, :wallet_id, :from_address_id, :amount, :asset_id, :to_address_id
14
-
15
- # A representation of a Transfer status.
16
- module Status
17
- # The Transfer is awaiting being broadcast to the Network. At this point, transaction
18
- # hashes may not yet be assigned.
19
- PENDING = :pending
20
-
21
- # The Transfer has been broadcast to the Network. At this point, at least the transaction hash
22
- # should be assigned.
23
- BROADCAST = :broadcast
24
-
25
- # The Transfer is complete, and has confirmed on the Network.
26
- COMPLETE = :complete
27
-
28
- # The Transfer has failed for some reason.
29
- FAILED = :failed
30
- end
31
-
32
- # Returns a new Transfer object.
33
- # @param network_id [Symbol] The ID of the Network on which the Transfer originated
34
- # @param wallet_id [String] The ID of the Wallet from which the Transfer originated
35
- # @param from_address_id [String] The ID of the address from which the Transfer originated
36
- # @param amount [Integer, Float, BigDecimal] The amount of the Asset to send. Integers are interpreted as
37
- # the smallest denomination of the Asset (e.g. Wei for Ether). Floats and BigDecimals are interpreted as the Asset
38
- # itself (e.g. Ether).
39
- # @param asset_id [Symbol] The ID of the Asset being transferred. Currently only ETH is supported.
40
- # @param to_address_id [String] The address to which the Transfer is being sent
41
- # @param client [Jimson::Client] (Optional) The JSON RPC client to use for interacting with the Network
42
- def initialize(network_id, wallet_id, from_address_id, amount, asset_id, to_address_id,
43
- client: Jimson::Client.new(ENV.fetch('BASE_SEPOLIA_RPC_URL', nil)))
44
-
45
- raise ArgumentError, "Unsupported asset: #{asset_id}" if asset_id != :eth
46
-
47
- @network_id = network_id
48
- @wallet_id = wallet_id
49
- @from_address_id = from_address_id
50
- @amount = normalize_eth_amount(amount)
51
- @asset_id = asset_id
52
- @to_address_id = to_address_id
53
- @client = client
54
- end
55
-
56
- # Returns the underlying Transfer transaction, creating it if it has not been yet.
57
- # @return [Eth::Tx::Eip1559] The Transfer transaction
58
- def transaction
59
- return @transaction unless @transaction.nil?
60
-
61
- nonce = @client.eth_getTransactionCount(@from_address_id.to_s, 'latest').to_i(16)
62
- gas_price = @client.eth_gasPrice.to_i(16)
63
-
64
- params = {
65
- chain_id: BASE_SEPOLIA.chain_id, # TODO: Don't hardcode Base Sepolia.
66
- nonce: nonce,
67
- priority_fee: gas_price, # TODO: Optimize this.
68
- max_gas_fee: gas_price,
69
- gas_limit: 21_000, # TODO: Handle multiple currencies.
70
- from: Eth::Address.new(@from_address_id),
71
- to: Eth::Address.new(@to_address_id),
72
- value: (@amount * Coinbase::WEI_PER_ETHER).to_i
73
- }
74
-
75
- @transaction = Eth::Tx::Eip1559.new(Eth::Tx.validate_eip1559_params(params))
76
- @transaction
77
- end
78
-
79
- # Returns the status of the Transfer.
80
- # @return [Symbol] The status
81
- def status
82
- begin
83
- # Create the transaction, and attempt to get the hash to see if it has been signed.
84
- transaction.hash
85
- rescue Eth::Signature::SignatureError
86
- # If the transaction has not been signed, it is still pending.
87
- return Status::PENDING
88
- end
89
-
90
- onchain_transaction = @client.eth_getTransactionByHash(transaction_hash)
91
-
92
- if onchain_transaction.nil?
93
- # If the transaction has not been broadcast, it is still pending.
94
- Status::PENDING
95
- elsif onchain_transaction['blockHash'].nil?
96
- # If the transaction has been broadcast but hasn't been included in a block, it is
97
- # broadcast.
98
- Status::BROADCAST
99
- else
100
- transaction_receipt = @client.eth_getTransactionReceipt(transaction_hash)
101
-
102
- if transaction_receipt['status'].to_i(16) == 1
103
- Status::COMPLETE
104
- else
105
- Status::FAILED
106
- end
107
- end
108
- end
109
-
110
- # Waits until the Transfer is completed or failed by polling the Network at the given interval. Raises a
111
- # Timeout::Error if the Transfer takes longer than the given timeout.
112
- # @param interval_seconds [Integer] The interval at which to poll the Network, in seconds
113
- # @param timeout_seconds [Integer] The maximum amount of time to wait for the Transfer to complete, in seconds
114
- # @return [Transfer] The completed Transfer object
115
- def wait!(interval_seconds = 0.2, timeout_seconds = 10)
116
- start_time = Time.now
117
-
118
- loop do
119
- return self if status == Status::COMPLETE || status == Status::FAILED
120
-
121
- raise Timeout::Error, 'Transfer timed out' if Time.now - start_time > timeout_seconds
122
-
123
- self.sleep interval_seconds
124
- end
125
-
126
- self
127
- end
128
-
129
- # Returns the transaction hash of the Transfer, or nil if not yet available.
130
- # @return [String] The transaction hash
131
- def transaction_hash
132
- "0x#{transaction.hash}"
133
- rescue Eth::Signature::SignatureError
134
- nil
135
- end
136
-
137
- private
138
-
139
- # Normalizes the given Ether amount into a BigDecimal.
140
- # @param amount [Integer, Float, BigDecimal] The amount to normalize
141
- # @return [BigDecimal] The normalized amount
142
- def normalize_eth_amount(amount)
143
- case amount
144
- when BigDecimal
145
- amount
146
- when Integer, Float
147
- BigDecimal(amount.to_s)
148
- else
149
- raise ArgumentError, "Invalid amount: #{amount}"
150
- end
151
- end
152
- end
153
- end
data/lib/coinbase.rb DELETED
@@ -1,18 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'coinbase/address'
4
- require_relative 'coinbase/asset'
5
- require_relative 'coinbase/balance_map'
6
- require_relative 'coinbase/constants'
7
- require_relative 'coinbase/network'
8
- require_relative 'coinbase/transfer'
9
- require_relative 'coinbase/wallet'
10
- require 'dotenv'
11
-
12
- # The Coinbase SDK.
13
- module Coinbase
14
- # Initializes the Coinbase SDK.
15
- def self.init
16
- Dotenv.load
17
- end
18
- end