# web3py第三课：游戏脚本编写 & 不开源合约调用 

By [ourens.eth](https://paragraph.com/@ourens) · 2022-01-02

---

终于到了大家心心念念的游戏脚本编写的教程了，今天我会以前段时间比较火的游戏“掰手腕”为例子，来教大家如何写一个游戏脚本。

教程
--

无论哪个游戏，我们要写脚本，都是要先进行一下交互，看自己的交互记录来写脚本。

这里我展示一下我的一次fight记录：

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

从这个记录中，我们可以得到很多信息。比如游戏的合约地址、方法名、参数名、参数值。

其实知道这些就可以写脚本了，但是我们还需要ABI才可以进行调用，如果我们打开合约的源代码看到的这是这样：

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

这说明该合约没有开源，所以无法看到合约的源代码，这时候我们要怎么寻找ABI呢？

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

如果你学习过智能合约的一些知识，可能会发现，网站（DAPP）也是通过ABI+web3.js跟智能合约做交互，我们web3py也是一样的道理。所以这些游戏网站都会有ABI来让你调用，也就是说我们去扒一扒网站的源代码即可！

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

通过搜索，在网站的源代码中很容易可以找到。如果JS比较多，需要一个一个看。如果你用safari浏览器可以全局搜索，Chrome好像要一个一个的去找一下。

然后ABI一般都非常长，我们如果只用一个fight方法，完全可以只取这一段：

    [{"inputs":[{"internalType":"uint256","name":"armzId","type":"uint256"},{"internalType":"uint256","name":"boss","type":"uint256"}],"name":"fight","outputs":[],"stateMutability":"nonpayable","type":"function"}]
    

这一段ABI就只包含了fight一个方法，你在寻找ABI的时候注意核对一下inputs参数是否对应你之前的交互记录里面的参数，一定做到完全匹配再用。

完整的交互fight方法如下：

    from web3 import Web3, HTTPProvider
    
    contract_address = ''  # 智能合约地址
    contract_abi = ''  # ABI
    private_key = ''
    address = ''
    token_id = 112233
    rpc = 'https://bsc-dataseed1.binance.org:443'
    web3 = Web3(HTTPProvider(rpc))
    
    arms_contract = web3.eth.contract(address=contract_address, abi=contract_abi)
    func = arms_contract.functions.fight(token_id, 0)
    nonce = web3.eth.getTransactionCount(address)
    params = {
        "from": address,
        "value": web3.toWei(0, 'ether'),
        'gasPrice': web3.toWei(5, 'gwei'),
        "gas": 500000,
        "nonce": nonce,
    }
    try:
        tx = func.buildTransaction(params)
        signed_tx = web3.eth.account.sign_transaction(tx, private_key=private_key)
        tx_hash = web3.eth.sendRawTransaction(signed_tx.rawTransaction)
        print(f'战斗成功：{tx_hash.hex()}')
    except Exception as e:
        print(f'战斗失败', e)
    

然后我们聊一下两个参数，第一个参数就是你参与战斗的NFT的TokenID，这个你在区块链浏览器就可以看到。另一个参数就是你选择的Boss编号，从0到2，对应页面的这三个BOSS：

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

再来说说如何用代码去寻找你的TokenID，你可能有上百个NFT，如果没有存储的习惯，是很难去寻找所有Token的编号。这里我给大家推荐一个接口。

这里还是用BSC举例，其他的evm公链都有类似接口。

[https://docs.bscscan.com/api-endpoints/tokens#get-address-bep721-token-inventory-by-contract-address](https://docs.bscscan.com/api-endpoints/tokens#get-address-bep721-token-inventory-by-contract-address)

这个接口中只需要修改address为你的地址，contractaddress改成合约地址，就可以拿到所有的tokenID，但是可能会出现重复。

如果你mint了一个NFT，并把这个NFT交易出去了，会有两条记录，但是你现在是没有持有这个NFT的。所以需要进行一个过滤，过滤偶数的记录，留下单数的即可。

好了，到这里基本就把掰手腕的战斗交互讲完了。剩下的mint和领取币，大家可以照猫画虎的去完成，如果有遇到任何问题欢迎在discord中提问！

最后
--

我发现其实如果你自己真的打算玩这个游戏，要投入资金去搞是值得写一写脚本。像我只为了写个教程的就算了，因为你要付出不少的成本去测试…

我终于发现众筹的钱是做什么的了，是给我报销gas和游戏的费用 T T

如果对智能合约开发感兴趣，可以看看B站的这套视频：

[https://space.bilibili.com/2043099931/video](https://space.bilibili.com/2043099931/video)

这套视频我看完了，很不错，就是前半段声音可能有点小，后面就好很多。

---

*Originally published on [ourens.eth](https://paragraph.com/@ourens/web3py)*
