banano 0.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.
@@ -0,0 +1,227 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'forwardable'
4
+
5
+ # The <tt>Banano::WalletAccount</tt> class lets you manage
6
+ # your banano accounts, including making and receiving payments.
7
+ #
8
+ module Banano
9
+ class WalletAccount
10
+ extend Forwardable
11
+ # @!method balance(raw: true)
12
+ # (see Banano::Account#balance)
13
+ # @!method block_count
14
+ # (see Banano::Account#block_count)
15
+ # @!method delegators(raw: true)
16
+ # (see Banano::Account#delegators)
17
+ # @!method exists?
18
+ # (see Banano::Account#exists?)
19
+ # @!method id
20
+ # (see Banano::Account#id)
21
+ # @!method info((detailed: false, raw: true)
22
+ # (see Banano::Account#info)
23
+ # @!method last_modified_at
24
+ # (see Banano::Account#last_modified_at)
25
+ # @!method pending(limit: 1000, detailed: false, raw: true)
26
+ # (see Banano::Account#pending)
27
+ # @!method public_key
28
+ # (see Banano::Account#public_key)
29
+ # @!method history(limit: 1000, raw: true)
30
+ # (see Banano::Account#history)
31
+ # @!method representative
32
+ # (see Banano::Account#representative)
33
+ def_delegators :@banano_account_instance,
34
+ :balance,
35
+ :delegators,
36
+ :exists?,
37
+ :id,
38
+ :info,
39
+ :last_modified_at,
40
+ :pending,
41
+ :public_key,
42
+ :history,
43
+ :representative
44
+ alias open? exists?
45
+
46
+ def initialize(node:, wallet:, account: nil)
47
+ @node = node
48
+ @wallet = wallet
49
+ @account = account
50
+ @banano_account_instance = nil
51
+
52
+ unless @account.nil?
53
+ # Wallet must contain the account
54
+ unless Banano::Wallet.new(node: @node, wallet: @wallet).contains?(@account)
55
+ raise ArgumentError, "Account does not exist in wallet. Account: #{@account}, wallet: #{@wallet}"
56
+ end
57
+
58
+ # An object to delegate account methods that don't
59
+ # expect a wallet param in the RPC call, to allow this
60
+ # class to support all methods that can be called on Banano::Account
61
+ @banano_account_instance = Banano::Account.new(node: @node, address: @account)
62
+ end
63
+ end
64
+
65
+ # Creates a new account, or multiple new accounts, in this wallet.
66
+ #
67
+ # ==== Examples:
68
+ #
69
+ # wallet_account.create # => Banano::WalletAccount
70
+ # wallet_account.create(2) # => [Banano::WalletAccount, Banano::WalletAccount]
71
+ #
72
+ # @param count [Integer] number of accounts to create
73
+ #
74
+ # @return [Banano::WalletAccount] returns a single {Banano::WalletAccount}
75
+ # if invoked with no argument
76
+ # @return [Array<Banano::WalletAccount>] returns an Array of {Banano::WalletAccount}
77
+ # if method was called with argument +n+ > 1
78
+ # @raise [ArgumentError] if +n+ is less than 1
79
+ def create(count = 1)
80
+ raise ArgumentError, "number of accounts must be greater than 0" if count < 1
81
+
82
+ if count == 1
83
+ Banano::WalletAccount.new(node: @node,
84
+ wallet: @wallet,
85
+ account: rpc(action: :account_create)[:account])
86
+ else
87
+ Array(rpc(action: :accounts_create, params: {count: count})[:accounts]).map do |account|
88
+ Banano::WalletAccount.new(node: @node,
89
+ wallet: @wallet,
90
+ account: account)
91
+ end
92
+ end
93
+ end
94
+
95
+ # Unlinks the account from the wallet.
96
+ #
97
+ # ==== Example:
98
+ #
99
+ # wallet_account.destroy # => true
100
+ #
101
+ # @return [Boolean] +true+ if action was successful, otherwise +false+
102
+ def destroy
103
+ rpc(action: :account_remove)[:removed] == '1'
104
+ end
105
+
106
+ # Makes a payment from this account to another account
107
+ # on the banano network. Returns a <i>send</i> block hash
108
+ # if successful, or a {Banano::Error} if unsuccessful.
109
+ #
110
+ # Note, there may be a delay in receiving a response due to Proof
111
+ # of Work being done. <i>Proof of Work is precomputed for one transaction
112
+ # in the background. If it has been a while since your last transaction
113
+ # it will send instantly, the next one will need to wait for
114
+ # Proof of Work to be generated.</i>
115
+ #
116
+ # @param to [String] account id of the recipient of your payment
117
+ # @param amount [Integer|Float]
118
+ # @param raw [Boolean] raw or banano units
119
+ # @param id [String] must be unique per payment. It serves an important
120
+ # purpose; it allows you to make the same call multiple times with
121
+ # the same +id+ and be reassured that you will only ever send this
122
+ # nano payment once
123
+ #
124
+ # @return [String] the send block id for the payment
125
+ # @raise [Banano::Error] if unsuccessful
126
+ def pay(to:, amount:, raw: true, id:)
127
+ # Check that to account is a valid address
128
+ response = rpc(action: :validate_account_number, params: {account: to})
129
+ raise ArgumentError, "Account address is invalid: #{to}" unless response[:valid] == '1'
130
+
131
+ raw_amount = raw ? amount : Banano::Unit.ban_to_raw(amount)
132
+ # account is called source, so don't use the normal rpc method
133
+ p = {
134
+ wallet: @wallet,
135
+ source: @account,
136
+ destination: to,
137
+ amount: raw_amount,
138
+ id: id
139
+ }
140
+ response = rpc(action: :send, params: p)
141
+ return Banano::Error.new(response[:error]) if response.key?(:error)
142
+
143
+ response[:block]
144
+ end
145
+
146
+ # Receives a pending payment for this account.
147
+ #
148
+ # When called with no +block+ argument, the latest pending payment
149
+ # for the account will be received.
150
+ #
151
+ # Returns a <i>receive</i> block id
152
+ # if a receive was successful, or +false+ if there were no pending
153
+ # payments to receive.
154
+ #
155
+ # You can receive a specific pending block if you know it by
156
+ # passing the block in as an argument.
157
+ #
158
+ # ==== Examples:
159
+ #
160
+ # account.receive # => "9AE2311..."
161
+ # account.receive("718CC21...") # => "9AE2311..."
162
+ #
163
+ # @param block [String] optional block id of pending payment. If
164
+ # not provided, the latest pending payment will be received
165
+ #
166
+ # @return [String] the receive block id
167
+ # @return [false] if there was no block to receive
168
+ def receive(block = nil)
169
+ if block.nil?
170
+ _receive_without_block
171
+ else
172
+ _receive_with_block(block)
173
+ end
174
+ end
175
+
176
+ # Sets the representative for the account.
177
+ #
178
+ # A representative is an account that will vote on your account's
179
+ # behalf on the nano network if your account is offline and there is
180
+ # a fork of the network that requires voting on.
181
+ #
182
+ # Returns the <em>change block</em> that was
183
+ # broadcast to the nano network. The block contains the information
184
+ # about the representative change for your account.
185
+ #
186
+ # @param [String] representative the id of the representative account
187
+ # to set as this account's representative
188
+ # @return [String] id of the <i>change</i> block created
189
+ # @raise [ArgumentError] if the representative account does not exist
190
+ def change_representative(representative)
191
+ unless Banano::Account.new(node: @node, address: representative).exists?
192
+ raise ArgumentError, "Representative account does not exist: #{representative}"
193
+ end
194
+
195
+ rpc(action: :account_representative_set,
196
+ params: {representative: representative})[:block]
197
+ end
198
+
199
+ private
200
+
201
+ def _receive_without_block
202
+ # Discover the first pending block
203
+ pending_blocks = rpc(action: :pending, params: {account: @account, count: 1})
204
+
205
+ return false if pending_blocks[:blocks].empty?
206
+
207
+ # Then call receive_with_block as normal
208
+ _receive_with_block(pending_blocks[:blocks][0])
209
+ end
210
+
211
+ # Returns block if successful, otherwise false
212
+ def _receive_with_block(block)
213
+ response = rpc(action: :receive, params: {block: block})[:block]
214
+ response.nil? ? false : response
215
+ end
216
+
217
+ def rpc(action:, params: {})
218
+ p = {}
219
+ return p unless @wallet
220
+
221
+ p[:wallet] = @wallet
222
+ p[:account] = @account unless @account.nil?
223
+
224
+ @node.rpc(action: action, params: p.merge(params))
225
+ end
226
+ end
227
+ end
metadata ADDED
@@ -0,0 +1,161 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: banano
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Stoyan Zhekov
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2020-06-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: faraday
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: faraday_middleware
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: pry
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '12.3'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '12.3'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.9'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.9'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rubocop
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '0.85'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '0.85'
97
+ - !ruby/object:Gem::Dependency
98
+ name: webmock
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '3.8'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '3.8'
111
+ description: Library for working with Banano currency. Implements parts of the RPC
112
+ protocol for access to Banano node. Convertion between raw and banano units etc.
113
+ email:
114
+ - zh@zhware.net
115
+ executables: []
116
+ extensions: []
117
+ extra_rdoc_files: []
118
+ files:
119
+ - CHANGELOG.md
120
+ - LICENSE.txt
121
+ - README.md
122
+ - bin/console
123
+ - bin/setup
124
+ - lib/banano.rb
125
+ - lib/banano/account.rb
126
+ - lib/banano/client.rb
127
+ - lib/banano/error.rb
128
+ - lib/banano/key.rb
129
+ - lib/banano/node.rb
130
+ - lib/banano/unit.rb
131
+ - lib/banano/util.rb
132
+ - lib/banano/version.rb
133
+ - lib/banano/wallet.rb
134
+ - lib/banano/wallet_account.rb
135
+ homepage: http://github.com/zh/rbanano
136
+ licenses:
137
+ - MIT
138
+ metadata:
139
+ homepage_uri: http://github.com/zh/rbanano
140
+ source_code_uri: http://github.com/zh/rbanano
141
+ changelog_uri: http://github.com/zh/rbanano/CHANGELOG.md
142
+ post_install_message:
143
+ rdoc_options: []
144
+ require_paths:
145
+ - lib
146
+ required_ruby_version: !ruby/object:Gem::Requirement
147
+ requirements:
148
+ - - ">="
149
+ - !ruby/object:Gem::Version
150
+ version: 2.3.0
151
+ required_rubygems_version: !ruby/object:Gem::Requirement
152
+ requirements:
153
+ - - ">="
154
+ - !ruby/object:Gem::Version
155
+ version: '0'
156
+ requirements: []
157
+ rubygems_version: 3.0.3
158
+ signing_key:
159
+ specification_version: 4
160
+ summary: Library for working with Banano currency.
161
+ test_files: []