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.

Defined Under Namespace

Classes: WalletData

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(seed: nil, address_count: 1, client: Jimson::Client.new(ENV.fetch('BASE_SEPOLIA_RPC_URL', nil))) ⇒ Wallet

Returns a new Wallet object.

Parameters:

  • seed (Integer) (defaults to: nil)

    (Optional) The seed to use for the Wallet. Expects a 32-byte hexadecimal. If not provided, a new seed will be generated.

  • address_count (Integer) (defaults to: 1)

    (Optional) The number of addresses to generate for the Wallet. If not provided, a single address will be generated.

  • client (Jimson::Client) (defaults to: Jimson::Client.new(ENV.fetch('BASE_SEPOLIA_RPC_URL', nil)))

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

Raises:

  • (ArgumentError)


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

def initialize(seed: nil, address_count: 1, client: Jimson::Client.new(ENV.fetch('BASE_SEPOLIA_RPC_URL', nil)))
  raise ArgumentError, 'Seed must be 32 bytes' if !seed.nil? && seed.length != 64
  raise ArgumentError, 'Address count must be positive' if address_count < 1

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

  @wallet_id = SecureRandom.uuid
  # 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

  @client = client

  address_count.times { create_address }
end

Instance Attribute Details

#network_idObject (readonly)

Returns the value of attribute network_id.



12
13
14
# File 'lib/coinbase/wallet.rb', line 12

def network_id
  @network_id
end

#wallet_idObject (readonly)

Returns the value of attribute wallet_id.



12
13
14
# File 'lib/coinbase/wallet.rb', line 12

def wallet_id
  @wallet_id
end

Instance Method Details

#create_addressAddress

Creates a new Address in the Wallet.

Returns:



42
43
44
45
46
47
48
49
50
51
# File 'lib/coinbase/wallet.rb', line 42

def create_address
  # TODO: Register with server.
  path = "#{@address_path_prefix}/#{@address_index}"
  private_key = @master.node_for_path(path).private_key.to_hex
  key = Eth::Key.new(priv: private_key)
  address = Address.new(@network_id, key.address.address, @wallet_id, key, client: @client)
  @addresses << address
  @address_index += 1
  address
end

#default_addressAddress

Returns the default address of the Wallet.

Returns:

  • (Address)

    The default address



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

def default_address
  @addresses.first
end

#exportWalletData

Exports the Wallet’s data to a WalletData object.

Returns:



137
138
139
# File 'lib/coinbase/wallet.rb', line 137

def export
  WalletData.new(@master.seed_hex, @addresses.length)
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:



62
63
64
# File 'lib/coinbase/wallet.rb', line 62

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



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/coinbase/wallet.rb', line 93

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

  eth_balance = list_balances[normalized_asset_id] || BigDecimal(0)

  case asset_id
  when :eth
    eth_balance
  when :gwei
    eth_balance * Coinbase::GWEI_PER_ETHER
  when :wei
    eth_balance * Coinbase::WEI_PER_ETHER
  else
    BigDecimal(0)
  end
end

#list_addressesArray<Address>

Returns the list of Addresses in the Wallet.

Returns:

  • (Array<Address>)

    The list of Addresses



68
69
70
71
# File 'lib/coinbase/wallet.rb', line 68

def list_addresses
  # TODO: Register with server.
  @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.



75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/coinbase/wallet.rb', line 75

def list_balances
  balance_map = BalanceMap.new

  @addresses.each do |address|
    address.list_balances.each do |asset_id, balance|
      balance_map[asset_id] ||= BigDecimal(0)
      current_balance = balance_map[asset_id]
      new_balance = balance + current_balance
      balance_map[asset_id] = new_balance
    end
  end

  balance_map
end

#to_dataWalletData

Returns the data required to recreate the Wallet.

Returns:



156
157
158
# File 'lib/coinbase/wallet.rb', line 156

def to_data
  WalletData.new(@master.seed_hex, @addresses.length)
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.



121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/coinbase/wallet.rb', line 121

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