Appearance
与已部署的合约交互
概述
在本教程中,我们将通过调用其公共方法与已部署的智能合约进行交互,在单独的进程或由不同的方进行。
为此,我们需要创建一个与链上已部署合约相对应的智能合约实例。
智能合约
我们将重用之前步骤中的状态合约 Counter
from a previous step。
ts
export class Counter extends SmartContract {
// 状态变量
@prop(true)
count: bigint
constructor(count: bigint) {
super(...arguments)
this.count = count
}
@method()
public incrementOnChain() {
// 增加计数器。
this.increment()
// 确保下一个输出将包含带有更新计数器属性的此合约的代码。
// 并确保合约中的余额不变
const amount: bigint = this.ctx.utxo.value
// 包含最新状态和可选更改输出的输出
const outputs: ByteString = this.buildStateOutput(amount) + this.buildChangeOutput()
// 验证解锁交易具有相同的输出
assert(this.ctx.hashOutputs == hash256(outputs), 'hashOutputs mismatch')
}
@method()
increment(): void {
this.count++
}
}
部署
要部署智能合约,我们定义以下函数:
ts
async function deploy(initialCount = 100n): Promise<string> {
const instance = new Counter(initialCount)
await instance.connect(getDefaultSigner())
const tx = await instance.deploy(1)
console.log(`Counter deployed: ${tx.id}, the count is: ${instance.count}`)
return tx.id
}
该函数以 1 聪的余额部署合约,并返回已部署合约的事务 ID。
交互
Next, we update our deployed smart contract by calling the following function:
ts
async function callIncrementOnChain(
txId: string,
atOutputIndex = 0
): Promise<string> {
// 通过提供者获取 TX 并重建合约实例。
const signer = getDefaultSigner()
const tx = await signer.connectedProvider.getTransaction(txId)
const instance = Counter.fromTx(tx, atOutputIndex)
await instance.connect(signer)
const nextInstance = instance.next()
nextInstance.increment()
const { tx: callTx } = await instance.methods.incrementOnChain({
next: {
instance: nextInstance,
balance: instance.balance,
},
} as MethodCallOptions<Counter>)
console.log(`Counter incrementOnChain called: ${callTx.id}, the count now is: ${nextInstance.count}`)
return callTx.id
}
该函数将已部署智能合约的事务 ID 作为参数,并使用 DefaultProvider
从区块链中获取事务数据。随后,它使用 fromTx
函数重建智能合约实例。
让我们将整个过程封装在一个主函数中,该函数设计为部署合约并将其值增加五次:
ts
async function main() {
await compileContract()
let lastTxId = await deploy()
for (let i = 0; i < 5; ++i) {
lastTxId = await callIncrementOnChain(lastTxId)
}
}
(async () => {
await main()
})()
如果我们执行代码,我们应该得到类似于以下内容的输出:
ts
Counter deployed: 1cd6eb4ff0a5bd83f06c60c5e9a5c113c6e44fd876096e4e94e04a80fee8c8ca, the count is: 100
Counter incrementOnChain called: c5b8d8f37f5d9c089a73a321d58c3ae205087ba21c1e32ed09a1b2fbd4f65330, the count now is: 101
Counter incrementOnChain called: c62bb0f187f81dfeb5b70eafe80d549d3b2c6219e16d9575639b4fbdffd1d391, the count now is: 102
Counter incrementOnChain called: 9fb217b98324b633d8a0469d6a2478f522c1f40c0b6d806430efe5ae5457ca0e, the count now is: 103
Counter incrementOnChain called: 2080ddecc7f7731fc6afd307a57c8b117227755bd7b82eb0bc7cd8b78417ad9a, the count now is: 104
Counter incrementOnChain called: de43687fd386e92cd892c18600d473bc38d5adb0cc34bbda892b94c61b5d5eb8, the count now is: 105
结论
恭喜!您现在已成功部署并调用了一个比特币智能合约。 您可以在我们的 boilerplate 仓库 中看到一个完整的测试示例。