Vesting Schedule: The contract implements a linear vesting schedule where tokens are released in 25% increments over 4 blocks.
Allocation Types:
Direct allocation (vested)
Reserve allocation (vested)
Free mint allocation (unrestricted)
Asset Verification: The code includes methods to verify the status of both vested and free-minted assets through API calls.
Usage Flow
Create the contract using createContract()
Wait for vesting periods to unlock
Use vestedMint() to claim vested tokens
Use freeMint() to mint from the free allocation
Verify asset status using the checking functions
This example demonstrates a complete flow of creating and interacting with a vesting contract on the Glittr platform, including both restricted (vested) and unrestricted (free mint) token distributions.
Full Code Example
import { Account, GlittrSDK, Fraction, OpReturnMessage, electrumFetchNonGlittrUtxos, BitcoinUTXO, Output, addFeeToTx, txBuilder, BlockTxTuple,} from"@glittr-sdk/sdk";constNETWORK="regtest";constclient=newGlittrSDK({ network:NETWORK, apiKey: <yourapikeyhere>, glittrApi:"https://devnet-core-api.glittr.fi",// devnet electrumApi:"https://devnet-electrum.glittr.fi"// devnet});constaccount=newAccount({ wif:"...", network:NETWORK,});constreserveAccount=newAccount({ wif:"...", network:NETWORK,});constfreeMintAccount=newAccount({ wif:"...", network:NETWORK,});asyncfunctiondeployVestingContract() {constreceiver1PublicKey=Array.from(account.p2pkh().keypair.publicKey);constreceiver2PublicKey=Array.from(reserveAccount.p2pkh().keypair.publicKey );constquarterlyVesting: [Fraction,number][] = [ [[25,100],-1],// 25% unlocked after 1 blocks [[25,100],-2],// 25% unlocked after 2 blocks [[25,100],-3],// 25% unlocked after 3 blocks [[25,100],-4],// 25% unlocked after 4 blocks ];consttx:OpReturnMessage= { contract_creation: { contract_type: { moa: { divisibility:100, live_time:0, supply_cap: 1000n.toString(), mint_mechanism: { preallocated: { allocations: {"100": [receiver1PublicKey],"200": [receiver2PublicKey] }, vesting_plan: { scheduled: quarterlyVesting } }, free_mint: { supply_cap: 700n.toString(), amount_per_mint: 1n.toString() } } } } } }constaddress=account.p2pkh().addressconstutxos=awaitelectrumFetchNonGlittrUtxos(client.electrumApi,client.apiKey, address)constnonFeeInputs:BitcoinUTXO[] = []constnonFeeOutputs:Output[] = [ { script:txBuilder.compile(tx), value:0 },// Output #0 should always be OP_RETURN { address: address, value:546 } ]const { inputs,outputs } =awaitaddFeeToTx(NETWORK, address, utxos, nonFeeInputs, nonFeeOutputs)consttxid=awaitclient.createAndBroadcastRawTx({ account:account.p2pkh(), inputs, outputs })console.log(`TXID : ${txid}`)}asyncfunctionvestedMint() {constcontract:BlockTxTuple= [101832,1]; // https://explorer.glittr.fi/tx/8bb7f3332eb1c50d25ae31c1a06c2af56dc7e2d2f37b03c275cf1d547bbdcc21consttx:OpReturnMessage= { contract_call: { contract, call_type: { mint: { pointer:1// Points to the mint receiver's index in Output array } } } }constaddress=reserveAccount.p2pkh().addressconstutxos=awaitelectrumFetchNonGlittrUtxos(client.electrumApi,client.apiKey, address)constnonFeeInputs:BitcoinUTXO[] = []constnonFeeOutputs:Output[] = [ { script:txBuilder.compile(tx), value:0 },// Output #0 should alwasy be OP_RETURN { address: address, value:546 } ]const { inputs,outputs } =awaitaddFeeToTx(NETWORK, address, utxos, nonFeeInputs, nonFeeOutputs)consttxid=awaitclient.createAndBroadcastRawTx({ account:reserveAccount.p2pkh(), inputs, outputs })console.log(`TXID : ${txid}`)}asyncfunctionfreeMint() {constcontract:BlockTxTuple= [101832,1]; // https://explorer.glittr.fi/tx/8bb7f3332eb1c50d25ae31c1a06c2af56dc7e2d2f37b03c275cf1d547bbdcc21consttx:OpReturnMessage= { contract_call: { contract, call_type: { mint: { pointer:1// Points to the mint receiver's index in Output array } } } }constaddress=freeMintAccount.p2pkh().addressconstutxos=awaitelectrumFetchNonGlittrUtxos(client.electrumApi,client.apiKey, address)constnonFeeInputs:BitcoinUTXO[] = []constnonFeeOutputs:Output[] = [ { script:txBuilder.compile(tx), value:0 },// Output #0 should alwasy be OP_RETURN { address: address, value:546 } ]const { inputs,outputs } =awaitaddFeeToTx(NETWORK, address, utxos, nonFeeInputs, nonFeeOutputs)consttxid=awaitclient.createAndBroadcastRawTx({ account:freeMintAccount.p2pkh(), inputs, outputs })console.log(`TXID : ${txid}`)}/** * Call deployVestingContract() function first * wait for confirmation and indexing * then call the vestedMint() and freeMint() */deployVestingContract()/** * Function to check asset after mint * change the mintTxId and mintVout * with your vestedMint() and freeMint() result */asyncfunction_checkingAssetFreeMint() {constmintTxid="22acf70357c3adf8c3236e1c230b7c3d6796488825b963edd0d52ff13ba5a822";constmintVout=0;constresult=awaitfetch(`https://devnet-core-api.glittr.fi/assets/${mintTxid}/${mintVout}` );console.log(awaitresult.text());}asyncfunction_checkingAssetVested() {constmintTxid="82eda96aa5f9a0941b2b0f00b692aa389f54b210af23977f21e0006259f3282b";constmintVout=0;constresult=awaitfetch(`https://devnet-core-api.glittr.fi/assets/${mintTxid}/${mintVout}` );console.log(awaitresult.text());}