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.
60 61 62 63 64 65 66 67 |
# File 'lib/zold/wallet.rb', line 60 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
69 70 71 |
# File 'lib/zold/wallet.rb', line 69 def ==(other) to_s == other.to_s end |
#add(txn) ⇒ Object
Add a transaction to the wallet.
160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
# File 'lib/zold/wallet.rb', line 160 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.
212 213 214 215 |
# File 'lib/zold/wallet.rb', line 212 def age list = txns list.empty? ? 0 : (Time.now - list.min_by(&:date).date) / (60 * 60) end |
#balance ⇒ Object
Returns current wallet balance.
133 134 135 |
# File 'lib/zold/wallet.rb', line 133 def balance txns.inject(Amount::ZERO) { |sum, t| sum + t.amount } end |
#digest ⇒ Object
Returns a pseudo-unique hexadecimal digest of the wallet content.
207 208 209 |
# File 'lib/zold/wallet.rb', line 207 def digest OpenSSL::Digest::SHA256.file(path).hexdigest end |
#exists? ⇒ Boolean
Returns TRUE if the wallet file exists.
103 104 105 |
# File 'lib/zold/wallet.rb', line 103 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.
240 241 242 243 |
# File 'lib/zold/wallet.rb', line 240 def flush @head.flush @txns.flush end |
#id ⇒ Object
Returns the wallet ID.
128 129 130 |
# File 'lib/zold/wallet.rb', line 128 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.
177 178 179 180 |
# File 'lib/zold/wallet.rb', line 177 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.
184 185 186 187 188 |
# File 'lib/zold/wallet.rb', line 184 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.
113 114 115 116 117 118 119 120 |
# File 'lib/zold/wallet.rb', line 113 def init(id, pubkey, overwrite: false, network: 'test') raise "File '#{path}' already exists" if File.exist?(path) && !overwrite raise "Invalid network name '#{network}'" unless network =~ /^[a-z]{4,16}$/ FileUtils.mkdir_p(File.dirname(path)) IO.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.
197 198 199 |
# File 'lib/zold/wallet.rb', line 197 def key Key.new(text: @head.fetch[3]) end |
#mnemo ⇒ Object
Returns a convenient printable mnemo code of the wallet (mostly useful for logs).
79 80 81 |
# File 'lib/zold/wallet.rb', line 79 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.
202 203 204 |
# File 'lib/zold/wallet.rb', line 202 def mtime File.mtime(path) end |
#network ⇒ Object
Returns the network ID of the wallet.
89 90 91 92 93 |
# File 'lib/zold/wallet.rb', line 89 def network n = @head.fetch[0] raise "Invalid network name '#{n}'" unless n =~ /^[a-z]{4,16}$/ n end |
#path ⇒ Object
Returns the absolute path of the wallet file (it may be absent).
108 109 110 |
# File 'lib/zold/wallet.rb', line 108 def path @file end |
#prefix?(prefix) ⇒ Boolean
Returns TRUE if the public key of the wallet includes this payment prefix of the invoice.
192 193 194 |
# File 'lib/zold/wallet.rb', line 192 def prefix?(prefix) key.to_pub.include?(prefix) end |
#protocol ⇒ Object
Returns the protocol ID of the wallet file.
96 97 98 99 100 |
# File 'lib/zold/wallet.rb', line 96 def protocol v = @head.fetch[1] raise "Invalid protocol version name '#{v}'" unless v =~ /^[0-9]+$/ 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.
233 234 235 236 |
# File 'lib/zold/wallet.rb', line 233 def refurbish IO.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.
123 124 125 |
# File 'lib/zold/wallet.rb', line 123 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.
219 220 221 222 |
# File 'lib/zold/wallet.rb', line 219 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.
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
# File 'lib/zold/wallet.rb', line 138 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
73 74 75 |
# File 'lib/zold/wallet.rb', line 73 def to_s id.to_s end |
#to_text ⇒ Object
Convert the content of the wallet to the text.
84 85 86 |
# File 'lib/zold/wallet.rb', line 84 def to_text (@head.fetch + [''] + @txns.fetch.map(&:to_text)).join("\n") end |
#txns ⇒ Object
Retrieve the total list of all transactions.
225 226 227 |
# File 'lib/zold/wallet.rb', line 225 def txns @txns.fetch end |