Skip to main content

Totem Personal Node

Type: Personal infrastructure node
Audience: Power users, self-sovereign builders, multi-device wallet operators

Totem Personal Node keeps a Minima node running 24/7 on behalf of a single user, synchronising WOTS key state and spend policies across all of that user's devices. It is the foundation for any application that needs always-available address resolution or multi-device signing coordination.


Packages used

PackageRole in Totem Personal Node
@totemsdk/lookup-nodeRuns the Hyperswarm-based address lookup node
@totemsdk/lookup-protocolWire protocol for address announcements and queries
@totemsdk/agent-policyGoverns which spend requests are auto-approved vs. queued
@totemsdk/pureminima-rpcLow-level RPC for block sync and UTXO queries
@totemsdk/chain-providerHigh-level abstraction over the local Minima node
@totemsdk/wots-leaseShared WOTS lease strategy — one lease shared across devices
@totemsdk/realtimeReal-time push of new TxPoW events to connected devices

Core integration path

1. Start the lookup node

import { createLookupNode } from '@totemsdk/lookup-node';

const node = await createLookupNode({
seed: process.env.NODE_SEED!,
port: 9001,
announceInterval: 30_000,
});

node.on('query', async (query) => {
const result = await resolveFromLocalIndex(query.address);
return result;
});

await node.start();
console.log('Lookup node running, peer ID:', node.peerId);

2. Register addresses on the lookup network

import { LookupClient } from '@totemsdk/lookup-client';

const client = new LookupClient({ bootstrapPeers: BOOTSTRAP_NODES });

// Announce all wallet addresses to the lookup network
for (const account of wallet.getAccounts()) {
await client.announce({
address: account.address,
publicKey: account.publicKey,
nodeId: node.peerId,
});
}

3. Shared WOTS lease for multi-device signing

import { createSharedLeaseStrategy } from '@totemsdk/wots-lease';

// One lease shared across all devices — prevents index reuse
const leaseStrategy = createSharedLeaseStrategy({
storageKey: `personal-node:${userId}:wots-lease`,
storage: encryptedStorage,
maxSignaturesPerLease: 100,
renewThreshold: 0.8, // Renew when 80% used
});

const signer = await leaseStrategy.getSigner();

4. Personal spend policy

import type { AgentPolicy, AgentProposal } from '@totemsdk/agent-policy';

const personalPolicy: AgentPolicy = {
async evaluate(proposal: AgentProposal) {
// Always auto-approve from known trusted devices
if (TRUSTED_DEVICE_IDS.has(proposal.requestedBy.id)) {
return {
outcome: 'approved',
receipt: buildReceipt(proposal, 'trusted-device'),
};
}

// Queue unknown devices for manual confirmation
return {
outcome: 'requires_human',
prompt: `Unknown device ${proposal.requestedBy.id} wants to spend ${proposal.intent.amount} MIN`,
};
},
};

5. Real-time sync to connected devices

import { createRealtimeServer } from '@totemsdk/realtime';

const rtServer = createRealtimeServer({ port: 9004 });

// Push every new TxPoW that touches a watched address
rpc.on('NEWTXPOW', (txpow) => {
const touchedAddresses = extractTouchedAddresses(txpow);
for (const addr of touchedAddresses) {
rtServer.broadcast(addr, { type: 'newtxpow', txpow });
}
});

Future QVAC hook

Future QVAC hook

A QVAC agent attached to a personal node can auto-rebalance channel liquidity, monitor for unusual spend patterns and self-impose temporary rate limits, and auto-renew WOTS leases before exhaustion — all without any key exposure. The personalPolicy evaluator is the exact insertion point.