nanook 2.1.0 → 2.2.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +36 -1
- data/README.md +20 -9
- data/lib/nanook.rb +4 -4
- data/lib/nanook/account.rb +169 -111
- data/lib/nanook/error.rb +1 -0
- data/lib/nanook/node.rb +131 -4
- data/lib/nanook/rpc.rb +23 -2
- data/lib/nanook/util.rb +19 -0
- data/lib/nanook/version.rb +1 -1
- data/lib/nanook/wallet.rb +111 -75
- data/lib/nanook/wallet_account.rb +44 -40
- metadata +2 -2
    
        data/lib/nanook/error.rb
    CHANGED
    
    
    
        data/lib/nanook/node.rb
    CHANGED
    
    | @@ -1,31 +1,96 @@ | |
| 1 1 | 
             
            class Nanook
         | 
| 2 | 
            +
             | 
| 3 | 
            +
              # The <tt>Nanook::Node</tt> class contains methods to manage your nano
         | 
| 4 | 
            +
              # node and query its data of the nano network.
         | 
| 5 | 
            +
              #
         | 
| 6 | 
            +
              # Your node is constantly syncing data with other nodes on the network. When
         | 
| 7 | 
            +
              # your node first starts up after being built, its database will be empty
         | 
| 8 | 
            +
              # and it will begin synchronizing and downloading data of the nano ledger
         | 
| 9 | 
            +
              # to its local database. The ledger is the central record of all accounts
         | 
| 10 | 
            +
              # and transactions. Some of the methods in this class query your node's
         | 
| 11 | 
            +
              # database formed from the nano ledger, and so the responses are determined
         | 
| 12 | 
            +
              # by the completeness of your node's database.
         | 
| 13 | 
            +
              #
         | 
| 14 | 
            +
              # You can determine how synchronized your node is with the nano ledger
         | 
| 15 | 
            +
              # with the {#sync_progress} method.
         | 
| 16 | 
            +
              #
         | 
| 17 | 
            +
              # === Initializing
         | 
| 18 | 
            +
              #
         | 
| 19 | 
            +
              # Initialize this class through the convenient {Nanook#node} method:
         | 
| 20 | 
            +
              #
         | 
| 21 | 
            +
              #   node = Nanook.new.node
         | 
| 22 | 
            +
              #
         | 
| 23 | 
            +
              # Or compose the longhand way like this:
         | 
| 24 | 
            +
              #
         | 
| 25 | 
            +
              #   rpc_conn = Nanook::Rpc.new
         | 
| 26 | 
            +
              #   node = Nanook::Node.new(rpc_conn)
         | 
| 2 27 | 
             
              class Node
         | 
| 3 28 |  | 
| 4 29 | 
             
                def initialize(rpc)
         | 
| 5 30 | 
             
                  @rpc = rpc
         | 
| 6 31 | 
             
                end
         | 
| 7 32 |  | 
| 33 | 
            +
                # The number of accounts in the nano ledger--essentially all
         | 
| 34 | 
            +
                # accounts with _open_ blocks. An _open_ block
         | 
| 35 | 
            +
                # is the type of block written to the nano ledger when an account
         | 
| 36 | 
            +
                # receives its first payment (see {Nanook::WalletAccount#receive}). All accounts
         | 
| 37 | 
            +
                # that respond +true+ to {Nanook::Account#exists?} have open blocks in the ledger.
         | 
| 38 | 
            +
                #
         | 
| 39 | 
            +
                # @return [Integer] number of accounts with _open_ blocks.
         | 
| 8 40 | 
             
                def account_count
         | 
| 9 41 | 
             
                  rpc(:frontier_count)[:count]
         | 
| 10 42 | 
             
                end
         | 
| 11 43 | 
             
                alias_method :frontier_count, :account_count
         | 
| 12 44 |  | 
| 45 | 
            +
                # The count of all blocks downloaded to the node, and
         | 
| 46 | 
            +
                # blocks still to be synchronized by the node.
         | 
| 47 | 
            +
                #
         | 
| 48 | 
            +
                # ==== Example:
         | 
| 49 | 
            +
                #
         | 
| 50 | 
            +
                #
         | 
| 51 | 
            +
                #
         | 
| 52 | 
            +
                # @return [Hash{Symbol=>Integer}] number of blocks and unchecked
         | 
| 53 | 
            +
                #   synchronizing blocks
         | 
| 13 54 | 
             
                def block_count
         | 
| 14 55 | 
             
                  rpc(:block_count)
         | 
| 15 56 | 
             
                end
         | 
| 16 57 |  | 
| 17 | 
            -
                 | 
| 58 | 
            +
                # The count of all known blocks by their type.
         | 
| 59 | 
            +
                #
         | 
| 60 | 
            +
                # ==== Example:
         | 
| 61 | 
            +
                #
         | 
| 62 | 
            +
                #   node.block_count_by_type
         | 
| 63 | 
            +
                #
         | 
| 64 | 
            +
                # Example response:
         | 
| 65 | 
            +
                #
         | 
| 66 | 
            +
                #   {
         | 
| 67 | 
            +
                #     send: 1000,
         | 
| 68 | 
            +
                #     receive: 900,
         | 
| 69 | 
            +
                #     open: 900,
         | 
| 70 | 
            +
                #     change: 50
         | 
| 71 | 
            +
                #   }
         | 
| 72 | 
            +
                #
         | 
| 73 | 
            +
                # @return [Hash{Symbol=>Integer}] number of blocks by type
         | 
| 74 | 
            +
                def block_count_by_type
         | 
| 18 75 | 
             
                  rpc(:block_count_type)
         | 
| 19 76 | 
             
                end
         | 
| 77 | 
            +
                alias_method :block_count_type, :block_count_by_type
         | 
| 20 78 |  | 
| 79 | 
            +
                # Initialize bootstrap to a specific IP address and port.
         | 
| 80 | 
            +
                #
         | 
| 81 | 
            +
                # @return [Boolean] indicating if the action was successful
         | 
