Deploying a Contract
Deploying a smart contract on OP_NET using WalletConnect requires careful handling of UTXOs and constructing deployment parameters. This guide explains the process of using TransactionFactory
to sign and deploy contracts.
Steps to Deploy a Contract
1. Get Required Parameters
Before deploying a contract, ensure you have the following parameters:
account
: Wallet account for transaction signing.signer
: Wallet signer for transaction authorization.
import { useWallet } from "@btc-vision/walletconnect";
const { account, signer } = useWallet();
2. Obtaining Proper UTXOs
Before building a transaction, you need to gather the required UTXOs for funding. Use the utxoManager
from the JSONRpcProvider
to fetch UTXOs associated with your address.
const utxos = await account.provider.utxoManager.getUTXOs({
address: account.address.p2tr(account.network),
});
Ensure you have enough UTXOs to cover the transaction inputs, gas fees, and any additional outputs.
Learn more about UTXO Manager.
3. Fetching Contract Bytecode
Retrieve the contract bytecode (compiled contract code) to be deployed. You can read the bytecode from a compiled .wasm
file or use the hex string directly.
const bytecodeArrayBuffer = await fetch("contract.wasm").then((res) =>
res.arrayBuffer()
);
const bytecode = Buffer.from(new Uint8Array(bytecodeArrayBuffer));
// OR directly define the bytecode as a hex string
// const bytecodeBuffer = Buffer.from("your-contract-bytecode", "hex");
4. Constructing Deployment Parameters
The IDeploymentParameters
interface defines the required parameters for contract deployment. Ensure you provide the signer, network, contract bytecode, and other necessary details.
const deploymentParameters: IDeploymentParameters = {
signer: signer!, // OP_WALLET does not require a signer
network: account.network,
from: account.address.p2tr(account.network),
bytecode: bytecode,
utxos: utxos,
feeRate: 100,
priorityFee: 10_000n,
gasSatFee: 10_000n,
};
5. Signing the Deployment Transaction
Use the signDeployment
method from TransactionFactory
to sign the deployment transaction. This method returns a DeploymentResult
object containing the signed transaction and contract details.
const transactionFactory = new TransactionFactory();
const deploymentResult = await transactionFactory.signDeployment(
deploymentParameters
);
console.log(deploymentResult); // This is not sent to the blockchain yet
6. Broadcasting the Transaction
After signing the deployment transaction, you can broadcast it to the network using the sendRawTransactions
method. This step finalizes the contract deployment process.
const transactionReceipt = await account.provider.sendRawTransactions(
deploymentResult.transaction
);
const txId = transactionReceipt[1].result;
const contractAddress = deploymentResult.contractAddress;
console.log(`Transaction ID: ${txId}`);
console.log(`Contract Address: ${contractAddress}`);
Object Definitions
DeploymentResult
ObjectProperty | Type | Description |
---|---|---|
transaction | string | Array of raw transaction strings. |
contractAddress | string | Contract's Taproot address. |
contractPubKey | string | Contract's tweaked public key. |
p2trAddress | string | Contract's P2TR address. |
utxos | UTXO[] | Array of new UTXOs after deployment. |
Full Example
import {
IDeploymentParameters,
TransactionFactory,
} from "@btc-vision/transaction";
import { SupportedWallets, useWallet } from "@btc-vision/walletconnect";
function DeployContract() {
const { account, connect, disconnect, signer } = useWallet();
async function deployContract() {
if (!account) throw new Error("Connect wallet first");
const utxos = await account.provider.utxoManager.getUTXOs({
address: account.address.p2tr(account.network),
});
const bytecodeArrayBuffer = await fetch("contract.wasm").then((res) =>
res.arrayBuffer()
);
const bytecode = Buffer.from(new Uint8Array(bytecodeArrayBuffer));
const deploymentParameters: IDeploymentParameters = {
signer: signer!, // OP_WALLET does not require a signer
network: account.network,
from: account.address.p2tr(account.network),
bytecode: bytecode,
utxos: utxos,
feeRate: 100,
priorityFee: 10_000n,
gasSatFee: 10_000n,
};
const transactionFactory = new TransactionFactory();
const deploymentResult = await transactionFactory.signDeployment(
deploymentParameters
);
console.log(deploymentResult); // This is not sent to the blockchain yet
const transactionReceipt = await account.provider.sendRawTransactions(
deploymentResult.transaction
);
const txId = transactionReceipt[1].result;
const contractAddress = deploymentResult.contractAddress;
console.log(`Transaction ID: ${txId}`);
console.log(`Contract Address: ${contractAddress}`);
}
return (
<div>
{account ? (
<div>
<p>Connected Address: {account.address.p2tr(account.network)}</p>
<button onClick={deployContract}>Deploy Contract</button>
<button onClick={disconnect}>Disconnect</button>
</div>
) : (
<button onClick={() => connect(SupportedWallets.OP_WALLET)}>
Connect Wallet
</button>
)}
</div>
);
}
export default DeployContract;
Best Practices
- Ensure your wallet has sufficient UTXOs to fund the deployment and associated fees.
- Adjust the
feeRate
andpriorityFee
parameters based on current network conditions to minimize costs. - Before deploying on mainnet, test your contract deployment process on regtest or testnet to avoid unnecessary costs.