# 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}`)
}
```


---

# 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/usd-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.
