# 使用web3.py与智能合约交互

By [Yooma](https://paragraph.com/@yooma) · 2022-12-26

---

**注：本篇文章交互用到的合约以及 infura 的创建与项目链接在**[**本篇文章**](https://mirror.xyz/0x450AF1Ea236932c0e18B53BC1FeB15E47AA292df/e3bgX7ufBgeiFex8Ht1A5ab7XU2-GlArWypqqGhT-_M)**中提到**

一：安装
----

二：使用
----

### 1：通过infura链接来与以太坊合约交互

![输出为True话代表链接成功](https://storage.googleapis.com/papyrus_images/6c246e28dae2d20e67990276abc4fa52a1cf6025f86fa117a9cedc5d0c9ffcb0.png)

输出为True话代表链接成功

infura截图

![ https://<your-provider-url>](https://storage.googleapis.com/papyrus_images/1e354f188fd50d1fbaf665b5090a75940b55e13d14741208fef135cb8e7c7780.png)

https://<your-provider-url>

连接成功之后我们把[本篇文章](https://mirror.xyz/0x450AF1Ea236932c0e18B53BC1FeB15E47AA292df/e3bgX7ufBgeiFex8Ht1A5ab7XU2-GlArWypqqGhT-_M)中的abi与部署的合约地址用到这里

abi文件（rent\_nft\_test.json）在 brownie\_test/build/contracts 中

那么如何获取到该合约中发生得mint/transfer等信息

    from web3 import Web3
    import json
    
    # 首先通过infura节点链接
    w3=Web3(Web3.HTTPProvider('https://<your-provider-url>'))
    
    # 合约abi文件
    with open('./brownie_test/build/contracts/ERC4907.json', 'r') as f:
        abi_contract = json.loads(f.read())['abi']
    
    # 与infura节点链接成功后 指定address以及abi与该合约建立连接
    # address是合约地址 abi是该合约对应的abi
    my_contract = w3.eth.contract(address='0xADD22a3efa6f22dd60DF65CDfE096da0366eE002', abi=abi_contract)
    
    # 现在来测试获取到的该合约的信息
    # ownerOf是合约中定义的方法，获取tokenId为1的owner地址，通过functions来调用它
    print('token_id 1 owner: 'my_contract.functions.ownerOf(1).call())
    
    # result
    >>> token_id 1 owner: 0x60EA96f57B3a5715A90DAe1440a78f8bb339C92e
    # 这个地址是在我部署该合约时mint tokenId为1的nft的钱包地址
    # 证明获取该合约信息成功
    

上面获取合约信息成功，下面来给合约进行一次mint事件

    接上面代码：
    
    # 要给address去mint一个nft
    address = '0x60EA96f57B3a5715A90DAe1440a78f8bb339C92e
    
    # 生成nonce
    nonce = w3.eth.getTransactionCount(address)
    
    # mint token id 为 2 的nft，
    # 通过functions调用mint
    

![合约代码中mint](https://storage.googleapis.com/papyrus_images/2cd75aa20352a951230d5c1884c2c80ac728c188b77c20f64a41bfd806706351.png)

合约代码中mint

    
    # buildTransaction构建交易字典，以此来传入合约中需要接受得msg.sender（address）
    mint = my_contract.functions.mint(2).build_transaction({'from': address, 'nonce': nonce})
    
    # 签名
    sign = w3.eth.account.sign_transaction(mint, '钱包地址私钥，在metamask查看')
    
    # 给链上发送这次mint
    w3.eth.send_raw_transaction(sign.rawTransaction)
    

关于nonce：

为了防止交易重播，ETH（ETC）节点要求每笔交易必须有一个nonce数值。每一个账户从同一个节点发起交易时，这个nonce值从0开始计数，发送一笔nonce对应加1。当前面的nonce处理完成之后才会处理后面的nonce。

在 send\_raw\_transaction 后去[goerli测试官网](https://goerli.etherscan.io/)查看该合约会有一次新的mint记录

![](https://storage.googleapis.com/papyrus_images/adc34073df2def0790725377c6cf4d0f46eac424eefdc57d5f0a3bb7ea8ef49e.png)

![](https://storage.googleapis.com/papyrus_images/f0855a832dd102c6443fb9d83bdf908b862138af229b1e3ec6f50ae85799c99c.png)

再来测试下给该nft设定一个user（租赁此nft的用户）

![](https://storage.googleapis.com/papyrus_images/d8231aeadf4733e48f5add1194e055eedb6293e69888d57cca404563cbd16681.png)

python：就像发送一次mint请求一样来setUser

    from web3 import Web3
    import json
    
    # 首先通过infura节点链接
    w3=Web3(Web3.HTTPProvider('https://<your-provider-url>'))
    
    # 合约abi文件
    with open('./brownie_test/build/contracts/ERC4907.json', 'r') as f:
        abi_contract = json.loads(f.read())['abi']
    
    # 与infura节点链接成功后 指定address以及abi与该合约建立连接
    # address是合约地址 abi是该合约对应的abi
    my_contract = w3.eth.contract(address='0xADD22a3efa6f22dd60DF65CDfE096da0366eE002', abi=abi_contract)
    
    # nft owner
    address = '0x60EA96f57B3a5715A90DAe1440a78f8bb339C92e
    
    # 生成nonce
    nonce = w3.eth.getTransactionCount(address)
    # 上面代码与上方的一样
    
    # 通过chain.time(来获取链上时间)
    from brownie import chain
    
    # 调用setUser 给传入接收的值只有这里与mint是有区别的
    # 1: nft tokenId  
    # 0x450AF1Ea236932c0e18B53BC1FeB15E47AA292df user地址
    # 到期时间
    # 到期后这个nft user地址自动清零
    x = my_contract.functions.setUser(1, '0x450AF1Ea236932c0e18B53BC1FeB15E47AA292df', 10*60+chain.time()).build_transaction({'from': address, 'nonce': nonce})
    
    signed_txn = w3.eth.account.sign_transaction(x, '钱包地址私钥，在metamask查看')
    
    w3.eth.send_raw_transaction(signed_txn.rawTransaction)
    

[以太坊goerli测试网官网查看数据](https://goerli.etherscan.io/address/0x2a4f14bf2933e7849c8c393a24d3b420138233f8)

![会看到这里有一条我们刚刚setUser的数据](https://storage.googleapis.com/papyrus_images/c8e21920ccf0e2c71fb47704369621c0c9354b969a9b55a2d825c81b0a15e09f.png)

会看到这里有一条我们刚刚setUser的数据

此时在代码中查看下tokenId是1的nft的user

    print(my_contract.functions.userOf(1).call())
    
    # result
    >>>0x450AF1Ea236932c0e18B53BC1FeB15E47AA292df
    

以上是使用web3.py与智能合约交互的方式，流程如此，如需进行Transfer事件或获取其他信息可以修改mint，ownerOf等（合约中定义的function以及event），也可以查阅[官方文档](https://web3py.readthedocs.io/en/stable/quickstart.html)找到更多的操作。

---

*Originally published on [Yooma](https://paragraph.com/@yooma/web3-py)*
