Module: EthTool
- Defined in:
- lib/eth_tool.rb,
lib/eth_tool/version.rb
Constant Summary collapse
- VERSION =
"0.1.5"
Class Attribute Summary collapse
-
.logger ⇒ Object
Returns the value of attribute logger.
Class Method Summary collapse
- .airdrop(private_key, airdrop_contract_address, token_contract_address, addresses, values, gas_limit, gas_price) ⇒ Object
- .build_airdrop_data(token_contract_address, addresses, values) ⇒ Object
- .confirmations(txhash) ⇒ Object
- .confirmed?(txhash, number) ⇒ Boolean
-
.dec_to_hex(value) ⇒ Object
helper methods #########################################################.
-
.estimate_gas(to, data) ⇒ Object
def self.wputs(text) File.open(‘/Users/wuminzhe/Projects/eth_tool/scripts/fuck.txt’, ‘a’) { |f| f.puts(text) } end.
- .fee(gas_limit, gas_price) ⇒ Object
-
.fill_eth(private_key, to, amount, gas_limit = 60000, gas_price = 5_000_000_000) ⇒ Object
目标地址上需要填充满这么多eth amount = BigDecimal(gas_limit) * BigDecimal(gas_price) / 10**18.
- .generate_addresses_from_xprv(xprv, amount) ⇒ Object
- .generate_raw_transaction(private_key, value, data, gas_limit, gas_price = nil, to = nil, nonce = nil) ⇒ Object
- .get_eth_balance(address) ⇒ Object
- .get_private_key_from_keystore(dir, address, passphrase) ⇒ Object
- .get_private_key_from_xprv(xprv, index) ⇒ Object
- .get_token_balance(address, token_contract_address, token_decimals) ⇒ Object
- .mined?(txhash) ⇒ Boolean
- .padding(str) ⇒ Object
- .rpc ⇒ Object
- .rpc=(url) ⇒ Object
- .sweep_eth(private_key, to, gas_limit = 60000, gas_price = 5_000_000_000) ⇒ Object
-
.sweep_token(private_key, token_contract_address, token_decimals, to, gas_limit = 60000, gas_price = 5_000_000_000) ⇒ Object
sweep.
- .token_transfer_success?(txhash) ⇒ Boolean
- .transfer_eth(private_key, amount, gas_limit, gas_price, to) ⇒ Object
- .transfer_token(private_key, token_contract_address, token_decimals, amount, gas_limit, gas_price, to, nonce = nil) ⇒ Object
- .tx_replace(private_key, txhash, gas_price) ⇒ Object
- .wait_for_miner(txhash, timeout: 1200, step: 20) ⇒ Object
Class Attribute Details
.logger ⇒ Object
Returns the value of attribute logger.
22 23 24 |
# File 'lib/eth_tool.rb', line 22 def logger @logger end |
Class Method Details
.airdrop(private_key, airdrop_contract_address, token_contract_address, addresses, values, gas_limit, gas_price) ⇒ Object
88 89 90 91 92 93 94 |
# File 'lib/eth_tool.rb', line 88 def self.airdrop(private_key, airdrop_contract_address, token_contract_address, addresses, values, gas_limit, gas_price) data = build_airdrop_data(token_contract_address, addresses, values) rawtx = generate_raw_transaction(private_key, 0, data, gas_limit, gas_price, airdrop_contract_address) @@rpc.eth_send_raw_transaction(rawtx) end |
.build_airdrop_data(token_contract_address, addresses, values) ⇒ Object
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/eth_tool.rb', line 72 def self.build_airdrop_data(token_contract_address, addresses, values) data = "0xad8733ca" data = data + padding(token_contract_address) data = data + "0000000000000000000000000000000000000000000000000000000000000060" data = data + "0000000000000000000000000000000000000000000000000000000000001840" data = data + "00000000000000000000000000000000000000000000000000000000000000be" addresses.each do |address| data = data + padding(address.downcase) end data = data + "00000000000000000000000000000000000000000000000000000000000000be" values.each do |value| data = data + padding(value.to_i.to_s(16)) end return data end |
.confirmations(txhash) ⇒ Object
215 216 217 218 219 220 221 222 223 |
# File 'lib/eth_tool.rb', line 215 def self.confirmations(txhash) tx = @@rpc.eth_get_transaction_by_hash(txhash)["result"] return 0 unless (tx and (not tx['blockNumber'].nil?)) block_number = tx['blockNumber'].to_i(16) current_block_number = @@rpc.eth_block_number["result"].to_i(16) current_block_number - block_number end |
.confirmed?(txhash, number) ⇒ Boolean
203 204 205 206 207 208 209 210 211 212 213 |
# File 'lib/eth_tool.rb', line 203 def self.confirmed?(txhash, number) tx = @@rpc.eth_get_transaction_by_hash(txhash)["result"] return false unless (tx and (not tx['blockNumber'].nil?)) block_number = tx['blockNumber'].to_i(16) current_block_number = @@rpc.eth_block_number["result"].to_i(16) confirmations = current_block_number - block_number confirmations >= number end |
.dec_to_hex(value) ⇒ Object
helper methods #########################################################
237 238 239 |
# File 'lib/eth_tool.rb', line 237 def self.dec_to_hex(value) '0x'+value.to_s(16) end |
.estimate_gas(to, data) ⇒ Object
def self.wputs(text)
File.open('/Users/wuminzhe/Projects/eth_tool/scripts/fuck.txt', 'a') { |f| f.puts(text) }
end
68 69 70 |
# File 'lib/eth_tool.rb', line 68 def self.estimate_gas(to, data) @@rpc.eth_estimate_gas({to: to, data: data})["result"].to_i(16) end |
.fee(gas_limit, gas_price) ⇒ Object
17 18 19 |
# File 'lib/eth_tool.rb', line 17 def self.fee(gas_limit, gas_price) BigDecimal(gas_limit) * BigDecimal(gas_price) / 10**18.to_f end |
.fill_eth(private_key, to, amount, gas_limit = 60000, gas_price = 5_000_000_000) ⇒ Object
目标地址上需要填充满这么多eth amount = BigDecimal(gas_limit) * BigDecimal(gas_price) / 10**18
139 140 141 142 143 144 145 146 |
# File 'lib/eth_tool.rb', line 139 def self.fill_eth(private_key, to, amount, gas_limit=60000, gas_price=5_000_000_000) # 目标地址上现有eth eth_balance = get_eth_balance(to) return unless eth_balance < amount # 如果有足够多的eth,就直接返回 transfer_eth(private_key, (amount-eth_balance), gas_limit, gas_price, to) end |
.generate_addresses_from_xprv(xprv, amount) ⇒ Object
173 174 175 176 177 178 179 180 181 |
# File 'lib/eth_tool.rb', line 173 def self.generate_addresses_from_xprv(xprv, amount) result = [] wallet = Bip44::Wallet.from_xprv(xprv) amount.times do |i| sub_wallet = wallet.sub_wallet("m/#{i}") result << sub_wallet.ethereum_address end result end |
.generate_raw_transaction(private_key, value, data, gas_limit, gas_price = nil, to = nil, nonce = nil) ⇒ Object
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/eth_tool.rb', line 40 def self.generate_raw_transaction(private_key, value, data, gas_limit, gas_price = nil, to = nil, nonce = nil) key = ::Eth::Key.new priv: private_key address = key.address gas_price_in_dec = gas_price.nil? ? @@rpc.eth_gas_price["result"].to_i(16) : gas_price nonce = nonce.nil? ? @@rpc.eth_get_transaction_count(address, 'pending')["result"].to_i(16) : nonce args = { from: address, value: 0, data: '0x0', nonce: nonce, gas_limit: gas_limit, gas_price: gas_price_in_dec } args[:value] = (value * 10**18).to_i if value args[:data] = data if data args[:to] = to if to tx = Eth::Tx.new(args) tx.sign key tx.hex end |
.get_eth_balance(address) ⇒ Object
35 36 37 38 |
# File 'lib/eth_tool.rb', line 35 def self.get_eth_balance(address) result = @@rpc.eth_get_balance(address)['result'].to_i(16) BigDecimal(result) / BigDecimal(10**18) end |
.get_private_key_from_keystore(dir, address, passphrase) ⇒ Object
163 164 165 166 167 168 169 170 171 |
# File 'lib/eth_tool.rb', line 163 def self.get_private_key_from_keystore(dir, address, passphrase) path = File.join(dir, '*') Dir[path].each do |file| if file.end_with?(address[2..-1]) key = ::Eth::Key.decrypt(File.read(file), passphrase) return key.private_key.to_hex end end end |
.get_private_key_from_xprv(xprv, index) ⇒ Object
183 184 185 186 187 |
# File 'lib/eth_tool.rb', line 183 def self.get_private_key_from_xprv(xprv, index) wallet = Bip44::Wallet.from_xprv(xprv) sub_wallet = wallet.sub_wallet("m/#{index}") return sub_wallet.private_key, sub_wallet.ethereum_address end |
.get_token_balance(address, token_contract_address, token_decimals) ⇒ Object
28 29 30 31 32 33 |
# File 'lib/eth_tool.rb', line 28 def self.get_token_balance(address, token_contract_address, token_decimals) data = '0x70a08231' + padding(address) # Ethereum::Function.calc_id('balanceOf(address)') # 70a08231 result = @@rpc.eth_call({to: token_contract_address, data: data})['result'].to_i(16) BigDecimal(result) / BigDecimal(10**token_decimals) end |
.mined?(txhash) ⇒ Boolean
198 199 200 201 |
# File 'lib/eth_tool.rb', line 198 def self.mined?(txhash) tx = @@rpc.eth_get_transaction_by_hash(txhash)["result"] tx and (not tx['blockNumber'].nil?) end |
.padding(str) ⇒ Object
241 242 243 244 245 246 |
# File 'lib/eth_tool.rb', line 241 def self.padding(str) if str =~ /^0x[a-f0-9]*/ str = str[2 .. str.length-1] end str.rjust(64, '0') end |
.rpc ⇒ Object
13 14 15 |
# File 'lib/eth_tool.rb', line 13 def self.rpc @@rpc end |
.rpc=(url) ⇒ Object
9 10 11 |
# File 'lib/eth_tool.rb', line 9 def self.rpc=(url) @@rpc = Ethereum::HttpClient.new(url) end |
.sweep_eth(private_key, to, gas_limit = 60000, gas_price = 5_000_000_000) ⇒ Object
127 128 129 130 131 132 133 134 135 |
# File 'lib/eth_tool.rb', line 127 def self.sweep_eth(private_key, to, gas_limit=60000, gas_price=5_000_000_000) address = ::Eth::Key.new(priv: private_key).address eth_balance = get_eth_balance(address) # 转eth不能都转,要留一点作为gas费用 keep = BigDecimal(gas_limit) * BigDecimal(gas_price) / 10**18 amount = eth_balance - keep return if amount <= 0 transfer_eth(private_key, amount, gas_limit, gas_price, to) end |
.sweep_token(private_key, token_contract_address, token_decimals, to, gas_limit = 60000, gas_price = 5_000_000_000) ⇒ Object
sweep
120 121 122 123 124 125 |
# File 'lib/eth_tool.rb', line 120 def self.sweep_token(private_key, token_contract_address, token_decimals, to, gas_limit=60000, gas_price=5_000_000_000) address = ::Eth::Key.new(priv: private_key).address token_balance = get_token_balance(address, token_contract_address, token_decimals) return if token_balance == 0 transfer_token(private_key, token_contract_address, token_decimals, token_balance, gas_limit, gas_price, to) end |
.token_transfer_success?(txhash) ⇒ Boolean
225 226 227 228 229 230 231 232 233 |
# File 'lib/eth_tool.rb', line 225 def self.token_transfer_success?(txhash) tx = @@rpc.eth_get_transaction_by_hash(txhash)["result"] return false unless (tx and (not tx['blockNumber'].nil?)) receipt = @@rpc.eth_get_transaction_receipt(txhash)["result"] return false unless receipt return false if (receipt['status'] && receipt['status'] == '0x0') end |
.transfer_eth(private_key, amount, gas_limit, gas_price, to) ⇒ Object
110 111 112 113 114 115 116 117 |
# File 'lib/eth_tool.rb', line 110 def self.transfer_eth(private_key, amount, gas_limit, gas_price, to) if amount < (1.0/10**18) logger.info "转账金额不能小于以太坊最小单位" return end rawtx = generate_raw_transaction(private_key, amount, nil, gas_limit, gas_price, to) @@rpc.eth_send_raw_transaction(rawtx) end |
.transfer_token(private_key, token_contract_address, token_decimals, amount, gas_limit, gas_price, to, nonce = nil) ⇒ Object
96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/eth_tool.rb', line 96 def self.transfer_token(private_key, token_contract_address, token_decimals, amount, gas_limit, gas_price, to, nonce=nil) if amount < (1.0/10**token_decimals) logger.info "转账金额不能小于精度最小单位(#{token_contract_address}, #{token_decimals})" return end # 生成raw transaction amount_in_wei = (amount * (10**token_decimals)).to_i data = '0xa9059cbb' + padding(to) + padding(dec_to_hex(amount_in_wei)) # Ethereum::Function.calc_id('transfer(address,uint256)') # a9059cbb rawtx = generate_raw_transaction(private_key, 0, data, gas_limit, gas_price, token_contract_address, nonce) @@rpc.eth_send_raw_transaction(rawtx) end |
.tx_replace(private_key, txhash, gas_price) ⇒ Object
148 149 150 151 152 153 154 155 156 157 158 159 160 161 |
# File 'lib/eth_tool.rb', line 148 def self.tx_replace(private_key, txhash, gas_price) tx = @@rpc.eth_get_transaction_by_hash(txhash)["result"] return if tx.nil? value = tx["value"].to_i(16) data = tx["input"] gas_limit = tx["gas"].to_i(16) gas_price = gas_price to = tx["to"] nonce = tx["nonce"].to_i(16) rawtx = generate_raw_transaction(private_key, value, data, gas_limit, gas_price, to, nonce) @@rpc.eth_send_raw_transaction(rawtx) end |
.wait_for_miner(txhash, timeout: 1200, step: 20) ⇒ Object
189 190 191 192 193 194 195 196 |
# File 'lib/eth_tool.rb', line 189 def self.wait_for_miner(txhash, timeout: 1200, step: 20) start_time = Time.now loop do raise Timeout::Error if ((Time.now - start_time) > timeout) return true if mined?(txhash) sleep step end end |