xrbp 0.0.1

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.
Files changed (53) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +22 -0
  3. data/README.md +7 -0
  4. data/examples/autoconnect_timeout.rb +20 -0
  5. data/examples/cmd.rb +13 -0
  6. data/examples/ledger.rb +15 -0
  7. data/examples/ledger_multi_subscribe.rb +20 -0
  8. data/examples/ledger_subscribe.rb +18 -0
  9. data/examples/multi.rb +10 -0
  10. data/examples/paginate.rb +13 -0
  11. data/examples/prioritized.rb +13 -0
  12. data/examples/round_robin.rb +11 -0
  13. data/examples/websocket.rb +20 -0
  14. data/lib/xrbp/model/account.rb +27 -0
  15. data/lib/xrbp/model/base.rb +31 -0
  16. data/lib/xrbp/model/ledger.rb +24 -0
  17. data/lib/xrbp/model.rb +3 -0
  18. data/lib/xrbp/network/nodes.rb +8 -0
  19. data/lib/xrbp/network.rb +6 -0
  20. data/lib/xrbp/version.rb +3 -0
  21. data/lib/xrbp/websocket/client.rb +127 -0
  22. data/lib/xrbp/websocket/cmds/account_info.rb +20 -0
  23. data/lib/xrbp/websocket/cmds/account_lines.rb +33 -0
  24. data/lib/xrbp/websocket/cmds/account_objects.rb +33 -0
  25. data/lib/xrbp/websocket/cmds/account_offers.rb +33 -0
  26. data/lib/xrbp/websocket/cmds/account_tx.rb +20 -0
  27. data/lib/xrbp/websocket/cmds/book_offers.rb +38 -0
  28. data/lib/xrbp/websocket/cmds/ledger.rb +25 -0
  29. data/lib/xrbp/websocket/cmds/ledger_entry.rb +16 -0
  30. data/lib/xrbp/websocket/cmds/paginated.rb +43 -0
  31. data/lib/xrbp/websocket/cmds/server_info.rb +11 -0
  32. data/lib/xrbp/websocket/cmds/subscribe.rb +18 -0
  33. data/lib/xrbp/websocket/cmds.rb +12 -0
  34. data/lib/xrbp/websocket/command.rb +19 -0
  35. data/lib/xrbp/websocket/connection.rb +169 -0
  36. data/lib/xrbp/websocket/has_plugin.rb +30 -0
  37. data/lib/xrbp/websocket/message.rb +41 -0
  38. data/lib/xrbp/websocket/multi/fallback.rb +18 -0
  39. data/lib/xrbp/websocket/multi/multi_connection.rb +55 -0
  40. data/lib/xrbp/websocket/multi/parallel.rb +28 -0
  41. data/lib/xrbp/websocket/multi/prioritized.rb +15 -0
  42. data/lib/xrbp/websocket/multi/round_robin.rb +19 -0
  43. data/lib/xrbp/websocket/plugins/autoconnect.rb +42 -0
  44. data/lib/xrbp/websocket/plugins/command_dispatcher.rb +39 -0
  45. data/lib/xrbp/websocket/plugins/command_paginator.rb +45 -0
  46. data/lib/xrbp/websocket/plugins/connection_timeout.rb +54 -0
  47. data/lib/xrbp/websocket/plugins/message_dispatcher.rb +141 -0
  48. data/lib/xrbp/websocket/plugins/result_parser.rb +31 -0
  49. data/lib/xrbp/websocket/plugins.rb +18 -0
  50. data/lib/xrbp/websocket/socket.rb +109 -0
  51. data/lib/xrbp/websocket.rb +15 -0
  52. data/lib/xrbp.rb +5 -0
  53. metadata +123 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: d140a426f073971891c8e8e81f5313112c661703cebaee32719f6b04d6ca86b0
