rippler 0.0.10 → 0.0.11

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.
data/README.md CHANGED
@@ -32,9 +32,13 @@ Ripple server replies are returned as JSON and printed to stdout. If you want to
32
32
 
33
33
  ## Usage: additional commands
34
34
 
35
- Rippler also provides additional commands that print out human-readable output:
35
+ Rippler also provides additional commands that print out human-readable output. You can use option -t for text (rather than structural) output.
36
36
 
37
- $ rippler history account:molecular
37
+ $ rippler -t order_book buy:BTC/bitstamp sell:XRP
38
+
39
+ This one prints current order book for any currency pair.
40
+
41
+ $ rippler -t history account:molecular
38
42
 
39
43
  This one prints any account history in a human-readable format.
40
44
 
@@ -46,6 +50,10 @@ This one prints out all outstanding balances (debit/credit IOUs and XRP) for a s
46
50
 
47
51
  This one monitors Ripple transactions in real-time similar to #ripple-watch, but more interesting since it shows known account names instead of opaque addresses. Ctrl-C to stop it.
48
52
 
53
+ $ rippler path_find source_account:RippleUnion destination_account:singpolyma 'destination_amount:{currency:CAD, value:1}'
54
+
55
+ This one finds possible paths for amounts of money between two addresses, and prints out what the source would have to send to get that amount to the destination.
56
+
49
57
  ## Contacts database
50
58
 
51
59
  Contacts database is in lib/rippler/contacts.rb, mostly auto-scraped from Bitcointalk. It may be a bit inaccurate, you can modify/extend it as you see fit.
@@ -6,4 +6,16 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
6
6
  require 'rippler'
7
7
  require "pp"
8
8
 
9
- pp Rippler.process ARGV
9
+ if ARGV[0] == '-t'
10
+ ARGV.shift
11
+
12
+ Rippler.process(ARGV).each do |v|
13
+ if v.is_a?(String)
14
+ puts v
15
+ else
16
+ pp v
17
+ end
18
+ end
19
+ else
20
+ pp Rippler.process ARGV
21
+ end
@@ -11,6 +11,7 @@ require 'rippler/account'
11
11
  require 'rippler/ledger'
12
12
  require 'rippler/transaction'
13
13
  require 'rippler/line'
14
+ require 'rippler/offer'
14
15
 
15
16
  module Rippler
16
17
  extend Rippler::Utils
@@ -18,16 +19,23 @@ module Rippler
18
19
  RIPPLE_URI = 'wss://s1.ripple.com:51233'
19
20
  DEFAULT_ACCT = Rippler::Contacts["molecular"]
20
21
 
22
+ def self.parse_params command_line
23
+ params = command_line.map {|p| p.split(':',2)}.flatten. # get json pairs
24
+ map {|p| p =~ /\[.*\]/ ? p.gsub(/\[|\]/,'').split(',') : p}. # get arrays
25
+ map {|p| p =~ /\{(.*)\}/ ? self.parse_params($1.split(/\s*,\s*/)) : p} # get objects
26
+ Hash[*params]
27
+ end
28
+
21
29
  # Turn command line arguments into command json
22
30
  def self.process args
23
31
  command_line = args.empty? ? ['account_info'] : args.dup
24
32
 
25
33
  command = command_line.shift
26
- params = command_line.map {|p| p.split(':')}.flatten. # get json pairs
27
- map {|p| p =~ /\[.*\]/ ? p.gsub(/\[|\]/,'').split(',') : p} # get arrays
28
- params = Hash[*params]
34
+ params = self.parse_params command_line
29
35
 
30
36
  params['account'] = Account(params['account']).address if params['account']
37
+ params['destination_account'] = Account(params['destination_account']).address if params['destination_account']
38
+ params['source_account'] = Account(params['source_account']).address if params['source_account']
31
39
 
32
40
  # p command, params
33
41
 
@@ -86,17 +94,12 @@ module Rippler
86
94
 
