Class: Coinbase::Wallet

Inherits:
Object
  • Object
show all
Defined in:
lib/coinbase/wallet.rb

Overview

A representation of a Wallet. Wallets come with a single default Address, but can expand to have a set of Addresses, each of which can hold a balance of one or more Assets. Wallets can create new Addresses, list their addresses, list their balances, and transfer Assets to other Addresses. Wallets should be created through User#create_wallet or User#import_wallet.

Defined Under Namespace

Classes: Data

Constant Summary collapse

MAX_ADDRESSES =

The maximum number of addresses in a Wallet.

20

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(model, seed: nil, address_models: []) ⇒ Wallet

Returns a new Wallet object. Do not use this method directly. Instead, use User#create_wallet or User#import_wallet.

Parameters:

  • model (Coinbase::Client::Wallet)

    The underlying Wallet object

  • seed (String) (defaults to: nil)

    (Optional) The seed to use for the Wallet. Expects a 32-byte hexadecimal with no 0x prefix. If nil, a new seed will be generated. If the empty string, no seed is generated, and the Wallet will be instantiated without a seed and its corresponding private keys.

  • address_models (Array<Coinbase::Client::Address>) (defaults to: [])

    (Optional) The models of the addresses already registered with the Wallet. If not provided, the Wallet will derive the first default address.

  • client (Jimson::Client)

    (Optional) The JSON RPC client to use for interacting with the Network



80
81
82
83
84
85
86
87
88
89
# File 'lib/coinbase/wallet.rb', line 80

def initialize(model, seed: nil, address_models: [])
  validate_seed_and_address_models(seed, address_models)

  @model = model
  @master = master_node(seed)
  @addresses = []
  @private_key_index = 0

  derive_addresses(address_models)
end

Instance Attribute Details

#addressesObject (readonly)

Returns the value of attribute addresses.



15
16
17
# File 'lib/coinbase/wallet.rb', line 15

def addresses
  @addresses
end

#modelObject (readonly)

Returns the value of attribute model.



15
16
17
# File 'lib/coinbase/wallet.rb', line 15

def model
  @model
end

Class Method Details

.create(network_id: 'base-sepolia') ⇒ Coinbase::Wallet

Creates a new Wallet on the specified Network and generate a default address for it.

Parameters:

  • network_id (String) (defaults to: 'base-sepolia')

    (Optional) the ID of the blockchain network. Defaults to ‘base-sepolia’.

Returns:



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/coinbase/wallet.rb', line 41

def create(network_id: 'base-sepolia')
  model = Coinbase.call_api do
    wallets_api.create_wallet(
      create_wallet_request: {
        wallet: {
          network_id: network_id
        }
      }
    )
  end

  wallet = new(model)

  wallet.create_address

  wallet
end

.import(data) ⇒ Coinbase::Wallet

Imports a Wallet from previously exported wallet data.

Parameters:

Returns:

Raises:

  • (ArgumentError)


24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/coinbase/wallet.rb', line 24

def import(data)
  raise ArgumentError, 'data must be a Coinbase::Wallet::Data object' unless data.is_a?(Data)

  model = Coinbase.call_api do
    wallets_api.get_wallet(data.wallet_id)
  end

  address_list = Coinbase.call_api do
    addresses_api.list_addresses(model.id, { limit: MAX_ADDRESSES })
  end

  new(model, seed: data.seed, address_models: address_list.data)
end

Instance Method Details

#address(address_id) ⇒ Address

Returns the Address with the given ID.

Parameters:

  • address_id (String)

    The ID of the Address to retrieve

Returns:



153
154
155
# File 'lib/coinbase/wallet.rb', line 153

def address(address_id)
  @addresses.find { |address| address.id == address_id }
end

#balance(asset_id) ⇒ BigDecimal

Returns the balance of the provided Asset. Balances are aggregated across all Addresses in the Wallet.

Parameters:

  • asset_id (Symbol)

    The ID of the Asset to retrieve the balance for

Returns:

  • (BigDecimal)

    The balance of the Asset



170
171
172
173
174
175
176
177
178
# File 'lib/coinbase/wallet.rb', line 170

def balance(asset_id)
  response = Coinbase.call_api do
    wallets_api.get_wallet_balance(id, Coinbase::Asset.primary_denomination(asset_id).to_s)
  end

  return BigDecimal('0') if response.nil?

  Coinbase::Balance.from_model_and_asset_id(response, asset_id).amount
end

#balancesBalanceMap

Returns the list of balances of this Wallet. Balances are aggregated across all Addresses in the Wallet.

Returns:

  • (BalanceMap)

    The list of balances. The key is the Asset ID, and the value is the balance.



159
160
161
162
163
164
165
# File 'lib/coinbase/wallet.rb', line 159

def balances
  response = Coinbase.call_api do
    wallets_api.list_wallet_balances(id)
  end

  Coinbase::BalanceMap.from_balances(response.data)
