草庐IT

Python--web3区块链-智能合约测试

ZongXin.Zhou 2023-10-22 原文

提示:阅读该文章建议先了解什么是智能合约。

一、智能合约python基础

1、连接环境

# web3对象与已部署的用户合约进行通信
rpc = "HTTP合约通讯地址(http url)" 
web3 = Web3(HTTPProvider(rpc))

2、区块相关

# 当前区块高度
blockNumber = web3.eth.blockNumber
print(blockNumber)
# 获取最新的区块
block = web3.eth.getBlock('latest')
print(block)
# 输出默认区块
print(web3.eth.defaultBlock)

3、账户相关

# 将第一个测试账户设置为默认账户
web3.eth.defaultAccount = web3.eth.accounts[0:1]
# 输出默认账户
print(web3.eth.defaultAccount)
# 获取账号信息
accounts = web3.eth.accounts
print("账户列表:", accounts)
# 获取当前gas的价格
print(web3.eth.gasPrice)
address1 = "你的钱包地址"
# 获取eth余额
balance1 = web3.fromWei(web3.eth.getBalance(address1), "ether")
print(balance1)

二、智能合约ABI简易介绍

ABI官方链接

“合约ABI是以太坊生态系统中与合约交互的标准方式,不论是外部客户端与合约的交互还是合约与合约之间的交互。”上述是以太坊官方文档给出的定义,更通俗的理解,包含两方面内容:
ABI是合约接口的说明。
ABI定义与合约进行交互数据编码规则

在测试合约接口的时候我们会用到

三、测试合约前提

1、熟悉项目业务层逻辑

2、开发提供智能合约接口文档

1)、确认我们要在那个链上测试,让开发提供对应的测试币
(2)、提供测试地址(类似于web2的url)
(3)、提供最新合约地址(这个地址开发每次部署到链上都会变更)
(4)、提供ABI(合约接口的说明)如果开发不给可以在eth区块链浏览器上获得
(5)、我们自己测试钱包的秘钥

四、智能合约转账(单元脚本)

from web3 import Web3, HTTPProvider
import json, os

rpc = "HTTP合约通讯地址(http url)"
address1 = "个人合约地址"
address2 = "智能合约地址"
test_key = "个人钱包秘钥地址"

# 连接钱包地址
web3 = Web3(HTTPProvider(rpc))

# 结果为true表示连接成功
connect = web3.isConnected()
print(connect)

# 转账
def transfer_eth(amount, gas_price=20, gas_limit=21000):
    # 带签名的合约写操作
    params = {
        # 发送代币地址
        'from': address1,
        # 接收代币的地址
        'to': address2,

        # 代币数量,以wei为单位,可以是字符串和int类型 web3.toWei(数值,代币单位)
        # 为了方便调通代码,我们这里用wei来做单位,正常都是用ether。
        # 1 ether = 1 x 10^18wei = 1 x 10^9 Gwei
        'value': web3.toWei(amount, 'wei'),

        # 每个在链上可以执行的命令都设置了一个消耗的gas值,例:PUSH操作需要消耗3个gas,一次转账一般要消耗21000 gas,gas使用ether来支付
        # 1 ether = 1 x 10^18wei = 1 x 10^9 Gwei, 无论您执行的命令是成功还是失败,都需要支付计算费用
        # 简易理解:gas_limit 是一次交易中gas的可用上限
        'gas': gas_limit,

        # 通过gasPrice可以节省矿工费用,但也会减慢矿工打包的速度。因为,矿工会优先打包gas price设置高的交易,如果您想加快转账,您可以把gas price设置得更高,这样您就可以插队靠前
        # 一次转账一般要消耗21000 gas,如果你设置的gas Price = 1000000000wei = 1Gwei,则此次转账的交易手续费为:TxFee = 21000 Gwei = 0.000021 ether
        # A账户欲向B账户转账4 ether,则要求A账户至少要有 4 + 0.000021 = 4. 000021 ethrer
        # 简易理解:gasPrice就是你想用多少气费进行交易,为什么设置20,是因为当前市场价20就够了。如果你有钱,想更快也可以设置成25甚至更高
        'gasPrice': web3.toWei(gas_price, 'gwei'),

        # 'nonce': web3.eth.getTransactionCount(主钱包地址),主要标记当前最新的交易号是多少,算是记录在交易队列中的位置
        'nonce': web3.eth.getTransactionCount(address1),
    }
    # web3.eth.account.signTransaction用账户对交易签名(转账需要的参数,from钱包地址的秘钥)
    signed_tx = web3.eth.account.signTransaction(params, private_key=test_key)

    # 交易发送并获取交易hash
    tx_hash = web3.eth.sendRawTransaction(signed_tx.rawTransaction)
    return tx_hash


