Skip to main content

API Reference

Complete reference documentation for all Hoosat-mo modules.

Core Modules

Primary Modules (Production-Ready)

  • wallet.mo - Complete wallet functionality with transaction lifecycle
  • address.mo - Address generation, validation, and encoding
  • validation.mo - Input validation and security checks
  • errors.mo - Comprehensive error handling

Transaction Modules

Supporting Modules

Quick Reference

Common Imports

import Wallet "mo:hoosat-mo/wallet";
import Address "mo:hoosat-mo/address";
import Validation "mo:hoosat-mo/validation";
import Errors "mo:hoosat-mo/errors";
import Types "mo:hoosat-mo/types";
import Transaction "mo:hoosat-mo/transaction";
import Sighash "mo:hoosat-mo/sighash";

Type Overview

// Core types from types.mo
public type UTXO = {
transactionId: Text;
index: Nat32;
amount: Nat64;
scriptVersion: Nat16;
scriptPublicKey: Text;
address: Text;
};

public type HoosatTransaction = {
version: Nat16;
inputs: [TransactionInput];
outputs: [TransactionOutput];
lockTime: Nat64;
subnetworkId: Text;
gas: Nat64;
payload: Text;
};

// Result types from errors.mo
public type HoosatError = {
#InvalidAddress: Text;
#InvalidAmount: Text;
#InsufficientFunds: { available: Nat64; required: Nat64 };
#NetworkError: Text;
#SigningError: Text;
#ValidationError: Text;
#InternalError: Text;
};

Module Organization

Production Architecture

The package follows a layered architecture:

Application Layer

wallet.mo (High-level wallet operations)

validation.mo (Input validation)

transaction.mo + address.mo (Core operations)

sighash.mo (Cryptographic operations)

types.mo (Data structures)

Usage Patterns

For Simple Applications

Use the high-level wallet.mo module:

let wallet = Wallet.createMainnetWallet("key", ?"hoosat");
let result = await wallet.sendTransaction(from, to, amount, null, null);

For Advanced Control

Use lower-level modules directly:

import Address "mo:hoosat-mo/address";
import Transaction "mo:hoosat-mo/transaction";
import Sighash "mo:hoosat-mo/sighash";

// Build custom transaction
let tx = Transaction.buildTransaction(utxo, recipientScript, amount, fee, changeScript);

// Calculate signature hash
let hash = Sighash.calculateSighashEcdsa(tx, 0, utxo, Sighash.SigHashAll, reusedValues);

Error Handling

All modules use Result<T, HoosatError> for error handling:

import Result "mo:base/Result";
import Errors "mo:hoosat-mo/errors";

let result = await someOperation();
switch (result) {
case (#ok(value)) {
// Handle success
};
case (#err(error)) {
// Handle error
let errorMsg = Errors.errorToText(error);
Debug.print("Error: " # errorMsg);
};
};

Address Types

The package supports three address types:

import Address "mo:hoosat-mo/address";

// Schnorr (32-byte pubkey)
Address.SCHNORR // = 0

// ECDSA (33-byte pubkey)
Address.ECDSA // = 1

// Pay-to-Script-Hash (32-byte hash)
Address.P2SH // = 2

Signature Hash Types

Standard Hoosat sighash types:

import Sighash "mo:hoosat-mo/sighash";

Sighash.SigHashAll // 0x01 - Signs all inputs and outputs
Sighash.SigHashNone // 0x02 - Signs inputs only
Sighash.SigHashSingle // 0x04 - Signs inputs and one output
Sighash.SigHashAnyOneCanPay // 0x80 - Signs only current input
Sighash.SigHashAll_AnyOneCanPay // 0x81 - Combination
Sighash.SigHashNone_AnyOneCanPay // 0x82 - Combination
Sighash.SigHashSingle_AnyOneCanPay // 0x84 - Combination

Constants

Key constants used throughout the package:

// Address payload lengths
Address.SCHNORR_PAYLOAD_LEN // 32 bytes
Address.ECDSA_PAYLOAD_LEN // 33 bytes

// Transaction defaults
Transaction.DUST_THRESHOLD // 1,000 sompi
Transaction.DEFAULT_VERSION // 0
Transaction.DEFAULT_SEQUENCE // 0

// Network
Wallet.MAINNET_API // "https://api.network.hoosat.fi"
Wallet.TESTNET_API // "https://api.testnet.hoosat.fi" (if available)

Best Practices

1. Always Validate Inputs

import Validation "mo:hoosat-mo/validation";

let validation = Validation.validateAddress(address);
switch (validation) {
case (#ok(_)) { /* proceed */ };
case (#err(e)) { /* handle error */ };
};

2. Use Structured Error Handling

import Errors "mo:hoosat-mo/errors";

switch (result) {
case (#err(#InsufficientFunds(info))) {
Debug.print("Need: " # debug_show(info.required));
Debug.print("Have: " # debug_show(info.available));
};
case (#err(#NetworkError(msg))) {
Debug.print("Network issue: " # msg);
};
case (#err(error)) {
Debug.print(Errors.errorToText(error));
};
case (#ok(value)) { /* success */ };
};

3. Reuse Sighash Values

import Sighash "mo:hoosat-mo/sighash";

let reusedValues : Sighash.SighashReusedValues = {
var previousOutputsHash = null;
var sequencesHash = null;
var sigOpCountsHash = null;
var outputsHash = null;
var payloadHash = null;
};

// Calculate multiple sighashes efficiently
for (i in inputs.keys()) {
let hash = Sighash.calculateSighashEcdsa(
tx, i, utxos[i], Sighash.SigHashAll, reusedValues
);
};

4. Handle Dust Threshold

import Transaction "mo:hoosat-mo/transaction";

let DUST = 1000; // 1,000 sompi minimum

if (changeAmount < DUST) {
// Add to fee instead of creating change output
fee += changeAmount;
} else {
// Create change output
builder.addChangeOutput(changeAddress);
};

Performance Tips

Minimize HTTP Outcalls

HTTP outcalls are expensive (cycles). Cache results when possible:

private var balanceCache : [(Text, (Nat64, Nat64))] = [];

public func getCachedBalance(addr: Text, ttl: Nat64) : async Nat64 {
let now = Time.now();
switch (Array.find(balanceCache, func((a, _)) : Bool { a == addr })) {
case (?(_, (balance, timestamp))) {
if (now - timestamp < ttl) {
return balance;
};
};
case (null) {};
};

// Fetch fresh balance
let result = await wallet.getBalance(addr);
switch (result) {
case (#ok(balance)) {
balanceCache := Array.append(balanceCache, [(addr, (balance, now))]);
return balance;
};
case (#err(_)) { return 0; };
};
};

Batch Operations

Process multiple operations together:

public func checkMultipleBalances(
addresses: [Text]
) : async [Nat64] {
let results = Array.init<Nat64>(addresses.size(), 0);

for (i in addresses.keys()) {
let result = await wallet.getBalance(addresses[i]);
switch (result) {
case (#ok(balance)) { results[i] := balance; };
case (#err(_)) { results[i] := 0; };
};
};

Array.freeze(results)
};

Next Steps

Explore detailed documentation for each module:

  1. Wallet Module - High-level wallet operations
  2. Address Module - Address generation and validation
  3. Transaction Module - Transaction building
  4. Validation Module - Input validation
  5. Error Handling - Error types and handling

Additional Resources