Spaces:
Runtime error
sidebar_position: 2
How to Customize a Contract Tx
Deployment Tx
Default
For contract deployment, the default tx builder creates a transaction with the following structure:
Inputs:
- [0β¦]: One or more P2PKH inputs for paying transaction fees.
Outputs:
- [0]: The output containing the contract.
- [1]: A P2PKH change output if needed.
Numbers in [] represent index, starting from 0.
Customize
You can customize a contract's deployment tx builder by overriding its buildDeployTransaction method. An example is shown below.
class DemoContract extends SmartContract {
// ...
// customize the deployment tx by overriding `SmartContract.buildDeployTransaction` method
override async buildDeployTransaction(utxos: UTXO[], amount: number,
changeAddress?: bsv.Address | string): Promise<bsv.Transaction> {
const deployTx = new bsv.Transaction()
// add p2pkh inputs for paying tx fees
.from(utxos)
// add contract output
.addOutput(new bsv.Transaction.Output({
script: this.lockingScript,
satoshis: amount,
}))
// add OP_RETURN output
.addData('Hello World')
if (changeAddress) {
deployTx.change(changeAddress);
if (this._provider) {
deployTx.feePerKb(await this.provider.getFeePerKb())
}
}
return deployTx;
}
}
You may visit the full code for more details.
Call Tx
Default
For contract calls, the default tx builder creates a transaction with the following structure:
Inputs
- [0]: The input that spends the contract UTXO.
- [1β¦]: Zero or more P2PKH inputs for paying transaction fees.
Outputs
- [0β¦N-1]: One or more outputs, each containing a new contract instance (UTXO) if the contract is stateful.
- [N]: A P2PKH change output if needed.
Customize
You can customize a tx builder for a public @method
of your contract by calling bindTxBuilder
. The first parameter is the public method name, and the second parameter is the customized tx builder.
// bind a customized tx builder for the public method `MyContract.unlock`
instance.bindTxBuilder("unlock", (current: T, options: MethodCallOptions<T>, ...args: any) => {
// the tx is NOT signed
const unsignedTx: bsv.Transaction = new bsv.Transaction()
// add contract input
.addInput(current.buildContractInput(options.fromUTXO))
// add a p2pkh output
.addOutput(new bsv.Transaction.Output({
script: bsv.Script.fromHex(Utils.buildPublicKeyHashScript(args[0])),
satoshis: args[1]
}))
// add change output
.change(options.changeAddress)
return Promise.resolve({
tx: unsignedTx,
atInputIndex: 0, // the contract input's index
nexts: []
})
})
Note that the parameters of your customized tx builder consist of the following parts:
current
is the actual instance of the smart contract.options
is of typeMethodCallOptions
....args: any
is an argument list the same as the bound pubic@method
.
Notes
Please be aware that each of these tx builders should only create an unsigned transaction. If required, the transaction gets signed automatically in a later step prior to broadcasting.
Also, your customized tx must satisfy all of the called @method
's assertions.