# Minting

Token minting creates the on-chain representation of a bond on the Internet Computer master ledger.


# Minting Flow

sequenceDiagram
    participant ISSUER as Issuer
    participant II as Issuer Interface
    participant ML as Master Ledger
    participant STORE as Metadata Store

    ISSUER->>II: Create Token Request
    II->>II: Validate Issuer Auth
    II->>ML: create_token(params)

    ML->>ML: Validate Parameters
    ML->>ML: Generate Token ID
    ML->>STORE: Store Metadata
    ML->>ML: Mint Initial Supply
    ML->>ML: Assign to Issuer Treasury

    ML-->>II: Token Created
    II-->>ISSUER: Token ID + Details

# Token Creation

# Create Token Request

type CreateTokenArgs = record {
    // Bond identification
    isin : Text;
    name : Text;
    symbol : Text;

    // Token parameters
    total_supply : nat;
    decimals : nat8;

    // Bond metadata
    bond_metadata : BondMetadata;

    // Compliance
    transfer_restrictions : TransferRestrictions;
};

type BondMetadata = record {
    issuer_name : Text;
    issuer_id : Text;
    maturity_date : Timestamp;
    coupon_rate_bps : nat16;        // Basis points
    coupon_frequency : CouponFrequency;
    collateral_type : Text;
    collateral_location : Text;
    prospectus_hash : Text;         // IPFS hash
    legal_docs_hash : Text;         // IPFS hash
};

type TransferRestrictions = record {
    kyc_required : bool;
    lock_period : opt Duration;
    max_holders : opt nat32;
    geographic_restrictions : vec Text;
};

# Token ID Generation

Token IDs are deterministically generated from the ISIN:

Token ID = SHA256(ISIN || Canister ID || Timestamp)
         = "trtg_ch1234567890_a1b2c3..."

# Token Data Model

# On-Chain Token Record

type Token = record {
    // Identity
    id : TokenId;
    isin : Text;
    name : Text;
    symbol : Text;

    // Supply
    total_supply : nat;
    circulating_supply : nat;
    decimals : nat8;

    // Metadata
    bond_metadata : BondMetadata;

    // State
    status : TokenStatus;
    created_at : Timestamp;
    created_by : Principal;

    // Compliance
    transfer_restrictions : TransferRestrictions;

    // Treasury
    treasury_balance : nat;
};

type TokenStatus = variant {
    Pending;        // Created but not yet active
    Active;         // Trading enabled
    Suspended;      // Trading halted
    Matured;        // Past maturity date
    Redeemed;       // Fully redeemed
};

# Initial State

After minting, the token is in this state:

Field Value
status Pending
total_supply As specified
circulating_supply 0
treasury_balance total_supply

# Metadata Storage

# On-Chain vs Off-Chain

flowchart TB
    subgraph On-Chain (Master Ledger)
        ID[Token ID]
        ISIN[ISIN]
        SUPPLY[Supply Info]
        STATUS[Status]
        HASHES[Document Hashes]
    end

    subgraph Off-Chain (IPFS)
        PROSPECTUS[Prospectus PDF]
        LEGAL[Legal Documents]
        IMAGES[Property Images]
        REPORTS[Valuation Reports]
    end

    HASHES --> PROSPECTUS
    HASHES --> LEGAL
    HASHES --> IMAGES
    HASHES --> REPORTS

# IPFS Document Structure

{
  "version": "1.0",
  "isin": "CH1234567890",
  "documents": {
    "prospectus": {
      "hash": "QmProspectusHash...",
      "name": "Prospectus_TRTG-DR1.pdf",
      "size": 2048576
    },
    "term_sheet": {
      "hash": "QmTermSheetHash...",
      "name": "TermSheet_TRTG-DR1.pdf",
      "size": 524288
    },
    "valuation": {
      "hash": "QmValuationHash...",
      "name": "Valuation_Report.pdf",
      "size": 1048576
    }
  },
  "collateral": {
    "type": "commercial_real_estate",
    "location": "Dominican Republic",
    "description": "Land development project",
    "images": [
      "QmImage1...",
      "QmImage2..."
    ]
  }
}

# Validation Rules

# Pre-Mint Validation

