Class: ERC20::FakeWallet

Inherits:
Object
  • Object
show all
Includes:
Checks
Defined in:
lib/erc20/fake_wallet.rb

Overview

A fake wallet that behaves like a ERC20::Wallet.

It rejects exactly what the real wallet rejects, so that a broken private key, address, or amount fails in a test the same way it would fail with a real provider, where money is at stake.

Author

Yegor Bugayenko (yegor256@gmail.com)

Copyright

Copyright (c) 2025 Yegor Bugayenko

License

MIT

Constant Summary collapse

TXN_HASH =
'0x172de9cda30537eae68ab4a96163ebbb8f8a85293b8737dd2e5deb4714b14623'

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeFakeWallet

Ctor.



27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/erc20/fake_wallet.rb', line 27

def initialize
  @host = 'example.com'
  @port = 443
  @ssl = true
  @chain = 1
  @contract = ERC20::Wallet::USDT
  @ws_path = '/'
  @http_path = '/'
  @history = []
  @balances = {}
  @eth_balances = {}
end

Instance Attribute Details

#chainObject (readonly)

Returns the value of attribute chain.



24
25
26
# File 'lib/erc20/fake_wallet.rb', line 24

def chain
  @chain
end

#contractObject (readonly)

Returns the value of attribute contract.



24
25
26
# File 'lib/erc20/fake_wallet.rb', line 24

def contract
  @contract
end

#historyObject (readonly)

Returns the value of attribute history.



24
25
26
# File 'lib/erc20/fake_wallet.rb', line 24

def history
  @history
end

#hostObject (readonly)

Returns the value of attribute host.



24
25
26
# File 'lib/erc20/fake_wallet.rb', line 24

def host
  @host
end

#http_pathObject (readonly)

Returns the value of attribute http_path.



24
25
26
# File 'lib/erc20/fake_wallet.rb', line 24

def http_path
  @http_path
end

#portObject (readonly)

Returns the value of attribute port.



24
25
26
# File 'lib/erc20/fake_wallet.rb', line 24

def port
  @port
end

#sslObject (readonly)

Returns the value of attribute ssl.



24
25
26
# File 'lib/erc20/fake_wallet.rb', line 24

def ssl
  @ssl
end

#ws_pathObject (readonly)

Returns the value of attribute ws_path.



24
25
26
# File 'lib/erc20/fake_wallet.rb', line 24

def ws_path
  @ws_path
end

Instance Method Details

#accept(addresses, active = [], raw: false, delay: 1, subscription_id: rand(1..99_999)) ⇒ Object

Wait and accept.

Parameters:

  • addresses (Array<String>)

    Addresses to monitor

  • active (Array) (defaults to: [])

    List of addresses that we are actually listening to

  • raw (Boolean) (defaults to: false)

    TRUE if you need to get JSON events as they arrive from Websockets

  • delay (Numeric) (defaults to: 1)

    How many seconds to wait between eth_subscribe calls

  • subscription_id (Integer) (defaults to: rand(1..99_999))

    Unique ID of the subscription



160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# File 'lib/erc20/fake_wallet.rb', line 160

def accept(addresses, active = [], raw: false, delay: 1, subscription_id: rand(1..99_999))
  to_addresses(addresses)
  to_active(active)
  to_delay(delay)
  to_subscription(subscription_id)
  @history << { method: :accept, addresses:, active:, raw:, delay:, subscription_id: }
  addresses.to_a.each { |a| active.append(a) }
  loop do
    sleep(delay)
    to_addresses(addresses)
    a = addresses.to_a.sample
    next if a.nil?
    yield(
      if raw
        {}
      else
        {
          amount: 424_242,
          block: 42,
          from: '0xd5ff1bfcde7a03da61ad229d962c74f1ea2f16a5',
          index: 0,
          to: a,
          txn: TXN_HASH
        }
      end
    )
  end
end

#balance(address) ⇒ Integer

Get ERC20 balance of a public address.

Parameters:

  • address (String)

    Public key, in hex, starting from '0x'

Returns:

  • (Integer)

    Balance, in tokens



58
59
60
61
62
63
# File 'lib/erc20/fake_wallet.rb', line 58

def balance(address)
  to_address(address)
  b = @balances[address] || 42_000_000
  @history << { method: :balance, address:, result: b }
  b
end

#eth_balance(address) ⇒ Integer

Get ETH balance of a public address.

Parameters:

  • address (String)

    Public key, in hex, starting from '0x'

Returns:

  • (Integer)

    Balance, in tokens



