{"version":3,"file":"index.cjs","names":["WalletClient","PushDrop","LockingScript","toUTF8","toArray","normalizeBRC100ByteArray","normalizeBRC100ByteArray","WalletClient","toBase64","Random","stringifyBRC100","Transaction","Beef","LookupResolver","toArray","TopicBroadcaster"],"sources":["../src/constants.ts","../src/BTMSToken.ts","../src/utils.ts","../src/BTMSHelpers.ts","../src/BTMS.ts"],"sourcesContent":["/**\n * BTMS Protocol Constants\n *\n * Constants used throughout the BTMS core library.\n * These align with the BTMSTopicManager protocol.\n */\n\nimport type { WalletProtocol, SatoshiValue, BasketStringUnder300Bytes } from '@bsv/sdk'\n\n// ---------------------------------------------------------------------------\n// Protocol Constants\n// ---------------------------------------------------------------------------\n\n/** BTMS Topic Manager identifier */\nexport const BTMS_TOPIC = 'tm_btms'\n\n/** BTMS Lookup Service identifier */\nexport const BTMS_LOOKUP_SERVICE = 'ls_btms'\n\n/** Literal used in field[0] to indicate token issuance */\nexport const ISSUE_MARKER = 'ISSUE'\n\n/** Default satoshi value for BTMS token outputs */\nexport const DEFAULT_TOKEN_SATOSHIS = 1 as SatoshiValue\n\n/** Message box for BTMS token payments */\nexport const BTMS_MESSAGE_BOX = 'btms_tokens'\n\n// ---------------------------------------------------------------------------\n// Wallet Protocol Constants\n// ---------------------------------------------------------------------------\n\n/**\n * BTMS Protocol ID for wallet operations\n *\n * Format: [securityLevel, protocolName]\n * - Security level 0: No special security requirements\n * - Protocol name \"p btms\": Matches the basket prefix for consistency\n */\nexport const BTMS_PROTOCOL_ID: WalletProtocol = [0, 'p btms']\n\n// ---------------------------------------------------------------------------\n// Basket Constants\n// ---------------------------------------------------------------------------\n\n/**\n * Basket name for all BTMS tokens\n *\n * All BTMS token outputs are stored in a single basket: \"p btms\"\n * Individual assets are differentiated by:\n * - Tags: btms_issue, btms_change, btms_received, btms_send\n * - Token script content (assetId encoded in the token)\n *\n * This architecture allows efficient querying:\n * - Single listOutputs call to get all BTMS tokens\n * - Filter by tags to get owned tokens (issue/change/received)\n * - Decode scripts to discover unique assets\n */\nexport const BTMS_BASKET = 'p btms' as BasketStringUnder300Bytes\n\n// ---------------------------------------------------------------------------\n// Label Constants\n// ---------------------------------------------------------------------------\n\n/** Prefix for BTMS P-labels (BRC-111 format: `p <moduleId> <payload>`) */\nexport const BTMS_LABEL_PREFIX = 'p btms '\n\n// ---------------------------------------------------------------------------\n// Output Tag Constants\n// ---------------------------------------------------------------------------\n// Tags follow the format: btms_<category>_<value>\n// Examples: btms_type_issue, btms_direction_incoming, btms_assetid_<assetId>\n\n// ---------------------------------------------------------------------------\n// Validation Constants\n// ---------------------------------------------------------------------------\n\n/** Maximum allowed token amount */\nexport const MAX_TOKEN_AMOUNT = Number.MAX_SAFE_INTEGER\n\n/** Minimum allowed token amount */\nexport const MIN_TOKEN_AMOUNT = 1\n","import { toArray, toUTF8 } from '@bsv/sdk/primitives/utils'\n/**\n * BTMSToken - Token Encoding and Decoding\n *\n * This module handles the encoding and decoding of BTMS tokens using PushDrop.\n * It implements the exact 3-field schema expected by BTMSTopicManager:\n *\n * Field 0: assetId (or \"ISSUE\" for new tokens)\n * Field 1: amount (as UTF-8 string)\n * Field 2: metadata (optional JSON string)\n */\n\nimport {\n  LockingScript,\n  PushDrop,\n  WalletInterface,\n  WalletClient,\n  WalletProtocol,\n  WalletCounterparty\n} from '@bsv/sdk'\nimport type { BTMSTokenDecodeResult, DecodedBTMSToken } from './types.js'\nimport { BTMS_PROTOCOL_ID, ISSUE_MARKER, MIN_TOKEN_AMOUNT, MAX_TOKEN_AMOUNT } from './constants.js'\n\n/**\n * BTMSToken handles encoding and decoding of BTMS PushDrop tokens.\n *\n * The token format follows the BTMSTopicManager protocol exactly:\n * - Field 0: assetId or \"ISSUE\"\n * - Field 1: amount (positive integer as string)\n * - Field 2: metadata (optional JSON)\n *\n * @example\n * ```typescript\n * const token = new BTMSToken(wallet)\n *\n * // Create an issuance token\n * const lockScript = await token.createIssuance(1000, { name: 'MyToken' })\n *\n * // Create a transfer token\n * const transferScript = await token.createTransfer('abc123.0', 500, metadata, recipient)\n *\n * // Decode a token\n * const decoded = BTMSToken.decode(lockingScriptHex)\n * ```\n */\nexport class BTMSToken {\n  private readonly wallet: WalletInterface\n  private readonly protocolID: WalletProtocol\n  private readonly originator?: string\n\n  constructor(\n    wallet?: WalletInterface,\n    protocolID: WalletProtocol = BTMS_PROTOCOL_ID,\n    originator?: string\n  ) {\n    this.wallet = wallet ?? new WalletClient()\n    this.protocolID = protocolID\n    this.originator = originator\n  }\n\n  /**\n   * Create a token issuance locking script.\n   *\n   * Issuance tokens use \"ISSUE\" as field[0]. The canonical assetId\n   * becomes `{txid}.{outputIndex}` after the transaction is mined.\n   *\n   * @param amount - Number of tokens to issue (positive integer)\n   * @param keyID - Key ID for derivation\n   * @param metadata - Optional metadata object (will be JSON stringified)\n   * @param counterparty - Who can spend this token (default: 'self')\n   * @returns The locking script for the issuance output\n   */\n  async createIssuance(\n    amount: number,\n    keyID: string,\n    metadata?: Record<string, unknown>,\n    counterparty: WalletCounterparty = 'self'\n  ): Promise<LockingScript> {\n    this.validateAmount(amount)\n\n    const fields = this.buildFields(ISSUE_MARKER, amount, metadata)\n    const pushdrop = new PushDrop(this.wallet, this.originator)\n\n    return pushdrop.lock(fields, this.protocolID, keyID, counterparty, false)\n  }\n\n  /**\n   * Create a token transfer locking script.\n   *\n   * Transfer tokens reference an existing assetId in field[0].\n   * The metadata must match the original issuance metadata for the\n   * TopicManager to accept the output.\n   *\n   * @param assetId - The canonical asset ID (txid.outputIndex format)\n   * @param amount - Number of tokens to transfer (positive integer)\n   * @param metadata - Metadata (must match original issuance)\n   * @param counterparty - Recipient's identity key or 'self'\n   * @param keyID - key ID for derivation\n   * @param includeSignature - Whether to include PushDrop signature (default false, since signAction handles signing)\n   * @returns The locking script for the transfer output\n   */\n  async createTransfer(\n    assetId: string,\n    amount: number,\n    keyID: string,\n    counterparty: WalletCounterparty = 'self',\n    metadata?: string,\n    includeSignature = false\n  ): Promise<LockingScript> {\n    this.validateAmount(amount)\n    this.validateAssetId(assetId)\n\n    // For transfers, metadata is passed as-is (already stringified from original)\n    const fields = this.buildFieldsRaw(assetId, amount, metadata)\n    const pushdrop = new PushDrop(this.wallet, this.originator)\n\n    return pushdrop.lock(fields, this.protocolID, keyID, counterparty, false, includeSignature)\n  }\n\n  /**\n   * Create an unlocking script template for spending a BTMS token.\n   *\n   * @param counterparty - The counterparty used when the token was created\n   * @param keyID - Key ID for derivation from customInstructions\n   * @returns An unlocker that can sign transactions\n   */\n  createUnlocker(keyID: string, counterparty: WalletCounterparty = 'self') {\n    return new PushDrop(this.wallet, this.originator).unlock(this.protocolID, keyID, counterparty)\n  }\n\n  /**\n   * Decode a BTMS token from a locking script.\n   *\n   * This is a static method that can be used without a wallet instance.\n   *\n   * @param lockingScript - The locking script (hex string or LockingScript)\n   * @returns Decoded token data or invalid result\n   */\n  static decode(lockingScript: string | LockingScript): BTMSTokenDecodeResult {\n    try {\n      const script =\n        typeof lockingScript === 'string' ? LockingScript.fromHex(lockingScript) : lockingScript\n\n      const decoded = PushDrop.decode(script)\n      const fields = decoded.fields\n\n      // BTMS tokens have 2-4 fields:\n      // - Without signature: 2 fields (assetId, amount) or 3 fields (assetId, amount, metadata)\n      // - With signature: 3 fields (assetId, amount, signature) or 4 fields (assetId, amount, metadata, signature)\n      if (fields.length < 2 || fields.length > 4) {\n        return {\n          valid: false,\n          error: `Invalid field count: expected 2-4, got ${fields.length}`\n        }\n      }\n\n      // Decode fields\n      const assetId = toUTF8(fields[0])\n      const amountStr = toUTF8(fields[1])\n\n      // Try to get metadata from field 2 if it looks like JSON\n      let metadata: string | undefined\n      if (fields.length >= 3) {\n        const potentialMetadata = toUTF8(fields[2])\n        // Only treat as metadata if it starts with { (JSON object)\n        if (potentialMetadata.startsWith('{')) {\n          metadata = potentialMetadata\n        }\n      }\n\n      // Validate amount\n      const amount = Number(amountStr)\n      if (\n        !/^[1-9]\\d*$/.test(amountStr) ||\n        !Number.isSafeInteger(amount) ||\n        amount < MIN_TOKEN_AMOUNT ||\n        amount > MAX_TOKEN_AMOUNT\n      ) {\n        return {\n          valid: false,\n          error: `Invalid amount: ${amountStr}`\n        }\n      }\n\n      // Validate assetId format (either \"ISSUE\" or txid.outputIndex format)\n      if (assetId !== ISSUE_MARKER && !BTMSToken.isValidAssetId(assetId)) {\n        return {\n          valid: false,\n          error: `Invalid assetId format: ${assetId}`\n        }\n      }\n\n      // Validate metadata is valid JSON if present\n      if (metadata) {\n        try {\n          JSON.parse(metadata)\n        } catch {\n          return {\n            valid: false,\n            error: 'Metadata is not valid JSON'\n          }\n        }\n      }\n\n      return {\n        valid: true,\n        assetId,\n        amount,\n        metadata,\n        lockingPublicKey: decoded.lockingPublicKey.toString()\n      }\n    } catch (error) {\n      return {\n        valid: false,\n        error: error instanceof Error ? error.message : 'Failed to decode token'\n      }\n    }\n  }\n\n  /**\n   * Check if a string is a valid asset ID format (txid.outputIndex)\n   */\n  static isValidAssetId(assetId: string): boolean {\n    if (assetId === ISSUE_MARKER) return false\n\n    const parts = assetId.split('.')\n    if (parts.length !== 2) return false\n\n    const [txid, outputIndexStr] = parts\n\n    // txid should be 64 hex characters\n    if (!/^[a-fA-F0-9]{64}$/.test(txid)) return false\n\n    // outputIndex should be a non-negative integer\n    const outputIndex = Number(outputIndexStr)\n    if (!Number.isInteger(outputIndex) || outputIndex < 0) return false\n\n    return true\n  }\n\n  /**\n   * Check if a decoded token is an issuance\n   */\n  static isIssuance(decoded: DecodedBTMSToken): boolean {\n    return decoded.assetId === ISSUE_MARKER\n  }\n\n  /**\n   * Compute the canonical asset ID from a transaction ID and output index.\n   * This is used after an issuance transaction is mined.\n   */\n  static computeAssetId(txid: string, outputIndex: number): string {\n    return `${txid}.${outputIndex}`\n  }\n\n  // ---------------------------------------------------------------------------\n  // Private Methods\n  // ---------------------------------------------------------------------------\n\n  private validateAmount(amount: number): void {\n    if (!Number.isSafeInteger(amount)) {\n      throw new TypeError('Amount must be a safe integer')\n    }\n    if (amount < MIN_TOKEN_AMOUNT) {\n      throw new Error(`Amount must be at least ${MIN_TOKEN_AMOUNT}`)\n    }\n    if (amount > MAX_TOKEN_AMOUNT) {\n      throw new Error(`Amount must not exceed ${MAX_TOKEN_AMOUNT}`)\n    }\n  }\n\n  private validateAssetId(assetId: string): void {\n    if (!BTMSToken.isValidAssetId(assetId)) {\n      throw new Error(`Invalid assetId format: ${assetId}. Expected txid.outputIndex format.`)\n    }\n  }\n\n  private buildFields(\n    assetId: string,\n    amount: number,\n    metadata?: Record<string, unknown>\n  ): number[][] {\n    const fields: number[][] = [toArray(assetId, 'utf8'), toArray(String(amount), 'utf8')]\n\n    if (metadata && Object.keys(metadata).length > 0) {\n      fields.push(toArray(JSON.stringify(metadata), 'utf8'))\n    }\n\n    return fields\n  }\n\n  private buildFieldsRaw(assetId: string, amount: number, metadata?: string): number[][] {\n    const fields: number[][] = [toArray(assetId, 'utf8'), toArray(String(amount), 'utf8')]\n\n    if (metadata) {\n      fields.push(toArray(metadata, 'utf8'))\n    }\n\n    return fields\n  }\n}\n","/**\n * Utility functions for BTMS\n */\n\nimport { HexString, TXIDHexString, OutpointString } from '@bsv/sdk'\nimport { BTMSToken } from './BTMSToken.js'\nimport { DEFAULT_TOKEN_SATOSHIS, ISSUE_MARKER } from './constants.js'\n\n/**\n * Parsed custom instructions containing key derivation info\n */\nexport interface ParsedCustomInstructions {\n  /** The keyID string (derivationPrefix + ' ' + derivationSuffix) */\n  keyID: string\n  /** The sender's identity key (counterparty for unlocking) */\n  senderIdentityKey?: string\n}\n\n/**\n * Extract keyID and senderIdentityKey from customInstructions stored with a UTXO.\n *\n * @param customInstructions - The customInstructions JSON string\n * @param txid - Transaction ID (for error messages)\n * @param outputIndex - Output index (for error messages)\n * @returns Parsed instructions containing keyID and optional senderIdentityKey\n * @throws Error if customInstructions are missing or invalid\n */\nexport function parseCustomInstructions(\n  customInstructions: string | undefined,\n  txid: string,\n  outputIndex: number\n): ParsedCustomInstructions {\n  if (!customInstructions) {\n    throw new Error(`Missing customInstructions for UTXO ${txid}.${outputIndex}`)\n  }\n  try {\n    const instructions = JSON.parse(customInstructions)\n    if (\n      typeof instructions.derivationPrefix === 'string' &&\n      instructions.derivationPrefix.length > 0 &&\n      typeof instructions.derivationSuffix === 'string' &&\n      instructions.derivationSuffix.length > 0 &&\n      (instructions.senderIdentityKey === undefined ||\n        typeof instructions.senderIdentityKey === 'string')\n    ) {\n      return {\n        keyID: `${instructions.derivationPrefix} ${instructions.derivationSuffix}`,\n        senderIdentityKey: instructions.senderIdentityKey\n      }\n    } else {\n      throw new Error('Missing derivation info in customInstructions')\n    }\n  } catch (error) {\n    throw new Error(\n      `Invalid customInstructions for UTXO ${txid}.${outputIndex}: ${error instanceof Error ? error.message : 'Unknown error'}`\n    )\n  }\n}\n\n/**\n * Decode and extract token amount from an output locking script.\n * Handles ISSUE_MARKER conversion to canonical assetId.\n *\n * @param output - Output with locking script, satoshis, and index\n * @param txid - Transaction ID for computing asset ID from ISSUE_MARKER\n * @param assetId - Expected asset ID to match against\n * @returns Token amount if valid and matches assetId, null otherwise\n */\nexport function decodeOutputAmount(\n  output: { lockingScript?: HexString; satoshis: number; outputIndex: number },\n  txid: TXIDHexString,\n  assetId: string\n): number | null {\n  if (!output.lockingScript || output.satoshis !== DEFAULT_TOKEN_SATOSHIS) return null\n  const decoded = BTMSToken.decode(output.lockingScript)\n  if (!decoded.valid) return null\n\n  let outputAssetId = decoded.assetId\n  if (decoded.assetId === ISSUE_MARKER) {\n    outputAssetId = BTMSToken.computeAssetId(txid, output.outputIndex)\n  }\n\n  if (outputAssetId !== assetId) return null\n  return decoded.amount\n}\n\n/**\n * Decode and extract token amount from an input source locking script.\n * Handles ISSUE_MARKER conversion using source outpoint.\n *\n * @param input - Input with source locking script and outpoint\n * @param assetId - Expected asset ID to match against\n * @returns Token amount if valid and matches assetId, null otherwise\n */\nexport function decodeInputAmount(\n  input: { sourceLockingScript?: HexString; sourceOutpoint: OutpointString },\n  assetId: string\n): number | null {\n  if (!input.sourceLockingScript) return null\n  const decoded = BTMSToken.decode(input.sourceLockingScript)\n  if (!decoded.valid) return null\n\n  let inputAssetId = decoded.assetId\n  if (decoded.assetId === ISSUE_MARKER) {\n    const [sourceTxid, sourceIndex] = input.sourceOutpoint.split('.')\n    inputAssetId = BTMSToken.computeAssetId(sourceTxid, Number(sourceIndex))\n  }\n\n  if (inputAssetId !== assetId) return null\n  return decoded.amount\n}\n","/**\n * BTMSHelpers — private helper functions extracted from BTMS to reduce cognitive complexity.\n *\n * These functions are internal implementation details and are NOT part of the public API.\n */\n\nimport { BTMSToken } from './BTMSToken.js'\nimport { decodeOutputAmount, decodeInputAmount } from './utils.js'\nimport type {\n  BTMSAssetMetadata,\n  BTMSTransaction,\n  DecodedBTMSToken,\n  IncomingToken,\n  GetTransactionsResult\n} from './types.js'\nimport {\n  normalizeBRC100ByteArray,\n  type ListActionsResult,\n  type PubKeyHex,\n  type TXIDHexString\n} from '@bsv/sdk'\nimport { BTMS_LABEL_PREFIX, ISSUE_MARKER, DEFAULT_TOKEN_SATOSHIS } from './constants.js'\n\n/** Reject token values that cannot be represented exactly by the public number-based API. */\nexport function assertSafeTokenAmount(\n  amount: number,\n  label = 'Token amount',\n  allowZero = false\n): void {\n  const minimum = allowZero ? 0 : 1\n  if (!Number.isSafeInteger(amount) || amount < minimum) {\n    throw new RangeError(\n      `${label} must be a ${allowZero ? 'non-negative' : 'positive'} integer within the safe integer range`\n    )\n  }\n}\n\n/** Add token values without silently rounding above Number.MAX_SAFE_INTEGER. */\nexport function addTokenAmounts(left: number, right: number, label = 'Token amount'): number {\n  assertSafeTokenAmount(left, label, true)\n  assertSafeTokenAmount(right, label, true)\n  const total = left + right\n  assertSafeTokenAmount(total, label, true)\n  return total\n}\n\n/** Subtract token values without permitting an underflow or inexact result. */\nexport function subtractTokenAmounts(left: number, right: number, label = 'Token amount'): number {\n  assertSafeTokenAmount(left, label, true)\n  assertSafeTokenAmount(right, label, true)\n  if (right > left) throw new RangeError(`${label} must not be negative`)\n  return left - right\n}\n\n// ---------------------------------------------------------------------------\n// getTransactions helpers\n// ---------------------------------------------------------------------------\n\n/** Strip the BTMS label prefix and return payload strings. */\nexport function stripLabelPrefix(labels: string[]): string[] {\n  return labels.map(l => (l.startsWith(BTMS_LABEL_PREFIX) ? l.slice(BTMS_LABEL_PREFIX.length) : l))\n}\n\n/** Derive the transaction type from label payloads. */\nexport function parseTxType(payloads: string[]): 'issue' | 'send' | 'receive' | 'burn' {\n  if (payloads.some(l => l.includes('type issue'))) return 'issue'\n  if (payloads.some(l => l.includes('type receive'))) return 'receive'\n  if (payloads.some(l => l.includes('type burn'))) return 'burn'\n  return 'send'\n}\n\n/** Extract the counterparty key from label payloads. */\nexport function parseTxCounterparty(payloads: string[]): PubKeyHex | undefined {\n  const found = payloads.find(l => l.startsWith('counterparty '))\n  return found ? found.replace('counterparty ', '') : undefined\n}\n\n/** Extract a numeric timestamp from label payloads. */\nexport function parseTxTimestamp(payloads: string[]): number | undefined {\n  const found = payloads.find(l => l.startsWith('timestamp '))\n  if (!found) return undefined\n  const n = Number(found.replace('timestamp ', ''))\n  return Number.isFinite(n) ? n : undefined\n}\n\n/** Sum token amounts from outputs whose tag matches `tagName`. */\nexport function sumOutputAmountsByTag(\n  outputs: NonNullable<ListActionsResult['actions'][number]['outputs']>,\n  tagName: string,\n  txid: TXIDHexString,\n  assetId: string\n): number {\n  let total = 0\n  for (const output of outputs) {\n    if (!output.tags?.includes(tagName)) continue\n    const amt = decodeOutputAmount(output, txid, assetId)\n    if (amt !== null) total = addTokenAmounts(total, amt, 'Transaction output total')\n  }\n  return total\n}\n\n/** Sum token amounts from all inputs. */\nexport function sumInputAmounts(\n  inputs: NonNullable<ListActionsResult['actions'][number]['inputs']>,\n  assetId: string\n): number {\n  let total = 0\n  for (const input of inputs) {\n    const amt = decodeInputAmount(input, assetId)\n    if (amt !== null) total = addTokenAmounts(total, amt, 'Transaction input total')\n  }\n  return total\n}\n\n/** Calculate the display amount for an `issue` or `receive` action. */\nexport function calcSimpleOutputAmount(\n  action: ListActionsResult['actions'][number],\n  tagName: string,\n  assetId: string\n): number {\n  if (!action.outputs) return 0\n  return sumOutputAmountsByTag(action.outputs, tagName, action.txid, assetId)\n}\n\n/** Calculate the amount sent (outputs tagged `btms_type_send`, with input-minus-change fallback). */\nexport function calcSendAmount(\n  action: ListActionsResult['actions'][number],\n  assetId: string\n): number {\n  const sendOutputs = action.outputs?.filter(o => o.tags?.includes('btms_type_send')) ?? []\n  let decoded = 0\n  let total = 0\n\n  for (const output of sendOutputs) {\n    const amt = decodeOutputAmount(output, action.txid, assetId)\n    if (amt !== null) {\n      total = addTokenAmounts(total, amt, 'Transaction send total')\n      decoded += 1\n    }\n  }\n\n  if (decoded > 0) return total\n\n  // Fallback: inputs − change\n  const inputAmount = action.inputs ? sumInputAmounts(action.inputs, assetId) : 0\n  const changeAmount = action.outputs\n    ? sumOutputAmountsByTag(action.outputs, 'btms_type_change', action.txid, assetId)\n    : 0\n  return subtractTokenAmounts(inputAmount, changeAmount, 'Transaction send amount')\n}\n\n/** Calculate the amount burned (inputs − change). */\nexport function calcBurnAmount(\n  action: ListActionsResult['actions'][number],\n  assetId: string\n): number {\n  const inputAmount = action.inputs ? sumInputAmounts(action.inputs, assetId) : 0\n  const changeAmount = action.outputs\n    ? sumOutputAmountsByTag(action.outputs, 'btms_type_change', action.txid, assetId)\n    : 0\n  return subtractTokenAmounts(inputAmount, changeAmount, 'Transaction burn amount')\n}\n\n/** Calculate display amount for any action type. */\nexport function calcActionAmount(\n  action: ListActionsResult['actions'][number],\n  type: 'issue' | 'send' | 'receive' | 'burn',\n  assetId: string\n): number {\n  switch (type) {\n    case 'issue':\n      return calcSimpleOutputAmount(action, 'btms_type_issue', assetId)\n    case 'receive':\n      return calcSimpleOutputAmount(action, 'btms_type_receive', assetId)\n    case 'send':\n      return calcSendAmount(action, assetId)\n    case 'burn':\n      return calcBurnAmount(action, assetId)\n  }\n}\n\n/** Map a single `listActions` action into a `BTMSTransaction`. */\nexport function mapActionToTransaction(\n  action: ListActionsResult['actions'][number],\n  assetId: string\n): BTMSTransaction {\n  const payloads = stripLabelPrefix(action.labels ?? [])\n  const type = parseTxType(payloads)\n  const counterparty = parseTxCounterparty(payloads)\n  const timestamp = parseTxTimestamp(payloads)\n  const direction: 'incoming' | 'outgoing' =\n    type === 'send' || type === 'burn' ? 'outgoing' : 'incoming'\n  let amount = calcActionAmount(action, type, assetId)\n  if (direction === 'outgoing') amount = -amount\n\n  return {\n    txid: action.txid,\n    type,\n    direction,\n    amount,\n    assetId,\n    counterparty,\n    description: action.description,\n    status: action.status === 'completed' ? 'completed' : 'pending',\n    timestamp\n  }\n}\n\n/** Build a full `GetTransactionsResult` from a `ListActionsResult`. */\nexport function buildTransactionsResult(\n  result: ListActionsResult,\n  assetId: string\n): GetTransactionsResult {\n  const transactions = result.actions.map(action => mapActionToTransaction(action, assetId))\n  return {\n    transactions,\n    total: result.totalActions || transactions.length\n  }\n}\n\n// ---------------------------------------------------------------------------\n// listAssets helpers\n// ---------------------------------------------------------------------------\n\nexport interface AssetAccumulator {\n  balance: number\n  metadata?: BTMSAssetMetadata\n}\n\n/** Attempt to parse metadata (string or object). Returns undefined on failure. */\nexport function parseMetadata(raw: unknown): BTMSAssetMetadata | undefined {\n  if (!raw) return undefined\n  try {\n    return typeof raw === 'string' ? JSON.parse(raw) : (raw as BTMSAssetMetadata)\n  } catch {\n    return undefined\n  }\n}\n\n/** Resolve the assetId for one output (handles ISSUE_MARKER). */\nexport function resolveOutputAssetId(\n  decoded: DecodedBTMSToken,\n  outpoint: string\n): string | undefined {\n  if (decoded.assetId === ISSUE_MARKER) {\n    const [txid, outputIndexStr] = outpoint.split('.')\n    const id = BTMSToken.computeAssetId(txid, Number(outputIndexStr))\n    return BTMSToken.isValidAssetId(id) ? id : undefined\n  }\n  return BTMSToken.isValidAssetId(decoded.assetId) ? decoded.assetId : undefined\n}\n\n/** Process one wallet output and accumulate its contribution into `assetBalances`. */\nexport function accumulateOutputIntoBalances(\n  output: { spendable?: boolean; satoshis?: number; outpoint: string; lockingScript?: string },\n  assetBalances: Map<string, AssetAccumulator>\n): void {\n  if (!output.spendable) return\n  if (output.satoshis !== DEFAULT_TOKEN_SATOSHIS) return\n\n  const decoded = BTMSToken.decode(output.lockingScript ?? '')\n  if (!decoded.valid) return\n\n  const assetId = resolveOutputAssetId(decoded, output.outpoint)\n  if (!assetId) return\n\n  const current = assetBalances.get(assetId) ?? { balance: 0 }\n  current.balance = addTokenAmounts(current.balance, decoded.amount, 'Asset balance')\n  current.metadata ??= parseMetadata(decoded.metadata)\n  assetBalances.set(assetId, current)\n}\n\n/** Parse a single raw message body into an `IncomingToken`. Returns null on failure. */\nexport function parseIncomingMessage(msg: {\n  body: string\n  messageId?: string\n  sender?: string\n}): IncomingToken | null {\n  try {\n    const payment = JSON.parse(msg.body) as IncomingToken\n    if (payment.beef !== undefined) {\n      const beef = normalizeBRC100ByteArray(payment.beef)\n      if (beef == null) return null\n      if (beef.length === 0) return null\n      payment.beef = beef\n    }\n    if (msg.messageId !== undefined) payment.messageId = msg.messageId\n    if (msg.sender !== undefined) payment.sender = msg.sender\n    return payment\n  } catch {\n    return null\n  }\n}\n\n// ---------------------------------------------------------------------------\n// getSpendableTokens helpers\n// ---------------------------------------------------------------------------\n\n/** Return true if the decoded token belongs to the target `assetId`. */\nexport function tokenMatchesAsset(\n  decoded: DecodedBTMSToken,\n  outpoint: string,\n  assetId: string\n): boolean {\n  if (decoded.assetId === ISSUE_MARKER) {\n    const [txid, outputIndexStr] = outpoint.split('.')\n    return BTMSToken.computeAssetId(txid, Number(outputIndexStr)) === assetId\n  }\n  return decoded.assetId === assetId\n}\n\n// ---------------------------------------------------------------------------\n// findBadOutputs helpers\n// ---------------------------------------------------------------------------\n\nexport interface BadOutput {\n  outpoint: string\n  reason: string\n}\n\n/** Validate a single output and return a `BadOutput` entry, or null if valid. */\nexport function validateOutputForBadness(output: {\n  outpoint: string\n  spendable?: boolean\n  satoshis?: number\n  lockingScript?: string\n}): BadOutput | null {\n  if (!output.spendable) return null\n\n  if (output.satoshis !== DEFAULT_TOKEN_SATOSHIS) {\n    return { outpoint: output.outpoint, reason: 'Unexpected satoshi value' }\n  }\n  if (!output.lockingScript) {\n    return { outpoint: output.outpoint, reason: 'Missing locking script' }\n  }\n\n  try {\n    const decoded = BTMSToken.decode(output.lockingScript)\n    if (!decoded.valid) {\n      return { outpoint: output.outpoint, reason: decoded.error ?? 'Invalid token encoding' }\n    }\n  } catch (error) {\n    return {\n      outpoint: output.outpoint,\n      reason: error instanceof Error ? error.message : 'Failed to decode token'\n    }\n  }\n\n  return null\n}\n\n// ---------------------------------------------------------------------------\n// verifyOwnership helpers\n// ---------------------------------------------------------------------------\n\n/** Verify that a single proven token's asset ID matches the proof's assetId. */\nexport function verifyProvenTokenAssetId(\n  decoded: DecodedBTMSToken,\n  txid: string,\n  outputIndex: number,\n  expectedAssetId: string\n): void {\n  const tokenAssetId =\n    decoded.assetId === ISSUE_MARKER ? BTMSToken.computeAssetId(txid, outputIndex) : decoded.assetId\n  if (tokenAssetId !== expectedAssetId) {\n    throw new Error('Token asset ID does not match proof asset ID')\n  }\n}\n","import { toArray, toBase64 } from '@bsv/sdk/primitives/utils'\nimport {\n  WalletClient,\n  Transaction,\n  Beef,\n  TopicBroadcaster,\n  LookupResolver,\n  LockingScript,\n  CreateActionArgs,\n  CreateActionOutput,\n  ListOutputsResult,\n  ListOutputsArgs,\n  ListActionsResult,\n  TXIDHexString,\n  HexString,\n  PubKeyHex,\n  LabelStringUnder300Bytes,\n  OutputTagStringUnder300Bytes,\n  Random,\n  WalletInterface,\n  CommsLayer,\n  AtomicBEEF,\n  normalizeBRC100ByteArray,\n  stringifyBRC100\n} from '@bsv/sdk'\nimport { BTMSToken } from './BTMSToken.js'\nimport { parseCustomInstructions } from './utils.js'\nimport {\n  accumulateOutputIntoBalances,\n  parseIncomingMessage,\n  buildTransactionsResult,\n  tokenMatchesAsset,\n  validateOutputForBadness,\n  verifyProvenTokenAssetId,\n  addTokenAmounts,\n  subtractTokenAmounts,\n  assertSafeTokenAmount,\n  type AssetAccumulator,\n  type BadOutput\n} from './BTMSHelpers.js'\nimport type {\n  BTMSConfig,\n  BTMSAsset,\n  BTMSAssetMetadata,\n  BTMSTokenOutput,\n  IssueResult,\n  SendResult,\n  AcceptResult,\n  RefundResult,\n  TokenForRecipient,\n  IncomingToken,\n  OwnershipProof,\n  ProvenToken,\n  ProveOwnershipResult,\n  VerifyOwnershipResult,\n  SelectionOptions,\n  SelectionResult,\n  ChangeStrategyOptions,\n  ChangeContext,\n  ChangeOutput,\n  BurnResult,\n  GetTransactionsResult\n} from './types.js'\nimport {\n  BTMS_TOPIC,\n  BTMS_LOOKUP_SERVICE,\n  BTMS_PROTOCOL_ID,\n  BTMS_BASKET,\n  BTMS_LABEL_PREFIX,\n  BTMS_MESSAGE_BOX,\n  DEFAULT_TOKEN_SATOSHIS,\n  ISSUE_MARKER\n} from './constants.js'\n\ntype UtxoVerificationResult = {\n  utxo: BTMSTokenOutput\n  found: boolean\n  beef?: Beef\n}\n\nfunction normalizeIncomingTokenBeef(value: unknown): AtomicBEEF | undefined {\n  if (value === undefined) return undefined\n  const beef = normalizeBRC100ByteArray(value)\n  if (beef == null || beef.length === 0) {\n    throw new Error('Incoming token BEEF must be a non-empty BRC-100 byte array')\n  }\n  return beef\n}\n\nfunction requireWalletVerdict(\n  result: unknown,\n  field: 'accepted' | 'relinquished',\n  operation: string\n): void {\n  if (\n    typeof result !== 'object' ||\n    result === null ||\n    (result as Record<string, unknown>)[field] !== true\n  ) {\n    throw new Error(`Wallet did not ${operation}`)\n  }\n}\n\n/**\n * BTMS - Basic Token Management System\n *\n * @example\n * ```typescript\n * // Create a BTMS instance\n * const btms = new BTMS()\n *\n * // Issue new tokens\n * const result = await btms.issue(1000, { name: 'GOLD', description: 'A test token' })\n * console.log('Asset ID:', result.assetId)\n *\n * // Check balance\n * const balance = await btms.getBalance(result.assetId)\n * console.log('Balance:', balance)\n *\n * // Send tokens\n * await btms.send(result.assetId, recipientPubKey, 100)\n *\n * // List all assets\n * const assets = await btms.listAssets()\n * ```\n */\nexport class BTMS {\n  private readonly wallet: WalletInterface\n  private readonly networkPreset: NonNullable<BTMSConfig['networkPreset']>\n  private readonly comms?: CommsLayer\n  private tokenTemplate: BTMSToken\n  private cachedIdentityKey?: PubKeyHex\n  private originator?: string\n  private static readonly LIST_OUTPUTS_PAGE_SIZE = 1000\n  private static readonly MAX_LIST_OUTPUTS_PAGES = 1000\n  private static readonly BROADCAST_MAX_ATTEMPTS = 3\n\n  constructor(config: BTMSConfig = {}) {\n    // Apply defaults\n    this.wallet = config.wallet ?? new WalletClient('auto')\n    this.networkPreset = config.networkPreset ?? 'mainnet'\n    this.comms = config.comms\n\n    this.tokenTemplate = new BTMSToken(this.wallet, BTMS_PROTOCOL_ID, this.originator)\n  }\n\n  /**\n   * Set the originator for wallet calls.\n   * This is passed through to all wallet operations.\n   */\n  setOriginator(originator: string): void {\n    this.originator = originator\n    // Recreate token template with new originator\n    this.tokenTemplate = new BTMSToken(this.wallet, BTMS_PROTOCOL_ID, this.originator)\n  }\n\n  // ---------------------------------------------------------------------------\n  // Token Issuance\n  // ---------------------------------------------------------------------------\n\n  /**\n   * Issue new BTMS tokens.\n   *\n   * Creates a new token with the specified amount and optional metadata.\n   * The token will be stored in basket 'p btms <assetId>' where assetId is\n   * the canonical txid.0 format determined after transaction creation.\n   *\n   * @param amount - Number of tokens to issue (positive integer)\n   * @param metadata - Optional metadata including name, description, iconURL, etc.\n   * @returns Issue result with txid and assetId\n   *\n   * @example\n   * ```typescript\n   * const result = await btms.issue(1000000, {\n   *   name: 'GOLD',\n   *   description: 'Represents 1 gram of gold',\n   *   iconURL: 'https://example.com/gold.png' // or a UHRP url\n   * })\n   * console.log('Asset ID:', result.assetId) // e.g., 'abc123...def.0'\n   * ```\n   */\n  async issue(amount: number, metadata?: BTMSAssetMetadata): Promise<IssueResult> {\n    try {\n      // Generate random derivation keys for privacy\n      const derivationPrefix = toBase64(Random(32))\n      const derivationSuffix = toBase64(Random(32))\n      const keyID = `${derivationPrefix} ${derivationSuffix}`\n\n      // Create the issuance locking script\n      const lockingScript = await this.tokenTemplate.createIssuance(amount, keyID, metadata)\n      const lockingScriptHex = lockingScript.toHex()\n\n      const tokenName = metadata?.name ?? 'tokens'\n\n      const monthLabel = this.getMonthLabel()\n      const timestampLabel = this.getTimestampLabel()\n      const monthTag = this.getMonthTag()\n      const timestampTag = this.getTimestampTag()\n      const counterparty = await this.getIdentityKey()\n\n      // Build the action WITHOUT a basket - we'll internalize after to use the real assetId\n      const args: CreateActionArgs = {\n        description: `Issue ${amount} ${tokenName}`,\n        labels: [\n          `${BTMS_LABEL_PREFIX}type issue`,\n          `${BTMS_LABEL_PREFIX}direction incoming`,\n          timestampLabel,\n          monthLabel,\n          `${BTMS_LABEL_PREFIX}counterparty ${counterparty}`\n        ],\n        outputs: [\n          {\n            satoshis: DEFAULT_TOKEN_SATOSHIS,\n            lockingScript: lockingScriptHex,\n            customInstructions: stringifyBRC100({\n              derivationPrefix,\n              derivationSuffix\n            }),\n            outputDescription: `Issue ${amount} ${tokenName}`,\n            tags: [\n              'btms_type_issue',\n              'btms_direction_incoming',\n              timestampTag,\n              monthTag,\n              `btms_counterparty_${counterparty}`\n            ]\n          }\n        ],\n        options: {\n          acceptDelayedBroadcast: false,\n          randomizeOutputs: false\n        }\n      }\n\n      // Create the action (no basket yet)\n      const createResult = await this.wallet.createAction(args)\n\n      if (!createResult.tx || !createResult.txid) {\n        throw new Error('Transaction creation failed - no tx returned')\n      }\n\n      // Get the txid to compute the canonical assetId\n      const assetId = BTMSToken.computeAssetId(createResult.txid, 0)\n\n      // Now internalize the action into the BTMS basket\n      const internalizeResult = await this.wallet.internalizeAction({\n        tx: createResult.tx,\n        labels: [\n          `${BTMS_LABEL_PREFIX}type issue`,\n          `${BTMS_LABEL_PREFIX}direction incoming`,\n          timestampLabel,\n          monthLabel,\n          `${BTMS_LABEL_PREFIX}assetId ${assetId}`,\n          `${BTMS_LABEL_PREFIX}counterparty ${counterparty}`\n        ],\n        outputs: [\n          {\n            outputIndex: 0,\n            protocol: 'basket insertion',\n            insertionRemittance: {\n              basket: BTMS_BASKET,\n              customInstructions: stringifyBRC100({\n                derivationPrefix,\n                derivationSuffix\n              }),\n              tags: [\n                'btms_type_issue',\n                'btms_direction_incoming',\n                timestampTag,\n                monthTag,\n                `btms_assetid_${assetId}`,\n                `btms_counterparty_${counterparty}`\n              ]\n            }\n          }\n        ],\n        description: `Issue ${amount} ${tokenName}`\n      })\n      requireWalletVerdict(internalizeResult, 'accepted', 'accept the issued token')\n\n      // Broadcast to overlay\n      await this.broadcastWithRetry(\n        Transaction.fromAtomicBEEF(createResult.tx),\n        `issuance ${createResult.txid}`\n      )\n\n      return {\n        success: true,\n        txid: createResult.txid,\n        assetId,\n        outputIndex: 0,\n        amount\n      }\n    } catch (error) {\n      return {\n        success: false,\n        txid: '',\n        assetId: '',\n        outputIndex: 0,\n        amount,\n        error: error instanceof Error ? error.message : 'Unknown error'\n      }\n    }\n  }\n\n  // ---------------------------------------------------------------------------\n  // Token Transfers\n  // ---------------------------------------------------------------------------\n\n  /**\n   * Send tokens to a recipient.\n   *\n   * Selects UTXOs to cover the amount, creates transfer outputs,\n   * and broadcasts the transaction. If a messenger is configured,\n   * also sends the token data to the recipient.\n   *\n   * @param assetId - The asset to send\n   * @param recipient - Recipient's identity public key\n   * @param amount - Amount to send\n   * @param options - Optional send options including change strategy\n   * @returns Send result with transaction details\n   */\n  async send(\n    assetId: string,\n    recipient: PubKeyHex,\n    amount: number,\n    options: { changeStrategy?: ChangeStrategyOptions } = {}\n  ): Promise<SendResult> {\n    try {\n      // Validate inputs\n      if (!BTMSToken.isValidAssetId(assetId)) {\n        throw new Error(`Invalid assetId: ${assetId}`)\n      }\n      assertSafeTokenAmount(amount, 'Amount')\n\n      // Fetch spendable UTXOs for this asset\n      const { tokens: utxos } = await this.getSpendableTokens(assetId)\n\n      if (utxos.length === 0) {\n        throw new Error(`No spendable tokens found for asset ${assetId}`)\n      }\n\n      // Select and verify UTXOs on the overlay\n      const { selected, totalInput, inputBeef } = await this.selectAndVerifyUTXOs(utxos, amount)\n\n      if (totalInput < amount) {\n        throw new Error(`Insufficient balance on overlay. Have ${totalInput}, need ${amount}`)\n      }\n\n      // Get metadata from first selected UTXO (must be consistent)\n      const metadata = selected[0].token.metadata\n      this.assertConsistentMetadata(selected, metadata)\n\n      // Build outputs\n      const outputs: CreateActionOutput[] = []\n      const monthLabel = this.getMonthLabel()\n      const timestampLabel = this.getTimestampLabel()\n      const monthTag = this.getMonthTag()\n      const timestampTag = this.getTimestampTag()\n\n      // Generate random derivation for recipient output\n      const transferDerivationPrefix = toBase64(Random(32))\n      const recipientDerivationSuffix = toBase64(Random(32))\n      const recipientKeyID = `${transferDerivationPrefix} ${recipientDerivationSuffix}`\n\n      // Recipient output\n      const recipientScript = await this.tokenTemplate.createTransfer(\n        assetId,\n        amount,\n        recipientKeyID,\n        recipient,\n        metadata,\n        false\n      )\n      const recipientScriptHex = recipientScript.toHex()\n\n      outputs.push({\n        satoshis: DEFAULT_TOKEN_SATOSHIS,\n        lockingScript: recipientScriptHex,\n        customInstructions: stringifyBRC100({\n          derivationPrefix: transferDerivationPrefix,\n          derivationSuffix: recipientDerivationSuffix\n        }),\n        outputDescription: `Send ${amount} tokens`,\n        tags: [\n          'btms_type_send',\n          'btms_direction_outgoing',\n          timestampTag,\n          monthTag,\n          `btms_assetid_${assetId}`,\n          `btms_counterparty_${recipient}`\n        ]\n      })\n\n      // Change outputs (if needed)\n      const changeAmount = subtractTokenAmounts(totalInput, amount, 'Change amount')\n      if (changeAmount > 0) {\n        const changeOutputItems = await this.buildChangeOutputs(\n          { changeAmount, paymentAmount: amount, totalInput, assetId },\n          options.changeStrategy,\n          transferDerivationPrefix,\n          metadata\n        )\n        for (const item of changeOutputItems) outputs.push(item)\n      }\n\n      // Build inputs\n      const inputs = selected.map(u => ({\n        outpoint: u.outpoint,\n        unlockingScriptLength: 74,\n        inputDescription: `Spend ${u.token.amount} tokens`\n      }))\n\n      const completeInputBeef =\n        inputBeef instanceof Beef\n          ? await this.ensureCompleteInputBeef(\n              selected.map(u => ({ txid: u.txid, outputIndex: u.outputIndex })),\n              inputBeef,\n              assetId\n            )\n          : inputBeef\n\n      // Create the action with BEEF from overlay\n      const createArgs: CreateActionArgs = {\n        description: `Send ${amount} tokens to ${recipient.slice(0, 8)}...`,\n        labels: [\n          `${BTMS_LABEL_PREFIX}type send`,\n          `${BTMS_LABEL_PREFIX}direction outgoing`,\n          timestampLabel,\n          monthLabel,\n          `${BTMS_LABEL_PREFIX}assetId ${assetId}`,\n          `${BTMS_LABEL_PREFIX}counterparty ${recipient}`\n        ],\n        inputBEEF: completeInputBeef.toBinary(),\n        inputs,\n        outputs,\n        options: {\n          acceptDelayedBroadcast: false,\n          randomizeOutputs: false\n        }\n      }\n\n      const { signableTransaction } = await this.wallet.createAction(createArgs)\n\n      if (!signableTransaction) {\n        throw new Error('Failed to create signable transaction')\n      }\n\n      const spends = await this.buildSpendsForInputs(selected, signableTransaction.tx)\n      const { tx: signedTx, txid } = await this.signAndBroadcast(\n        signableTransaction.reference,\n        spends\n      )\n\n      // Build token data for recipient\n      const tokenForRecipient: TokenForRecipient = {\n        txid,\n        outputIndex: 0,\n        lockingScript: recipientScriptHex,\n        amount,\n        satoshis: DEFAULT_TOKEN_SATOSHIS,\n        beef: signedTx,\n        customInstructions: stringifyBRC100({\n          derivationPrefix: transferDerivationPrefix,\n          derivationSuffix: recipientDerivationSuffix\n        }),\n        assetId,\n        metadata\n      }\n\n      // Send to recipient via comms layer (if configured and not sending to self)\n      if (this.comms) {\n        await this.comms.sendMessage({\n          recipient,\n          messageBox: BTMS_MESSAGE_BOX,\n          body: stringifyBRC100(tokenForRecipient)\n        })\n      }\n\n      return {\n        success: true,\n        txid,\n        tokenForRecipient,\n        changeAmount: changeAmount > 0 ? changeAmount : undefined\n      }\n    } catch (error) {\n      return {\n        success: false,\n        txid: '',\n        tokenForRecipient: {} as TokenForRecipient,\n        error: error instanceof Error ? error.message : 'Unknown error'\n      }\n    }\n  }\n\n  // ---------------------------------------------------------------------------\n  // Burning Tokens\n  // ---------------------------------------------------------------------------\n\n  /**\n   * Burn (destroy) tokens permanently.\n   *\n   * This operation spends token UTXOs without creating corresponding outputs,\n   * effectively destroying the tokens. This is useful when tokens represent\n   * claims on physical assets that have been redeemed (e.g., trading gold\n   * tokens for physical gold).\n   *\n   * @param assetId - The asset to burn\n   * @param amount - Amount to burn (if undefined, burns entire balance)\n   * @param options - Optional change strategy for remaining balance\n   * @returns Burn result with transaction details\n   *\n   * @example\n   * ```typescript\n   * // Burn 50 tokens\n   * const result = await btms.burn('abc123.0', 50)\n   *\n   * // Burn entire balance\n   * const result = await btms.burn('abc123.0')\n   * ```\n   */\n  async burn(\n    assetId: string,\n    amount?: number,\n    options: { changeStrategy?: ChangeStrategyOptions } = {}\n  ): Promise<BurnResult> {\n    try {\n      // Validate inputs\n      if (!BTMSToken.isValidAssetId(assetId)) {\n        throw new Error(`Invalid assetId: ${assetId}`)\n      }\n      if (amount !== undefined) assertSafeTokenAmount(amount, 'Amount')\n\n      // Fetch spendable UTXOs for this asset\n      const { tokens: utxos } = await this.getSpendableTokens(assetId)\n\n      if (utxos.length === 0) {\n        throw new Error(`No spendable tokens found for asset ${assetId}`)\n      }\n\n      // Calculate total available\n      const totalAvailable = utxos.reduce(\n        (sum, u) => addTokenAmounts(sum, u.token.amount, 'Available balance'),\n        0\n      )\n\n      // Determine amount to burn\n      const amountToBurn = amount ?? totalAvailable\n\n      if (amountToBurn > totalAvailable) {\n        throw new Error(\n          `Insufficient balance. Have ${totalAvailable}, trying to burn ${amountToBurn}`\n        )\n      }\n\n      // Select UTXOs to cover the amount to burn\n      const { selected, totalInput, inputBeef } = await this.selectAndVerifyUTXOs(\n        utxos,\n        amountToBurn\n      )\n\n      // Get metadata from first selected UTXO (for change output if needed)\n      const metadata = selected[0].token.metadata\n\n      // Build outputs (only change if partial burn)\n      const outputs: CreateActionOutput[] = []\n      const changeAmount = subtractTokenAmounts(totalInput, amountToBurn, 'Change amount')\n      const monthLabel = this.getMonthLabel()\n      const timestampLabel = this.getTimestampLabel()\n      const counterparty = await this.getIdentityKey()\n\n      if (changeAmount > 0) {\n        const changeDerivationPrefix = toBase64(Random(32))\n        const changeOutputItems = await this.buildChangeOutputs(\n          { changeAmount, paymentAmount: amountToBurn, totalInput, assetId },\n          options.changeStrategy,\n          changeDerivationPrefix,\n          metadata\n        )\n        for (const item of changeOutputItems) outputs.push(item)\n      }\n\n      // Build inputs - note: inputDescription should reflect what's happening to the tokens\n      // The actual burn amount is amountToBurn, change goes back to user\n      const inputs = selected.map((u, i) => ({\n        outpoint: u.outpoint,\n        unlockingScriptLength: 74,\n        inputDescription:\n          i === 0\n            ? `Burn ${amountToBurn} tokens (from UTXO with ${u.token.amount})`\n            : `Input ${u.token.amount} tokens for burn`\n      }))\n\n      const completeInputBeef =\n        inputBeef instanceof Beef\n          ? await this.ensureCompleteInputBeef(\n              selected.map(u => ({ txid: u.txid, outputIndex: u.outputIndex })),\n              inputBeef,\n              assetId\n            )\n          : inputBeef\n\n      // Create the action\n      const createArgs: CreateActionArgs = {\n        description: `Burn ${amountToBurn} tokens of ${assetId.slice(0, 8)}...`,\n        labels: [\n          `${BTMS_LABEL_PREFIX}type burn`,\n          `${BTMS_LABEL_PREFIX}direction incoming`,\n          timestampLabel,\n          monthLabel,\n          `${BTMS_LABEL_PREFIX}assetId ${assetId}`,\n          `${BTMS_LABEL_PREFIX}counterparty ${counterparty}`\n        ],\n        inputBEEF: completeInputBeef.toBinary(),\n        inputs,\n        outputs,\n        options: {\n          acceptDelayedBroadcast: false,\n          randomizeOutputs: false\n        }\n      }\n\n      const { signableTransaction } = await this.wallet.createAction(createArgs)\n\n      if (!signableTransaction) {\n        throw new Error('Failed to create signable transaction')\n      }\n\n      const spends = await this.buildSpendsForInputs(selected, signableTransaction.tx)\n      const txid = await this.signAndBroadcastBurn(\n        signableTransaction.reference,\n        spends,\n        changeAmount\n      )\n\n      return {\n        success: true,\n        txid,\n        assetId,\n        amountBurned: amountToBurn\n      }\n    } catch (error) {\n      return {\n        success: false,\n        txid: '',\n        assetId,\n        amountBurned: 0,\n        error: error instanceof Error ? error.message : 'Unknown error'\n      }\n    }\n  }\n\n  // ---------------------------------------------------------------------------\n  // Receiving Tokens\n  // ---------------------------------------------------------------------------\n\n  /**\n   * List incoming token payments (requires comms layer).\n   *\n   * @param assetId - Optional filter by asset ID\n   * @returns List of incoming payments\n   */\n  async listIncoming(assetId?: string): Promise<IncomingToken[]> {\n    if (!this.comms) {\n      return []\n    }\n\n    const messages = await this.comms.listMessages({\n      messageBox: BTMS_MESSAGE_BOX\n    })\n\n    const payments: IncomingToken[] = []\n    for (const msg of messages) {\n      const payment = parseIncomingMessage(msg)\n      if (payment != null && (!assetId || payment.assetId === assetId)) {\n        payments.push(payment)\n      }\n    }\n\n    return payments\n  }\n\n  /**\n   * Accept an incoming token.\n   *\n   * Verifies the token on the overlay, internalizes it into the wallet,\n   * and acknowledges receipt via the messenger.\n   *\n   * @param token - The incoming token to accept\n   * @returns Accept result\n   */\n  async accept(token: IncomingToken): Promise<AcceptResult> {\n    try {\n      const beef = normalizeIncomingTokenBeef(token.beef)\n      // Decode and validate the token\n      const decoded = BTMSToken.decode(token.lockingScript)\n      if (!decoded.valid) {\n        throw new Error(`Invalid token: ${decoded.error}`)\n      }\n\n      // Verify the token exists on the overlay\n      const { found: isOnOverlay } = await this.lookupTokenOnOverlay(token.txid, token.outputIndex)\n\n      // Re-broadcast if token is not on overlay\n      if (!isOnOverlay && beef != null) {\n        const tx = Transaction.fromBEEF(beef)\n        try {\n          await this.broadcastWithRetry(tx, `accept rebroadcast ${token.txid}`)\n        } catch {\n          throw new Error('Token not found on overlay and broadcast failed!')\n        }\n      }\n\n      // We must verify we can unlock this token in the future!\n      // Parse customInstructions to get key derivation parameters\n      const { keyID } = parseCustomInstructions(\n        token.customInstructions,\n        token.txid,\n        token.outputIndex\n      )\n\n      // Derive the public key we would use to unlock this token\n      const { publicKey: derivedPubKey } = await this.wallet.getPublicKey({\n        protocolID: BTMS_PROTOCOL_ID,\n        keyID,\n        counterparty: token.sender,\n        forSelf: true\n      })\n\n      // Compare with the locking public key embedded in the script\n      if (decoded.lockingPublicKey !== derivedPubKey) {\n        throw new Error(\n          `Key derivation mismatch: expected ${decoded.lockingPublicKey}, derived ${derivedPubKey}. ` +\n            `Cannot unlock this token with the provided customInstructions.`\n        )\n      }\n\n      // Internalize the token into the wallet\n      // Augment customInstructions with senderIdentityKey so we can unlock later\n      const originalInstructions = JSON.parse(token.customInstructions)\n      const augmentedInstructions = stringifyBRC100({\n        ...originalInstructions,\n        senderIdentityKey: token.sender\n      })\n      const monthLabel = this.getMonthLabel()\n      const timestampLabel = this.getTimestampLabel()\n      const monthTag = this.getMonthTag()\n      const timestampTag = this.getTimestampTag()\n\n      const internalizeResult = await this.wallet.internalizeAction({\n        tx: beef as AtomicBEEF,\n        labels: [\n          `${BTMS_LABEL_PREFIX}type receive`,\n          `${BTMS_LABEL_PREFIX}direction incoming`,\n          timestampLabel,\n          monthLabel,\n          `${BTMS_LABEL_PREFIX}assetId ${token.assetId}`,\n          `${BTMS_LABEL_PREFIX}counterparty ${token.sender}`\n        ],\n        outputs: [\n          {\n            outputIndex: token.outputIndex,\n            protocol: 'basket insertion',\n            insertionRemittance: {\n              basket: BTMS_BASKET,\n              customInstructions: augmentedInstructions,\n              tags: [\n                'btms_type_receive',\n                'btms_direction_incoming',\n                timestampTag,\n                monthTag,\n                `btms_assetid_${token.assetId}`,\n                `btms_counterparty_${token.sender}`\n              ]\n            }\n          }\n        ],\n        description: `Receive ${token.amount} tokens`,\n        seekPermission: true\n      })\n      requireWalletVerdict(internalizeResult, 'accepted', 'accept the incoming token')\n\n      // Acknowledge receipt via comms layer\n      if (this.comms && token.messageId) {\n        await this.comms.acknowledgeMessage({\n          messageIds: [token.messageId]\n        })\n      }\n\n      return {\n        success: true,\n        assetId: token.assetId,\n        amount: token.amount\n      }\n    } catch (error) {\n      return {\n        success: false,\n        assetId: token.assetId,\n        amount: token.amount,\n        error: error instanceof Error ? error.message : 'Unknown error'\n      }\n    }\n  }\n\n  /**\n   * Refund an incoming token back to the sender without internalizing it.\n   *\n   * Verifies the token, spends it, and sends a new token of equal value\n   * back to the original sender. The original incoming message is acknowledged\n   * so it disappears from the receiver's incoming list.\n   *\n   * @param token - The incoming token to refund\n   * @returns Refund result\n   */\n  async refundIncoming(token: IncomingToken): Promise<RefundResult> {\n    try {\n      if (!this.comms) {\n        throw new Error('Comms layer is required to refund incoming tokens')\n      }\n      const beef = normalizeIncomingTokenBeef(token.beef)\n\n      // Decode and validate the token\n      const decoded = BTMSToken.decode(token.lockingScript)\n      if (!decoded.valid) {\n        throw new Error(`Invalid token: ${decoded.error}`)\n      }\n\n      // Verify the token exists on the overlay (fetch BEEF if possible)\n      const overlayLookup = await this.lookupTokenOnOverlay(token.txid, token.outputIndex, true)\n\n      // Re-broadcast if token is not on overlay\n      if (!overlayLookup.found && beef != null) {\n        const tx = Transaction.fromBEEF(beef)\n        try {\n          await this.broadcastWithRetry(tx, `refund rebroadcast ${token.txid}`)\n        } catch {\n          throw new Error('Token not found on overlay and broadcast failed!')\n        }\n      }\n\n      const inputBeef =\n        overlayLookup.beef ?? (beef != null ? Beef.fromBinaryStrict(beef) : undefined)\n\n      if (!inputBeef) {\n        throw new Error('Missing BEEF data required to refund token')\n      }\n\n      const completeInputBeef =\n        inputBeef instanceof Beef\n          ? await this.ensureCompleteInputBeef(\n              [{ txid: token.txid, outputIndex: token.outputIndex }],\n              inputBeef\n            )\n          : inputBeef\n\n      // Validate ability to unlock this token\n      const { keyID } = parseCustomInstructions(\n        token.customInstructions,\n        token.txid,\n        token.outputIndex\n      )\n\n      const { publicKey: derivedPubKey } = await this.wallet.getPublicKey({\n        protocolID: BTMS_PROTOCOL_ID,\n        keyID,\n        counterparty: token.sender,\n        forSelf: true\n      })\n\n      if (decoded.lockingPublicKey !== derivedPubKey) {\n        throw new Error(\n          `Key derivation mismatch: expected ${decoded.lockingPublicKey}, derived ${derivedPubKey}. ` +\n            `Cannot unlock this token with the provided customInstructions.`\n        )\n      }\n\n      const monthLabel = this.getMonthLabel()\n      const timestampLabel = this.getTimestampLabel()\n      const monthTag = this.getMonthTag()\n      const timestampTag = this.getTimestampTag()\n\n      // Create a new transfer back to the sender\n      const refundDerivationPrefix = toBase64(Random(32))\n      const refundDerivationSuffix = toBase64(Random(32))\n      const refundKeyID = `${refundDerivationPrefix} ${refundDerivationSuffix}`\n\n      const refundScript = await this.tokenTemplate.createTransfer(\n        token.assetId,\n        token.amount,\n        refundKeyID,\n        token.sender,\n        decoded.metadata,\n        false\n      )\n\n      const outputs: CreateActionOutput[] = [\n        {\n          satoshis: DEFAULT_TOKEN_SATOSHIS,\n          lockingScript: refundScript.toHex(),\n          customInstructions: stringifyBRC100({\n            derivationPrefix: refundDerivationPrefix,\n            derivationSuffix: refundDerivationSuffix\n          }),\n          outputDescription: `Refund ${token.amount} tokens`,\n          tags: [\n            'btms_type_send',\n            'btms_direction_outgoing',\n            timestampTag,\n            monthTag,\n            `btms_assetid_${token.assetId}`,\n            `btms_counterparty_${token.sender}`\n          ]\n        }\n      ]\n\n      const inputs = [\n        {\n          outpoint: `${token.txid}.${token.outputIndex}`,\n          unlockingScriptLength: 74,\n          inputDescription: `Refund ${token.amount} tokens`\n        }\n      ]\n\n      const createArgs: CreateActionArgs = {\n        description: `Refund ${token.amount} tokens to ${token.sender.slice(0, 8)}...`,\n        labels: [\n          `${BTMS_LABEL_PREFIX}type send`,\n          `${BTMS_LABEL_PREFIX}direction outgoing`,\n          timestampLabel,\n          monthLabel,\n          `${BTMS_LABEL_PREFIX}assetId ${token.assetId}`,\n          `${BTMS_LABEL_PREFIX}counterparty ${token.sender}`\n        ],\n        inputBEEF: completeInputBeef.toBinary(),\n        inputs,\n        outputs,\n        options: {\n          acceptDelayedBroadcast: false,\n          randomizeOutputs: false\n        }\n      }\n\n      const { signableTransaction } = await this.wallet.createAction(createArgs)\n\n      if (!signableTransaction) {\n        throw new Error('Failed to create signable transaction')\n      }\n\n      const originalInstructions = JSON.parse(token.customInstructions)\n      const refundInstructions = stringifyBRC100({\n        ...originalInstructions,\n        senderIdentityKey: token.sender\n      })\n\n      const selectedUtxo: BTMSTokenOutput = {\n        outpoint: `${token.txid}.${token.outputIndex}`,\n        txid: token.txid,\n        outputIndex: token.outputIndex,\n        satoshis: token.satoshis,\n        lockingScript: token.lockingScript,\n        customInstructions: refundInstructions,\n        token: decoded,\n        spendable: true,\n        beef\n      }\n\n      const spends = await this.buildSpendsForInputs([selectedUtxo], signableTransaction.tx)\n      const { tx: signedTx, txid } = await this.signAndBroadcast(\n        signableTransaction.reference,\n        spends\n      )\n\n      const tokenForRecipient: TokenForRecipient = {\n        txid,\n        outputIndex: 0,\n        lockingScript: refundScript.toHex(),\n        amount: token.amount,\n        satoshis: DEFAULT_TOKEN_SATOSHIS,\n        beef: signedTx,\n        customInstructions: stringifyBRC100({\n          derivationPrefix: refundDerivationPrefix,\n          derivationSuffix: refundDerivationSuffix\n        }),\n        assetId: token.assetId,\n        metadata: decoded.metadata\n      }\n\n      await this.comms.sendMessage({\n        recipient: token.sender,\n        messageBox: BTMS_MESSAGE_BOX,\n        body: stringifyBRC100(tokenForRecipient)\n      })\n\n      if (token.messageId) {\n        await this.comms.acknowledgeMessage({\n          messageIds: [token.messageId]\n        })\n      }\n\n      return {\n        success: true,\n        txid,\n        assetId: token.assetId,\n        amount: token.amount\n      }\n    } catch (error) {\n      return {\n        success: false,\n        txid: '',\n        assetId: token.assetId,\n        amount: token.amount,\n        error: error instanceof Error ? error.message : 'Unknown error'\n      }\n    }\n  }\n\n  // ---------------------------------------------------------------------------\n  // Balance and Asset Queries\n  // ---------------------------------------------------------------------------\n\n  /**\n   * Get the balance of a specific asset.\n   *\n   * @param assetId - The asset to check\n   * @returns Total spendable balance\n   */\n  async getBalance(assetId: string): Promise<number> {\n    const { tokens: utxos } = await this.getSpendableTokens(assetId)\n    return utxos.reduce((sum, u) => addTokenAmounts(sum, u.token.amount, 'Asset balance'), 0)\n  }\n\n  /**\n   * Get info for a specific asset by ID using a targeted tag-based query.\n   * Uses the assetId label to efficiently find outputs for this asset.\n   *\n   * @param assetId - The asset ID to look up\n   * @returns Asset info with name and metadata, or null if not found\n   */\n  async getAssetInfo(\n    assetId: string\n  ): Promise<{ name?: string; metadata?: BTMSAssetMetadata } | null> {\n    if (!BTMSToken.isValidAssetId(assetId)) return null\n    return await this.lookupAssetMetadataOnOverlay(assetId)\n  }\n\n  /**\n   * Lookup asset metadata from the overlay using assetId and BEEF.\n   */\n  private async lookupAssetMetadataOnOverlay(\n    assetId: string\n  ): Promise<{ name?: string; metadata?: BTMSAssetMetadata } | null> {\n    try {\n      const lookup = new LookupResolver({ networkPreset: this.networkPreset })\n      const result = await lookup.query({\n        service: BTMS_LOOKUP_SERVICE,\n        query: { assetId, limit: 1 }\n      })\n\n      if (result.type !== 'output-list' || result.outputs.length === 0) {\n        return null\n      }\n\n      const output = result.outputs[0] as { context: any; outputIndex: number; beef?: number[] }\n      if (!output.beef) return null\n      const tx = Transaction.fromBEEF(output.beef)\n      const lockingScript = tx.outputs[output.outputIndex]?.lockingScript\n      if (!lockingScript) return null\n\n      const decoded = BTMSToken.decode(lockingScript)\n      if (!decoded.valid) return null\n\n      const resolvedAssetId =\n        decoded.assetId === ISSUE_MARKER ? `${tx.id('hex')}.${output.outputIndex}` : decoded.assetId\n\n      if (resolvedAssetId !== assetId) {\n        return null\n      }\n\n      if (decoded.metadata) {\n        const meta =\n          typeof decoded.metadata === 'string' ? JSON.parse(decoded.metadata) : decoded.metadata\n        return { name: meta?.name, metadata: meta }\n      }\n      return { name: undefined, metadata: undefined }\n    } catch {\n      return null\n    }\n  }\n\n  /**\n   * List all assets owned by this wallet.\n   *\n   * @returns List of assets with balances\n   */\n  async listAssets(): Promise<BTMSAsset[]> {\n    const assetIds = new Set<string>()\n    // Discover assets using a single basket query; compute balances in one pass.\n    const assetBalances = new Map<string, AssetAccumulator>()\n\n    await this.collectOwnedTokensIntoBalances(assetIds, assetBalances)\n    const allIncoming = await this.collectIncomingMessages(assetIds)\n    return this.buildAssetList(assetIds, assetBalances, allIncoming)\n  }\n\n  /** Scan basket outputs and populate `assetIds` + `assetBalances`. */\n  private async collectOwnedTokensIntoBalances(\n    assetIds: Set<string>,\n    assetBalances: Map<string, AssetAccumulator>\n  ): Promise<void> {\n    try {\n      const pages = await this.listOutputsPaged({\n        basket: BTMS_BASKET,\n        tags: ['btms_type_issue', 'btms_type_change', 'btms_type_receive'],\n        tagQueryMode: 'any',\n        include: 'locking scripts'\n      })\n      for (const page of pages) {\n        for (const output of page.outputs) {\n          accumulateOutputIntoBalances(output, assetBalances)\n        }\n      }\n      for (const assetId of assetBalances.keys()) assetIds.add(assetId)\n    } catch (error) {\n      console.warn(\n        `[BTMS] listAssets failed to read wallet outputs: ${error instanceof Error ? error.message : String(error)}`\n      )\n    }\n  }\n\n  /** Fetch pending incoming messages and add their asset IDs to `assetIds`. */\n  private async collectIncomingMessages(assetIds: Set<string>): Promise<IncomingToken[]> {\n    const allIncoming: IncomingToken[] = []\n    if (!this.comms) return allIncoming\n    try {\n      const messages = await this.comms.listMessages({ messageBox: BTMS_MESSAGE_BOX })\n      for (const msg of messages) {\n        const payment = parseIncomingMessage(msg)\n        if (!payment) continue\n        allIncoming.push(payment)\n        if (BTMSToken.isValidAssetId(payment.assetId)) assetIds.add(payment.assetId)\n      }\n    } catch {\n      console.warn('[BTMS] listAssets failed to read incoming comms messages')\n    }\n    return allIncoming\n  }\n\n  /** Build the final `BTMSAsset[]` from accumulated data. */\n  private buildAssetList(\n    assetIds: Set<string>,\n    assetBalances: Map<string, AssetAccumulator>,\n    allIncoming: IncomingToken[]\n  ): BTMSAsset[] {\n    const assets: BTMSAsset[] = []\n    for (const assetId of assetIds) {\n      const assetData = assetBalances.get(assetId)\n      const balance = assetData?.balance ?? 0\n      const metadata = assetData?.metadata\n      const hasPendingIncoming = allIncoming.some(p => p.assetId === assetId)\n      if (balance > 0 || hasPendingIncoming) {\n        assets.push({ assetId, name: metadata?.name, balance, metadata, hasPendingIncoming })\n      }\n    }\n    return assets\n  }\n\n  /**\n   * Get transaction history for an asset.\n   *\n   * @param assetId - The asset to query\n   * @param limit - Maximum number of transactions to return\n   * @param offset - Number of transactions to skip (for pagination)\n   * @returns Transaction history with pagination info\n   */\n  async getTransactions(assetId: string, limit = 50, offset = 0): Promise<GetTransactionsResult> {\n    const result: ListActionsResult = await this.wallet.listActions({\n      labels: [`${BTMS_LABEL_PREFIX}assetId ${assetId}`],\n      labelQueryMode: 'all',\n      includeLabels: true,\n      includeOutputs: true,\n      includeInputs: true,\n      includeInputSourceLockingScripts: true,\n      includeOutputLockingScripts: true,\n      limit,\n      offset\n    })\n    return buildTransactionsResult(result, assetId)\n  }\n\n  /**\n   * Get all spendable token UTXOs for an asset.\n   *\n   * @param assetId - The asset to query\n   * @param includeBeef - Whether to include full transaction data (for spending)\n   * @returns List of spendable token outputs and optional BEEF\n   */\n  async getSpendableTokens(\n    assetId: string,\n    includeBeef = false\n  ): Promise<{ tokens: BTMSTokenOutput[]; beef?: Beef }> {\n    const pages = await this.listOutputsPaged({\n      basket: BTMS_BASKET,\n      tags: ['btms_type_issue', 'btms_type_change', 'btms_type_receive'],\n      tagQueryMode: 'any',\n      include: includeBeef ? 'entire transactions' : 'locking scripts',\n      includeTags: true,\n      includeCustomInstructions: true\n    })\n\n    const tokens: BTMSTokenOutput[] = []\n    const mergedBeef = includeBeef ? new Beef() : undefined\n\n    for (const page of pages) {\n      if (includeBeef && page.BEEF) mergedBeef?.mergeBeef(page.BEEF)\n      for (const output of page.outputs) {\n        const token = this.tryDecodeSpendableOutput(output, page.BEEF, assetId, includeBeef)\n        if (token) tokens.push(token)\n      }\n    }\n\n    return { tokens, beef: mergedBeef }\n  }\n\n  /** Attempt to decode one basket output into a `BTMSTokenOutput` for the given asset. */\n  private tryDecodeSpendableOutput(\n    output: {\n      outpoint: string\n      spendable?: boolean\n      satoshis?: number\n      lockingScript?: string\n      customInstructions?: string\n    },\n    pageBEEF: number[] | Uint8Array | undefined,\n    assetId: string,\n    includeBeef: boolean\n  ): BTMSTokenOutput | null {\n    try {\n      if (!output.spendable) return null\n      if (output.satoshis !== DEFAULT_TOKEN_SATOSHIS) return null\n\n      const [txid, outputIndexStr] = output.outpoint.split('.')\n      const outputIndex = Number(outputIndexStr)\n\n      const scriptHex: HexString | undefined = this.resolveScriptHex(output, pageBEEF, includeBeef)\n      if (!scriptHex) return null\n\n      const decoded = BTMSToken.decode(scriptHex)\n      if (!decoded.valid) return null\n      if (!tokenMatchesAsset(decoded, output.outpoint, assetId)) return null\n\n      return {\n        outpoint: output.outpoint,\n        txid,\n        outputIndex,\n        satoshis: output.satoshis,\n        lockingScript: scriptHex,\n        customInstructions: output.customInstructions,\n        token: decoded,\n        spendable: true,\n        beef: includeBeef && pageBEEF ? pageBEEF : undefined\n      }\n    } catch {\n      return null\n    }\n  }\n\n  /**\n   * Find outputs in the BTMS basket that cannot be decoded as valid tokens.\n   * Useful for cleaning up corrupted or non-overlay outputs.\n   */\n  async findBadOutputs(): Promise<BadOutput[]> {\n    const pages = await this.listOutputsPaged({\n      basket: BTMS_BASKET,\n      tags: ['btms_type_issue', 'btms_type_change', 'btms_type_receive'],\n      tagQueryMode: 'any',\n      include: 'locking scripts'\n    })\n\n    const badOutputs: BadOutput[] = []\n    for (const page of pages) {\n      for (const output of page.outputs) {\n        const bad = validateOutputForBadness(output)\n        if (bad) badOutputs.push(bad)\n      }\n    }\n    return badOutputs\n  }\n\n  /**\n   * Relinquish corrupted outputs from the BTMS basket using wallet.relinquishOutput.\n   * Returns which outpoints were relinquished and which failed.\n   */\n  async relinquishBadOutputs(): Promise<{\n    relinquished: string[]\n    failed: Array<{ outpoint: string; error: string }>\n  }> {\n    const badOutputs = await this.findBadOutputs()\n    const relinquished: string[] = []\n    const failed: Array<{ outpoint: string; error: string }> = []\n\n    for (const bad of badOutputs) {\n      try {\n        const result = await this.wallet.relinquishOutput({\n          basket: BTMS_BASKET,\n          output: bad.outpoint\n        })\n        requireWalletVerdict(result, 'relinquished', 'relinquish the output')\n        relinquished.push(bad.outpoint)\n      } catch (error) {\n        failed.push({\n          outpoint: bad.outpoint,\n          error: error instanceof Error ? error.message : 'Failed to relinquish output'\n        })\n      }\n    }\n\n    return { relinquished, failed }\n  }\n\n  // ---------------------------------------------------------------------------\n  // Ownership Proof Methods\n  // ---------------------------------------------------------------------------\n\n  /**\n   * Prove ownership of tokens to a verifier.\n   *\n   * Creates a cryptographic proof that the caller owns the specified tokens\n   * by revealing key linkage information that only the owner could produce.\n   *\n   * @param assetId - The asset to prove ownership of\n   * @param amount - The amount to prove (must have sufficient balance)\n   * @param verifier - The verifier's identity public key\n   * @returns Ownership proof that can be verified by the verifier\n   *\n   * @example\n   * ```typescript\n   * const proof = await btms.proveOwnership('abc123.0', 100, verifierPubKey)\n   * // Send proof to verifier for verification\n   * ```\n   */\n  async proveOwnership(\n    assetId: string,\n    amount: number,\n    verifier: PubKeyHex\n  ): Promise<ProveOwnershipResult> {\n    try {\n      // Validate inputs\n      if (!BTMSToken.isValidAssetId(assetId)) {\n        throw new Error(`Invalid assetId: ${assetId}`)\n      }\n      assertSafeTokenAmount(amount, 'Amount')\n\n      // Get prover's identity key\n      const prover = await this.getIdentityKey()\n\n      // Get spendable tokens for this asset\n      const { tokens: utxos } = await this.getSpendableTokens(assetId)\n      if (utxos.length === 0) {\n        throw new Error(`No tokens found for asset ${assetId}`)\n      }\n\n      // Select tokens to cover the amount\n      const { selected, totalInput } = BTMS.selectUTXOs(utxos, amount)\n      if (totalInput < amount) {\n        throw new Error(`Insufficient balance. Have ${totalInput}, need ${amount}`)\n      }\n\n      // Generate key linkage proofs for each selected token\n      const provenTokens: ProvenToken[] = []\n\n      for (const utxo of selected) {\n        const { keyID } = parseCustomInstructions(\n          utxo.customInstructions,\n          utxo.txid,\n          utxo.outputIndex\n        )\n\n        // Reveal specific key linkage for this token\n        // The counterparty is 'self' for tokens we own (resolved to our own key)\n        const linkageResult = await this.wallet.revealSpecificKeyLinkage({\n          counterparty: prover, // Self-owned tokens use our own key as counterparty\n          verifier,\n          protocolID: BTMS_PROTOCOL_ID,\n          keyID\n        })\n\n        provenTokens.push({\n          output: {\n            txid: utxo.txid,\n            outputIndex: utxo.outputIndex,\n            lockingScript: utxo.lockingScript,\n            satoshis: utxo.satoshis\n          },\n          keyID,\n          linkage: {\n            prover: linkageResult.prover,\n            verifier: linkageResult.verifier,\n            counterparty: linkageResult.counterparty,\n            encryptedLinkage: linkageResult.encryptedLinkage,\n            encryptedLinkageProof: linkageResult.encryptedLinkageProof,\n            proofType: linkageResult.proofType\n          }\n        })\n      }\n\n      const proof: OwnershipProof = {\n        prover,\n        verifier,\n        tokens: provenTokens,\n        amount,\n        assetId\n      }\n\n      return {\n        success: true,\n        proof\n      }\n    } catch (error) {\n      return {\n        success: false,\n        error: error instanceof Error ? error.message : 'Unknown error'\n      }\n    }\n  }\n\n  /**\n   * Verify an ownership proof from a prover.\n   *\n   * Validates that:\n   * 1. The key linkage is valid for each token\n   * 2. The tokens exist on the overlay\n   * 3. The total amount matches the claimed amount\n   * 4. All tokens belong to the claimed prover\n   *\n   * @param proof - The ownership proof to verify\n   * @returns Verification result\n   *\n   * @example\n   * ```typescript\n   * const result = await btms.verifyOwnership(proof)\n   * if (result.valid) {\n   *   console.log(`Verified ${result.amount} tokens owned by ${result.prover}`)\n   * }\n   * ```\n   */\n  async verifyOwnership(proof: OwnershipProof): Promise<VerifyOwnershipResult> {\n    try {\n      assertSafeTokenAmount(proof.amount, 'Claimed amount')\n\n      // Get verifier's identity key\n      const verifierKey = await this.getIdentityKey()\n\n      // Verify the proof is intended for us\n      if (proof.verifier !== verifierKey) {\n        throw new Error('Proof is not intended for this verifier')\n      }\n\n      let amountProven = 0\n\n      // Verify each token in the proof\n      const seenOutpoints = new Set<string>()\n      for (const provenToken of proof.tokens) {\n        const outpoint = `${provenToken.output.txid}.${provenToken.output.outputIndex}`\n        if (seenOutpoints.has(outpoint)) {\n          throw new Error(`Duplicate token outpoint in proof: ${outpoint}`)\n        }\n        seenOutpoints.add(outpoint)\n        amountProven = addTokenAmounts(\n          amountProven,\n          await this.verifySingleProvenToken(provenToken, proof.assetId, proof.prover),\n          'Proven amount'\n        )\n      }\n\n      // Verify the total amount matches\n      if (amountProven < proof.amount) {\n        throw new Error(`Amount proven (${amountProven}) is less than claimed (${proof.amount})`)\n      }\n\n      return {\n        valid: true,\n        amount: amountProven,\n        assetId: proof.assetId,\n        prover: proof.prover\n      }\n    } catch (error) {\n      return {\n        valid: false,\n        error: error instanceof Error ? error.message : 'Unknown error'\n      }\n    }\n  }\n\n  /**\n   * Lookup a token on the overlay network.\n   *\n   * @param txid - Transaction ID\n   * @param outputIndex - Output index\n   * @param includeBeef - Whether to return BEEF data\n   * @returns Whether the token was found and optionally the BEEF\n   */\n  protected async lookupTokenOnOverlay(\n    txid: TXIDHexString,\n    outputIndex: number,\n    includeBeef = false\n  ): Promise<{ found: boolean; beef?: Beef }> {\n    try {\n      const lookup = new LookupResolver({ networkPreset: this.networkPreset })\n      const result = await lookup.query({\n        service: BTMS_LOOKUP_SERVICE,\n        query: { txid, outputIndex }\n      })\n\n      // Check if we got a valid result\n      if (result.type === 'output-list' && result.outputs.length > 0) {\n        const beef = includeBeef ? Beef.fromBinaryStrict(result.outputs[0].beef) : undefined\n        return { found: true, beef }\n      }\n      return { found: false }\n    } catch {\n      return { found: false }\n    }\n  }\n\n  // ---------------------------------------------------------------------------\n  // Utility Methods\n  // ---------------------------------------------------------------------------\n\n  /**\n   * Get the wallet's identity public key (cached after first call).\n   */\n  async getIdentityKey(): Promise<PubKeyHex> {\n    if (!this.cachedIdentityKey) {\n      const { publicKey } = await this.wallet.getPublicKey({\n        identityKey: true\n      })\n      this.cachedIdentityKey = publicKey\n    }\n    return this.cachedIdentityKey\n  }\n\n  private getMonthLabel(): LabelStringUnder300Bytes {\n    const now = new Date()\n    const year = now.getUTCFullYear()\n    const month = String(now.getUTCMonth() + 1).padStart(2, '0')\n    return `${BTMS_LABEL_PREFIX}month ${year}-${month}`\n  }\n\n  private getTimestampLabel(): LabelStringUnder300Bytes {\n    return `${BTMS_LABEL_PREFIX}timestamp ${Date.now()}`\n  }\n\n  private getMonthTag(): OutputTagStringUnder300Bytes {\n    const now = new Date()\n    const year = now.getUTCFullYear()\n    const month = String(now.getUTCMonth() + 1).padStart(2, '0')\n    return `btms_month_${year}-${month}`\n  }\n\n  private getTimestampTag(): OutputTagStringUnder300Bytes {\n    return `btms_timestamp_${Date.now()}`\n  }\n\n  private async buildSpendsForInputs(\n    selected: BTMSTokenOutput[],\n    unsignedTx: number[] | Uint8Array\n  ): Promise<Record<number, { unlockingScript: string }>> {\n    const txData = Array.isArray(unsignedTx) ? unsignedTx : toArray(unsignedTx)\n    const txForSigning = Transaction.fromAtomicBEEF(txData)\n    const spends: Record<number, { unlockingScript: string }> = {}\n    for (let i = 0; i < selected.length; i++) {\n      const utxo = selected[i]\n      const { keyID, senderIdentityKey } = parseCustomInstructions(\n        utxo.customInstructions,\n        utxo.txid,\n        utxo.outputIndex\n      )\n      const counterparty = senderIdentityKey ?? 'self'\n      const unlocker = this.tokenTemplate.createUnlocker(keyID, counterparty)\n      const unlockingScript = await unlocker.sign(txForSigning, i)\n      spends[i] = { unlockingScript: unlockingScript.toHex() }\n    }\n    return spends\n  }\n\n  private async signAndBroadcast(\n    reference: string,\n    spends: Record<number, { unlockingScript: string }>\n  ): Promise<{ tx: AtomicBEEF; txid: TXIDHexString }> {\n    const signResult = await this.wallet.signAction({\n      reference,\n      spends\n    })\n\n    if (!signResult.tx) {\n      throw new Error('Failed to sign transaction')\n    }\n\n    const txData = Array.isArray(signResult.tx) ? signResult.tx : toArray(signResult.tx)\n    const finalTx = Transaction.fromAtomicBEEF(txData)\n    const txid = finalTx.id('hex')\n\n    await this.broadcastWithRetry(finalTx, `txid ${txid}`)\n\n    return { tx: signResult.tx, txid }\n  }\n\n  private async broadcastWithRetry(\n    tx: Transaction,\n    context: string,\n    maxAttempts = BTMS.BROADCAST_MAX_ATTEMPTS\n  ): Promise<void> {\n    let lastError = 'Unknown error'\n\n    for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n      try {\n        const broadcaster = new TopicBroadcaster([BTMS_TOPIC], {\n          networkPreset: this.networkPreset\n        })\n        const broadcastResult = await broadcaster.broadcast(tx)\n\n        if (broadcastResult.status === 'success') {\n          return\n        }\n\n        lastError = (broadcastResult as any).description || `status: ${broadcastResult.status}`\n        console.warn(\n          `[BTMS] Broadcast attempt ${attempt}/${maxAttempts} failed for ${context}: ${lastError}`\n        )\n      } catch (error) {\n        lastError = error instanceof Error ? error.message : String(error)\n        console.warn(\n          `[BTMS] Broadcast attempt ${attempt}/${maxAttempts} threw for ${context}: ${lastError}`\n        )\n      }\n    }\n\n    throw new Error(`Broadcast failed after ${maxAttempts} attempts: ${lastError}`)\n  }\n\n  private async listOutputsPaged(args: ListOutputsArgs): Promise<ListOutputsResult[]> {\n    const pages: ListOutputsResult[] = []\n    const pageSize = BTMS.LIST_OUTPUTS_PAGE_SIZE\n    let offset = 0\n\n    for (let i = 0; i < BTMS.MAX_LIST_OUTPUTS_PAGES; i++) {\n      const page = await this.wallet.listOutputs({\n        ...args,\n        limit: pageSize,\n        offset\n      })\n      pages.push(page)\n\n      const count = page.outputs.length\n      if (count === 0 || count < pageSize) {\n        return pages\n      }\n      offset += count\n    }\n\n    console.warn(`[BTMS] listOutputs pagination reached max pages (${BTMS.MAX_LIST_OUTPUTS_PAGES})`)\n    return pages\n  }\n\n  /**\n   * Ensure a createAction inputBEEF is complete and non-txid-only for required inputs.\n   */\n  private async ensureCompleteInputBeef(\n    requiredInputs: Array<{ txid: TXIDHexString; outputIndex: number }>,\n    baseBeef: Beef,\n    assetIdForRecovery?: string\n  ): Promise<Beef> {\n    const merged = baseBeef.clone()\n\n    const validate = (beef: Beef): { ok: true } | { ok: false; reason: string } => {\n      const txidOnlyTxs = beef.txs.filter((tx: any) => tx?.isTxidOnly).map((tx: any) => tx.txid)\n      if (txidOnlyTxs.length > 0) {\n        return {\n          ok: false,\n          reason: `BEEF contains txid-only entries: ${txidOnlyTxs.slice(0, 3).join(', ')}`\n        }\n      }\n\n      const beefBin = beef.toBinary()\n      for (const input of requiredInputs) {\n        const beefTx = beef.findTxid(input.txid)\n        if (!beefTx || (beefTx as any).isTxidOnly) {\n          return {\n            ok: false,\n            reason: `Missing complete transaction for input ${input.txid}.${input.outputIndex}`\n          }\n        }\n\n        try {\n          const tx = Transaction.fromBEEF(beefBin, input.txid)\n          if (tx.outputs[input.outputIndex] === undefined) {\n            return {\n              ok: false,\n              reason: `Missing referenced output ${input.txid}.${input.outputIndex}`\n            }\n          }\n        } catch (error) {\n          return {\n            ok: false,\n            reason: `Unresolvable ancestry for ${input.txid}.${input.outputIndex}: ${error instanceof Error ? error.message : 'unknown error'}`\n          }\n        }\n      }\n\n      return { ok: true }\n    }\n\n    let validation = validate(merged)\n    if (validation.ok) {\n      return merged\n    }\n\n    // Recovery path: merge wallet-provided BEEF for the same asset (when available).\n    if (assetIdForRecovery && BTMSToken.isValidAssetId(assetIdForRecovery)) {\n      const { beef: walletBeef } = await this.getSpendableTokens(assetIdForRecovery, true)\n      if (walletBeef) {\n        merged.mergeBeef(walletBeef)\n      }\n      validation = validate(merged)\n      if (validation.ok) {\n        return merged\n      }\n    }\n\n    throw new Error(`Unable to build complete inputBEEF for createAction: ${validation.reason}`)\n  }\n\n  /**\n   * Decode a token from a locking script.\n   */\n  decodeToken(lockingScript: string | LockingScript) {\n    return BTMSToken.decode(lockingScript)\n  }\n\n  // ---------------------------------------------------------------------------\n  // Private helpers extracted to reduce cognitive complexity\n  // ---------------------------------------------------------------------------\n\n  /** Assert that all selected UTXOs carry the same metadata. */\n  private assertConsistentMetadata(\n    selected: Array<{ token: { metadata?: unknown } }>,\n    metadata: unknown\n  ): void {\n    const metadataJson = stringifyBRC100(metadata ?? null)\n    for (const utxo of selected) {\n      if (stringifyBRC100(utxo.token.metadata ?? null) !== metadataJson) {\n        throw new Error('Metadata mismatch across selected tokens')\n      }\n    }\n  }\n\n  /** Build change `CreateActionOutput` entries for a send or burn. */\n  private async buildChangeOutputs(\n    context: ChangeContext,\n    changeStrategy: ChangeStrategyOptions | undefined,\n    derivationPrefix: string,\n    metadata: string | undefined\n  ): Promise<CreateActionOutput[]> {\n    const changeOutputItems = BTMS.computeChangeOutputs(context, changeStrategy)\n    const timestampTag = this.getTimestampTag()\n    const monthTag = this.getMonthTag()\n    const result: CreateActionOutput[] = []\n    for (const changeOutput of changeOutputItems) {\n      const changeDerivationSuffix = toBase64(Random(32))\n      const changeKeyID = `${derivationPrefix} ${changeDerivationSuffix}`\n      const changeScript = await this.tokenTemplate.createTransfer(\n        context.assetId,\n        changeOutput.amount,\n        changeKeyID,\n        'self',\n        metadata\n      )\n      result.push({\n        satoshis: DEFAULT_TOKEN_SATOSHIS,\n        lockingScript: changeScript.toHex(),\n        customInstructions: stringifyBRC100({\n          derivationPrefix,\n          derivationSuffix: changeDerivationSuffix\n        }),\n        basket: BTMS_BASKET,\n        outputDescription: `Change: ${changeOutput.amount} tokens`,\n        tags: [\n          'btms_type_change',\n          'btms_direction_incoming',\n          timestampTag,\n          monthTag,\n          `btms_assetid_${context.assetId}`\n        ]\n      })\n    }\n    return result\n  }\n\n  /**\n   * Sign and broadcast a burn transaction.\n   * When burning all tokens (no change outputs), overlay rejection is treated as success.\n   */\n  private async signAndBroadcastBurn(\n    reference: string,\n    spends: Record<number, { unlockingScript: string }>,\n    changeAmount: number\n  ): Promise<TXIDHexString> {\n    try {\n      const { txid } = await this.signAndBroadcast(reference, spends)\n      return txid\n    } catch (broadcastError: any) {\n      const errorMsg: string = broadcastError?.message ?? ''\n      const isBurnAll = changeAmount === 0\n      const isOverlayRejection =\n        errorMsg.includes('No host acknowledged') || errorMsg.includes('not in admitted outputs')\n      if (!isBurnAll || !isOverlayRejection) throw broadcastError\n\n      // Sign-only path for burn-all (overlay won't admit with no outputs)\n      const signResult = await this.wallet.signAction({ reference, spends })\n      if (!signResult.tx) throw new Error('Failed to sign transaction')\n      const txData = Array.isArray(signResult.tx) ? signResult.tx : toArray(signResult.tx)\n      return Transaction.fromAtomicBEEF(txData).id('hex')\n    }\n  }\n\n  /** Verify a single proven token and return its amount contribution. */\n  private async verifySingleProvenToken(\n    provenToken: ProvenToken,\n    expectedAssetId: string,\n    prover: PubKeyHex\n  ): Promise<number> {\n    const decoded = BTMSToken.decode(provenToken.output.lockingScript)\n    if (!decoded.valid) throw new Error('Invalid token in proof')\n\n    verifyProvenTokenAssetId(\n      decoded,\n      provenToken.output.txid,\n      provenToken.output.outputIndex,\n      expectedAssetId\n    )\n\n    if (provenToken.linkage.prover !== prover) {\n      throw new Error('Token linkage prover does not match proof prover')\n    }\n\n    const lookupResult = await this.lookupTokenOnOverlay(\n      provenToken.output.txid,\n      provenToken.output.outputIndex\n    )\n    if (!lookupResult.found) throw new Error('Token not found on overlay')\n\n    const { plaintext: linkage } = await this.wallet.decrypt({\n      ciphertext: provenToken.linkage.encryptedLinkage,\n      protocolID: [2, `specific linkage revelation ${BTMS_PROTOCOL_ID[0]} ${BTMS_PROTOCOL_ID[1]}`],\n      keyID: provenToken.keyID,\n      counterparty: prover\n    })\n\n    if (!linkage || linkage.length === 0) throw new Error('Invalid key linkage for token')\n    return decoded.amount\n  }\n\n  private async verifySelectedUtxos(\n    selected: BTMSTokenOutput[]\n  ): Promise<UtxoVerificationResult[]> {\n    return await Promise.all(\n      selected.map(async utxo => {\n        const { found, beef } = await this.lookupTokenOnOverlay(utxo.txid, utxo.outputIndex, true)\n        return found ? { utxo, found, beef } : { utxo, found: false, beef: undefined }\n      })\n    )\n  }\n\n  private async missingUtxoBeefByOutpoint(\n    invalidUtxos: BTMSTokenOutput[],\n    assetId: string | undefined\n  ): Promise<Map<string, BTMSTokenOutput>> {\n    const needsBeef = invalidUtxos.some(utxo => !utxo.beef)\n    if (!needsBeef || !assetId) return new Map()\n    const { tokens } = await this.getSpendableTokens(assetId, true)\n    return new Map(tokens.map(utxo => [utxo.outpoint, utxo]))\n  }\n\n  private async rebroadcastMissingUtxos(\n    invalidUtxos: BTMSTokenOutput[],\n    assetId: string | undefined\n  ): Promise<UtxoVerificationResult[]> {\n    const beefByOutpoint = await this.missingUtxoBeefByOutpoint(invalidUtxos, assetId)\n    return await Promise.all(\n      invalidUtxos.map(async original => {\n        const utxo = beefByOutpoint.get(original.outpoint) ?? original\n        return { utxo, ...(await this.tryRebroadcastUtxo(utxo)) }\n      })\n    )\n  }\n\n  private mergeVerificationBeefs(\n    verificationResults: UtxoVerificationResult[],\n    inputBeef: Beef\n  ): void {\n    for (const result of verificationResults) {\n      if (result.beef) inputBeef.mergeBeef(result.beef)\n    }\n  }\n\n  /**\n   * Select and verify UTXOs on the overlay.\n   *\n   * Selects UTXOs first using the specified strategy, then verifies only\n   * the selected ones on the overlay. If any fail verification, retries\n   * with remaining UTXOs.\n   *\n   * @param utxos - Available UTXOs to select from\n   * @param amount - Target amount to cover\n   * @param options - Selection options including strategy\n   * @returns Selected UTXOs, total input, and merged BEEF from overlay\n   */\n  async selectAndVerifyUTXOs(\n    utxos: BTMSTokenOutput[],\n    amount: number,\n    options: SelectionOptions = {}\n  ): Promise<{ selected: BTMSTokenOutput[]; totalInput: number; inputBeef: Beef }> {\n    const inputBeef = new Beef()\n    let remainingUtxos = [...utxos]\n\n    while (remainingUtxos.length > 0) {\n      // Select UTXOs using the specified strategy\n      const { selected, totalInput } = BTMS.selectUTXOs(remainingUtxos, amount, options)\n\n      if (selected.length === 0 || totalInput < amount) {\n        // Not enough UTXOs available\n        return { selected: [], totalInput: 0, inputBeef }\n      }\n\n      const verificationResults = await this.verifySelectedUtxos(selected)\n\n      // Separate valid and invalid UTXOs\n      let validResults = verificationResults.filter(r => r.found)\n      let invalidUtxos = verificationResults.filter(r => !r.found).map(r => r.utxo)\n\n      // Re-broadcast missing UTXOs only if we need to fetch BEEF\n      if (invalidUtxos.length > 0) {\n        const rebroadcastResults = await this.rebroadcastMissingUtxos(\n          invalidUtxos,\n          selected[0]?.token.assetId\n        )\n\n        validResults = [...validResults, ...rebroadcastResults.filter(r => r.found)]\n        invalidUtxos = rebroadcastResults.filter(r => !r.found).map(r => r.utxo)\n      }\n\n      // Merge BEEF from valid UTXOs\n      this.mergeVerificationBeefs(validResults, inputBeef)\n\n      // If all selected UTXOs are valid, we're done\n      if (invalidUtxos.length === 0) {\n        return {\n          selected: validResults.map(r => r.utxo),\n          totalInput,\n          inputBeef\n        }\n      }\n\n      // Some UTXOs failed verification - remove them and retry\n      remainingUtxos = remainingUtxos.filter(\n        u => !invalidUtxos.some(invalid => invalid.outpoint === u.outpoint)\n      )\n    }\n\n    // Token supply exhausted\n    return { selected: [], totalInput: 0, inputBeef }\n  }\n\n  /** Resolve the locking-script hex for one page output (handles BEEF and plain-script modes). */\n  private resolveScriptHex(\n    output: { outpoint: string; lockingScript?: string },\n    pageBEEF: number[] | Uint8Array | undefined,\n    includeBeef: boolean\n  ): string | undefined {\n    if (!includeBeef) return output.lockingScript\n    if (!pageBEEF) return undefined\n    const [txid, outputIndexStr] = output.outpoint.split('.')\n    const tx = Transaction.fromBEEF(pageBEEF, txid)\n    return tx.outputs[Number(outputIndexStr)].lockingScript.toHex()\n  }\n\n  /** Attempt to re-broadcast a UTXO and return whether it was admitted by the overlay. */\n  private async tryRebroadcastUtxo(utxo: {\n    beef?: number[] | Uint8Array\n    txid: string\n  }): Promise<{ found: boolean; beef?: Beef }> {\n    if (!utxo.beef) return { found: false }\n    try {\n      const beefArr = Array.isArray(utxo.beef) ? utxo.beef : toArray(utxo.beef)\n      const tx = Transaction.fromAtomicBEEF(Transaction.fromBEEF(beefArr, utxo.txid).toAtomicBEEF())\n      const broadcaster = new TopicBroadcaster([BTMS_TOPIC], { networkPreset: this.networkPreset })\n      const response = await broadcaster.broadcast(tx)\n      if (response.status === 'success') {\n        return { found: true, beef: Beef.fromBinaryStrict(beefArr) }\n      }\n    } catch {\n      // fall through\n    }\n    return { found: false }\n  }\n\n  // ---------------------------------------------------------------------------\n  // Static Methods\n  // ---------------------------------------------------------------------------\n\n  /**\n   * Select UTXOs to cover a target amount using a configurable strategy.\n   *\n   * @param utxos - Available UTXOs to select from\n   * @param amount - Target amount to cover\n   * @param options - Selection options including strategy\n   * @returns Selected UTXOs, total input amount, and excluded UTXOs\n   */\n  static selectUTXOs<T extends { token: { amount: number } }>(\n    utxos: T[],\n    amount: number,\n    options: SelectionOptions = {}\n  ): SelectionResult<T> {\n    assertSafeTokenAmount(amount, 'Target amount')\n\n    const {\n      strategy = 'largest-first',\n      fallbackStrategy = 'largest-first',\n      maxInputs,\n      minUtxoAmount = 0\n    } = options\n\n    assertSafeTokenAmount(minUtxoAmount, 'Minimum UTXO amount', true)\n    for (const utxo of utxos) assertSafeTokenAmount(utxo.token.amount, 'UTXO amount')\n\n    // Filter by minimum amount\n    const eligible = utxos.filter(u => u.token.amount >= minUtxoAmount)\n    const excluded = utxos.filter(u => u.token.amount < minUtxoAmount)\n\n    // Sort based on strategy\n    let sorted: T[]\n    switch (strategy) {\n      case 'smallest-first':\n        sorted = [...eligible].sort((a, b) => a.token.amount - b.token.amount)\n        break\n      case 'random':\n        sorted = BTMS.shuffle(eligible)\n        break\n      case 'exact-match': {\n        // Try to find exact match first\n        const exactMatch = eligible.find(u => u.token.amount === amount)\n        if (exactMatch) {\n          return { selected: [exactMatch], totalInput: amount, excluded }\n        }\n        // Fall back to configured strategy\n        switch (fallbackStrategy) {\n          case 'smallest-first':\n            sorted = [...eligible].sort((a, b) => a.token.amount - b.token.amount)\n            break\n          case 'random':\n            sorted = BTMS.shuffle(eligible)\n            break\n          case 'largest-first':\n          default:\n            sorted = [...eligible].sort((a, b) => b.token.amount - a.token.amount)\n            break\n        }\n        break\n      }\n      case 'largest-first':\n      default:\n        sorted = [...eligible].sort((a, b) => b.token.amount - a.token.amount)\n        break\n    }\n\n    // Select UTXOs until we meet the target\n    const selected: T[] = []\n    let totalInput = 0\n\n    for (const utxo of sorted) {\n      if (totalInput >= amount) break\n      if (maxInputs !== undefined && selected.length >= maxInputs) break\n      selected.push(utxo)\n      totalInput = addTokenAmounts(totalInput, utxo.token.amount, 'Selected input total')\n    }\n\n    return { selected, totalInput, excluded }\n  }\n\n  /**\n   * Compute change outputs using the specified strategy.\n   *\n   * @param context - Change context with amounts and asset info\n   * @param options - Change strategy options\n   * @returns Array of change outputs to create\n   */\n  static computeChangeOutputs(\n    context: ChangeContext,\n    options: ChangeStrategyOptions = {}\n  ): ChangeOutput[] {\n    const { changeAmount, paymentAmount, totalInput } = context\n\n    assertSafeTokenAmount(changeAmount, 'Change amount', true)\n    assertSafeTokenAmount(paymentAmount, 'Payment amount', true)\n    assertSafeTokenAmount(totalInput, 'Total input amount', true)\n    if (addTokenAmounts(changeAmount, paymentAmount, 'Change context total') !== totalInput) {\n      throw new RangeError('Change amount plus payment amount must equal total input amount')\n    }\n\n    if (changeAmount <= 0) {\n      return []\n    }\n\n    const { strategy = 'single', splitCount = 2, minOutputAmount = 1 } = options\n\n    let outputs: ChangeOutput[]\n\n    // If a custom strategy object is provided, use it\n    if (typeof strategy === 'object' && 'computeChange' in strategy) {\n      outputs = strategy.computeChange(context)\n    } else {\n      // Built-in strategies\n      switch (strategy) {\n        case 'split-equal':\n          outputs = BTMS.splitEqualChange(changeAmount, splitCount, minOutputAmount)\n          break\n\n        case 'split-random':\n          outputs = BTMS.splitRandomChange(changeAmount, splitCount, minOutputAmount)\n          break\n\n        case 'single':\n        default:\n          outputs = [{ amount: changeAmount }]\n          break\n      }\n    }\n\n    let outputTotal = 0\n    for (const output of outputs) {\n      assertSafeTokenAmount(output.amount, 'Change output amount')\n      outputTotal = addTokenAmounts(outputTotal, output.amount, 'Change output total')\n    }\n    if (outputTotal !== changeAmount) {\n      throw new RangeError('Change outputs must exactly equal the change amount')\n    }\n    return outputs\n  }\n\n  /**\n   * Split change into equal amounts.\n   */\n  private static splitEqualChange(\n    changeAmount: number,\n    splitCount: number,\n    minOutputAmount: number\n  ): ChangeOutput[] {\n    // Ensure we can create at least minOutputAmount per output\n    const maxOutputs = Math.floor(changeAmount / minOutputAmount)\n    const actualCount = Math.min(splitCount, maxOutputs)\n\n    if (actualCount <= 1) {\n      return [{ amount: changeAmount }]\n    }\n\n    const perOutput = Math.floor(changeAmount / actualCount)\n    const remainder = changeAmount - perOutput * actualCount\n\n    const outputs: ChangeOutput[] = []\n    for (let i = 0; i < actualCount; i++) {\n      // Add remainder to the last output\n      const amount = i === actualCount - 1 ? perOutput + remainder : perOutput\n      outputs.push({ amount })\n    }\n\n    return outputs\n  }\n\n  /**\n   * Split change into random amounts using a logarithmic distribution.\n   * Uses a Benford-inspired formula to favor smaller amounts, creating\n   * more natural-looking output amounts for privacy.\n   */\n  private static splitRandomChange(\n    changeAmount: number,\n    splitCount: number,\n    minOutputAmount: number\n  ): ChangeOutput[] {\n    // Ensure we can create at least minOutputAmount per output\n    const maxOutputs = Math.floor(changeAmount / minOutputAmount)\n    const actualCount = Math.min(splitCount, maxOutputs)\n\n    if (actualCount <= 1) {\n      return [{ amount: changeAmount }]\n    }\n\n    const outputs: ChangeOutput[] = []\n    let remaining = changeAmount - actualCount * minOutputAmount // Reserve minimum for each\n\n    // Distribute using Benford-like distribution\n    for (let i = 0; i < actualCount - 1; i++) {\n      const portion = BTMS.benfordNumber(0, remaining)\n      outputs.push({ amount: minOutputAmount + portion })\n      remaining -= portion\n    }\n\n    // Last output gets the remainder\n    outputs.push({ amount: minOutputAmount + remaining })\n\n    // Shuffle to avoid predictable ordering\n    for (let i = outputs.length - 1; i > 0; i--) {\n      const j = BTMS.randomInt(i + 1)\n      ;[outputs[i], outputs[j]] = [outputs[j], outputs[i]]\n    }\n\n    return outputs\n  }\n\n  /**\n   * Generate a logarithmically-distributed random number.\n   * Uses a formula inspired by Benford's law to favor smaller values,\n   * creating more natural-looking distributions.\n   */\n  private static benfordNumber(min: number, max: number): number {\n    if (max <= min) return min\n    const d = BTMS.randomInt(9) + 1\n    return Math.floor(min + ((max - min) * Math.log10(1 + 1 / d)) / Math.log10(10))\n  }\n\n  private static shuffle<T>(items: T[]): T[] {\n    const shuffled = [...items]\n    for (let i = shuffled.length - 1; i > 0; i--) {\n      const j = BTMS.randomInt(i + 1)\n      ;[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]]\n    }\n    return shuffled\n  }\n\n  private static randomInt(maxExclusive: number): number {\n    if (maxExclusive <= 0) return 0\n    const maxUint32 = 0x100000000\n    const limit = maxUint32 - (maxUint32 % maxExclusive)\n\n    while (true) {\n      const bytes = Random(4)\n      const value = ((bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3]) >>> 0\n      if (value < limit) return value % maxExclusive\n    }\n  }\n}\n"],"mappings":"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"}