之前使用trufle console 进行了合约交互,其实如果使用python或者js的话,也有相应的类库

python:https://web3py.readthedocs.io/

JavaScript:https://web3js.readthedocs.io/

实现的目标

  • 链接测试eth网络
  • 测试基本信息
  • 实现eth网络间转账
  • 实现eth指定地址转账
  • 和eth智能合约进行交互

链接eth测试网络

先测试下链接

1
2
3
4
5
6
7
from web3 import Web3

w3 = Web3(Web3.HTTPProvider("http://127.0.0.1:7545"))

print(w3.isConnected())

# True

输出 True ,那么就是成功的。这里的http://127.0.0.1:7545 是我使用Ganache来运行在本地的eth网络环境。你也可以使用 https://infura.io/ 这类线上的环境。

跑起来之后,可以看到我的默认第一个区块的账号是

0x0374AD83DfEB8cfD94889631255AE43B2Aa93bbe

1
2
3
4
5
6
# 运行代码的时候,默认币地址就是你的第一个地址
from web3 import Web3

w3 = Web3(Web3.HTTPProvider("http://127.0.0.1:7545"))

print(w3.eth.coinbase)

查看账户余额

测试查看制定账户的余额,我这里的指定账户为默认账号。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from web3 import Web3

w3 = Web3(Web3.HTTPProvider("http://127.0.0.1:7545"))

# 输出该区块的账号信息
# print(w3.eth.get_accounts())
# 输出有多少余额,这里单位需要转换,将wei单位转为ether单位
# getBalance 默认返回的是 wei的单位
# https://web3py.readthedocs.io/en/latest/examples.html#checking-the-balance-of-an-account
blance = w3.eth.getBalance("0x0374AD83DfEB8cfD94889631255AE43B2Aa93bbe")

trans_blance = w3.fromWei(blance, 'ether')

print(trans_blance)
# 9.96

进行转账

我从默认地址0x0374AD83DfEB8cfD94889631255AE43B2Aa93bbe转账到第二个地址0x13d2F0AB715924cdaF9623F155275CEdA55819EE

具体看这个API https://web3py.readthedocs.io/en/latest/web3.eth.html?highlight=sendTransaction#web3.eth.Eth.sendTransaction 进行转账

from:从哪个地址转出,默认是 web3.eth.defaultAccount

to:接受转账的地址

value: 默认为 wei 需要对wei进行转化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
from web3 import Web3


w3 = Web3(Web3.HTTPProvider("http://127.0.0.1:7545"))

from_address = '0x13d2F0AB715924cdaF9623F155275CEdA55819EE'
to_address = '0x969bB21356157B614d1c473eb012826eb9cDca84'

print('before trans from_address blance:',
w3.fromWei(w3.eth.getBalance(from_address), 'ether'))

tx_hash = w3.eth.send_transaction({
'from': from_address,
'to': to_address,
'value': w3.toWei('1', 'ether')
})

print('trans hash:', w3.toHex(tx_hash))


# get blance
to_address_blance = w3.eth.getBalance(to_address)
from_address_blance = w3.eth.getBalance(from_address)

print('from_adderss', w3.fromWei(from_address_blance, 'ether'))
print('to_address', w3.fromWei(to_address_blance, 'ether'))

之后会输出如下的信息: 转账前是:95,之后是:94,转账的账号余额为6

1
2
3
4
before trans from_address blance: 95.997060045
trans hash: 0x80a7b2e0191fa86a619aeba241d15db09d15f787ad77df51f65cc7212d4e7798
from_adderss 94.996640045
to_address 6

成功之后就可以看到转账的信息。通过ganache可以看到转账的区块信息。

使用签名进行转账

一直很奇怪,在本地可以不用私钥直接转帐。。。按道理应该是需要私钥才能转账,回头可以试试线上的测试版本。

以下就是使用签名进行转账,如果把private_key1 改成另外一个错误的,即转账就失败了

私钥的话,可以使用ganache 进行查看

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
from web3 import Web3

web3 = Web3(Web3.HTTPProvider("http://127.0.0.1:7545"))

account1 = web3.eth.accounts[0]
private_key1 = 'a175f272c0ef9944268c724dfa0d3e278d9bc0ebb1ed47c082d71f94063e5d0b'
account2 = web3.eth.accounts[1]

# nonce 是一个随机数,为了避免重放攻击
nonce = web3.eth.getTransactionCount(account1)
print(nonce)
tx = {
'nonce': nonce,
'to': account2,
'value': web3.toWei(1, 'ether'),
'gas': 2000000,
'gasPrice': web3.toWei('50', 'gwei')
}


signed_tx = web3.eth.account.sign_transaction(tx, private_key1)

print(signed_tx)

tx_hash = web3.eth.sendRawTransaction(signed_tx.rawTransaction)

print(web3.toHex(tx_hash))

与智能合约进行交互

之前部署了metacoin,所以直接准备调用metacoin的方法来测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
from web3 import Web3, HTTPProvider
import json

web3 = Web3(HTTPProvider("http://127.0.0.1:7545"))

contract_address = '0x10BD02647FE442dA2E86D4b05a4aaEC24464314E'

from_address = '0x0374AD83DfEB8cfD94889631255AE43B2Aa93bbe'
to_address = '0x13d2F0AB715924cdaF9623F155275CEdA55819EE'

# read json
with open('./MetaCoin.json', 'r') as f:
contract_json = json.load(f)


contract_instance = web3.eth.contract(
address=contract_address, abi=contract_json['abi'])


print(contract_instance.address)


print(contract_instance.functions.getBalance(
from_address).call())
print(contract_instance.functions.getBalance(
to_address).call())

print(web3.toHex(contract_instance.functions.sendCoin(to_address, 1).transact(
{'from': from_address})))