@ordchan/sdk v0.3.0
OrdChan SDK
A TypeScript SDK for interacting with the OrdChan protocol - a decentralized messaging platform built on Bitcoin Ordinals.
Features
- 🔍 Search & Discover - Find boards, threads, and replies
- 📝 Content Creation - Create boards, threads, and replies
- 🔔 Real-time Updates - Subscribe to new content via WebSockets
- 👛 Wallet Integration - Built-in adapters for popular Bitcoin wallets (UniSat, OKX, Xverse)
- 🔑 Direct Key Access - Use private keys or seed phrases without a browser extension
- 🌍 Network Support - Works on both mainnet and testnet
- 🏷️ Username Market - Buy, sell, and make offers on usernames
- 📊 Voting System - Upvote/downvote content with satoshis
- 🧰 Ordinals Processing - Extract and parse ordinals inscriptions from blocks and transactions
- 🧩 Extensible Architecture - Easily add custom wallet adapters
- 🔄 Transaction Access - Get raw transaction data from Bitcoin nodes or public APIs
- 💱 NFT Marketplace - Buy and sell NFTs with our marketplace utilities (new in v0.3.0)
- 🌐 Cross-Platform - Compatible with both browser and Node.js environments (new in v0.3.0)
Installation
npm install @ordchan/sdkOr using Yarn:
yarn add @ordchan/sdkQuick Start
import { OrdChanSDK, UniSatWalletAdapter, PrivateKeyWalletAdapter } from '@ordchan/sdk';
// Initialize the SDK
const sdk = new OrdChanSDK({
apiUrl: 'https://api.ordchan.com'
});
// Connect wallet (choose one method)
const connectBrowserWallet = async () => {
const wallet = new UniSatWalletAdapter();
await wallet.connect();
sdk.setWalletAdapter(wallet);
console.log('Connected to browser wallet');
};
const connectWithSeedPhrase = async () => {
const wallet = new PrivateKeyWalletAdapter({
seedPhrase: 'your twelve or twenty four word mnemonic seed phrase',
network: 'mainnet'
});
await wallet.connect();
sdk.setWalletAdapter(wallet);
console.log('Connected with seed phrase');
};
// Get all boards
const getBoards = async () => {
const boards = await sdk.boards.getAll();
console.log('Boards:', boards);
};
// Create a new thread
const createThread = async () => {
const thread = await sdk.threads.create({
board: 'bitcoin',
title: 'Hello OrdChan',
content: 'This is my first thread'
});
console.log('Created thread:', thread);
};
// Subscribe to new replies in a thread
const subscribeToReplies = (threadId) => {
const unsubscribe = sdk.replies.subscribe(
{ threadId },
(reply) => {
console.log('New reply:', reply);
}
);
// To stop listening later:
// unsubscribe();
};NFT Marketplace (New in v0.3.0)
The SDK includes a complete marketplace implementation for buying and selling NFTs on Bitcoin:
import { marketplace } from '@ordchan/sdk';
import { UniSatWalletAdapter, PrivateKeyWalletAdapter } from '@ordchan/sdk';
// Example 1: Sell an NFT by creating a listing
const sellNft = async () => {
// Connect a wallet (browser extension or private key)
const wallet = new PrivateKeyWalletAdapter({
seedPhrase: 'your seed phrase here',
network: 'bitcoin'
});
await wallet.connect();
// Get seller's address
const sellerAddress = await wallet.getAddress();
// Find the UTXO containing the inscription
const inscriptionId = '1d33f2a46047fbb366652d003d8049bbadc6e38062ce1b9b57408a2a5d4373a7i0';
const inscriptionUtxo = await marketplace.utxo.findInscriptionUtxo(
inscriptionId,
sellerAddress,
'bitcoin' // or 'fractal' for Fractal network
);
if (!inscriptionUtxo) {
console.error('Inscription not found in this wallet');
return;
}
// Create a listing PSBT
const price = 10000; // 10,000 satoshis
const listingPsbt = marketplace.psbt.createNftListingPsbt({
inscriptionUtxo,
sellerAddress,
recipientAddress: sellerAddress, // Where to receive payment
price,
platformFeeAddress: 'bc1q...' // Optional: platform fee recipient
});
// Sign the listing PSBT with the wallet
const privateKey = await wallet.getPrivateKey(); // Implementation depends on wallet
const signedPsbt = marketplace.psbt.signNftSellerPsbt(listingPsbt, privateKey);
console.log('Listing PSBT created and signed:');
console.log(signedPsbt);
// This PSBT can now be shared with potential buyers
return signedPsbt;
};
// Example 2: Buy an NFT from a listing
const buyNft = async (listingPsbtHex) => {
// Connect a wallet
const wallet = new UniSatWalletAdapter();
await wallet.connect();
// Get buyer's address
const buyerAddress = await wallet.getAddress();
// Find payment UTXOs
const utxos = await marketplace.utxo.findAllUtxos(buyerAddress, 'bitcoin');
// Create buyer's PSBT
const buyerPsbt = marketplace.psbt.createNftBuyerPsbt({
sellerSignedPsbtHex: listingPsbtHex,
buyerAddress,
changeAddress: buyerAddress,
paymentUtxos: utxos,
feeRate: 5 // sats/byte
});
// Sign the buyer's PSBT
const signedBuyerPsbt = await wallet.signPsbt(buyerPsbt);
// Combine PSBTs
const completePsbt = marketplace.psbt.combineNftPsbts(
listingPsbtHex,
signedBuyerPsbt
);
// Extract and broadcast the final transaction
const txHex = marketplace.transaction.extractTransaction(completePsbt);
if (txHex) {
const result = await marketplace.transaction.broadcastTransaction(
txHex,
'bitcoin' // or 'fractal'
);
console.log('NFT purchase successful!');
console.log('Transaction ID:', result.txid);
console.log('Explorer URL:', marketplace.transaction.getExplorerUrl(result.txid, 'bitcoin'));
}
};Cross-Platform Compatibility (New in v0.3.0)
The SDK now works seamlessly in both browser and Node.js environments:
import { marketplace, wallet } from '@ordchan/sdk';
// Browser environment: Use a browser wallet
const useBrowserWallet = async () => {
// This will only attempt to connect if running in a browser
try {
const walletAdapter = new wallet.UniSatWalletAdapter();
await walletAdapter.connect();
console.log('Connected to UniSat wallet');
return walletAdapter;
} catch (error) {
console.error('Browser wallet not available:', error);
return null;
}
};
// Node.js environment: Use a private key or seed phrase
const usePrivateKeyWallet = async () => {
const walletAdapter = new wallet.PrivateKeyWalletAdapter({
seedPhrase: 'your seed phrase here',
// or privateKey: 'your WIF private key',
network: 'bitcoin'
});
await walletAdapter.connect();
console.log('Connected with private key wallet');
return walletAdapter;
};
// Works in both environments
const getWalletAdapter = async () => {
// Try browser wallet first
const browserWallet = await useBrowserWallet().catch(() => null);
if (browserWallet) return browserWallet;
// Fall back to private key wallet
return await usePrivateKeyWallet();
};UTXO Management (New in v0.3.0)
The SDK provides comprehensive UTXO utilities:
import { marketplace } from '@ordchan/sdk';
// Find UTXOs containing a specific inscription
const findInscription = async () => {
const inscriptionId = '1d33f2a46047fbb366652d003d8049bbadc6e38062ce1b9b57408a2a5d4373a7i0';
const address = 'bc1q...';
const network = 'bitcoin'; // or 'fractal'
const utxo = await marketplace.utxo.findInscriptionUtxo(
inscriptionId,
address,
network
);
if (utxo) {
console.log(`Inscription found in UTXO: ${utxo.txid}:${utxo.vout}`);
console.log(`Value: ${utxo.value} sats`);
} else {
console.log('Inscription not found in this address');
}
};
// Find all UTXOs for an address
const findAllUtxos = async () => {
const address = 'bc1q...';
const utxos = await marketplace.utxo.findAllUtxos(address, 'bitcoin');
console.log(`Found ${utxos.length} UTXOs with total value: ${
utxos.reduce((sum, u) => sum + u.value, 0)
} sats`);
};
// Select UTXOs for a transaction
const selectUtxos = () => {
const availableUtxos = [/* array of UTXOs */];
const amountNeeded = 50000; // 50,000 sats
const minUtxosNeeded = 2; // Need at least 2 UTXOs for placeholder inputs
const selectedUtxos = marketplace.utxo.selectUtxosForPayment(
availableUtxos,
amountNeeded,
minUtxosNeeded
);
console.log(`Selected ${selectedUtxos.length} UTXOs with value: ${
selectedUtxos.reduce((sum, u) => sum + u.value, 0)
} sats`);
};
// Create placeholder UTXOs for complex transactions
const createPlaceholderUtxos = async () => {
const wallet = new wallet.PrivateKeyWalletAdapter({
seedPhrase: 'your seed phrase here'
});
await wallet.connect();
const address = await wallet.getAddress();
const utxos = await marketplace.utxo.findAllUtxos(address);
// Create multiple small UTXOs from a larger one
const txid = await marketplace.transaction.createPlaceholderUtxos(
utxos,
address,
wallet.getPrivateKey(),
5, // number of UTXOs to create
5000, // value of each UTXO (5,000 sats)
5, // fee rate (sats/byte)
'bitcoin' // network
);
console.log(`Created placeholder UTXOs in transaction: ${txid}`);
};Transaction Handling (New in v0.3.0)
The SDK provides comprehensive transaction utilities:
import { marketplace } from '@ordchan/sdk';
// Broadcast a transaction
const broadcastTx = async () => {
const txHex = '020000000001...'; // Transaction hex
const network = 'bitcoin'; // or 'fractal'
try {
const result = await marketplace.transaction.broadcastTransaction(txHex, network);
console.log('Transaction broadcast successful!');
console.log('Transaction ID:', result.txid);
// Get explorer URL
const url = marketplace.transaction.getExplorerUrl(result.txid, network);
console.log('View transaction:', url);
} catch (error) {
console.error('Broadcast failed:', error);
}
};
// Sign a PSBT with a private key
const signPsbt = () => {
const psbtHex = '70736274ff...'; // PSBT hex
const privateKey = Buffer.from('...'); // Private key buffer
// Optionally specify sighash types for each input
const sighashTypes = [
0x01, // SIGHASH_ALL for input 0
0x81 // SIGHASH_SINGLE|ANYONECANPAY for input 1
];
const signedPsbtHex = marketplace.transaction.signPsbt(
psbtHex,
privateKey,
sighashTypes // optional
);
console.log('Signed PSBT:', signedPsbtHex);
};
// Extract a transaction from a PSBT
const extractTx = () => {
const psbtHex = '70736274ff...'; // PSBT hex
// Try to extract a complete transaction
const txHex = marketplace.transaction.extractTransaction(psbtHex);
if (txHex) {
console.log('Extracted transaction:', txHex);
} else {
// Try with allowIncomplete=true for partially signed PSBTs
const incompleteTxHex = marketplace.transaction.extractTransaction(psbtHex, true);
console.log('Extracted incomplete transaction:', incompleteTxHex);
}
};
// Calculate transaction fee
const calculateFee = () => {
const txHex = '020000000001...'; // Transaction hex
const feeRate = 5; // sats/byte
const estimatedFee = marketplace.transaction.estimateTransactionFee(txHex, feeRate);
console.log(`Estimated fee: ${estimatedFee} sats`);
};Ordinals Processing
The SDK includes powerful utilities for processing Bitcoin blocks and transactions to extract ordinals inscriptions:
// Initialize the SDK
const sdk = new OrdChanSDK({
apiUrl: 'https://api.ordchan.com'
});
// Process a Bitcoin block to extract all ordinals inscriptions
const processBlock = async () => {
const blockHash = '000000000000000000076c036ff5119e5c5a633a9e8e5ba71b7ad89e52a0dcec'; // Block 800000
const messages = await sdk.ordinals.processBlock(blockHash);
console.log(`Found ${messages.length} ordinals in block`);
// Filter to only OrdChan protocol messages
const ordchanMessages = sdk.ordinals.filterByProtocol(messages, ['ordchan']);
console.log(`Found ${ordchanMessages.length} OrdChan messages`);
};
// Process a single transaction to extract ordinals
const processTransaction = async () => {
const txid = 'f34c43b1158de337e8e4f74d09256a574e865d8ab280926a0cd40d4e7aabf9a2';
const messages = await sdk.ordinals.processTransaction(txid);
console.log(`Found ${messages.length} inscriptions in transaction`);
};
// Process a transaction directly from its raw hex
const processTransactionHex = async () => {
// Get transaction hex from anywhere (from wallet, API, or manual construction)
const txHex = '020000000001018c57c91a45a44ba....'; // Transaction hex data
// Process directly without needing to broadcast or have txid
const { txid, ordinals } = await sdk.ordinals.processTransactionFromHex(txHex);
console.log(`Transaction ID: ${txid}`);
console.log(`Found ${ordinals.length} inscriptions in transaction hex`);
// You can also provide optional block information if available
const result = await sdk.ordinals.processTransactionFromHex(txHex, {
blockInfo: {
blockHeight: 800000,
blockHash: '000000000000000000076c036ff5119e5c5a633a9e8e5ba71b7ad89e52a0dcec',
timestamp: 1685341196
}
});
console.log(`Transaction ${result.txid} has ${result.ordinals.length} inscriptions`);
};
// Extract a message from an inscription ID
const extractMessage = async () => {
const inscriptionId = 'f34c43b1158de337e8e4f74d09256a574e865d8ab280926a0cd40d4e7aabf9a2i0';
const content = await sdk.ordinals.extractMessage(inscriptionId);
console.log('Inscription content:', content);
};See ORDINALS_PROCESSING.md for more details.
Transaction Data Access
The SDK provides methods to retrieve raw Bitcoin transaction data from various sources:
// Initialize the SDK with Bitcoin RPC configuration (optional)
const sdk = new OrdChanSDK({
apiUrl: 'https://api.ordchan.com',
// Optionally configure Bitcoin RPC access
bitcoinRpc: {
host: 'localhost',
port: 8332,
user: 'username',
password: 'password'
// Alternatively, use a cookie file
// cookieFile: '~/.bitcoin/.cookie'
},
// Optionally configure fallbacks and preferred data sources
dataSourceConfig: {
preferBlockstream: false, // Prefer blockstream.info API over RPC
preferMempool: true, // Prefer mempool.space API over RPC
fallbackToPublicApis: true // Use public APIs if RPC fails
}
});
// Get raw transaction hex
const getRawTx = async (txid) => {
try {
const txHex = await sdk.transactions.getRawTransactionHex(txid);
console.log(`Transaction hex (${txHex.length / 2} bytes):`);
console.log(txHex.substring(0, 100) + '...');
// Parse the transaction
const tx = bitcoin.Transaction.fromHex(txHex);
console.log(`Transaction has ${tx.ins.length} inputs and ${tx.outs.length} outputs`);
return txHex;
} catch (error) {
console.error('Failed to get transaction hex:', error);
}
};The SDK will automatically try multiple sources to get transaction data: 1. Local Bitcoin node (via RPC) if configured 2. mempool.space API 3. blockstream.info API 4. blockchain.info API 5. OrdChan API as a last resort
Documentation
For full API documentation, see the SDK Docs.
Examples
The repository includes several examples demonstrating how to use the SDK:
- Connect to wallet
- Create a new thread
- Register a username
- Process ordinals inscriptions
- Get transaction data
- Buy and sell NFTs
Version History
v0.3.0
- Added comprehensive NFT marketplace functionality
- Made wallet adapters compatible with both browser and Node.js
- Added UTXO management utilities
- Added transaction handling utilities
- Fixed TypeScript compilation issues
- Improved error handling and type safety
v0.2.3
- Added ordinals processing utilities
- Added transaction data access
- Added username market functionality
- Improved wallet adapters
v0.2.0
- Initial public release
- Basic board and thread functionality
- Wallet integration
License
MIT