print("运行转账后的交易hash值:", transfer_eth(100))

执行完代码,我们就可以去etherscan上根据钱包地址查看交易数据了

五、获取智能合约接口数据(单元脚本)

(1)、把ABI放到任意目录下

(2)、编写单元测试脚本
from web3 import Web3, HTTPProvider
import json, os

rpc = "HTTP合约通讯地址(http url)"
address = "智能合约地址"

# 连接钱包地址
web3 = Web3(HTTPProvider(rpc))

# 结果为true表示连接成功
connect = web3.isConnected()
print(connect)

# 获取ABI存放地址
filePath = os.path.dirname(__file__) + '/abi.json'

# 这里是读取咱们的abi合约接口规范,方便后面使用
with open(filePath, 'r') as f:
    abi = json.load(f)

# 官方文档:创建一个新的契约实例及其在json接口对象中定义的所有方法和事件
# 官方文档:该web3.eth.Contract对象可以轻松地与以太坊区块链上的智能合约进行交互。
# 个人理解:创建与合约交互的对象,连接完通讯地址后,我们对这地址签订合同,合同里面有合约地址和接口规范(ABI)
# web3.eth.contract(接口文档的合约地址, ABI接口规范)
contract = web3.eth.contract(address=address, abi=abi)

# 通过合约.功能.调用接口方法(传参数).获取返回值
# contract.functions.接口方法名(参数1,参数2,参数3).call()
res = contract.functions.getLastMintInfo(10).call()
print("getLastMintInfo:", res)

获取结果

六、mint智能合约接口数据(单元脚本)

from web3 import Web3, HTTPProvider
import json, os


rpc = "HTTP合约通讯地址(http url)"
address1 = "个人合约地址"
address2 = "智能合约地址"
test_key = "个人钱包秘钥地址"

# 连接钱包地址
web3 = Web3(HTTPProvider(rpc))

# 结果为true表示连接成功
connect = web3.isConnected()
print(connect)

# 获取ABI存放地址
filePath = os.path.dirname(__file__) + '/abi.json'

# 这里是读取咱们的abi合约接口规范,方便后面使用
with open(filePath, 'r') as f:
    abi = json.load(f)

# 个人理解:创建与合约交互的对象,连接完通讯地址后,我们对这地址签订合同,合同里面有合约地址和接口规范(ABI)
# web3.eth.contract(接口文档的合约地址, ABI接口规范)
contract = web3.eth.contract(address=address2, abi=abi)

# 通过合约功能.调用接口方法(传递mint方法的入参).创建交易参数({key:value})
transaction = contract.functions.mint(1).buildTransaction({
    'gas': 70000,  # 最大气费上限
    'gasPrice': web3.toWei('20', 'gwei'),  # 气费
    'from': address1,  # 接受地址
    'value': web3.toWei('0.01', 'ether'),  # mint多少eth
    'nonce': web3.eth.getTransactionCount(address1),  # 当前第几个交易
})
# web3.eth.account.signTransaction用账户对交易签名(转账需要的参数,from钱包地址的秘钥)
signed_tx = web3.eth.account.signTransaction(transaction, private_key=test_key)
# 交易发送并获取交易hash
tx_hash = web3.eth.sendRawTransaction(signed_tx.rawTransaction)
print(tx_hash)

