Class: NanoAccount

Inherits:
Object
  • Object
show all
Defined in:
lib/account.rb

Overview

A Nano account which has an address and a blockchain.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(address, public_key = nil, private_key = nil, representative = nil) ⇒ NanoAccount

Create a new NanoAccount instance representing an existing account. public_key and private_key are optional, but without them the account is immutable. Params:

address

The address of the account.

public_key

(Optional) The public key of the account.

private_key

(Optional) The private key of the account.

representative

(Optional) This block’s representative. Required only if the account must be opened.



20
21
22
23
24
25
# File 'lib/account.rb', line 20

def initialize(address, public_key=nil, private_key=nil, representative=nil)
    @address = address
    @public_key = public_key
    @private_key = private_key
    @representative = representative || address
end

Instance Attribute Details

#addressObject

Returns the value of attribute address.



11
12
13
# File 'lib/account.rb', line 11

def address
  @address
end

#private_keyObject

Returns the value of attribute private_key.



11
12
13
# File 'lib/account.rb', line 11

def private_key
  @private_key
end

#public_keyObject

Returns the value of attribute public_key.



11
12
13
# File 'lib/account.rb', line 11

def public_key
  @public_key
end

Class Method Details

.generate(representative = nil) ⇒ Object

Generate a new Nano account and return a mutable NanoAccount instance for it. Params:

representative

(Optional) This account’s representative. Set to the account itself if not specified.

Returns: A NanoAccount instance for the new account.



32
33
34
35
36
37
38
39
40
# File 'lib/account.rb', line 32

def self.generate(representative=nil)
    result = NanoConfiguration.client.key_create
    NanoAccount.new(
        result["account"],
        result["public"],
        result["private"],
        representative
    ) 
end

Instance Method Details

#balanceObject

The balance of the account, not including unpocketed transactions.



179
180
181
# File 'lib/account.rb', line 179

def balance
    NanoConfiguration.client.(account: @address)["balance"]
end

#block_countObject

The number of blocks on this account’s chain.



56
57
58
59
60
61
62
63
64
65
# File 'lib/account.rb', line 56

def block_count
    begin
        NanoConfiguration.client.(account: @address)["block_count"].to_i
    rescue => error
        # Unopened accounts appear to throw instead
        raise if error.message != "Account not found"

        return 0
    end
end

#mutable?Boolean

A boolean indicating whether public_key and private_key are specified.

Returns:

  • (Boolean)


43
44
45
# File 'lib/account.rb', line 43

def mutable?
    @private_key != nil && @public_key != nil
end

#pending_balanceObject

The unpocketed balance of the account.



184
185
186
# File 'lib/account.rb', line 184

def pending_balance
    NanoConfiguration.client.(account: @address)["pending"]
end

#pending_transactionsObject

The list of pending transactions for this account.



48
49
50
51
52
53
# File 'lib/account.rb', line 48

def pending_transactions
    res = NanoConfiguration.client.accounts_pending(accounts: [ @address ])["blocks"][@address]
    res = [] if res == nil

    res
end

#pocketObject

Scan for any pending transactions on this chain and generate ‘receive’ or ‘open’ blocks for them. Requires that this account is mutable. Returns: A boolean indicating whether any transactions were pocketed or not.



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/account.rb', line 71

def pocket
    raise ImmutableAccountError unless mutable?

    # Get pending transactions
    pending = pending_transactions

    return false if pending.length == 0

    # Determine whether the first processed transaction must be an 'open' block
    block_type = (block_count == 0 ? "open" : "receive")
    
    pending.each do |pending_hash|
        # NOTE: This is using implicit PoW
        if block_type == "open"
            # Work against the public key
            work = NanoConfiguration.client.work_generate({
                hash: @public_key
            })["work"]

            # Create a block for this 'open' transaction
            block = NanoConfiguration.client.block_create({
                type: block_type,
                key: @private_key,
                account: @address,
                representative: @representative,
                source: pending_hash,
                work: work
            })["block"]

            # Since this block was an 'open', ensure that the next one is a 'receive'
            block_type = "receive"
        else
            # Get the frontier of this chain
            frontier = NanoConfiguration.client.({
                account: @address,
                count: 1
            })["frontier"]

            # Work against the frontier
            work = NanoConfiguration.client.work_generate({
                hash: frontier
            })["work"]

            # Create a block for this 'receive' transaction 
            block = NanoConfiguration.client.block_create({
                type: block_type,
                key: @private_key,
                account: @address,
                source: pending_hash,
                previous: frontier,
                work: work
            })["block"]
        end

        print "Block is: "
        p block

        # Publish the new block
        NanoConfiguration.client.process(block: block)
    end

    true
end

#send(amount, recipient) ⇒ Object

Send an amount of Nano to another address. Params:

amount

The amount of raw Nano to send.

recipient

The recipient account of the Nano, as a string or NanoAccount.



139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/account.rb', line 139

def send(amount, recipient)
    raise ImmutableAccountError unless mutable?

    if recipient.is_a?(String)
        recipient = NanoAccount.new(recipient)
    end

    # Get the frontier of this chain
    frontier = NanoConfiguration.client.({
        account: @address,
        count: 1
    })["frontier"]

    # Work against the frontier
    work = NanoConfiguration.client.work_generate({
        hash: frontier
    })["work"]

    # Create a 'send' block
    block = NanoConfiguration.client.block_create({
        type: "send",
        key: @private_key,
        account: @address,
        destination: recipient.address,
        previous: frontier,
        work: work,
        amount: amount.to_i.to_s,
        balance: balance
    })["block"]

    # Publish the block
    NanoConfiguration.client.process(block: block)
end

#total_balanceObject

The total balance of the account, including unpocketed balances.



174
175
176
# File 'lib/account.rb', line 174

def total_balance
    balance + pending_balance
end