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

Instance Method Summary collapse

Constructor Details

#initialize(model, seed: nil, address_count: 0) ⇒ 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 not provided, a new seed will be generated.

  • address_count (Integer) (defaults to: 0)

    (Optional) The number of addresses already registered for the Wallet.

  • client (Jimson::Client)

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

Raises:

  • (ArgumentError)


22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/coinbase/wallet.rb', line 22

def initialize(model, seed: nil, address_count: 0)
  raise ArgumentError, 'Seed must be 32 bytes' if !seed.nil? && seed.length != 64

  @model = model

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

  # TODO: Make Network an argument to the constructor.
  @network_id = :base_sepolia
  @addresses = []

  # TODO: Adjust derivation path prefix based on network protocol.
  @address_path_prefix = "m/44'/60'/0'/0"
  @address_index = 0

  if address_count.positive?
    address_count.times { derive_address }
  else
    create_address
    # Update the model to reflect the new default address.
    update_model
  end
end

Instance Method Details

#create_addressAddress

Creates a new Address in the Wallet.

Returns:



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/coinbase/wallet.rb', line 60

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 = addresses_api.create_address(wallet_id, opts)

  cache_address(address_model, key)
end

#default_addressAddress

Returns the default address of the Wallet.

Returns:

  • (Address)

    The default address



78
79
80
# File 'lib/coinbase/wallet.rb', line 78

def default_address
  @addresses.find { |address| address.address_id == @model.default_address.address_id }
end

#exportData

Exports the Wallet’s data to a Data object.

Returns:

  • (Data)

    The Wallet data



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

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

#get_address(address_id) ⇒ Address

Returns the Address with the given ID.

Parameters:

  • address_id (String)

    The ID of the Address to retrieve

Returns:



85
86
87
# File 'lib/coinbase/wallet.rb', line 85

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

#get_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



105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/coinbase/wallet.rb', line 105

def get_balance(asset_id)
  normalized_asset_id = if i[wei gwei].include?(asset_id)
                          :eth
                        else
                          asset_id
                        end

  response = wallets_api.get_wallet_balance(wallet_id, normalized_asset_id.to_s)

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

  amount = BigDecimal(response.amount)

  case asset_id
  when :eth
    amount / BigDecimal(Coinbase::WEI_PER_ETHER.to_s)
  when :gwei
    amount / BigDecimal(Coinbase::GWEI_PER_ETHER.to_s)
  when :usdc
    amount / BigDecimal(Coinbase::ATOMIC_UNITS_PER_USDC.to_s)
  else
    amount
  end
end

#list_addressesArray<Address>

Returns the list of Addresses in the Wallet.

Returns:

  • (Array<Address>)

    The list of Addresses



91
92
93
# File 'lib/coinbase/wallet.rb', line 91

def list_addresses
  @addresses
end

#list_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.



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

def list_balances
  response = wallets_api.list_wallet_balances(wallet_id)
  Coinbase.to_balance_map(response)
end

#network_idSymbol

Returns the Network ID of the Wallet.

Returns:

  • (Symbol)

    The Network ID



54
55
56
# File 'lib/coinbase/wallet.rb', line 54

def network_id
  Coinbase.to_sym(@model.network_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.



137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/coinbase/wallet.rb', line 137

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.address_id
  elsif destination.is_a?(Address)
    raise ArgumentError, 'Transfer must be on the same Network' if destination.network_id != @network_id

    destination = destination.address_id
  end

  default_address.transfer(amount, asset_id, destination)
end

#wallet_idString

Returns the Wallet ID.

Returns:

  • (String)

    The Wallet ID



48
49
50
# File 'lib/coinbase/wallet.rb', line 48

def wallet_id
  @model.id
end