87
95
  ### These API commands need some pre/post-process wrappers
88
96
 
89
- # book_offers needs to convert "taker_gets" & "taker_pays" params
90
- # from "CUR/issuer" to { "currency": currency, "issuer" : address },
97
+ # book_offers should accept "taker_gets" & "taker_pays" params
98
+ # in both "CUR/issuer" and {"currency":currency, "issuer":address} formats
91
99
  def self.book_offers params
92
- taker_gets = Money("0/#{params['taker_gets']}")
93
- taker_pays = Money("0/#{params['taker_pays']}")
94
-
95
- reply = request( params.merge('command' => "book_offers",
96
- 'taker_gets' => taker_gets.to_hash,
97
- 'taker_pays' => taker_pays.to_hash))
98
-
99
- # lines = reply["result"]["lines"]
100
+ request( params.merge('command' => "book_offers",
101
+ 'taker_gets' => Money(params['taker_gets']).to_hash,
102
+ 'taker_pays' => Money(params['taker_pays']).to_hash))
100
103
  end
101
104
 
102
105
 
@@ -108,6 +111,22 @@ module Rippler
108
111
 
109
112
  ### These are user-defined methods that post-process Ripple replies
110
113
 
114
+ # Subscibe to event streams, print events out nicely formatted
115
+ def self.order_book params
116
+
117
+ buy = params['buy']
118
+ sell = params['sell']
119
+ reply = book_offers('taker_gets' => buy,'taker_pays' => sell)
120
+
121
+ asks = reply['result']['offers'].map {|o| Offer.new(o)}
122
+
123
+ reply = book_offers('taker_gets' => sell,'taker_pays' => buy)
124
+
125
+ bids = reply['result']['offers'].map {|o| Offer.new(o)}
126
+
127
+ (asks.reverse + bids.unshift("-"*40) ).map(&:to_s)
128
+ end
129
+
111
130
  # Subscibe to event streams, print events out nicely formatted
112
131
  def self.monitor params
113
132
  subscribe(params) do |message|
@@ -155,8 +174,27 @@ module Rippler
155
174
  'sort_asc' => 1
156
175
  }.merge(params) ) #(optional)
157
176
  txs = reply["result"]["transactions"]
158
- txs.map {|t| Transaction.new(t)}.map(&:to_s)
177
+ txs.map {|t| Transaction.new(t)}.map(&:to_s).reverse
159
178
  .push("Total transactions: #{txs.size}")
179
+ end
160
180
 
181
+ def self.path_find params
182
+ params.merge!('command' => 'ripple_path_find')
183
+ if params['destination_amount'] && ! params['destination_amount']['issuer']
184
+ params['destination_amount']['issuer'] = params['destination_account']
185
+ end
186
+ reply = request(params)
187
+ reply['result']['alternatives'].map {|alt|
188
+ if alt['source_amount'].is_a?(String)
189
+ # XRP as per https://ripple.com/wiki/JSON_API#XRP
190
+ if alt['source_amount'] =~ /\./
191
+ alt['source_amount'].to_f
192
+ else
193
+ alt['source_amount'].to_i.to_f / 1000000
194
+ end
195
+ else
196
+ "#{alt['source_amount']['value']}/#{alt['source_amount']['currency']}/#{alt['source_amount']['issuer']}"
197
+ end
198
+ }
161
199
  end
162
200
  end
@@ -13,7 +13,6 @@ module Rippler
13
13
  X.FortKnox.9 rp7gaQch2fiNQHDPrnPk9pG65e9cnv7g6X
14
14
  X.FortKnox.a rstKSeB2Qx7zrwSkyc7X9Xm5nYTJqtL3iM
15
15
  X.FortKnox.b rJYMACXJd1eejwzZA53VncYmiK2kZSBxyD
16
- X.FortKnox.c r9ycgvDgXjeiaYmoz4F8sKBNXgHHx1wVFM
17
16
  X.Distributor.1 r8TR1AeB1RDQFabM6i8UoFsRF5basqoHJ