| 21 82 | 
             
                def bootstrap(address:, port:)
         | 
| 22 83 | 
             
                  rpc(:bootstrap, address: address, port: port).has_key?(:success)
         | 
| 23 84 | 
             
                end
         | 
| 24 85 |  | 
| 86 | 
            +
                # Initialize multi-connection bootstrap to random peers
         | 
| 87 | 
            +
                #
         | 
| 88 | 
            +
                # @return [Boolean] indicating if the action was successful
         | 
| 25 89 | 
             
                def bootstrap_any
         | 
| 26 90 | 
             
                  rpc(:bootstrap_any).has_key?(:success)
         | 
| 27 91 | 
             
                end
         | 
| 28 92 |  | 
| 93 | 
            +
                # @return [String]
         | 
| 29 94 | 
             
                def inspect
         | 
| 30 95 | 
             
                  "#{self.class.name}(object_id: \"#{"0x00%x" % (object_id << 1)}\")"
         | 
| 31 96 | 
             
                end
         | 
| @@ -34,14 +99,60 @@ class Nanook | |
| 34 99 | 
             
                  rpc(:peers)[:peers]
         | 
| 35 100 | 
             
                end
         | 
| 36 101 |  | 
| 37 | 
            -
                 | 
| 38 | 
            -
             | 
| 102 | 
            +
                # All representatives and their voting weight.
         | 
| 103 | 
            +
                #
         | 
| 104 | 
            +
                # ==== Example:
         | 
| 105 | 
            +
                #
         | 
| 106 | 
            +
                #   node.representatives
         | 
| 107 | 
            +
                #
         | 
| 108 | 
            +
                # Example response:
         | 
| 109 | 
            +
                #
         | 
| 110 | 
            +
                #   {
         | 
| 111 | 
            +
                #     xrb_1111111111111111111111111111111111111111111111111117353trpda: 3822372327060170000000000000000000000,
         | 
| 112 | 
            +
                #     xrb_1111111111111111111111111111111111111111111111111awsq94gtecn: 30999999999999999999999999000000,
         | 
| 113 | 
            +
                #     xrb_114nk4rwjctu6n6tr6g6ps61g1w3hdpjxfas4xj1tq6i8jyomc5d858xr1xi: 0
         | 
| 114 | 
            +
                #   }
         | 
| 115 | 
            +
                #
         | 
| 116 | 
            +
                # @return [Hash{Symbol=>Integer}] known representatives and their voting weight
         | 
| 117 | 
            +
                def representatives(unit: Nanook.default_unit)
         | 
| 118 | 
            +
                  unless Nanook::UNITS.include?(unit)
         | 
| 119 | 
            +
                    raise ArgumentError.new("Unsupported unit: #{unit}")
         | 
| 120 | 
            +
                  end
         | 
| 121 | 
            +
             | 
| 122 | 
            +
                  response = rpc(:representatives)[:representatives]
         | 
| 123 | 
            +
                  return response if unit == :raw
         | 
| 124 | 
            +
             | 
| 125 | 
            +
                  r = response.map do |account_id, balance|
         | 
| 126 | 
            +
                    balance = Nanook::Util.raw_to_NANO(balance)
         | 
| 127 | 
            +
             | 
| 128 | 
            +
                    [account_id, balance]
         | 
| 129 | 
            +
                  end
         | 
| 130 | 
            +
             | 
| 131 | 
            +
                  Hash[r].to_symbolized_hash
         | 
| 132 | 
            +
                end
         | 
| 133 | 
            +
             | 
| 134 | 
            +
                # All online representatives that have voted recently. Note, due to the
         | 
| 135 | 
            +
                # design of the nano RPC, this method cannot return the voting weight
         | 
| 136 | 
            +
                # of the representatives.
         | 
| 137 | 
            +
                #
         | 
| 138 | 
            +
                # ==== Example:
         | 
| 139 | 
            +
                #
         | 
| 140 | 
            +
                #   node.representatives_online # => ["xrb_111...", "xrb_222"]
         | 
| 141 | 
            +
                #
         | 
| 142 | 
            +
                # @return [Array<String>] array of representative account ids
         | 
| 143 | 
            +
                def representatives_online
         | 
| 144 | 
            +
                  response = rpc(:representatives_online)[:representatives].keys.map(&:to_s)
         | 
| 39 145 | 
             
                end
         | 
| 40 146 |  | 
| 147 | 
            +
                # Safely shuts down the node.
         | 
| 148 | 
            +
                #
         | 
| 149 | 
            +
                # @return [Boolean] indicating if action was successful
         | 
| 41 150 | 
             
                def stop
         | 
| 42 151 | 
             
                  rpc(:stop).has_key?(:success)
         | 
| 43 152 | 
             
                end
         | 
| 44 153 |  | 
| 154 | 
            +
                # @param limit [Integer] number of synchronizing blocks to return
         | 
| 155 | 
            +
                # @return [Hash{Symbol=>String}] information about the synchronizing blocks for this node
         | 
| 45 156 | 
             
                def synchronizing_blocks(limit: 1000)
         | 
| 46 157 | 
             
                  response = rpc(:unchecked, count: limit)[:blocks]
         | 
| 47 158 | 
             
                  response = response.map do |block, info|
         | 
| @@ -49,7 +160,16 @@ class Nanook | |
| 49 160 | 
             
                  end
         | 
| 50 161 | 
             
                  Hash[response.sort].to_symbolized_hash
         | 
| 51 162 | 
             
                end
         | 
| 52 | 
            -
             | 
| 163 | 
            +
                alias_method :unchecked, :synchronizing_blocks
         | 
| 164 | 
            +
             | 
| 165 | 
            +
                # The percentage completeness of the synchronization process for
         | 
| 166 | 
            +
                # your node as it downloads the nano ledger. Note, it's normal for
         | 
| 167 | 
            +
                # your progress to not ever reach 100. The closer to 100, the more
         | 