end

#can_sign?Boolean

Returns whether the Wallet has a seed with which to derive keys and sign transactions.

Returns:

  • (Boolean)

    Whether the Wallet has a seed with which to derive keys and sign transactions.



222
223
224
# File 'lib/coinbase/wallet.rb', line 222

def can_sign?
  !@master.nil?
end

#create_addressAddress

Creates a new Address in the Wallet.

Returns:



123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/coinbase/wallet.rb', line 123

def create_address
  key = derive_key
  attestation = create_attestation(key)
  public_key = key.public_key.compressed.unpack1('H*')

  opts = {
    create_address_request: {
      public_key: public_key,
      attestation: attestation
    }
  }
  address_model = Coinbase.call_api do
    addresses_api.create_address(id, opts)
  end

  # Auto-reload wallet to set default address on first address creation.
  reload if addresses.empty?

  cache_address(address_model, key)
end

#default_addressAddress

Returns the default address of the Wallet.

Returns:

  • (Address)

    The default address



146
147
148
# File 'lib/coinbase/wallet.rb', line 146

def default_address
  address(@model.default_address&.address_id)
end

#exportData

Exports the Wallet’s data to a Data object.

Returns:

  • (Data)

    The Wallet data



203
204
205
206
207
# File 'lib/coinbase/wallet.rb', line 203

def export
  raise 'Cannot export Wallet without loaded seed' if @master.nil?

  Data.new(wallet_id: id, seed: @master.seed_hex)
end

#faucetCoinbase::FaucetTransaction

Requests funds from the faucet for the Wallet’s default address and returns the faucet transaction. This is only supported on testnet networks.

Returns:

Raises:



214
215
216
217
218
# File 'lib/coinbase/wallet.rb', line 214

def faucet
  Coinbase.call_api do
    Coinbase::FaucetTransaction.new(addresses_api.request_faucet_funds(id, default_address.id))
  end
end

#idString

Returns the Wallet ID.

Returns:

  • (String)

    The Wallet ID



93
94
95
# File 'lib/coinbase/wallet.rb', line 93

def id
  @model.id
end

#inspectString

Same as to_s.

Returns:

  • (String)

    a String representation of the Wallet



235
236
237
# File 'lib/coinbase/wallet.rb', line 235

def inspect
  to_s
end

#network_idSymbol

Returns the Network ID of the Wallet.

Returns:

  • (Symbol)

    The Network ID



99
100
101
# File 'lib/coinbase/wallet.rb', line 99

def network_id
  Coinbase.to_sym(@model.network_id)
end

#seed=(seed) ⇒ Object

Sets the seed of the Wallet. This seed is used to derive keys and sign transactions.

Parameters:

  • seed (String)

    The seed to set. Expects a 32-byte hexadecimal with no 0x prefix.

Raises:

  • (ArgumentError)


105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/coinbase/wallet.rb', line 105

def seed=(seed)
  raise ArgumentError, 'Seed must be 32 bytes' if seed.length != 64
  raise 'Seed is already set' unless @master.nil?
  raise 'Cannot set seed for Wallet with non-zero private key index' if @private_key_index.positive?

  @master = MoneyTree::Master.new(seed_hex: seed)

  @addresses.each do
    key = derive_key
    a = address(key.address.to_s)
    raise "Seed does not match wallet; cannot find address #{key.address}" if a.nil?

    a.key = key
  end
end

#to_sString

Returns a String representation of the Wallet.

Returns:

  • (String)

    a String representation of the Wallet



228
229
230
231
# File 'lib/coinbase/wallet.rb', line 228

def to_s
  "Coinbase::Wallet{wallet_id: '#{id}', network_id: '#{network_id}', " \
    "default_address: '#{@model.default_address&.address_id}'}"
end

#transfer(amount, asset_id, destination) ⇒ Transfer

Transfers the given amount of the given Asset to the given address. Only same-Network Transfers are supported. Currently only the default_address is used to source the Transfer.

Parameters:

  • amount (Integer, Float, BigDecimal)

    The amount of the Asset to send

  • asset_id (Symbol)

    The ID of the Asset to send

  • destination (Wallet | Address | String)

    The destination of the transfer. If a Wallet, sends to the Wallet’s default address. If a String, interprets it as the address ID.

Returns:

  • (Transfer)

    The hash of the Transfer transaction.



187
188
189
190
191
192
193
194
195
196
197
198
199
# File 'lib/coinbase/wallet.rb', line 187

def transfer(amount, asset_id, destination)
  if destination.is_a?(Wallet)
    raise ArgumentError, 'Transfer must be on the same Network' if destination.network_id != network_id

    destination = destination.default_address.id
  elsif destination.is_a?(Address)
    raise ArgumentError, 'Transfer must be on the same Network' if destination.network_id != network_id

    destination = destination.id
  end

  default_address.transfer(amount, asset_id, destination)
end