4
+ data.tar.gz: 394f8602052b068b2816ddfa4e06621e7537311b26a9d8248c8eaeb44514e510
5
+ SHA512:
6
+ metadata.gz: b47922beac1ce4613e1bc4b8953bcdf9368d9fdecdef26b6c489f08ad00db2ce2be9780fa9e3fdcdf3f9b31f5912dd4c54c352e8833c002cef6e5c0c30edbafd
7
+ data.tar.gz: '0833467cf31a91d158f78b9b480faaddb4447fc7bd4eeb693b21e93ac91ad9e7fdd7ede68e432d7b4755da81ac6fd46f08abaf97e27e27536eee22a34b0af503'
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2019 Dev Null Productions <devnullproductions@gmail.com>
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,7 @@
1
+ XRBP - Ruby XRP Library
2
+ Copyright (C) 2019 Dev Null Productions
3
+ MIT License
4
+
5
+ ---
6
+
7
+ XRPB is a rubygem which facilitates reading and writing data to/from the XRP ledger.
@@ -0,0 +1,20 @@
1
+ $: << File.expand_path('../../lib', __FILE__)
2
+ require 'xrbp'
3
+
4
+ ws = XRBP::WebSocket::Connection.new "wss://s1.ripple.com:443"
5
+
6
+ ws.on :open do
7
+ puts "Opened"
8
+ end
9
+
10
+ ws.on :close do
11
+ puts "Closed"
12
+ end
13
+
14
+ ws.on :error do |e|
15
+ puts "Err #{e}"
16
+ end
17
+
18
+ ws.add_plugin :autoconnect, :connection_timeout
19
+ ws.connection_timeout = 3
20
+ sleep(60)
data/examples/cmd.rb ADDED
@@ -0,0 +1,13 @@
1
+ $: << File.expand_path('../../lib', __FILE__)
2
+ require 'xrbp'
3
+
4
+ ws = XRBP::WebSocket::Connection.new "wss://s1.ripple.com:443"
5
+
6
+ ws.connect
7
+ ws.add_plugin :command_dispatcher
8
+ ws.cmd(XRBP::WebSocket::Cmds::ServerInfo.new) do |r|
9
+ puts r
10
+ ws.close!
11
+ end
12
+
13
+ ws.wait_for_close
@@ -0,0 +1,15 @@
1
+ $: << File.expand_path('../../lib', __FILE__)
2
+ require 'xrbp'
3
+
4
+ ws = XRBP::WebSocket::Connection.new "wss://s1.ripple.com:443"
5
+ ws.add_plugin :command_dispatcher
6
+ ws.connect
7
+
8
+ puts XRBP::Model::Ledger.new.sync(:connection => ws)
9
+
10
+ XRBP::Model::Ledger.new.sync(:connection => ws) do |l|
11
+ puts l
12
+ ws.close!
13
+ end
14
+
15
+ ws.wait_for_close
@@ -0,0 +1,20 @@
1
+ $: << File.expand_path('../../lib', __FILE__)
2
+ require 'xrbp'
3
+
4
+ ws = XRBP::WebSocket::Parallel.new "wss://s1.ripple.com:443",
5
+ "wss://s2.ripple.com:443"
6
+ ws.add_plugin :command_dispatcher
7
+ ws.connect
8
+
9
+ l = 0
10
+ ws.on :message do |msg|
11
+ msg = JSON.parse(msg.data)
12
+ next unless msg["ledger_index"] && msg["ledger_index"] > l
13
+ l = msg["ledger_index"]
14
+ puts msg
15
+ end
16
+
17
+ XRBP::Model::Ledger.subscribe(:connection => ws)
18
+
19
+ #ws.wait_for_close
20
+ sleep(1) while true
@@ -0,0 +1,18 @@
1
+ $: << File.expand_path('../../lib', __FILE__)
2
+ require 'xrbp'
3
+
4
+ ws = XRBP::WebSocket::Connection.new "wss://s1.ripple.com:443"
5
+ ws.add_plugin :command_dispatcher
6
+ ws.connect
7
+
8
+ i = 0
9
+ ws.on :message do |msg|
10
+ puts msg
11
+
12
+ i += 1
13
+ ws.close! if i > 5
14
+ end
15
+
16
+ XRBP::Model::Ledger.subscribe(:connection => ws)
17
+
18
+ ws.wait_for_close
data/examples/multi.rb ADDED
@@ -0,0 +1,10 @@
1
+ $: << File.expand_path('../../lib', __FILE__)
2
+ require 'xrbp'
3
+
4
+ ws = XRBP::WebSocket::MultiConnection.new "wss://s1.ripple.com:443",
5
+ "wss://s2.ripple.com:443"
6
+
7
+ ws.add_plugin :command_dispatcher
8
+ ws.connect
9
+
10
+ puts ws.cmd(XRBP::WebSocket::Cmds::ServerInfo.new)
@@ -0,0 +1,13 @@
1
+ $: << File.expand_path('../../lib', __FILE__)
2
+ require 'xrbp'
3
+
4
+ ws = XRBP::WebSocket::Connection.new "wss://s1.ripple.com:443"
5
+
6
+ ws.connect
7
+ ws.add_plugin :command_dispatcher, :command_paginator
8
+ ws.cmd(XRBP::WebSocket::Cmds::AccountObjects.new("rhub8VRN55s94qWKDv6jmDy1pUykJzF3wq", :paginate => true)) do |r|
9
+ puts r
10
+ ws.close!
11
+ end
12
+
13
+ ws.wait_for_close
@@ -0,0 +1,13 @@
1
+ $: << File.expand_path('../../lib', __FILE__)
2
+ require 'xrbp'
3
+
4
+ ws = XRBP::WebSocket::Prioritized.new "wss://s1.ripple.com:443",
5
+ "wss://s2.ripple.com:443"
6
+
7
+ ws.add_plugin :command_dispatcher, :result_parser
8
+ ws.parse_results { |res|
9
+ res["result"]["ledger"]
10
+ }
11
+ ws.connect
12
+
13
+ puts ws.cmd(XRBP::WebSocket::Cmds::Ledger.new(28327070))
@@ -0,0 +1,11 @@
1
+ $: << File.expand_path('../../lib', __FILE__)
2
+ require 'xrbp'
3
+
4
+ ws = XRBP::WebSocket::RoundRobin.new "wss://s1.ripple.com:443",
5
+ "wss://s2.ripple.com:443"
6
+
7
+ ws.add_plugin :command_dispatcher
8
+ ws.connect
9
+
10
+ puts ws.cmd(XRBP::WebSocket::Cmds::ServerInfo.new)
11
+ puts ws.cmd(XRBP::WebSocket::Cmds::ServerInfo.new)
@@ -0,0 +1,20 @@
1
+ $: << File.expand_path('../../lib', __FILE__)
2
+ require 'xrbp'
3
+
4
+ ws = XRBP::WebSocket::Connection.new "wss://s1.ripple.com:443"
5
+
6
+ ws.on :open do
7
+ puts "Opened"
8
+ ws.close!
9
+ end
10
+
11
+ ws.on :close do
12
+ puts "Closed"
13
+ end
14
+
15
+ ws.on :error do |e|
16
+ puts "Err #{e}"
17
+ end
18
+
19
+ ws.connect
20
+ ws.wait_for_close
@@ -0,0 +1,27 @@
1
+ module XRBP
2
+ module Model
3
+ class Account < Base
4
+ extend Base::ClassMethods
5
+
6
+ attr_accessor :id
7
+
8
+ def self.create(opts={})
9
+ end
10
+
11
+ def initialize(opts={})
12
+ @id = opts[:id]
13
+ super(opts)
14
+ end
15
+
16
+ def info(opts={}, &bl)
17
+ set_opts(opts)
18
+ connection.cmd(WebSocket::Cmds::AccountInfo.new(id, full_opts), &bl)
19
+ end
20
+
21
+ def objects(opts={}, &bl)
22
+ set_opts(opts)
23
+ connection.cmd(WebSocket::Cmds::AccountObjects.new(id, full_opts), &bl)
24
+ end
25
+ end # class Account
26
+ end # module Model
27
+ end # module XRBP
@@ -0,0 +1,31 @@
1
+ module XRBP
2
+ module Model
3
+ class Base
4
+ module ClassMethods
5
+ attr_accessor :opts, :connection
6
+
7
+ def set_opts(opts={})
8
+ self.opts ||= {}
9
+ self.opts.merge!(opts)
10
+ self.connection = opts[:connection] if opts[:connection]
11
+ end
12
+ end
13
+
14
+ attr_accessor :opts, :connection
15
+
16
+ def initialize(opts={})
17
+ set_opts(opts)
18
+ end
19
+
20
+ def set_opts(opts={})
21
+ @opts ||= {}
22
+ @opts.merge!(opts)
23
+ @connection = opts[:connection] if opts[:connection]
24
+ end
25
+
26
+ def full_opts
27
+ (self.class.opts || {}).merge(opts || {}).except(:connection)
28
+ end
29
+ end # class Base
30
+ end # module Model
31
+ end # module XRBP
@@ -0,0 +1,24 @@
1
+ module XRBP
2
+ module Model
3
+ class Ledger < Base
4
+ extend Base::ClassMethods
5
+
6
+ attr_accessor :id
7
+
8
+ def initialize(opts={})
9
+ @id = opts[:id]
10
+ super(opts)
11
+ end
12
+
13
+ def sync(opts={}, &bl)
14
+ set_opts(opts)
15
+ connection.cmd(WebSocket::Cmds::Ledger.new(id, full_opts), &bl)
16
+ end
17
+
18
+ def self.subscribe(opts={}, &bl)
19
+ set_opts(opts)
20
+ connection.cmd(WebSocket::Cmds::Subscribe.new(:streams => ["ledger"]), &bl)
21
+ end
22
+ end # class Ledger
23
+ end # module Model
24
+ end # module XRBP
data/lib/xrbp/model.rb ADDED
@@ -0,0 +1,3 @@
1
+ require_relative './model/base'
2
+ require_relative './model/ledger'
3
+ require_relative './model/account'
@@ -0,0 +1,8 @@
1
+ module XRBP
2
+ module Network
3
+ class Node
4
+ # TODO retrieve individual node peers &
5
+ # iterator-based mechanism to crawl nodes
6
+ end
7
+ end # module Network
8
+ end # module XRBP
@@ -0,0 +1,6 @@
1
+ # TODO implement these http based synchronization targets (w/ robust common http logic)
2
+ #require_relative './network/nodes'
3
+ #require_relative './network/validators'
4
+ #require_relative './network/gateways'
5
+ #require_relative './network/valuations'
6
+ #require_relative './network/tips'
@@ -0,0 +1,3 @@
1
+ module XRBP
2
+ VERSION = '0.0.1'
3
+ end # module XRBP
@@ -0,0 +1,127 @@
1
+ require 'websocket'
2
+
3
+ module XRBP
4
+ module WebSocket
5
+ class Client
6
+ include EventEmitter
7
+
8
+ attr_reader :url, :options
9
+
10
+ def initialize(url, options={})
11
+ @url = url
12
+ @options = options
13
+
14
+ @handshaked = false
15
+ @closed = false
16
+ end
17
+
18
+ def connect
19
+ emit :connecting
20
+ @closed = false
21
+ socket.connect
22
+ handshake!
23
+ @thread = poll
24
+ self
25
+ end
26
+
27
+ ###
28
+
29
+ def open?
30
+ handshake.finished? and !closed?
31
+ end
32
+
33
+ def closed?
34
+ !!@closed
35
+ end
36
+
37
+ def close(err=nil)
38
+ return if closed?
39
+
40
+ # XXX set closed true first incase callbacks need to check this
41
+ @closed = true
42
+
43
+ send_data nil, :type => :close unless socket.pipe_broken
44
+ emit :close, err
45
+
46
+ ensure
47
+ # Always set closed true
48
+ @closed = true
49
+ socket.close if socket
50
+ @handshake = nil
51
+ @handshaked = false
52
+ @socket = nil
53
+ #Thread.kill @thread if @thread
54
+ @thread.join if @thread && Thread.current != @thread
55
+ emit :completed
56
+ end
57
+
58
+ ###
59
+
60
+ def socket
61
+ @socket ||= Socket.new self
62
+ end
63
+
64
+ ###
65
+
66
+ def handshake
67
+ @handshake ||= ::WebSocket::Handshake::Client.new :url => url,
68
+ :headers => options[:headers]
69
+ end
70
+
71
+ def handshaked?
72
+ !!@handshaked
73
+ end
74
+
75
+ def handshake!
76
+ socket.write handshake.to_s
77
+
78
+ until handshaked?
79
+ socket.read_next handshake
80
+ @handshaked = handshake.finished?
81
+ end
82
+ end
83
+
84
+ ###
85
+
86
+ def send_data(data, opt={:type => :text})
87
+ return if !handshaked? || closed?
88
+
89
+ frame = ::WebSocket::Frame::Outgoing::Client.new(:data => data,
90
+ :type => opt[:type],
91
+ :version => handshake.version)
92
+
93
+ begin
94
+ socket.write_nonblock(frame.to_s)
95
+
96
+ rescue Errno::EPIPE, OpenSSL::SSL::SSLError => e
97
+ close(e)
98
+ end
99
+ end
100
+
101
+ def poll
102
+ return Thread.new(socket) do |socket|
103
+ frame = ::WebSocket::Frame::Incoming::Client.new
104
+ emit :open
105
+
106
+ until closed? do
107
+ begin
108
+ socket.read_next(frame)
109
+
110
+ if msg = frame.next
111
+ emit :message, msg
112
+ frame = ::WebSocket::Frame::Incoming::Client.new
113
+ end
114
+
115
+ rescue EOFError => e
116
+ emit :error, e
117
+ close(e)
118
+
119
+ rescue => e
120
+ emit :error, e
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end # class Client
126
+ end # module WebSocket
127
+ end # module XRBP
@@ -0,0 +1,20 @@
1
+ module XRBP
2
+ module WebSocket
3
+ module Cmds
4
+ class AccountInfo < Command
5
+ attr_accessor :account, :args
6
+
7
+ def initialize(account, args={})
8
+ @account = account
9
+ @args = args
10
+ super(to_h)
11
+ end
12
+
13
+ def to_h
14
+ args.merge(:command => :account_info,
15
+ :account => account)
16
+ end
17
+ end # class AccountInfo
18
+ end # module Cmds
19
+ end # module WebSocket
20
+ end # module Wipple
@@ -0,0 +1,33 @@
1
+ module XRBP
2
+ module WebSocket
3
+ module Cmds
4
+ class AccountLines < Command
5
+ include Paginated
6
+
7
+ def page_title
8
+ "account_lines"
9
+ end
10
+
11
+ attr_accessor :account, :args
12
+
13
+ def initialize(account, args={})
14
+ @account = account
15
+ @args = args
16
+ parse_paginate(args)
17
+ super(to_h)
18
+ end
19
+
20
+ def self.from_h(h)
21
+ _h = Hash[h]
22
+ a = _h.delete(:account)
23
+ new a, _h
24
+ end
25
+
26
+ def to_h
27
+ args_without_paginate.merge(:command => :account_lines,
28
+ :account => account)
29
+ end
30
+ end # class AccountLines
31
+ end # module Cmds
32
+ end # module WebSocket
33
+ end # module Wipple
@@ -0,0 +1,33 @@
1
+ module XRBP
2
+ module WebSocket
3
+ module Cmds
4
+ class AccountObjects < Command
5
+ include Paginated
6
+
7
+ def page_title
8
+ "account_objects"
9
+ end
10
+
11
+ attr_accessor :account, :args
12
+
13
+ def initialize(account, args={})
14
+ @account = account
15
+ @args = args
16
+ parse_paginate(args)
17
+ super(to_h)
18
+ end
19
+
20
+ def self.from_h(h)
21
+ _h = Hash[h]
22
+ a = _h.delete(:account)
23
+ new a, _h
24
+ end
25
+
26
+ def to_h
27
+ args_without_paginate.merge(:command => :account_objects,
28
+ :account => account)
29
+ end
30
+ end # class AccountLines
31
+ end # module Cmds
32
+ end # module WebSocket
33
+ end # module Wipple
@@ -0,0 +1,33 @@
1
+ module XRBP
2
+ module WebSocket
3
+ module Cmds
4
+ class AccountOffers < Command
5
+ include Paginated
6
+
7
+ def page_title
8
+ "offers"
9
+ end
10
+
11
+ attr_accessor :account, :args
12
+
13
+ def initialize(account, args={})
14
+ @account = account
15
+ @args = args
16
+ parse_paginate(args)
17
+ super(to_h)
18
+ end
19
+
20
+ def self.from_h(h)
21
+ _h = Hash[h]
22
+ a = _h.delete(:account)
23
+ new a, _h
24
+ end
25
+
26
+ def to_h
27
+ args_without_paginate.merge(:command => :account_offers,
28
+ :account => account)
29
+ end
30
+ end # class AccountLines
31
+ end # module Cmds
32
+ end # module WebSocket
33
+ end # module Wipple
@@ -0,0 +1,20 @@
1
+ module XRBP
2
+ module WebSocket
3
+ module Cmds
4
+ class AccountTx < Command
5
+ attr_accessor :account, :args
6
+
7
+ def initialize(account, args={})
8
+ @account = account
9
+ @args = args
10
+ super(to_h)
11
+ end
12
+
13
+ def to_h
14
+ args.merge(:command => :account_tx,
15
+ :account => account)
16
+ end
17
+ end # class AccountLines
18
+ end # module Cmds
19
+ end # module WebSocket
20
+ end # module Wipple
@@ -0,0 +1,38 @@
1
+ module XRBP
2
+ module WebSocket
3
+ module Cmds
4
+ class BookOffers < Command
5
+ include Paginated
6
+
7
+ def page_title
8
+ "offers"
9
+ end
10
+
11
+ attr_accessor :args
12
+
13
+ def initialize(args={})
14
+ @args = args
15
+ parse_paginate(args)
16
+ super(to_h)
17
+ end
18
+
19
+ def self.from_h(h)
20
+ new Hash[h]
21
+ end
22
+
23
+ def sanitized_args
24
+ sa = Hash[args_without_paginate]
25
+
26
+ sa[:taker_gets].delete(:issuer) if sa[:taker_gets][:currency] == "XRP"
27
+ sa[:taker_pays].delete(:issuer) if sa[:taker_pays][:currency] == "XRP"
28
+
29
+ sa
30
+ end
31
+
32
+ def to_h
33
+ sanitized_args.merge(:command => :book_offers)
34
+ end
35
+ end # class BookOffers
36
+ end # module Cmds
37
+ end # module WebSocket
38
+ end # module Wipple
@@ -0,0 +1,25 @@
1
+ module XRBP
2
+ module WebSocket
3
+ module Cmds
4
+ class Ledger < Command
5
+ attr_accessor :id, :args
6
+
7
+ def initialize(id=nil, args={})
8
+ @id = id
9
+ @args = args
10
+ super(to_h)
11
+ end
12
+
13
+ def id?
14
+ !!id
15
+ end
16
+
17
+ def to_h
18
+ h = args.merge(:command => :ledger)
19
+ h['ledger_index'] = id if id?
20
+ return h
21
+ end
22
+ end
23
+ end # module Cmds
24
+ end # module WebSocket
25
+ end # module Wipple
@@ -0,0 +1,16 @@
1
+ module XRBP
2
+ module WebSocket
3
+ module Cmds
4
+ class LedgerEntry < Command
5
+ def initialize(args={})
6
+ @args = args
7
+ super(to_h)
8
+ end
9
+
10
+ def to_h
11
+ @args.merge('command' => 'ledger_entry')
12
+ end
13
+ end
14
+ end # module Cmds
15
+ end # module WebSocket
16
+ end # module Wipple