Spaces:
Runtime error
Runtime error
File size: 3,847 Bytes
711e9c6 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
---
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](https://learnmeabitcoin.com/technical/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](../how-to-write-a-contract/built-ins#builddeploytransaction) method. An example is shown below.
```ts
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](https://github.com/sCrypt-Inc/boilerplate/blob/f63c37038a03bc51267e816d9441969d3e1d2ece/src/contracts/auction.ts#L100-L127) 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](../how-to-write-a-contract/stateful-contract).
* [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.
```ts
// 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 type [`MethodCallOptions`](../how-to-test-a-contract.md#methodcalloptions).
- `...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.
|