18
17
  X.Veirou rhq5LEZSWHWY6H3raiC2KGe8TVeirou4BS
19
18
  X.Wow rHD7Bs8Zk1oQeUhLjPrsFStFcRE2NWoWpe
@@ -43,7 +42,6 @@ module Rippler
43
42
  X.16 rUGNvasUuxLiPL5RXvfZXW8HjBtSHZgqgz
44
43
  X.17 rPyuHFYDwYMGJ5xhMbzfYeikx7ARV3ExvF
45
44
  X.18 r4MZrGMPEHfxGNQHR92BJo5hU9BiqMsTej
46
- X.19 r3ADD8kXSUKHd6zTCKfnKT3zV9EZHjzp1S
47
45
  X.20 rnW7DHtmZGJk4uhGTSU2BW3iPCPWb2xegg
48
46
  X.21 rUrdFHbrEKWNQQ444zcTLrThjcnHCw2FPu
49
47
  X.22 r49nVgaYSDuU7GEQh4mF1nyjsXSVRcUHsr
@@ -82,7 +80,6 @@ module Rippler
82
80
  X.56 rDZ8QghKF4C11pmbVAkqumPTehiF8mfHt3
83
81
  X.57 rDGd76GCnZYGhjiAngV3xrPV4Qkfx79qqp
84
82
  X.58 r9Y4Mdhs339CxpCFxgdBVRcuM5i4rMRbu
85
- X.59 rPcu8U9dSsK6nHtqgpeSvjuFTmNGq3arPh
86
83
 
87
84
  ADDRESS_ONE rrrrrrrrrrrrrrrrrrrrBZbvji
88
85
  OpenCoin rJR7gjNe3DpJ7kpB4CHBxjDKfwVMpTKPpj
@@ -95,6 +92,8 @@ module Rippler
95
92
  bitstamp rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B
96
93
  bitstamp.hotwallet rrpNnNLKrartuEqfJGpqyDwPj1AFPg9vn1
97
94
  bitstamp.NejcKodric rphasxS8Q5p5TLTpScQCBhh5HfJfPbM2M8
95
+ bitstamp.wholesale r9ycgvDgXjeiaYmoz4F8sKBNXgHHx1wVFM
96
+ RippleUnion r3ADD8kXSUKHd6zTCKfnKT3zV9EZHjzp1S
98
97
 
99
98
  TTBit rGwUWgN5BEg3QGNY3RX2HfYowjUTZdid3E
100
99
  BankOfZed ra88Lr8fyo9cUTuyjVFMTrvTSBU93erjyh
@@ -507,6 +506,7 @@ module Rippler
507
506
  DrG.1 rJEZjBv27ZHCPAoDtTBJb9r82VnUdkRd77
508
507
  DrG.2 rQNFxWVBxnjeF5gaFKwoj5nr3WansCtR19
509
508
  UnitClick rLKojeESeKi9mdBuPLkiQhCxs4wh8iKy2W
509
+ UnitClick.1 rJrJuCmNuZ9shGgZvAhM6Xsv8PdghQTokc
510
510
  saddambitcoin rMSEYpzcRtkiA5kkxYEWZtvLr8u3jnn385
511
511
  helloworld111 rwGAnUvzT5yrDz6dXxm6MWVhpV9abm39W3
512
512
  dykast rQfwn3GVHVEfTpjqU2Y3BoMGAGHrw43XnT
@@ -577,10 +577,25 @@ module Rippler
577
577
  v7znay rGNNQZo3KXaeC8i33FmbddUk43iRELPkKk
578
578
  wannabitcoin rLubad3VQxaeT6qk43jEGPJX7ADkMBkwTM
579
579
  webr3 rnW7DHtmZGJk4uhGTSU2BW3iPCPWb2xegg