| 168 | 
            +
                # complete your node's data is, and so the query methods in this class
         | 
| 169 | 
            +
                # become more reliable.
         | 
| 170 | 
            +
                #
         | 
| 171 | 
            +
                # @return [Float] the percentage completeness of the synchronization
         | 
| 172 | 
            +
                #   process for your node
         | 
| 53 173 | 
             
                def sync_progress
         | 
| 54 174 | 
             
                  response = rpc(:block_count)
         | 
| 55 175 |  | 
| @@ -60,13 +180,20 @@ class Nanook | |
| 60 180 | 
             
                  count.to_f * 100 / total.to_f
         | 
| 61 181 | 
             
                end
         | 
| 62 182 |  | 
| 183 | 
            +
                # This method is deprecated and will be removed in 3.0, as a node never
         | 
| 184 | 
            +
                # reaches 100% synchronization.
         | 
| 185 | 
            +
                #
         | 
| 186 | 
            +
                # @return [Boolean] signalling if this node ever reaches 100% synchronized
         | 
| 63 187 | 
             
                def synced?
         | 
| 188 | 
            +
                  warn "[DEPRECATION] `synced?` is deprecated and will be removed in 3.0"
         | 
| 64 189 | 
             
                  rpc(:block_count)[:unchecked] == 0
         | 
| 65 190 | 
             
                end
         | 
| 66 191 |  | 
| 192 | 
            +
                # @return [Hash{Symbol=>Integer|String}] version information for this node
         | 
| 67 193 | 
             
                def version
         | 
| 68 194 | 
             
                  rpc(:version)
         | 
| 69 195 | 
             
                end
         | 
| 196 | 
            +
                alias_method :info, :version
         | 
| 70 197 |  | 
| 71 198 | 
             
                private
         | 
| 72 199 |  | 
    
        data/lib/nanook/rpc.rb
    CHANGED
    
    | @@ -2,10 +2,23 @@ require 'json' | |
| 2 2 | 
             
            require 'symbolized'
         | 
| 3 3 |  | 
| 4 4 | 
             
            class Nanook
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              # The <tt>Nanook::Rpc</tt> class is responsible for maintaining the
         | 
| 7 | 
            +
              # connection to the RPC server, calling the RPC and parsing its response
         | 
| 8 | 
            +
              # into Ruby primitives.
         | 
| 9 | 
            +
              #
         | 
| 10 | 
            +
              # Internally, the {Nanook} class creates an instance of this class, and
         | 
| 11 | 
            +
              # it's generally more convenient to interact with the RPC through an
         | 
| 12 | 
            +
              # instance of {Nanook#rpc} instead of by instantiating this class directly:
         | 
| 13 | 
            +
              #
         | 
| 14 | 
            +
              #   nanook = Nanook.new
         | 
| 15 | 
            +
              #   nanook.rpc(:accounts_create, wallet: wallet_id, count: 2)
         | 
| 5 16 | 
             
              class Rpc
         | 
| 6 17 |  | 
| 18 | 
            +
                # Default RPC server and port to connect to
         | 
| 7 19 | 
             
                DEFAULT_URI = "http://localhost:7076"
         | 
| 8 | 
            -
                 | 
| 20 | 
            +
                # Default request timeout in seconds
         | 
| 21 | 
            +
                DEFAULT_TIMEOUT = 60
         | 
| 9 22 |  | 
| 10 23 | 
             
                def initialize(uri=DEFAULT_URI, timeout:DEFAULT_TIMEOUT)
         | 
| 11 24 | 
             
                  @rpc_server = URI(uri)
         | 
| @@ -20,6 +33,12 @@ class Nanook | |
| 20 33 | 
             
                  @request.content_type = "application/json"
         | 
| 21 34 | 
             
                end
         | 
| 22 35 |  | 
| 36 | 
            +
                # Calls the RPC server and returns the response.
         | 
| 37 | 
            +
                #
         | 
| 38 | 
            +
                # @param action [Symbol] the "action" of the RPC to call. The RPC always
         | 
| 39 | 
            +
                #   expects an "action" param to identify what RPC action is being called.
         | 
| 40 | 
            +
                # @param params [Hash] all other params to pass to the RPC
         | 
| 41 | 
            +
                # @return [Hash] the response from the RPC
         | 
| 23 42 | 
             
                def call(action, params={})
         | 
| 24 43 | 
             
                  # Stringify param values
         | 
| 25 44 | 
             
                  params = Hash[params.map {|k, v| [k, v.to_s] }]
         | 
| @@ -36,13 +55,14 @@ class Nanook | |
| 36 55 | 
             
                  end
         | 
| 37 56 | 
             
                end
         | 
| 38 57 |  | 
| 58 | 
            +
                # @return [String]
         | 
| 39 59 | 
             
                def inspect
         | 
| 40 60 | 
             
                  "#{self.class.name}(host: \"#{@rpc_server}\", timeout: #{@http.read_timeout} object_id: \"#{"0x00%x" % (object_id << 1)}\")"
         | 
| 41 61 | 
             
                end
         | 
| 42 62 |  | 
| 43 63 | 
             
                private
         | 
| 44 64 |  | 
| 45 | 
            -
                #  | 
| 65 | 
            +
                # Recursively parses the RPC response, sending values to #parse_value
         | 
| 46 66 | 
             
                def process_hash(h)
         | 
| 47 67 | 
             
                  new_hash = h.map do |k,v|
         | 
| 48 68 | 
             
                    v = if v.is_a?(Array)
         | 
| @@ -63,6 +83,7 @@ class Nanook | |
| 63 83 | 
             
                  Hash[new_hash.sort].to_symbolized_hash
         | 
| 64 84 | 
             
                end
         | 
| 65 85 |  | 
| 86 | 
            +
                # Converts Strings to primitives
         | 
| 66 87 | 
             
                def parse_value(v)
         | 
| 67 88 | 
             
                  return v.to_i if v.match(/^\d+\Z/)
         | 