有关Python--web3区块链-智能合约测试的更多相关文章

  1. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  2. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  3. ruby - 使用 C 扩展开发 ruby​​gem 时,如何使用 Rspec 在本地进行测试? - 2

    我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当

  4. ruby - Ruby 的 Hash 在比较键时使用哪种相等性测试? - 2

    我有一个围绕一些对象的包装类,我想将这些对象用作散列中的键。包装对象和解包装对象应映射到相同的键。一个简单的例子是这样的:classAattr_reader:xdefinitialize(inner)@inner=innerenddefx;@inner.x;enddef==(other)@inner.x==other.xendenda=A.new(o)#oisjustanyobjectthatallowso.xb=A.new(o)h={a=>5}ph[a]#5ph[b]#nil,shouldbe5ph[o]#nil,shouldbe5我试过==、===、eq?并散列所有无济于事。

  5. ruby - RSpec - 使用测试替身作为 block 参数 - 2

    我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere

  6. ruby - Sinatra:运行 rspec 测试时记录噪音 - 2

    Sinatra新手;我正在运行一些rspec测试,但在日志中收到了一堆不需要的噪音。如何消除日志中过多的噪音?我仔细检查了环境是否设置为:test,这意味着记录器级别应设置为WARN而不是DEBUG。spec_helper:require"./app"require"sinatra"require"rspec"require"rack/test"require"database_cleaner"require"factory_girl"set:environment,:testFactoryGirl.definition_file_paths=%w{./factories./test/

  7. ruby-on-rails - 迷你测试错误 : "NameError: uninitialized constant" - 2

    我遵循MichaelHartl的“RubyonRails教程:学习Web开发”,并创建了检查用户名和电子邮件长度有效性的测试(名称最多50个字符,电子邮件最多255个字符)。test/helpers/application_helper_test.rb的内容是:require'test_helper'classApplicationHelperTest在运行bundleexecraketest时,所有测试都通过了,但我看到以下消息在最后被标记为错误:ERROR["test_full_title_helper",ApplicationHelperTest,1.820016791]test

  8. ruby - 即使失败也继续进行多主机测试 - 2

    我已经构建了一些serverspec代码来在多个主机上运行一组测试。问题是当任何测试失败时,测试会在当前主机停止。即使测试失败,我也希望它继续在所有主机上运行。Rakefile:namespace:specdotask:all=>hosts.map{|h|'spec:'+h.split('.')[0]}hosts.eachdo|host|begindesc"Runserverspecto#{host}"RSpec::Core::RakeTask.new(host)do|t|ENV['TARGET_HOST']=hostt.pattern="spec/cfengine3/*_spec.r

  9. ruby-on-rails - 如何使辅助方法在 Rails 集成测试中可用? - 2

    我在app/helpers/sessions_helper.rb中有一个帮助程序文件,其中包含一个方法my_preference,它返回当前登录用户的首选项。我想在集成测试中访问该方法。例如,这样我就可以在测试中使用getuser_path(my_preference)。在其他帖子中,我读到这可以通过在测试文件中包含requiresessions_helper来实现,但我仍然收到错误NameError:undefinedlocalvariableormethod'my_preference'.我做错了什么?require'test_helper'require'sessions_hel

  10. ruby-on-rails - Cucumber 是否只是 rspec 的包装器以帮助将测试组织成功能? - 2

    只是想确保我理解了事情。据我目前收集到的信息,Cucumber只是一个“包装器”,或者是一种通过将事物分类为功能和步骤来组织测试的好方法,其中实际的单元测试处于步骤阶段。它允许您根据事物的工作方式组织您的测试。对吗? 最佳答案 有点。它是一种组织测试的方式,但不仅如此。它的行为就像最初的Rails集成测试一样,但更易于使用。这里最大的好处是您的session在整个Scenario中保持透明。关于Cucumber的另一件事是您(应该)从使用您的代码的浏览器或客户端的角度进行测试。如果您愿意,您可以使用步骤来构建对象和设置状态,但通常您

随机推荐