# 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());
}

```