| 68 89 | 
             
                  return true if v == "true"
         | 
    
        data/lib/nanook/util.rb
    CHANGED
    
    | @@ -1,18 +1,37 @@ | |
| 1 1 | 
             
            require 'bigdecimal'
         | 
| 2 2 |  | 
| 3 3 | 
             
            class Nanook
         | 
| 4 | 
            +
             | 
| 5 | 
            +
              # Set of class utility methods.
         | 
| 4 6 | 
             
              class Util
         | 
| 5 7 |  | 
| 8 | 
            +
                # Constant used to convert back and forth between raw and NANO.
         | 
| 6 9 | 
             
                STEP = BigDecimal.new("10")**BigDecimal.new("30")
         | 
| 7 10 |  | 
| 11 | 
            +
                # Converts an amount of NANO to an amount of raw.
         | 
| 12 | 
            +
                #
         | 
| 13 | 
            +
                # @param nano [Float|Integer] amount in nano
         | 
| 14 | 
            +
                # @return [Integer] amount in raw
         | 
| 8 15 | 
             
                def self.NANO_to_raw(nano)
         | 
| 9 16 | 
             
                  (BigDecimal.new(nano.to_s) * STEP).to_i
         | 
| 10 17 | 
             
                end
         | 
| 11 18 |  | 
| 19 | 
            +
                # Converts an amount of raw to an amount of NANO.
         | 
| 20 | 
            +
                #
         | 
| 21 | 
            +
                # @param raw [Integer] amount in raw
         | 
| 22 | 
            +
                # @return [Float|Integer] amount in NANO
         | 
| 12 23 | 
             
                def self.raw_to_NANO(raw)
         | 
| 13 24 | 
             
                  (raw.to_f / STEP).to_f
         | 
| 14 25 | 
             
                end
         | 
| 15 26 |  | 
| 27 | 
            +
                # Converts an empty String value into an empty version of another type.
         | 
| 28 | 
            +
                #
         | 
| 29 | 
            +
                # The RPC often returns an empty String (<tt>""</tt>) as a value, when a
         | 
| 30 | 
            +
                # +nil+, or empty Array (<tt>[]</tt>), or empty Hash (<tt>{}</tt>) would be better.
         | 
| 31 | 
            +
                # If the response might be
         | 
| 32 | 
            +
                #
         | 
| 33 | 
            +
                # @param response the value returned from the RPC server
         | 
| 34 | 
            +
                # @param type the type to return an empty of
         | 
| 16 35 | 
             
                def self.coerce_empty_string_to_type(response, type)
         | 
| 17 36 | 
             
                  if response == "" || response.nil?
         | 
| 18 37 | 
             
                    return type.new
         | 
    
        data/lib/nanook/version.rb
    CHANGED
    
    
    
        data/lib/nanook/wallet.rb
    CHANGED
    
    | @@ -3,21 +3,42 @@ class Nanook | |
| 3 3 | 
             
              # The <tt>Nanook::Wallet</tt> class lets you manage your nano wallets,
         | 
| 4 4 | 
             
              # as well as some account-specific things like making and receiving payments.
         | 
| 5 5 | 
             
              #
         | 
| 6 | 
            -
              #  | 
| 7 | 
            -
              # | 
| 6 | 
            +
              # === Wallet seeds vs ids
         | 
| 7 | 
            +
              #
         | 
| 8 | 
            +
              # Your wallets each have an id as well as a seed. Both are 32-byte uppercase hex
         | 
| 9 | 
            +
              # strings that look like this:
         | 
| 8 10 | 
             
              #
         | 
| 9 11 | 
             
              #   000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F
         | 
| 10 12 | 
             
              #
         | 
| 11 | 
            -
              #  | 
| 12 | 
            -
              #  | 
| 13 | 
            -
              #  | 
| 14 | 
            -
              #  | 
| 15 | 
            -
              #  | 
| 16 | 
            -
              # your  | 
| 13 | 
            +
              # This class uses wallet _ids_ to identify your wallet. A wallet id only
         | 
| 14 | 
            +
              # exists locally on the nano node that it was created on. The person
         | 
| 15 | 
            +
              # who knows this id can only perform all read and write actions against
         | 
| 16 | 
            +
              # the wallet and all accounts inside the wallet from the same nano node
         | 
| 17 | 
            +
              # that it was created on. This makes wallet ids fairly safe to use as a
         | 
| 18 | 
            +
              # person needs to know your wallet id as well as have access to run
         | 
| 19 | 
            +
              # RPC commands against your nano node to be able to control your accounts.
         | 
| 20 | 
            +
              #
         | 
| 21 | 
            +
              # A _seed_ on the otherhand can be used to link any wallet to another
         | 
| 22 | 
            +
              # wallet's accounts, from anywhere in the nano network. This happens
         | 
| 23 | 
            +
              # by setting a wallet's seed to be the same as a previous wallet's seed.
         | 
| 24 | 
            +
              # When a wallet has the same seed as another wallet, any accounts
         | 
| 25 | 
            +
              # created in the second wallet will be the same accounts as those that were
         | 
| 26 | 
            +
              # created in the previous wallet, and the new wallet's owner will
         | 
| 27 | 
            +
              # also gain ownership of the previous wallet's accounts. Note, that the
         | 
| 28 | 
            +
              # two wallets will have different ids, but the same seed.
         | 
| 29 | 
            +
              #
         | 
| 30 | 
            +
              # Nanook is based on the Nano RPC, which uses wallet ids and not seeds.
         | 
| 31 | 
            +
              # The RPC and therefore Nanook cannot tell you what a wallet's seed is,
         | 
| 32 | 
            +
              # only its id. Knowing a wallet's seed is very useful for if you ever
         | 
| 33 | 
            +
              # want to restore the wallet anywhere else on the nano network besides
         | 
| 34 | 
            +
              # the node you originally created it on. The nano command line interface
         | 
| 35 | 
            +
              # (CLI) is the only method for discovering a wallet's seed. See the
         | 
