ledger-lite 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Manifest.txt +2 -0
- data/README.md +28 -33
- data/lib/ledger-lite.rb +2 -179
- data/lib/ledger-lite/base.rb +251 -0
- data/lib/ledger-lite/version.rb +1 -1
- data/test/helper.rb +39 -2
- data/test/test_blocks.rb +2 -0
- data/test/test_transactions.rb +2 -0
- data/test/test_transactions_v2.rb +109 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8bb00328da0a43ae0598c37a0fdf2bbfb10879b1
|
4
|
+
data.tar.gz: d86879ffe02cc2d2eb90995449de681855259903
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e90be7b13645162660fa2c0d1a0c19f816a97d1d8cd531e073039e27a24187a57526a8ca46c603229724ae3c25355416ab179810ea6c6f88573deea9ef7a698d
|
7
|
+
data.tar.gz: 522966950666004944338587eb7dfe07a2af5d9e3708d22913f4200ada59bfd432dd63ccf29f21c9781834617a745ec98634825e97854972386e6e460e46c7e1
|
data/Manifest.txt
CHANGED
data/README.md
CHANGED
@@ -79,34 +79,34 @@ telling you who owns how much:
|
|
79
79
|
|
80
80
|
### Use `write` to write / add transactions
|
81
81
|
|
82
|
-
|
82
|
+
|
83
|
+
Or use transaction hashes:
|
83
84
|
|
84
85
|
``` ruby
|
85
86
|
ledger = Ledger.new
|
86
87
|
|
87
|
-
ledger.write(
|
88
|
-
ledger.write(
|
89
|
-
ledger.write(
|
90
|
-
ledger.write(
|
88
|
+
ledger.write( from: "Keukenhof†", to: "Vincent", amount: 11 )
|
89
|
+
ledger.write( from: "Vincent", to: "Anne", amount: 3 )
|
90
|
+
ledger.write( from: "Anne", to: "Julia", amount: 2 )
|
91
|
+
ledger.write( from: "Julia", to: "Luuk", amount: 1 )
|
91
92
|
|
92
|
-
ledger.write(
|
93
|
-
|
94
|
-
|
95
|
-
|
93
|
+
ledger.write( { from: "Dutchgrown†", to: "Ruben", amount: 11 },
|
94
|
+
{ from: "Vincent", to: "Max", amount: 3 },
|
95
|
+
{ from: "Ruben", to: "Julia", amount: 2 },
|
96
|
+
{ from: "Anne", to: "Martijn", amount: 1 } )
|
96
97
|
|
97
98
|
pp ledger
|
98
99
|
```
|
99
100
|
|
100
|
-
|
101
|
-
Or pass in many transaction (Tx) classes/structs:
|
101
|
+
Or use transaction (tx) classes/structs:
|
102
102
|
|
103
103
|
``` ruby
|
104
104
|
ledger = Ledger.new
|
105
105
|
|
106
|
-
ledger.write( Tx.new( "Keukenhof†", "Vincent", 11 )
|
107
|
-
|
108
|
-
|
109
|
-
|
106
|
+
ledger.write( Tx.new( "Keukenhof†", "Vincent", 11 ))
|
107
|
+
ledger.write( Tx.new( "Vincent", "Anne", 3 ))
|
108
|
+
ledger.write( Tx.new( "Anne", "Julia", 2 ))
|
109
|
+
ledger.write( Tx.new( "Julia", "Luuk", 1 ))
|
110
110
|
|
111
111
|
ledger.write( Tx.new( "Dutchgrown†", "Ruben", 11 ),
|
112
112
|
Tx.new( "Vincent", "Max", 3 ),
|
@@ -134,24 +134,6 @@ ledger << [Tx.new( "Dutchgrown†", "Ruben", 11 ),
|
|
134
134
|
pp ledger
|
135
135
|
```
|
136
136
|
|
137
|
-
Or use transaction hashes:
|
138
|
-
|
139
|
-
``` ruby
|
140
|
-
ledger = Ledger.new
|
141
|
-
|
142
|
-
ledger.write( { from: "Keukenhof†", to: "Vincent", amount: 11 },
|
143
|
-
{ from: "Vincent", to: "Anne", amount: 3 },
|
144
|
-
{ from: "Anne", to: "Julia", amount: 2 },
|
145
|
-
{ from: "Julia", to: "Luuk", amount: 1 })
|
146
|
-
|
147
|
-
ledger.write( { from: "Dutchgrown†", to: "Ruben", amount: 11 },
|
148
|
-
{ from: "Vincent", to: "Max", amount: 3 },
|
149
|
-
{ from: "Ruben", to: "Julia", amount: 2 },
|
150
|
-
{ from: "Anne", to: "Martijn", amount: 1 })
|
151
|
-
|
152
|
-
pp ledger
|
153
|
-
```
|
154
|
-
|
155
137
|
|
156
138
|
Or use blocks of transaction hashes:
|
157
139
|
|
@@ -208,6 +190,19 @@ pp ledger
|
|
208
190
|
|
209
191
|
|
210
192
|
|
193
|
+
## Ledger Lite in the Real World
|
194
|
+
|
195
|
+
- [**centralbank**](https://github.com/openblockchains/centralbank) - command line tool (and core library) - print your own money / cryptocurrency; run your own federated central bank nodes on the blockchain peer-to-peer over HTTP; revolutionize the world one block at a time
|
196
|
+
- [**shilling**](https://github.com/bitshilling/bitshilling.tools) - command line tool (and core library) - shilling (or schilling) on the blockchain! rock-solid alpine dollar from austria; print (mine) your own shillings; run your own federated shilling central bank nodes w/ public distributed (hyper) ledger book on the blockchain peer-to-peer over HTTP; revolutionize the world one block at a time
|
197
|
+
- You? Add your tool / service
|
198
|
+
|
199
|
+
|
200
|
+
|
201
|
+
## References
|
202
|
+
|
203
|
+
[**Programming Cryptocurrencies and Blockchains (in Ruby)**](http://yukimotopress.github.io/blockchains) by Gerald Bauer et al, 2018, Yuki & Moto Press
|
204
|
+
|
205
|
+
|
211
206
|
## License
|
212
207
|
|
213
208
|
![](https://publicdomainworks.github.io/buttons/zero88x31.png)
|
data/lib/ledger-lite.rb
CHANGED
@@ -1,186 +1,9 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
require 'pp' # for pp => pretty printer
|
4
|
-
require 'forwardable'
|
5
|
-
require 'date'
|
6
|
-
require 'time'
|
7
|
-
require 'json'
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
## our own code
|
13
|
-
require 'ledger-lite/version' # note: let version always go first
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
module LedgerLite
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
class Configuration
|
22
|
-
|
23
|
-
## system settings
|
24
|
-
|
25
|
-
## use a different name e.g.
|
26
|
-
## - mint (like royal mint or federal coin mint?) or
|
27
|
-
## - base
|
28
|
-
## - magic (for creating coins out-of-nothing?) or
|
29
|
-
## - network or ??) - why? why not?
|
30
|
-
##
|
31
|
-
attr_accessor :coinbase
|
32
|
-
|
33
|
-
## note: for now is an array (allow/ support multiple coinbases)
|
34
|
-
## note: add a (†) coinbase marker
|
35
|
-
COINBASE = ['Coinbase†']
|
36
|
-
|
37
|
-
def initialize
|
38
|
-
@coinbase = COINBASE
|
39
|
-
end
|
40
|
-
|
41
|
-
def coinbase?( addr )
|
42
|
-
@coinbase.include?( addr )
|
43
|
-
end
|
44
|
-
end # class Configuration
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
class Ledger
|
50
|
-
extend Forwardable
|
51
|
-
|
52
|
-
|
53
|
-
## lets you use
|
54
|
-
## Ledger.configure do |config|
|
55
|
-
## config.coinbase = ['Keukenhof†']
|
56
|
-
## end
|
57
|
-
|
58
|
-
def self.configure
|
59
|
-
yield( config )
|
60
|
-
end
|
61
|
-
|
62
|
-
def self.config
|
63
|
-
@config ||= Configuration.new
|
64
|
-
end
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
attr_reader :addr ## make addr private e.g. remove - why? e.g. use hash forwards/delegates - why not?
|
69
|
-
|
70
|
-
|
71
|
-
## delegate some methods (and operators) to addr hash (for easier/shortcut access)
|
72
|
-
def_delegators :@addr, :[], :size, :each, :empty?, :any?
|
73
|
-
|
74
|
-
|
75
|
-
def initialize( *args )
|
76
|
-
@addr = {}
|
77
|
-
|
78
|
-
## add all transactions passed in on startup; if no args - do nothing
|
79
|
-
unless args.empty?
|
80
|
-
## note: MUST unsplat (*) args
|
81
|
-
## otherwise args get "double" wrapped in array
|
82
|
-
write( *args )
|
83
|
-
end
|
84
|
-
end # method initialize
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
def write( *args )
|
89
|
-
puts "write:"
|
90
|
-
pp args
|
91
|
-
|
92
|
-
## note: allow/support splat-* for now for convenience (auto-wraps args into array)
|
93
|
-
if args.size == 1 && args[0].is_a?( Array )
|
94
|
-
puts " unwrap array in array"
|
95
|
-
blks_or_txns = args[0] ## "unwrap" array in array
|
96
|
-
else
|
97
|
-
blks_or_txns = args ## use "auto-wrapped" splat array
|
98
|
-
end
|
99
|
-
|
100
|
-
## "unpack" transactions from possible (optional) blocks
|
101
|
-
## and return "flattend" **single** array of transactions
|
102
|
-
transactions = unpack_transactions( blks_or_txns )
|
103
|
-
|
104
|
-
## unpack & unsplat array (to pass in args to send) => from, to, amount
|
105
|
-
transactions.each { |tx| send( *unpack(tx) ) }
|
106
|
-
end
|
107
|
-
|
108
|
-
## note: add and the << operator is an alias for write
|
109
|
-
alias :add :write
|
110
|
-
alias :<< :write
|
111
|
-
|
112
|
-
|
113
|
-
def unpack_transactions( blocks )
|
114
|
-
## "unpack" transactions from possible (optional) blocks
|
115
|
-
## and return "flattend" **single** array of transactions
|
116
|
-
|
117
|
-
blocks.reduce( [] ) do |acc, block|
|
118
|
-
if block.respond_to?( :transactions ) ## bingo! assume it's block if it has transactions method
|
119
|
-
acc + block.transactions
|
120
|
-
else ## note: otherwise assumes it's just a "plain" **single** transaction
|
121
|
-
tx = block
|
122
|
-
acc + [tx] ## wrap in array (use acc << tx - with side effects/mutate in place - why? why not?)
|
123
|
-
end
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
def unpack( tx )
|
128
|
-
## "unpack" from, to, amount values
|
129
|
-
|
130
|
-
puts "unpack:"
|
131
|
-
pp tx
|
132
|
-
|
133
|
-
if tx.is_a?( Hash ) ## support hashes
|
134
|
-
from = tx[:from]
|
135
|
-
to = tx[:to]
|
136
|
-
amount = tx[:amount]
|
137
|
-
else ## assume it's a transaction (tx) struct/class
|
138
|
-
from = tx.from
|
139
|
-
to = tx.to
|
140
|
-
amount = tx.amount
|
141
|
-
end
|
142
|
-
[from,to,amount]
|
143
|
-
end
|
144
|
-
|
145
|
-
|
146
|
-
##
|
147
|
-
# find a better name - why? why not?
|
148
|
-
## e.g. use can? funds? sufficient? has_funds?
|
149
|
-
def sufficient_funds?( addr, amount )
|
150
|
-
return true if self.class.config.coinbase?( addr ) ## note: coinbase has unlimited funds!!!
|
151
|
-
@addr.has_key?( addr ) && @addr[addr] - amount >= 0
|
152
|
-
end
|
153
|
-
|
154
|
-
|
155
|
-
## apply/do single transaction - send payment - do transfer
|
156
|
-
## - find a different name - why? why not?
|
157
|
-
def send( from, to, amount )
|
158
|
-
|
159
|
-
if sufficient_funds?( from, amount )
|
160
|
-
if self.class.config.coinbase?( from )
|
161
|
-
# note: coinbase has unlimited funds!! ("virtual" built-in money printing address)
|
162
|
-
else
|
163
|
-
@addr[ from ] ||= 0
|
164
|
-
@addr[ from ] -= amount
|
165
|
-
end
|
166
|
-
@addr[ to ] ||= 0
|
167
|
-
@addr[ to ] += amount
|
168
|
-
end
|
169
|
-
end # method transfer
|
170
|
-
|
171
|
-
## note: transfer is an alias for send (payment)
|
172
|
-
alias :transfer :send
|
173
|
-
|
174
|
-
|
175
|
-
end # class Ledger
|
176
|
-
|
177
|
-
|
178
|
-
end # module LedgerLite
|
179
3
|
|
4
|
+
## our own code (without "top-level" shortcuts e.g. "modular version")
|
5
|
+
require 'ledger-lite/base'
|
180
6
|
|
181
7
|
###
|
182
8
|
# add convenience top-level shortcut / alias
|
183
9
|
Ledger = LedgerLite::Ledger
|
184
|
-
|
185
|
-
# say hello
|
186
|
-
puts LedgerLite.banner if defined?($RUBYLIBS_DEBUG) && $RUBYLIBS_DEBUG
|
@@ -0,0 +1,251 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'pp' # for pp => pretty printer
|
4
|
+
require 'forwardable'
|
5
|
+
|
6
|
+
|
7
|
+
|
8
|
+
|
9
|
+
## our own code
|
10
|
+
require 'ledger-lite/version' # note: let version always go first
|
11
|
+
|
12
|
+
|
13
|
+
|
14
|
+
module LedgerLite
|
15
|
+
|
16
|
+
|
17
|
+
|
18
|
+
class Configuration
|
19
|
+
|
20
|
+
## system settings
|
21
|
+
|
22
|
+
## use a different name e.g.
|
23
|
+
## - mint (like royal mint or federal coin mint?) or
|
24
|
+
## - base
|
25
|
+
## - magic (for creating coins out-of-nothing?) or
|
26
|
+
## - network or ??) - why? why not?
|
27
|
+
##
|
28
|
+
attr_accessor :coinbase
|
29
|
+
|
30
|
+
## note: for now is an array (allow/ support multiple coinbases)
|
31
|
+
## note: add a (†) coinbase marker
|
32
|
+
COINBASE = ['Coinbase†']
|
33
|
+
|
34
|
+
def initialize
|
35
|
+
@coinbase = COINBASE
|
36
|
+
end
|
37
|
+
|
38
|
+
def coinbase?( addr )
|
39
|
+
@coinbase.include?( addr )
|
40
|
+
end
|
41
|
+
end # class Configuration
|
42
|
+
|
43
|
+
|
44
|
+
|
45
|
+
|
46
|
+
class Base
|
47
|
+
extend Forwardable
|
48
|
+
|
49
|
+
|
50
|
+
## lets you use
|
51
|
+
## Ledger.configure do |config|
|
52
|
+
## config.coinbase = ['Keukenhof†']
|
53
|
+
## end
|
54
|
+
|
55
|
+
def self.configure
|
56
|
+
yield( config )
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.config
|
60
|
+
@config ||= Configuration.new
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
|
65
|
+
attr_reader :addr ## make addr private e.g. remove - why? e.g. use hash forwards/delegates - why not?
|
66
|
+
|
67
|
+
|
68
|
+
## delegate some methods (and operators) to addr hash (for easier/shortcut access)
|
69
|
+
def_delegators :@addr, :[], :size, :each, :empty?, :any?
|
70
|
+
|
71
|
+
|
72
|
+
def initialize( *args )
|
73
|
+
@addr = {}
|
74
|
+
|
75
|
+
## add all transactions passed in on startup; if no args - do nothing
|
76
|
+
unless args.empty?
|
77
|
+
## note: MUST unsplat (*) args
|
78
|
+
## otherwise args get "double" wrapped in array
|
79
|
+
write( *args )
|
80
|
+
end
|
81
|
+
end # method initialize
|
82
|
+
|
83
|
+
|
84
|
+
|
85
|
+
def write( *args )
|
86
|
+
puts "write:"
|
87
|
+
pp args
|
88
|
+
|
89
|
+
## note: allow/support splat-* for now for convenience (auto-wraps args into array)
|
90
|
+
if args.size == 1 && args[0].is_a?( Array )
|
91
|
+
puts " unwrap array in array"
|
92
|
+
blks_or_txns = args[0] ## "unwrap" array in array
|
93
|
+
else
|
94
|
+
blks_or_txns = args ## use "auto-wrapped" splat array
|
95
|
+
end
|
96
|
+
|
97
|
+
## "unpack" transactions from possible (optional) blocks
|
98
|
+
## and return "flattend" **single** array of transactions
|
99
|
+
transactions = unpack_transactions( blks_or_txns )
|
100
|
+
|
101
|
+
## unpack & unsplat array (to pass in args to send) => from, to, amount
|
102
|
+
transactions.each { |tx| send( *unpack(tx) ) }
|
103
|
+
end
|
104
|
+
|
105
|
+
## note: add and the << operator is an alias for write
|
106
|
+
alias :add :write
|
107
|
+
alias :<< :write
|
108
|
+
|
109
|
+
|
110
|
+
def unpack_transactions( blocks )
|
111
|
+
## "unpack" transactions from possible (optional) blocks
|
112
|
+
## and return "flattend" **single** array of transactions
|
113
|
+
|
114
|
+
blocks.reduce( [] ) do |acc, block|
|
115
|
+
if block.respond_to?( :transactions ) ## bingo! assume it's block if it has transactions method
|
116
|
+
acc + block.transactions
|
117
|
+
else ## note: otherwise assumes it's just a "plain" **single** transaction
|
118
|
+
tx = block
|
119
|
+
acc + [tx] ## wrap in array (use acc << tx - with side effects/mutate in place - why? why not?)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end ## class Base
|
124
|
+
|
125
|
+
|
126
|
+
|
127
|
+
class Ledger < Base
|
128
|
+
|
129
|
+
def unpack( tx )
|
130
|
+
## "unpack" from, to, amount values
|
131
|
+
|
132
|
+
puts "unpack:"
|
133
|
+
pp tx
|
134
|
+
|
135
|
+
if tx.is_a?( Hash ) ## support hashes
|
136
|
+
from = tx[:from]
|
137
|
+
to = tx[:to]
|
138
|
+
amount = tx[:amount]
|
139
|
+
else ## assume it's a transaction (tx) struct/class
|
140
|
+
from = tx.from
|
141
|
+
to = tx.to
|
142
|
+
amount = tx.amount
|
143
|
+
end
|
144
|
+
[from,to,amount]
|
145
|
+
end
|
146
|
+
|
147
|
+
|
148
|
+
##
|
149
|
+
# find a better name - why? why not?
|
150
|
+
## e.g. use can? funds? sufficient? has_funds?
|
151
|
+
def sufficient?( addr, amount )
|
152
|
+
return true if self.class.config.coinbase?( addr ) ## note: coinbase has unlimited funds!!!
|
153
|
+
|
154
|
+
@addr.has_key?( addr ) &&
|
155
|
+
@addr[addr] - amount >= 0
|
156
|
+
end
|
157
|
+
|
158
|
+
## note: sufficient_funds? is an alias for sufficient?
|
159
|
+
alias :sufficient_funds? :sufficient?
|
160
|
+
|
161
|
+
|
162
|
+
## apply/do single transaction - send payment - do transfer
|
163
|
+
## - find a different name - why? why not?
|
164
|
+
def send( from, to, amount )
|
165
|
+
|
166
|
+
if sufficient?( from, amount )
|
167
|
+
if self.class.config.coinbase?( from )
|
168
|
+
# note: coinbase has unlimited funds!! ("virtual" built-in money printing address)
|
169
|
+
else
|
170
|
+
@addr[ from ] -= amount
|
171
|
+
end
|
172
|
+
@addr[ to ] ||= 0
|
173
|
+
@addr[ to ] += amount
|
174
|
+
end
|
175
|
+
end # method send
|
176
|
+
|
177
|
+
## note: transfer is an alias for send (payment)
|
178
|
+
alias :transfer :send
|
179
|
+
|
180
|
+
end # class Ledger
|
181
|
+
|
182
|
+
|
183
|
+
|
184
|
+
|
185
|
+
module V2
|
186
|
+
## ledger for commodities (e.g.tulips) / assets / etc.
|
187
|
+
|
188
|
+
class Ledger < Base
|
189
|
+
|
190
|
+
def unpack( tx )
|
191
|
+
## "unpack" from, to, amount values
|
192
|
+
|
193
|
+
puts "unpack:"
|
194
|
+
pp tx
|
195
|
+
|
196
|
+
if tx.is_a?( Hash ) ## support hashes
|
197
|
+
from = tx[:from]
|
198
|
+
to = tx[:to]
|
199
|
+
qty = tx[:qty] ## check: use different name e.g. amount, num, etc. why? why not?
|
200
|
+
name = tx[:name] ## check: use different name e.g. title, what, etc. why? why not?
|
201
|
+
else ## assume it's a transaction (tx) struct/class
|
202
|
+
from = tx.from
|
203
|
+
to = tx.to
|
204
|
+
qty = tx.qty
|
205
|
+
name = tx.name
|
206
|
+
end
|
207
|
+
[from,to,qty,name]
|
208
|
+
end
|
209
|
+
|
210
|
+
|
211
|
+
##
|
212
|
+
# find a better name - why? why not?
|
213
|
+
def sufficient?( addr, qty, name )
|
214
|
+
return true if self.class.config.coinbase?( addr ) ## note: coinbase has unlimited funds!!!
|
215
|
+
|
216
|
+
@addr.has_key?( addr ) &&
|
217
|
+
@addr[addr].has_key?( name ) &&
|
218
|
+
@addr[addr][name] - qty >= 0
|
219
|
+
end
|
220
|
+
|
221
|
+
|
222
|
+
## apply/do single transaction - send commodity/assets - do transfer
|
223
|
+
## - find a different name - why? why not?
|
224
|
+
def send( from, to, qty, name )
|
225
|
+
|
226
|
+
if sufficient?( from, qty, name )
|
227
|
+
if self.class.config.coinbase?( from )
|
228
|
+
# note: coinbase has unlimited funds!! ("virtual" built-in money printing address)
|
229
|
+
else
|
230
|
+
@addr[ from ][ name ] -= qty
|
231
|
+
end
|
232
|
+
@addr[ to ] ||= {} ## make sure addr exists (e.g. init with empty hash {})
|
233
|
+
@addr[ to ][ name ] ||= 0
|
234
|
+
@addr[ to ][ name ] += qty
|
235
|
+
end
|
236
|
+
end # method send
|
237
|
+
|
238
|
+
## note: transfer is an alias for send (payment)
|
239
|
+
alias :transfer :send
|
240
|
+
|
241
|
+
end # class Ledger
|
242
|
+
|
243
|
+
end # module V2
|
244
|
+
|
245
|
+
|
246
|
+
|
247
|
+
end # module LedgerLite
|
248
|
+
|
249
|
+
|
250
|
+
# say hello
|
251
|
+
puts LedgerLite.banner if defined?($RUBYLIBS_DEBUG) && $RUBYLIBS_DEBUG
|
data/lib/ledger-lite/version.rb
CHANGED
data/test/helper.rb
CHANGED
@@ -7,12 +7,13 @@ require 'minitest/autorun'
|
|
7
7
|
|
8
8
|
## our own code
|
9
9
|
|
10
|
-
require 'ledger-lite'
|
10
|
+
require 'ledger-lite/base' ## note: use "modular" version without "top-level" Ledger constant
|
11
11
|
|
12
12
|
|
13
13
|
|
14
14
|
## some helper classes for testing
|
15
15
|
|
16
|
+
module V1
|
16
17
|
class Transaction
|
17
18
|
|
18
19
|
attr_reader :from, :to, :amount
|
@@ -36,7 +37,43 @@ class Transaction
|
|
36
37
|
|
37
38
|
end # class Transaction
|
38
39
|
|
39
|
-
Tx
|
40
|
+
Tx = Transaction ## convenience shortcut
|
41
|
+
Ledger = LedgerLite::Ledger
|
42
|
+
end # module V1
|
43
|
+
|
44
|
+
|
45
|
+
|
46
|
+
module V2
|
47
|
+
class Transaction
|
48
|
+
|
49
|
+
attr_reader :from, :to, :qty, :name
|
50
|
+
|
51
|
+
#####
|
52
|
+
# flexible for testing - allows:
|
53
|
+
# Tx.new( 'Alice', 'Bob', 12, 'Tulip Semper Augustus' )
|
54
|
+
# Tx.new( from: 'Alice', to: 'Bob', qty: 12, name: 'Semper Augustus' )
|
55
|
+
|
56
|
+
def initialize( *args, **kwargs )
|
57
|
+
if args.empty? # try keyword args
|
58
|
+
@from = kwargs[:from]
|
59
|
+
@to = kwargs[:to]
|
60
|
+
@qty = kwargs[:qty]
|
61
|
+
@name = kwargs[:name]
|
62
|
+
else # try positional args
|
63
|
+
@from = args[0]
|
64
|
+
@to = args[1]
|
65
|
+
@qty = args[2]
|
66
|
+
@name = args[3]
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
end # class Transaction
|
71
|
+
|
72
|
+
Tx = Transaction ## convenience shortcut
|
73
|
+
Ledger = LedgerLite::V2::Ledger
|
74
|
+
end # module V2
|
75
|
+
|
76
|
+
|
40
77
|
|
41
78
|
|
42
79
|
class Block
|
data/test/test_blocks.rb
CHANGED
data/test/test_transactions.rb
CHANGED
@@ -0,0 +1,109 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
###
|
4
|
+
# to run use
|
5
|
+
# ruby -I ./lib -I ./test test/test_transactions_v2.rb
|
6
|
+
|
7
|
+
|
8
|
+
require 'helper'
|
9
|
+
|
10
|
+
|
11
|
+
class TestTransactionsV2 < MiniTest::Test
|
12
|
+
|
13
|
+
include V2 # includes Ledger, Tx, etc.
|
14
|
+
|
15
|
+
def setup
|
16
|
+
Ledger.configure do |config|
|
17
|
+
## note: for testing use different coinbase than "classic / standard" V1 version
|
18
|
+
config.coinbase = ["Flowers†", "Bloom & Blossom†"]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
|
24
|
+
def test_send
|
25
|
+
|
26
|
+
ledger = Ledger.new
|
27
|
+
|
28
|
+
ledger.send( "Flowers†", "Vincent", 11, "Tulip Admiral van Eijck" )
|
29
|
+
ledger.send( "Vincent", "Anne", 3, "Tulip Admiral van Eijck" )
|
30
|
+
ledger.send( "Anne", "Julia", 2, "Tulip Admiral van Eijck" )
|
31
|
+
ledger.send( "Julia", "Luuk", 1, "Tulip Admiral van Eijck" )
|
32
|
+
|
33
|
+
ledger.send( "Bloom & Blossom†", "Ruben", 11, "Tulip Semper Augustus" )
|
34
|
+
ledger.send( "Vincent", "Max", 3, "Tulip Admiral van Eijck" )
|
35
|
+
ledger.send( "Ruben", "Julia", 2, "Tulip Semper Augustus" )
|
36
|
+
ledger.send( "Anne", "Martijn", 1, "Tulip Admiral van Eijck" )
|
37
|
+
|
38
|
+
pp ledger
|
39
|
+
|
40
|
+
balances = {"Vincent"=>{"Tulip Admiral van Eijck"=>5},
|
41
|
+
"Anne"=>{"Tulip Admiral van Eijck"=>0},
|
42
|
+
"Julia"=>{"Tulip Admiral van Eijck"=>1, "Tulip Semper Augustus"=>2},
|
43
|
+
"Luuk"=>{"Tulip Admiral van Eijck"=>1},
|
44
|
+
"Ruben"=>{"Tulip Semper Augustus"=>9},
|
45
|
+
"Max"=>{"Tulip Admiral van Eijck"=>3},
|
46
|
+
"Martijn"=>{"Tulip Admiral van Eijck"=>1}}
|
47
|
+
|
48
|
+
assert_equal balances, ledger.addr
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
def test_with_tx
|
53
|
+
|
54
|
+
ledger = Ledger.new
|
55
|
+
|
56
|
+
ledger.write( Tx.new( "Flowers†", "Vincent", 11, "Tulip Admiral van Eijck" ))
|
57
|
+
ledger.write( Tx.new( "Vincent", "Anne", 3, "Tulip Admiral van Eijck" ))
|
58
|
+
|
59
|
+
ledger << Tx.new( "Anne", "Julia", 2, "Tulip Admiral van Eijck" )
|
60
|
+
ledger << Tx.new( "Julia", "Luuk", 1, "Tulip Admiral van Eijck" )
|
61
|
+
|
62
|
+
|
63
|
+
ledger.write( Tx.new( "Bloom & Blossom†", "Ruben", 11, "Tulip Semper Augustus" ),
|
64
|
+
Tx.new( "Vincent", "Max", 3, "Tulip Admiral van Eijck" ),
|
65
|
+
Tx.new( "Ruben", "Julia", 2, "Tulip Semper Augustus" ),
|
66
|
+
Tx.new( "Anne", "Martijn", 1, "Tulip Admiral van Eijck" ))
|
67
|
+
|
68
|
+
pp ledger
|
69
|
+
|
70
|
+
balances = {"Vincent"=>{"Tulip Admiral van Eijck"=>5},
|
71
|
+
"Anne"=>{"Tulip Admiral van Eijck"=>0},
|
72
|
+
"Julia"=>{"Tulip Admiral van Eijck"=>1, "Tulip Semper Augustus"=>2},
|
73
|
+
"Luuk"=>{"Tulip Admiral van Eijck"=>1},
|
74
|
+
"Ruben"=>{"Tulip Semper Augustus"=>9},
|
75
|
+
"Max"=>{"Tulip Admiral van Eijck"=>3},
|
76
|
+
"Martijn"=>{"Tulip Admiral van Eijck"=>1}}
|
77
|
+
|
78
|
+
assert_equal balances, ledger.addr
|
79
|
+
end
|
80
|
+
|
81
|
+
|
82
|
+
def test_with_hash
|
83
|
+
|
84
|
+
ledger = Ledger.new
|
85
|
+
|
86
|
+
ledger.write( { from: "Flowers†", to: "Vincent", qty: 11, name: "Tulip Admiral van Eijck" },
|
87
|
+
{ from: "Vincent", to: "Anne", qty: 3, name: "Tulip Admiral van Eijck" },
|
88
|
+
{ from: "Anne", to: "Julia", qty: 2, name: "Tulip Admiral van Eijck" },
|
89
|
+
{ from: "Julia", to: "Luuk", qty: 1, name: "Tulip Admiral van Eijck" })
|
90
|
+
|
91
|
+
ledger.write( { from: "Bloom & Blossom†", to: "Ruben", qty: 11, name: "Tulip Semper Augustus" },
|
92
|
+
{ from: "Vincent", to: "Max", qty: 3, name: "Tulip Admiral van Eijck" },
|
93
|
+
{ from: "Ruben", to: "Julia", qty: 2, name: "Tulip Semper Augustus" },
|
94
|
+
{ from: "Anne", to: "Martijn", qty: 1, name: "Tulip Admiral van Eijck" })
|
95
|
+
|
96
|
+
pp ledger
|
97
|
+
|
98
|
+
balances = {"Vincent"=>{"Tulip Admiral van Eijck"=>5},
|
99
|
+
"Anne"=>{"Tulip Admiral van Eijck"=>0},
|
100
|
+
"Julia"=>{"Tulip Admiral van Eijck"=>1, "Tulip Semper Augustus"=>2},
|
101
|
+
"Luuk"=>{"Tulip Admiral van Eijck"=>1},
|
102
|
+
"Ruben"=>{"Tulip Semper Augustus"=>9},
|
103
|
+
"Max"=>{"Tulip Admiral van Eijck"=>3},
|
104
|
+
"Martijn"=>{"Tulip Admiral van Eijck"=>1}}
|
105
|
+
|
106
|
+
assert_equal balances, ledger.addr
|
107
|
+
end
|
108
|
+
|
109
|
+
end # class TestTransactionsV2
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ledger-lite
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gerald Bauer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-01-
|
11
|
+
date: 2018-01-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rdoc
|
@@ -56,10 +56,12 @@ files:
|
|
56
56
|
- README.md
|
57
57
|
- Rakefile
|
58
58
|
- lib/ledger-lite.rb
|
59
|
+
- lib/ledger-lite/base.rb
|
59
60
|
- lib/ledger-lite/version.rb
|
60
61
|
- test/helper.rb
|
61
62
|
- test/test_blocks.rb
|
62
63
|
- test/test_transactions.rb
|
64
|
+
- test/test_transactions_v2.rb
|
63
65
|
- test/test_version.rb
|
64
66
|
homepage: https://github.com/openblockchains/ledger.lite.rb
|
65
67
|
licenses:
|