580
+ webr3.1 rPcu8U9dSsK6nHtqgpeSvjuFTmNGq3arPh
580
581
  WikileaksDude rE7QqUJQWFGu7JZU6E9byysF6Qu5UQjQkP
582
+ WikileaksDude.1 r9nzyxxnnmf2Qg8HjKYdwWSN6YJXJtMpQ
581
583
  LoweryCBS rBiYVjzHRQxMDMdC5ynKsejqoy1qJMQ8zR
582
584
  ScratAcorns rEwNm7FWSy4whunsNRCebPbDktjeoGhdbS
583
585
  Dreamweaver rnt5BahXixR8PeBwsYXynN6Ew8MCn87GUn
586
+ nomis rUr7cFcUasrhZ234RZKfKHmQNzM5FPQEHi
587
+ alberthrocks rUaEuoMVzmZNxx3etp8DhEWGD6UeJaoiq4
588
+ Xenius rfaLKpYas7BLsjnbm2dpPDQRKaNbBLGTgs
589
+ liamwli rEvjdo5evfU65J9evHZyHFsEVs4t4Mbfqr
590
+ fghj rHpaEMuN84JR6VT2umSbtSrHJ8JGWyza8f
591
+ MasonIII rsieHiunKBtHr1JXZZvU98erDkG8MD7R2r
592
+ macbook-air rp3dmTa3i1aFY1JwsMKc1WVKJtdj3s6cHc
593
+ Dabs rsAbwKtKaePtmVZhS5H2eT5K4u9UWR7mX5
594
+ Liquid rsuvuGXuWdoRUJXiLQ7z9kyM4tjuXgrZJs
595
+ Projects rsjPEDMnjdcKRJhCDm61YbXPNgJN6tjoPc
596
+ Snowpea rsCmWSczxBpRri57jcMw8duYJETaspFRd9
597
+ stick rQy7ajMPs2WMmMgLTtZtadLxTEvsXDhRF
598
+ darkmule r4VfSDJZNX53TRd6nExAmzsPdX7jbRSHf1
584
599
  ]]
585
600
 
586
601
  Addresses = Contacts.invert
@@ -18,13 +18,18 @@ module Rippler
18
18
  @issuer = data['issuer']
19
19
  when String
20
20
  @value, @currency, @issuer = *data.split('/')
21
- if @currency
22
- @value = @value.to_f
21
+
22
+ if @value.to_f == 0 # No value, must be generic currency: XRP or USD/bitstamp
23
+ @currency, @issuer = @value, @currency
23
24
  else
24
- @value = @value.to_i/1000000.0
25
- @currency = "XRP"
25
+ if @currency
26
+ @value = @value.to_f
27
+ else
28
+ @value = @value.to_i/1000000.0
29
+ @currency = "XRP"
30
+ end
26
31
  end
27
- when Int
32
+ when Integer
28
33
  @value = data.to_i/1000000.0
29
34
  @currency = "XRP"
30
35
  end
@@ -44,8 +49,8 @@ module Rippler
44
49
  [self, cross]
45
50
  end
46
51
  r = first.value.to_f/second.value.to_f
47
- r = r.to_i == r ? r.to_i : r
48
- "#{r}#{first.currency}/#{second.currency}"
52
+ r = r.to_i == r ? r.to_i : r.round(2)
53
+ "#{r} #{first.currency}/#{second.currency}"
49
54
  end
50
55
 
51
56
  # Allows methods such as xrp? usd? or btc?
