# Vesting and Freemint Contract

This page breaks down a TypeScript example that demonstrates how to create and interact with a vesting contract using the Glittr SDK.

### 1. Setup and Configuration

```typescript
import {
  Account,
  GlittrSDK,
  Fraction,
  OpReturnMessage,
  electrumFetchNonGlittrUtxos,
  BitcoinUTXO,
  Output,
  addFeeToTx,
  txBuilder,
  BlockTxTuple,
} from "@glittr-sdk/sdk";

// Initialize SDK with network configuration
const NETWORK = "regtest";
const client = new GlittrSDK({
  network: NETWORK,
  apiKey: <your api key here>,
  glittrApi: "https://devnet-core-api.glittr.fi",
  electrumApi: "https://devnet-electrum.glittr.fi",
});

// Create three accounts for different roles
const account = new Account({...});         // Main account
const reserveAccount = new Account({...});  // Reserve account
const freeMintAccount = new Account({...}); // Free minting account
```

The code starts by setting up the SDK client and creating three different accounts that will play different roles in the vesting contract.

### 2. Contract Creation

The `deployVestingContract()` function demonstrates how to create a vesting contract with the following characteristics:

* Total supply cap: 1000 tokens
* Divisibility: 100 (similar to decimals in other token standards)
* Allocation:
  * 100 tokens to receiver1
  * 200 tokens to receiver2 (reserve)
  * 700 tokens for free minting

The vesting schedule is quarterly:

```typescript
const quarterlyVesting: [Ratio, 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
];
```

Contract creation code:

```typescript
async function deployVestingContract() {
  // Example: pre-allocation with free mint
  // {
  // TxType: Contract,
  // simpleAsset:{
  // 	supplyCap: 1000,
  // 	Divisibility: 100,
  // 	liveTime: 0
  // },
  // Allocation:{
  // {100:pk1}
  // {200:reservePubKey},
  // {700: freemint}
  // vestingSchedule:{
  // 		Fractions: [.25, .25, .25, .25],
  // 		Blocks: [-1, -2, -3, -4] // relative block
  // },
  // FreeMint:{
  // 		mintCap: 1,
  // },
  // },
  // }

  const receiver1PublicKey = Array.from(account.p2pkh().keypair.publicKey);
  const receiver2PublicKey = Array.from(
    reserveAccount.p2pkh().keypair.publicKey
  );

  console.log(receiver1PublicKey, receiver2PublicKey);

  const quarterlyVesting: [Ratio, 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
  ];

  const tx: 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()
            }
          }
        }
      }
    }
  }

  const address = account.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: account.p2pkh(),
    inputs,
    outputs
  })

  console.log(`TX: https://explorer.glittr.fi/tx/${txid}`);
}
```

### 3. Minting Operations

The code includes two types of minting:

#### Vested Minting

```typescript
async function vestedMint() {
  const contract: BlockTxTuple = [101832, 1]; // https://explorer.glittr.fi/tx/8bb7f3332eb1c50d25ae31c1a06c2af56dc7e2d2f37b03c275cf1d547bbdcc21

  const tx: OpReturnMessage = {
    contract_call: {
      contract,
      call_type: {
        mint: {
          pointer: 1 // Points to the mint receiver's index in Output array
        }
      }
    }
  }

  const address = reserveAccount.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 alwasy be OP_RETURN
    { address: address, value: 546 }
  ]

  const { inputs, outputs } = await addFeeToTx(NETWORK, address, utxos, nonFeeInputs, nonFeeOutputs)

  const txid = await client.createAndBroadcastRawTx({
    account: reserveAccount.p2pkh(),
    inputs,
    outputs
  })

  console.log(`TX: https://explorer.glittr.fi/tx/${txid}`);
}
```

#### Free Minting

Call the following function using account that don't have vesting allocation a.k.a the `freeMintAccount.`

```typescript
async function freeMint() {
  const contract: BlockTxTuple = [101832, 1]; // https://explorer.glittr.fi/tx/8bb7f3332eb1c50d25ae31c1a06c2af56dc7e2d2f37b03c275cf1d547bbdcc21

  const tx: OpReturnMessage = {
    contract_call: {
      contract,
      call_type: {
        mint: {
          pointer: 1 // Points to the mint receiver's index in Output array
        }
      }
    }
  }

  const address = freeMintAccount.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 alwasy be OP_RETURN
    { address: address, value: 546 }
  ]

  const { inputs, outputs } = await addFeeToTx(NETWORK, address, utxos, nonFeeInputs, nonFeeOutputs)

  const txid = await client.createAndBroadcastRawTx({
    account: freeMintAccount.p2pkh(),
    inputs,
    outputs
  })

  console.log(`TX: https://explorer.glittr.fi/tx/${txid}`);
}
```

### 4. Asset Checking

The code provides two utility functions to check the status of assets:

```typescript
async function _checkingAssetFreeMint() {
  const mintTxid =
    "22acf70357c3adf8c3236e1c230b7c3d6796488825b963edd0d52ff13ba5a822";
  const mintVout = 0;
  const result = await fetch(
    `https://devnet-core-api.glittr.fi/assets/${mintTxid}/${mintVout}`
  );

  console.log(await result.text());
}
```

### Key Concepts

1. **Vesting Schedule**: The contract implements a linear vesting schedule where tokens are released in 25% increments over 4 blocks.
2. **Allocation Types**:
   * Direct allocation (vested)
   * Reserve allocation (vested)
   * Free mint allocation (unrestricted)
3. **Asset Verification**: The code includes methods to verify the status of both vested and free-minted assets through API calls.

### Usage Flow

1. Create the contract using `createContract()`
2. Wait for vesting periods to unlock
3. Use `vestedMint()` to claim vested tokens
4. Use `freeMint()` to mint from the free allocation
5. 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

```typescript
import {
  Account,
  GlittrSDK,
  Fraction,
  OpReturnMessage,
  electrumFetchNonGlittrUtxos,
  BitcoinUTXO,
  Output,
  addFeeToTx,
  txBuilder,
  BlockTxTuple,
} 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 account = new Account({
  wif: "...",
  network: NETWORK,
});

