Architecture
Introduction
The opnet client library is the official SDK for building Bitcoin-based applications on OP_NET. It provides full TypeScript support with type-safe contract interactions, enabling developers to integrate smart contract functionality directly into their applications.
The library follows a layered architecture where each layer encapsulates specific domain functionality. Foundational layers handle network communication and transaction processing, while higher layers build upon these to provide contract interaction and application-level features.
Contract Layer
The contract layer provides the classes required to represent and interact with deployed smart contracts on OP_NET. By leveraging Application Binary Interface (ABI) definitions, this layer enables type-safe contract interactions where method parameters and return values are validated at compile time. Contracts rely on RPC providers to communicate with OP_NET nodes.
Creating a Contract
The getContract() factory function is the recommended method for creating type-safe contract instances. This factory handles the instantiation process by binding ABI methods to the contract address and configuring the underlying RPC provider for network communication. The resulting contract instance exposes all defined methods as strongly-typed functions, allowing full IntelliSense support and compile-time parameter validation.
import { getContract, IOP20Contract, OP_20_ABI } from 'opnet';
const token = getContract<IOP20Contract>(
contractAddress,
OP_20_ABI,
provider,
network
);
// Type-safe method calls
const name = await token.name();
const balance = await token.balanceOf(address);ABIs (Application Binary Interface)
ABIs define the contract interface: what methods and events exist. The library includes pre-built ABIs for standard contracts:
| ABI | Purpose |
|---|---|
| OP_20_ABI | Fungible tokens (like ERC20) |
| OP_721_ABI | NFTs (like ERC721) |
| MOTOSWAP_ROUTER_ABI | DEX router |
| MotoswapPoolAbi | Liquidity pools |
Type Safety
The library provides full TypeScript support with generics for type-safe contract interactions.
// Type-safe contract interface
interface IMyToken extends IOP20Contract {
mint(to: Address, amount: bigint): Promise<CallResult<never>>;
}
// Generic contract instantiation
const token = getContract<IMyToken>(
address,
myTokenABI,
provider,
network
);
// Type-checked method calls
const result = await token.mint(recipient, 1000n);
// ^^^^^ TypeScript knows this returns CallResult<never>Provider Layer
RPC providers handle communication with OP_NET nodes by abstracting the underlying network protocol and managing request serialization, response parsing, and connection handling. Providers can be configured to connect to different nodes or networks, enabling seamless transitions between development, testing, and production environments without modifying application code.
Since Bitcoin uses UTXOs instead of account balances, the provider layer includes a UTXOsManager that handles UTXO fetching and tracking.
Two provider types are available:
- JSONRpcProvider: HTTP-based with a request/response pattern.
- WebSocketRpcProvider: Supports real-time subscriptions and notifications.
import { JSONRpcProvider } from 'opnet';
import { networks } from '@btc-vision/bitcoin';
// JSON-RPC for standard operations
const provider = new JSONRpcProvider(
'https://regtest.opnet.org',
networks.regtest
);
// Get blockchain state
const blockNumber = await provider.getBlockNumber();
const balance = await provider.getBalance('bc1q...');
// Get UTXOs for an address
const utxos = await provider.utxoManager.getUTXOs({
address: 'bc1q...',
optimize: true,
});Networks
Endpoints
The following table lists the supported Bitcoin networks and their corresponding RPC endpoints:
| Network | Purpose | RPC URL |
|---|---|---|
| Mainnet | Production | https://mainnet.opnet.org |
| Regtest | Local development and testing | https://regtest.opnet.org |
No RPC endpoint is provided for Testnet. Use Regtest for development and testing purposes.
Specifying a Network
The library exposes the networks object which defines available Bitcoin networks. This object is used to specify the target network when calling methods that require network identification.
import { networks } from '@btc-vision/bitcoin';
// Network objects
networks.bitcoin // Mainnet
networks.testnet // Testnet
networks.regtest // RegtestData Layer
The data layer provides classes for managing core blockchain data including blocks, transactions, and epochs. This layer does not access node data directly but instead provides type definitions that represent blockchain data across all interactions with the OP_NET network.
This separation ensures type safety throughout the application while delegating network communication to other layers. When data is fetched or operations are performed, responses are deserialized into the corresponding data layer types, providing strongly-typed objects for application consumption.
Blocks
Blocks in OP_NET correspond directly to Bitcoin blocks and contain all OP_NET transactions processed within that block. The data layer provides access to block information including block height, hash, timestamp, and the decoded OP_NET transactions contained within.
import { JSONRpcProvider } from 'opnet';
import { networks } from '@btc-vision/bitcoin';
const network = networks.regtest;
const provider = new JSONRpcProvider('https://regtest.opnet.org', network);
const blockNumber = await provider.getBlockNumber();
console.log('Current block:', blockNumber);Transactions
Three transaction types exist within OP_NET:
- Deployment: Deploys new smart contracts to the network.
- Interaction: Invokes methods on deployed smart contracts.
- Generic:: Standard Bitcoin transfers without contract interaction.
Refer to the Transaction Types Explained section for detailed information.
Epochs
OP_NET uses epochs for consensus, where each epoch represents a mining cycle during which participants submit SHA-1 collision solutions. The data layer exposes epoch information including mining status, rewards, and finalization state.
Refer to the About Epochs section for detailed information.
import { JSONRpcProvider } from 'opnet';
import { networks } from '@btc-vision/bitcoin';
// JSON-RPC for standard operations
const provider = new JSONRpcProvider(
'https://regtest.opnet.org',
networks.regtest
);
const epoch = await provider.getLatestEpoch(true);
console.log('Epoch:', epoch.epochNumber);
console.log('Proposer:', epoch.proposer?.publicKey);Library Modules
The library exposes its functionality through a set of exports. All public classes, interfaces, types, and utility functions are accessible from the main package entry point.
import {
// Providers
JSONRpcProvider,
WebSocketRpcProvider,
// Contracts
getContract,
CallResult,
OPNetEvent,
// ABIs
OP_20_ABI,
OP_721_ABI,
MOTOSWAP_ROUTER_ABI,
// Types
IOP20Contract,
IOP721Contract,
// Data Classes
Block,
Epoch,
Transaction,
// Utils
BitcoinUtils,
RevertDecoder,
} from 'opnet';Best Practices
- Always simulate before sending: Check for reverts without spending BTC.
- Use type-safe interfaces: Leverage TypeScript for contract interactions.
- Handle BigInt correctly: All amounts are bigint type.
- Track UTXOs: Use UTXOsManager to avoid double-spending.
- Choose the right provider: JSON-RPC for most cases, WebSocket for real-time.