@@ -0,0 +1,63 @@
1
+ module Rippler
2
+ class Offer
3
+ include Rippler::Utils
4
+
5
+ # attr_accessor :address, :balance, :flags
6
+
7
+ # Hash:
8
+ # {"Account"=>"rngJ9Co6MPZxJcyepRv2hMPV1HqaeGCdVU",
9
+ # "BookDirectory"=> "4627DFFCFF8B5A265EDBD8AE8C14A52325DBFEDAF4F5C32E5E03DACD3F94D000",
10
+ # "BookNode"=>"0000000000000000",
11
+ # "Flags"=>0,
12
+ # "LedgerEntryType"=>"Offer",
13
+ # "OwnerNode"=>"0000000000000000",
14
+ # "PreviousTxnID"=> "704A6FCC2DD0AEE9B5F420C3641FB86FFE73F4D233E4B9F6A10E5DE79F7DAACF",
15
+ # "PreviousTxnLgrSeq"=>432517,
16
+ # "Sequence"=>191,
17
+ # "TakerGets"=>
18
+ # {"currency"=>"USD", "issuer"=>"rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B", "value"=>"150"},
19
+ # "TakerPays"=>"449850000000",
20
+ # "index"=> "D34C841609A12DAF9DF1B59CA7CB930091A1A16C4A400D8AFDF73311CBB2A2C5",
21
+ # "taker_gets_funded"=>
22
+ # {"currency"=>"USD", "issuer"=>"rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B", "value"=>"51.73532238374231"},
23
+ # "taker_pays_funded"=>"155154231828"},
24
+ def initialize data
25
+ @data = data
26
+ @take
27
+ case data
28
+ when String
29
+ @address = Rippler::Contacts[data] || data
30
+ @name = Rippler::Addresses[@address]
31
+ when Hash
32
+ @address = data["Account"]
33
+ @name = Rippler::Addresses[@address]
34
+ @balance = Money(data["Balance"])
35
+ @flags = data["Flags"]
36
+ end
37
+ end
38
+
39
+ def gets
40
+ @get ||= Money(@data['TakerGets'])
41
+ end
42
+
43
+ def pays
44
+ @pay = Money(@data['TakerPays'])
45
+ end
46
+
47
+ def account
48
+ @account ||= Account(@data['Account'])
49
+ end
50
+
51
+ def funded
52
+ if @data['taker_gets_funded'] || @data['taker_pays_funded']
53
+ funds = Money(@data['taker_gets_funded'])
54
+ " (#{(funds.value/gets.value*100).round(2)}% funded)"
55
+ end
56
+ end
57
+
58
+ def to_s
59
+ "OFR at #{gets.rate(pays)}, #{gets} for #{pays}" +
60
+ "#{funded} by #{account} ##{@data['Sequence']}"
61
+ end
62
+ end
63
+ end
@@ -28,10 +28,7 @@ module Rippler
28
28
  when "OfferCancel"
29
29
  "CAN #{Account(tx['Account'])} ##{tx['Sequence']}"
30
30
  when "OfferCreate"
31
- get = Money(tx['TakerGets'])
32
- pay = Money(tx['TakerPays'])
33
- "OFR #{Account(tx['Account'])} ##{tx['Sequence']} offers " +
34
- "#{get} for #{pay} (#{get.rate(pay)})"
31
+ Offer(tx).to_s
35
32
  when "TrustSet"
36
33
  "TRS #{Money(tx['LimitAmount'])} #{Account(tx['Account'])}"
37
34
  else
@@ -15,5 +15,9 @@ module Rippler
15
15
  def Account(data)
16
16
  Rippler::Account.new(data)
17
17
  end
18
+
19
+ def Offer(data)
20
+ Rippler::Offer.new(data)
21
+ end
18
22
  end
19
23
  end
@@ -1,3 +1,3 @@
1
1
  module Rippler
2
- VERSION = "0.0.10"
2
+ VERSION = "0.0.11"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rippler
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.10
4
+ version: 0.0.11
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-03-26 00:00:00.000000000 Z
12
+ date: 2013-03-31 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: faye-websocket
@@ -48,6 +48,7 @@ files:
48
48
  - lib/rippler/ledger.rb
49
49
  - lib/rippler/line.rb
50
50
  - lib/rippler/money.rb
51
+ - lib/rippler/offer.rb
51
52
  - lib/rippler/transaction.rb
52
53
  - lib/rippler/utils.rb
53
54
  - lib/rippler/version.rb