flowchart TB
    REQ[Create Token Request] --> V1{Valid ISIN?}
    V1 -->|No| E1[Error: Invalid ISIN]
    V1 -->|Yes| V2{ISIN Unique?}

    V2 -->|No| E2[Error: ISIN Exists]
    V2 -->|Yes| V3{Valid Symbol?}

    V3 -->|No| E3[Error: Invalid Symbol]
    V3 -->|Yes| V4{Valid Supply?}

    V4 -->|No| E4[Error: Invalid Supply]
    V4 -->|Yes| V5{Valid Metadata?}

    V5 -->|No| E5[Error: Invalid Metadata]
    V5 -->|Yes| MINT[Proceed with Minting]

# Validation Checks

Check Rule
ISIN Format Valid country code, 9 digits, valid check digit
ISIN Uniqueness Not already registered
Symbol 3-10 uppercase alphanumeric
Supply > 0, ≤ MAX_SUPPLY
Decimals 0-18 (typically 0 for bonds)
Maturity Date Future date
Coupon Rate 0-10000 bps (0-100%)
Document Hashes Valid IPFS CID format

# Issuer Treasury

After minting, all tokens are held in the issuer's treasury:

flowchart LR
    MINT[Mint 10,000 Tokens] --> TREASURY[Issuer Treasury]
    TREASURY --> DIST1[Distribution to Investor A]
    TREASURY --> DIST2[Distribution to Investor B]
    TREASURY --> DIST3[Distribution to Investor C]

# Treasury Operations

candid
service : {
    // Get treasury balance
    treasury_balance : (TokenId) -> (nat) query;

    // Distribute from treasury (issuer only)
    distribute : (DistributeArgs) -> (Result<TransactionId, Error>);

    // Return to treasury (issuer only, for buybacks)
    return_to_treasury : (ReturnArgs) -> (Result<TransactionId, Error>);
}

type DistributeArgs = record {
    token_id : TokenId;
    recipient : Principal;
    amount : nat;
    memo : opt Text;
};

# Token Activation

After minting, the token must be activated before trading:

sequenceDiagram
    participant ISSUER as Issuer
    participant ML as Master Ledger
    participant GOV as Governance

    Note over ISSUER,GOV: Token in Pending state

    ISSUER->>ML: activate_token(token_id)
    ML->>ML: Verify all metadata present
    ML->>ML: Verify collateral docs
    ML->>GOV: Log activation

    ML->>ML: Set status = Active
    ML-->>ISSUER: Token Activated

    Note over ISSUER,GOV: Trading now enabled

# Activation Checklist

Before activation:

  • All metadata fields populated
  • Document hashes verified
  • Collateral documentation complete
  • Issuer treasury funded
  • Compliance review passed

# Canister Interface

# Token Creation

candid
service : {
    // Create new token (issuer only)
    create_token : (CreateTokenArgs) -> (Result<TokenId, Error>);

    // Activate token for trading (issuer only)
    activate_token : (TokenId) -> (Result<(), Error>);

    // Get token details
    get_token : (TokenId) -> (opt Token) query;

    // List all tokens
    list_tokens : (opt TokenStatus) -> (vec Token) query;

    // Update metadata (issuer only, limited fields)
    update_metadata : (TokenId, MetadataUpdate) -> (Result<(), Error>);
}

# Error Types

type MintError = variant {
    NotAuthorized;
    InvalidIsin : Text;
    IsinAlreadyExists;
    InvalidSymbol : Text;
    InvalidSupply;
    InvalidMetadata : Text;
    InvalidDocumentHash : Text;
    MaturityInPast;
    InternalError : Text;
};

# Events

Token creation emits events for indexing and auditing:

type TokenEvent = variant {
    Created : record {
        token_id : TokenId;
        isin : Text;
        symbol : Text;
        total_supply : nat;
        created_by : Principal;
        timestamp : Timestamp;
    };
    Activated : record {
        token_id : TokenId;
        activated_by : Principal;
        timestamp : Timestamp;
    };
    MetadataUpdated : record {
        token_id : TokenId;
        updated_by : Principal;
        fields : vec Text;
        timestamp : Timestamp;
    };
};