This page explains how to create a simple wrapped Bitcoin implementation using the Glittr SDK. The example demonstrates creating a contract that allows users to mint wrapped BTC tokens at a 1:1 ratio.
First, we import the necessary components from the Glittr SDK and initialize the client with the appropriate network settings. In this case, we're using the regtest network for development purposes.
2. Account Setup
// Create two accounts: creator and minter
const creatorAccount = new Account({
wif: "...",
network: NETWORK,
});
const minterAccount = new Account({
wif: "...",
network: NETWORK,
});
We create two accounts:
creatorAccount: The account that will create and manage the contract
minterAccount: The account that will mint wrapped BTC tokens
This utility function allows you to check the details of an asset by its transaction ID and output index.
Key Concepts
1:1 Backing: Each wrapped BTC token is backed by an equivalent amount of Bitcoin.
Supply Cap: The contract matches Bitcoin's supply cap of 21 million.
Divisibility: The wrapped token maintains the same 8 decimal places as Bitcoin.
Purchase/Burn: Users can mint tokens by sending BTC and burn tokens to receive BTC back.
This implementation provides a simple way to create wrapped Bitcoin tokens that maintain a 1:1 peg with actual Bitcoin, allowing for easier integration with other Glittr contracts and applications.
Usage Flow
Initialize the SDK and accounts
const client = new GlittrSDK({...});
const creatorAccount = new Account({...});
const minterAccount = new Account({...});
Create the wrapped BTC contract
await deployWbtcContract();
Mint wrapped BTC tokens
await mint();
Check asset details
await _checkingAsset();
Full Code Example
import {
Account,
addFeeToTx,
BitcoinUTXO,
BlockTxTuple,
electrumFetchNonGlittrUtxos,
GlittrSDK,
OpReturnMessage,
Output,
txBuilder
} from "@glittr-sdk/sdk";
const NETWORK = "regtest";
const client = new GlittrSDK({
network: NETWORK,
apiKey: <your api key here>,
glittrApi: "https://devnet-core-api.glittr.fi", // devnet
electrumApi: "https://devnet-electrum.glittr.fi" // devnet
});
const creatorAccount = new Account({
wif: "...",
network: NETWORK,
});
const minterAccount = new Account({
wif: "...",
network: NETWORK,
});
console.log(`Creator account ${creatorAccount.p2pkh().address}`);
console.log(`Minter account ${minterAccount.p2pkh().address}`);
async function deployWbtcContract() {
const tx: OpReturnMessage = {
contract_creation: {
contract_type: {
moa: {
divisibility: 8,
live_time: 0,
supply_cap: 21000000n.toString(),
mint_mechanism: {
purchase: {
input_asset: 'raw_btc',
ratio: { fixed: { ratio: [1, 1] } } // 1:1 ratio
}
}
}
}
}
}
const address = creatorAccount.p2pkh().address
const utxos = await electrumFetchNonGlittrUtxos(client.electrumApi, client.apiKey, address)
const nonFeeInputs: BitcoinUTXO[] = []
const nonFeeOutputs: Output[] = [
{ script: txBuilder.compile(tx), value: 0 }, // Output #0 should always be OP_RETURN
{ address: address, value: 546 }
]
const { inputs, outputs } = await addFeeToTx(NETWORK, address, utxos, nonFeeInputs, nonFeeOutputs)
const txid = await client.createAndBroadcastRawTx({
account: creatorAccount.p2pkh(),
inputs,
outputs
})
console.log(`TXID : ${txid}`)
}
async function mint() {
// Change this to your deployWbtcContract() result
const contract: BlockTxTuple = [101869, 1]; // https://explorer.glittr.fi/tx/688cbe5f4c147e46ef3ed2bbf448291c2041a7ab14ee9032ce1153b1ce89ed6e
const tx: OpReturnMessage = {
contract_call: {
contract,
call_type: {
mint: {
pointer: 1 // Points to the mint receiver's index in Output array
}
}
}
}
const address = minterAccount.p2pkh().address
const utxos = await electrumFetchNonGlittrUtxos(client.electrumApi, client.apiKey, address)
const nonFeeInputs: BitcoinUTXO[] = []
const nonFeeOutputs: Output[] = [
{ script: txBuilder.compile(tx), value: 0 }, // Output #0 should always be OP_RETURN
{ address: address, value: 546 },
{ address: creatorAccount.p2pkh().address, value: 1000 } // Mint 1000 sats
]
const { inputs, outputs } = await addFeeToTx(NETWORK, address, utxos, nonFeeInputs, nonFeeOutputs)
const txid = await client.createAndBroadcastRawTx({
account: minterAccount.p2pkh(),
inputs,
outputs
})
console.log(`TXID : ${txid}`)
}
/**
* Call deployWbtcContract() function first
* wait for confirmation and indexing
* then call the mint() function
*/
deployWbtcContract()
/**
* Function to check asset after mint
* change the mintTxId and mintVout
* with your vestedMint() and freeMint() result
*/
async function _checkingAsset() {
const mintTxid =
"a320545261eb503ba305ebaf3e7bcaa7534c905b91b03a51759cf8e8128808de";
const mintVout = 0;
const result = await fetch(
`https://devnet-core-api.glittr.fi/assets/${mintTxid}/${mintVout}`
);
console.log(await result.text());
}