# USD Contract

This page explains how to create a USD-pegged token using the Glittr SDK with oracle-based price feeds. The token's mint price will be determined by the current BTC/USD exchange rate.

### 1. Setup and Configuration

```typescript
import {
  Account,
  GlittrSDK,
  OpReturnMessage,
  electrumFetchNonGlittrUtxos,
  BitcoinUTXO,
  Output,
  addFeeToTx,
  txBuilder,
  BlockTxTuple,
} from "@glittr-sdk/sdk";
import {
  OracleMessage,
  OracleMessageSigned,
} from "@glittr-sdk/sdk/dist/transaction/calltype/types";
import { schnorr, getPublicKey } from "@noble/secp256k1";
import { sha256 } from "bitcoinjs-lib/src/crypto";

const NETWORK = "regtest";
const client = new GlittrSDK({
  network: NETWORK,
  apiKey: 'your-api-key',
  glittrApi: "https://devnet-core-api.glittr.fi", // devnet
  electrumApi: "https://devnet-electrum.glittr.fi" // devnet
});
```

We start by setting up the SDK client for the regtest network (development environment) and import necessary functions.

### 2. Account and Oracle Setup

```typescript
// Create accounts for different roles
const creatorAccount = new Account({
  wif: "...",
  network: NETWORK,
});

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

// Setup oracle for price feeds
const oraclePrivateKey = new Uint8Array([...]);
const oraclePubkey = Array.from(getPublicKey(oraclePrivateKey, true)).slice(1);
```

We set up:

* A creator account that will deploy the contract
* A minter account that will mint tokens
* An oracle account that will provide BTC/USD price feeds

### 3. Creating the USD-Pegged Contract

