lib/nanook/wallet.rb in nanook-1.0.2 vs lib/nanook/wallet.rb in nanook-2.0.0
- old
+ new
@@ -18,16 +18,16 @@
# === Initializing
#
# Initialize this class through the convenient Nanook#wallet method:
#
# nanook = Nanook.new
- # wallet = nanook.wallet(wallet_seed)
+ # wallet = nanook.wallet(wallet_id)
#
# Or compose the longhand way like this:
#
# rpc_conn = Nanook::Rpc.new
- # wallet = Nanook::Wallet.new(rpc_conn, wallet_seed)
+ # wallet = Nanook::Wallet.new(rpc_conn, wallet_id)
class Wallet
def initialize(rpc, wallet)
@rpc = rpc
@wallet = wallet
@@ -56,22 +56,21 @@
# wallet.account(account_id) # Returns a Nanook::WalletAccount for the account
def account(account=nil)
Nanook::WalletAccount.new(@rpc, @wallet, account)
end
- # Returns an Array with Strings of all account ids in the wallet.
+ # ==== Example:
#
- # ==== Example response
+ # wallet.accounts # => [Nanook::WalletAccount, Nanook::WalletAccount...]
#
- # [
- # "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000",
- # "xrb_1e5aqegc1jb7qe964u4adzmcezyo6o146zb8hm6dft8tkp79za3sxwjym5rx"
- # ]
+ # @return [Array<Nanook::WalletAccount>] all accounts in the wallet
def accounts
wallet_required!
response = rpc(:account_list)[:accounts]
- Nanook::Util.coerce_empty_string_to_type(response, Array)
+ Nanook::Util.coerce_empty_string_to_type(response, Array).map do |account|
+ Nanook::WalletAccount.new(@rpc, @wallet, account)
+ end
end
# Returns a Hash containing the balance of all accounts in the
# wallet, optionally breaking the balances down by account.
#
@@ -121,14 +120,14 @@
# "xrb_1e5aqegc1jb7qe964u4adzmcezyo6o146zb8hm6dft8tkp79za3sxwjym5rx"=>{
# "balance"=>51.4,
# "pending"=>0
# },
# }
- def balance(account_break_down: false, unit: Nanook::WalletAccount::DEFAULT_UNIT)
+ def balance(account_break_down: false, unit: Nanook.default_unit)
wallet_required!
- unless Nanook::WalletAccount::UNITS.include?(unit)
+ unless Nanook::UNITS.include?(unit)
raise ArgumentError.new("Unsupported unit: #{unit}")
end
if account_break_down
return Nanook::Util.coerce_empty_string_to_type(rpc(:wallet_balances)[:balances], Hash).tap do |r|
@@ -147,35 +146,32 @@
r[:pending] = Nanook::Util.raw_to_NANO(r[:pending])
end
end
end
+ # Changes a wallet's seed.
+ #
+ # @param seed [String] the seed to change to.
+ # @return [Boolean] indicating whether the change was successful.
+ def change_seed(seed)
+ wallet_required!
+ rpc(:wallet_change_seed, seed: seed).has_key?(:success)
+ end
+
# Creates a new wallet.
#
- # Nanook.new.wallet.create
+ # The wallet will be created only on this node. It's important that
+ # if you intend to add funds to accounts in this wallet that you
+ # backup the wallet *seed* in order to restore the wallet in future.
#
- # ==== Very important
+ # ==== Example:
+ # Nanook.new.wallet.create # => Nanook::Wallet
#
- # <b>Please read this.</b> The response of this method is a wallet seed. A seed is
- # a 32-byte uppercase hex string. You can think of this string as your
- # API key to the nano network. The person who knows it can do all read and write
- # actions against the wallet and all accounts inside the wallet from
- # anywhere on the nano network, not just on the node you created the
- # wallet on.
- #
- # If you intend for your wallet to contain funds, then make sure that
- # you consider the seed that is returned as the key to your funds
- # and store it somewhere secret and safe. Only transmit
- # the seed over secure (SSH or SSL) networks and do not store it where
- # it is able to be easily comprised by a hacker, which includes your
- # personal computer.
- #
- # ==== Example response:
- #
- # "CC2C9846A44DB6F0363F647D12B957794AD937F59498D4E35C172C81E2888650"
+ # @return [Nanook::Wallet]
def create
- rpc(:wallet_create)[:wallet]
+ @wallet = rpc(:wallet_create)[:wallet]
+ self
end
# Destroy the wallet. Returns a boolean indicating whether the action
# was successful or not.
#
@@ -212,12 +208,13 @@
end
def id
@wallet
end
+ alias_method :seed, :id
- def inspect # :nodoc:
+ def inspect
"#{self.class.name}(id: \"#{id}\", object_id: \"#{"0x00%x" % (object_id << 1)}\")"
end
# Make a payment from an account in your wallet to another account
# on the nano network. Returns a <i>send</i> block hash if successful,
@@ -250,16 +247,98 @@
# "718CC2121C3E641059BC1C2CFC45666C99E8AE922F7A807B7D07B62C995D79E2"
#
# Or:
#
# "Account not found"
- def pay(from:, to:, amount:, unit: Nanook::WalletAccount::DEFAULT_UNIT, id:)
+ def pay(from:, to:, amount:, unit: Nanook.default_unit, id:)
wallet_required!
validate_wallet_contains_account!(from)
account(from).pay(to: to, amount: amount, unit: unit, id: id)
end
+ # Returns information about pending blocks (payments) that are waiting
+ # to be received by accounts in this wallet.
+ #
+ # See also the #receive method of this class for how to receive a pending payment.
+ #
+ # @param limit [Integer] number of accounts with pending payments to return (default is 1000)
+ # @param detailed [Boolean]return a more complex Hash of pending block information (default is +false+)
+ # @param unit (see Nanook::Account#balance)
+ #
+ # ==== Example 1:
+ #
+ # wallet.pending
+ #
+ # ==== Example 1 response:
+ # {
+ # :xrb_1111111111111111111111111111111111111111111111111117353trpda=>[
+ # "142A538F36833D1CC78B94E11C766F75818F8B940771335C6C1B8AB880C5BB1D",
+ # "718CC2121C3E641059BC1C2CFC45666C99E8AE922F7A807B7D07B62C995D79E2"
+ # ],
+ # :xrb_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3=>[
+ # "4C1FEEF0BEA7F50BE35489A1233FE002B212DEA554B55B1B470D78BD8F210C74"
+ # ]
+ # }
+ # ==== Example 2:
+ #
+ # wallet.pending(detailed: true)
+ #
+ # ==== Example 2 response:
+ # {
+ # :xrb_1111111111111111111111111111111111111111111111111117353trpda=>[
+ # {
+ # :amount=>6.0,
+ # :source=>"xrb_3dcfozsmekr1tr9skf1oa5wbgmxt81qepfdnt7zicq5x3hk65fg4fqj58mbr",
+ # :block=>:"142A538F36833D1CC78B94E11C766F75818F8B940771335C6C1B8AB880C5BB1D"
+ # },
+ # {
+ # :amount=>12.0,
+ # :source=>"xrb_3dcfozsmekr1tr9skf1oa5wbgmxt81qepfdnt7zicq5x3hk65fg4fqj58mbr",
+ # :block=>:"242A538F36833D1CC78B94E11C766F75818F8B940771335C6C1B8AB880C5BB1D"
+ # }
+ # ],
+ # :xrb_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3=>[
+ # {
+ # :amount=>106.370018,
+ # :source=>"xrb_13ezf4od79h1tgj9aiu4djzcmmguendtjfuhwfukhuucboua8cpoihmh8byo",
+ # :block=>:"4C1FEEF0BEA7F50BE35489A1233FE002B212DEA554B55B1B470D78BD8F210C74"
+ # }
+ # ]
+ # }
+ def pending(limit:1000, detailed:false, unit:Nanook.default_unit)
+ wallet_required!
+
+ unless Nanook::UNITS.include?(unit)
+ raise ArgumentError.new("Unsupported unit: #{unit}")
+ end
+
+ params = { count: limit }
+ params[:source] = true if detailed
+
+ response = rpc(:wallet_pending, params)[:blocks]
+ response = Nanook::Util.coerce_empty_string_to_type(response, Hash)
+
+ return response unless detailed
+
+ # Map the RPC response, which is:
+ # account=>block=>[amount|source] into
+ # account=>[block|amount|source]
+ x = response.map do |account, data|
+ new_data = data.map do |block, amount_and_source|
+ d = amount_and_source.merge(block: block.to_s)
+ if unit == :nano
+ d[:amount] = Nanook::Util.raw_to_NANO(d[:amount])
+ end
+ d
+ end
+
+ [account, new_data]
+ end
+
+ Hash[x].to_symbolized_hash
+ end
+
# Receives a pending payment into an account in the wallet.
#
# When called with no +block+ argument, the latest pending payment
# for the account will be received.
#
@@ -292,10 +371,37 @@
wallet_required!
validate_wallet_contains_account!(into)
account(into).receive(block)
end
+ # Restore a previously created wallet by its seed.
+ # A new wallet will be created on your node (with a new wallet id)
+ # and will have its seed set to the given seed.
+ #
+ # ==== Example:
+ #
+ # Nanook.new.wallet.restore(seed) # => Nanook::Wallet
+ #
+ # @param seed [String] the wallet seed to restore.
+ # @param accounts [Integer] optionally restore the given number of accounts for the wallet.
+ #
+ # @return [Nanook::Wallet] a new wallet
+ # @raise [Nanook::Error] if unsuccessful
+ def restore(seed, accounts:0)
+ create
+
+ unless change_seed(seed)
+ raise Nanook::Error.new("Unable to set seed for wallet")
+ end
+
+ if accounts > 0
+ account.create(accounts)
+ end
+
+ self
+ end
+
# Returns a boolean to indicate if the wallet is locked.
#
# ==== Example response
#
# true
@@ -303,26 +409,26 @@
wallet_required!
response = rpc(:wallet_locked)
!response.empty? && response[:locked] != 0
end
- # Unlocks a previously locked wallet. Returns a boolean to indicate
- # if the action was successful.
+ # Unlocks a previously locked wallet.
#
- # ==== Example response
+ # ==== Example:
#
- # true
+ # wallet.unlock("new_pass") #=> true
+ # @return [Boolean] indicates if the action was successful
def unlock(password)
wallet_required!
rpc(:password_enter, password: password)[:valid] == 1
end
- # Changes the password for a wallet. Returns a boolean to indicate
- # if the action was successful.
+ # Changes the password for a wallet.
#
- # ==== Example response
+ # ==== Example:
#
- # true
+ # wallet.change_password("new_pass") #=> true
+ # @return [Boolean] indicates if the action was successful
def change_password(password)
wallet_required!
rpc(:password_change, password: password)[:changed] == 1
end