zold 0.6.3 → 0.6.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2005a5319083f1a638f7c4764776cf02c22fec87
4
- data.tar.gz: 9ffb162b8a5c5daa797b0c1402283d49a81f5d26
3
+ metadata.gz: 1a13c84bf909f10c8a8bd34f48c944609b5b5bfe
4
+ data.tar.gz: e713cdd2f5b956c880cf55236d740d923a19aa22
5
5
  SHA512:
6
- metadata.gz: 39f357589c34b08f98d405b8ee8307a8044c5809e51fce67a00e87ce53d713be7179ba2098ee548e4b7b9788aa276e9b40ebe271c4ade47cc7917d859a08079a
7
- data.tar.gz: 18edefa475f83289160649fbfdd07df40e7c494722f5c5352650d3ae1e16d945ea269d430294a9e61e8f6f4d202c1f3efe7c66b4f72b0657dac7a9434e73e2ea
6
+ metadata.gz: 5ae863d2f4fb67e945b6cab6a02db1919ee60c89f9daeb1828c0e2204ae00c18f01cd2dce35b271860ea55d8f87ae26944095c739b85749494ab974396469038
7
+ data.tar.gz: 00ced2cb1e217024213035cc6f6f2d4c79f7d2ca165e0367ea4c51f8d9682b95c656a46a084ab9a89b0cbf87efe7800f8315c56614f222b6e2dcf773860f7810
data/README.md CHANGED
@@ -17,6 +17,10 @@
17
17
  **NOTICE**: It's an experiment and a very early draft! Please, feel free to
18
18
  submit your ideas or pull requests.
19
19
 
