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
-
#age ⇒ Object
Age of wallet in hours.
- #balance ⇒ Object
- #digest ⇒ Object
- #exists? ⇒ Boolean
- #flush ⇒ Object
- #id ⇒ Object
- #includes_negative?(id, bnf = nil) ⇒ Boolean
- #includes_positive?(id, bnf) ⇒ Boolean
- #income ⇒ Object
- #init(id, pubkey, overwrite: false, network: 'test') ⇒ Object
-
#initialize(file) ⇒ Wallet
constructor
A new instance of Wallet.
- #key ⇒ Object
- #mnemo ⇒ Object
- #mtime ⇒ Object
- #network ⇒ Object
- #path ⇒ Object
- #prefix?(prefix) ⇒ Boolean
- #protocol ⇒ Object
- #refurbish ⇒ Object
- #root? ⇒ Boolean
-
#size ⇒ Object
Size of the wallet file in bytes.
- #sub(amount, invoice, pvt, details = '-', time: Time.now) ⇒ Object
- #to_s ⇒ Object
- #to_text ⇒ Object
- #txns ⇒ Object
Constructor Details
#initialize(file) ⇒ Wallet
Returns a new instance of Wallet.
57 58 59 60 61 62 63 64 |
# File 'lib/zold/wallet.rb', line 57 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
66 67 68 |
# File 'lib/zold/wallet.rb', line 66 def ==(other) to_s == other.to_s end |
#add(txn) ⇒ Object
144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
# File 'lib/zold/wallet.rb', line 144 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(@file, 'a') { |f| f.print "#{txn}\n" } @txns.flush end |
#age ⇒ Object
Age of wallet in hours
193 194 195 196 |
# File 'lib/zold/wallet.rb', line 193 def age list = txns list.empty? ? 0 : (Time.now - list.min_by(&:date).date) / (60 * 60) end |
#balance ⇒ Object
119 120 121 |
# File 'lib/zold/wallet.rb', line 119 def balance txns.inject(Amount::ZERO) { |sum, t| sum + t.amount } end |
#digest ⇒ Object
188 189 190 |
# File 'lib/zold/wallet.rb', line 188 def digest OpenSSL::Digest::SHA256.file(@file).hexdigest end |
#exists? ⇒ Boolean
94 95 96 |
# File 'lib/zold/wallet.rb', line 94 def exists? File.exist?(@file) end |
#flush ⇒ Object
215 216 217 218 |
# File 'lib/zold/wallet.rb', line 215 def flush @head.flush @txns.flush end |
#id ⇒ Object
115 116 117 |
# File 'lib/zold/wallet.rb', line 115 def id Id.new(@head.fetch[2].strip) end |
#includes_negative?(id, bnf = nil) ⇒ Boolean
159 160 161 162 |
# File 'lib/zold/wallet.rb', line 159 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
164 165 166 167 168 |
# File 'lib/zold/wallet.rb', line 164 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 |
#income ⇒ Object
178 179 180 181 182 |
# File 'lib/zold/wallet.rb', line 178 def income txns.each do |t| yield t unless t.amount.negative? end end |
#init(id, pubkey, overwrite: false, network: 'test') ⇒ Object
102 103 104 105 106 107 108 109 |
# File 'lib/zold/wallet.rb', line 102 def init(id, pubkey, overwrite: false, network: 'test') raise "File '#{@file}' already exists" if File.exist?(@file) && !overwrite raise "Invalid network name '#{network}'" unless network =~ /^[a-z]{4,16}$/ FileUtils.mkdir_p(File.dirname(@file)) IO.write(@file, "#{network}\n#{PROTOCOL}\n#{id}\n#{pubkey.to_pub}\n\n") @txns.flush @head.flush end |
#key ⇒ Object
174 175 176 |
# File 'lib/zold/wallet.rb', line 174 def key Key.new(text: @head.fetch[3].strip) end |
#mnemo ⇒ Object
74 75 76 |
# File 'lib/zold/wallet.rb', line 74 def mnemo "#{id}/#{balance.to_zld(4)}/#{txns.count}t/#{digest[0, 6]}/#{Size.new(size)}" end |
#mtime ⇒ Object
184 185 186 |
# File 'lib/zold/wallet.rb', line 184 def mtime File.mtime(@file) end |
#network ⇒ Object
82 83 84 85 86 |
# File 'lib/zold/wallet.rb', line 82 def network n = @head.fetch[0].strip raise "Invalid network name '#{n}'" unless n =~ /^[a-z]{4,16}$/ n end |
#path ⇒ Object
98 99 100 |
# File 'lib/zold/wallet.rb', line 98 def path @file end |
#prefix?(prefix) ⇒ Boolean
170 171 172 |
# File 'lib/zold/wallet.rb', line 170 def prefix?(prefix) key.to_pub.include?(prefix) end |
#protocol ⇒ Object
88 89 90 91 92 |
# File 'lib/zold/wallet.rb', line 88 def protocol v = @head.fetch[1].strip raise "Invalid protocol version name '#{v}'" unless v =~ /^[0-9]+$/ v.to_i end |
#refurbish ⇒ Object
207 208 209 210 211 212 213 |
# File 'lib/zold/wallet.rb', line 207 def refurbish IO.write( @file, "#{network}\n#{protocol}\n#{id}\n#{key.to_pub}\n\n#{txns.map { |t| t.to_s + "\n" }.join}" ) @txns.flush end |
#size ⇒ Object
Size of the wallet file in bytes
199 200 201 |
# File 'lib/zold/wallet.rb', line 199 def size File.size(path) end |
#sub(amount, invoice, pvt, details = '-', time: Time.now) ⇒ Object
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
# File 'lib/zold/wallet.rb', line 123 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
70 71 72 |
# File 'lib/zold/wallet.rb', line 70 def to_s id.to_s end |
#to_text ⇒ Object
78 79 80 |
# File 'lib/zold/wallet.rb', line 78 def to_text (@head.fetch + [''] + @txns.fetch.map(&:to_text)).join("\n") end |
#txns ⇒ Object
203 204 205 |
# File 'lib/zold/wallet.rb', line 203 def txns @txns.fetch end |