Skip to main content

Wallet Example

Complete working example of a Hoosat wallet canister.

Basic Wallet

import Wallet "mo:hoosat-mo/wallet";
import Result "mo:base/Result";
import Errors "mo:hoosat-mo/errors";
import Debug "mo:base/Debug";
import HashMap "mo:base/HashMap";
import Principal "mo:base/Principal";

actor HoosatWallet {
// Initialize wallet
let wallet = Wallet.createMainnetWallet("dfx_test_key", ?"hoosat");

// Store user addresses
private var userAddresses = HashMap.HashMap<Principal, Text>(
10,
Principal.equal,
Principal.hash
);

// Generate address for caller
public shared(msg) func getMyAddress() : async Text {
let caller = msg.caller;

// Check if address already exists
switch (userAddresses.get(caller)) {
case (?addr) { return addr; };
case (null) {
// Generate new address
let result = await wallet.generateAddress(null, null);
switch (result) {
case (#ok(info)) {
userAddresses.put(caller, info.address);
return info.address;
};
case (#err(e)) {
Debug.print("Error: " # Errors.errorToText(e));
return "";
};
};
};
};
};

// Check balance
public shared(msg) func getMyBalance() : async Nat64 {
let addr = await getMyAddress();
if (addr == "") { return 0; };

let result = await wallet.getBalance(addr);
switch (result) {
case (#ok(balance)) { return balance; };
case (#err(e)) {
Debug.print("Error: " # Errors.errorToText(e));
return 0;
};
};
};

// Send transaction
public shared(msg) func send(to: Text, amount: Nat64) : async ?Text {
let from = await getMyAddress();
if (from == "") { return null; };

let result = await wallet.sendTransaction(from, to, amount, null, null);
switch (result) {
case (#ok(tx)) {
Debug.print("TX: " # tx.transactionId);
return ?tx.transactionId;
};
case (#err(e)) {
Debug.print("Error: " # Errors.errorToText(e));
return null;
};
};
};
};

Advanced Wallet with Features

import Wallet "mo:hoosat-mo/wallet";
import Validation "mo:hoosat-mo/validation";
import Errors "mo:hoosat-mo/errors";
import Result "mo:base/Result";
import Array "mo:base/Array";
import Time "mo:base/Time";
import HashMap "mo:base/HashMap";
import Principal "mo:base/Principal";

actor AdvancedWallet {
let wallet = Wallet.createMainnetWallet("dfx_test_key", ?"hoosat");

// Transaction history
type TxRecord = {
timestamp: Int;
from: Text;
to: Text;
amount: Nat64;
txId: Text;
status: Text;
};

private stable var txHistory : [TxRecord] = [];
private var balanceCache = HashMap.HashMap<Text, (Nat64, Int)>(
10,
Text.equal,
Text.hash
);

// Send with validation and logging
public func safeSend(
from: Text,
to: Text,
amount: Nat64
) : async Result.Result<Text, Errors.HoosatError> {
// Validate recipient
let addrVal = Validation.validateAddress(to);
switch (addrVal) {
case (#err(e)) { return #err(e); };
case (#ok(_)) {};
};

// Validate amount
if (amount < 1000) {
return #err(#InvalidAmount("Below dust threshold"));
};

// Send transaction
let result = await wallet.sendTransaction(from, to, amount, null, null);

switch (result) {
case (#ok(tx)) {
// Log transaction
let record : TxRecord = {
timestamp = Time.now();
from = from;
to = to;
amount = amount;
txId = tx.transactionId;
status = "pending";
};
txHistory := Array.append(txHistory, [record]);

return #ok(tx.transactionId);
};
case (#err(e)) {
return #err(e);
};
};
};

// Get cached balance
public func getCachedBalance(addr: Text) : async Nat64 {
let now = Time.now();
let ttl = 60_000_000_000; // 60 seconds

// Check cache
switch (balanceCache.get(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.put(addr, (balance, now));
return balance;
};
case (#err(_)) { return 0; };
};
};

// Get transaction history
public query func getTxHistory() : async [TxRecord] {
return txHistory;
};
};

Testing the Wallet

# Deploy
dfx deploy

# Generate address
dfx canister call hoosat_wallet getMyAddress

# Check balance
dfx canister call hoosat_wallet getMyBalance

# Send HTN (requires funded address)
dfx canister call hoosat_wallet send '("hoosat:qp...", 100000000)'