| 36 | 
            +
              # {https://github.com/nanocurrency/raiblocks/wiki/Command-line-interface
         | 
| 37 | 
            +
              # --wallet_decrypt_unsafe CLI command}.
         | 
| 17 38 | 
             
              #
         | 
| 18 39 | 
             
              # === Initializing
         | 
| 19 40 | 
             
              #
         | 
| 20 | 
            -
              # Initialize this class through the convenient Nanook#wallet method:
         | 
| 41 | 
            +
              # Initialize this class through the convenient {Nanook#wallet} method:
         | 
| 21 42 | 
             
              #
         | 
| 22 43 | 
             
              #   nanook = Nanook.new
         | 
| 23 44 | 
             
              #   wallet = nanook.wallet(wallet_id)
         | 
| @@ -33,31 +54,37 @@ class Nanook | |
| 33 54 | 
             
                  @wallet = wallet
         | 
| 34 55 | 
             
                end
         | 
| 35 56 |  | 
| 36 | 
            -
                #  | 
| 37 | 
            -
                #  | 
| 57 | 
            +
                # Returns the given account in the wallet as a {Nanook::WalletAccount} instance
         | 
| 58 | 
            +
                # to let you start working with it.
         | 
| 38 59 | 
             
                #
         | 
| 39 | 
            -
                # | 
| 60 | 
            +
                # Call with no +account+ argument if you wish to create a new account
         | 
| 61 | 
            +
                # in the wallet, like this:
         | 
| 40 62 | 
             
                #
         | 
| 41 | 
            -
                #  | 
| 63 | 
            +
                #   wallet.account.create     # => Nanook::WalletAccount
         | 
| 42 64 | 
             
                #
         | 
| 43 | 
            -
                #  | 
| 65 | 
            +
                # See {Nanook::WalletAccount} for all the methods you can call on the
         | 
| 66 | 
            +
                # account object returned.
         | 
| 44 67 | 
             
                #
         | 
| 45 | 
            -
                # ====  | 
| 46 | 
            -
                # [+account+] Optional String of an account (starting with
         | 
| 47 | 
            -
                #             <tt>"xrb..."</tt>) to start working with. Must be an
         | 
| 48 | 
            -
                #             account within the wallet. When
         | 
| 49 | 
            -
                #             no account is given, the instance returned only allows you to call
         | 
| 50 | 
            -
                #             +create+ on it, to create a new account. Otherwise, you
         | 
| 51 | 
            -
                #             must pass an account string for all other methods.
         | 
| 68 | 
            +
                # ==== Examples:
         | 
| 52 69 | 
             
                #
         | 
| 53 | 
            -
                #  | 
| 70 | 
            +
                #   wallet.account("xrb_...") # => Nanook::WalletAccount
         | 
| 71 | 
            +
                #   wallet.account.create     # => Nanook::WalletAccount
         | 
| 54 72 | 
             
                #
         | 
| 55 | 
            -
                # | 
| 56 | 
            -
                #    | 
| 73 | 
            +
                # @param [String] account optional String of an account (starting with
         | 
| 74 | 
            +
                #   <tt>"xrb..."</tt>) to start working with. Must be an account within
         | 
| 75 | 
            +
                #   the wallet. When no account is given, the instance returned only
         | 
| 76 | 
            +
                #   allows you to call +create+ on it, to create a new account.
         | 
| 77 | 
            +
                # @raise [ArgumentError] if the wallet does no contain the account
         | 
| 78 | 
            +
                # @return [Nanook::WalletAccount]
         | 
| 57 79 | 
             
                def account(account=nil)
         | 
| 58 80 | 
             
                  Nanook::WalletAccount.new(@rpc, @wallet, account)
         | 
| 59 81 | 
             
                end
         | 
| 60 82 |  | 
| 83 | 
            +
                # Array of {Nanook::WalletAccount} instances of accounts in the wallet.
         | 
| 84 | 
            +
                #
         | 
| 85 | 
            +
                # See {Nanook::WalletAccount} for all the methods you can call on the
         | 
| 86 | 
            +
                # account objects returned.
         | 
| 87 | 
            +
                #
         | 
| 61 88 | 
             
                # ==== Example:
         | 
| 62 89 | 
             
                #
         | 
| 63 90 | 
             
                #   wallet.accounts # => [Nanook::WalletAccount, Nanook::WalletAccount...]
         | 
| @@ -71,21 +98,9 @@ class Nanook | |
| 71 98 | 
             
                  end
         | 
| 72 99 | 
             
                end
         | 
| 73 100 |  | 
| 74 | 
            -
                #  | 
| 75 | 
            -
                # wallet, optionally breaking the balances down by account.
         | 
| 76 | 
            -
                #
         | 
| 77 | 
            -
                # ==== Arguments
         | 
| 101 | 
            +
                # Balance of all accounts in the wallet, optionally breaking the balances down by account.
         | 
| 78 102 | 
             
                #
         | 
| 79 | 
            -
                #  | 
| 80 | 
            -
                #                         the response will contain balances per
         | 
| 81 | 
            -
                #                         account.
         | 
| 82 | 
            -
                # [+unit:+]   Symbol (default is +:nano+) Represents the unit that
         | 
| 83 | 
            -
                #             the balances will be returned in.
         | 
| 84 | 
            -
                #             Must be either +:nano+ or +:raw+. (Note: this method
         | 
| 85 | 
            -
                #             interprets +:nano+ as NANO, which is technically Mnano
         | 
| 86 | 
            -
                #             See {What are Nano's Units}[https://nano.org/en/faq#what-are-nano-units-])
         | 
| 87 | 
            -
                #
         | 
| 88 | 
            -
                # ==== Examples
         | 
| 103 | 
            +
                # ==== Examples:
         | 
| 89 104 | 
             
                #   wallet.balance
         | 
| 90 105 | 
             
                #
         | 
| 91 106 | 
             
                # Example response:
         | 
| @@ -122,6 +137,12 @@ class Nanook | |
| 122 137 | 
             
                #       "pending"=>0
         | 
