Class: Zold::Wallet
- Inherits:
-
Object
- Object
- Zold::Wallet
- Defined in:
- lib/zold/wallet.rb
Overview
A single wallet
Constant Summary collapse
- MAINET =
The name of the main production network. All other networks must have different names.
'zold'- EXT =
The extension of the wallet files
'.z'
Instance Method Summary collapse
- #==(other) ⇒ Object
-
#add(txn) ⇒ Object
Add a transaction to the wallet.
-
#age ⇒ Object
Age of wallet in hours.
-
#balance ⇒ Object
Returns current wallet balance.
-
#digest ⇒ Object
Returns a pseudo-unique hexadecimal digest of the wallet content.
-
#exists? ⇒ Boolean
Returns TRUE if the wallet file exists.
-
#flush ⇒ Object
Flush the in-memory cache and force the object to load all data from the disc again.
-
#id ⇒ Object
Returns the wallet ID.
-
#includes_negative?(id, bnf = nil) ⇒ Boolean
Returns TRUE if the wallet contains a payment sent with the specified ID, which was sent to the specified beneficiary.
-
#includes_positive?(id, bnf) ⇒ Boolean
Returns TRUE if the wallet contains a payment received with the specified ID, which was sent by the specified beneficiary.
-
#init(id, pubkey, overwrite: false, network: 'test') ⇒ Object
Creates an empty wallet with the specified ID and public key.
-
#initialize(file) ⇒ Wallet
constructor
The constructor of the wallet, from the file.
-
#key ⇒ Object
Returns the public key of the wallet.
-
#mnemo ⇒ Object
Returns a convenient printable mnemo code of the wallet (mostly useful for logs).
-
#mtime ⇒ Object
Returns the time of when the wallet file was recently modified.
-
#network ⇒ Object
Returns the network ID of the wallet.
-
#path ⇒ Object
Returns the absolute path of the wallet file (it may be absent).
-
#prefix?(prefix) ⇒ Boolean
Returns TRUE if the public key of the wallet includes this payment prefix of the invoice.
-
#protocol ⇒ Object
Returns the protocol ID of the wallet file.
-
#refurbish ⇒ Object
Resaves the content of the wallet to the disc in the right format.
-
#root? ⇒ Boolean
Returns TRUE if it’s a root wallet.
-
#size ⇒ Object
Size of the wallet file in bytes.
-
#sub(amount, invoice, pvt, details = '-', time: Time.now) ⇒ Object
Add a payment transaction to the wallet.
- #to_s ⇒ Object
-
#to_text ⇒ Object
Convert the content of the wallet to the text.
-
#txns ⇒ Object
Retrieve the total list of all transactions.
Constructor Details
#initialize(file) ⇒ Wallet
The constructor of the wallet, from the file. The file may be absent at the time of creating the object. Later, don’t forget to call init() in order to initialize the wallet, if it’s absent.
43 44 45 46 47 48 49 50 |
# File 'lib/zold/wallet.rb', line 43 def initialize(file) unless file.end_with?(Wallet::EXT, Copies::EXT) raise "Wallet file must end with #{Wallet::EXT} or #{Copies::EXT}: #{file}" end @file = File.absolute_path(file) @txns = CachedTxns.new(Txns.new(@file)) @head = CachedHead.new(Head.new(@file)) end |
Instance Method Details
#==(other) ⇒ Object
52 53 54 |
# File 'lib/zold/wallet.rb', line 52 def ==(other) to_s == other.to_s end |
#add(txn) ⇒ Object
Add a transaction to the wallet.
143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
# File 'lib/zold/wallet.rb', line 143 def add(txn) raise 'The txn has to be of type Txn' unless txn.is_a?(Txn) raise "Wallet #{id} can't pay itself: #{txn}" if txn.bnf == id raise "The amount can't be zero in #{id}: #{txn}" if txn.amount.zero? if txn.amount.negative? && includes_negative?(txn.id) raise "Negative transaction with the same ID #{txn.id} already exists in #{id}" end if txn.amount.positive? && includes_positive?(txn.id, txn.bnf) raise "Positive transaction with the same ID #{txn.id} and BNF #{txn.bnf} already exists in #{id}" end raise "The tax payment already exists in #{id}: #{txn}" if Tax.new(self).exists?(txn.details) File.open(path, 'a') { |f| f.print "#{txn}\n" } @txns.flush end |
#age ⇒ Object
Age of wallet in hours.
195 196 197 198 |
# File 'lib/zold/wallet.rb', line 195 def age list = txns list.empty? ? 0 : (Time.now - list.min_by(&:date).date) / (60 * 60) end |
#balance ⇒ Object
Returns current wallet balance.
116 117 118 |
# File 'lib/zold/wallet.rb', line 116 def balance txns.inject(Amount::ZERO) { |sum, t| sum + t.amount } end |
#digest ⇒ Object
Returns a pseudo-unique hexadecimal digest of the wallet content.
190 191 192 |
# File 'lib/zold/wallet.rb', line 190 def digest OpenSSL::Digest::SHA256.file(path).hexdigest end |
#exists? ⇒ Boolean
Returns TRUE if the wallet file exists.
86 87 88 |
# File 'lib/zold/wallet.rb', line 86 def exists? File.exist?(path) end |
#flush ⇒ Object
Flush the in-memory cache and force the object to load all data from the disc again.
223 224 225 226 |
# File 'lib/zold/wallet.rb', line 223 def flush @head.flush @txns.flush end |
#id ⇒ Object
Returns the wallet ID.
111 112 113 |
# File 'lib/zold/wallet.rb', line 111 def id Id.new(@head.fetch[2]) end |
#includes_negative?(id, bnf = nil) ⇒ Boolean
Returns TRUE if the wallet contains a payment sent with the specified ID, which was sent to the specified beneficiary.
160 161 162 163 |
# File 'lib/zold/wallet.rb', line 160 def includes_negative?(id, bnf = nil) raise 'The txn ID has to be of type Integer' unless id.is_a?(Integer) !txns.find { |t| t.id == id && (bnf.nil? || t.bnf == bnf) && t.amount.negative? }.nil? end |
#includes_positive?(id, bnf) ⇒ Boolean
Returns TRUE if the wallet contains a payment received with the specified ID, which was sent by the specified beneficiary.
167 168 169 170 171 |
# File 'lib/zold/wallet.rb', line 167 def includes_positive?(id, bnf) raise 'The txn ID has to be of type Integer' unless id.is_a?(Integer) raise 'The bnf has to be of type Id' unless bnf.is_a?(Id) !txns.find { |t| t.id == id && t.bnf == bnf && !t.amount.negative? }.nil? end |
#init(id, pubkey, overwrite: false, network: 'test') ⇒ Object
Creates an empty wallet with the specified ID and public key.
96 97 98 99 100 101 102 103 |
# File 'lib/zold/wallet.rb', line 96 def init(id, pubkey, overwrite: false, network: 'test') raise "File '#{path}' already exists" if File.exist?(path) && !overwrite raise "Invalid network name '#{network}'" unless /^[a-z]{4,16}$/.match?(network) FileUtils.mkdir_p(File.dirname(path)) File.write(path, "#{network}\n#{PROTOCOL}\n#{id}\n#{pubkey.to_pub}\n\n") @txns.flush @head.flush end |
#key ⇒ Object
Returns the public key of the wallet.
180 181 182 |
# File 'lib/zold/wallet.rb', line 180 def key Key.new(text: @head.fetch[3]) end |
#mnemo ⇒ Object
Returns a convenient printable mnemo code of the wallet (mostly useful for logs).
62 63 64 |
# File 'lib/zold/wallet.rb', line 62 def mnemo "#{id}/#{balance.to_zld(4)}/#{txns.count}t/#{digest[0, 6]}/#{Size.new(size)}" end |
#mtime ⇒ Object
Returns the time of when the wallet file was recently modified.
185 186 187 |
# File 'lib/zold/wallet.rb', line 185 def mtime File.mtime(path) end |
#network ⇒ Object
Returns the network ID of the wallet.
72 73 74 75 76 |
# File 'lib/zold/wallet.rb', line 72 def network n = @head.fetch[0] raise "Invalid network name '#{n}'" unless /^[a-z]{4,16}$/.match?(n) n end |
#path ⇒ Object
Returns the absolute path of the wallet file (it may be absent).
91 92 93 |
# File 'lib/zold/wallet.rb', line 91 def path @file end |
#prefix?(prefix) ⇒ Boolean
Returns TRUE if the public key of the wallet includes this payment prefix of the invoice.
175 176 177 |
# File 'lib/zold/wallet.rb', line 175 def prefix?(prefix) key.to_pub.include?(prefix) end |
#protocol ⇒ Object
Returns the protocol ID of the wallet file.
79 80 81 82 83 |
# File 'lib/zold/wallet.rb', line 79 def protocol v = @head.fetch[1] raise "Invalid protocol version name '#{v}'" unless /^[0-9]+$/.match?(v) v.to_i end |
#refurbish ⇒ Object
Resaves the content of the wallet to the disc in the right format. All unnecessary space and EOL-s are removed. This operation is required in order to make sure two wallets with the same content are identical, no matter whether they were formatted differently.
216 217 218 219 |
# File 'lib/zold/wallet.rb', line 216 def refurbish File.write(path, "#{(@head.fetch + [''] + @txns.fetch.map(&:to_s)).join("\n")}\n") @txns.flush end |
#root? ⇒ Boolean
Returns TRUE if it’s a root wallet.
106 107 108 |
# File 'lib/zold/wallet.rb', line 106 def root? id == Id::ROOT end |
#size ⇒ Object
Size of the wallet file in bytes. If the file doesn’t exist an exception will be raised.
202 203 204 205 |
# File 'lib/zold/wallet.rb', line 202 def size raise "The wallet file #{path} doesn't exist" unless File.exist?(path) File.size(path) end |
#sub(amount, invoice, pvt, details = '-', time: Time.now) ⇒ Object
Add a payment transaction to the wallet.
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/zold/wallet.rb', line 121 def sub(amount, invoice, pvt, details = '-', time: Time.now) raise 'The amount has to be of type Amount' unless amount.is_a?(Amount) raise "The amount can't be negative: #{amount}" if amount.negative? raise 'The pvt has to be of type Key' unless pvt.is_a?(Key) prefix, target = invoice.split('@') tid = max + 1 raise 'Too many transactions already, can\'t add more' if max > 0xffff txn = Txn.new( tid, time, amount * -1, prefix, Id.new(target), details ) txn = txn.signed(pvt, id) raise "Invalid private key for the wallet #{id}" unless Signature.new(network).valid?(key, id, txn) add(txn) txn end |
#to_s ⇒ Object
56 57 58 |
# File 'lib/zold/wallet.rb', line 56 def to_s id.to_s end |
#to_text ⇒ Object
Convert the content of the wallet to the text.
67 68 69 |
# File 'lib/zold/wallet.rb', line 67 def to_text (@head.fetch + [''] + @txns.fetch.map(&:to_text)).join("\n") end |
#txns ⇒ Object
Retrieve the total list of all transactions.
208 209 210 |
# File 'lib/zold/wallet.rb', line 208 def txns @txns.fetch end |