Skip to main content

Deploying a Contract in the Browser

Deploying a smart contract on OP_NET through a browser leverages the opnet.web3.deployContract() method from the wallet's Web3Provider. This guide walks you through deploying a contract directly using OP_WALLET in a browser environment.

Learn More

For a detailed guide on interacting with OP_WALLET, refer to Interacting with a Browser Wallet that Directly Supports OP_NET.


Steps to Deploy a Contract

1. Request Public Key and UTXOs

First, you must fetch the connected wallet's public key and UTXOs to fund the transaction.

import { networks } from "@btc-vision/bitcoin";
import { Address } from "@btc-vision/transaction";

const pubKey = await opnet.getPublicKey();
const account = Address.fromString(pubKey); // Sender's address

const utxos = await provider.utxoManager.getUTXOs({
address: account.p2tr(networks.regtest), // Sender's address (P2TR)
});
UTXO Management

Ensure you have enough UTXOs to cover the transaction inputs, gas fees, and any additional outputs.

Learn more about UTXO Manager.

2. Fetch the Contract Bytecode

Retrieve the contract bytecode from a file or define it directly as a hex string.

// Fetch the bytecode from a file and convert it to a Buffer
const bytecodeArrayBuffer = await fetch("contract.wasm").then((res) =>
res.arrayBuffer()
);
const bytecodeBuffer = Buffer.from(new Uint8Array(bytecodeArrayBuffer));
// OR directly define the bytecode as a hex string
// const bytecodeBuffer = Buffer.from("your-contract-bytecode", "hex");

3. Using opnet.web3.deployContract()

The deployContract() method simplifies the deployment process by combining UTXO management, bytecode inclusion, and gas calculations.

const deployTx = await opnet.web3.deployContract({
from: account.p2tr(networks.regtest), // Sender's address (P2TR)
bytecode: bytecodeBuffer, // Contract bytecode
utxos, // UTXOs for funding
feeRate: Number((await provider.gasParameters()).baseGas * 2n), // Gas fee rate (satoshis per byte)
priorityFee: 5000n, // Priority fee for faster processing
// calldata: Buffer.from([]), // Optional initialization calldata
// optionalOutputs: [ // Optional additional outputs
// {
// address: "optional-address",
// value: 1000, // satoshis
// },
// ],
});

Full Example

import { networks } from "@btc-vision/bitcoin";
import { Address } from "@btc-vision/transaction";
import { JSONRpcProvider } from "opnet";

// Initialize the provider and OP_NET instance
const provider = new JSONRpcProvider(
"https://regtest.opnet.org",
networks.regtest
);
const opnet = window.opnet;

if (!opnet || !opnet.web3) {
throw new Error("OP_WALLET is not available in this browser.");
}

const pubKey = await opnet.getPublicKey();
const account = Address.fromString(pubKey); // Sender's address

const utxos = await provider.utxoManager.getUTXOs({
address: account.p2tr(networks.regtest), // Sender's address (P2TR)
});
if (!utxos || utxos.length === 0) {
throw new Error("No UTXOs available.");
}

// Fetch the bytecode from a file and convert it to a Buffer
const bytecodeArrayBuffer = await fetch("contract.wasm").then((res) =>
res.arrayBuffer()
);
const bytecodeBuffer = Buffer.from(new Uint8Array(bytecodeArrayBuffer));
// OR directly define the bytecode as a hex string
// const bytecodeBuffer = Buffer.from("your-contract-bytecode", "hex");

// Deploy the contract
const deployTx = await opnet.web3.deployContract({
from: account.p2tr(networks.regtest), // Sender's address (P2TR)
bytecode: bytecodeBuffer, // Contract bytecode
utxos, // UTXOs for funding
feeRate: Number((await provider.gasParameters()).baseGas * 2n), // Gas fee rate (satoshis per byte)
priorityFee: 5000n, // Priority fee for faster processing
// calldata: Buffer.from([]), // Optional initialization calldata
// optionalOutputs: [ // Optional additional outputs
// {
// address: "optional-address",
// value: 1000, // satoshis
// },
// ],
});

console.log("Deployed contract:", deployTx);

Deployment Result

The deployContract() method returns a DeploymentResult object:

export interface DeploymentResult {
readonly transaction: [string, string]; // Array of raw transaction strings
readonly contractAddress: string; // Contract's address
readonly contractPubKey: string; // Contract's tweaked public key
readonly p2trAddress: string; // Contract's P2TR address
readonly utxos: UTXO[]; // Array of new UTXOs after deployment
}

Best Practices

  • Always verify that the selected UTXOs can cover the transaction's cost, including fees.
  • Avoid deploying directly on mainnet without thorough testing on regtest or testnet.
  • Handle private keys and sensitive information securely in your browser environment.