| 123 138 | 
             
                #     },
         | 
| 124 139 | 
             
                #   }
         | 
| 140 | 
            +
                #
         | 
| 141 | 
            +
                # @param [Boolean] account_break_down (default is +false+). When +true+
         | 
| 142 | 
            +
                #  the response will contain balances per account.
         | 
| 143 | 
            +
                # @param unit (see Nanook::Account#balance)
         | 
| 144 | 
            +
                #
         | 
| 145 | 
            +
                # @return [Hash{Symbol=>Integer|Float|Hash}]
         | 
| 125 146 | 
             
                def balance(account_break_down: false, unit: Nanook.default_unit)
         | 
| 126 147 | 
             
                  wallet_required!
         | 
| 127 148 |  | 
| @@ -150,6 +171,10 @@ class Nanook | |
| 150 171 |  | 
| 151 172 | 
             
                # Changes a wallet's seed.
         | 
| 152 173 | 
             
                #
         | 
| 174 | 
            +
                # ==== Example:
         | 
| 175 | 
            +
                #
         | 
| 176 | 
            +
                #   wallet.change_seed("000D1BA...") # => true
         | 
| 177 | 
            +
                #
         | 
| 153 178 | 
             
                # @param seed [String] the seed to change to.
         | 
| 154 179 | 
             
                # @return [Boolean] indicating whether the change was successful.
         | 
| 155 180 | 
             
                def change_seed(seed)
         | 
| @@ -162,6 +187,10 @@ class Nanook | |
| 162 187 | 
             
                # The wallet will be created only on this node. It's important that
         | 
| 163 188 | 
             
                # if you intend to add funds to accounts in this wallet that you
         | 
| 164 189 | 
             
                # backup the wallet *seed* in order to restore the wallet in future.
         | 
| 190 | 
            +
                # The nano command line interface (CLI) is the only method for
         | 
| 191 | 
            +
                # backing up a wallet's seed. See the
         | 
| 192 | 
            +
                # {https://github.com/nanocurrency/raiblocks/wiki/Command-line-interface
         | 
| 193 | 
            +
                # --wallet_decrypt_unsafe CLI command}.
         | 
| 165 194 | 
             
                #
         | 
| 166 195 | 
             
                # ==== Example:
         | 
| 167 196 | 
             
                #   Nanook.new.wallet.create # => Nanook::Wallet
         | 
| @@ -172,11 +201,13 @@ class Nanook | |
| 172 201 | 
             
                  self
         | 
| 173 202 | 
             
                end
         | 
| 174 203 |  | 
| 175 | 
            -
                #  | 
| 176 | 
            -
                # | 
| 204 | 
            +
                # Destroys the wallet.
         | 
| 205 | 
            +
                #
         | 
| 206 | 
            +
                # ==== Example:
         | 
| 207 | 
            +
                #
         | 
| 208 | 
            +
                #   wallet.destroy # => true
         | 
| 177 209 | 
             
                #
         | 
| 178 | 
            -
                #  | 
| 179 | 
            -
                #   true
         | 
| 210 | 
            +
                # @return [Boolean] indicating success of the action
         | 
| 180 211 | 
             
                def destroy
         | 
| 181 212 | 
             
                  wallet_required!
         | 
| 182 213 | 
             
                  rpc(:wallet_destroy)
         | 
| @@ -185,80 +216,81 @@ class Nanook | |
| 185 216 |  | 
| 186 217 | 
             
                # Generates a String containing a JSON representation of your wallet.
         | 
| 187 218 | 
             
                #
         | 
| 188 | 
            -
                # ==== Example | 
| 219 | 
            +
                # ==== Example:
         | 
| 189 220 | 
             
                #
         | 
| 190 | 
            -
                #   "{\n    \"0000000000000000000000000000000000000000000000000000000000000000\": \"0000000000000000000000000000000000000000000000000000000000000003\",\n    \"0000000000000000000000000000000000000000000000000000000000000001\": \"C3A176FC3B90113277BFC91F55128FC9A1F1B6166A73E7446927CFFCA4C2C9D9\",\n    \"0000000000000000000000000000000000000000000000000000000000000002\": \"3E58EC805B99C52B4715598BD332C234A1FBF1780577137E18F53B9B7F85F04B\",\n    \"0000000000000000000000000000000000000000000000000000000000000003\": \"5FF8021122F3DEE0E4EC4241D35A3F41DEF63CCF6ADA66AF235DE857718498CD\",\n    \"0000000000000000000000000000000000000000000000000000000000000004\": \"A30E0A32ED41C8607AA9212843392E853FCBCB4E7CB194E35C94F07F91DE59EF\",\n    \"0000000000000000000000000000000000000000000000000000000000000005\": \"E707002E84143AA5F030A6DB8DD0C0480F2FFA75AB1FFD657EC22B5AA8E395D5\",\n    \"0000000000000000000000000000000000000000000000000000000000000006\": \"0000000000000000000000000000000000000000000000000000000000000001\",\n    \"8646C0423160DEAEAA64034F9C6858F7A5C8A329E73E825A5B16814F6CCAFFE3\": \"0000000000000000000000000000000000000000000000000000000100000000\"\n}\n"
         | 