20
+ Here is the [White Paper](https://latexonline.cc/compile?git=https%3A%2F%2Fgithub.com%2Fyegor256%2Fzold&target=wp%2Fwp.tex&command=pdflatex&trackId=1520158941887).
21
+
22
+ The license is [MIT](https://github.com/zerocracy/zold/blob/master/LICENSE.txt).
23
+
20
24
  ## How to Use
21
25
 
22
26
  Install Ruby 2.2+, [Rubygems](https://rubygems.org/pages/download), and then run:
@@ -38,139 +42,54 @@ For more options and commands just run:
38
42
  $ zold --help
39
43
  ```
40
44
 
41
- You will need PGP keys in `~/.ssh`. To generate them, if you don't have them
42
- yet, you can run:
45
+ You will need PGP keys in `~/.ssh`. To generate them (if you don't have them yet):
43
46
 
44
47
  ```bash
45
48
  $ ssh-keygen -t rsa -b 4096
46
49
  ```
47
50
 
48
- ### Remote
49
-
50
- Each node maintains a list of visible "remote" nodes.
51
- The gem is shipped together with a hard-coded list of a few of them.
52
-
53
- * `remote update` goes through the list of all remote nodes,
54
- checks their availability, and either removes them from the list or
55
- adds new nodes to the list.
56
-
57
- * `remote add <IP>` adds a new remote node to the list.
58
-
59
- * `remote remove <IP>` removes a remote node.
60
-
61
- * `remote show` prints the entire list of remote nodes.
62
-
63
- The node always tries to make sure the summary of all scores in the
64
- list of remote nodes is right above the MSS, but not more.
65
-
66
- ### Fetch
67
-
68
- The node attempts to pull the wallet from the first remote.
69
- The remote returns the wallet, if it exists. Otherwise, rejects the request
70
- and returns the list of all remotes known to it.
71
-
72
- The node stores the content of the wallet and the score of the remote
73
- to the local storage.
74
- The local storage doesn't keep all remote copies, but only their unique
75
- versions and summary scores for each version.
76
-
77
- Fetching stops when:
78
-
79
- * Total score is above MSS _or_
80
- * There is only one version and the total score is above ½ MSS.
81
-
82
- If not, the node attempts the next remote in the list.
83
-
84
- ### Merge
85
-
86
- The remote copy is accepted "as is" without verifications if:
87
-
88
- * All remote copies are identical _and_
89
- * Their summary score is above the MSS.
90
-
91
- Otherwise, the node goes through the entire list of transactions visible in all
92
- remote copies and merges them one by one into the "head" copy.
93
- The decision is made per each transaction.
94
-
95
- If a transaction exists in the head, it remains there.
96
-
97
- Otherwise, if it's a positive transaction that increases the balance of the head copy,
98
- the signature is validated (in the paying wallet, which is pulled first)
99
- and it goes into the head. The transaction gets a new ID.
100
-
101
- If it's a negative transaction, the decision is made between all copies.
102
- The one with the largest score goes first, if the balance of the wallet
103
- is big enough. Then, the next one in the line and so on. The transactions
104
- that negate the balance are rejected.
105
-
106
- ### Pay
107
-
108
- The node pulls both wallets. Then, say, the user makes a payment
109
- from the wallet `0123456789abcdef` to the wallet `4567456745674567`:
51
+ First, create a wallet (instead of `5f96e731e48ae21f` there will be your
52
+ person wallet number, use it everywhere below):
110
53
 
111
54
  ```bash
112
- zold send 0123456789abcdef 4567456745674567 5
113
- ```
114
-
115
- The content of both files get changed. An outgoing transaction with a negative
116
- amount gets added to the end of the paying wallet `0123456789abcdef`:
117
-
118
- ```text
119
- 500;2017-07-19T22:18:43Z;-83886080;4567456745674567;-;b6SKMPrVjLx...
55
+ $ zold create
56
+ 5f96e731e48ae21f
120
57
  ```
121
58
 
122
- The incoming transaction gets appended to the end of the receiving wallet
123
- `4567456745674567`:
59
+ Then, give its number to your friend, who is going to pay you.
60
+ When the payment is sent, ask him or her for the number of the wallet
61
+ the payment has been sent from and then fetch that wallet
62
+ (let's say it is `5555444433332222`):
124
63
 
125
- ```text
126
- 500;2017-07-19T22:18:43Z;83886080;0123456789abcdef;-
64
+ ```bash
65
+ $ zold fetch 5555444433332222
66
+ 5.00 ZLD added to 5f96e731e48ae21f: To my friend!
127
67
  ```
128
68
 
129
- ### Push
130
-
131
- The node sends a package of a few wallets to the biggest remote available
132
- (with the highest score).
133
- The package must also include a fee to the wallet that belongs to the
134
- remote.
135
-
136
- The remote stores them as remote copies and performs _pull_.
137
-
138
- The remote sends "pull requests" to all available nodes.
139
- They must pull from the node for free, if their scores are lower or equal
140
- to the score of the node.
141
-
142
- ## RESTful API
143
-
144
- The full list of RESTful resources:
69
+ Now, you have the money in your wallet!
145
70
 
146
- * `/` (GET): status page of the node, in JSON
71
+ Next, you can pay your friend back:
147
72
 
148
- * `/remotes` (GET): load all known remotes in JSON
149
-
150
- * `/wallet/<ID>` (GET): fetch wallet in JSON
151
-
152
- * `/wallet/<ID>` (PUT): push wallet
153
-
154
- Each HTTP response contains `Content-type` header.
155
-
156
- ## Files
73
+ ```bash
74
+ $ zold pay 5f96e731e48ae21f 5555444433332222 2.50 'Here is a refund'
75
+ -2.50 ZLD added to 5f96e731e48ae21f: Here is a refund
76
+ ```
157
77
 
78
+ Finally, you have to push your wallet to the network so that your friend
79
+ knows about the payment:
158
80
 
159
- `.zold/remotes` is a comma-separated file with a list of remote nodes with
160
- these columns:
81
+ ```bash
82
+ $ zold push 5f96e731e48ae21f
83
+ ```
161
84
 
162
- * Address or IP;
163
- * TCP port (usually 4096);
164
- * Score (positive integer);
165
- * Time of score update, ISO 8601.
85
+ That's it.
166
86
 
167
- `.zold/copies` is a directory of directories, named after wallet IDs,
168
- each of which contains copies of wallets, named like `1`, `2`, `3`, etc. Also,
169
- each sub-directory contains a comma-separated file `scores` with these columns:
87
+ You also can contribute to Zold by running a node on your server.
88
+ In order to do that just run:
170
89
 
171
- * The name of the copy, e.g. `1`;
172
- * The address of the remote (host name or IP);
173
- * The TCP port number of the remote;
174
- * The score (positive integer);
175
- * The time of fetching, in ISO 8601.
90
+ ```bash
91
+ $ zold node --invoice=5f96e731e48ae21f
92
+ ```
176
93
 
94
+ Grateful users of the system will pay "taxes" to your wallet for processing
95
+ of their transactions.
@@ -3,7 +3,7 @@ set -x
3
3
  set -e
4
4
  shopt -s expand_aliases
5
5
 
6
- alias zold="$1 --ignore-global-config --trace"
6
+ alias zold="$1 --ignore-global-config --trace --ignore-this-stupid-option"
7
7
 
8
8
  port=`python -c 'import socket; s=socket.socket(); s.bind(("", 0)); print(s.getsockname()[1]); s.close()'`
9
9
 
@@ -25,7 +25,7 @@ zold remote clean
25
25
  zold remote add localhost ${port}
26
26
  zold remote show
27
27
 
28
- zold create --public-key=id_rsa.pub 0000000000000000
28
+ zold --public-key=id_rsa.pub create 0000000000000000
29
29
  target=`zold create --public-key=id_rsa.pub`
30
30
  invoice=`zold invoice ${target}`
31
31
  zold pay --private-key=id_rsa 0000000000000000 ${invoice} 14.99 'To save the world!'
data/lib/zold/amount.rb CHANGED
@@ -28,10 +28,15 @@ module Zold
28
28
  # Amount
29
29
  class Amount
30
30
  def initialize(coins: nil, zld: nil)
31
- raise 'You can\'t specify both coints and zld' if !coins.nil? && !zld.nil?
32
- raise "Integer is required, while #{coins.class} provided: #{coins}" unless coins.nil? || coins.is_a?(Integer)
33
- @coins = coins unless coins.nil?
34
- @coins = (zld * 2**24).to_i unless zld.nil?
31
+ if !coins.nil?
32
+ raise "Integer is required, while #{coins.class} provided: #{coins}" unless coins.is_a?(Integer)
33
+ @coins = coins
34
+ elsif !zld.nil?
35
+ raise "Float is required, while #{zld.class} provided: #{zld}" unless zld.is_a?(Float)
36
+ @coins = (zld * 2**24).to_i
37
+ else
38
+ raise 'You can\'t specify both coints and zld'
39
+ end
35
40
  end
36
41
 
37
42
  ZERO = Amount.new(coins: 0)
@@ -0,0 +1,50 @@
1
+ # Copyright (c) 2018 Yegor Bugayenko
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the 'Software'), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all
11
+ # copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ # SOFTWARE.
20
+
21
+ require 'slop'
22
+ require 'json'
23
+ require 'net/http'
24
+ require_relative '../log'
25
+ require_relative '../id'
26
+ require_relative '../http'
27
+
28
+ # Args.
29
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
30
+ # Copyright:: Copyright (c) 2018 Yegor Bugayenko
31
+ # License:: MIT
32
+ module Zold
33
+ # Command line args
34
+ class Args
35
+ def initialize(opts, log)
36
+ @opts = opts
37
+ @log = log
38
+ end
39
+
40
+ def take
41
+ if @opts.help?
42
+ @log.info(@opts.to_s)
43
+ return
44
+ end
45
+ args = @opts.arguments.reject { |a| a.start_with?('-') }
46
+ raise 'Try --help' if args.empty?
47
+ args[1..-1]
48
+ end
49
+ end
50
+ end
@@ -21,6 +21,9 @@
21
21
  require 'uri'
22
22
  require 'json'
23
23
  require 'time'
24
+ require 'slop'
25
+ require 'rainbow'
26
+ require_relative 'args'
24
27
  require_relative '../log'
25
28
  require_relative '../http'
26
29
  require_relative '../score'
@@ -44,12 +47,8 @@ module Zold
44
47
  Available options:"
45
48
  o.bool '--help', 'Print instructions'
46
49
  end
47
- if opts.help?
48
- @log.info(opts.to_s)
49
- return
50
- end
51
- mine = opts.arguments[1..-1]
52
- raise 'At least one wallet ID is required' if mine.empty?
50
+ mine = Args.new(opts, @log).take || return
51
+ mine = @wallets.all if mine.empty?
53
52
  mine.each do |id|
54
53
  clean(Copies.new(File.join(@copies, id)), opts)
55
54
  end
@@ -18,6 +18,9 @@
18
18
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
19
  # SOFTWARE.
20
20
 
21
+ require 'slop'
22
+ require 'rainbow'
23
+ require_relative 'args'
21
24
  require_relative '../wallet'
22
25
  require_relative '../log'
23
26
  require_relative '../id'
@@ -44,11 +47,7 @@ Available options:"
44
47
  default: '~/.ssh/id_rsa.pub'
45
48
  o.bool '--help', 'Print instructions'
46
49
  end
47
- if opts.help?
48
- @log.info(opts.to_s)
49
- return
50
- end
51
- mine = opts.arguments[1..-1]
50
+ mine = Args.new(opts, @log).take || return
52
51
  create(mine.empty? ? Id.new : Id.new(mine[0]), opts)
53
52
  end
54
53
 
@@ -21,6 +21,8 @@
21
21
  require 'tempfile'
22
22
  require 'slop'
23
23
  require 'diffy'
24
+ require 'rainbow'
25
+ require_relative 'args'
24
26
  require_relative '../log'
25
27
  require_relative '../patch'
26
28
  require_relative '../wallet'
@@ -44,11 +46,7 @@ module Zold
44
46
  Available options:"
45
47
  o.bool '--help', 'Print instructions'
46
48
  end
47
- if opts.help?
48
- @log.info(opts.to_s)
49
- return
50
- end
51
- mine = opts.arguments[1..-1]
49
+ mine = Args.new(opts, @log).take || return
52
50
  raise 'At least one wallet ID is required' if mine.empty?
53
51
  stdout = ''
54
52
  mine.each do |id|
@@ -22,6 +22,8 @@ require 'uri'
22
22
  require 'json'
23
23
  require 'time'
24
24
  require 'slop'
25
+ require 'rainbow'
26
+ require_relative 'args'
25
27
  require_relative '../log'
26
28
  require_relative '../http'
27
29
  require_relative '../score'
@@ -52,12 +54,8 @@ Available options:"
52
54
  default: []
53
55
  o.bool '--help', 'Print instructions'
54
56
  end
55
- if opts.help?
56
- @log.info(opts.to_s)
57
- return
58
- end
59
- mine = opts.arguments[1..-1]
60
- raise 'At least one wallet ID is required' if mine.empty?
57
+ mine = Args.new(opts, @log).take || return
58
+ mine = @wallets.all if mine.empty?
61
59
  mine.each do |id|
62
60
  fetch(id, Copies.new(File.join(@copies, id)), opts)
63
61
  end
@@ -19,6 +19,7 @@
19
19
  # SOFTWARE.
20
20
 
21
21
  require 'slop'
22
+ require_relative 'args'
22
23
  require_relative '../log'
23
24
  require_relative '../prefixes'
24
25
 
@@ -45,11 +46,7 @@ Available options:"
45
46
  default: 8
46
47
  o.bool '--help', 'Print instructions'
47
48
  end
48
- if opts.help?
49
- @log.info(opts.to_s)
50
- return
51
- end
52
- mine = opts.arguments[1..-1]
49
+ mine = Args.new(opts, @log).take || return
53
50
  raise 'Receiver wallet ID is required' if mine[0].nil?
54
51
  wallet = @wallets.find(Zold::Id.new(mine[0]))
55
52
  raise 'Wallet doesn\'t exist, do \'fetch\' first' unless wallet.exists?
@@ -19,6 +19,8 @@
19
19
  # SOFTWARE.
20
20
 
21
21
  require 'slop'
22
+ require 'rainbow'
23
+ require_relative 'args'
22
24
  require_relative '../log'
23
25
  require_relative '../id'
24
26
  require_relative '../wallet'
@@ -44,12 +46,8 @@ module Zold
44
46
  Available options:"
45
47
  o.bool '--help', 'Print instructions'
46
48
  end
47
- if opts.help?
48
- @log.info(opts.to_s)
49
- return
50
- end
51
- mine = opts.arguments[1..-1]
52
- raise 'At least one wallet ID is required' if mine.empty?
49
+ mine = Args.new(opts, @log).take || return
50
+ mine = @wallets.all if mine.empty?
53
51
  modified = []
54
52
  mine.each do |id|
55
53
  wallet = @wallets.find(Id.new(id))
@@ -41,7 +41,7 @@ module Zold
41
41
  opts = Slop.parse(args, help: true, suppress_errors: true) do |o|
42
42
  o.banner = 'Usage: zold node [options]'
43
43
  o.string '--invoice',
44
- 'The invoice you want to collect money to'
44
+ 'The invoice you want to collect money to or the wallet ID'
45
45
  o.integer '--port',
46
46
  "TCP port to open for the Net (default: #{Remotes::PORT})",
47
47
  default: Remotes::PORT
@@ -94,9 +94,15 @@ module Zold
94
94
  :entrance, Entrance.new(wallets, remotes, copies, address, log: @log)
95
95
  )
96
96
  Zold::Front.set(:port, opts['bind-port'])
97
- farm = Farm.new(opts[:invoice], log: @log)
97
+ invoice = opts[:invoice]
98
+ unless invoice.include?('@')
99
+ require_relative 'invoice'
100
+ invoice = Invoice.new(wallets: @wallets, log: @log).run(['invoice', invoice])
101
+ end
102
+ farm = Farm.new(invoice, log: @log)
98
103
  farm.start(
99
- opts[:host], opts[:port],
104
+ opts[:host],
105
+ opts[:port],
100
106
  threads: opts[:threads], strength: opts[:strength]
101
107
  )
102
108
  Zold::Front.set(:farm, farm)
@@ -19,6 +19,8 @@
19
19
  # SOFTWARE.
20
20
 
21
21
  require 'slop'
22
+ require 'rainbow'
23
+ require_relative 'args'
22
24
  require_relative '../log'
23
25
 
24
26
  # PAY command.
@@ -35,10 +37,10 @@ module Zold
35
37
 
36
38
  def run(args = [])
37
39
  opts = Slop.parse(args, help: true, suppress_errors: true) do |o|
38
- o.banner = "Usage: zold pay wallet invoice amount [details] [options]
40
+ o.banner = "Usage: zold pay wallet target amount [details] [options]
39
41
  Where:
40
42
  'wallet' is the sender's wallet ID
41
- 'invoice' is the beneficiary's invoice number, generated by 'zold invoice'
43
+ 'target' is the beneficiary (either wallet ID or invoice number)'
42
44
  'amount' is the amount to pay, in ZLD, for example '14.95'
43
45
  'details' is the optional text to attach to the payment
44
46
  Available options:"
@@ -51,16 +53,16 @@ Available options:"
51
53
  default: false
52
54
  o.bool '--help', 'Print instructions'
53
55
  end
54
- if opts.help?
55
- @log.info(opts.to_s)
56
- return
57
- end
58
- mine = opts.arguments[1..-1]
56
+ mine = Args.new(opts, @log).take || return
59
57
  raise 'Payer wallet ID is required as the first argument' if mine[0].nil?
60
58
  from = @wallets.find(Zold::Id.new(mine[0]))
61
59
  raise 'Wallet doesn\'t exist, do \'fetch\' first' unless from.exists?
62
- raise 'Recepient\'s invoice is required as the second argument' if mine[1].nil?
60
+ raise 'Recepient\'s invoice or wallet ID is required as the second argument' if mine[1].nil?
63
61
  invoice = mine[1]
62
+ unless invoice.include?('@')
63
+ require_relative 'invoice'
64
+ invoice = Invoice.new(wallets: @wallets, log: @log).run(['invoice', invoice])
65
+ end
64
66
  raise 'Amount is required (in ZLD) as the third argument' if mine[2].nil?
65
67
  amount = Zold::Amount.new(zld: mine[2].to_f)
66
68
  details = mine[3] ? mine[3] : '-'
@@ -18,6 +18,9 @@
18
18
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
19
  # SOFTWARE.
20
20
 
21
+ require 'slop'
22
+ require 'rainbow'
23
+ require_relative 'args'
21
24
  require_relative '../log'
22
25
  require_relative '../wallet'
23
26
  require_relative '../wallets'
@@ -42,12 +45,8 @@ module Zold
42
45
  Available options:"
43
46
  o.bool '--help', 'Print instructions'
44
47
  end
45
- if opts.help?
46
- @log.info(opts.to_s)
47
- return
48
- end
49
- mine = opts.arguments[1..-1]
50
- raise 'At least one wallet ID is required' if mine.empty?
48
+ mine = Args.new(opts, @log).take || return
49
+ mine = @wallets.all if mine.empty?
51
50
  modified = []
52
51
  mine.each do |id|
53
52
  modified += propagate(@wallets.find(id), opts)
@@ -18,9 +18,11 @@
18
18
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
19
  # SOFTWARE.
20
20
 
21
+ require 'rainbow'
21
22
  require 'slop'
22
23
  require 'json'
23
24
  require 'net/http'
25
+ require_relative 'args'
24
26
  require_relative '../log'
25
27
  require_relative '../id'
26
28
  require_relative '../http'
@@ -44,12 +46,8 @@ module Zold
44
46
  Available options:"
45
47
  o.bool '--help', 'Print instructions'
46
48
  end
47
- if opts.help?
48
- @log.info(opts.to_s)
49
- return
50
- end
51
- mine = opts.arguments[1..-1]
52
- raise 'At least one wallet ID is required' if mine.empty?
49
+ mine = Args.new(opts, @log).take || return
50
+ mine = @wallets.all if mine.empty?
53
51
  mine.each do |id|
54
52
  push(@wallets.find(Id.new(id)), opts)
55
53
  end
@@ -23,6 +23,7 @@ require 'rainbow'
23
23
  require 'net/http'
24
24
  require 'json'
25
25
  require 'time'
26
+ require_relative 'args'
26
27
  require_relative '../log'
27
28
  require_relative '../http'
28
29
  require_relative '../remotes'
@@ -62,11 +63,7 @@ Available options:"
62
63
  default: false
63
64
  o.bool '--help', 'Print instructions'
64
65
  end
65
- if opts.help?
66
- @log.info(opts.to_s)
67
- return
68
- end
69
- mine = opts.arguments[1..-1]
66
+ mine = Args.new(opts, @log).take || return
70
67
  command = mine[0]
71
68
  case command
72
69
  when 'show'
@@ -19,6 +19,8 @@
19
19
  # SOFTWARE.
20
20
 
21
21
  require 'slop'
22
+ require 'rainbow'
23
+ require_relative 'args'
22
24
  require_relative '../log'
23
25
  require_relative '../id'
24
26
  require_relative '../amount'
@@ -41,11 +43,7 @@ module Zold
41
43
  Available options:"
42
44
  o.bool '--help', 'Print instructions'
43
45
  end
44
- if opts.help?
45
- @log.info(opts.to_s)
46
- return
47
- end
48
- mine = opts.arguments[1..-1]
46
+ mine = Args.new(opts, @log).take || return
49
47
  if mine.empty?
50
48
  require_relative 'list'
51
49
  List.new(wallets: @wallets, log: @log).run(args)
@@ -20,6 +20,8 @@
20
20
 
21
21
  require 'slop'
22
22
  require 'json'
23
+ require 'rainbow'
24
+ require_relative 'args'
23
25
  require_relative 'pay'
24
26
  require_relative '../log'
25
27
  require_relative '../score'
@@ -57,7 +59,7 @@ Available options:"
57
59
  default: '~/.ssh/id_rsa'
58
60
  o.bool '--help', 'Print instructions'
59
61
  end
60
- mine = opts.arguments[1..-1]
62
+ mine = Args.new(opts, @log).take || return
61
63
  command = mine[0]
62
64
  case command
63
65
  when 'show'
@@ -0,0 +1,51 @@
1
+ # Copyright (c) 2018 Yegor Bugayenko
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the 'Software'), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all
11
+ # copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ # SOFTWARE.
20
+
21
+ # Hex num.
22
+ #
23
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
24
+ # Copyright:: Copyright (c) 2018 Yegor Bugayenko
25
+ # License:: MIT
26
+ module Zold
27
+ # A hex num
28
+ class Hexnum
29
+ def initialize(num, length)
30
+ @num = num
31
+ @length = length
32
+ end
33
+
34
+ def to_i
35
+ @num
36
+ end
37
+
38
+ def to_s
39
+ format("%0#{@length}x", @num).gsub(/^\.{2}/, 'ff')
40
+ end
41
+
42
+ def self.parse(txt)
43
+ n = Integer("0x#{txt}", 16)
44
+ if txt.start_with?('f')
45
+ max = Integer("0x#{'f' * txt.length}", 16)
46
+ n = n - max - 1
47
+ end
48
+ Hexnum.new(n, txt.length)
49
+ end
50
+ end
51
+ end