Class: Bitcoin::Wallet::Account

Inherits:
Object
  • Object
show all
Includes:
HexConverter
Defined in:
lib/bitcoin/wallet/account.rb

Overview

the account in BIP-44

Constant Summary collapse

PURPOSE_TYPE =
{legacy: 44, nested_witness: 49, native_segwit: 84}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from HexConverter

#to_hex

Constructor Details

#initialize(account_key, purpose = PURPOSE_TYPE[:native_segwit], index = 0, name = '') ⇒ Account

Returns a new instance of Account.



19
20
21
22
23
24
25
26
27
28
# File 'lib/bitcoin/wallet/account.rb', line 19

def initialize(, purpose = PURPOSE_TYPE[:native_segwit], index = 0, name = '')
  validate_params!(, purpose, index)
  @purpose = purpose
  @index = index
  @name = name
  @receive_depth = 0
  @change_depth = 0
  @lookahead = 10
  @account_key = 
end

Instance Attribute Details

#account_keyObject (readonly)

account xpub key Bitcoin::ExtPubkey



13
14
15
# File 'lib/bitcoin/wallet/account.rb', line 13

def 
  @account_key
end

#change_depthObject

change address depth(address index)



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

def change_depth
  @change_depth
end

#indexObject (readonly)

BIP-44 index



11
12
13
# File 'lib/bitcoin/wallet/account.rb', line 11

def index
  @index
end

#lookaheadObject

Returns the value of attribute lookahead.



16
17
18
# File 'lib/bitcoin/wallet/account.rb', line 16

def lookahead
  @lookahead
end

#nameObject (readonly)

account name



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

def name
  @name
end

#purposeObject (readonly)

either 44 or 49 or 84



10
11
12
# File 'lib/bitcoin/wallet/account.rb', line 10

def purpose
  @purpose
end

#receive_depthObject

receive address depth(address index)



14
15
16
# File 'lib/bitcoin/wallet/account.rb', line 14

def receive_depth
  @receive_depth
end

#walletObject

Returns the value of attribute wallet.



17
18
19
# File 'lib/bitcoin/wallet/account.rb', line 17

def wallet
  @wallet
end

Class Method Details

.parse_from_payload(payload) ⇒ Object



30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/bitcoin/wallet/account.rb', line 30

def self.parse_from_payload(payload)
  buf = StringIO.new(payload)
   = Bitcoin::ExtPubkey.parse_from_payload(buf.read(78))
  payload = buf.read
  name, payload = Bitcoin.unpack_var_string(payload)
  name = name.force_encoding('utf-8')
  purpose, index, receive_depth, change_depth, lookahead = payload.unpack('I*')
  a = Account.new(, purpose, index, name)
  a.receive_depth = receive_depth
  a.change_depth = change_depth
  a.lookahead = lookahead
  a
end

Instance Method Details

#create_changeBitcoin::ExtPubkey

create new change key

Returns:



66
67
68
69
70
# File 'lib/bitcoin/wallet/account.rb', line 66

def create_change
  @change_depth += 1
  save
  save_key(1, @change_depth, derive_key(1, @change_depth))
end

#create_receiveBitcoin::ExtPubkey

create new receive key

Returns:



58
59
60
61
62
# File 'lib/bitcoin/wallet/account.rb', line 58

def create_receive
  @receive_depth += 1
  save
  save_key(0, @receive_depth, derive_key(0, @receive_depth))
end

#derived_change_keysArray[Bitcoin::ExtPubkey]

get the list of derived keys for change key.



94
95
96
# File 'lib/bitcoin/wallet/account.rb', line 94

def derived_change_keys
  (change_depth + 1).times.map{|i|derive_key(1,i)}
end

#derived_receive_keysArray[Bitcoin::ExtPubkey]

get the list of derived keys for receive key.



88
89
90
# File 'lib/bitcoin/wallet/account.rb', line 88

def derived_receive_keys
  (receive_depth + 1).times.map{|i|derive_key(0,i)}
end

#pathObject

account derivation path



113
114
115
# File 'lib/bitcoin/wallet/account.rb', line 113

def path
  "m/#{purpose}'/#{Bitcoin.chain_params.bip44_coin_type}'/#{index}'"
end

#saveObject

save this account payload to database.



73
74
75
76
77
# File 'lib/bitcoin/wallet/account.rb', line 73

def save
  wallet.db.(self)
  save_key(0, receive_depth, derive_key(0, receive_depth)) if receive_depth.zero?
  save_key(1, change_depth, derive_key(1, change_depth)) if change_depth.zero?
end

#save_key(purpose, index, key) ⇒ Object

Parameters:

  • purpose

    0:recieve, 1:change

  • index

    receive_depth or change_depth

  • key

    the key to be saved



82
83
84
# File 'lib/bitcoin/wallet/account.rb', line 82

def save_key(purpose, index, key)
  wallet.db.save_key(self, purpose, index, key)
end

#to_hObject



127
128
129
130
131
132
133
134
# File 'lib/bitcoin/wallet/account.rb', line 127

def to_h
  {
      name: name, type: type, index: index, receive_depth: receive_depth, change_depth: change_depth,
      look_ahead: lookahead, receive_address: derive_key(0, receive_depth).addr,
      change_address: derive_key(1, change_depth).addr,
      account_key: .to_base58, path: path, watch_only: watch_only
  }
end

#to_payloadObject



44
45
46
47
48
49
# File 'lib/bitcoin/wallet/account.rb', line 44

def to_payload
  payload = .to_payload
  payload << Bitcoin.pack_var_string(name.unpack1('H*').htb)
  payload << [purpose, index, receive_depth, change_depth, lookahead].pack('I*')
  payload
end

#typeObject

get account type label.



99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/bitcoin/wallet/account.rb', line 99

def type
  case purpose
    when PURPOSE_TYPE[:legacy]
      'pubkeyhash'
    when PURPOSE_TYPE[:nested_witness]
      'p2wpkh-p2sh'
    when PURPOSE_TYPE[:native_segwit]
      'p2wpkh'
    else
      'unknown'
  end
end

#watch_onlyObject



117
118
119
# File 'lib/bitcoin/wallet/account.rb', line 117

def watch_only
  false # TODO implements import watch only address.
end

#watch_targetsArray[String]

get data elements tobe monitored with Bloom Filter.

Returns:



123
124
125
# File 'lib/bitcoin/wallet/account.rb', line 123

def watch_targets
  wallet.db.get_keys(self).map { |key| Bitcoin.hash160(key) }
end

#witness?Boolean

whether support witness

Returns:

  • (Boolean)


52
53
54
# File 'lib/bitcoin/wallet/account.rb', line 52

def witness?
  [PURPOSE_TYPE[:nested_witness], PURPOSE_TYPE[:native_segwit]].include?(purpose)
end