const reserveAccount = new Account({
  wif: "...",
  network: NETWORK,
});

const freeMintAccount = new Account({
  wif: "...",
  network: NETWORK,
});

async function deployVestingContract() {
  const receiver1PublicKey = Array.from(account.p2pkh().keypair.publicKey);
  const receiver2PublicKey = Array.from(
    reserveAccount.p2pkh().keypair.publicKey
  );

  const quarterlyVesting: [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
  ];

  const tx: 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()
            }
          }
        }
      }
    }
  }

  const address = account.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: account.p2pkh(),
    inputs,
    outputs
  })

  console.log(`TXID : ${txid}`)
}

async function vestedMint() {
  const contract: BlockTxTuple = [101832, 1]; // https://explorer.glittr.fi/tx/8bb7f3332eb1c50d25ae31c1a06c2af56dc7e2d2f37b03c275cf1d547bbdcc21

  const tx: OpReturnMessage = {
    contract_call: {
      contract,
      call_type: {
        mint: {
          pointer: 1 // Points to the mint receiver's index in Output array
        }
      }
    }
  }

  const address = reserveAccount.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 alwasy be OP_RETURN
    { address: address, value: 546 }
  ]

  const { inputs, outputs } = await addFeeToTx(NETWORK, address, utxos, nonFeeInputs, nonFeeOutputs)

  const txid = await client.createAndBroadcastRawTx({
    account: reserveAccount.p2pkh(),
    inputs,
    outputs
  })

  console.log(`TXID : ${txid}`)
}

async function freeMint() {
  const contract: BlockTxTuple = [101832, 1]; // https://explorer.glittr.fi/tx/8bb7f3332eb1c50d25ae31c1a06c2af56dc7e2d2f37b03c275cf1d547bbdcc21

  const tx: OpReturnMessage = {
    contract_call: {
      contract,
      call_type: {
        mint: {
          pointer: 1 // Points to the mint receiver's index in Output array
        }
      }
    }
  }

  const address = freeMintAccount.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 alwasy be OP_RETURN
    { address: address, value: 546 }
  ]

  const { inputs, outputs } = await addFeeToTx(NETWORK, address, utxos, nonFeeInputs, nonFeeOutputs)

  const txid = await client.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
 */
async function _checkingAssetFreeMint() {
  const mintTxid =
    "22acf70357c3adf8c3236e1c230b7c3d6796488825b963edd0d52ff13ba5a822";
  const mintVout = 0;
  const result = await fetch(
    `https://devnet-core-api.glittr.fi/assets/${mintTxid}/${mintVout}`
  );

  console.log(await result.text());
}

async function _checkingAssetVested() {
  const mintTxid =
    "82eda96aa5f9a0941b2b0f00b692aa389f54b210af23977f21e0006259f3282b";
  const mintVout = 0;
  const result = await fetch(
    `https://devnet-core-api.glittr.fi/assets/${mintTxid}/${mintVout}`
  );

  console.log(await result.text());
}

```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.glittr.fi/examples/vesting-and-freemint-contract.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
