rippler 0.0.10 → 0.0.11

Sign up to get free protection for your applications and to get access to all the features.
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