ledger-lite 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|

|
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:
|