| 221 | 
            +
                #   wallet.export # => "{\n    \"0000000000000000000000000000000000000000000000000000000000000000\": \"0000000000000000000000000000000000000000000000000000000000000003\",\n    \"0000000000000000000000000000000000000000000000000000000000000001\": \"C3A176FC3B90113277BFC91F55128FC9A1F1B6166A73E7446927CFFCA4C2C9D9\",\n    \"0000000000000000000000000000000000000000000000000000000000000002\": \"3E58EC805B99C52B4715598BD332C234A1FBF1780577137E18F53B9B7F85F04B\",\n    \"0000000000000000000000000000000000000000000000000000000000000003\": \"5FF8021122F3DEE0E4EC4241D35A3F41DEF63CCF6ADA66AF235DE857718498CD\",\n    \"0000000000000000000000000000000000000000000000000000000000000004\": \"A30E0A32ED41C8607AA9212843392E853FCBCB4E7CB194E35C94F07F91DE59EF\",\n    \"0000000000000000000000000000000000000000000000000000000000000005\": \"E707002E84143AA5F030A6DB8DD0C0480F2FFA75AB1FFD657EC22B5AA8E395D5\",\n    \"0000000000000000000000000000000000000000000000000000000000000006\": \"0000000000000000000000000000000000000000000000000000000000000001\",\n    \"8646C0423160DEAEAA64034F9C6858F7A5C8A329E73E825A5B16814F6CCAFFE3\": \"0000000000000000000000000000000000000000000000000000000100000000\"\n}\n"
         | 
| 191 222 | 
             
                def export
         | 
| 192 223 | 
             
                  wallet_required!
         | 
| 193 224 | 
             
                  rpc(:wallet_export)[:json]
         | 
| 194 225 | 
             
                end
         | 
| 195 226 |  | 
| 196 | 
            -
                #  | 
| 197 | 
            -
                #
         | 
| 198 | 
            -
                # ==== Arguments
         | 
| 227 | 
            +
                # Will return +true+ if the account exists in the wallet.
         | 
| 199 228 | 
             
                #
         | 
| 200 | 
            -
                #  | 
| 229 | 
            +
                # ==== Example:
         | 
| 230 | 
            +
                #   wallet.contains?("xrb_...") # => true
         | 
| 201 231 | 
             
                #
         | 
| 202 | 
            -
                #  | 
| 203 | 
            -
                # | 
| 232 | 
            +
                # @param account [String] id (will start with <tt>"xrb_..."</tt>)
         | 
| 233 | 
            +
                # @return [Boolean] indicating if the wallet contains the given account
         | 
| 204 234 | 
             
                def contains?(account)
         | 
| 205 235 | 
             
                  wallet_required!
         | 
| 206 236 | 
             
                  response = rpc(:wallet_contains, account: account)
         | 
| 207 237 | 
             
                  !response.empty? && response[:exists] == 1
         | 
| 208 238 | 
             
                end
         | 
| 209 239 |  | 
| 210 | 
            -
                # @return [String]
         | 
| 240 | 
            +
                # @return [String] the wallet id
         | 
| 211 241 | 
             
                def id
         | 
| 212 242 | 
             
                  @wallet
         | 
| 213 243 | 
             
                end
         | 
| 214 | 
            -
                alias_method :seed, :id
         | 
| 215 244 |  | 
| 216 245 | 
             
                # @return [String]
         | 
| 217 246 | 
             
                def inspect
         | 
| 218 247 | 
             
                  "#{self.class.name}(id: \"#{id}\", object_id: \"#{"0x00%x" % (object_id << 1)}\")"
         | 
| 219 248 | 
             
                end
         | 
| 220 249 |  | 
| 221 | 
            -
                #  | 
| 222 | 
            -
                # on the nano network. | 
| 223 | 
            -
                # if successful, or a {Nanook::Error} if unsuccessful.
         | 
| 250 | 
            +
                # Makes a payment from an account in your wallet to another account
         | 
| 251 | 
            +
                # on the nano network.
         | 
| 224 252 | 
             
                #
         | 
| 225 | 
            -
                # Note, there may be a delay in receiving a response due to Proof of | 
| 253 | 
            +
                # Note, there may be a delay in receiving a response due to Proof of
         | 
| 254 | 
            +
                # Work being done. From the {Nano RPC}[https://github.com/nanocurrency/raiblocks/wiki/RPC-protocol#account-create]:
         | 
| 226 255 | 
             
                #
         | 
| 227 | 
            -
                # <i>Proof of Work is precomputed for one transaction in the | 
| 256 | 
            +
                # <i>Proof of Work is precomputed for one transaction in the
         | 
| 257 | 
            +
                # background. If it has been a while since your last transaction it
         | 
| 258 | 
            +
                # will send instantly, the next one will need to wait for Proof of
         | 
| 259 | 
            +
                # Work to be generated.</i>
         | 
| 228 260 | 
             
                #
         | 
| 229 | 
            -
                # ==== Examples
         | 
| 261 | 
            +
                # ==== Examples:
         | 
| 230 262 | 
             
                #
         | 
| 231 263 | 
             
                #   wallet.pay(from: "xrb_...", to: "xrb_...", amount: 1.1, id: "myUniqueId123") # => "9AE2311..."
         | 
| 232 264 | 
             
                #   wallet.pay(from: "xrb_...", to: "xrb_...", amount: 54000000000000, unit: :raw, id: "myUniqueId123") # => "9AE2311..."
         | 
| 233 265 | 
             
                #
         | 
| 234 | 
            -
                # ==== Arguments
         | 
| 235 | 
            -
                #
         | 
| 236 266 | 
             
                # @param from [String] account id of an account in your wallet
         | 
| 237 267 | 
             
                # @param to (see Nanook::WalletAccount#pay)
         | 
| 238 268 | 
             
                # @param amount (see Nanook::WalletAccount#pay)
         | 
| 239 269 | 
             
                # @param unit (see Nanook::Account#balance)
         | 
| 240 270 | 
             
                # @params id (see Nanook::WalletAccount#pay)
         | 
| 241 271 | 
             
                # @return (see Nanook::WalletAccount#pay)
         | 
| 272 | 
            +
                # @raise [Nanook::Error] if unsuccessful
         | 
| 242 273 | 
             
                def pay(from:, to:, amount:, unit: Nanook.default_unit, id:)
         | 
| 243 274 | 
             
                  wallet_required!
         | 
| 244 275 | 
             
                  validate_wallet_contains_account!(from)
         | 
| 245 276 | 
             
                  account(from).pay(to: to, amount: amount, unit: unit, id: id)
         | 
| 246 277 | 
             
                end
         | 
| 247 278 |  | 
| 248 | 
            -
                #  | 