69
70
71
72
73
74
# File 'lib/erc20/fake_wallet.rb', line 69

def eth_balance(address)
  to_address(address)
  b = @eth_balances[address] || 77_000_000_000_000_000
  @history << { method: :eth_balance, address:, result: b }
  b
end

#eth_pay(priv, address, amount, price: gas_price) ⇒ String

Send a single ETH payment from a private address to a public one.

Parameters:

  • priv (String)

    Private key, in hex

  • address (String)

    Public key, in hex

  • amount (Integer)

    The amount of ETHs to send

  • price (Integer) (defaults to: gas_price)

    The most you pay per computation unit, in wei

Returns:

  • (String)

    Transaction hash



143
144
145
146
147
148
149
150
151
# File 'lib/erc20/fake_wallet.rb', line 143

def eth_pay(priv, address, amount, price: gas_price)
  to_priv(priv)
  to_address(address)
  to_amount(amount)
  to_price(price)
  hex = TXN_HASH
  @history << { method: :eth_pay, priv:, address:, amount:, price:, result: hex }
  hex
end

#gas_estimate(from, to, amount) ⇒ Integer

How many gas units are required to send an ERC20 transaction.

Parameters:

  • from (String)

    The departing address, in hex

  • to (String)

    Arriving address, in hex

  • amount (Integer)

    How many ERC20 tokens to send

Returns:

  • (Integer)

    How many gas units required



95
96
97
98
99
100
101
102
# File 'lib/erc20/fake_wallet.rb', line 95

def gas_estimate(from, to, amount)
  to_address(from)
  to_address(to)
  to_amount(amount)
  gas = 66_000
  @history << { method: :gas_estimate, from:, to:, amount:, result: gas }
  gas
end

#gas_priceInteger

What is the price of gas unit in wei?

The unit is the same as in ERC20::Wallet#gas_price: a price in gwei would be a billion times smaller and would make every fee computed in a test look affordable, while in production it wouldn't be.

Returns:

  • (Integer)

    Price of gas unit, in wei (1 gwei = 0.000000001 ETH)



111
112
113
114
115
# File 'lib/erc20/fake_wallet.rb', line 111

def gas_price
  wei = 55_555_000_000
  @history << { method: :gas_price, result: wei }
  wei
end

#pay(priv, address, amount, limit: nil, price: gas_price) ⇒ String

Send a single ERC20 payment from a private address to a public one.

Parameters:

  • priv (String)

    Private key, in hex

  • address (String)

    Public key, in hex

  • amount (Integer)

    The amount of ERC20 tokens to send

  • limit (Integer) (defaults to: nil)

    Optional gas limit

  • price (Integer) (defaults to: gas_price)

    The most you pay per computation unit, in wei

Returns:

  • (String)

    Transaction hash



125
126
127
128
129
130
131
132
133
134
# File 'lib/erc20/fake_wallet.rb', line 125

def pay(priv, address, amount, limit: nil, price: gas_price)
  to_priv(priv)
  to_address(address)
  to_amount(amount)
  to_limit(limit) if limit
  to_price(price)
  hex = TXN_HASH
  @history << { method: :pay, priv:, address:, amount:, limit:, price:, result: hex }
  hex
end

#set_balance(address, tokens) ⇒ Object

Set balance, to be returned by the balance().

Parameters:

  • address (String)

    Public key, in hex, starting from '0x'

  • tokens (Integer)

    How many tokens to put there



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

def set_balance(address, tokens)
  @balances[address] = tokens
end

#set_eth_balance(address, wei) ⇒ Object

Set balance, to be returned by the balance().

Parameters:

  • address (String)

    Public key, in hex, starting from '0x'

  • wei (Integer)

    How many wei to put there



50
51
52
# File 'lib/erc20/fake_wallet.rb', line 50

def set_eth_balance(address, wei)
  @eth_balances[address] = wei
end

#sum_of(txn, to: nil) ⇒ Integer

Get ERC20 amount (in tokens) that was sent in the given transaction.

Parameters:

  • txn (String)

    Hex of transaction

  • to (String) (defaults to: nil)

    Public key of the receiver, in hex, starting from '0x'

Returns:

  • (Integer)

    Amount, in ERC20 tokens



81
82
83
84
85
86
87
# File 'lib/erc20/fake_wallet.rb', line 81

def sum_of(txn, to: nil)
  to_txn(txn)
  to_address(to) unless to.nil?
  tokens = 42_000_000
  @history << { method: :sum_of, txn:, to:, result: tokens }
  tokens
end