```typescript
async function deployUsdContract() {
  const tx: OpReturnMessage = {
    contract_creation: {
      contract_type: {
        moa: {
          divisibility: 1,
          live_time: 0,
          mint_mechanism: {
            purchase: {
              input_asset: 'raw_btc',
              ratio: {
                oracle: {
                  setting: {
                    pubkey: oraclePubkey,
                    asset_id: 'btc',
                    block_height_slippage: 5
                  }
                }
              }
            }
          }
        }
      }
    }
  }

  const utxos = await electrumFetchNonGlittrUtxos(client.electrumApi, client.apiKey, creatorAccount.p2pkh().address)
  const nonFeeInputs: BitcoinUTXO[] = []
  const nonFeeOutputs: Output[] = [
    { script: txBuilder.compile(tx), value: 0 },
    { address: creatorAccount.p2pkh().address, value: 546 }
  ]

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

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

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

The contract creation:

* Sets up a token with 1 decimal place precision
* Uses an oracle for price determination
* Allows a 5-block window for price updates
* Sends BTC to the creator's address during mints

### 4. Minting USD-Pegged Tokens

```typescript
async function mint() {
  const contract: BlockTxTuple = [101999, 1]

  // Get block height
  const blockHeightFetch = await fetch(`${client.electrumApi}/blocks/tip/height`)
  const blockHeight = await blockHeightFetch.json()

  // 1 BTC = 70000 usd
  // 1 sat = 0.0007
  // with divisibilty 8 => 1 sat = 70000
  // times 10**-8 for display

  const oracleMessage: OracleMessage = {
    asset_id: "btc",
    ratio: [70000, 1], // 1 sats = 70000 asset
    block_height: blockHeight,
  };

  const signature = await schnorr.sign(
    sha256(Buffer.from(JSON.stringify(oracleMessage), "ascii")).toString("hex"),
    oraclePrivateKey
  );

  const oracleSignedMessage: OracleMessageSigned = {
    signature: Array.from(signature),
    message: oracleMessage,
  };

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

  const utxos = await electrumFetchNonGlittrUtxos(client.electrumApi, client.apiKey, minterAccount.p2pkh().address)
  const nonFeeInputs: BitcoinUTXO[] = []
  const nonFeeOutputs: Output[] = [
    { script: txBuilder.compile(tx), value: 0 }, // Output #0 should always be OP_RETURN
    { address: minterAccount.p2pkh().address, value: 546 },
    { address: creatorAccount.p2pkh().address, value: 1000 },
  ]

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

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

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

The minting process:

1. Gets current block height
2. Creates an oracle message with the BTC/USD price
3. Signs the message with the oracle's private key
4. Creates and broadcasts a mint transaction

### 5. Checking Asset Details

```typescript
async function _checkingAsset() {
  const mintTxid = "cece25c03d7d2c1a297eab6eff89965989259953c0b55e08c3f1370a0ecdfdc8"
  const mintVout = 0
  const assetFetch = await fetch(`${client.glittrApi}/assets/${mintTxid}/${mintVout}`)
  const asset = await assetFetch.text()

  console.log(`Asset : ${asset}`)
}
```

This function allows you to check the details of minted assets.

### Key Concepts

1. **Oracle-Based Pricing**: The contract uses an oracle to determine the BTC/USD exchange rate
2. **Price Updates**: Allows a 5-block window for price updates to account for network delays
3. **USD Pegging**: Tokens are minted based on the current BTC/USD rate
4. **Example Rate**: In this example, 1 satoshi = 0.0007 USD (BTC price of \~$70,000)

This implementation creates a USD-pegged token where users can mint tokens by sending BTC, with the amount of tokens received based on the current BTC/USD exchange rate provided by the oracle.

### Usage Flow

1. **Setup**

   ```typescript
   // Initialize SDK and accounts
   const client = new GlittrSDK({...});
   const creatorAccount = new Account({...});
   const minterAccount = new Account({...});
   ```
2. **Create Contract**

   ```typescript
   await deployUsdContract();
   ```
3. **Mint Tokens**

   ```typescript
   await mint();
   ```
4. **Check Asset Details**

   ```typescript
   await _checkingAsset();
   ```

### Full Code Example

```typescript
import {
  Account,
  GlittrSDK,
  OpReturnMessage,
  electrumFetchNonGlittrUtxos,
  BitcoinUTXO,
  Output,
  addFeeToTx,
  txBuilder,
  BlockTxTuple,
} from "@glittr-sdk/sdk";
import {
  OracleMessage,
  OracleMessageSigned,
} from "@glittr-sdk/sdk/dist/transaction/calltype/types";
import { schnorr, getPublicKey } from "@noble/secp256k1";
import { sha256 } from "bitcoinjs-lib/src/crypto";

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,
});

// ORACLE
// Generate a random private key
const oraclePrivateKey = new Uint8Array([...]);

// Get the corresponding public key
const oraclePubkey = Array.from(getPublicKey(oraclePrivateKey, true)).slice(1);
console.log("Oracle public key:", Buffer.from(oraclePubkey).toString("hex"));

async function deployUsdContract() {
  const tx: OpReturnMessage = {
    contract_creation: {
      contract_type: {
        moa: {
          divisibility: 1,
          live_time: 0,
          mint_mechanism: {
            purchase: {
              input_asset: 'raw_btc',
              ratio: {
                oracle: {
                  setting: {
                    pubkey: oraclePubkey,
                    asset_id: 'btc',
                    block_height_slippage: 5
                  }
                }
              }
            }
          }
        }
      }
    }
  }

  const utxos = await electrumFetchNonGlittrUtxos(client.electrumApi, client.apiKey, creatorAccount.p2pkh().address)
  const nonFeeInputs: BitcoinUTXO[] = []
  const nonFeeOutputs: Output[] = [
    { script: txBuilder.compile(tx), value: 0 },
    { address: creatorAccount.p2pkh().address, value: 546 }
  ]

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

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

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

async function mint() {
  const contract: BlockTxTuple = [101999, 1]

  // Get block height
  const blockHeightFetch = await fetch(`${client.electrumApi}/blocks/tip/height`)
  const blockHeight = await blockHeightFetch.json()

  // 1 BTC = 70000 usd
  // 1 sat = 0.0007
  // with divisibilty 8 => 1 sat = 70000
  // times 10**-8 for display

  const oracleMessage: OracleMessage = {
    asset_id: "btc",
    ratio: [70000, 1], // 1 sats = 70000 asset
    block_height: blockHeight,
  };

  const signature = await schnorr.sign(
    sha256(Buffer.from(JSON.stringify(oracleMessage), "ascii")).toString("hex"),
    oraclePrivateKey
  );

  const oracleSignedMessage: OracleMessageSigned = {
    signature: Array.from(signature),
    message: oracleMessage,
  };

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

  const utxos = await electrumFetchNonGlittrUtxos(client.electrumApi, client.apiKey, minterAccount.p2pkh().address)
  const nonFeeInputs: BitcoinUTXO[] = []
  const nonFeeOutputs: Output[] = [
    { script: txBuilder.compile(tx), value: 0 }, // Output #0 should always be OP_RETURN
    { address: minterAccount.p2pkh().address, value: 546 },
    { address: creatorAccount.p2pkh().address, value: 1000 },
  ]

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

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

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

/**
 * Call deployUsdContract() function first
 * wait for confirmation and indexing
 * then call the mint() function
 */
deployUsdContract()


/**
 * Function to check asset after mint
 * change the mintTxId and mintVout
 * with your mint() fnction result
 */
async function _checkingAsset() {
  const mintTxid = "cece25c03d7d2c1a297eab6eff89965989259953c0b55e08c3f1370a0ecdfdc8"
  const mintVout = 0
  const assetFetch = await fetch(`${client.glittrApi}/assets/${mintTxid}/${mintVout}`)
  const asset = await assetFetch.text()

  console.log(`Asset : ${asset}`)
}
```