| 279 | 
            +
                # Information about pending blocks (payments) that are waiting
         | 
| 249 280 | 
             
                # to be received by accounts in this wallet.
         | 
| 250 281 | 
             
                #
         | 
| 251 | 
            -
                # See also the #receive method of this class for how to receive a pending payment.
         | 
| 282 | 
            +
                # See also the {#receive} method of this class for how to receive a pending payment.
         | 
| 252 283 | 
             
                #
         | 
| 253 284 | 
             
                # @param limit [Integer] number of accounts with pending payments to return (default is 1000)
         | 
| 254 285 | 
             
                # @param detailed [Boolean]return a more complex Hash of pending block information (default is +false+)
         | 
| 255 286 | 
             
                # @param unit (see Nanook::Account#balance)
         | 
| 256 287 | 
             
                #
         | 
| 257 | 
            -
                # ====  | 
| 288 | 
            +
                # ==== Examples:
         | 
| 258 289 | 
             
                #
         | 
| 259 290 | 
             
                #   wallet.pending
         | 
| 260 291 | 
             
                #
         | 
| 261 | 
            -
                #  | 
| 292 | 
            +
                # Example response:
         | 
| 293 | 
            +
                #
         | 
| 262 294 | 
             
                #   {
         | 
| 263 295 | 
             
                #     :xrb_1111111111111111111111111111111111111111111111111117353trpda=>[
         | 
| 264 296 | 
             
                #       "142A538F36833D1CC78B94E11C766F75818F8B940771335C6C1B8AB880C5BB1D",
         | 
| @@ -268,11 +300,13 @@ class Nanook | |
| 268 300 | 
             
                #       "4C1FEEF0BEA7F50BE35489A1233FE002B212DEA554B55B1B470D78BD8F210C74"
         | 
| 269 301 | 
             
                #     ]
         | 
| 270 302 | 
             
                #   }
         | 
| 271 | 
            -
                # | 
| 303 | 
            +
                #
         | 
| 304 | 
            +
                # Asking for more information:
         | 
| 272 305 | 
             
                #
         | 
| 273 306 | 
             
                #   wallet.pending(detailed: true)
         | 
| 274 307 | 
             
                #
         | 
| 275 | 
            -
                #  | 
| 308 | 
            +
                # Example response:
         | 
| 309 | 
            +
                #
         | 
| 276 310 | 
             
                #   {
         | 
| 277 311 | 
             
                #     :xrb_1111111111111111111111111111111111111111111111111117353trpda=>[
         | 
| 278 312 | 
             
                #       {
         | 
| @@ -332,14 +366,13 @@ class Nanook | |
| 332 366 | 
             
                # When called with no +block+ argument, the latest pending payment
         | 
| 333 367 | 
             
                # for the account will be received.
         | 
| 334 368 | 
             
                #
         | 
| 335 | 
            -
                # Returns a <i>receive</i> block hash
         | 
| 336 | 
            -
                #  | 
| 337 | 
            -
                # payments to receive.
         | 
| 369 | 
            +
                # Returns a <i>receive</i> block hash id if a receive was successful,
         | 
| 370 | 
            +
                # or +false+ if there were no pending payments to receive.
         | 
| 338 371 | 
             
                #
         | 
| 339 372 | 
             
                # You can receive a specific pending block if you know it by
         | 
| 340 373 | 
             
                # passing the block has in as an argument.
         | 
| 341 374 | 
             
                #
         | 
| 342 | 
            -
                # ==== Examples
         | 
| 375 | 
            +
                # ==== Examples:
         | 
| 343 376 | 
             
                #
         | 
| 344 377 | 
             
                #   wallet.receive(into: "xrb...")               # => "9AE2311..."
         | 
| 345 378 | 
             
                #   wallet.receive("718CC21...", into: "xrb...") # => "9AE2311..."
         | 
| @@ -354,7 +387,7 @@ class Nanook | |
| 354 387 | 
             
                  account(into).receive(block)
         | 
| 355 388 | 
             
                end
         | 
| 356 389 |  | 
| 357 | 
            -
                #  | 
| 390 | 
            +
                # Restores a previously created wallet by its seed.
         | 
| 358 391 | 
             
                # A new wallet will be created on your node (with a new wallet id)
         | 
| 359 392 | 
             
                # and will have its seed set to the given seed.
         | 
| 360 393 | 
             
                #
         | 
| @@ -381,11 +414,13 @@ class Nanook | |
| 381 414 | 
             
                  self
         | 
| 382 415 | 
             
                end
         | 
| 383 416 |  | 
| 384 | 
            -
                # Returns  | 
| 417 | 
            +
                # Returns +true+ if the wallet is locked.
         | 
| 385 418 | 
             
                #
         | 
| 386 | 
            -
                # ==== Example | 
| 419 | 
            +
                # ==== Example:
         | 
| 387 420 | 
             
                #
         | 
| 388 | 
            -
                #    | 
| 421 | 
            +
                #   wallet.locked? #=> false
         | 
| 422 | 
            +
                #
         | 
| 423 | 
            +
                # @return [Boolean] indicates if the wallet is locked
         | 
| 389 424 | 
             
                def locked?
         | 
| 390 425 | 
             
                  wallet_required!
         | 
| 391 426 | 
             
                  response = rpc(:wallet_locked)
         | 
| @@ -397,7 +432,8 @@ class Nanook | |
| 397 432 | 
             
                # ==== Example:
         | 
| 398 433 | 
             
                #
         | 
| 399 434 | 
             
                #   wallet.unlock("new_pass") #=> true
         | 
| 400 | 
            -
                # | 
| 435 | 
            +
                #
         | 
| 436 | 
            +
                # @return [Boolean] indicates if the unlocking action was successful
         | 
| 401 437 | 
             
                def unlock(password)
         | 
| 402 438 | 
             
                  wallet_required!
         | 
| 403 439 | 
             
                  rpc(:password_enter, password: password)[:valid] == 1
         |