{
  "version": 3,
  "sources": ["../src/createOrdinals.ts", "../src/constants.ts", "../src/signData.ts", "../src/templates/ordP2pkh.ts", "../src/utils/strings.ts", "../src/utils/subtypeData.ts", "../src/utils/utxo.ts", "../src/types.ts", "../src/sendOrdinals.ts", "../node_modules/@bopen-io/templates/dist/esm/src/template/opreturn/OpReturn.js", "../node_modules/@bopen-io/templates/dist/esm/src/template/metanet/Metanet.js", "../node_modules/@bopen-io/templates/dist/esm/src/template/pushdrop/MultiPushDrop.js", "../node_modules/@bopen-io/templates/dist/esm/src/template/bsocial/BSocial.js", "../node_modules/@bopen-io/templates/dist/esm/src/template/bitcom/BitCom.js", "../node_modules/@bopen-io/templates/dist/esm/src/template/bitcom/B.js", "../node_modules/@bopen-io/templates/dist/esm/src/template/bitcom/MAP.js", "../node_modules/@bopen-io/templates/dist/esm/src/template/bitcom/AIP.js", "../node_modules/@bopen-io/templates/dist/esm/src/template/bitcom/BAP.js", "../node_modules/@bopen-io/templates/dist/esm/src/template/inscription/Inscription.js", "../node_modules/@bopen-io/templates/dist/esm/src/template/bsv21/BSV21.js", "../node_modules/@bopen-io/templates/dist/esm/src/template/bsv20/BSV20.js", "../node_modules/@bopen-io/templates/dist/esm/src/template/ordlock/OrdLock.js", "../node_modules/@bopen-io/templates/dist/esm/src/template/lockup/Lock.js", "../node_modules/@bopen-io/templates/dist/esm/src/template/cosign/Cosign.js", "../node_modules/@bopen-io/templates/dist/esm/src/template/multisig/MultiSigPubkeyHash.js", "../src/sendUtxos.ts", "../src/transferOrdinals.ts", "../src/validate.ts", "../src/templates/ordLock.ts", "../src/createListings.ts", "../src/cancelListings.ts", "../src/purchaseOrdListing.ts", "../src/utils/paymail.ts", "../src/deployBsv21.ts", "../src/utils/icon.ts", "../src/burnOrdinals.ts", "../src/utils/broadcast.ts", "../src/utils/httpClient.ts", "../src/utils/fetch.ts"],
  "sourcesContent": [
    "import { P2PKH, SatoshisPerKilobyte, Script, Transaction, Utils } from \"@bsv/sdk\";\nimport { DEFAULT_SAT_PER_KB } from \"./constants\";\nimport { signData } from \"./signData\";\nimport OrdP2PKH from \"./templates/ordP2pkh\";\nimport type {\n\tChangeResult,\n\tCreateOrdinalsCollectionConfig,\n\tCreateOrdinalsCollectionItemConfig,\n\tCreateOrdinalsConfig,\n\tUtxo,\n} from \"./types\";\nimport stringifyMetaData from \"./utils/subtypeData\";\nimport { inputFromB64Utxo } from \"./utils/utxo\";\n\n/**\n * Creates a transaction with inscription outputs\n * @param {CreateOrdinalsConfig | CreateOrdinalsCollectionConfig | CreateOrdinalsCollectionItemConfig} config - Configuration object for creating ordinals\n * @param {Utxo[]} config.utxos - Utxos to spend (with base64 encoded scripts)\n * @param {Destination[]} config.destinations - Array of destinations with addresses and inscriptions\n * @param {PrivateKey} config.paymentPk - Private key to sign utxos\n * @param {string} config.changeAddress - Optional. Address to send change to. If not provided, defaults to paymentPk address\n * @param {number} config.satsPerKb - Optional. Satoshis per kilobyte for fee calculation. Default is DEFAULT_SAT_PER_KB\n * @param {PreMAP} config.metaData - Optional. MAP (Magic Attribute Protocol) metadata to include in inscriptions\n * @param {LocalSigner | RemoteSigner} config.signer - Optional. Local or remote signer (used for data signature)\n * @param {Payment[]} config.additionalPayments - Optional. Additional payments to include in the transaction\n * @returns {Promise<ChangeResult>} Transaction with inscription outputs\n */\nexport const createOrdinals = async (\n\tconfig:\n\t\t| CreateOrdinalsConfig\n\t\t| CreateOrdinalsCollectionConfig\n\t\t| CreateOrdinalsCollectionItemConfig,\n): Promise<ChangeResult> => {\n\tconst {\n\t\tutxos,\n\t\tdestinations,\n\t\tpaymentPk,\n\t\tsatsPerKb = DEFAULT_SAT_PER_KB,\n\t\tmetaData,\n\t\tsigner,\n\t\tadditionalPayments = [],\n\t\tsignInputs = true,\n\t} = config;\n\t\n\t// Warn if creating many inscriptions at once\n\tif (destinations.length > 100) {\n\t\tconsole.warn(\n\t\t\t\"Creating many inscriptions at once can be slow. Consider using multiple transactions instead.\",\n\t\t);\n\t}\n\n\tconst modelOrFee = new SatoshisPerKilobyte(satsPerKb);\n\tlet tx = new Transaction();\n\n\t// Outputs\n\t// Add inscription outputs\n\tfor (const destination of destinations) {\n\t\tif (!destination.inscription) {\n\t\t\tthrow new Error(\"Inscription is required for all destinations\");\n\t\t}\n\n\t\t// remove any undefined fields from metadata\n\t\tif (metaData) {\n\t\t\tfor(const key of Object.keys(metaData)) {\n\t\t\t\tif (metaData[key] === undefined) {\n\t\t\t\t\tdelete metaData[key];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\ttx.addOutput({\n\t\t\tsatoshis: 1,\n\t\t\tlockingScript: new OrdP2PKH().lock(\n\t\t\t\tdestination.address,\n\t\t\t\tdestination.inscription,\n\t\t\t\tstringifyMetaData(metaData),\n\t\t\t),\n\t\t});\n\t}\n\n\t// Add additional payments if any\n\tfor (const p of additionalPayments) {\n\t\ttx.addOutput({\n\t\t\tsatoshis: p.amount,\n\t\t\tlockingScript: new P2PKH().lock(p.to),\n\t\t});\n\t}\n\n\tlet payChange: Utxo | undefined;\n  const changeAddress = config.changeAddress || paymentPk?.toAddress();\n\tif(!changeAddress) {\n\t\tthrow new Error(\"Either changeAddress or paymentPk is required\");\n\t}\n\tconst changeScript = new P2PKH().lock(changeAddress);\n\tconst changeOut = {\n\t\tlockingScript: changeScript,\n\t\tchange: true,\n\t};\n\ttx.addOutput(changeOut);\n\n\tlet totalSatsIn = 0n;\n\tconst totalSatsOut = tx.outputs.reduce(\n\t\t(total, out) => total + BigInt(out.satoshis || 0),\n\t\t0n,\n\t);\n\n\tlet fee = 0;\n\n\tif(signer) {\n\t\tconst utxo = utxos.pop() as Utxo\n\t\tif (signInputs) {\n\t\t\tconst payKeyToUse = utxo.pk || paymentPk;\n\t\t\tif(!payKeyToUse) {\n\t\t\t\tthrow new Error(\"Private key is required to sign the transaction\");\n\t\t\t}\n\t\t\ttx.addInput(inputFromB64Utxo(utxo, new P2PKH().unlock(\n\t\t\t\tpayKeyToUse,\n\t\t\t\t\"all\",\n\t\t\t\ttrue,\n\t\t\t\tutxo.satoshis,\n\t\t\t\tScript.fromBinary(Utils.toArray(utxo.script, 'base64'))\n\t\t\t)));\n\t\t} else {\n\t\t\t// Add input without unlock template for external signing\n\t\t\ttx.addInput(inputFromB64Utxo(utxo));\n\t\t}\n\t\ttotalSatsIn += BigInt(utxo.satoshis);\n\t\ttx = await signData(tx, signer);\n\t\t// Calculate fee after signing since it adds OP_RETURN outputs\n\t\tfee = await modelOrFee.computeFee(tx);\n\t}\n\tfor (const utxo of utxos) {\n\t\tif (totalSatsIn >= totalSatsOut + BigInt(fee)) {\n\t\t\tbreak;\n\t\t}\n\t\tif (signInputs) {\n\t\t\tconst payKeyToUse = utxo.pk || paymentPk;\n\t\t\tif(!payKeyToUse) {\n\t\t\t\tthrow new Error(\"Private key is required to sign the transaction\");\n\t\t\t}\n\t\t\tconst input = inputFromB64Utxo(utxo, new P2PKH().unlock(\n\t\t\t\tpayKeyToUse,\n\t\t\t\t\"all\",\n\t\t\t\ttrue,\n\t\t\t\tutxo.satoshis,\n\t\t\t\tScript.fromBinary(Utils.toArray(utxo.script, 'base64'))\n\t\t\t));\n\t\t\ttx.addInput(input);\n\t\t} else {\n\t\t\t// Add input without unlock template for external signing\n\t\t\ttx.addInput(inputFromB64Utxo(utxo));\n\t\t}\n\t\t// stop adding inputs if the total amount is enough\n\t\ttotalSatsIn += BigInt(utxo.satoshis);\n\t\tfee = await modelOrFee.computeFee(tx);\n\t}\n\n\t// make sure we have enough\n\tif (totalSatsIn < totalSatsOut + BigInt(fee)) {\n\t\tthrow new Error(\n\t\t\t`Not enough funds to create ordinals. Total sats in: ${totalSatsIn}, Total sats out: ${totalSatsOut}, Fee: ${fee}`,\n\t\t);\n\t}\n\n\t// Calculate fee\n\tawait tx.fee(modelOrFee);\n\n\t// Sign the transaction (if signInputs is true)\n\tif (signInputs) {\n\t\tawait tx.sign();\n\t}\n\n\tconst payChangeOutIdx = tx.outputs.findIndex((o) => o.change);\n\tif (payChangeOutIdx !== -1) {\n\t\tconst changeOutput = tx.outputs[payChangeOutIdx];\n\t\tpayChange = {\n\t\t\tsatoshis: changeOutput.satoshis as number,\n\t\t\ttxid: tx.id(\"hex\") as string,\n\t\t\tvout: payChangeOutIdx,\n\t\t\tscript: Buffer.from(changeOutput.lockingScript.toBinary()).toString(\n\t\t\t\t\"base64\",\n\t\t\t),\n\t\t};\n\t}\n\n\tif (payChange) {\n\t\tconst changeOutput = tx.outputs[tx.outputs.length - 1];\n\t\tpayChange.satoshis = changeOutput.satoshis as number;\n\t\tpayChange.txid = tx.id(\"hex\") as string;\n\t}\n\n\treturn {\n\t\ttx,\n\t\tspentOutpoints: tx.inputs.map(\n\t\t\t(i) => `${i.sourceTXID}_${i.sourceOutputIndex}`,\n\t\t),\n\t\tpayChange,\n\t};\n};\n",
    "export const MAP_PREFIX = \"1PuQa7K62MiKCtssSLKy1kh56WWU7MtUR5\";\nexport const DEFAULT_SAT_PER_KB = 100;\nexport const API_HOST = \"https://ordinals.gorillapool.io/api\";",
    "import type { Transaction } from \"@bsv/sdk\";\nimport { Sigma } from \"sigma-protocol\";\nimport type { LocalSigner, RemoteSigner } from \"./types\";\n\n/**\n * Signs data in the transaction with Sigma protocol\n * @param {Transaction} tx - Transaction to sign\n * @param {LocalSigner | RemoteSigner} signer - Local or remote signer (used for data signature)\n * @returns {Transaction} Transaction with signed data\n */\nexport const signData = async (\n\ttx: Transaction,\n\tsigner: LocalSigner | RemoteSigner,\n): Promise<Transaction> => {\n\t// Sign tx if idKey or remote signer like starfish/tokenpass\n\tconst idKey = (signer as LocalSigner)?.idKey;\n\tconst keyHost = (signer as RemoteSigner)?.keyHost;\n\n\tif (idKey) {\n\t\tconst sigma = new Sigma(tx);\n\t\tconst { signedTx } = sigma.sign(idKey);\n\t\treturn signedTx;\n\t}\n\tif (keyHost) {\n\t\tconst authToken = (signer as RemoteSigner)?.authToken;\n\t\tconst sigma = new Sigma(tx);\n\t\ttry {\n\t\t\tconst { signedTx } = await sigma.remoteSign(keyHost, authToken);\n\t\t\treturn signedTx;\n\t\t} catch (e) {\n\t\t\tconsole.log(e);\n\t\t\tthrow new Error(`Remote signing to ${keyHost} failed`);\n\t\t}\n\t}\n\tthrow new Error(\"Signer must be a LocalSigner or RemoteSigner\");\n};\n",
    "import {\n\tLockingScript,\n\tP2PKH,\n\ttype Script,\n} from \"@bsv/sdk\";\nimport type { Inscription, MAP } from \"../types\";\nimport { toHex } from \"../utils/strings\";\nimport { MAP_PREFIX } from \"../constants\";\n\n/**\n * OrdP2PKH (1Sat Ordinal + Pay To Public Key Hash) class implementing ScriptTemplate.\n *\n * This class provides methods to create an Ordinal with Pay To Public Key Hash locking and unlocking scripts. \n * It extends the standard P2PKH script template and provides a custom lock method.\n */\nexport default class OrdP2PKH extends P2PKH {\n\t/**\n\t * Creates a 1Sat Ordinal + P2PKH locking script for a given address string\n\t *\n\t * @param {string} address - An destination address for the Ordinal.\n\t * @param {Object} [inscription] - Base64 encoded file data and Content type of the file.\n\t * @param {MAP} [metaData] - (optional) MAP Metadata to be included in OP_RETURN.\n\t * @returns {LockingScript} - A P2PKH locking script.\n\t */\n\t// unlock method inherits from p2pkh\n\tlock(\n\t\taddress: string,\n\t\tinscription?: Inscription,\n\t\tmetaData?: MAP | undefined,\n\t): Script {\n\t\t// Create ordinal output and inscription in a single output\n\t\tconst lockingScript = new P2PKH().lock(address);\n\t\treturn applyInscription(lockingScript, inscription, metaData);\n\t}\n}\n\nexport const applyInscription = (lockingScript: LockingScript, inscription?: Inscription, metaData?: MAP, withSeparator=false) => {\n\tlet ordAsm = \"\";\n\t// This can be omitted for reinscriptions that just update metadata\n\tif (inscription?.dataB64 !== undefined && inscription?.contentType !== undefined) {\n\t\tconst ordHex = toHex(\"ord\");\n\t\tconst fsBuffer = Buffer.from(inscription.dataB64, \"base64\");\n\t\tconst fileHex = fsBuffer.toString(\"hex\").trim();\n\t\tif (!fileHex) {\n\t\t\tthrow new Error(\"Invalid file data\");\n\t\t}\n\t\tconst fileMediaType = toHex(inscription.contentType);\n\t\tif (!fileMediaType) {\n\t\t\tthrow new Error(\"Invalid media type\");\n\t\t}\n\t\tordAsm = `OP_0 OP_IF ${ordHex} OP_1 ${fileMediaType} OP_0 ${fileHex} OP_ENDIF`;\n\t}\n\n\tlet inscriptionAsm = `${ordAsm ? `${ordAsm} ${withSeparator ? 'OP_CODESEPARATOR ' : ''}` : \"\"}${lockingScript.toASM()}`;\n\n\t// MAP.app and MAP.type keys are required\n\tif (metaData && (!metaData.app || !metaData.type)) {\n\t\tthrow new Error(\"MAP.app and MAP.type are required fields\");\n\t}\n\n\tif (metaData?.app && metaData?.type) {\n\t\tconst mapPrefixHex = toHex(MAP_PREFIX);\n\t\tconst mapCmdValue = toHex(\"SET\");\n\t\tinscriptionAsm = `${inscriptionAsm ? `${inscriptionAsm} ` : \"\"}OP_RETURN ${mapPrefixHex} ${mapCmdValue}`;\n\n\t\tfor (const [key, value] of Object.entries(metaData)) {\n\t\t\tif (key !== \"cmd\") {\n\t\t\t\tinscriptionAsm = `${inscriptionAsm} ${toHex(key)} ${toHex(\n\t\t\t\t\tvalue as string,\n\t\t\t\t)}`;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn LockingScript.fromASM(inscriptionAsm);\n}\n",
    "/**\n * Converts a string to its hexadecimal representation\n *\n * @param {string} utf8Str - The string to convert\n * @returns {string} The hexadecimal representation of the input string\n */\nconst toHex = (utf8Str: string): string => {\n  return Buffer.from(utf8Str).toString(\"hex\");\n};\n\nexport { toHex };\n",
    "import type { MAP, PreMAP } from \"../types\";\n\nconst stringifyMetaData = (metaData?: PreMAP): MAP | undefined => {\n  if (!metaData) return undefined;\n\tconst result: MAP = {\n\t\tapp: metaData.app,\n\t\ttype: metaData.type,\n\t};\n\n\tfor (const [key, value] of Object.entries(metaData)) {\n\t\tif (value !== undefined) {\n\t\t\tif (typeof value === \"string\") {\n\t\t\t\tresult[key] = value;\n\t\t\t} else if (Array.isArray(value) || typeof value === \"object\") {\n\t\t\t\tresult[key] = JSON.stringify(value);\n\t\t\t} else {\n\t\t\t\tresult[key] = String(value);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn result;\n};\n\nexport default stringifyMetaData;\n",
    "import {\n\ttype Transaction,\n\ttype UnlockingScript,\n\tfromUtxo,\n\ttype TransactionInput,\n\tUtils,\n\tP2PKH,\n\tScript,\n} from \"@bsv/sdk\";\nimport { type NftUtxo, type TokenSelectionOptions, type TokenSelectionResult, TokenSelectionStrategy, TokenType, type TokenUtxo, type Utxo } from \"../types\";\nimport { API_HOST } from \"../constants\";\nimport { toToken } from \"satoshi-token\";\n\nconst { fromBase58Check } = Utils;\n\n// Standard P2PKH unlocking script size: ~107 bytes\n// (1 byte push + 71-72 bytes signature + 1 byte push + 33 bytes pubkey)\nconst P2PKH_UNLOCK_SIZE = 107;\n\n/**\n * Converts a Utxo object with a base64 encoded script to a TransactionInput\n * @param {Utxo} utxo - Utxo object with base64 encoded script\n * @param {Object} [unlockScriptTemplate] - Optional. Object with sign and estimateLength functions.\n *   When omitted, creates input for external signing (signInputs: false mode) with fee estimation only.\n * @returns {TransactionInput} Transaction input with source info\n */\nexport const inputFromB64Utxo = (\n\tutxo: Utxo,\n\tunlockScriptTemplate?: {\n\t\tsign: (tx: Transaction, inputIndex: number) => Promise<UnlockingScript>;\n\t\testimateLength: (tx: Transaction, inputIndex: number) => Promise<number>;\n\t},\n): TransactionInput => {\n\tconst utxoHex = {\n\t\t...utxo,\n\t\tscript: Buffer.from(utxo.script, \"base64\").toString(\"hex\"),\n\t};\n\n\tif (unlockScriptTemplate) {\n\t\treturn fromUtxo(utxoHex, unlockScriptTemplate);\n\t}\n\n\t// For signInputs: false mode - create input that supports fee estimation\n\t// but will be signed externally (e.g., by wallet).\n\t// Uses fromUtxo with a template that estimates size but throws on sign.\n\treturn fromUtxo(utxoHex, {\n\t\testimateLength: async () => P2PKH_UNLOCK_SIZE,\n\t\tsign: async () => {\n\t\t\tthrow new Error(\n\t\t\t\t\"Cannot sign input: transaction was built with signInputs: false. \" +\n\t\t\t\t\"This input must be signed externally (e.g., by a wallet).\"\n\t\t\t);\n\t\t},\n\t});\n};\n\n/**\n * Fetches pay utxos from the API\n * @param {string} address - Address to fetch utxos for\n * @returns {Promise<Utxo[]>} Array of pay utxos\n */\nexport const fetchPayUtxos = async (address: string, scriptEncoding: \"hex\" | \"base64\" | \"asm\" = \"base64\"): Promise<Utxo[]> => {\n\tconst payUrl = `${API_HOST}/txos/address/${address}/unspent?bsv20=false`;\n\tconst payRes = await fetch(payUrl);\n\tif (!payRes.ok) {\n\t\tthrow new Error(\"Error fetching pay utxos\");\n\t}\n\tlet payUtxos = await payRes.json();\n\t// exclude all 1 satoshi utxos\n\tpayUtxos = payUtxos.filter((u: Utxo) => u.satoshis !== 1 && !isLock(u));\n\n\t// Get pubkey hash from address\n\tconst pubKeyHash = fromBase58Check(address);\n\tconst p2pkhScript = new P2PKH().lock(pubKeyHash.data);\n\tpayUtxos = payUtxos.map((utxo: Partial<Utxo>) => ({\n\t\ttxid: utxo.txid,\n\t\tvout: utxo.vout,\n\t\tsatoshis: utxo.satoshis,\n\t\tscript: scriptEncoding === \"hex\" || scriptEncoding === \"base64\" ? Buffer.from(p2pkhScript.toBinary()).toString(scriptEncoding) : p2pkhScript.toASM(),\n\t}));\n\treturn payUtxos as Utxo[];\n};\n\n/**\n * Fetches NFT utxos from the API\n * @param {string} address - Address to fetch utxos for\n * @param {string} [collectionId] - Optional. Collection id (collection insciprtion origin)\n * @param {number} [limit=10] - Optional. Number of utxos to fetch. Default is 10\n * @param {number} [offset=0] - Optional. Offset for fetching utxos. Default is 0\n * @param {string} [scriptEncoding=\"base64\"] - Optional. Encoding for the script. Default is base64. Options are hex, base64, or asm.\n * @returns {Promise<Utxo[]>} Array of NFT utxos\n */\nexport const fetchNftUtxos = async (\n\taddress: string,\n\tcollectionId?: string,\n\tlimit = 10,\n\toffset = 0,\n  scriptEncoding: \"hex\" | \"base64\" | \"asm\" = \"base64\",\n): Promise<NftUtxo[]> => {\n\tlet url = `${API_HOST}/txos/address/${address}/unspent?limit=${limit}&offset=${offset}&`;\n\n\tif (collectionId) {\n\t\tconst query = {\n\t\t\tmap: {\n\t\t\t\tsubTypeData: { collectionId },\n\t\t\t},\n\t\t};\n\t\tconst b64Query = Buffer.from(JSON.stringify(query)).toString(\"base64\");\n\t\turl += `q=${b64Query}`;\n\t}\n\n\tconst res = await fetch(url);\n\tif (!res.ok) {\n\t\tthrow new Error(`Error fetching NFT utxos for ${address}`);\n\t}\n\n\t// Returns a BSV20Txo but we only need a few fields\n\tlet nftUtxos = await res.json();\n\n\t// Only include 1 satoshi outputs, non listings\n\tnftUtxos = nftUtxos.filter(\n\t\t(u: {\n\t\t\tsatoshis: number;\n\t\t\tdata: { list: { price: number; payout: string } | undefined } | null;\n\t\t}) => u.satoshis === 1 && !u.data?.list,\n\t);\n\n\tconst outpoints = nftUtxos.map(\n\t\t(utxo: { txid: string; vout: number }) => `${utxo.txid}_${utxo.vout}`,\n\t);\n\t// Fetch the scripts up to the limit\n\tconst nftRes = await fetch(`${API_HOST}/txos/outpoints?script=true`, {\n\t\tmethod: \"POST\",\n\t\theaders: {\n\t\t\t\"Content-Type\": \"application/json\",\n\t\t},\n\t\tbody: JSON.stringify([...outpoints]),\n\t});\n\n\tif (!nftRes.ok) {\n\t\tthrow new Error(`Error fetching NFT scripts for ${address}`);\n\t}\n\n\tconst nfts = (await nftRes.json() || [])\n\n\tnftUtxos = nfts.map(\n\t\t(utxo: {\n\t\t\torigin: { outpoint: string };\n\t\t\tscript: string;\n\t\t\tvout: number;\n\t\t\ttxid: string;\n\t\t}) => {\n      let script = utxo.script;\n      if (scriptEncoding === \"hex\") {\n        script = Buffer.from(script, \"base64\").toString(\"hex\");\n      } else if (scriptEncoding === \"asm\") {\n        script = Script.fromHex(Buffer.from(script, \"base64\").toString(\"hex\")).toASM();\n      }\n\t\t\tconst nftUtxo = {\n\t\t\t\torigin: utxo.origin.outpoint,\n\t\t\t\tscript,\n\t\t\t\tvout: utxo.vout,\n\t\t\t\ttxid: utxo.txid,\n\t\t\t\tsatoshis: 1,\n\t\t\t} as NftUtxo;\n\t\t\tif (collectionId) {\n\t\t\t\tnftUtxo.collectionId = collectionId;\n\t\t\t}\n\t\t\treturn nftUtxo;\n\t\t},\n\t);\n\n\treturn nftUtxos as NftUtxo[];\n};\n\n/**\n * Fetches token utxos from the API\n * @param {TokenType} protocol - Token protocol. Either BSV20 or BSV21\n * @param {string} tokenId - Token id. Ticker for BSV20 and id (mint+deploy inscription origin) for BSV21\n * @param {string} address - Address to fetch utxos for\n * @param {number} [limit=10] - Number of utxos to fetch. Default is 10\n * @param {number} [offset=0] - Offset for fetching utxos. Default is 0\n * @returns {Promise<TokenUtxo[]>} Array of token utxos\n */\nexport const fetchTokenUtxos = async (\n\tprotocol: TokenType,\n\ttokenId: string,\n\taddress: string,\n  limit = 10,\n  offset = 0,\n): Promise<TokenUtxo[]> => {\n\tconst url = `${API_HOST}/bsv20/${address}/${protocol === TokenType.BSV20 ? \"tick\" : \"id\"}/${tokenId}?bsv20=true&listing=false&limit=${limit}&offset=${offset}`;\n\tconst res = await fetch(url);\n\tif (!res.ok) {\n\t\tthrow new Error(`Error fetching ${protocol} utxos`);\n\t}\n\n\t// returns a BSV20Txo but we only need a few fields\n\tlet tokenUtxos = await res.json();\n\n\ttokenUtxos = tokenUtxos.map((utxo: Partial<TokenUtxo>) => ({\n\t\tamt: utxo.amt,\n\t\tscript: utxo.script,\n\t\tvout: utxo.vout,\n\t\ttxid: utxo.txid,\n\t\tid: tokenId,\n\t\tsatoshis: 1,\n\t}));\n\n\treturn tokenUtxos as TokenUtxo[];\n};\n\nconst isLock = (utxo: Utxo) => {\n  return !!(utxo as unknown as { data?: {lock: { address: string, until: number } }}).data?.lock;\n}\n\n/**\n * Selects token UTXOs based on the required amount and specified strategies.\n * @param {TokenUtxo[]} tokenUtxos - Array of token UTXOs.\n * @param {number} requiredTokens - Required amount in tokens (displayed amount).\n * @param {number} decimals - Number of decimal places for the token.\n * @param {TokenSelectionOptions} [options={}] - Options for token selection.\n * @returns {TokenSelectionResult} Selected token UTXOs and total selected amount.\n */\nexport const selectTokenUtxos = (\n  tokenUtxos: TokenUtxo[],\n  requiredTokens: number,\n  decimals: number,\n  options: TokenSelectionOptions = {}\n): TokenSelectionResult => {\n  const {\n    inputStrategy = TokenSelectionStrategy.RetainOrder,\n    outputStrategy = TokenSelectionStrategy.RetainOrder,\n  } = options;\n  \n  // Sort the UTXOs based on the input strategy\n  const sortedUtxos = [...tokenUtxos].sort((a, b) => {\n    if (inputStrategy === TokenSelectionStrategy.RetainOrder) return 0;\n    const amtA = BigInt(a.amt);\n    const amtB = BigInt(b.amt);\n\n    switch (inputStrategy) {\n      case TokenSelectionStrategy.SmallestFirst:\n        return Number(amtA - amtB);\n      case TokenSelectionStrategy.LargestFirst:\n        return Number(amtB - amtA);\n      case TokenSelectionStrategy.Random:\n        return Math.random() - 0.5;\n      default:\n        return 0;\n    }\n  });\n\n  let totalSelected = 0;\n  const selectedUtxos: TokenUtxo[] = [];\n\n  for (const utxo of sortedUtxos) {\n    selectedUtxos.push(utxo);\n    totalSelected += toToken(utxo.amt, decimals);\n    if (totalSelected >= requiredTokens && requiredTokens > 0) {\n      break;\n    }\n  }\n\n  // Sort the selected UTXOs based on the output strategy\n  if (outputStrategy !== TokenSelectionStrategy.RetainOrder) {\n    selectedUtxos.sort((a, b) => {\n      const amtA = BigInt(a.amt);\n      const amtB = BigInt(b.amt);\n\n      switch (outputStrategy) {\n        case TokenSelectionStrategy.SmallestFirst:\n          return Number(amtA - amtB);\n        case TokenSelectionStrategy.LargestFirst:\n          return Number(amtB - amtA);\n        case TokenSelectionStrategy.Random:\n          return Math.random() - 0.5;\n        default:\n          return 0;\n      }\n    });\n  }\n\n  return {\n    selectedUtxos,\n    totalSelected,\n    isEnough: totalSelected >= requiredTokens\n  };\n};",
    "import type { PrivateKey, Script, Transaction } from \"@bsv/sdk\";\nimport type { AuthToken } from \"sigma-protocol\";\n\n// biome-ignore lint/complexity/noBannedTypes: Reserved for future use\ntype Signer = {};\n\nexport interface LocalSigner extends Signer {\n  idKey: PrivateKey;\n}\n\nexport interface RemoteSigner extends Signer {\n  keyHost: string;\n  authToken?: AuthToken;\n}\n\nexport type Destination = {\n  address: string;\n  inscription?: Inscription;\n};\n\n/**\n * @typedef {Object} Listing\n * @property {string} payAddress - Address to send the payment upon purchase\n * @property {string} price - Listing price in satoshis\n * @property {String} ordAddress - Where to return a listed ordinal upon cancel.\n * @property {Utxo} listingUtxo - Utxo of the listing\n */\nexport type NewListing = {\n  payAddress: string;\n  price: number;\n  ordAddress: string;\n  listingUtxo: Utxo;\n}\n\n/**\n * @typedef {Object} ExistingListing\n * @property {string} payout - Payment output script base64 encoded\n * @property {Utxo} listingUtxo - Utxo of the listing\n */\nexport type ExistingListing = {\n  payout: string;\n  listingUtxo: Utxo;\n}\n\n/**\n * @typedef {Object} NewTokenListing\n * @property {string} payAddress - Address to send the payment upon purchase\n * @property {string} price - Listing price in satoshis\n * @property {String} ordAddress - Where to return a listed ordinal upon cancel.\n * @property {number} tokens - Number of tokens in whole token display format. Ex. 0.5 for 0.5 tokens. Library handles conversion to 'tsat' format.\n */\nexport type NewTokenListing = {\n  payAddress: string;\n  price: number;\n  tokens: number;\n  ordAddress: string;\n}\n\n/**\n * @typedef {Object} Distribution\n * @property {string} address - Destination address. Must be a Ordinals address (BSV address for recieving 1Sat ordinals tokens).\n * @property {number} tokens - Number of tokens in whole token display format. Ex. 0.5 for 0.5 tokens. Library handles conversion to 'tsat' format. \n * @property {boolean} [omitMetaData] - Optional. Set to true to omit metadata from this distribution's output.\n */\nexport type Distribution = {\n  address: string | Script;\n  tokens: number;\n  omitMetaData?: boolean;\n};\n\n/**\n * @typedef {Object} Utxo\n * @property {number} satoshis - Amount in satoshis\n * @property {string} txid - Transaction id\n * @property {number} vout - Output index\n * @property {string} script - Base64 encoded locking script\n * @property {PrivateKey} [pk] - Optional. Private key for unlocking this utxo\n */\nexport type Utxo = {\n  satoshis: number;\n  txid: string;\n  vout: number;\n  script: string;\n  pk?: PrivateKey;\n};\n\n/**\n * @typedef {Object} NftUtxo\n * @property {string} collectionId - Optional. Collection id of the NFT\n * @property {string} contentType - Media type of the NFT\n * @property {string} creatorBapId - Optional. Creator BAP id of the NFT\n * @property {string} origin - Origin address of the NFT\n * @property {number} satoshis - Always 1\n * @property {PrivateKey} [pk] - Optional. Private key for unlocking this utxo\n */\nexport interface NftUtxo extends Utxo {\n  collectionId?: string;\n  contentType: string;\n  creatorBapId?: string;\n  origin: string;\n  satoshis: 1;\n  pk?: PrivateKey;\n}\n\n/**\n * @typedef {Object} TokenUtxo\n * @property {string} amt - Number of tokens as a string in 'tsat' format. Ex. 100000000 for 1 token with 8 decimal places.\n * @property {string} id - Token id -  either tick or id depending on protocol\n * @property {string} satoshis - Always 1\n * @property {string} [payout] - Optional. Payment output script base64 encoded\n * @property {number} [price] - Optional. Listing price in satoshis\n * @property {boolean} [isListing] - Optional. True if the token is a listing\n * @property {PrivateKey} [pk] - Optional. Private key for unlocking this utxo\n */\nexport interface TokenUtxo extends Utxo {\n  amt: string;\n  id: string;\n  satoshis: 1;\n  payout?: string;\n  price?: number;\n  isListing?: boolean;\n  pk?: PrivateKey;\n}\n\nexport enum TokenSelectionStrategy {\n  SmallestFirst = \"smallest\",\n  LargestFirst = \"largest\",\n  RetainOrder = \"retain\",\n  Random = \"random\",\n}\n\nexport interface TokenSelectionOptions {\n  inputStrategy?: TokenSelectionStrategy;\n  outputStrategy?: TokenSelectionStrategy;\n}\n\nexport interface TokenSelectionResult {\n  selectedUtxos: TokenUtxo[];\n  totalSelected: number;\n  isEnough: boolean;\n}\n\nexport type Inscription = {\n  dataB64: string;\n  contentType: string;\n};\n\nexport type ImageContentType =\n  | \"image/png\"\n  | \"image/jpeg\"\n  | \"image/gif\"\n  | \"image/svg+xml\"\n  | \"image/webp\";\n\n/**\n * @typedef {Object} IconInscription\n * @property {string} dataB64 - Base64 encoded image data. Must be a square image.\n * @property {ImageContentType} contentType - Media type of the image\n */\nexport type IconInscription = {\n  dataB64: string;\n  contentType: ImageContentType;\n};\n\nexport type Payment = {\n  to: string;\n  amount: number;\n};\n\nexport type TokenInscription = {\n  p: \"bsv-20\";\n  amt: string;\n  op: \"transfer\" | \"mint\" | \"deploy+mint\" | \"burn\";\n  dec?: string;\n};\n\nexport interface MintTokenInscription extends TokenInscription {\n  op: \"mint\";\n}\n\nexport interface DeployMintTokenInscription extends TokenInscription {\n  op: \"deploy+mint\";\n  sym: string;\n  icon: string;\n}\n\nexport interface TransferTokenInscription extends TokenInscription {\n  p: \"bsv-20\";\n  amt: string;\n  op: \"transfer\" | \"burn\";\n}\n\nexport interface TransferBSV20Inscription extends TransferTokenInscription {\n  tick: string;\n}\n\nexport interface TransferBSV21Inscription extends TransferTokenInscription {\n  id: string;\n}\n\nexport enum TokenType {\n  BSV20 = \"bsv20\",\n  BSV21 = \"bsv21\",\n}\n\nexport type BaseResult = {\n  tx: Transaction;\n  spentOutpoints: string[];\n};\n\nexport interface ChangeResult extends BaseResult {\n  payChange?: Utxo;\n};\n\n/**\n * MAP (Magic Attribute Protocol) metadata object with stringified values for writing to the blockchain\n * @typedef {Object} MAP\n * @property {string} app - Application identifier\n * @property {string} type - Metadata type\n * @property {string} [prop] - Optional. Additional metadata properties\n */\nexport type MAP = {\n  app: string;\n  type: string;\n  [prop: string]: string;\n};\n\nexport type PreMAP = {\n  app: string;\n  type: string;\n  [prop: string]: unknown;\n  royalties?: Royalty[];\n  subTypeData?: CollectionSubTypeData | CollectionItemSubTypeData;\n};\n\nexport type CreateOrdinalsConfig = {\n  utxos: Utxo[];\n  destinations: Destination[];\n  paymentPk?: PrivateKey;\n  changeAddress?: string;\n  satsPerKb?: number;\n  metaData?: PreMAP;\n  signer?: LocalSigner | RemoteSigner;\n  additionalPayments?: Payment[];\n  /** When false, inputs are added without unlocking scripts and tx.sign() is skipped. Default: true */\n  signInputs?: boolean;\n};\n\nexport enum RoytaltyType {\n  Paymail = \"paymail\",\n  Address = \"address\",\n  Script = \"script\",\n}\n\n/**\n * Royalty object\n * @typedef {Object} Royalty\n * @property {RoytaltyType} type - Royalty type, string, one of \"paymail\", \"address\", \"script\"\n * @property {string} destination - Royalty destination\n * @property {string} percentage - Royalty percentage as a string float 0-1 (0.01 = 1%)\n */\nexport type Royalty = {\n  type: RoytaltyType;\n  destination: string;\n  percentage: string; // string float 0-1\n};\n\nexport interface CreateOrdinalsMetadata extends PreMAP {\n  type: \"ord\",\n  name: string,\n  previewUrl?: string,\n}\n\nexport interface CreateOrdinalsCollectionMetadata extends CreateOrdinalsMetadata {\n  subType: \"collection\",\n  subTypeData: CollectionSubTypeData, // JSON stringified CollectionSubTypeData\n  royalties?: Royalty[],\n};\n\nexport interface CreateOrdinalsCollectionItemMetadata extends CreateOrdinalsMetadata {\n  subType: \"collectionItem\",\n  subTypeData: CollectionItemSubTypeData, // JSON stringified CollectionItemSubTypeData\n};\n\n/**\n * Configuration object for creating an ordinals collection\n * @typedef {Object} CreateOrdinalsCollectionConfig\n * @property metaData - MAP (Magic Attribute Protocol) metadata for the collection\n * @property metaData.type - \"ord\"\n * @property metaData.subType - \"collection\"\n * @property metaData.name - Collection name\n * @property metaData.subTypeData - JSON stringified CollectionSubTypeData\n * @property [metaData.royalties] - Optional. Royalties address\n * @property [metaData.previewUrl] - Optional. Preview URL\n */\nexport interface CreateOrdinalsCollectionConfig extends CreateOrdinalsConfig {\n  metaData: CreateOrdinalsCollectionMetadata\n}\n\nexport type CollectionTraits = {\n  [trait: string]: CollectionTrait;\n};\n\nexport type CollectionTrait = {\n  values: string[];\n  occurancePercentages: string[];\n};\n\nexport type Rarity = {\n  [key: string]: string;\n}\n\nexport type RarityLabels = Rarity[]\nexport interface CollectionSubTypeData {\n  description: string;\n  quantity: number;\n  rarityLabels: RarityLabels;\n  traits: CollectionTraits;\n}\n\nexport interface CreateOrdinalsCollectionItemMetadata extends PreMAP {\n  type: \"ord\",\n  name: string,\n  subType: \"collectionItem\",\n  subTypeData: CollectionItemSubTypeData, // JSON stringified CollectionItemSubTypeData\n  previewUrl?: string,\n}\n\n/**\n * Configuration object for creating an ordinals collection item\n * @typedef {Object} CreateOrdinalsCollectionItemConfig\n * @property metaData - MAP (Magic Attribute Protocol) metadata for the collection item\n * @property metaData.type - \"ord\"\n * @property metaData.subType - \"collectionItem\"\n * @property metaData.name - Collection item name\n * @property metaData.subTypeData - JSON stringified CollectionItemSubTypeData\n * @property [metaData.royalties] - Optional. Royalties address\n * @property [metaData.previewUrl] - Optional. Preview URL\n */\nexport interface CreateOrdinalsCollectionItemConfig extends CreateOrdinalsConfig {\n  metaData: CreateOrdinalsCollectionItemMetadata\n}\n\n/**\n * Subtype data for an ordinals collection item\n * @typedef {Object} CollectionItemSubTypeData\n * @property {string} collectionId - Collection id\n * @property {number} mintNumner - Mint number\n * @property {number} rank - Rank\n * @property {string} rarityLabel - Rarity label\n * @property {string} traits - traits object\n * @property {string} attachments - array of attachment objects\n */\nexport interface CollectionItemSubTypeData {\n  collectionId: string;\n  mintNumber?: number;\n  rank?: number;\n  rarityLabel?: RarityLabels;\n  traits?: CollectionItemTrait[];\n  attachments?: CollectionItemAttachment[];\n}\n\nexport type CollectionItemTrait = {\n  name: string;\n  value: string;\n  rarityLabel?: string;\n  occurancePercentrage?: string;\n};\n\nexport type CollectionItemAttachment = {\n  name: string;\n  description?: string;\n  \"content-type\": string;\n  url: string;\n}\n\nexport interface BurnMAP extends MAP {\n  type: \"ord\";\n  op: \"burn\";\n}\n\nexport type BurnOrdinalsConfig = {\n  ordPk?: PrivateKey;\n  ordinals: Utxo[];\n  metaData?: BurnMAP;\n}\n\nexport type SendOrdinalsConfig = {\n  paymentUtxos: Utxo[];\n  ordinals: Utxo[];\n  paymentPk?: PrivateKey;\n  ordPk?: PrivateKey;\n  destinations: Destination[];\n  changeAddress?: string;\n  satsPerKb?: number;\n  metaData?: PreMAP;\n  signer?: LocalSigner | RemoteSigner;\n  additionalPayments?: Payment[];\n  enforceUniformSend?: boolean;\n  /** When false, inputs are added without unlocking scripts and tx.sign() is skipped. Default: true */\n  signInputs?: boolean;\n}\n\nexport type DeployBsv21TokenConfig = {\n  symbol: string;\n  decimals?: number;\n  icon: string | IconInscription;\n  utxos: Utxo[];\n  initialDistribution: Distribution;\n  paymentPk?: PrivateKey;\n  destinationAddress: string;\n  changeAddress?: string;\n  satsPerKb?: number;\n  additionalPayments?: Payment[];\n  signer?: LocalSigner | RemoteSigner;\n  /** When false, inputs are added without unlocking scripts and tx.sign() is skipped. Default: true */\n  signInputs?: boolean;\n};\n\nexport type SendUtxosConfig = {\n  utxos: Utxo[];\n  paymentPk?: PrivateKey;\n  payments: Payment[];\n  satsPerKb?: number;\n  changeAddress?: string;\n  metaData?: MAP;\n  signer?: LocalSigner | RemoteSigner;\n  /** When false, inputs are added without unlocking scripts and tx.sign() is skipped. Default: true */\n  signInputs?: boolean;\n};\n\nexport interface TokenChangeResult extends ChangeResult {\n  tokenChange?: TokenUtxo[];\n}\n\n/**\n * Configuration object for token outputs\n * @typedef {Object} TokenSplitConfig\n * @property {number} outputs - Number of outputs to split the token into. Default is 1.\n * @property {number} threshold - Optional. Minimum amount of tokens per output.\n * @property {boolean} omitMetaData - Set to true to omit metadata from the token change outputs\n **/\nexport type TokenSplitConfig = {\n  outputs: number;\n  threshold?: number;\n  omitMetaData?: boolean;\n}\n\nexport enum TokenInputMode {\n  All = \"all\",\n  Needed = \"needed\",\n}\n\n/**\n * Configuration object for transferring token ordinals\n * @typedef {Object} TransferOrdTokensConfig\n * @property {TokenType} protocol - Token protocol\n * @property {string} tokenID - Token id\n * @property {number} decimals - Number of decimal places for this token.\n * @property {Utxo[]} utxos - Array of payment Utxos\n * @property {TokenUtxo[]} inputTokens - Array of TokenUtxos to be transferred\n * @property {Distribution[]} distributions - Array of Distribution objects\n * @property {PrivateKey} paymentPk - Private key of the payment address\n * @property {PrivateKey} ordPk - Private key of the ord address\n * @property {string} [changeAddress] - Optional. Address to send the change\n * @property {string} [tokenChangeAddress] - Optional. Address to send the token change\n * @property {number} [satsPerKb] - Optional. Satoshis per kilobyte\n * @property {PreMAP} [metaData] - Optional. MAP metadata object\n * @property {LocalSigner | RemoteSigner} [signer] - Optional. Signer object\n * @property {Payment[]} [additionalPayments] - Optional. Array of additional payments\n * @property {boolean} [burn] - Optional. Set to true to burn the input tokens\n * @property {TokenSplitConfig} [splitConfig] - Optional. Configuration object for splitting token change\n * @property {TokenInputMode} [tokenInputMode] - Optional. Token input mode. Default is \"needed\"\n */\nexport type TransferOrdTokensConfig = {\n  protocol: TokenType;\n  tokenID: string;\n  decimals: number;\n  utxos: Utxo[];\n  inputTokens: TokenUtxo[];\n  distributions: Distribution[];\n  paymentPk?: PrivateKey;\n  ordPk?: PrivateKey;\n  inputMode?: TokenInputMode;\n  changeAddress?: string;\n  tokenChangeAddress?: string;\n  satsPerKb?: number;\n  metaData?: PreMAP;\n  signer?: LocalSigner | RemoteSigner;\n  additionalPayments?: Payment[];\n  burn?: boolean;\n  splitConfig?: TokenSplitConfig;\n  tokenInputMode?: TokenInputMode;\n  /** When false, inputs are added without unlocking scripts and tx.sign() is skipped. Default: true */\n  signInputs?: boolean;\n}\n\nexport type CreateOrdListingsConfig = {\n  utxos: Utxo[];\n  listings: NewListing[];\n  paymentPk?: PrivateKey;\n  ordPk: PrivateKey,\n  changeAddress?: string;\n  satsPerKb?: number;\n  additionalPayments?: Payment[];\n  signer?: LocalSigner | RemoteSigner;\n  /** When false, inputs are added without unlocking scripts and tx.sign() is skipped. Default: true */\n  signInputs?: boolean;\n}\n\nexport type PurchaseOrdListingConfig = {\n  utxos: Utxo[];\n  paymentPk?: PrivateKey;\n  listing: ExistingListing;\n  ordAddress: string;\n  changeAddress?: string;\n  satsPerKb?: number;\n  additionalPayments?: Payment[],\n  royalties?: Royalty[],\n  metaData?: MAP,\n}\n\nexport type PurchaseOrdTokenListingConfig = {\n  protocol: TokenType;\n  tokenID: string;\n  utxos: Utxo[];\n  paymentPk?: PrivateKey;\n  listingUtxo: TokenUtxo;\n  ordAddress: string;\n  changeAddress?: string;\n  satsPerKb?: number;\n  additionalPayments?: Payment[],\n  metaData?: MAP,\n}\n\nexport type CancelOrdListingsConfig = {\n  utxos: Utxo[],\n  paymentPk?: PrivateKey;\n  ordPk?: PrivateKey;\n  listingUtxos: Utxo[];\n  additionalPayments?: Payment[];\n  changeAddress?: string;\n  satsPerKb?: number;\n}\n\nexport interface CancelOrdTokenListingsConfig extends CancelOrdListingsConfig {\n  utxos: Utxo[],\n  paymentPk?: PrivateKey;\n  ordPk?: PrivateKey;\n  listingUtxos: TokenUtxo[];\n  additionalPayments: Payment[];\n  changeAddress?: string;\n  satsPerKb?: number;\n  protocol: TokenType,\n  tokenID: string;\n  ordAddress?: string;\n}\n\n/**\n * Configuration object for creating a token listing\n * @typedef {Object} CreateOrdTokenListingsConfig\n * @property {Utxo[]} utxos - Array of payment Utxos\n * @property {TokenUtxo[]} inputTokens - Array of TokenUtxos to be listed\n * @property {NewTokenListing[]} listings - Array of NewTokenListings\n * @property {PrivateKey} paymentPk - Private key of the payment address\n * @property {PrivateKey} ordPk - Private key of the ord address\n * @property {string} tokenChangeAddress - Address to send the token change\n * @property {number} [satsPerKb] - Optional. Satoshis per kilobyte\n * @property {Payment[]} [additionalPayments] - Optional. Array of additional payments\n * @property {TokenType} protocol - Token protocol\n * @property {string} tokenID - Token id\n * @property {number} decimals - Number of decimal places for this token.\n */\nexport interface CreateOrdTokenListingsConfig {\n  utxos: Utxo[];\n  listings: NewTokenListing[];\n  paymentPk?: PrivateKey;\n  ordPk?: PrivateKey,\n  changeAddress?: string;\n  satsPerKb?: number;\n  additionalPayments?: Payment[];\n  protocol: TokenType;\n  tokenID: string;\n  decimals: number;\n  inputTokens: TokenUtxo[];\n  tokenChangeAddress: string;\n  signer?: LocalSigner | RemoteSigner;\n  /** When false, inputs are added without unlocking scripts and tx.sign() is skipped. Default: true */\n  signInputs?: boolean;\n}\n\nexport const MAX_TOKEN_SUPPLY = 18446744073709551615n; // 2^64 - 1",
    "import {\n\tTransaction,\n\tSatoshisPerKilobyte,\n\tP2PKH,\n\tScript,\n\tUtils,\n} from \"@bsv/sdk\";\nimport { DEFAULT_SAT_PER_KB } from \"./constants\";\nimport OrdP2PKH from \"./templates/ordP2pkh\";\nimport type { SendOrdinalsConfig, Utxo, ChangeResult } from \"./types\";\nimport { inputFromB64Utxo } from \"./utils/utxo\";\nimport { signData } from \"./signData\";\nimport stringifyMetaData from \"./utils/subtypeData\";\nimport { MAP } from \"@bopen-io/templates\";\n\n/**\n * Sends ordinals to the given destinations\n * @param {SendOrdinalsConfig} config - Configuration object for sending ordinals\n * @param {Utxo[]} config.paymentUtxos - Utxos to spend (with base64 encoded scripts)\n * @param {Utxo[]} config.ordinals - Utxos to spend (with base64 encoded scripts)\n * @param {PrivateKey} config.paymentPk - Private key to sign paymentUtxos\n * @param {PrivateKey} config.ordPk - Private key to sign ordinals\n * @param {Destination[]} config.destinations - Array of destinations with addresses and inscriptions\n * @param {string} [config.changeAddress] - Optional. Address to send change to, if any. If not provided, defaults to paymentPk address\n * @param {number} [config.satsPerKb] - Optional. Satoshis per kilobyte for fee calculation. Default is DEFAULT_SAT_PER_KB\n * @param {PreMAP} [config.metaData] - Optional. MAP (Magic Attribute Protocol) metadata to include in inscriptions\n * @param {LocalSigner | RemoteSigner} [config.signer] - Optional. Signer object to sign the transaction\n * @param {Payment[]} [config.additionalPayments] - Optional. Additional payments to include in the transaction\n * @param {boolean} [config.enforceUniformSend] - Optional. Default: true. Enforce that the number of destinations matches the number of ordinals being sent. Sending ordinals requires a 1:1 mapping of destinations to ordinals. This is only used for sub-protocols like BSV21 that manage tokens without sending the inscriptions directly.\n * @returns {Promise<ChangeResult>} Transaction, spent outpoints, and change utxo\n */\nexport const sendOrdinals = async (\n\tconfig: SendOrdinalsConfig,\n): Promise<ChangeResult> => {\n\tif (!config.satsPerKb) {\n\t\tconfig.satsPerKb = DEFAULT_SAT_PER_KB;\n\t}\n\tif (!config.additionalPayments) {\n\t\tconfig.additionalPayments = [];\n\t}\n\tif (config.enforceUniformSend === undefined) {\n\t\tconfig.enforceUniformSend = true;\n\t}\n\tif (config.signInputs === undefined) {\n\t\tconfig.signInputs = true;\n\t}\n\n\tconst {ordPk, paymentPk, signInputs} = config;\n\n\tconst modelOrFee = new SatoshisPerKilobyte(config.satsPerKb);\n\tlet tx = new Transaction();\n\tconst spentOutpoints: string[] = [];\n\n\t// Inputs\n\t// Add ordinal inputs\n\tfor (const ordUtxo of config.ordinals) {\n\t\tif (ordUtxo.satoshis !== 1) {\n\t\t\tthrow new Error(\"1Sat Ordinal utxos must have exactly 1 satoshi\");\n\t\t}\n\n\t\tif (signInputs) {\n\t\t\tconst ordKeyToUse = ordUtxo.pk || ordPk;\n\t\t\tif (!ordKeyToUse) {\n\t\t\t\tthrow new Error(\"Private key is required to sign the ordinal\");\n\t\t\t}\n\t\t\tconst input = inputFromB64Utxo(\n\t\t\t\tordUtxo,\n\t\t\t\tnew OrdP2PKH().unlock(\n\t\t\t\t\tordKeyToUse,\n\t\t\t\t\t\"all\",\n\t\t\t\t\ttrue,\n\t\t\t\t\tordUtxo.satoshis,\n\t\t\t\t\tScript.fromBinary(Utils.toArray(ordUtxo.script, 'base64'))\n\t\t\t\t),\n\t\t\t);\n\t\t\ttx.addInput(input);\n\t\t} else {\n\t\t\ttx.addInput(inputFromB64Utxo(ordUtxo));\n\t\t}\n\t\tspentOutpoints.push(`${ordUtxo.txid}_${ordUtxo.vout}`);\n\t}\n\n\t// Outputs\n\t// check that ordinals coming in matches ordinals going out if supplied\n\tif (\n\t\tconfig.enforceUniformSend &&\n\t\tconfig.destinations.length !== config.ordinals.length\n\t) {\n\t\tthrow new Error(\n\t\t\t\"Number of destinations must match number of ordinals being sent\",\n\t\t);\n\t}\n\n\t// Add ordinal outputs\n\tfor (const destination of config.destinations) {\n\t\tlet s: Script;\n\t\tif (\n\t\t\tdestination.inscription?.dataB64 &&\n\t\t\tdestination.inscription?.contentType\n\t\t) {\n\t\t\ts = new OrdP2PKH().lock(\n\t\t\t\tdestination.address,\n\t\t\t\tdestination.inscription,\n\t\t\t\tstringifyMetaData(config.metaData),\n\t\t\t);\n\t\t} else {\n\t\t\ts = new P2PKH().lock(destination.address);\n\n\t\t\tif (config.metaData) {\n\t\t\t\tconst data = {} as Record<string, string>;\n\t\t\t\tfor (const key in config.metaData) {\n\t\t\t\t\tdata[key] = (config.metaData[key] as any).toString();\n\t\t\t\t}\n\t\t\t\ts = new Script([\n\t\t\t\t\t...s.chunks,\n\t\t\t\t\t...MAP.lock(\"SET\", data).chunks,\n\t\t\t\t])\n\t\t\t}\n\t\t}\n\n\t\ttx.addOutput({\n\t\t\tsatoshis: 1,\n\t\t\tlockingScript: s,\n\t\t});\n\t}\n\n  \n\t// Add additional payments if any\n\tfor (const p of config.additionalPayments) {\n\t\ttx.addOutput({\n\t\t\tsatoshis: p.amount,\n\t\t\tlockingScript: new P2PKH().lock(p.to),\n\t\t});\n\t}\n\n  // add change to the outputs\n\tlet payChange: Utxo | undefined;\n\n  const changeAddress = config.changeAddress || paymentPk?.toAddress();\n\tif(!changeAddress) {\n\t\tthrow new Error(\"Either changeAddress or paymentPk is required\");\n\t}\n\tconst changeScript = new P2PKH().lock(changeAddress);\n\tconst changeOut = {\n\t\tlockingScript: changeScript,\n\t\tchange: true,\n\t};\n\ttx.addOutput(changeOut);\n\n\t// Inputs\n\tlet totalSatsIn = 0n;\n\tconst totalSatsOut = tx.outputs.reduce(\n\t\t(total, out) => total + BigInt(out.satoshis || 0),\n\t\t0n,\n\t);\n\tlet fee = 0;\n\tfor (const utxo of config.paymentUtxos) {\n\t\tif (signInputs) {\n\t\t\tconst payKeyToUse = utxo.pk || paymentPk;\n\t\t\tif (!payKeyToUse) {\n\t\t\t\tthrow new Error(\"Private key is required to sign the payment\");\n\t\t\t}\n\t\t\tconst input = inputFromB64Utxo(utxo, new P2PKH().unlock(\n\t\t\t\tpayKeyToUse,\n\t\t\t\t\"all\",\n\t\t\t\ttrue,\n\t\t\t\tutxo.satoshis,\n\t\t\t\tScript.fromBinary(Utils.toArray(utxo.script, 'base64'))\n\t\t\t));\n\t\t\ttx.addInput(input);\n\t\t} else {\n\t\t\ttx.addInput(inputFromB64Utxo(utxo));\n\t\t}\n\t\tspentOutpoints.push(`${utxo.txid}_${utxo.vout}`);\n\n\t\t// stop adding inputs if the total amount is enough\n\t\ttotalSatsIn += BigInt(utxo.satoshis);\n\t\tfee = await modelOrFee.computeFee(tx);\n\n\t\tif (totalSatsIn >= totalSatsOut + BigInt(fee)) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (totalSatsIn < totalSatsOut) {\n\t\tthrow new Error(\"Not enough ordinals to send\");\n\t}\n\n\tif (config.signer) {\n\t\ttx = await signData(tx, config.signer);\n\t}\n\n\t// Calculate fee\n\tawait tx.fee(modelOrFee);\n\n\t// Sign the transaction (if signInputs is true)\n\tif (signInputs) {\n\t\tawait tx.sign();\n\t}\n\n\tconst payChangeOutIdx = tx.outputs.findIndex((o) => o.change);\n\tif (payChangeOutIdx !== -1) {\n\t\tconst changeOutput = tx.outputs[payChangeOutIdx];\n\t\tpayChange = {\n\t\t\tsatoshis: changeOutput.satoshis as number,\n\t\t\ttxid: tx.id(\"hex\") as string,\n\t\t\tvout: payChangeOutIdx,\n\t\t\tscript: Buffer.from(changeOutput.lockingScript.toBinary()).toString(\n\t\t\t\t\"base64\",\n\t\t\t),\n\t\t};\n\t}\n\n\tif (payChange) {\n\t\tconst changeOutput = tx.outputs[tx.outputs.length - 1];\n\t\tpayChange.satoshis = changeOutput.satoshis as number;\n\t\tpayChange.txid = tx.id(\"hex\") as string;\n\t}\n\n\treturn {\n\t\ttx,\n\t\tspentOutpoints,\n\t\tpayChange,\n\t};\n};\n",
    "import { OP, LockingScript, Utils } from '@bsv/sdk';\n/**\n * OpReturn class implementing ScriptTemplate.\n *\n * This class provides methods to create OpReturn scripts from data. Only lock script is available.\n */\nexport class OpReturn {\n    /**\n       * Creates an OpReturn script\n       *\n       * @param {string | string[] | number[]} data The data or array of data to push after OP_RETURN.\n       * @param {('hex' | 'utf8' | 'base64')} enc The data encoding type, defaults to utf8.\n       * @returns {LockingScript} - An OpReturn locking script.\n       */\n    lock(data, enc) {\n        const script = [\n            { op: OP.OP_FALSE },\n            { op: OP.OP_RETURN }\n        ];\n        if (typeof data === 'string') {\n            data = [data];\n        }\n        if ((data.length > 0) && typeof data[0] === 'number') {\n            script.push({ op: data.length, data: data });\n        }\n        else {\n            for (const entry of data.filter(Boolean)) {\n                const arr = Utils.toArray(entry, enc);\n                script.push({ op: arr.length, data: arr });\n            }\n        }\n        return new LockingScript(script);\n    }\n    /**\n       * Unlock method is not available for OpReturn scripts, throws exception.\n       */\n    unlock() {\n        throw new Error('Unlock is not supported for OpReturn scripts');\n    }\n    /**\n   * Decodes an OpReturn script data to utf8\n   * @param script The opreturn script\n   * @returns An array of UTF8 encoded strings\n   */\n    static decode(script) {\n        const tokens = script.toASM().split(' ').slice(2);\n        return tokens.map(token => Utils.toUTF8(Utils.toArray(token, 'hex')));\n    }\n}\n//# sourceMappingURL=OpReturn.js.map",
    "import { OP, LockingScript, Utils } from '@bsv/sdk';\n/**\n * Metanet class implementing ScriptTemplate.\n *\n * This class provides methods to create Metanet outputs from data. Only lock script is available.\n */\nexport default class Metanet {\n    /**\n   * Creates a Metanet output script\n   *\n   * @param {PublicKey} pubkey the public key responsible for the metanet node\n   * @param {string} parentTXID the TXID of the parent metanet transaction or null for root node\n   * @param {string[]} data the output data, an array of metadata ending in data payload\n   * @returns {LockingScript} - A Metanet locking script.\n   *\n   * @example\n   * // creates a root metanet output with 'subprotocol' and 'filename' metadata followed by data\n   * lock(pubkey, null, txid, ['subprotocol', 'filename', data ])\n   */\n    lock(pubkey, parentTXID, data = []) {\n        const script = [\n            { op: OP.OP_FALSE },\n            { op: OP.OP_RETURN }\n        ];\n        const fields = [\n            'meta',\n            pubkey.toString(),\n            parentTXID ?? 'null'\n        ].concat(data);\n        for (const field of fields.filter(Boolean)) {\n            script.push({ op: field.length, data: Utils.toArray(field) });\n        }\n        return new LockingScript(script);\n    }\n    /**\n      * Unlock method is not available for Metanet scripts, throws exception.\n      */\n    unlock() {\n        throw new Error('Unlock is not supported for Metanet scripts');\n    }\n}\n//# sourceMappingURL=Metanet.js.map",
    "import { LockingScript, UnlockingScript, OP, Utils, Hash, TransactionSignature, Signature } from '@bsv/sdk';\n// Helper to ensure a value is not null or undefined\nfunction verifyTruthy(v, err) {\n    if (v === null || v === undefined)\n        throw new Error(err ?? 'Value must not be null or undefined');\n    return v;\n}\n// Helper to create minimally encoded script chunks (same as in PushDrop)\nconst createMinimallyEncodedScriptChunk = (data) => {\n    if (data.length === 0)\n        return { op: 0 }; // OP_0\n    if (data.length === 1 && data[0] === 0)\n        return { op: 0 }; // OP_0\n    if (data.length === 1 && data[0] > 0 && data[0] <= 16)\n        return { op: 0x50 + data[0] }; // OP_1 to OP_16\n    if (data.length === 1 && data[0] === 0x81)\n        return { op: 0x4f }; // OP_1NEGATE\n    if (data.length <= 75)\n        return { op: data.length, data };\n    if (data.length <= 255)\n        return { op: 0x4c, data }; // OP_PUSHDATA1\n    if (data.length <= 65535)\n        return { op: 0x4d, data }; // OP_PUSHDATA2\n    return { op: 0x4e, data }; // OP_PUSHDATA4\n};\n/**\n * MultiPushDrop Script Template\n *\n * This template creates locking scripts that allow spending by any one of multiple\n * specified public keys (1-of-N). It also pushes arbitrary data fields onto the stack,\n * which are dropped after the signature check.\n *\n * When using this among adversarial or non-trusted groups, the MASSIVE caveat is that\n * there is no constraint enforcing that any group members are kept in the loop. Any group\n * member can trivially destroy the token. For more practical non-trusted arrangements,\n * techniques like OP_PUSH_TX should be used instead.\n *\n * There's also a known bug in this implementation where it won't work with over around 120\n * keys but involving more than a few people than just a few into a FULLY TRUST BASED exchange\n * is never a good idea. Use a more robust, application-specific mechanism.\n */\nexport class MultiPushDrop {\n    wallet;\n    originator;\n    /**\n       * Decodes a MultiPushDrop locking script back into its data fields and the list of locking public keys.\n       * @param script The MultiPushDrop locking script to decode.\n       * @returns {MultiPushDropDecoded} An object containing the locking public keys and data fields.\n       * @throws {Error} If the script structure is not a valid MultiPushDrop script.\n       */\n    static decode(script) {\n        const chunks = script.chunks;\n        let cursor = 0;\n        // Decode keys until they stop being 33 bytes long\n        const lockingPublicKeys = [];\n        while (chunks[cursor].data?.length === 33) {\n            const keyChunk = verifyTruthy(chunks[cursor], `Missing public key chunk ${cursor}`);\n            const keyData = verifyTruthy(keyChunk.data, `Public key chunk ${cursor} has no data`);\n            lockingPublicKeys.push(Utils.toHex(keyData));\n            cursor++;\n        }\n        // Skip the nPublicKeys chunk and opcodes.\n        // This amounts to 8 items to skip.\n        cursor += 8;\n        // Decode Data Fields\n        const fields = [];\n        for (let i = cursor; i < chunks.length; i++) {\n            const nextOpcode = chunks[i + 1]?.op;\n            const chunkData = chunks[i].data ?? []; // Use OP code for OP_0-OP_16 etc. if data is null\n            let currentField = [];\n            if (chunkData.length > 0) {\n                currentField = chunkData;\n            }\n            else if (chunks[i].op >= OP.OP_1 && chunks[i].op <= OP.OP_16) {\n                currentField = [chunks[i].op - OP.OP_1 + 1];\n            }\n            else if (chunks[i].op === OP.OP_0) {\n                currentField = []; // Represent OP_0 as empty array\n            }\n            else if (chunks[i].op === OP.OP_1NEGATE) {\n                currentField = [0x81];\n            }\n            else if (chunks[i].op === OP.OP_DROP || chunks[i].op === OP.OP_2DROP) {\n                // Stop before the drops\n                break;\n            }\n            else {\n                // Assume it's a data push even if data is empty for some reason\n                currentField = chunkData;\n            }\n            fields.push(currentField);\n            // If the next opcode is a DROP, we've found the last field\n            if (nextOpcode === OP.OP_DROP || nextOpcode === OP.OP_2DROP) {\n                break;\n            }\n        }\n        return {\n            lockingPublicKeys,\n            fields\n        };\n    }\n    /**\n      * Constructs a new instance of the MultiPushDrop class.\n      *\n      * @param {WalletInterface} wallet - The wallet interface used for deriving keys and signing.\n      * @param {string} [originator] - The originator domain for wallet requests.\n      */\n    constructor(wallet, originator) {\n        this.wallet = wallet;\n        this.originator = originator;\n    }\n    /**\n      * Creates a MultiPushDrop locking script.\n      *\n      * @param {number[][]} fields - The arbitrary data fields to include in the script.\n      * @param {[SecurityLevel, string]} protocolID - The protocol ID used for key derivation.\n      * @param {string} keyID - The key ID used for key derivation.\n      * @param {WalletCounterparty[]} counterparties - An array of counterparties ('self' or PubKeyHex) whose derived keys can unlock the script. Must contain at least one.\n      * @returns {Promise<LockingScript>} The generated MultiPushDrop locking script.\n      * @throws {Error} If counterparties array is empty.\n      */\n    async lock(fields, protocolID, keyID, counterparties) {\n        if (!Array.isArray(counterparties) || counterparties.length === 0) {\n            throw new Error('MultiPushDrop requires at least one counterparty.');\n        }\n        const publicKeys = [];\n        for (const counterparty of counterparties) {\n            const { publicKey } = await this.wallet.getPublicKey({\n                protocolID,\n                keyID,\n                counterparty\n            }, this.originator);\n            publicKeys.push(publicKey);\n        }\n        const nPublicKeys = publicKeys.length;\n        const lockPart = [];\n        // Push Public Keys\n        for (const publicKeyHex of publicKeys) {\n            lockPart.push({\n                op: publicKeyHex.length / 2, // Length of compressed pubkey is 33 bytes (66 hex)\n                data: Utils.toArray(publicKeyHex, 'hex')\n            });\n        }\n        // Pick the value on the stack that's right before the locking script.\n        // This should be the index of the key to use in the unlock.\n        lockPart.push(createMinimallyEncodedScriptChunk([nPublicKeys]));\n        lockPart.push({ op: OP.OP_PICK });\n        // Now we use the index to get the actual key.\n        lockPart.push({ op: OP.OP_PICK });\n        // We pull the signature from the bottom of the stack, no matter the number of keys.\n        lockPart.push({ op: OP.OP_DEPTH });\n        lockPart.push({ op: OP.OP_1SUB });\n        lockPart.push({ op: OP.OP_PICK });\n        // We swap the signature and public key so they're in the correct order, then CHECKSIGVERIFY\n        lockPart.push({ op: OP.OP_SWAP });\n        lockPart.push({ op: OP.OP_CHECKSIGVERIFY });\n        // Construct PushDrop Part for fields\n        const pushDropPart = [];\n        for (const field of fields) {\n            pushDropPart.push(createMinimallyEncodedScriptChunk(field));\n        }\n        // Add Drop Opcodes\n        // We need to drop N keys, the number N itself, and M fields after verification succeeds.\n        // We also copied the signature itself so we need to drop that.\n        // Then we push a single true.\n        let itemsToDrop = fields.length + nPublicKeys + 2;\n        while (itemsToDrop > 1) {\n            pushDropPart.push({ op: OP.OP_2DROP });\n            itemsToDrop -= 2;\n        }\n        if (itemsToDrop === 1) {\n            pushDropPart.push({ op: OP.OP_DROP });\n        }\n        // Combine parts and return\n        return new LockingScript([\n            ...lockPart,\n            ...pushDropPart,\n            { op: OP.OP_TRUE }\n        ]);\n    }\n    /**\n       * Creates an unlocking script template for spending a MultiPushDrop output.\n       *\n       * @param {[SecurityLevel, string]} protocolID - The protocol ID used for key derivation.\n       * @param {string} keyID - The key ID used for key derivation.\n       * @param {WalletCounterparty} creator - The identity key of the person who made the locking script. Could come from one of the fields or be passed off chain.\n       * @param {'all' | 'none' | 'single'} [signOutputs='all'] - Specifies which transaction outputs to sign.\n       * @param {boolean} [anyoneCanPay=false] - Specifies if the SIGHASH_ANYONECANPAY flag should be used.\n       * @returns {ScriptTemplateUnlock} An object containing `sign` and `estimateLength` functions.\n       * @throws {Error} If we are not found in the list of keys, or if required signing info (sourceTXID, satoshis, lockingScript) is missing.\n       */\n    unlock(protocolID, keyID, creator, signOutputs = 'all', anyoneCanPay = false) {\n        return {\n            sign: async (tx, inputIndex) => {\n                // Prepare for signing\n                let signatureScope = TransactionSignature.SIGHASH_FORKID;\n                if (signOutputs === 'all')\n                    signatureScope |= TransactionSignature.SIGHASH_ALL;\n                else if (signOutputs === 'none')\n                    signatureScope |= TransactionSignature.SIGHASH_NONE;\n                else if (signOutputs === 'single')\n                    signatureScope |= TransactionSignature.SIGHASH_SINGLE;\n                if (anyoneCanPay)\n                    signatureScope |= TransactionSignature.SIGHASH_ANYONECANPAY;\n                const input = tx.inputs[inputIndex];\n                const currentSourceTXID = input.sourceTXID ?? input.sourceTransaction?.id('hex');\n                const currentSourceSatoshis = input.sourceTransaction?.outputs[input.sourceOutputIndex].satoshis;\n                const currentLockingScript = input.sourceTransaction?.outputs[input.sourceOutputIndex]?.lockingScript;\n                if (typeof currentSourceTXID !== 'string')\n                    throw new Error('Input sourceTXID or sourceTransaction required for signing.');\n                if (currentSourceSatoshis === undefined)\n                    throw new Error('Input sourceSatoshis or sourceTransaction required for signing.');\n                if (currentLockingScript == null)\n                    throw new Error('Input lockingScript or sourceTransaction required for signing.');\n                const otherInputs = tx.inputs.filter((_, index) => index !== inputIndex);\n                const decoded = MultiPushDrop.decode(currentLockingScript);\n                // Find the index of the unlocker's public key\n                let unlockerIndex = -1;\n                const { publicKey: unlockerPubKeyHex } = await this.wallet.getPublicKey({\n                    protocolID,\n                    keyID,\n                    counterparty: creator,\n                    forSelf: true\n                }, this.originator);\n                for (let i = 0; i < decoded.lockingPublicKeys.length; i++) {\n                    if (decoded.lockingPublicKeys[i] === unlockerPubKeyHex) {\n                        unlockerIndex = i;\n                        break;\n                    }\n                }\n                if (unlockerIndex === -1) {\n                    throw new Error(`Unlocker key derived for counterparty (creator) \"${creator}\" not found in the list of locking keys.`);\n                }\n                unlockerIndex = decoded.lockingPublicKeys.length - 1 - unlockerIndex;\n                // Calculate Preimage\n                const preimage = TransactionSignature.format({\n                    sourceTXID: currentSourceTXID,\n                    sourceOutputIndex: verifyTruthy(input.sourceOutputIndex),\n                    sourceSatoshis: currentSourceSatoshis,\n                    transactionVersion: tx.version,\n                    otherInputs,\n                    inputIndex,\n                    outputs: tx.outputs,\n                    inputSequence: input.sequence ?? 0xffffffff,\n                    subscript: currentLockingScript,\n                    lockTime: tx.lockTime,\n                    scope: signatureScope\n                });\n                // Create Signature\n                const preimageHash = Hash.hash256(preimage);\n                const { signature: bareSignature } = await this.wallet.createSignature({\n                    hashToDirectlySign: preimageHash,\n                    protocolID,\n                    keyID,\n                    counterparty: creator\n                }, this.originator);\n                const signature = Signature.fromDER([...bareSignature]);\n                const txSignature = new TransactionSignature(signature.r, signature.s, signatureScope);\n                const sigForScript = txSignature.toChecksigFormat();\n                // Create Unlocking Script Chunks: <Signature> <Index>\n                const unlockingChunks = [];\n                unlockingChunks.push({ op: sigForScript.length, data: sigForScript });\n                unlockingChunks.push(createMinimallyEncodedScriptChunk([unlockerIndex]));\n                return new UnlockingScript(unlockingChunks);\n            },\n            // Estimate length: Signature (~71-73 bytes) + Index push (1 byte for 0-15, potentially more)\n            estimateLength: async () => {\n                // A conservative estimate, usually 73 + 1 = 74\n                // Could potentially be larger if index > 15, but that's rare.\n                return 74;\n            }\n        };\n    }\n}\n//# sourceMappingURL=MultiPushDrop.js.map",
    "import { Script, Utils } from '@bsv/sdk';\nimport BitCom from '../bitcom/BitCom.js';\nimport B from '../bitcom/B.js';\nimport MAP from '../bitcom/MAP.js';\nimport AIP from '../bitcom/AIP.js';\n// Constants for BSocial protocol\nconst BSOCIAL_APP_NAME = 'bsocial';\n// Protocol addresses\nconst B_PROTOCOL_ADDRESS = '19HxigV4QyBv3tHpQVcUEQyq1pzZVdoAut';\nconst MAP_PROTOCOL_ADDRESS = '1PuQa7K62MiKCtssSLKy1kh56WWU7MtUR5';\nconst AIP_PROTOCOL_ADDRESS = '15PciHG22SNLQJXMoSUaWVi7WSqc7hCfva';\n// Action types\nexport var BSocialActionType;\n(function (BSocialActionType) {\n    BSocialActionType[\"POST\"] = \"post\";\n    BSocialActionType[\"LIKE\"] = \"like\";\n    BSocialActionType[\"UNLIKE\"] = \"unlike\";\n    BSocialActionType[\"FOLLOW\"] = \"follow\";\n    BSocialActionType[\"UNFOLLOW\"] = \"unfollow\";\n    BSocialActionType[\"MESSAGE\"] = \"message\";\n})(BSocialActionType || (BSocialActionType = {}));\n// Context types\nexport var BSocialContext;\n(function (BSocialContext) {\n    BSocialContext[\"TX\"] = \"tx\";\n    BSocialContext[\"CHANNEL\"] = \"channel\";\n    BSocialContext[\"BAP_ID\"] = \"bapID\";\n    BSocialContext[\"PROVIDER\"] = \"provider\";\n    BSocialContext[\"VIDEO_ID\"] = \"videoID\";\n    BSocialContext[\"GEOHASH\"] = \"geohash\";\n    BSocialContext[\"BTC_TX\"] = \"btcTx\";\n    BSocialContext[\"ETH_TX\"] = \"ethTx\";\n})(BSocialContext || (BSocialContext = {}));\n/**\n * BSocial class implementing ScriptTemplate.\n *\n * This class provides methods to create BSocial protocol transactions for social media\n * actions like posts, likes, follows, etc. following BitcoinSchema.org standards.\n */\nexport default class BSocial {\n    action;\n    content;\n    tags;\n    identityKey;\n    constructor(action, content, tags, identityKey) {\n        this.action = action;\n        this.content = content;\n        this.tags = tags;\n        this.identityKey = identityKey;\n    }\n    /**\n     * Creates a BSocial locking script for various social actions\n     *\n     * @returns A locking script for the BSocial action\n     */\n    async lock() {\n        const protocols = [];\n        // Add B protocol for content (if present and not empty)\n        if (this.content !== undefined && this.content !== null) {\n            const bScript = B.text(this.content);\n            // Extract only the protocol data (skip OP_RETURN and address)\n            const bDataChunks = bScript.chunks.slice(2); // Skip OP_RETURN and address\n            const bDataScript = new Script(bDataChunks);\n            protocols.push({\n                protocol: B_PROTOCOL_ADDRESS,\n                script: bDataScript.toBinary(),\n                pos: protocols.length\n            });\n        }\n        // Add MAP protocol for action metadata\n        const mapData = {\n            app: BSOCIAL_APP_NAME,\n            type: this.action.type\n        };\n        if (this.action.context) {\n            mapData.context = this.action.context;\n        }\n        if (this.action.contextValue != null && this.action.contextValue !== '') {\n            mapData.contextValue = this.action.contextValue;\n        }\n        if (this.action.subcontext) {\n            mapData.subcontext = this.action.subcontext;\n        }\n        if (this.action.subcontextValue != null && this.action.subcontextValue !== '') {\n            mapData.subcontextValue = this.action.subcontextValue;\n        }\n        // Add specific action data\n        if (this.action.type === BSocialActionType.LIKE && 'txid' in this.action) {\n            mapData.tx = this.action.txid;\n        }\n        if (this.action.type === BSocialActionType.FOLLOW && 'bapId' in this.action) {\n            mapData.bapId = this.action.bapId;\n        }\n        // Add tags if present\n        if ((this.tags != null) && this.tags.length > 0) {\n            this.tags.forEach((tag, index) => {\n                mapData[`tag${index}`] = tag;\n            });\n        }\n        const mapScript = MAP.set(mapData);\n        // Extract only the protocol data (skip OP_RETURN and address)\n        const mapDataChunks = mapScript.chunks.slice(2); // Skip OP_RETURN and address\n        const mapDataScript = new Script(mapDataChunks);\n        protocols.push({\n            protocol: MAP_PROTOCOL_ADDRESS,\n            script: mapDataScript.toBinary(),\n            pos: protocols.length\n        });\n        // Add AIP protocol for signature (if identity key provided)\n        if (this.identityKey != null) {\n            // Create data to sign (all protocol data)\n            const signatureData = [];\n            for (const proto of protocols) {\n                signatureData.push(...Utils.toArray(proto.protocol, 'utf8'));\n                signatureData.push(...proto.script);\n                signatureData.push(0x7c); // '|' separator\n            }\n            const aipData = await AIP.sign(signatureData, this.identityKey);\n            const aipScript = aipData.lock();\n            // Extract only the AIP data from the script (skip OP_RETURN and protocol address)\n            const aipChunks = aipScript.chunks.slice(2); // Skip OP_RETURN and AIP protocol address\n            const aipDataScript = new Script(aipChunks);\n            protocols.push({\n                protocol: AIP_PROTOCOL_ADDRESS,\n                script: aipDataScript.toBinary(),\n                pos: protocols.length\n            });\n        }\n        // Create BitCom transaction\n        const bitcom = new BitCom(protocols);\n        return bitcom.lock();\n    }\n    /**\n     * Unlock method is not available for BSocial scripts, throws exception.\n     */\n    unlock() {\n        throw new Error('Unlock is not supported for BSocial scripts');\n    }\n    /**\n     * Creates a post transaction\n     *\n     * @param post The post data\n     * @param tags Optional tags for the post\n     * @param identityKey Optional private key for AIP signature\n     * @returns A locking script for the post\n     */\n    static async createPost(post, tags, identityKey) {\n        const bsocial = new BSocial(post, post.content, tags, identityKey);\n        return await bsocial.lock();\n    }\n    /**\n     * Creates a like transaction\n     *\n     * @param like The like data\n     * @param identityKey Optional private key for AIP signature\n     * @returns A locking script for the like\n     */\n    static async createLike(like, identityKey) {\n        const bsocial = new BSocial(like, undefined, undefined, identityKey);\n        return await bsocial.lock();\n    }\n    /**\n     * Creates a follow transaction\n     *\n     * @param follow The follow data\n     * @param identityKey Optional private key for AIP signature\n     * @returns A locking script for the follow\n     */\n    static async createFollow(follow, identityKey) {\n        const bsocial = new BSocial(follow, undefined, undefined, identityKey);\n        return await bsocial.lock();\n    }\n    /**\n     * Decodes a BSocial transaction script\n     *\n     * @param script The script to decode\n     * @returns Decoded BSocial data\n     */\n    static decode(script) {\n        try {\n            // First decode the BitCom structure\n            const bitcom = BitCom.decode(script);\n            if (bitcom == null) {\n                return null;\n            }\n            let content;\n            let action;\n            let tags = [];\n            const attachments = [];\n            let aip;\n            // Process each protocol in the BitCom transaction\n            for (const protocol of bitcom.protocols) {\n                if (protocol.protocol === B_PROTOCOL_ADDRESS) {\n                    // Parse B protocol data directly: DATA MEDIA_TYPE ENCODING [FILENAME]\n                    const bScript = Script.fromBinary(protocol.script);\n                    const chunks = bScript.chunks;\n                    if (chunks.length >= 3) { // Need at least DATA, MEDIA_TYPE, ENCODING\n                        const dataChunk = chunks[0];\n                        const mediaTypeChunk = chunks[1];\n                        const encodingChunk = chunks[2];\n                        if ((dataChunk.data != null) && (mediaTypeChunk.data != null) && (encodingChunk.data != null)) {\n                            const mediaType = Utils.toUTF8(mediaTypeChunk.data);\n                            const encoding = Utils.toUTF8(encodingChunk.data);\n                            if (mediaType === 'text/plain' && encoding === 'utf-8') {\n                                content = Utils.toUTF8(dataChunk.data);\n                            }\n                            else {\n                                attachments.push({\n                                    type: mediaType,\n                                    content: dataChunk.data,\n                                    size: dataChunk.data.length,\n                                    encoding\n                                });\n                            }\n                        }\n                    }\n                }\n                else if (protocol.protocol === MAP_PROTOCOL_ADDRESS) {\n                    // Parse MAP protocol data directly: COMMAND key1 value1 key2 value2...\n                    const mapScript = Script.fromBinary(protocol.script);\n                    const chunks = mapScript.chunks;\n                    if (chunks.length >= 1) {\n                        // Read COMMAND (first chunk)\n                        const cmdChunk = chunks[0];\n                        if (cmdChunk.data != null) {\n                            const cmd = Utils.toUTF8(cmdChunk.data);\n                            // Handle SET command - read key-value pairs\n                            if (cmd === 'SET') {\n                                const mapData = {};\n                                for (let i = 1; i < chunks.length; i += 2) {\n                                    // Read key\n                                    const keyChunk = chunks[i];\n                                    if (keyChunk?.data == null)\n                                        break;\n                                    // Read value (next chunk)\n                                    const valueChunk = chunks[i + 1];\n                                    if (valueChunk?.data == null)\n                                        break;\n                                    const key = Utils.toUTF8(keyChunk.data);\n                                    const value = Utils.toUTF8(valueChunk.data);\n                                    mapData[key] = value;\n                                }\n                                const app = mapData.app;\n                                if (app === BSOCIAL_APP_NAME) {\n                                    const type = mapData.type;\n                                    const context = mapData.context;\n                                    const contextValue = mapData.contextValue;\n                                    const subcontext = mapData.subcontext;\n                                    const subcontextValue = mapData.subcontextValue;\n                                    action = {\n                                        app: BSOCIAL_APP_NAME,\n                                        type,\n                                        context,\n                                        contextValue,\n                                        subcontext,\n                                        subcontextValue\n                                    };\n                                    // Extract specific action data\n                                    if (type === BSocialActionType.LIKE) {\n                                        const txid = mapData.tx;\n                                        if (txid != null && txid !== '') {\n                                            action.txid = txid;\n                                        }\n                                    }\n                                    else if (type === BSocialActionType.FOLLOW) {\n                                        const bapId = mapData.bapId;\n                                        if (bapId != null && bapId !== '') {\n                                            action.bapId = bapId;\n                                        }\n                                    }\n                                    // Extract tags\n                                    const tagEntries = Object.entries(mapData).filter(([key]) => key.startsWith('tag'));\n                                    tags = tagEntries.map(([key, value]) => [key, value]);\n                                }\n                            }\n                        }\n                    }\n                }\n                else if (protocol.protocol === AIP_PROTOCOL_ADDRESS) {\n                    // Extract AIP signature data - create BitCom structure for AIP.decode\n                    const aipBitCom = {\n                        protocols: [protocol],\n                        scriptPrefix: []\n                    };\n                    const aipDecoded = AIP.decode(aipBitCom);\n                    if (aipDecoded != null && aipDecoded.length > 0) {\n                        aip = aipDecoded[0].data;\n                    }\n                }\n            }\n            // Must have action to be valid BSocial transaction\n            if (action == null) {\n                return null;\n            }\n            return {\n                action,\n                content,\n                attachments,\n                tags,\n                aip\n            };\n        }\n        catch (error) {\n            return null;\n        }\n    }\n    /**\n     * Signs data with AIP protocol\n     *\n     * @param privateKey The private key to sign with\n     * @param message The message to sign\n     * @returns Base64 encoded signature\n     */\n    static async signAIP(privateKey, message) {\n        const messageData = Utils.toArray(message, 'utf8');\n        const aipData = await AIP.sign(messageData, privateKey);\n        return Utils.toBase64(aipData.data.signature);\n    }\n    /**\n     * Creates a reply transaction\n     *\n     * @param reply The reply data\n     * @param replyTxId The transaction ID being replied to\n     * @param tags Optional tags for the reply\n     * @param identityKey Optional private key for AIP signature\n     * @returns A locking script for the reply\n     */\n    static async createReply(reply, replyTxId, tags, identityKey) {\n        const replyAction = {\n            ...reply,\n            context: BSocialContext.TX,\n            contextValue: replyTxId\n        };\n        const bsocial = new BSocial(replyAction, reply.content, tags, identityKey);\n        return await bsocial.lock();\n    }\n    /**\n     * Creates a message transaction\n     *\n     * @param message The message data\n     * @param identityKey Optional private key for AIP signature\n     * @returns A locking script for the message\n     */\n    static async createMessage(message, identityKey) {\n        const bsocial = new BSocial(message, message.content, undefined, identityKey);\n        return await bsocial.lock();\n    }\n}\n//# sourceMappingURL=BSocial.js.map",
    "import { Script, LockingScript, OP, Utils } from '@bsv/sdk';\n/**\n * BitCom template for handling multi-protocol Bitcoin transactions\n *\n * BitCom allows multiple protocols to be embedded in a single transaction output\n * using the pipe ('|') delimiter to separate different protocol sections.\n *\n * This implementation mirrors the Go template structure and behavior.\n */\nexport default class BitCom {\n    protocols;\n    scriptPrefix;\n    constructor(protocols = [], scriptPrefix = []) {\n        this.protocols = protocols;\n        this.scriptPrefix = scriptPrefix;\n    }\n    /**\n     * Decodes a script to extract BitCom protocol data\n     *\n     * Mirrors the Go implementation's decode algorithm exactly.\n     *\n     * @param script - The script to decode\n     * @returns BitComDecoded - The decoded BitCom structure, or null if no OP_RETURN found\n     */\n    static decode(script) {\n        // Handle null script safely - return empty structure like Go\n        if (script == null) {\n            return {\n                protocols: [],\n                scriptPrefix: []\n            };\n        }\n        let scriptBytes;\n        if (script instanceof LockingScript) {\n            scriptBytes = script.toBinary();\n        }\n        else {\n            scriptBytes = script.toBinary();\n        }\n        const pos = this.findReturn(scriptBytes, 0);\n        if (pos === -1) {\n            return null;\n        }\n        // Get prefix if present (matches Go: prefix = (*scr)[:pos])\n        let prefix = [];\n        if (pos > 0) {\n            prefix = scriptBytes.slice(0, pos);\n        }\n        const bitcom = {\n            scriptPrefix: prefix,\n            protocols: []\n        };\n        // Start after OP_RETURN (matches Go: pos++)\n        const currentPos = pos + 1;\n        // Parse protocols using SDK's built-in parsing (no custom readOp functions)\n        const remainingScript = Script.fromBinary(scriptBytes.slice(currentPos));\n        const chunks = remainingScript.chunks;\n        let chunkIndex = 0;\n        let currentProtocolPos = currentPos;\n        while (chunkIndex < chunks.length) {\n            const protocol = {\n                protocol: '',\n                script: [],\n                pos: currentProtocolPos\n            };\n            // Read protocol identifier from current chunk\n            const protocolChunk = chunks[chunkIndex];\n            if (protocolChunk.data == null) {\n                break;\n            }\n            protocol.protocol = Utils.toUTF8(protocolChunk.data);\n            chunkIndex++;\n            // Collect script chunks until we find a pipe delimiter or reach end\n            const protocolChunks = [];\n            while (chunkIndex < chunks.length) {\n                const chunk = chunks[chunkIndex];\n                // Check if this chunk is a pipe delimiter\n                if (chunk.data != null && chunk.data.length === 1 && chunk.data[0] === 0x7c) {\n                    // Found pipe delimiter - end current protocol\n                    chunkIndex++; // Skip the pipe\n                    break;\n                }\n                // Add chunk to current protocol (preserve chunk structure)\n                protocolChunks.push(chunk);\n                chunkIndex++;\n            }\n            // Convert chunks back to binary for protocol.script\n            const protocolScript = new Script(protocolChunks);\n            protocol.script = protocolScript.toBinary();\n            bitcom.protocols.push(protocol);\n            // Update position for next protocol\n            currentProtocolPos += protocolChunk.op + 1 + protocol.script.length + (chunkIndex < chunks.length ? 2 : 0); // +2 for pipe delimiter\n        }\n        return bitcom;\n    }\n    /**\n     * Creates a locking script from the BitCom structure\n     *\n     * Mirrors the Go Lock() method exactly.\n     *\n     * @returns LockingScript - The BitCom locking script\n     */\n    lock() {\n        const script = new Script();\n        // Add prefix if present (matches Go: s := script.NewFromBytes(b.ScriptPrefix))\n        if (this.scriptPrefix.length > 0) {\n            script.writeBin(this.scriptPrefix);\n        }\n        if (this.protocols.length > 0) {\n            // Add OP_RETURN (matches Go: _ = s.AppendOpcodes(script.OpRETURN))\n            script.writeOpCode(OP.OP_RETURN);\n            for (let i = 0; i < this.protocols.length; i++) {\n                const protocol = this.protocols[i];\n                // Add protocol identifier as push data (matches Go: _ = s.AppendPushData([]byte(p.Protocol)))\n                const protocolBytes = Utils.toArray(protocol.protocol, 'utf8');\n                script.writeBin(protocolBytes);\n                // Add protocol script data directly (matches Go: s = script.NewFromBytes(append(*s, p.Script...)))\n                if (protocol.script.length > 0) {\n                    // Parse the protocol script to get its chunks and append them\n                    const protocolScript = Script.fromBinary(protocol.script);\n                    for (const chunk of protocolScript.chunks) {\n                        if (chunk.data != null) {\n                            script.writeBin(chunk.data);\n                        }\n                        else {\n                            script.writeOpCode(chunk.op);\n                        }\n                    }\n                }\n                // Add pipe delimiter if not the last protocol (matches Go: _ = s.AppendPushData([]byte(\"|\")))\n                if (i < this.protocols.length - 1) {\n                    const pipeBytes = Utils.toArray('|', 'utf8');\n                    script.writeBin(pipeBytes);\n                }\n            }\n        }\n        return new LockingScript(script.chunks);\n    }\n    /**\n     * Finds the position of OP_RETURN in the script\n     *\n     * Mirrors the Go findReturn function exactly.\n     *\n     * @param scriptBytes - The script bytes to search\n     * @param from - Starting position\n     * @returns number - Position of OP_RETURN, or -1 if not found\n     */\n    static findReturn(scriptBytes, from) {\n        for (let i = from; i < scriptBytes.length; i++) {\n            if (scriptBytes[i] === OP.OP_RETURN) {\n                return i;\n            }\n        }\n        return -1;\n    }\n    /**\n     * Finds the position of pipe delimiter in the script\n     *\n     * Mirrors the Go findPipe function exactly.\n     *\n     * @param scriptBytes - The script bytes to search\n     * @param from - Starting position\n     * @returns number - Position of pipe delimiter, or -1 if not found\n     */\n    // Custom readOp methods removed - using SDK's built-in parsing instead\n    /**\n     * Converts various input types to a Script object\n     *\n     * Mirrors the Go ToScript function exactly.\n     *\n     * @param data - The data to convert (Script, LockingScript, or byte array)\n     * @returns Script - The converted script, or null if conversion fails\n     */\n    static toScript(data) {\n        if (data instanceof Script) {\n            return data;\n        }\n        if (data instanceof LockingScript) {\n            return new Script(data.chunks);\n        }\n        if (Array.isArray(data)) {\n            if (data.length === 0) {\n                return new Script();\n            }\n            return Script.fromBinary(data);\n        }\n        return null;\n    }\n}\n//# sourceMappingURL=BitCom.js.map",
    "import { Script, Utils } from '@bsv/sdk';\nimport BitCom from './BitCom.js';\n/**\n * B Protocol Prefix - the BitCom protocol address for B\n */\nexport const B_PREFIX = '19HxigV4QyBv3tHpQVcUEQyq1pzZVdoAut';\n/**\n * Media types for B protocol\n */\nexport var MediaType;\n(function (MediaType) {\n    MediaType[\"TextPlain\"] = \"text/plain\";\n    MediaType[\"TextMarkdown\"] = \"text/markdown\";\n    MediaType[\"TextHTML\"] = \"text/html\";\n    MediaType[\"ImagePNG\"] = \"image/png\";\n    MediaType[\"ImageJPEG\"] = \"image/jpeg\";\n    MediaType[\"ApplicationJSON\"] = \"application/json\";\n    MediaType[\"ApplicationPDF\"] = \"application/pdf\";\n})(MediaType || (MediaType = {}));\n/**\n * Encoding types for B protocol\n */\nexport var Encoding;\n(function (Encoding) {\n    Encoding[\"UTF8\"] = \"utf-8\";\n    Encoding[\"Binary\"] = \"binary\";\n    Encoding[\"Base64\"] = \"base64\";\n    Encoding[\"Hex\"] = \"hex\";\n})(Encoding || (Encoding = {}));\n/**\n * B (Binary) Protocol Template\n *\n * The B protocol is used for storing arbitrary binary data on the blockchain.\n * It follows the format: PREFIX DATA MEDIA_TYPE ENCODING [FILENAME]\n * where FILENAME is optional.\n */\n// eslint-disable-next-line @typescript-eslint/no-extraneous-class\nexport default class B {\n    /**\n     * Creates a B protocol locking script\n     *\n     * @param data - The binary data to store\n     * @param mediaType - The MIME type of the data\n     * @param encoding - The encoding format\n     * @param filename - Optional filename\n     * @returns LockingScript - The B protocol locking script\n     */\n    static lock(data, mediaType = MediaType.TextPlain, encoding = Encoding.UTF8, filename) {\n        // Convert data to number array\n        let dataBytes;\n        if (typeof data === 'string') {\n            if (encoding === Encoding.Hex) {\n                dataBytes = Utils.toArray(data, 'hex');\n            }\n            else if (encoding === Encoding.Base64) {\n                dataBytes = Utils.toArray(data, 'base64');\n            }\n            else {\n                dataBytes = Utils.toArray(data, 'utf8');\n            }\n        }\n        else if (data instanceof Uint8Array) {\n            dataBytes = Array.from(data);\n        }\n        else {\n            dataBytes = data;\n        }\n        const protocols = [{\n                protocol: B_PREFIX,\n                script: [],\n                pos: 0\n            }];\n        // Build the B protocol script: DATA MEDIA_TYPE ENCODING [FILENAME]\n        // ✅ CORRECT - Use SDK's built-in writeBin method\n        const script = new Script();\n        // Add DATA as push data\n        script.writeBin(dataBytes);\n        // Add MEDIA_TYPE as push data\n        script.writeBin(Utils.toArray(mediaType));\n        // Add ENCODING as push data\n        script.writeBin(Utils.toArray(encoding));\n        // Add optional FILENAME as push data\n        if (filename != null && filename !== '') {\n            script.writeBin(Utils.toArray(filename));\n        }\n        protocols[0].script = script.toBinary();\n        // Create BitCom structure and return locking script\n        const bitcom = new BitCom(protocols);\n        return bitcom.lock();\n    }\n    /**\n     * Decodes B protocol data from script\n     *\n     * @param script - The script containing B protocol data\n     * @returns BData - The decoded B protocol data, or null if invalid\n     */\n    static decode(script) {\n        let scriptToProcess = null;\n        if (Array.isArray(script)) {\n            scriptToProcess = Script.fromBinary(script);\n        }\n        else {\n            scriptToProcess = BitCom.toScript(script);\n        }\n        if (scriptToProcess == null) {\n            return null;\n        }\n        // First decode as BitCom to find B protocol\n        const bitcomData = BitCom.decode(scriptToProcess);\n        if (bitcomData == null) {\n            return null;\n        }\n        // Find B protocol in the protocols\n        const bProtocol = bitcomData.protocols.find((p) => p.protocol === B_PREFIX);\n        if (bProtocol == null) {\n            return null;\n        }\n        // Parse the B protocol script: DATA MEDIA_TYPE ENCODING [FILENAME]\n        // ✅ CORRECT - Use SDK native parsing\n        const parsedScript = Script.fromBinary(bProtocol.script);\n        const chunks = parsedScript.chunks;\n        if (chunks.length < 3) { // Need at least DATA, MEDIA_TYPE, ENCODING\n            return null;\n        }\n        // Access parsed chunks directly\n        const dataChunk = chunks[0];\n        if (dataChunk.data == null) {\n            return null;\n        }\n        const data = dataChunk.data;\n        // Return null for empty data as expected by tests\n        if (data.length === 0)\n            return null;\n        // Read MEDIA_TYPE (second chunk)\n        const mediaTypeChunk = chunks[1];\n        if (mediaTypeChunk.data == null) {\n            return null;\n        }\n        const mediaType = Utils.toUTF8(mediaTypeChunk.data);\n        // Read ENCODING (third chunk)\n        const encodingChunk = chunks[2];\n        if (encodingChunk.data == null) {\n            return null;\n        }\n        const encoding = Utils.toUTF8(encodingChunk.data);\n        // Try to read optional FILENAME (fourth chunk)\n        let filename;\n        if (chunks.length >= 4) {\n            const filenameChunk = chunks[3];\n            if (filenameChunk.data != null) {\n                filename = Utils.toUTF8(filenameChunk.data);\n            }\n        }\n        return {\n            data,\n            mediaType,\n            encoding,\n            filename\n        };\n    }\n    /**\n     * Helper method to create text content\n     *\n     * @param text - The text content\n     * @param mediaType - Optional media type (defaults to text/plain)\n     * @param filename - Optional filename\n     * @returns LockingScript - The B protocol locking script\n     */\n    static text(text, mediaType = MediaType.TextPlain, filename) {\n        return this.lock(text, mediaType, Encoding.UTF8, filename);\n    }\n    /**\n     * Helper method to create binary content\n     *\n     * @param data - The binary data\n     * @param mediaType - The media type\n     * @param filename - Optional filename\n     * @returns LockingScript - The B protocol locking script\n     */\n    static binary(data, mediaType, filename) {\n        return this.lock(data, mediaType, Encoding.Binary, filename);\n    }\n    /**\n     * Helper method to create base64 encoded content\n     *\n     * @param base64Data - The base64 encoded data\n     * @param mediaType - The media type\n     * @param filename - Optional filename\n     * @returns LockingScript - The B protocol locking script\n     */\n    static base64(base64Data, mediaType, filename) {\n        return this.lock(base64Data, mediaType, Encoding.Base64, filename);\n    }\n    /**\n     * Helper method to create hex encoded content\n     *\n     * @param hexData - The hex encoded data\n     * @param mediaType - The media type\n     * @param filename - Optional filename\n     * @returns LockingScript - The B protocol locking script\n     */\n    static hex(hexData, mediaType, filename) {\n        return this.lock(hexData, mediaType, Encoding.Hex, filename);\n    }\n}\n//# sourceMappingURL=B.js.map",
    "import { Script, Utils } from '@bsv/sdk';\nimport BitCom from './BitCom.js';\n/**\n * MAP Protocol Prefix - the BitCom protocol address for MAP\n */\nexport const MAP_PREFIX = '1PuQa7K62MiKCtssSLKy1kh56WWU7MtUR5';\n/**\n * MAP protocol commands\n */\nexport var MAPCommand;\n(function (MAPCommand) {\n    MAPCommand[\"SET\"] = \"SET\";\n    MAPCommand[\"DEL\"] = \"DEL\";\n    MAPCommand[\"ADD\"] = \"ADD\";\n    MAPCommand[\"SELECT\"] = \"SELECT\";\n})(MAPCommand || (MAPCommand = {}));\n/**\n * MAP (Metadata and Payload) Protocol Template\n *\n * The MAP protocol provides a way to store key-value metadata on the blockchain.\n * It supports different commands for setting, deleting, adding, and selecting data.\n */\n// eslint-disable-next-line @typescript-eslint/no-extraneous-class\nexport default class MAP {\n    /**\n     * Creates a MAP protocol locking script with SET command\n     *\n     * @param data - Key-value pairs to set\n     * @returns LockingScript - The MAP protocol locking script\n     */\n    static set(data) {\n        return this.lock(MAPCommand.SET, data);\n    }\n    /**\n     * Creates a MAP protocol locking script with ADD command\n     *\n     * @param key - The key to add values to\n     * @param values - Array of values to add\n     * @returns LockingScript - The MAP protocol locking script\n     */\n    static add(key, values) {\n        const data = {};\n        data[key] = values.join(' '); // Join values with space\n        return this.lock(MAPCommand.ADD, data);\n    }\n    /**\n     * Creates a MAP protocol locking script with DEL command\n     *\n     * @param keys - Array of keys to delete\n     * @returns LockingScript - The MAP protocol locking script\n     */\n    static del(keys) {\n        const data = {};\n        keys.forEach(key => {\n            data[key] = '';\n        });\n        return this.lock(MAPCommand.DEL, data);\n    }\n    /**\n     * Creates a MAP protocol locking script\n     *\n     * @param command - The MAP command\n     * @param data - The key-value data\n     * @returns LockingScript - The MAP protocol locking script\n     */\n    static lock(command, data) {\n        const protocols = [{\n                protocol: MAP_PREFIX,\n                script: [],\n                pos: 0\n            }];\n        // Build the MAP protocol script: CMD KEY1 VALUE1 KEY2 VALUE2 ...\n        const script = new Script();\n        // Add COMMAND\n        script.writeBin(Utils.toArray(command.toString()));\n        // Add key-value pairs\n        for (const [key, value] of Object.entries(data)) {\n            // Add KEY\n            script.writeBin(Utils.toArray(this.cleanString(key)));\n            // Add VALUE\n            script.writeBin(Utils.toArray(this.cleanString(value)));\n        }\n        protocols[0].script = script.toBinary();\n        // Create BitCom structure and return locking script\n        const bitcom = new BitCom(protocols);\n        return bitcom.lock();\n    }\n    /**\n     * Decodes MAP protocol data from script\n     *\n     * @param script - The script containing MAP protocol data\n     * @returns MAPData - The decoded MAP protocol data, or null if invalid\n     */\n    static decode(script) {\n        let scriptToProcess = null;\n        if (Array.isArray(script)) {\n            scriptToProcess = Script.fromBinary(script);\n        }\n        else {\n            scriptToProcess = BitCom.toScript(script);\n        }\n        if (scriptToProcess == null) {\n            return null;\n        }\n        // First decode as BitCom to find MAP protocol\n        const bitcomData = BitCom.decode(scriptToProcess);\n        if (bitcomData == null) {\n            return null;\n        }\n        // Find MAP protocol in the protocols\n        const mapProtocol = bitcomData.protocols.find((p) => p.protocol === MAP_PREFIX);\n        if (mapProtocol == null) {\n            return null;\n        }\n        // Parse the MAP protocol script using SDK native parsing\n        const parsedScript = Script.fromBinary(mapProtocol.script);\n        const chunks = parsedScript.chunks;\n        if (chunks.length < 1) { // At least command\n            return null;\n        }\n        // Read COMMAND (first chunk)\n        const cmdChunk = chunks[0];\n        if (cmdChunk.data == null) {\n            return null;\n        }\n        const cmd = Utils.toUTF8(cmdChunk.data);\n        const mapData = {\n            cmd,\n            data: {}\n        };\n        // Handle SET command - read key-value pairs\n        if (cmd === MAPCommand.SET) {\n            for (let i = 1; i < chunks.length; i += 2) {\n                // Read key\n                const keyChunk = chunks[i];\n                if (keyChunk?.data == null)\n                    break;\n                // Read value (next chunk)\n                const valueChunk = chunks[i + 1];\n                if (valueChunk?.data == null)\n                    break;\n                const key = this.cleanString(Utils.toUTF8(keyChunk.data));\n                const value = this.cleanString(Utils.toUTF8(valueChunk.data));\n                mapData.data[key] = value;\n            }\n        }\n        else if (cmd === MAPCommand.ADD) {\n            // For ADD command, read key and then all remaining values\n            if (chunks.length >= 2) {\n                const keyChunk = chunks[1];\n                if (keyChunk?.data != null) {\n                    const key = this.cleanString(Utils.toUTF8(keyChunk.data));\n                    const values = [];\n                    for (let i = 2; i < chunks.length; i++) {\n                        const valueChunk = chunks[i];\n                        if (valueChunk?.data != null) {\n                            values.push(this.cleanString(Utils.toUTF8(valueChunk.data)));\n                        }\n                    }\n                    mapData.data[key] = values.join(' ');\n                    mapData.adds = values;\n                }\n            }\n        }\n        else if (cmd === MAPCommand.DEL) {\n            // For DEL command, read all keys to delete\n            for (let i = 1; i < chunks.length; i++) {\n                const keyChunk = chunks[i];\n                if (keyChunk?.data != null) {\n                    const key = this.cleanString(Utils.toUTF8(keyChunk.data));\n                    mapData.data[key] = '';\n                }\n            }\n        }\n        return mapData;\n    }\n    /**\n     * Cleans a string by replacing null bytes with spaces and handling escape sequences\n     *\n     * @param str - The string to clean\n     * @returns string - The cleaned string\n     */\n    static cleanString(str) {\n        return str\n            .replace(/\\0/g, ' ') // Replace null bytes with spaces\n            .replace(/\\\\u0000/g, ' '); // Replace escaped null bytes with spaces\n    }\n    /**\n     * Helper method to create a simple key-value MAP\n     *\n     * @param key - The key\n     * @param value - The value\n     * @returns LockingScript - The MAP protocol locking script\n     */\n    static keyValue(key, value) {\n        return this.set({ [key]: value });\n    }\n    /**\n     * Helper method to create an app identification MAP\n     *\n     * @param appName - The application name\n     * @param type - The action/content type\n     * @param additionalData - Optional additional key-value pairs\n     * @returns LockingScript - The MAP protocol locking script\n     */\n    static app(appName, type, additionalData = {}) {\n        const data = {\n            app: appName,\n            type,\n            ...additionalData\n        };\n        return this.set(data);\n    }\n}\n//# sourceMappingURL=MAP.js.map",
    "import { Utils, Script, OP, BigNumber, BSM, Signature } from '@bsv/sdk';\nimport BitCom from './BitCom.js';\n/**\n * AIP (Author Identity Protocol) prefix for BitCom transactions\n */\nexport const AIP_PREFIX = '15PciHG22SNLQJXMoSUaWVi7WSqc7hCfva';\n/**\n * AIP (Author Identity Protocol) implementation\n *\n * AIP enables cryptographic signing of blockchain content with Bitcoin addresses,\n * providing verifiable authorship and identity verification within BitCom transactions.\n */\nexport default class AIP {\n    data;\n    constructor(data) {\n        this.data = data;\n    }\n    /**\n     * Extract AIP signatures from BitCom transaction\n     *\n     * @param bitcom - Decoded BitCom transaction\n     * @returns Array of AIP signatures found in transaction\n     */\n    static decode(bitcom) {\n        const aips = [];\n        // Safety check for nil\n        if (bitcom?.protocols?.length === 0) {\n            return aips;\n        }\n        for (let protoIdx = 0; protoIdx < bitcom.protocols.length; protoIdx++) {\n            const protocol = bitcom.protocols[protoIdx];\n            if (protocol.protocol === AIP_PREFIX) {\n                try {\n                    const script = Script.fromBinary(protocol.script);\n                    const chunks = script.chunks;\n                    // Need at least algorithm, address, and signature\n                    if (chunks?.length < 3) {\n                        continue;\n                    }\n                    const aip = new AIP({\n                        bitcomIndex: protoIdx,\n                        algorithm: Utils.toUTF8(chunks[0].data ?? []),\n                        address: Utils.toUTF8(chunks[1].data ?? []),\n                        signature: Array.from(chunks[2].data ?? []),\n                        fieldIndexes: undefined,\n                        valid: undefined\n                    });\n                    // Read optional field indexes (remaining chunks)\n                    const fieldIndexes = [];\n                    for (let i = 3; i < chunks.length; i++) {\n                        const indexStr = Utils.toUTF8(chunks[i].data ?? []);\n                        const index = parseInt(indexStr, 10);\n                        if (Number.isInteger(index) && !isNaN(index)) {\n                            fieldIndexes.push(index);\n                        }\n                        // Continue parsing even if we encounter invalid field indexes\n                    }\n                    if (fieldIndexes.length > 0) {\n                        aip.data.fieldIndexes = fieldIndexes;\n                    }\n                    // Validate signature against protocols that came before this AIP\n                    this.validateAIP(aip, bitcom.protocols.slice(0, protoIdx));\n                    aips.push(aip);\n                }\n                catch (error) {\n                    // Skip invalid AIP protocols\n                    continue;\n                }\n            }\n        }\n        return aips;\n    }\n    /**\n     * Create AIP signature for data\n     *\n     * @param data - Data to sign as number array\n     * @param privateKey - Private key for signing\n     * @param options - Additional signing options\n     * @returns AIP signature object\n     */\n    static async sign(data, privateKey, options = {}) {\n        const algorithm = options.algorithm ?? 'BITCOIN_ECDSA';\n        const address = privateKey.toAddress().toString();\n        // Use BSM signing following the pattern from BAP library\n        const dummySig = BSM.sign(data, privateKey, 'raw');\n        const messageHash = BSM.magicHash(data);\n        const recoveryFactor = dummySig.CalculateRecoveryFactor(privateKey.toPublicKey(), new BigNumber(messageHash));\n        // Create compact signature with recovery factor\n        const compactSig = BSM.sign(data, privateKey, 'raw').toCompact(recoveryFactor, true, 'base64');\n        // Convert to number array\n        const signatureArray = Array.from(Utils.toArray(compactSig, 'base64'));\n        return new AIP({\n            algorithm,\n            address,\n            signature: signatureArray,\n            fieldIndexes: options.fieldIndexes,\n            valid: true\n        });\n    }\n    /**\n     * Verify AIP signature\n     *\n     * @returns True if signature is valid\n     */\n    verify() {\n        return this.data.valid === true;\n    }\n    /**\n     * Generate locking script for AIP within BitCom\n     *\n     * @returns Locking script\n     */\n    lock() {\n        const script = new Script();\n        // Add algorithm\n        script.writeBin(Utils.toArray(this.data.algorithm, 'utf8'));\n        // Add address\n        script.writeBin(Utils.toArray(this.data.address, 'utf8'));\n        // Add signature\n        script.writeBin(this.data.signature);\n        // Add field indexes if present\n        if ((this.data.fieldIndexes != null) && this.data.fieldIndexes.length > 0) {\n            for (const index of this.data.fieldIndexes) {\n                script.writeBin(Utils.toArray(index.toString(), 'utf8'));\n            }\n        }\n        // Create BitCom protocol\n        const protocols = [{\n                protocol: AIP_PREFIX,\n                script: script.toBinary(),\n                pos: 0\n            }];\n        const bitcom = new BitCom(protocols);\n        return bitcom.lock();\n    }\n    /**\n     * Unlock method is not available for AIP scripts\n     *\n     * @throws Error - AIP signatures cannot be unlocked\n     */\n    unlock() {\n        throw new Error('AIP signatures cannot be unlocked');\n    }\n    /**\n     * Validate AIP signature against protocol data\n     *\n     * @param aip - AIP to validate\n     * @param protocols - Protocols that came before this AIP\n     */\n    static validateAIP(aip, protocols) {\n        try {\n            // Reconstruct signed data exactly as Go implementation\n            const data = [];\n            let fieldIndex = 0;\n            // Add OP_RETURN\n            data.push(OP.OP_RETURN);\n            // Process each protocol\n            for (const protocol of protocols) {\n                // Add protocol prefix\n                data.push(...Utils.toArray(protocol.protocol, 'utf8'));\n                // Parse protocol script\n                const script = Script.fromBinary(protocol.script);\n                const chunks = script.chunks;\n                // Process script chunks\n                for (const chunk of chunks) {\n                    if ((chunk.data != null) && chunk.data.length > 0) {\n                        // Check if this field should be signed\n                        const shouldSign = (aip.data.fieldIndexes == null) || aip.data.fieldIndexes.includes(fieldIndex);\n                        if (shouldSign) {\n                            data.push(...Array.from(chunk.data));\n                        }\n                    }\n                    else if ((chunk.op != null) && chunk.op > 0x43 && chunk.op < 0x4f) {\n                        // Handle printable opcodes\n                        data.push(chunk.op);\n                    }\n                    fieldIndex++;\n                }\n                // Add pipe delimiter\n                data.push(0x7c); // '|'\n            }\n            // Verify signature using BSM following the pattern from BAP library\n            const signatureBase64 = Utils.toBase64(aip.data.signature);\n            const sig = Signature.fromCompact(signatureBase64, 'base64');\n            // Try all recovery factors (0-3) to find the correct public key\n            for (let recovery = 0; recovery < 4; recovery++) {\n                try {\n                    const publicKey = sig.RecoverPublicKey(recovery, new BigNumber(BSM.magicHash(data)));\n                    const sigFitsPubkey = BSM.verify(data, sig, publicKey);\n                    if (sigFitsPubkey && publicKey.toAddress().toString() === aip.data.address) {\n                        aip.data.valid = true;\n                        return;\n                    }\n                }\n                catch (e) {\n                    // Try next recovery factor\n                }\n            }\n            aip.data.valid = false;\n        }\n        catch (error) {\n            aip.data.valid = false;\n        }\n    }\n}\n//# sourceMappingURL=AIP.js.map",
    "import { Script, Utils } from '@bsv/sdk';\nimport BitCom from './BitCom.js';\n/**\n * Bitcoin Attestation Protocol (BAP) Types\n */\nexport var BAPAttestationType;\n(function (BAPAttestationType) {\n    BAPAttestationType[\"ID\"] = \"ID\";\n    BAPAttestationType[\"ATTEST\"] = \"ATTEST\";\n    BAPAttestationType[\"REVOKE\"] = \"REVOKE\";\n    BAPAttestationType[\"ALIAS\"] = \"ALIAS\";\n})(BAPAttestationType || (BAPAttestationType = {}));\n/**\n * BAP Protocol Prefix\n */\nexport const BAP_PROTOCOL_PREFIX = '1BAPSuaPnfGnSBM3GLV9yhxUdYe4vGbdMT';\n/**\n * Bitcoin Attestation Protocol (BAP) Template\n *\n * BAP is an advanced identity and attestation system that builds on AIP to provide\n * verifiable claims, identity verification, and decentralized reputation management.\n *\n * Core attestation types:\n * - ID: Create and register digital identities with cryptographic proof\n * - ATTEST: Make verifiable claims and attestations about other identities\n * - REVOKE: Revoke previous attestations or invalidate claims\n * - ALIAS: Create human-readable aliases for identities\n */\nexport default class BAP {\n    bitcomIndex;\n    type;\n    idKey;\n    address;\n    sequence;\n    algorithm;\n    signerAddr;\n    signature;\n    rootAddress;\n    isSignedByID;\n    profile;\n    constructor(data) {\n        this.bitcomIndex = data.bitcomIndex;\n        this.type = data.type;\n        this.idKey = data.idKey;\n        this.address = data.address;\n        this.sequence = data.sequence;\n        this.algorithm = data.algorithm;\n        this.signerAddr = data.signerAddr;\n        this.signature = data.signature;\n        this.rootAddress = data.rootAddress;\n        this.isSignedByID = data.isSignedByID;\n        this.profile = data.profile;\n    }\n    /**\n     * Creates a BAP locking script\n     *\n     * @returns LockingScript - The BAP locking script\n     */\n    lock() {\n        const script = new Script();\n        // Add attestation type\n        script.writeBin(Utils.toArray(this.type, 'utf8'));\n        // Add type-specific data\n        if (this.type === BAPAttestationType.ID) {\n            if (this.idKey != null && this.idKey !== '') {\n                script.writeBin(Utils.toArray(this.idKey, 'utf8'));\n            }\n            if (this.address != null && this.address !== '') {\n                script.writeBin(Utils.toArray(this.address, 'utf8'));\n            }\n        }\n        else if (this.type === BAPAttestationType.ATTEST || this.type === BAPAttestationType.REVOKE) {\n            if (this.idKey != null && this.idKey !== '') {\n                script.writeBin(Utils.toArray(this.idKey, 'utf8'));\n            }\n            // Add sequence number\n            script.writeBin(Utils.toArray(this.sequence.toString(), 'utf8'));\n        }\n        else if (this.type === BAPAttestationType.ALIAS) {\n            if (this.idKey != null && this.idKey !== '') {\n                script.writeBin(Utils.toArray(this.idKey, 'utf8'));\n            }\n            if (this.profile != null) {\n                const profileJson = JSON.stringify(this.profile);\n                script.writeBin(Utils.toArray(profileJson, 'utf8'));\n            }\n        }\n        // Add pipe delimiter for AIP signature\n        // Note: No pipe delimiter - pipe is reserved for BitCom protocol separation\n        // Add AIP signature data\n        if (this.algorithm != null && this.algorithm !== '') {\n            script.writeBin(Utils.toArray(this.algorithm, 'utf8'));\n        }\n        if (this.signerAddr != null && this.signerAddr !== '') {\n            script.writeBin(Utils.toArray(this.signerAddr, 'utf8'));\n        }\n        if (this.signature != null && this.signature !== '') {\n            script.writeBin(Utils.toArray(this.signature, 'utf8'));\n        }\n        // Create BitCom structure\n        const bitcom = new BitCom([{\n                protocol: BAP_PROTOCOL_PREFIX,\n                script: script.toBinary(),\n                pos: 0\n            }]);\n        return bitcom.lock();\n    }\n    /**\n     * Decodes a BAP protocol from BitCom structure\n     *\n     * @param bitcom - The BitCom decoded structure\n     * @returns BAP | null - The decoded BAP data, or null if not found\n     */\n    static decode(bitcom) {\n        if (bitcom == null || bitcom.protocols == null || bitcom.protocols.length === 0) {\n            return null;\n        }\n        // Find BAP protocol\n        const bapProtocol = bitcom.protocols.find(p => p.protocol === BAP_PROTOCOL_PREFIX);\n        if (bapProtocol == null) {\n            return null;\n        }\n        try {\n            // Parse the protocol script data\n            const script = Script.fromBinary(bapProtocol.script);\n            const chunks = script.chunks;\n            if (chunks.length < 1) {\n                return null;\n            }\n            // Extract attestation type\n            const typeChunk = chunks[0];\n            if (typeChunk.data == null) {\n                return null;\n            }\n            const type = Utils.toUTF8(typeChunk.data);\n            // AIP signature data comes after type-specific data (no pipe delimiter)\n            const bapData = {\n                bitcomIndex: bapProtocol.pos,\n                type,\n                sequence: BigInt(0),\n                isSignedByID: false\n            };\n            // Parse type-specific data\n            if (type === BAPAttestationType.ID) {\n                if (chunks.length > 1 && (chunks[1].data != null)) {\n                    bapData.idKey = Utils.toUTF8(chunks[1].data);\n                }\n                if (chunks.length > 2 && (chunks[2].data != null)) {\n                    bapData.address = Utils.toUTF8(chunks[2].data);\n                }\n                bapData.isSignedByID = true;\n            }\n            else if (type === BAPAttestationType.ATTEST || type === BAPAttestationType.REVOKE) {\n                if (chunks.length > 1 && (chunks[1].data != null)) {\n                    bapData.idKey = Utils.toUTF8(chunks[1].data);\n                }\n                if (chunks.length > 2 && (chunks[2].data != null)) {\n                    const sequenceStr = Utils.toUTF8(chunks[2].data);\n                    bapData.sequence = BigInt(sequenceStr);\n                }\n            }\n            else if (type === BAPAttestationType.ALIAS) {\n                if (chunks.length > 1 && (chunks[1].data != null)) {\n                    bapData.idKey = Utils.toUTF8(chunks[1].data);\n                }\n                if (chunks.length > 2 && (chunks[2].data != null)) {\n                    try {\n                        const profileJson = Utils.toUTF8(chunks[2].data);\n                        bapData.profile = JSON.parse(profileJson);\n                    }\n                    catch (e) {\n                        // Invalid JSON, store as raw data\n                        bapData.profile = Utils.toUTF8(chunks[2].data);\n                    }\n                }\n            }\n            // Calculate where AIP data starts based on type (after type-specific fields)\n            const aipStartIdx = 3; // Default: after type, idKey, and one more field\n            // Parse AIP signature data if present (algorithm, signerAddr, signature)\n            if (chunks.length > aipStartIdx && (chunks[aipStartIdx].data != null)) {\n                bapData.algorithm = Utils.toUTF8(chunks[aipStartIdx].data);\n            }\n            if (chunks.length > aipStartIdx + 1 && (chunks[aipStartIdx + 1].data != null)) {\n                const signerData = chunks[aipStartIdx + 1].data;\n                if (signerData != null) {\n                    bapData.signerAddr = Utils.toUTF8(signerData);\n                }\n            }\n            if (chunks.length > aipStartIdx + 2 && (chunks[aipStartIdx + 2].data != null)) {\n                const signatureData = chunks[aipStartIdx + 2].data;\n                if (signatureData != null) {\n                    bapData.signature = Utils.toUTF8(signatureData);\n                }\n            }\n            // Set root address if we have signer address\n            if (bapData.signerAddr != null && bapData.signerAddr !== '') {\n                bapData.rootAddress = bapData.signerAddr;\n            }\n            // Set isSignedByID based on attestation type\n            if (type === BAPAttestationType.ID) {\n                bapData.isSignedByID = true; // ID attestations are always signed by the identity\n            }\n            else {\n                bapData.isSignedByID = false; // ATTEST/REVOKE/ALIAS are not signed by the ID itself\n            }\n            return new BAP(bapData);\n        }\n        catch (error) {\n            return null;\n        }\n    }\n    /**\n     * Creates a BAP ID attestation\n     *\n     * @param identityKey - The identity public key\n     * @param address - The associated address\n     * @param algorithm - The AIP algorithm\n     * @param signerAddr - The signer address\n     * @param signature - The AIP signature\n     * @returns BAP - The ID attestation\n     */\n    static createID(identityKey, address, algorithm, signerAddr, signature) {\n        return new BAP({\n            type: BAPAttestationType.ID,\n            idKey: identityKey,\n            address,\n            sequence: BigInt(0),\n            algorithm,\n            signerAddr,\n            signature,\n            rootAddress: signerAddr,\n            isSignedByID: true\n        });\n    }\n    /**\n     * Creates a BAP ATTEST attestation\n     *\n     * @param txid - The transaction ID being attested to\n     * @param sequence - The sequence number\n     * @param algorithm - The AIP algorithm\n     * @param signerAddr - The signer address\n     * @param signature - The AIP signature\n     * @returns BAP - The ATTEST attestation\n     */\n    static createAttest(txid, sequence, algorithm, signerAddr, signature) {\n        return new BAP({\n            type: BAPAttestationType.ATTEST,\n            idKey: txid,\n            sequence,\n            algorithm,\n            signerAddr,\n            signature,\n            rootAddress: signerAddr,\n            isSignedByID: false\n        });\n    }\n    /**\n     * Creates a BAP REVOKE attestation\n     *\n     * @param txid - The transaction ID being revoked\n     * @param sequence - The sequence number\n     * @param algorithm - The AIP algorithm\n     * @param signerAddr - The signer address\n     * @param signature - The AIP signature\n     * @returns BAP - The REVOKE attestation\n     */\n    static createRevoke(txid, sequence, algorithm, signerAddr, signature) {\n        return new BAP({\n            type: BAPAttestationType.REVOKE,\n            idKey: txid,\n            sequence,\n            algorithm,\n            signerAddr,\n            signature,\n            rootAddress: signerAddr,\n            isSignedByID: false\n        });\n    }\n    /**\n     * Creates a BAP ALIAS attestation\n     *\n     * @param alias - The human-readable alias\n     * @param profile - The profile data\n     * @param algorithm - The AIP algorithm\n     * @param signerAddr - The signer address\n     * @param signature - The AIP signature\n     * @returns BAP - The ALIAS attestation\n     */\n    static createAlias(alias, profile, algorithm, signerAddr, signature) {\n        return new BAP({\n            type: BAPAttestationType.ALIAS,\n            idKey: alias,\n            sequence: BigInt(0),\n            profile,\n            algorithm,\n            signerAddr,\n            signature,\n            rootAddress: signerAddr,\n            isSignedByID: false\n        });\n    }\n    /**\n     * Verifies the AIP signature for the BAP attestation\n     *\n     * @param protocolData - The protocol data for signature verification\n     * @returns boolean - True if signature is valid\n     */\n    verifySignature(protocolData) {\n        if (this.algorithm == null || this.algorithm === '' ||\n            this.signerAddr == null || this.signerAddr === '' ||\n            this.signature == null || this.signature === '') {\n            return false;\n        }\n        // This would need to be implemented with actual AIP verification\n        // For now, return true if all signature components are present\n        return true;\n    }\n    /**\n     * Placeholder for unlock method - BAP is read-only\n     */\n    unlock() {\n        throw new Error('BAP attestations cannot be unlocked - they are read-only identity records');\n    }\n}\n//# sourceMappingURL=BAP.js.map",
    "import { LockingScript, OP, Script, Utils, Hash } from '@bsv/sdk';\n/**\n * Inscription class implementing ScriptTemplate for Bitcoin ordinals and on-chain data storage.\n *\n * Inscriptions enable embedding arbitrary files, data, and content directly into blockchain\n * transactions using the script pattern: OP_0 OP_IF \"ord\" OP_1 [MIME_TYPE] OP_0 [CONTENT] OP_ENDIF\n *\n * @example\n * ```typescript\n * // Create inscription from text\n * const inscription = Inscription.fromText(\"Hello, BSV!\", \"text/plain\");\n * const lockingScript = inscription.lock();\n *\n * // Create inscription from binary data\n * const imageData = new Uint8Array([...]); // PNG image data\n * const imageInscription = Inscription.create(imageData, \"image/png\");\n *\n * // Parse inscription from script\n * const parsed = Inscription.decode(someScript);\n * if (parsed) {\n *   console.log(`Content type: ${parsed.file.type}`);\n *   console.log(`Content size: ${parsed.file.size} bytes`);\n * }\n * ```\n */\nexport default class Inscription {\n    /** Inscription file data */\n    file;\n    /** Optional parent inscription reference */\n    parent;\n    /** Optional script prefix */\n    scriptPrefix;\n    /** Optional script suffix */\n    scriptSuffix;\n    /** Unknown/custom fields (field number -> data) */\n    fields;\n    /**\n     * Creates a new Inscription instance\n     *\n     * @param file - The inscription file data\n     * @param parent - Optional parent inscription reference (32 or 36-byte outpoint)\n     * @param scriptPrefix - Optional script prefix\n     * @param scriptSuffix - Optional script suffix\n     * @param fields - Optional map of unknown/custom fields\n     */\n    constructor(file, parent, scriptPrefix, scriptSuffix, fields) {\n        this.file = file;\n        this.parent = parent;\n        this.scriptPrefix = scriptPrefix;\n        this.scriptSuffix = scriptSuffix;\n        this.fields = fields;\n    }\n    /**\n     * Creates an inscription locking script following the ordinals protocol format:\n     * [ScriptPrefix] OP_0 OP_IF \"ord\" OP_1 [MIME_TYPE] OP_0 [CONTENT] OP_ENDIF [ScriptSuffix]\n     *\n     * @returns A locking script containing the inscription data\n     */\n    lock() {\n        const script = new Script();\n        // Add script prefix if present\n        if (this.scriptPrefix != null) {\n            // Treat prefix as raw opcodes, not data\n            for (const opcode of this.scriptPrefix) {\n                script.writeOpCode(opcode);\n            }\n        }\n        // Start inscription envelope: OP_0 OP_IF\n        script.writeOpCode(OP.OP_0);\n        script.writeOpCode(OP.OP_IF);\n        // Protocol identifier: \"ord\"\n        script.writeBin(Utils.toArray('ord', 'utf8'));\n        // Add MIME type (field 1)\n        script.writeOpCode(OP.OP_1);\n        script.writeBin(Utils.toArray(this.file.type, 'utf8'));\n        // Add parent if present (field 3)\n        if ((this.parent != null) && this.parent.length === 36) {\n            script.writeOpCode(OP.OP_3);\n            script.writeBin(Array.from(this.parent));\n        }\n        // Add content (field 0)\n        script.writeOpCode(OP.OP_0);\n        script.writeBin(Array.from(this.file.content));\n        // End inscription envelope: OP_ENDIF\n        script.writeOpCode(OP.OP_ENDIF);\n        // Add script suffix if present\n        if (this.scriptSuffix != null) {\n            // Treat suffix as raw opcodes, not data\n            for (const opcode of this.scriptSuffix) {\n                script.writeOpCode(opcode);\n            }\n        }\n        return new LockingScript(script.chunks);\n    }\n    /**\n     * Unlock method is not applicable for inscription scripts.\n     * Inscriptions are typically used in outputs that don't require unlocking.\n     *\n     * @throws Error indicating unlock is not supported\n     */\n    unlock() {\n        throw new Error('Unlock is not supported for inscription scripts');\n    }\n    /**\n     * Verifies that the file hash matches the content\n     *\n     * @returns true if the hash is valid, false otherwise\n     */\n    verify() {\n        const calculatedHash = Hash.sha256(Array.from(this.file.content));\n        return Utils.toHex(calculatedHash) === Utils.toHex(Array.from(this.file.hash));\n    }\n    /**\n     * Creates a new inscription from content and MIME type\n     *\n     * @param content - The file content as bytes\n     * @param contentType - The MIME type of the content\n     * @param options - Optional inscription parameters\n     * @returns A new Inscription instance\n     */\n    static create(content, contentType, options = {}) {\n        // Validate MIME type\n        if (contentType === '' || contentType.length > 255) {\n            throw new Error('Content type must be a non-empty string with max 255 characters');\n        }\n        // Validate UTF-8 encoding for content type\n        try {\n            Utils.toArray(contentType, 'utf8');\n        }\n        catch {\n            throw new Error('Content type must be valid UTF-8');\n        }\n        // Validate parent if provided\n        if ((options.parent != null) && options.parent.length !== 36) {\n            throw new Error('Parent must be exactly 36 bytes (transaction outpoint)');\n        }\n        // Calculate hash and create file structure\n        const hash = new Uint8Array(Hash.sha256(Array.from(content)));\n        const file = {\n            hash,\n            size: content.length,\n            type: contentType,\n            content\n        };\n        return new Inscription(file, options.parent, options.scriptPrefix, options.scriptSuffix);\n    }\n    /**\n     * Creates an inscription from text content\n     *\n     * @param text - The text content\n     * @param contentType - Optional MIME type (defaults to \"text/plain;charset=utf-8\")\n     * @param options - Optional inscription parameters\n     * @returns A new Inscription instance\n     */\n    static fromText(text, contentType = 'text/plain;charset=utf-8', options = {}) {\n        const content = new Uint8Array(Utils.toArray(text, 'utf8'));\n        return Inscription.create(content, contentType, options);\n    }\n    /**\n     * Creates an inscription from a browser File object\n     *\n     * @param file - The File object\n     * @param options - Optional inscription parameters\n     * @returns Promise resolving to a new Inscription instance\n     */\n    static async fromFile(file, options = {}) {\n        const arrayBuffer = await file.arrayBuffer();\n        const content = new Uint8Array(arrayBuffer);\n        const contentType = file.type !== '' ? file.type : 'application/octet-stream';\n        return Inscription.create(content, contentType, options);\n    }\n    /**\n     * Checks if a script contains an inscription\n     *\n     * @param script - The script to check\n     * @returns true if the script contains an inscription pattern\n     */\n    static isInscription(script) {\n        try {\n            const chunks = script.chunks;\n            // Look for the pattern: OP_0 OP_IF \"ord\"\n            for (let i = 0; i < chunks.length - 2; i++) {\n                const chunk0 = chunks[i];\n                const chunk1 = chunks[i + 1];\n                const chunk2 = chunks[i + 2];\n                if (chunk0?.op === OP.OP_0 &&\n                    chunk1?.op === OP.OP_IF &&\n                    ((chunk2?.data) != null) &&\n                    chunk2.data.length === 3 &&\n                    Utils.toUTF8(chunk2.data) === 'ord') {\n                    return true;\n                }\n            }\n            return false;\n        }\n        catch {\n            return false;\n        }\n    }\n    /**\n     * Decodes an inscription from a script\n     *\n     * @param script - The script containing inscription data\n     * @returns Decoded inscription or null if not found/invalid\n     */\n    static decode(script) {\n        try {\n            const chunks = script.chunks;\n            // Find inscription pattern: OP_0 OP_IF \"ord\"\n            let inscriptionStart = -1;\n            for (let i = 0; i < chunks.length - 2; i++) {\n                const chunk0 = chunks[i];\n                const chunk1 = chunks[i + 1];\n                const chunk2 = chunks[i + 2];\n                if (chunk0?.op === OP.OP_0 &&\n                    chunk1?.op === OP.OP_IF &&\n                    ((chunk2?.data) != null) &&\n                    chunk2.data.length === 3 &&\n                    Utils.toUTF8(chunk2.data) === 'ord') {\n                    inscriptionStart = i;\n                    break;\n                }\n            }\n            if (inscriptionStart === -1) {\n                return null;\n            }\n            // Extract prefix (everything before inscription)\n            let scriptPrefix;\n            if (inscriptionStart > 0) {\n                const prefixScript = new Script();\n                for (let i = 0; i < inscriptionStart; i++) {\n                    const chunk = chunks[i];\n                    if (((chunk?.data) != null) && chunk.data.length > 0) {\n                        prefixScript.writeBin(chunk.data);\n                    }\n                    else if (chunk?.op !== undefined) {\n                        prefixScript.writeOpCode(chunk.op);\n                    }\n                }\n                scriptPrefix = new Uint8Array(prefixScript.toBinary());\n            }\n            // Parse inscription fields\n            let pos = inscriptionStart + 3; // Skip OP_0 OP_IF \"ord\"\n            let contentType = '';\n            let content = new Uint8Array(0);\n            let parent;\n            const fields = new Map();\n            while (pos < chunks.length) {\n                if (chunks[pos].op === OP.OP_ENDIF) {\n                    pos++;\n                    break;\n                }\n                // Read field number/key\n                const fieldChunk = chunks[pos];\n                let fieldNum;\n                let fieldKey;\n                // Handle OP codes for field numbers\n                if (fieldChunk.op === OP.OP_0) {\n                    fieldNum = 0;\n                }\n                else if (fieldChunk.op !== undefined && fieldChunk.op > OP.OP_PUSHDATA4 && fieldChunk.op <= OP.OP_16) {\n                    fieldNum = fieldChunk.op - 80; // OP_1 = 81, so OP_1 - 80 = 1\n                }\n                else if (fieldChunk.data != null && fieldChunk.data.length === 1) {\n                    // Single byte data as field number\n                    fieldNum = fieldChunk.data[0];\n                }\n                else if (fieldChunk.data != null && fieldChunk.data.length > 1) {\n                    // Multi-byte data as string key (like Go implementation)\n                    fieldKey = String.fromCharCode(...fieldChunk.data);\n                }\n                else {\n                    // Unknown field format, skip\n                    pos++;\n                    continue;\n                }\n                pos++;\n                // Read data\n                const dataChunk = chunks[pos];\n                if (pos >= chunks.length) {\n                    break;\n                }\n                // Data chunk may be empty or have data\n                const data = dataChunk?.data != null ? new Uint8Array(dataChunk.data) : new Uint8Array(0);\n                pos++;\n                // Process field based on number or key\n                if (fieldKey != null) {\n                    // String key field - store in fields map\n                    fields.set(fieldKey, data);\n                }\n                else if (fieldNum !== undefined) {\n                    switch (fieldNum) {\n                        case 0: // Content\n                            content = data;\n                            break;\n                        case 1: // MIME type\n                            try {\n                                contentType = Utils.toUTF8(Array.from(data));\n                            }\n                            catch {\n                                // Invalid UTF-8, use empty string\n                                contentType = '';\n                            }\n                            break;\n                        case 3: // Parent - accept both 32 and 36 bytes (like Go)\n                            if (data.length === 36) {\n                                parent = data;\n                            }\n                            else if (data.length === 32) {\n                                // 32-byte txid only - create 36-byte outpoint with vout=0\n                                parent = new Uint8Array(36);\n                                parent.set(data, 0);\n                                // Last 4 bytes are already 0 (vout = 0)\n                            }\n                            break;\n                        default:\n                            // Store unknown numeric fields in fields map\n                            fields.set(fieldNum.toString(), data);\n                    }\n                }\n            }\n            // Extract suffix (everything after OP_ENDIF)\n            let scriptSuffix;\n            if (pos < chunks.length) {\n                const suffixScript = new Script();\n                for (let i = pos; i < chunks.length; i++) {\n                    const chunk = chunks[i];\n                    if (((chunk?.data) != null) && chunk.data.length > 0) {\n                        suffixScript.writeBin(chunk.data);\n                    }\n                    else if (chunk?.op !== undefined) {\n                        suffixScript.writeOpCode(chunk.op);\n                    }\n                }\n                scriptSuffix = new Uint8Array(suffixScript.toBinary());\n            }\n            // Must have content to be valid\n            if (content.length === 0) {\n                return null;\n            }\n            // Calculate hash\n            const hash = new Uint8Array(Hash.sha256(Array.from(content)));\n            const file = {\n                hash,\n                size: content.length,\n                type: contentType,\n                content\n            };\n            return new Inscription(file, parent, scriptPrefix, scriptSuffix, fields.size > 0 ? fields : undefined);\n        }\n        catch {\n            return null;\n        }\n    }\n    /**\n     * Extracts text content from the inscription if it's a text type\n     *\n     * @returns The text content or null if not text or invalid UTF-8\n     */\n    getText() {\n        if (!this.file.type.startsWith('text/') && this.file.type !== 'application/json') {\n            return null;\n        }\n        try {\n            return Utils.toUTF8(Array.from(this.file.content));\n        }\n        catch {\n            return null;\n        }\n    }\n    /**\n     * Parses JSON content from the inscription\n     *\n     * @returns The parsed JSON object or null if not JSON or invalid\n     */\n    getJSON() {\n        const text = this.getText();\n        if (text == null)\n            return null;\n        try {\n            return JSON.parse(text);\n        }\n        catch {\n            return null;\n        }\n    }\n    /**\n     * Gets the raw content as bytes\n     *\n     * @returns The file content\n     */\n    getContent() {\n        return this.file.content;\n    }\n    /**\n     * Gets content as base64 string\n     *\n     * @returns Base64 encoded content\n     */\n    getBase64() {\n        return Utils.toBase64(Array.from(this.file.content));\n    }\n    /**\n     * Gets content as hex string\n     *\n     * @returns Hex encoded content\n     */\n    getHex() {\n        return Utils.toHex(Array.from(this.file.content));\n    }\n}\n//# sourceMappingURL=Inscription.js.map",
    "import { Utils } from '@bsv/sdk';\nimport Inscription from '../inscription/Inscription.js';\n/**\n * BSV-21 class implementing ScriptTemplate for advanced token functionality.\n *\n * BSV-21 is an advanced token standard that builds on inscriptions to create\n * sophisticated tokens with rich metadata, file attachments, and complex operations.\n * Unlike BSV-20's simple JSON structure, BSV-21 leverages the full power of\n * inscriptions for token data storage.\n *\n * @example\n * ```typescript\n * // Create deploy+mint token (initial token creation)\n * const token = BSV21.deployMint(\"MYTOKEN\", 1000000n, 8, \"https://example.com/icon.png\");\n * const lockingScript = token.lock();\n *\n * // Transfer tokens\n * const transfer = BSV21.transfer(\"token_deployment_outpoint\", 500n);\n * const transferScript = transfer.lock();\n *\n * // Parse token from script\n * const parsed = BSV21.decode(someScript);\n * if (parsed) {\n *   console.log(`Symbol: ${parsed.getSymbol()}`);\n *   console.log(`Amount: ${parsed.getAmount()}`);\n *   console.log(`Operation: ${parsed.tokenData.op}`);\n * }\n * ```\n */\nexport default class BSV21 {\n    /** BSV-21 token data */\n    tokenData;\n    /** Underlying inscription containing the token data */\n    inscription;\n    /**\n     * Creates a new BSV21 instance\n     *\n     * @param tokenData - The token data structure\n     * @param inscription - The inscription containing the token data\n     */\n    constructor(tokenData, inscription) {\n        this.tokenData = tokenData;\n        this.inscription = inscription;\n    }\n    /**\n     * Creates a deploy+mint token (initial token creation with minting)\n     *\n     * @param symbol - Token symbol/ticker (e.g., \"MYTOKEN\")\n     * @param amount - Initial amount to mint\n     * @param decimals - Number of decimal places (0-18, default 0)\n     * @param icon - Optional icon URL or data URI\n     * @param options - Optional inscription parameters\n     * @returns A new BSV21 instance\n     */\n    static deployMint(symbol, amount, decimals = 0, icon, options = {}) {\n        // Validate parameters\n        if (symbol == null || symbol === '' || symbol.length === 0) {\n            throw new Error('Symbol cannot be empty');\n        }\n        if (symbol.length > 32) {\n            throw new Error('Symbol cannot exceed 32 characters');\n        }\n        if (amount <= BigInt(0)) {\n            throw new Error('Amount must be positive');\n        }\n        if (decimals < 0 || decimals > 18) {\n            throw new Error('Decimals must be between 0 and 18');\n        }\n        // Create token data\n        const tokenData = {\n            p: 'bsv-20',\n            op: 'deploy+mint',\n            sym: symbol,\n            amt: amount.toString()\n        };\n        // Add optional fields\n        if (decimals > 0) {\n            tokenData.dec = decimals;\n        }\n        if (icon != null && icon !== '') {\n            tokenData.icon = icon;\n        }\n        // Create inscription with token JSON\n        const jsonContent = JSON.stringify(tokenData);\n        const inscription = Inscription.fromText(jsonContent, 'application/bsv-20', options);\n        return new BSV21(tokenData, inscription);\n    }\n    /**\n     * Creates a transfer token for moving tokens between addresses\n     *\n     * @param tokenId - Token deployment transaction outpoint (txid_vout)\n     * @param amount - Amount to transfer\n     * @param options - Optional inscription parameters\n     * @returns A new BSV21 instance\n     */\n    static transfer(tokenId, amount, options = {}) {\n        // Validate parameters\n        if (tokenId == null || tokenId === '' || tokenId.length === 0) {\n            throw new Error('Token ID cannot be empty');\n        }\n        if (amount <= BigInt(0)) {\n            throw new Error('Amount must be positive');\n        }\n        // Validate token ID format (txid_vout)\n        const parts = tokenId.split('_');\n        if (parts.length !== 2 || parts[0].length !== 64 || !/^\\d+$/.test(parts[1])) {\n            throw new Error('Token ID must be in format: txid_vout');\n        }\n        // Create token data\n        const tokenData = {\n            p: 'bsv-20',\n            op: 'transfer',\n            id: tokenId,\n            amt: amount.toString()\n        };\n        // Create inscription with token JSON\n        const jsonContent = JSON.stringify(tokenData);\n        const inscription = Inscription.fromText(jsonContent, 'application/bsv-20', options);\n        return new BSV21(tokenData, inscription);\n    }\n    /**\n     * Creates a burn token for permanently destroying tokens\n     *\n     * @param tokenId - Token deployment transaction outpoint (txid_vout)\n     * @param amount - Amount to burn\n     * @param options - Optional inscription parameters\n     * @returns A new BSV21 instance\n     */\n    static burn(tokenId, amount, options = {}) {\n        // Validate parameters\n        if (tokenId == null || tokenId === '' || tokenId.length === 0) {\n            throw new Error('Token ID cannot be empty');\n        }\n        if (amount <= BigInt(0)) {\n            throw new Error('Amount must be positive');\n        }\n        // Validate token ID format (txid_vout)\n        const parts = tokenId.split('_');\n        if (parts.length !== 2 || parts[0].length !== 64 || !/^\\d+$/.test(parts[1])) {\n            throw new Error('Token ID must be in format: txid_vout');\n        }\n        // Create token data\n        const tokenData = {\n            p: 'bsv-20',\n            op: 'burn',\n            id: tokenId,\n            amt: amount.toString()\n        };\n        // Create inscription with token JSON\n        const jsonContent = JSON.stringify(tokenData);\n        const inscription = Inscription.fromText(jsonContent, 'application/bsv-20', options);\n        return new BSV21(tokenData, inscription);\n    }\n    /**\n     * Decodes a BSV-21 token from a script\n     *\n     * @param script - The script containing BSV-21 token data\n     * @returns Decoded BSV-21 token or null if not found/invalid\n     */\n    static decode(script) {\n        try {\n            // First decode as inscription\n            const inscription = Inscription.decode(script);\n            if (inscription == null)\n                return null;\n            // Check if it's BSV-21 token (application/bsv-20 MIME type)\n            if (inscription.file.type !== 'application/bsv-20')\n                return null;\n            // Parse JSON content - use raw content since application/bsv-20 is not recognized as text\n            let jsonText;\n            try {\n                jsonText = Utils.toUTF8(Array.from(inscription.file.content));\n            }\n            catch {\n                return null;\n            }\n            const data = JSON.parse(jsonText);\n            // Validate required protocol fields\n            if (data.p !== 'bsv-20')\n                return null;\n            if (data.op == null || typeof data.op !== 'string')\n                return null;\n            if (data.amt == null || typeof data.amt !== 'string')\n                return null;\n            // Parse amount\n            let amount;\n            try {\n                amount = BigInt(data.amt);\n                if (amount <= BigInt(0))\n                    return null;\n            }\n            catch {\n                return null;\n            }\n            // Validate operation and required fields\n            const operation = data.op.toLowerCase();\n            switch (operation) {\n                case 'deploy+mint':\n                    if (data.sym == null || typeof data.sym !== 'string')\n                        return null;\n                    if (data.sym.length === 0 || data.sym.length > 32)\n                        return null;\n                    if (data.dec !== undefined) {\n                        // dec must be a string in the JSON - reject if it's a JS number\n                        if (typeof data.dec !== 'string')\n                            return null;\n                        const dec = parseInt(data.dec, 10);\n                        if (isNaN(dec))\n                            return null;\n                        if (dec < 0 || dec > 18)\n                            return null;\n                        // Normalize to number for tokenData\n                        data.dec = dec;\n                    }\n                    break;\n                case 'transfer':\n                case 'burn': {\n                    if (data.id == null || typeof data.id !== 'string')\n                        return null;\n                    // Validate token ID format\n                    const parts = data.id.split('_');\n                    if (parts.length !== 2 || parts[0].length !== 64 || !/^\\d+$/.test(parts[1])) {\n                        return null;\n                    }\n                    break;\n                }\n                default:\n                    return null;\n            }\n            // Create token data structure\n            const tokenData = {\n                p: 'bsv-20',\n                op: operation,\n                amt: data.amt\n            };\n            // Add operation-specific fields\n            if (operation === 'deploy+mint') {\n                tokenData.sym = data.sym;\n                if (data.dec !== undefined) {\n                    tokenData.dec = data.dec;\n                }\n                if (data.icon != null && data.icon !== '') {\n                    tokenData.icon = data.icon;\n                }\n            }\n            else {\n                tokenData.id = data.id;\n            }\n            return new BSV21(tokenData, inscription);\n        }\n        catch {\n            return null;\n        }\n    }\n    /**\n     * Creates a locking script containing the BSV-21 token inscription\n     *\n     * @param lockingScript - Optional locking script to append as suffix\n     * @returns A locking script containing the token data\n     */\n    lock(lockingScript) {\n        if (lockingScript != null) {\n            // Create new inscription with the locking script as suffix\n            const options = {\n                parent: this.inscription.parent,\n                scriptPrefix: this.inscription.scriptPrefix,\n                scriptSuffix: new Uint8Array(lockingScript.toBinary())\n            };\n            // Create new inscription with suffix\n            const jsonContent = JSON.stringify(this.tokenData);\n            const newInscription = Inscription.fromText(jsonContent, 'application/bsv-20', options);\n            return newInscription.lock();\n        }\n        return this.inscription.lock();\n    }\n    /**\n     * BSV-21 tokens cannot be unlocked directly as they are data containers\n     *\n     * @throws Error indicating unlock is not supported\n     */\n    unlock() {\n        throw new Error('BSV-21 tokens cannot be unlocked directly');\n    }\n    /**\n     * Gets the token amount as BigInt\n     *\n     * @returns Token amount\n     */\n    getAmount() {\n        return BigInt(this.tokenData.amt);\n    }\n    /**\n     * Gets the token amount as BigInt (concise method)\n     *\n     * @returns Token amount\n     */\n    amount() {\n        return this.getAmount();\n    }\n    /**\n     * Gets the token symbol (for deploy+mint operations)\n     *\n     * @returns Token symbol or undefined for transfer/burn operations\n     */\n    getSymbol() {\n        return this.tokenData.sym;\n    }\n    /**\n     * Gets the token symbol (concise method)\n     *\n     * @returns Token symbol or undefined for transfer/burn operations\n     */\n    symbol() {\n        return this.getSymbol();\n    }\n    /**\n     * Gets the number of decimal places (for deploy+mint operations)\n     *\n     * @returns Number of decimals, defaults to 0\n     */\n    getDecimals() {\n        return this.tokenData.dec ?? 0;\n    }\n    /**\n     * Gets the token ID (for transfer/burn operations)\n     *\n     * @returns Token deployment outpoint or undefined for deploy+mint operations\n     */\n    getTokenId() {\n        return this.tokenData.id;\n    }\n    /**\n     * Gets the icon URL or data URI (for deploy+mint operations)\n     *\n     * @returns Icon string or undefined\n     */\n    getIcon() {\n        return this.tokenData.icon;\n    }\n    /**\n     * Checks if this token has an icon\n     *\n     * @returns true if icon is present\n     */\n    hasIcon() {\n        return this.tokenData.icon != null && this.tokenData.icon !== '';\n    }\n    /**\n     * Gets the token operation type\n     *\n     * @returns The operation (deploy+mint, transfer, or burn)\n     */\n    getOperation() {\n        return this.tokenData.op;\n    }\n    /**\n     * Gets the token operation type (concise method)\n     *\n     * @returns The operation (deploy+mint, transfer, or burn)\n     */\n    operation() {\n        return this.getOperation();\n    }\n    /**\n     * Checks if this is a deploy+mint operation\n     *\n     * @returns true for deploy+mint operations\n     */\n    isDeployMint() {\n        return this.tokenData.op === 'deploy+mint';\n    }\n    /**\n     * Checks if this is a transfer operation\n     *\n     * @returns true for transfer operations\n     */\n    isTransfer() {\n        return this.tokenData.op === 'transfer';\n    }\n    /**\n     * Checks if this is a burn operation\n     *\n     * @returns true for burn operations\n     */\n    isBurn() {\n        return this.tokenData.op === 'burn';\n    }\n    /**\n     * Gets the underlying inscription\n     *\n     * @returns The inscription containing the token data\n     */\n    getInscription() {\n        return this.inscription;\n    }\n    /**\n     * Gets the token data as formatted JSON string\n     *\n     * @returns JSON representation of token data\n     */\n    toJSON() {\n        return JSON.stringify(this.tokenData, null, 2);\n    }\n    /**\n     * Validates the token data structure\n     *\n     * @returns true if token data is valid\n     */\n    validate() {\n        try {\n            // Validate basic structure\n            if (this.tokenData.p !== 'bsv-20')\n                return false;\n            if (this.tokenData.op == null || (this.tokenData.amt == null || this.tokenData.amt === ''))\n                return false;\n            // Validate amount\n            const amount = BigInt(this.tokenData.amt);\n            if (amount <= BigInt(0))\n                return false;\n            // Validate operation-specific fields\n            switch (this.tokenData.op) {\n                case 'deploy+mint':\n                    if (this.tokenData.sym == null || this.tokenData.sym === '' || this.tokenData.sym.length === 0 || this.tokenData.sym.length > 32) {\n                        return false;\n                    }\n                    if (this.tokenData.dec !== undefined && (this.tokenData.dec < 0 || this.tokenData.dec > 18)) {\n                        return false;\n                    }\n                    break;\n                case 'transfer':\n                case 'burn': {\n                    if (this.tokenData.id == null || this.tokenData.id === '')\n                        return false;\n                    const parts = this.tokenData.id.split('_');\n                    if (parts.length !== 2 || parts[0].length !== 64 || !/^\\d+$/.test(parts[1])) {\n                        return false;\n                    }\n                    break;\n                }\n                default:\n                    return false;\n            }\n            return true;\n        }\n        catch {\n            return false;\n        }\n    }\n}\n//# sourceMappingURL=BSV21.js.map",
    "import { Utils } from '@bsv/sdk';\nimport Inscription from '../inscription/Inscription.js';\n/**\n * BSV-20 class implementing ScriptTemplate for basic fungible tokens.\n *\n * BSV-20 is the foundational token standard for BSV blockchain, providing\n * simple and efficient fungible tokens with ticker-based identification.\n * It serves as the base layer for the token economy on BSV.\n *\n * @example\n * ```typescript\n * // Deploy a new token\n * const deploy = BSV20.deploy(\"MYTOKEN\", BigInt(\"21000000\"), 8, BigInt(\"1000000\"));\n * const deployScript = deploy.lock();\n *\n * // Mint tokens\n * const mint = BSV20.mint(\"MYTOKEN\", BigInt(\"1000000\"));\n * const mintScript = mint.lock();\n *\n * // Transfer tokens\n * const transfer = BSV20.transfer(\"MYTOKEN\", BigInt(\"500\"));\n * const transferScript = transfer.lock();\n *\n * // Parse token from script\n * const parsed = BSV20.decode(someScript);\n * if (parsed) {\n *   console.log(`Ticker: ${parsed.getTicker()}`);\n *   console.log(`Amount: ${parsed.getAmount()}`);\n *   console.log(`Operation: ${parsed.tokenData.op}`);\n * }\n * ```\n */\nexport default class BSV20 {\n    /** BSV-20 token data */\n    tokenData;\n    /** Underlying inscription containing the token data */\n    inscription;\n    /**\n     * Creates a new BSV20 instance\n     *\n     * @param tokenData - The token data structure\n     * @param inscription - The inscription containing the token data\n     */\n    constructor(tokenData, inscription) {\n        this.tokenData = tokenData;\n        this.inscription = inscription;\n    }\n    /**\n     * Creates a deploy operation for a new BSV-20 token\n     *\n     * @param ticker - Token ticker/symbol (1-32 characters)\n     * @param maxSupply - Maximum total supply\n     * @param decimals - Number of decimal places (0-18, default 0)\n     * @param limitPerMint - Optional limit per mint operation\n     * @param options - Optional inscription parameters\n     * @returns A new BSV20 instance\n     */\n    static deploy(ticker, maxSupply, decimals = 0, limitPerMint, options = {}) {\n        // Validate parameters\n        if (ticker == null || ticker === '' || ticker.length === 0) {\n            throw new Error('Ticker cannot be empty');\n        }\n        if (ticker.length > 32) {\n            throw new Error('Ticker cannot exceed 32 characters');\n        }\n        if (maxSupply <= BigInt(0)) {\n            throw new Error('Max supply must be positive');\n        }\n        if (decimals < 0 || decimals > 18) {\n            throw new Error('Decimals must be between 0 and 18');\n        }\n        if (limitPerMint != null && limitPerMint <= BigInt(0)) {\n            throw new Error('Limit per mint must be positive');\n        }\n        // Create token data\n        const tokenData = {\n            p: 'bsv-20',\n            op: 'deploy',\n            tick: ticker,\n            amt: '0', // Deploy operation has no amount\n            max: maxSupply.toString()\n        };\n        // Add optional fields\n        if (decimals > 0) {\n            tokenData.dec = decimals;\n        }\n        if (limitPerMint != null) {\n            tokenData.lim = limitPerMint.toString();\n        }\n        // Create inscription with token JSON\n        const jsonContent = JSON.stringify(tokenData);\n        const inscription = Inscription.fromText(jsonContent, 'application/bsv-20', options);\n        return new BSV20(tokenData, inscription);\n    }\n    /**\n     * Creates a mint operation for an existing BSV-20 token\n     *\n     * @param ticker - Token ticker to mint\n     * @param amount - Amount to mint\n     * @param options - Optional inscription parameters\n     * @returns A new BSV20 instance\n     */\n    static mint(ticker, amount, options = {}) {\n        // Validate parameters\n        if (ticker == null || ticker === '' || ticker.length === 0) {\n            throw new Error('Ticker cannot be empty');\n        }\n        if (ticker.length > 32) {\n            throw new Error('Ticker cannot exceed 32 characters');\n        }\n        if (amount <= BigInt(0)) {\n            throw new Error('Amount must be positive');\n        }\n        // Create token data\n        const tokenData = {\n            p: 'bsv-20',\n            op: 'mint',\n            tick: ticker,\n            amt: amount.toString()\n        };\n        // Create inscription with token JSON\n        const jsonContent = JSON.stringify(tokenData);\n        const inscription = Inscription.fromText(jsonContent, 'application/bsv-20', options);\n        return new BSV20(tokenData, inscription);\n    }\n    /**\n     * Creates a transfer operation for moving BSV-20 tokens\n     *\n     * @param ticker - Token ticker to transfer\n     * @param amount - Amount to transfer\n     * @param options - Optional inscription parameters\n     * @returns A new BSV20 instance\n     */\n    static transfer(ticker, amount, options = {}) {\n        // Validate parameters\n        if (ticker == null || ticker === '' || ticker.length === 0) {\n            throw new Error('Ticker cannot be empty');\n        }\n        if (ticker.length > 32) {\n            throw new Error('Ticker cannot exceed 32 characters');\n        }\n        if (amount <= BigInt(0)) {\n            throw new Error('Amount must be positive');\n        }\n        // Create token data\n        const tokenData = {\n            p: 'bsv-20',\n            op: 'transfer',\n            tick: ticker,\n            amt: amount.toString()\n        };\n        // Create inscription with token JSON\n        const jsonContent = JSON.stringify(tokenData);\n        const inscription = Inscription.fromText(jsonContent, 'application/bsv-20', options);\n        return new BSV20(tokenData, inscription);\n    }\n    /**\n     * Creates a burn operation for permanently destroying BSV-20 tokens\n     *\n     * @param ticker - Token ticker to burn\n     * @param amount - Amount to burn\n     * @param options - Optional inscription parameters\n     * @returns A new BSV20 instance\n     */\n    static burn(ticker, amount, options = {}) {\n        // Validate parameters\n        if (ticker == null || ticker === '' || ticker.length === 0) {\n            throw new Error('Ticker cannot be empty');\n        }\n        if (ticker.length > 32) {\n            throw new Error('Ticker cannot exceed 32 characters');\n        }\n        if (amount <= BigInt(0)) {\n            throw new Error('Amount must be positive');\n        }\n        // Create token data\n        const tokenData = {\n            p: 'bsv-20',\n            op: 'burn',\n            tick: ticker,\n            amt: amount.toString()\n        };\n        // Create inscription with token JSON\n        const jsonContent = JSON.stringify(tokenData);\n        const inscription = Inscription.fromText(jsonContent, 'application/bsv-20', options);\n        return new BSV20(tokenData, inscription);\n    }\n    /**\n     * Decodes a BSV-20 token from a script\n     *\n     * @param script - The script containing BSV-20 token data\n     * @returns Decoded BSV-20 token or null if not found/invalid\n     */\n    static decode(script) {\n        try {\n            // First decode as inscription\n            const inscription = Inscription.decode(script);\n            if (inscription == null)\n                return null;\n            // Check if it's BSV-20 token (application/bsv-20 MIME type)\n            if (inscription.file.type !== 'application/bsv-20')\n                return null;\n            // Parse JSON content - use raw content since application/bsv-20 is not recognized as text\n            let jsonText;\n            try {\n                jsonText = Utils.toUTF8(Array.from(inscription.file.content));\n            }\n            catch {\n                return null;\n            }\n            const data = JSON.parse(jsonText);\n            // Validate required protocol fields\n            if (data.p !== 'bsv-20')\n                return null;\n            if (data.op == null || typeof data.op !== 'string')\n                return null;\n            // Parse operation\n            const operation = data.op.toLowerCase();\n            if (!['deploy', 'mint', 'transfer', 'burn'].includes(operation))\n                return null;\n            // Validate operation-specific fields\n            switch (operation) {\n                case 'deploy':\n                    if (data.tick == null || typeof data.tick !== 'string')\n                        return null;\n                    if (data.tick.length === 0 || data.tick.length > 32)\n                        return null;\n                    if (data.max == null || typeof data.max !== 'string')\n                        return null;\n                    try {\n                        const maxSupply = BigInt(data.max);\n                        if (maxSupply <= BigInt(0))\n                            return null;\n                    }\n                    catch {\n                        return null;\n                    }\n                    if (data.dec !== undefined) {\n                        if (typeof data.dec !== 'number' || data.dec < 0 || data.dec > 18)\n                            return null;\n                    }\n                    if (data.lim !== undefined) {\n                        if (typeof data.lim !== 'string')\n                            return null;\n                        try {\n                            const limit = BigInt(data.lim);\n                            if (limit <= BigInt(0))\n                                return null;\n                        }\n                        catch {\n                            return null;\n                        }\n                    }\n                    break;\n                case 'mint':\n                case 'transfer':\n                case 'burn':\n                    if (data.tick == null || typeof data.tick !== 'string')\n                        return null;\n                    if (data.tick.length === 0 || data.tick.length > 32)\n                        return null;\n                    if (data.amt == null || typeof data.amt !== 'string')\n                        return null;\n                    try {\n                        const amount = BigInt(data.amt);\n                        if (amount <= BigInt(0))\n                            return null;\n                    }\n                    catch {\n                        return null;\n                    }\n                    break;\n            }\n            // Create token data structure\n            const tokenData = {\n                p: 'bsv-20',\n                op: operation,\n                amt: data.amt ?? '0'\n            };\n            // Add operation-specific fields\n            if (operation === 'deploy') {\n                tokenData.tick = data.tick;\n                tokenData.max = data.max;\n                if (data.dec !== undefined) {\n                    tokenData.dec = data.dec;\n                }\n                if (data.lim !== undefined) {\n                    tokenData.lim = data.lim;\n                }\n            }\n            else {\n                tokenData.tick = data.tick;\n            }\n            return new BSV20(tokenData, inscription);\n        }\n        catch {\n            return null;\n        }\n    }\n    /**\n     * Creates a locking script containing the BSV-20 token inscription\n     *\n     * @param lockingScript - Optional locking script to append as suffix\n     * @returns A locking script containing the token data\n     */\n    lock(lockingScript) {\n        if (lockingScript != null) {\n            // Create new inscription with the locking script as suffix\n            const options = {\n                parent: this.inscription.parent,\n                scriptPrefix: this.inscription.scriptPrefix,\n                scriptSuffix: new Uint8Array(lockingScript.toBinary())\n            };\n            // Create new inscription with suffix\n            const jsonContent = JSON.stringify(this.tokenData);\n            const newInscription = Inscription.fromText(jsonContent, 'application/bsv-20', options);\n            return newInscription.lock();\n        }\n        return this.inscription.lock();\n    }\n    /**\n     * BSV-20 tokens cannot be unlocked directly as they are data containers\n     *\n     * @throws Error indicating unlock is not supported\n     */\n    unlock() {\n        throw new Error('BSV-20 tokens cannot be unlocked directly');\n    }\n    /**\n     * Gets the token amount as BigInt\n     *\n     * @returns Token amount\n     */\n    getAmount() {\n        return BigInt(this.tokenData.amt);\n    }\n    /**\n     * Gets the token amount as BigInt (concise method)\n     *\n     * @returns Token amount\n     */\n    amount() {\n        return this.getAmount();\n    }\n    /**\n     * Gets the token ticker/symbol\n     *\n     * @returns Token ticker\n     */\n    getTicker() {\n        return this.tokenData.tick;\n    }\n    /**\n     * Gets the token ticker/symbol (concise method)\n     *\n     * @returns Token ticker\n     */\n    ticker() {\n        return this.getTicker();\n    }\n    /**\n     * Gets the number of decimal places (for deploy operations)\n     *\n     * @returns Number of decimals, defaults to 0\n     */\n    getDecimals() {\n        return this.tokenData.dec ?? 0;\n    }\n    /**\n     * Gets the maximum supply (for deploy operations)\n     *\n     * @returns Maximum supply as BigInt or undefined\n     */\n    getMaxSupply() {\n        return this.tokenData.max != null ? BigInt(this.tokenData.max) : undefined;\n    }\n    /**\n     * Gets the limit per mint operation (for deploy operations)\n     *\n     * @returns Limit per mint as BigInt or undefined\n     */\n    getLimitPerMint() {\n        return this.tokenData.lim != null ? BigInt(this.tokenData.lim) : undefined;\n    }\n    /**\n     * Gets the token operation type\n     *\n     * @returns The operation (deploy, mint, transfer, or burn)\n     */\n    getOperation() {\n        return this.tokenData.op;\n    }\n    /**\n     * Gets the token operation type (concise method)\n     *\n     * @returns The operation (deploy, mint, transfer, or burn)\n     */\n    operation() {\n        return this.getOperation();\n    }\n    /**\n     * Checks if this is a deploy operation\n     *\n     * @returns true for deploy operations\n     */\n    isDeploy() {\n        return this.tokenData.op === 'deploy';\n    }\n    /**\n     * Checks if this is a mint operation\n     *\n     * @returns true for mint operations\n     */\n    isMint() {\n        return this.tokenData.op === 'mint';\n    }\n    /**\n     * Checks if this is a transfer operation\n     *\n     * @returns true for transfer operations\n     */\n    isTransfer() {\n        return this.tokenData.op === 'transfer';\n    }\n    /**\n     * Checks if this is a burn operation\n     *\n     * @returns true for burn operations\n     */\n    isBurn() {\n        return this.tokenData.op === 'burn';\n    }\n    /**\n     * Gets the underlying inscription\n     *\n     * @returns The inscription containing the token data\n     */\n    getInscription() {\n        return this.inscription;\n    }\n    /**\n     * Gets the token data as formatted JSON string\n     *\n     * @returns JSON representation of token data\n     */\n    toJSON() {\n        return JSON.stringify(this.tokenData, null, 2);\n    }\n    /**\n     * Validates the token data structure\n     *\n     * @returns true if token data is valid\n     */\n    validate() {\n        try {\n            // Validate basic structure\n            if (this.tokenData.p !== 'bsv-20')\n                return false;\n            if (this.tokenData.op == null)\n                return false;\n            // Validate operation-specific fields\n            switch (this.tokenData.op) {\n                case 'deploy':\n                    if (this.tokenData.tick == null || this.tokenData.tick === '' || this.tokenData.tick.length === 0 || this.tokenData.tick.length > 32) {\n                        return false;\n                    }\n                    if (this.tokenData.max == null || this.tokenData.max === '')\n                        return false;\n                    try {\n                        const maxSupply = BigInt(this.tokenData.max);\n                        if (maxSupply <= BigInt(0))\n                            return false;\n                    }\n                    catch {\n                        return false;\n                    }\n                    if (this.tokenData.dec !== undefined && (this.tokenData.dec < 0 || this.tokenData.dec > 18)) {\n                        return false;\n                    }\n                    if (this.tokenData.lim !== undefined) {\n                        try {\n                            const limit = BigInt(this.tokenData.lim);\n                            if (limit <= BigInt(0))\n                                return false;\n                        }\n                        catch {\n                            return false;\n                        }\n                    }\n                    break;\n                case 'mint':\n                case 'transfer':\n                case 'burn':\n                    if (this.tokenData.tick == null || this.tokenData.tick === '' || this.tokenData.tick.length === 0 || this.tokenData.tick.length > 32) {\n                        return false;\n                    }\n                    if (this.tokenData.amt == null || this.tokenData.amt === '')\n                        return false;\n                    try {\n                        const amount = BigInt(this.tokenData.amt);\n                        if (amount <= BigInt(0))\n                            return false;\n                    }\n                    catch {\n                        return false;\n                    }\n                    break;\n                default:\n                    return false;\n            }\n            return true;\n        }\n        catch {\n            return false;\n        }\n    }\n}\n//# sourceMappingURL=BSV20.js.map",
    "import { Script, Utils } from '@bsv/sdk';\n/**\n * OrdLock PREFIX - sCrypt contract prefix shared with Lock template\n */\nexport const ORDLOCK_PREFIX = Utils.toArray('2097dfd76851bf465e8f715593b217714858bbe9570ff3bd5e33840a34e20ff0262102ba79df5f8ae7604a9830f03c7933028186aede0675a16f025dc4f8be8eec0382201008ce7480da41702918d1ec8e6849ba32b4d65b1e40dc669c31a1e6306b266c0000', 'hex');\n/**\n * OrdLock SUFFIX - contract validation script\n */\nexport const ORDLOCK_SUFFIX = Utils.toArray('615179547a75537a537a537a0079537a75527a527a7575615579008763567901c161517957795779210ac407f0e4bd44bfc207355a778b046225a7068fc59ee7eda43ad905aadbffc800206c266b30e6a1319c66dc401e5bd6b432ba49688eecd118297041da8074ce081059795679615679aa0079610079517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e01007e81517a75615779567956795679567961537956795479577995939521414136d08c5ed2bf3ba048afe6dcaebafeffffffffffffffffffffffffffffff00517951796151795179970079009f63007952799367007968517a75517a75517a7561527a75517a517951795296a0630079527994527a75517a6853798277527982775379012080517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e01205279947f7754537993527993013051797e527e54797e58797e527e53797e52797e57797e0079517a75517a75517a75517a75517a75517a75517a75517a75517a75517a75517a75517a75517a756100795779ac517a75517a75517a75517a75517a75517a75517a75517a75517a7561517a75517a756169587951797e58797eaa577961007982775179517958947f7551790128947f77517a75517a75618777777777777777777767557951876351795779a9876957795779ac777777777777777767006868', 'hex');\n/**\n * Finds the index of a subarray within an array\n */\nfunction indexOf(arr, subArr, fromIndex = 0) {\n    for (let i = fromIndex; i <= arr.length - subArr.length; i++) {\n        let found = true;\n        for (let j = 0; j < subArr.length; j++) {\n            if (arr[i + j] !== subArr[j]) {\n                found = false;\n                break;\n            }\n        }\n        if (found)\n            return i;\n    }\n    return -1;\n}\n/**\n * Reads a Bitcoin varint from a byte array\n * Returns the value and number of bytes consumed\n */\nfunction readVarInt(data, offset) {\n    const first = data[offset];\n    if (first < 0xfd) {\n        return { value: first, bytesRead: 1 };\n    }\n    else if (first === 0xfd) {\n        const value = data[offset + 1] | (data[offset + 2] << 8);\n        return { value, bytesRead: 3 };\n    }\n    else if (first === 0xfe) {\n        const value = data[offset + 1] | (data[offset + 2] << 8) | (data[offset + 3] << 16) | (data[offset + 4] << 24);\n        return { value, bytesRead: 5 };\n    }\n    else {\n        // 0xff - 8 byte value, but we'll just handle up to 4 bytes for simplicity\n        const value = data[offset + 1] | (data[offset + 2] << 8) | (data[offset + 3] << 16) | (data[offset + 4] << 24);\n        return { value, bytesRead: 9 };\n    }\n}\n/**\n * OrdLock - Ordinal Lock template for marketplace listings\n *\n * OrdLock enables trustless ordinal/NFT sales by locking an output with a\n * contract that can only be unlocked by providing payment to a specified address.\n *\n * @example\n * ```typescript\n * // Decode an OrdLock from a script\n * const ordlock = OrdLock.decode(script);\n * if (ordlock) {\n *   console.log(`Seller: ${ordlock.seller}`);\n *   console.log(`Price: ${ordlock.price} satoshis`);\n * }\n * ```\n */\n// eslint-disable-next-line @typescript-eslint/no-extraneous-class\nexport default class OrdLock {\n    /**\n     * Decodes an OrdLock from a script\n     *\n     * @param script - The script to decode\n     * @param mainnet - Whether to use mainnet address prefix (default: true)\n     * @returns Decoded OrdLock data or null if not found/invalid\n     */\n    static decode(script, mainnet = true) {\n        try {\n            const scriptBinary = script.toBinary();\n            // Find PREFIX\n            const prefixIndex = indexOf(scriptBinary, ORDLOCK_PREFIX);\n            if (prefixIndex === -1)\n                return null;\n            // Find SUFFIX after PREFIX\n            const suffixIndex = indexOf(scriptBinary, ORDLOCK_SUFFIX, prefixIndex + ORDLOCK_PREFIX.length);\n            if (suffixIndex === -1)\n                return null;\n            // Extract data between PREFIX and SUFFIX\n            const dataBytes = scriptBinary.slice(prefixIndex + ORDLOCK_PREFIX.length, suffixIndex);\n            if (dataBytes.length === 0)\n                return null;\n            // Parse the data as script chunks\n            const dataScript = Script.fromBinary(dataBytes);\n            const chunks = dataScript.chunks;\n            if (chunks.length < 2)\n                return null;\n            // Chunk 0: seller PKHash (20 bytes)\n            const sellerChunk = chunks[0];\n            if (sellerChunk?.data == null || sellerChunk.data.length !== 20)\n                return null;\n            // Chunk 1: payout TransactionOutput (satoshis + locking script)\n            const payoutChunk = chunks[1];\n            if (payoutChunk?.data == null || payoutChunk.data.length < 9)\n                return null;\n            const payoutData = payoutChunk.data;\n            // Parse TransactionOutput: 8-byte LE satoshis + varint script length + script\n            // Read 8-byte little-endian satoshis\n            let price = BigInt(0);\n            for (let i = 0; i < 8; i++) {\n                price |= BigInt(payoutData[i]) << BigInt(i * 8);\n            }\n            // Convert PKHash to address\n            const addressPrefix = mainnet ? [0x00] : [0x6f];\n            const seller = Utils.toBase58Check(sellerChunk.data, addressPrefix);\n            return {\n                seller,\n                price,\n                payout: Array.from(payoutData)\n            };\n        }\n        catch {\n            return null;\n        }\n    }\n    /**\n     * Checks if a script contains an OrdLock pattern\n     *\n     * @param script - The script to check\n     * @returns true if the script contains OrdLock pattern\n     */\n    static isOrdLock(script) {\n        const scriptBinary = script.toBinary();\n        const prefixIndex = indexOf(scriptBinary, ORDLOCK_PREFIX);\n        if (prefixIndex === -1)\n            return false;\n        const suffixIndex = indexOf(scriptBinary, ORDLOCK_SUFFIX, prefixIndex + ORDLOCK_PREFIX.length);\n        return suffixIndex !== -1;\n    }\n    /**\n     * Checks if an unlocking script indicates a purchase (vs cancellation)\n     *\n     * @param unlockingScript - The unlocking script to check\n     * @returns true if the unlock represents a purchase\n     */\n    static isPurchase(unlockingScript) {\n        const scriptBinary = unlockingScript.toBinary();\n        return indexOf(scriptBinary, ORDLOCK_SUFFIX) !== -1;\n    }\n}\n//# sourceMappingURL=OrdLock.js.map",
    "import { Script, Utils } from '@bsv/sdk';\n/**\n * Lock PREFIX - sCrypt contract prefix shared with OrdLock template\n */\nexport const LOCK_PREFIX = Utils.toArray('2097dfd76851bf465e8f715593b217714858bbe9570ff3bd5e33840a34e20ff0262102ba79df5f8ae7604a9830f03c7933028186aede0675a16f025dc4f8be8eec0382201008ce7480da41702918d1ec8e6849ba32b4d65b1e40dc669c31a1e6306b266c0000', 'hex');\n/**\n * Lock SUFFIX - time-lock contract validation script\n */\nexport const LOCK_SUFFIX = Utils.toArray('610079040065cd1d9f690079547a75537a537a537a5179537a75527a527a7575615579014161517957795779210ac407f0e4bd44bfc207355a778b046225a7068fc59ee7eda43ad905aadbffc800206c266b30e6a1319c66dc401e5bd6b432ba49688eecd118297041da8074ce081059795679615679aa0079610079517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e01007e81517a75615779567956795679567961537956795479577995939521414136d08c5ed2bf3ba048afe6dcaebafeffffffffffffffffffffffffffffff00517951796151795179970079009f63007952799367007968517a75517a75517a7561527a75517a517951795296a0630079527994527a75517a6853798277527982775379012080517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e01205279947f7754537993527993013051797e527e54797e58797e527e53797e52797e57797e0079517a75517a75517a75517a75517a75517a75517a75517a75517a75517a75517a75517a75517a756100795779ac517a75517a75517a75517a75517a75517a75517a75517a75517a7561517a75517a756169557961007961007982775179517954947f75517958947f77517a75517a756161007901007e81517a7561517a7561040065cd1d9f6955796100796100798277517951790128947f755179012c947f77517a75517a756161007901007e81517a7561517a756105ffffffff009f69557961007961007982775179517954947f75517958947f77517a75517a756161007901007e81517a7561517a75615279a2695679a95179876957795779ac7777777777777777', 'hex');\n/**\n * Finds the index of a subarray within an array\n */\nfunction indexOf(arr, subArr, fromIndex = 0) {\n    for (let i = fromIndex; i <= arr.length - subArr.length; i++) {\n        let found = true;\n        for (let j = 0; j < subArr.length; j++) {\n            if (arr[i + j] !== subArr[j]) {\n                found = false;\n                break;\n            }\n        }\n        if (found)\n            return i;\n    }\n    return -1;\n}\n/**\n * Checks if an array contains a subarray\n */\nfunction contains(arr, subArr, fromIndex = 0) {\n    return indexOf(arr, subArr, fromIndex) !== -1;\n}\n/**\n * Lock - Time-lock template for locking outputs until a specific block height or timestamp\n *\n * The Lock template enables creating outputs that can only be spent after a certain\n * block height or Unix timestamp has been reached.\n *\n * @example\n * ```typescript\n * // Decode a Lock from a script\n * const lock = Lock.decode(script);\n * if (lock) {\n *   console.log(`Address: ${lock.address}`);\n *   console.log(`Locked until: ${lock.until}`);\n * }\n * ```\n */\n// eslint-disable-next-line @typescript-eslint/no-extraneous-class\nexport default class Lock {\n    /**\n     * Decodes a Lock from a script\n     *\n     * @param script - The script to decode\n     * @param mainnet - Whether to use mainnet address prefix (default: true)\n     * @returns Decoded Lock data or null if not found/invalid\n     */\n    static decode(script, mainnet = true) {\n        try {\n            const scriptBinary = script.toBinary();\n            // Find PREFIX\n            const prefixIndex = indexOf(scriptBinary, LOCK_PREFIX);\n            if (prefixIndex === -1)\n                return null;\n            // Check that SUFFIX exists somewhere after PREFIX\n            if (!contains(scriptBinary, LOCK_SUFFIX, prefixIndex))\n                return null;\n            // Extract data starting after PREFIX\n            let pos = prefixIndex + LOCK_PREFIX.length;\n            // Parse the data as script chunks\n            const remainingBytes = scriptBinary.slice(pos);\n            const dataScript = Script.fromBinary(remainingBytes);\n            const chunks = dataScript.chunks;\n            if (chunks.length < 2)\n                return null;\n            // Chunk 0: address PKHash (20 bytes)\n            const addressChunk = chunks[0];\n            if (addressChunk?.data == null || addressChunk.data.length !== 20)\n                return null;\n            // Chunk 1: until value (variable length, little-endian)\n            const untilChunk = chunks[1];\n            if (untilChunk?.data == null)\n                return null;\n            // Read little-endian uint32 (pad to 4 bytes if needed)\n            const untilData = untilChunk.data;\n            const padded = new Uint8Array(4);\n            for (let i = 0; i < Math.min(untilData.length, 4); i++) {\n                padded[i] = untilData[i];\n            }\n            const until = padded[0] | (padded[1] << 8) | (padded[2] << 16) | (padded[3] << 24);\n            // Convert PKHash to address\n            const addressPrefix = mainnet ? [0x00] : [0x6f];\n            const address = Utils.toBase58Check(addressChunk.data, addressPrefix);\n            return {\n                address,\n                until: until >>> 0 // Ensure unsigned\n            };\n        }\n        catch {\n            return null;\n        }\n    }\n    /**\n     * Checks if a script contains a Lock pattern\n     *\n     * @param script - The script to check\n     * @returns true if the script contains Lock pattern\n     */\n    static isLock(script) {\n        const scriptBinary = script.toBinary();\n        const prefixIndex = indexOf(scriptBinary, LOCK_PREFIX);\n        if (prefixIndex === -1)\n            return false;\n        return contains(scriptBinary, LOCK_SUFFIX, prefixIndex);\n    }\n}\n//# sourceMappingURL=Lock.js.map",
    "import { OP, Utils } from '@bsv/sdk';\n/**\n * Cosign - Multi-signature template requiring owner + cosigner authorization\n *\n * The Cosign template creates outputs that require both the owner's signature\n * and a cosigner's signature to spend. The owner is identified by their public\n * key hash (address), while the cosigner is identified by their full public key.\n *\n * Script pattern:\n * OP_DUP OP_HASH160 <20-byte PKHash> OP_EQUALVERIFY OP_CHECKSIGVERIFY <33-byte pubkey> OP_CHECKSIG\n *\n * @example\n * ```typescript\n * // Decode a Cosign from a script\n * const cosign = Cosign.decode(script);\n * if (cosign) {\n *   console.log(`Owner address: ${cosign.address}`);\n *   console.log(`Cosigner pubkey: ${cosign.cosigner}`);\n * }\n * ```\n */\n// eslint-disable-next-line @typescript-eslint/no-extraneous-class\nexport default class Cosign {\n    /**\n     * Decodes a Cosign from a script\n     *\n     * @param script - The script to decode\n     * @param mainnet - Whether to use mainnet address prefix (default: true)\n     * @returns Decoded Cosign data or null if not found/invalid\n     */\n    static decode(script, mainnet = true) {\n        try {\n            const chunks = script.chunks;\n            // Look for pattern: OP_DUP OP_HASH160 <20-byte PKHash> OP_EQUALVERIFY OP_CHECKSIGVERIFY <33-byte pubkey> OP_CHECKSIG\n            for (let i = 0; i <= chunks.length - 7; i++) {\n                if (chunks[i].op === OP.OP_DUP &&\n                    chunks[i + 1].op === OP.OP_HASH160 &&\n                    chunks[i + 2].data?.length === 20 &&\n                    chunks[i + 3].op === OP.OP_EQUALVERIFY &&\n                    chunks[i + 4].op === OP.OP_CHECKSIGVERIFY &&\n                    chunks[i + 5].data?.length === 33 &&\n                    chunks[i + 6].op === OP.OP_CHECKSIG) {\n                    // Convert PKHash to address (we already verified length, so data is defined)\n                    const addressPrefix = mainnet ? [0x00] : [0x6f];\n                    const address = Utils.toBase58Check(chunks[i + 2].data, addressPrefix);\n                    // Convert cosigner pubkey to hex (we already verified length, so data is defined)\n                    const cosigner = Utils.toHex(chunks[i + 5].data);\n                    return {\n                        address,\n                        cosigner\n                    };\n                }\n            }\n            return null;\n        }\n        catch {\n            return null;\n        }\n    }\n    /**\n     * Checks if a script contains a Cosign pattern\n     *\n     * @param script - The script to check\n     * @returns true if the script contains Cosign pattern\n     */\n    static isCosign(script) {\n        return Cosign.decode(script) !== null;\n    }\n}\n//# sourceMappingURL=Cosign.js.map",
    "import { LockingScript, UnlockingScript, OP, Hash, PublicKey, TransactionSignature, Signature, Utils } from \"@bsv/sdk\";\nfunction concatPubkeys(pubkeys) {\n    return pubkeys.map((p) => p.toDER()).reduce((a, b) => a.concat(b), []);\n}\nfunction numberFromScriptChunk(chunk) {\n    let returnNum;\n    if (!chunk.data) {\n        returnNum = 1 + chunk.op - OP.OP_1;\n    }\n    else {\n        const reader = new Utils.Reader(chunk.data);\n        const threshold = reader.readInt64LEBn();\n        returnNum = threshold.toNumber();\n    }\n    return returnNum;\n}\nexport class MultiSigPubkeyHash {\n    static address(pubkeys, threshold) {\n        if (threshold < 1 || threshold > pubkeys.length)\n            throw new Error('threshold must be between 1 and the number of pubkeys');\n        if (!pubkeys || pubkeys.length < 2 || pubkeys.length < threshold)\n            throw new Error(`at least ${threshold || 2} pubkeys are required`);\n        const concat = concatPubkeys(pubkeys);\n        const hash = Hash.hash160(concat);\n        const writer = new Utils.Writer();\n        writer.write(hash);\n        writer.writeVarIntNum(threshold);\n        writer.writeVarIntNum(pubkeys.length);\n        const data = writer.toArray();\n        return Utils.toBase58Check(data, [0x98]);\n    }\n    static async addressBRC29(wallet, counterparties, keyID, threshold) {\n        const pubkeys = await Promise.all(counterparties.map(async (counterparty) => {\n            const { publicKey } = await wallet.getPublicKey({\n                protocolID: [1, \"multi sig brc29\"],\n                keyID,\n                counterparty\n            });\n            return PublicKey.fromString(publicKey);\n        }));\n        return { pubkeys: pubkeys.map(p => p.toString()), address: this.address(pubkeys, threshold) };\n    }\n    static thresholdAndTotalFromAddress(address) {\n        const h = Utils.fromBase58Check(address);\n        if (h.prefix[0] !== 0x98) {\n            throw new Error('only P2MSH is supported, set your prefix byte to 0x98');\n        }\n        const reader = new Utils.Reader(h.data);\n        const hash = reader.read(20);\n        const threshold = reader.readVarIntNum();\n        const total = reader.readVarIntNum();\n        return { hash, threshold, total };\n    }\n    lock(address, pubkeys, threshold = 1) {\n        let hash;\n        let total = pubkeys?.length || 0;\n        if (address) {\n            if (typeof address !== 'string')\n                throw new Error('address must be a string');\n            const result = MultiSigPubkeyHash.thresholdAndTotalFromAddress(address);\n            hash = result.hash;\n            total = result.total;\n            threshold = result.threshold;\n        }\n        else {\n            if (!pubkeys || total < 2)\n                throw new Error(`at least 2 pubkeys are required`);\n            const concat = concatPubkeys(pubkeys);\n            hash = Hash.hash160(concat);\n        }\n        if (!threshold || threshold < 1 || threshold > total)\n            throw new Error('threshold must be between 1 and the number of pubkeys');\n        if (total > 10)\n            throw new Error('total must be less than or equal to 10');\n        const script = new LockingScript();\n        for (let i = 0; i < total - 1; i++) {\n            script.writeOpCode(OP.OP_CAT);\n        }\n        script\n            .writeOpCode(OP.OP_DUP)\n            .writeOpCode(OP.OP_HASH160)\n            .writeBin(hash)\n            .writeOpCode(OP.OP_EQUALVERIFY)\n            .writeNumber(threshold)\n            .writeOpCode(OP.OP_SWAP);\n        for (let i = 0; i < total - 1; i++) {\n            script\n                .writeNumber(33)\n                .writeOpCode(OP.OP_SPLIT);\n        }\n        script.writeNumber(total);\n        script.writeOpCode(OP.OP_CHECKMULTISIG);\n        return script;\n    }\n    unlock(wallet, customInstructions, workingUnlockingScript, signOutputs = \"all\", anyoneCanPay = false, sourceSatoshis, lockingScript) {\n        return {\n            sign: async (tx, inputIndex) => {\n                if (!workingUnlockingScript) {\n                    workingUnlockingScript = new UnlockingScript();\n                    workingUnlockingScript.writeOpCode(OP.OP_0);\n                    customInstructions.pubkeys.forEach((pubkey) => {\n                        workingUnlockingScript.writeBin(PublicKey.fromString(pubkey).toDER());\n                    });\n                }\n                let signatureScope = TransactionSignature.SIGHASH_FORKID;\n                if (signOutputs === \"all\") {\n                    signatureScope |= TransactionSignature.SIGHASH_ALL;\n                }\n                if (signOutputs === \"none\") {\n                    signatureScope |= TransactionSignature.SIGHASH_NONE;\n                }\n                if (signOutputs === \"single\") {\n                    signatureScope |= TransactionSignature.SIGHASH_SINGLE;\n                }\n                if (anyoneCanPay) {\n                    signatureScope |= TransactionSignature.SIGHASH_ANYONECANPAY;\n                }\n                const input = tx.inputs[inputIndex];\n                const otherInputs = tx.inputs.filter((_, index) => index !== inputIndex);\n                const sourceTXID = input.sourceTXID\n                    ? input.sourceTXID\n                    : input.sourceTransaction?.id(\"hex\");\n                if (!sourceTXID) {\n                    throw new Error(\"The input sourceTXID or sourceTransaction is required for transaction signing.\");\n                }\n                sourceSatoshis ||= input.sourceTransaction?.outputs[input.sourceOutputIndex].satoshis;\n                if (!sourceSatoshis) {\n                    throw new Error(\"The sourceSatoshis or input sourceTransaction is required for transaction signing.\");\n                }\n                lockingScript ||= input.sourceTransaction?.outputs[input.sourceOutputIndex].lockingScript;\n                if (!lockingScript) {\n                    throw new Error(\"The lockingScript or input sourceTransaction is required for transaction signing.\");\n                }\n                const preimage = TransactionSignature.format({\n                    sourceTXID,\n                    sourceOutputIndex: input.sourceOutputIndex,\n                    sourceSatoshis,\n                    transactionVersion: tx.version,\n                    otherInputs,\n                    inputIndex,\n                    outputs: tx.outputs,\n                    inputSequence: input.sequence || 0xffffffff,\n                    subscript: lockingScript,\n                    lockTime: tx.lockTime,\n                    scope: signatureScope,\n                });\n                const hashToDirectlySign = Hash.hash256(preimage);\n                const { signature } = await wallet.createSignature({\n                    hashToDirectlySign,\n                    protocolID: [1, \"multi sig brc29\"],\n                    counterparty: customInstructions.counterparty,\n                    keyID: customInstructions.keyID,\n                });\n                const s = Signature.fromDER(signature);\n                const sig = new TransactionSignature(s.r, s.s, signatureScope);\n                const sigForScript = sig.toChecksigFormat();\n                workingUnlockingScript.writeBin(sigForScript);\n                const chunkforSig = workingUnlockingScript.chunks.pop();\n                // add it to the array before the pubkeys, pushing the other content to the right\n                workingUnlockingScript.chunks.splice(workingUnlockingScript.chunks.length - customInstructions.pubkeys.length, 0, chunkforSig);\n                return workingUnlockingScript;\n            },\n            estimateLength: (tx, inputIndex) => {\n                let numberOfPubkeys = 2;\n                let numberOfSignatures = 1;\n                const staticLength = 1;\n                const input = tx.inputs[inputIndex];\n                const lockingScript = input.sourceTransaction?.outputs[input.sourceOutputIndex].lockingScript;\n                if (!lockingScript) {\n                    return Promise.resolve(1000); // guess\n                }\n                const totalChunk = lockingScript?.chunks[lockingScript.chunks.length - 2];\n                numberOfPubkeys = numberFromScriptChunk(totalChunk);\n                const thresholdPos = lockingScript.chunks.map(chunk => chunk.op === OP.OP_EQUALVERIFY).indexOf(true) + 1;\n                const thresholdChunk = lockingScript?.chunks[thresholdPos];\n                numberOfSignatures = numberFromScriptChunk(thresholdChunk);\n                return Promise.resolve(staticLength + (numberOfSignatures * 74) + (numberOfPubkeys * 34));\n            }\n        };\n    }\n}\n//# sourceMappingURL=MultiSigPubkeyHash.js.map",
    "import {\n\tP2PKH,\n\ttype PrivateKey,\n\tSatoshisPerKilobyte,\n\tScript,\n\tTransaction,\n\ttype TransactionOutput,\n\tUtils,\n} from \"@bsv/sdk\";\nimport { DEFAULT_SAT_PER_KB } from \"./constants\";\nimport { signData } from \"./signData\";\nimport OrdP2PKH from \"./templates/ordP2pkh\";\nimport type { ChangeResult, SendUtxosConfig, Utxo } from \"./types\";\nimport { inputFromB64Utxo } from \"./utils/utxo\";\n\n/**\n * Sends utxos to the given destination\n * @param {SendUtxosConfig} config - Configuration object for sending utxos\n * @param {Utxo[]} config.utxos - Utxos to spend (with base64 encoded scripts)\n * @param {PrivateKey} config.paymentPk - Private key to sign utxos\n * @param {Payment[]} config.payments - Array of payments with addresses and amounts\n * @param {number} [config.satsPerKb] - (Optional) Satoshis per kilobyte for fee calculation. Default is DEFAULT_SAT_PER_KB\n * @param {string} [config.changeAddress] - (Optional) Address to send change to. If not provided, defaults to paymentPk address\n * @param {string} [config.metaData] - (Optional) Metadata to include in OP_RETURN of the payment output\n * @returns {Promise<ChangeResult>} - Returns a ChangeResult: payChange, tx, and spentOutputs\n */\nexport const sendUtxos = async (\n\tconfig: SendUtxosConfig,\n): Promise<ChangeResult> => {\n\tconst {\n\t\tutxos,\n\t\tpaymentPk,\n\t\tpayments,\n\t\tsatsPerKb = DEFAULT_SAT_PER_KB,\n\t\tmetaData,\n\t\tsigner,\n\t\tsignInputs = true,\n\t} = config;\n\n\tconst modelOrFee = new SatoshisPerKilobyte(satsPerKb);\n\n\tlet tx = new Transaction();\n\n\t// Outputs\n\tfor (const payment of payments) {\n\t\tconst sendTxOut: TransactionOutput = {\n\t\t\tsatoshis: payment.amount,\n\t\t\tlockingScript: new OrdP2PKH().lock(payment.to, undefined, metaData),\n\t\t};\n\t\ttx.addOutput(sendTxOut);\n\t}\n\n\t// Inputs\n\tlet totalSatsIn = 0n;\n\tconst totalSatsOut = tx.outputs.reduce(\n\t\t(total, out) => total + (out.satoshis || 0),\n\t\t0,\n\t);\n\n\tlet fee = 0;\n\n\tif(signer) {\n\t\tconst utxo = utxos.pop() as Utxo\n\t\tif (signInputs) {\n\t\t\tconst payKeyToUse = utxo.pk || paymentPk;\n\t\t\tif(!payKeyToUse) {\n\t\t\t\tthrow new Error(\"Private key is required to sign the transaction\");\n\t\t\t}\n\t\t\ttx.addInput(inputFromB64Utxo(utxo, new P2PKH().unlock(\n\t\t\t\tpayKeyToUse,\n\t\t\t\t\"all\",\n\t\t\t\ttrue,\n\t\t\t\tutxo.satoshis,\n\t\t\t\tScript.fromBinary(Utils.toArray(utxo.script, 'base64'))\n\t\t\t)));\n\t\t} else {\n\t\t\ttx.addInput(inputFromB64Utxo(utxo));\n\t\t}\n\t\ttotalSatsIn += BigInt(utxo.satoshis);\n\t\ttx = await signData(tx, signer);\n\t\t// Calculate fee after signing since it adds OP_RETURN outputs\n\t\tfee = await modelOrFee.computeFee(tx);\n\t}\n\tfor (const utxo of utxos) {\n\t\tif (signInputs) {\n\t\t\tconst payKeyToUse = utxo.pk || paymentPk;\n\t\t\tif (!payKeyToUse) {\n\t\t\t\tthrow new Error(\"Private key is required to sign the utxos\");\n\t\t\t}\n\t\t\tconst input = inputFromB64Utxo(utxo, new P2PKH().unlock(\n\t\t\t\tpayKeyToUse,\n\t\t\t\t\"all\",\n\t\t\t\ttrue,\n\t\t\t\tutxo.satoshis,\n\t\t\t\tScript.fromBinary(Utils.toArray(utxo.script, 'base64'))\n\t\t\t));\n\t\t\ttx.addInput(input);\n\t\t} else {\n\t\t\ttx.addInput(inputFromB64Utxo(utxo));\n\t\t}\n\n\t\t// stop adding inputs if the total amount is enough\n\t\ttotalSatsIn += BigInt(utxo.satoshis);\n\t\tfee = await modelOrFee.computeFee(tx);\n\n\t\tif (totalSatsIn >= totalSatsOut + fee) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// make sure we have enough\n\tif (totalSatsIn < totalSatsOut + fee) {\n\t\tthrow new Error(\n\t\t\t`Not enough funds to send. Total sats in: ${totalSatsIn}, Total sats out: ${totalSatsOut}, Fee: ${fee}`,\n\t\t);\n\t}\n\n  // Change\n\tlet payChange: Utxo | undefined;\n  // if we need to send change, add it to the outputs\n\tif (totalSatsIn > totalSatsOut + fee) {\n    const changeAddress = config.changeAddress || paymentPk?.toAddress();\n    if(!changeAddress) {\n      throw new Error(\"Either changeAddress or paymentPk is required\");\n    }\n    const changeScript = new P2PKH().lock(changeAddress);\n\t\tconst changeOut: TransactionOutput = {\n\t\t\tlockingScript: changeScript,\n\t\t\tchange: true,\n\t\t};\n\t\tpayChange = {\n\t\t\ttxid: \"\", // txid is not known yet\n\t\t\tvout: tx.outputs.length,\n\t\t\tsatoshis: 0, // change output amount is not known yet\n\t\t\tscript: Buffer.from(changeScript.toHex(), \"hex\").toString(\"base64\"),\n\t\t};\n\t\ttx.addOutput(changeOut);\n\t} else if (totalSatsIn < totalSatsOut + fee) {\n\t\tconsole.log(\"No change needed\");\n\t}\n\n\t// Calculate fee\n\tawait tx.fee(modelOrFee);\n\n\t// Sign the transaction (if signInputs is true)\n\tif (signInputs) {\n\t\tawait tx.sign();\n\t}\n\n\tconst payChangeOutIdx = tx.outputs.findIndex((o) => o.change);\n\tif (payChangeOutIdx !== -1) {\n\t\tconst changeOutput = tx.outputs[payChangeOutIdx];\n\t\tpayChange = {\n\t\t\tsatoshis: changeOutput.satoshis as number,\n\t\t\ttxid: tx.id(\"hex\") as string,\n\t\t\tvout: payChangeOutIdx,\n\t\t\tscript: Buffer.from(changeOutput.lockingScript.toBinary()).toString(\n\t\t\t\t\"base64\",\n\t\t\t),\n\t\t};\n\t}\n\n\tif (payChange) {\n\t\tconst changeOutput = tx.outputs[tx.outputs.length - 1];\n\t\tpayChange.satoshis = changeOutput.satoshis as number;\n\t\tpayChange.txid = tx.id(\"hex\") as string;\n\t}\n\n\treturn {\n\t\ttx,\n\t\tspentOutpoints: tx.inputs.map(\n\t\t\t(i) => `${i.sourceTXID}_${i.sourceOutputIndex}`,\n\t\t),\n\t\tpayChange,\n\t};\n};\n",
    "import {\n\tP2PKH,\n\tSatoshisPerKilobyte,\n\tScript,\n\tTransaction,\n\tUtils,\n} from \"@bsv/sdk\";\nimport { DEFAULT_SAT_PER_KB } from \"./constants\";\nimport OrdP2PKH, { applyInscription } from \"./templates/ordP2pkh\";\nimport {\n\tTokenType,\n\ttype TokenUtxo,\n\ttype TransferBSV20Inscription,\n\ttype TransferBSV21Inscription,\n\ttype TransferOrdTokensConfig,\n\ttype TokenChangeResult,\n\ttype TransferTokenInscription,\n\ttype Utxo,\n\tTokenInputMode,\n\ttype TokenSplitConfig,\n\ttype PreMAP,\n} from \"./types\";\nimport { inputFromB64Utxo } from \"./utils/utxo\";\nimport { signData } from \"./signData\";\nimport stringifyMetaData from \"./utils/subtypeData\";\nimport { ReturnTypes, toToken, toTokenSat } from \"satoshi-token\";\n\n/**\n * Transfer tokens to a destination\n * @param {TransferOrdTokensConfig} config - Configuration object for transferring tokens\n * @param {TokenType} config.protocol - Token protocol. Must be TokenType.BSV20 or TokenType.BSV21\n * @param {string} config.tokenID - Token ID. Either the tick or id value depending on the protocol\n * @param {Utxo[]} config.utxos - Payment Utxos available to spend. Will only consume what is needed.\n * @param {TokenUtxo[]} config.inputTokens - Token utxos to spend\n * @param {Distribution[]} config.distributions - Array of destinations with addresses and amounts\n * @param {PrivateKey} config.paymentPk - Private key to sign paymentUtxos\n * @param {PrivateKey} config.ordPk - Private key to sign ordinals\n * @param {decimals} config.decimals - Number of decimal places for the token\n * @param {string} [config.changeAddress] - Optional. Address to send payment change to, if any. If not provided, defaults to paymentPk address\n * @param {string} [config.tokenChangeAddress] - Optional. Address to send token change to, if any. If not provided, defaults to ordPk address\n * @param {number} [config.satsPerKb] - Optional. Satoshis per kilobyte for fee calculation. Default is DEFAULT_SAT_PER_KB\n * @param {PreMAP} [config.metaData] - Optional. MAP (Magic Attribute Protocol) metadata to include in inscriptions\n * @param {LocalSigner | RemoteSigner} [config.signer] - Optional. Signer object to sign the transaction\n * @param {Payment[]} [config.additionalPayments] - Optional. Additional payments to include in the transaction\n * @param {TokenInputMode} [config.tokenInputMode] - Optional. \"all\" or \"needed\". Default is \"needed\"\n * @param {TokenSplitConfig} [config.tokenSplitConfig] - Optional. Configuration object for splitting token change\n * @param {burn} [config.burn] - Optional. Set to true to burn the tokens.\n * @returns {Promise<TokenChangeResult>} Transaction with token transfer outputs\n */\nexport const transferOrdTokens = async (\n\tconfig: TransferOrdTokensConfig,\n): Promise<TokenChangeResult> => {\n\tconst {\n\t\tprotocol,\n\t\ttokenID,\n\t\tutxos,\n\t\tinputTokens,\n\t\tdistributions,\n\t\tpaymentPk,\n\t\tordPk,\n\t\tsatsPerKb = DEFAULT_SAT_PER_KB,\n\t\tmetaData,\n\t\tsigner,\n\t\tdecimals,\n\t\tadditionalPayments = [],\n\t\tburn = false,\n\t\ttokenInputMode = TokenInputMode.Needed,\n\t\tsplitConfig = {\n\t\t\toutputs: 1,\n\t\t\tomitMetaData: false,\n\t\t},\n\t\tsignInputs = true,\n\t} = config;\n\n\t// Ensure these inputs are for the expected token\n\tif (!inputTokens.every((token) => token.id === tokenID)) {\n\t\tthrow new Error(\"Input tokens do not match the provided tokenID\");\n\t}\n\n\t// calculate change amount\n\tlet changeTsats = 0n;\n\tlet totalTsatIn = 0n;\n\tlet totalTsatOut = 0n;\n\tconst totalAmtNeeded = distributions.reduce(\n\t\t(acc, dist) => acc + toTokenSat(dist.tokens, decimals, ReturnTypes.BigInt),\n\t\t0n,\n\t);\n\n\tconst modelOrFee = new SatoshisPerKilobyte(satsPerKb);\n\tlet tx = new Transaction();\n\n\t// Handle token inputs based on tokenInputMode\n\tlet tokensToUse: TokenUtxo[];\n\tif (tokenInputMode === TokenInputMode.All) {\n\t\ttokensToUse = inputTokens;\n\t\ttotalTsatIn = inputTokens.reduce(\n\t\t\t(acc, token) => acc + BigInt(token.amt),\n\t\t\t0n,\n\t\t);\n\t} else {\n\t\ttokensToUse = [];\n\t\tfor (const token of inputTokens) {\n\t\t\ttokensToUse.push(token);\n\t\t\ttotalTsatIn += BigInt(token.amt);\n\t\t\tif (totalTsatIn >= totalAmtNeeded) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (totalTsatIn < totalAmtNeeded) {\n\t\t\tthrow new Error(\"Not enough tokens to satisfy the transfer amount\");\n\t\t}\n\t}\n\n\tfor (const token of tokensToUse) {\n\t\tif (signInputs) {\n\t\t\tconst ordKeyToUse = token.pk || ordPk;\n\t\t\tif(!ordKeyToUse) {\n\t\t\t\tthrow new Error(\"Private key required for token input\");\n\t\t\t}\n\t\t\tconst inputScriptBinary = Utils.toArray(token.script, \"base64\");\n\t\t\tconst inputScript = Script.fromBinary(inputScriptBinary);\n\t\t\ttx.addInput(\n\t\t\t\tinputFromB64Utxo(\n\t\t\t\t\ttoken,\n\t\t\t\t\tnew OrdP2PKH().unlock(ordKeyToUse, \"all\", true, token.satoshis, inputScript),\n\t\t\t\t),\n\t\t\t);\n\t\t} else {\n\t\t\ttx.addInput(inputFromB64Utxo(token));\n\t\t}\n\t}\n\n\t// remove any undefined fields from metadata\n\tif (metaData) {\n\t\tfor (const key of Object.keys(metaData)) {\n\t\t\tif (metaData[key] === undefined) {\n\t\t\t\tdelete metaData[key];\n\t\t\t}\n\t\t}\n\t}\n\n\t// build destination inscriptions\n\tfor (const dest of distributions) {\n\t\tconst bigAmt = toTokenSat(dest.tokens, decimals, ReturnTypes.BigInt);\n    \n\t\tconst transferInscription: TransferTokenInscription = {\n\t\t\tp: \"bsv-20\",\n\t\t\top: burn ? \"burn\" : \"transfer\",\n\t\t\tamt: bigAmt.toString(),\n\t\t};\n\t\tlet inscriptionObj: TransferBSV20Inscription | TransferBSV21Inscription;\n\t\tif (protocol === TokenType.BSV20) {\n\t\t\tinscriptionObj = {\n\t\t\t\t...transferInscription,\n\t\t\t\ttick: tokenID,\n\t\t\t} as TransferBSV20Inscription;\n\t\t} else if (protocol === TokenType.BSV21) {\n\t\t\tinscriptionObj = {\n\t\t\t\t...transferInscription,\n\t\t\t\tid: tokenID,\n\t\t\t} as TransferBSV21Inscription;\n\t\t} else {\n\t\t\tthrow new Error(\"Invalid protocol\");\n\t\t}\n\n\t\tconst inscription = {\n\t\t\tdataB64: Buffer.from(JSON.stringify(inscriptionObj)).toString(\"base64\"),\n\t\t\tcontentType: \"application/bsv-20\",\n\t\t}\n\t\tconst lockingScript = typeof dest.address === 'string' ?\n\t\t\tnew OrdP2PKH().lock(\n\t\t\t\tdest.address,\n\t\t\t\tinscription,\n\t\t\t\t// when present, include metadata on each distribution if omit is not specified\n\t\t\t\tdest.omitMetaData ? undefined : stringifyMetaData(metaData),\n\t\t\t) :\n\t\t\tapplyInscription(dest.address, inscription);\n\n\t\ttx.addOutput({\n\t\t\tsatoshis: 1,\n\t\t\tlockingScript,\n\t\t});\n\t\ttotalTsatOut += bigAmt;\n\t}\n\n\tchangeTsats = totalTsatIn - totalTsatOut;\n\t\n\t// check that you have enough tokens to send and return change\n\tif (changeTsats < 0n) {\n\t\tthrow new Error(\"Not enough tokens to send\");\n\t}\n\n\tlet tokenChange: TokenUtxo[] = [];\n\tif (changeTsats > 0n) {\n    const tokenChangeAddress = config.tokenChangeAddress || ordPk?.toAddress();\n\t\tif(!tokenChangeAddress) {\n\t\t\tthrow new Error(\"ordPk or changeAddress required for token change\");\n\t\t}\n\t\ttokenChange = splitChangeOutputs(\n\t\t\ttx,\n\t\t\tchangeTsats,\n\t\t\tprotocol,\n\t\t\ttokenID,\n\t\t\ttokenChangeAddress,\n\t\t\tmetaData,\n\t\t\tsplitConfig,\n      \t\tdecimals,\n\t\t);\n\t}\n\n\t// Add additional payments if any\n\tfor (const p of additionalPayments) {\n\t\ttx.addOutput({\n\t\t\tsatoshis: p.amount,\n\t\t\tlockingScript: new P2PKH().lock(p.to),\n\t\t});\n\t}\n\n\t// add change to the outputs\n\tlet payChange: Utxo | undefined;\n  const changeAddress = config.changeAddress || paymentPk?.toAddress();\n\tif (!changeAddress) {\n\t\tthrow new Error(\"paymentPk or changeAddress required for payment change\");\n\t}\n\tconst changeScript = new P2PKH().lock(changeAddress);\n\tconst changeOut = {\n\t\tlockingScript: changeScript,\n\t\tchange: true,\n\t};\n\ttx.addOutput(changeOut);\n\n\tlet totalSatsIn = 0n;\n\tconst totalSatsOut = tx.outputs.reduce(\n\t\t(total, out) => total + BigInt(out.satoshis || 0),\n\t\t0n,\n\t);\n\tlet fee = 0;\n\tfor (const utxo of utxos) {\n\t\tif (signInputs) {\n\t\t\tconst payKeyToUse = utxo.pk || paymentPk;\n\t\t\tif(!payKeyToUse) {\n\t\t\t\tthrow new Error(\"paymentPk required for payment utxo\");\n\t\t\t}\n\t\t\tconst input = inputFromB64Utxo(\n\t\t\t\tutxo,\n\t\t\t\tnew P2PKH().unlock(\n\t\t\t\t\tpayKeyToUse,\n\t\t\t\t\t\"all\",\n\t\t\t\t\ttrue,\n\t\t\t\t\tutxo.satoshis,\n\t\t\t\t\tScript.fromBinary(Utils.toArray(utxo.script, \"base64\")),\n\t\t\t\t),\n\t\t\t);\n\t\t\ttx.addInput(input);\n\t\t} else {\n\t\t\ttx.addInput(inputFromB64Utxo(utxo));\n\t\t}\n\t\t// stop adding inputs if the total amount is enough\n\t\ttotalSatsIn += BigInt(utxo.satoshis);\n\t\tfee = await modelOrFee.computeFee(tx);\n\n\t\tif (totalSatsIn >= totalSatsOut + BigInt(fee)) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// make sure we have enough\n\tif (totalSatsIn < totalSatsOut + BigInt(fee)) {\n\t\tthrow new Error(\n\t\t\t`Not enough funds to transfer tokens. Total sats in: ${totalSatsIn}, Total sats out: ${totalSatsOut}, Fee: ${fee}`,\n\t\t);\n\t}\n\n\tif (signer) {\n\t\ttx = await signData(tx, signer);\n\t}\n\n\t// estimate the cost of the transaction and assign change value\n\tawait tx.fee(modelOrFee);\n\n\t// Sign the transaction (if signInputs is true)\n\tif (signInputs) {\n\t\tawait tx.sign();\n\t}\n\n\t// assign txid to tokenChange outputs\n\tconst txid = tx.id(\"hex\") as string;\n\tfor (const change of tokenChange) {\n\t\tchange.txid = txid;\n\t}\n\n\t// check for change\n\tconst payChangeOutIdx = tx.outputs.findIndex((o) => o.change);\n\tif (payChangeOutIdx !== -1) {\n\t\tconst changeOutput = tx.outputs[payChangeOutIdx];\n\t\tpayChange = {\n\t\t\tsatoshis: changeOutput.satoshis as number,\n\t\t\ttxid,\n\t\t\tvout: payChangeOutIdx,\n\t\t\tscript: Buffer.from(changeOutput.lockingScript.toBinary()).toString(\n\t\t\t\t\"base64\",\n\t\t\t),\n\t\t};\n\t}\n\n\tif (payChange) {\n\t\tconst changeOutput = tx.outputs[tx.outputs.length - 1];\n\t\tpayChange.satoshis = changeOutput.satoshis as number;\n\t\tpayChange.txid = tx.id(\"hex\") as string;\n\t}\n\n\treturn {\n\t\ttx,\n\t\tspentOutpoints: tx.inputs.map(\n\t\t\t(i) => `${i.sourceTXID}_${i.sourceOutputIndex}`,\n\t\t),\n\t\tpayChange,\n\t\ttokenChange,\n\t};\n};\n\nconst splitChangeOutputs = (\n  tx: Transaction,\n  changeTsats: bigint,\n  protocol: TokenType,\n  tokenID: string,\n  tokenChangeAddress: string,\n  metaData: PreMAP | undefined,\n  splitConfig: TokenSplitConfig,\n  decimals: number,\n): TokenUtxo[] => {\n  const tokenChanges: TokenUtxo[] = [];\n\n  const threshold = splitConfig.threshold !== undefined ? toTokenSat(splitConfig.threshold, decimals, ReturnTypes.BigInt) : undefined;\n  const maxOutputs = splitConfig.outputs;\n  const changeAmt = changeTsats;\n  let splitOutputs: bigint;\n  if (threshold !== undefined && threshold > 0n) {\n      splitOutputs = changeAmt / threshold;\n      splitOutputs = BigInt(Math.min(Number(splitOutputs), maxOutputs));\n  } else {\n      // If no threshold is specified, use maxOutputs directly\n      splitOutputs = BigInt(maxOutputs);\n  }\n  splitOutputs = BigInt(Math.max(Number(splitOutputs), 1));\n\n  const baseChangeAmount = changeAmt / splitOutputs;\n  let remainder = changeAmt % splitOutputs;\n\n  for (let i = 0n; i < splitOutputs; i++) {\n      let splitAmount = baseChangeAmount;\n      if (remainder > 0n) {\n          splitAmount += 1n;\n          remainder -= 1n;\n      }\n\n      const transferInscription: TransferTokenInscription = {\n          p: \"bsv-20\",\n          op: \"transfer\",\n          amt: splitAmount.toString(),\n      };\n      let inscription: TransferBSV20Inscription | TransferBSV21Inscription;\n      if (protocol === TokenType.BSV20) {\n          inscription = {\n              ...transferInscription,\n              tick: tokenID,\n          } as TransferBSV20Inscription;\n      } else if (protocol === TokenType.BSV21) {\n          inscription = {\n              ...transferInscription,\n              id: tokenID,\n          } as TransferBSV21Inscription;\n      } else {\n          throw new Error(\"Invalid protocol\");\n      }\n\n      const lockingScript = new OrdP2PKH().lock(\n          tokenChangeAddress,\n          {\n              dataB64: Buffer.from(JSON.stringify(inscription)).toString(\"base64\"),\n              contentType: \"application/bsv-20\",\n          },\n          splitConfig.omitMetaData ? undefined : stringifyMetaData(metaData),\n      );\n\n      const vout = tx.outputs.length;\n      tx.addOutput({ lockingScript, satoshis: 1 });\n      tokenChanges.push({\n          id: tokenID,\n          satoshis: 1,\n          script: Buffer.from(lockingScript.toBinary()).toString(\"base64\"),\n          txid: \"\",\n          vout,\n          amt: splitAmount.toString(),\n      });\n  }\n\n  return tokenChanges;\n};",
    "import type { CollectionItemSubTypeData, CollectionSubTypeData } from \"./types\";\n\n/**\n * Validates sub type data\n * @param {string} subType - Sub type of the ordinals token\n * @param {string} subTypeData - Sub type data of the ordinals token\n * @returns {Error | undefined} Error if validation fails, undefined if validation passes\n */\nexport const validateSubTypeData = (\n  subType: \"collection\" | \"collectionItem\",\n  subTypeData: CollectionItemSubTypeData | CollectionSubTypeData,\n): Error | undefined => {\n  try {\n    if (subType === \"collection\") {\n      const collectionData = subTypeData as CollectionSubTypeData;\n      if (!collectionData.description) {\n        return new Error(\"Collection description is required\");\n      }\n      if (!collectionData.quantity) {\n        return new Error(\"Collection quantity is required\");\n      }\n      if (collectionData.rarityLabels) {\n        if (!Array.isArray(collectionData.rarityLabels)) {\n          return new Error(\"Rarity labels must be an array\");\n        }\n        // make sure keys and values are strings\n        if (!collectionData.rarityLabels.every((label) => {\n          return Object.values(label).every(value => typeof value === 'string');\n        })) {\n          return new Error(`Invalid rarity labels ${collectionData.rarityLabels}`);\n        }\n      }\n      if (collectionData.traits ) {\n        if (typeof collectionData.traits !== \"object\") {\n        return new Error(\"Collection traits must be an object\");\n        }\n        if (collectionData.traits && !Object.keys(collectionData.traits).every(key => typeof key === 'string' && typeof collectionData.traits[key] === 'object')) {\n          return new Error(\"Collection traits must be a valid CollectionTraits object\");\n        }\n      }\n    }\n    if (subType === \"collectionItem\") {\n      const itemData = subTypeData as CollectionItemSubTypeData;\n      if (!itemData.collectionId) {\n        return new Error(\"Collection id is required\");\n      }\n      if (!itemData.collectionId.includes(\"_\")) {\n        return new Error(\"Collection id must be a valid outpoint\");\n      }\n      if (itemData.collectionId.split(\"_\")[0].length !== 64) {\n        return new Error(\"Collection id must contain a valid txid\");\n      }\n      if (Number.isNaN(Number.parseInt(itemData.collectionId.split(\"_\")[1]))) {\n        return new Error(\"Collection id must contain a valid vout\");\n      }\n\n      if (itemData.mintNumber && typeof itemData.mintNumber !== \"number\") {\n        return new Error(\"Mint number must be a number\");\n      }\n      if (itemData.rank && typeof itemData.rank !== \"number\") {\n        return new Error(\"Rank must be a number\");\n      }\n      if (itemData.rarityLabel && typeof itemData.rarityLabel !== \"string\") {\n        return new Error(\"Rarity label must be a string\");\n      }\n      if (itemData.traits && typeof itemData.traits !== \"object\") {\n        return new Error(\"Traits must be an object\");\n      }\n      if (itemData.attachments && !Array.isArray(itemData.attachments)) {\n        return new Error(\"Attachments must be an array\");\n      }\n    }\n    return undefined;\n  } catch (error) {\n    return new Error(\"Invalid JSON data\");\n  }\n};",
    "import {\n\tBigNumber,\n\ttype LockingScript,\n\tOP,\n\tP2PKH,\n\ttype PrivateKey,\n\tScript,\n\ttype Transaction,\n\tTransactionSignature,\n\tUnlockingScript,\n\tUtils,\n} from \"@bsv/sdk\";\nimport { toHex } from \"../utils/strings\";\nimport type { Inscription } from \"../types\";\n\nexport const oLockPrefix =\n\t\"2097dfd76851bf465e8f715593b217714858bbe9570ff3bd5e33840a34e20ff0262102ba79df5f8ae7604a9830f03c7933028186aede0675a16f025dc4f8be8eec0382201008ce7480da41702918d1ec8e6849ba32b4d65b1e40dc669c31a1e6306b266c0000\";\nexport const oLockSuffix =\n\t\"615179547a75537a537a537a0079537a75527a527a7575615579008763567901c161517957795779210ac407f0e4bd44bfc207355a778b046225a7068fc59ee7eda43ad905aadbffc800206c266b30e6a1319c66dc401e5bd6b432ba49688eecd118297041da8074ce081059795679615679aa0079610079517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e01007e81517a75615779567956795679567961537956795479577995939521414136d08c5ed2bf3ba048afe6dcaebafeffffffffffffffffffffffffffffff00517951796151795179970079009f63007952799367007968517a75517a75517a7561527a75517a517951795296a0630079527994527a75517a6853798277527982775379012080517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e01205279947f7754537993527993013051797e527e54797e58797e527e53797e52797e57797e0079517a75517a75517a75517a75517a75517a75517a75517a75517a75517a75517a75517a75517a756100795779ac517a75517a75517a75517a75517a75517a75517a75517a75517a7561517a75517a756169587951797e58797eaa577961007982775179517958947f7551790128947f77517a75517a75618777777777777777777767557951876351795779a9876957795779ac777777777777777767006868\";\n\n/**\n * OrdLock class implementing ScriptTemplate.\n *\n * This class provides methods for interacting with OrdinalLock contract \n */\nexport default class OrdLock {\n\t/**\n\t * Creates a 1Sat Ordinal Lock script\n\t *\n\t * @param {string} ordAddress - An address which can cancel listing.\n\t * @param {string} payAddress - Address which is paid on purchase\n\t * @param {number} price - Listing price in satoshis\n\t * @returns {LockingScript} - A P2PKH locking script.\n\t */\n\tlock(\n\t\tordAddress: string,\n\t\tpayAddress: string,\n\t\tprice: number,\n\t\tinscription?: Inscription,\n\t): Script {\n\t\tconst cancelPkh = Utils.fromBase58Check(ordAddress).data as number[];\n\t\tconst payPkh = Utils.fromBase58Check(payAddress).data as number[];\n\n\t\tlet script = new Script()\n\t\tif (inscription?.dataB64 !== undefined && inscription?.contentType !== undefined) {\n\t\t\tconst ordHex = toHex(\"ord\");\n\t\t\tconst fsBuffer = Buffer.from(inscription.dataB64, \"base64\");\n\t\t\tconst fileHex = fsBuffer.toString(\"hex\").trim();\n\t\t\tif (!fileHex) {\n\t\t\t\tthrow new Error(\"Invalid file data\");\n\t\t\t}\n\t\t\tconst fileMediaType = toHex(inscription.contentType);\n\t\t\tif (!fileMediaType) {\n\t\t\t\tthrow new Error(\"Invalid media type\");\n\t\t\t}\n\t\t\tscript = Script.fromASM(`OP_0 OP_IF ${ordHex} OP_1 ${fileMediaType} OP_0 ${fileHex} OP_ENDIF`);\n\t\t}\n\n\t\treturn script.writeScript(Script.fromHex(oLockPrefix))\n\t\t\t.writeBin(cancelPkh)\n\t\t\t.writeBin(OrdLock.buildOutput(price, new P2PKH().lock(payPkh).toBinary()))\n\t\t\t.writeScript(Script.fromHex(oLockSuffix))\n\t}\n\n\tcancelListing(\n\t\tprivateKey: PrivateKey,\n\t\tsignOutputs: 'all' | 'none' | 'single' = 'all',\n\t\tanyoneCanPay = false,\n\t\tsourceSatoshis?: number,\n\t\tlockingScript?: Script\n\t): {\n\t\tsign: (tx: Transaction, inputIndex: number) => Promise<UnlockingScript>\n\t\testimateLength: () => Promise<number>\n\t} {\n\t\tconst p2pkh = new P2PKH().unlock(privateKey, signOutputs, anyoneCanPay, sourceSatoshis, lockingScript)\n\t\treturn {\n\t\t\tsign: async (tx: Transaction, inputIndex: number) => {\n\t\t\t\treturn (await p2pkh.sign(tx, inputIndex)).writeOpCode(OP.OP_1)\n\t\t\t},\n\t\t\testimateLength: async () => {\n\t\t\t\treturn 107\n\t\t\t}\n\t\t}\n\t}\n\n\tpurchaseListing(\n\t\tsourceSatoshis?: number,\n\t\tlockingScript?: Script\n\t): {\n\t\tsign: (tx: Transaction, inputIndex: number) => Promise<UnlockingScript>\n\t\testimateLength: (tx: Transaction, inputIndex: number) => Promise<number>\n\t} {\n\t\tconst purchase = {\n\t\t\tsign: async (tx: Transaction, inputIndex: number) => {\n\t\t\t\tif (tx.outputs.length < 2) {\n\t\t\t\t\tthrow new Error(\"Malformed transaction\")\n\t\t\t\t}\n\t\t\t\tconst script = new UnlockingScript()\n\t\t\t\t\t.writeBin(OrdLock.buildOutput(\n\t\t\t\t\t\ttx.outputs[0].satoshis || 0,\n\t\t\t\t\t\ttx.outputs[0].lockingScript.toBinary()\n\t\t\t\t\t))\n\t\t\t\tif (tx.outputs.length > 2) {\n\t\t\t\t\tconst writer = new Utils.Writer()\n\t\t\t\t\tfor (const output of tx.outputs.slice(2)) {\n\t\t\t\t\t\twriter.write(OrdLock.buildOutput(output.satoshis || 0, output.lockingScript.toBinary()))\n\t\t\t\t\t}\n\t\t\t\t\tscript.writeBin(writer.toArray())\n\t\t\t\t} else {\n\t\t\t\t\tscript.writeOpCode(OP.OP_0)\n\t\t\t\t}\n\n\t\t\t\tconst input = tx.inputs[inputIndex]\n\t\t\t\tlet sourceSats = sourceSatoshis as number\n\t\t\t\tif (!sourceSats && input.sourceTransaction) {\n\t\t\t\t\tsourceSats = input.sourceTransaction.outputs[input.sourceOutputIndex].satoshis as number\n\t\t\t\t} else if (!sourceSatoshis) {\n\t\t\t\t\tthrow new Error(\"sourceTransaction or sourceSatoshis is required\")\n\t\t\t\t}\n\n\t\t\t\tconst sourceTXID = (input.sourceTXID || input.sourceTransaction?.id('hex')) as string\n\t\t\t\tlet subscript = lockingScript as LockingScript\n\t\t\t\tif (!subscript) {\n\t\t\t\t\tsubscript = input.sourceTransaction?.outputs[input.sourceOutputIndex].lockingScript as LockingScript\n\t\t\t\t}\n\t\t\t\tconst preimage = TransactionSignature.format({\n\t\t\t\t\tsourceTXID,\n\t\t\t\t\tsourceOutputIndex: input.sourceOutputIndex,\n\t\t\t\t\tsourceSatoshis: sourceSats,\n\t\t\t\t\ttransactionVersion: tx.version,\n\t\t\t\t\totherInputs: [],\n\t\t\t\t\tinputIndex,\n\t\t\t\t\toutputs: tx.outputs,\n\t\t\t\t\tinputSequence: input.sequence || 0xffffffff,\n\t\t\t\t\tsubscript,\n\t\t\t\t\tlockTime: tx.lockTime,\n\t\t\t\t\tscope: TransactionSignature.SIGHASH_ALL |\n\t\t\t\t\t\tTransactionSignature.SIGHASH_ANYONECANPAY |\n\t\t\t\t\t\tTransactionSignature.SIGHASH_FORKID\n\t\t\t\t});\n\n\t\t\t\treturn script.writeBin(preimage).writeOpCode(OP.OP_0)\n\t\t\t},\n\t\t\testimateLength: async (tx: Transaction, inputIndex: number) => {\n\t\t\t\treturn (await purchase.sign(tx, inputIndex)).toBinary().length\n\t\t\t}\n\t\t}\n\t\treturn purchase\n\t}\n\n\tstatic buildOutput(satoshis: number, script: number[]): number[] {\n\t\tconst writer = new Utils.Writer()\n\t\twriter.writeUInt64LEBn(new BigNumber(satoshis))\n\t\twriter.writeVarIntNum(script.length)\n\t\twriter.write(script)\n\t\treturn writer.toArray()\n\t}\n}\n",
    "import {\n  P2PKH,\n  SatoshisPerKilobyte,\n  Script,\n  Transaction,\n  Utils,\n} from \"@bsv/sdk\";\nimport { DEFAULT_SAT_PER_KB } from \"./constants\";\nimport OrdLock from \"./templates/ordLock\";\nimport OrdP2PKH from \"./templates/ordP2pkh\";\nimport {\n  type TokenChangeResult,\n  TokenType,\n  type CreateOrdListingsConfig,\n  type CreateOrdTokenListingsConfig,\n  type TokenUtxo,\n  type TransferBSV20Inscription,\n  type TransferBSV21Inscription,\n  type TransferTokenInscription,\n  type Utxo,\n} from \"./types\";\nimport { inputFromB64Utxo } from \"./utils/utxo\";\nimport { ReturnTypes, toToken, toTokenSat } from \"satoshi-token\";\nimport { signData } from \"./signData\";\nconst { toArray } = Utils;\n\nexport const createOrdListings = async (config: CreateOrdListingsConfig) => {\n  const {\n    utxos,\n    listings,\n    paymentPk,\n    ordPk,\n    satsPerKb = DEFAULT_SAT_PER_KB,\n    additionalPayments = [],\n    signer,\n    signInputs = true,\n  } = config;\n\n  const modelOrFee = new SatoshisPerKilobyte(satsPerKb);\n  let tx = new Transaction();\n\n  // Warn if creating many inscriptions at once\n  if (listings.length > 100) {\n    console.warn(\n      \"Creating many inscriptions at once can be slow. Consider using multiple transactions instead.\",\n    );\n  }\n\n  // Outputs\n  // Add listing outputs\n  for (const listing of listings) {\n    tx.addOutput({\n      satoshis: 1,\n      lockingScript: new OrdLock().lock(\n        listing.ordAddress,\n        listing.payAddress,\n        listing.price,\n      ),\n    });\n\n    if (signInputs) {\n      const inputScriptBinary = toArray(listing.listingUtxo.script, \"base64\");\n      const inputScript = Script.fromBinary(inputScriptBinary);\n      const ordKeyToUse = listing.listingUtxo.pk || ordPk;\n      if (!ordKeyToUse) {\n        throw new Error(\"Private key is required to sign the ordinal\");\n      }\n      tx.addInput(inputFromB64Utxo(\n        listing.listingUtxo,\n        new OrdP2PKH().unlock(\n          ordKeyToUse,\n          \"all\",\n          true,\n          listing.listingUtxo.satoshis,\n          inputScript,\n        ),\n      ));\n    } else {\n      tx.addInput(inputFromB64Utxo(listing.listingUtxo));\n    }\n  }\n\n  // Add additional payments if any\n  for (const p of additionalPayments) {\n    tx.addOutput({\n      satoshis: p.amount,\n      lockingScript: new P2PKH().lock(p.to),\n    });\n  }\n\n  // Check if change is needed\n  let payChange: Utxo | undefined;\n  const changeAddress = config.changeAddress || paymentPk?.toAddress();\n  if(!changeAddress) {\n    throw new Error(\"changeAddress or private key is required\");\n  }\n  const changeScript = new P2PKH().lock(changeAddress);\n  const changeOutput = {\n    lockingScript: changeScript,\n    change: true,\n  };\n  tx.addOutput(changeOutput);\n\n  let totalSatsIn = 0n;\n  const totalSatsOut = tx.outputs.reduce(\n    (total, out) => total + BigInt(out.satoshis || 0),\n    0n,\n  );\n  let fee = 0;\n  for (const utxo of utxos) {\n    if (signInputs) {\n      const payKeyToUse = utxo.pk || paymentPk;\n      if (!payKeyToUse) {\n        throw new Error(\"Private key is required to sign the transaction\");\n      }\n      const input = inputFromB64Utxo(utxo, new P2PKH().unlock(\n        payKeyToUse,\n        \"all\",\n        true,\n        utxo.satoshis,\n        Script.fromBinary(Utils.toArray(utxo.script, 'base64'))\n      ));\n      tx.addInput(input);\n    } else {\n      tx.addInput(inputFromB64Utxo(utxo));\n    }\n    // stop adding inputs if the total amount is enough\n    totalSatsIn += BigInt(utxo.satoshis);\n    fee = await modelOrFee.computeFee(tx);\n\n    if (totalSatsIn >= totalSatsOut + BigInt(fee)) {\n      break;\n    }\n  }\n\n  // make sure we have enough\n  if (totalSatsIn < totalSatsOut + BigInt(fee)) {\n    throw new Error(\n      `Not enough funds to create ordinal listings. Total sats in: ${totalSatsIn}, Total sats out: ${totalSatsOut}, Fee: ${fee}`,\n    );\n  }\n\n  if (signer) {\n    tx = await signData(tx, signer);\n  }\n\n  // Calculate fee\n  await tx.fee(modelOrFee);\n\n  // Sign the transaction (if signInputs is true)\n  if (signInputs) {\n    await tx.sign();\n  }\n\n  // check for change\n  const payChangeOutIdx = tx.outputs.findIndex((o) => o.change);\n  if (payChangeOutIdx !== -1) {\n    const changeOutput = tx.outputs[payChangeOutIdx];\n    payChange = {\n      satoshis: changeOutput.satoshis as number,\n      txid: tx.id(\"hex\") as string,\n      vout: payChangeOutIdx,\n      script: Buffer.from(changeOutput.lockingScript.toBinary()).toString(\n        \"base64\",\n      ),\n    };\n  }\n\n  if (payChange) {\n    const changeOutput = tx.outputs[tx.outputs.length - 1];\n    payChange.satoshis = changeOutput.satoshis as number;\n    payChange.txid = tx.id(\"hex\") as string;\n  }\n\n  return {\n    tx,\n    spentOutpoints: tx.inputs.map(\n      (i) => `${i.sourceTXID}_${i.sourceOutputIndex}`,\n    ),\n    payChange,\n  };\n};\n\nexport const createOrdTokenListings = async (\n  config: CreateOrdTokenListingsConfig,\n): Promise<TokenChangeResult> => {\n  const {\n    utxos,\n    protocol,\n    tokenID,\n    ordPk,\n    paymentPk,\n    additionalPayments = [],\n    tokenChangeAddress,\n    inputTokens,\n    listings,\n    decimals,\n    satsPerKb = DEFAULT_SAT_PER_KB,\n    signer,\n    signInputs = true,\n  } = config;\n\n\n  // Warn if creating many inscriptions at once\n  if (listings.length > 100) {\n    console.warn(\n      \"Creating many inscriptions at once can be slow. Consider using multiple transactions instead.\",\n    );\n  }\n\n  // Ensure these inputs are for the expected token\n  if (!inputTokens.every((token) => token.id === tokenID)) {\n    throw new Error(\"Input tokens do not match the provided tokenID\");\n  }\n\n  // calculate change amount\n  let changeAmt = 0n;\n  let totalAmtIn = 0n;\n  let totalAmtOut = 0n;\n\n  // Ensure these inputs are for the expected token\n  if (!inputTokens.every((token) => token.id === tokenID)) {\n    throw new Error(\"Input tokens do not match the provided tokenID\");\n  }\n\n  const modelOrFee = new SatoshisPerKilobyte(satsPerKb);\n  let tx = new Transaction();\n  // Outputs\n  // Add listing outputs\n  for (const listing of listings) {\n    // NewTokenListing is not adjusted for decimals\n    const bigAmt = toTokenSat(listing.tokens, decimals, ReturnTypes.BigInt);\n    const transferInscription: TransferTokenInscription = {\n      p: \"bsv-20\",\n      op: \"transfer\",\n      amt: bigAmt.toString(),\n    };\n    let inscription: TransferBSV20Inscription | TransferBSV21Inscription;\n    if (protocol === TokenType.BSV20) {\n      inscription = {\n        ...transferInscription,\n        tick: tokenID,\n      } as TransferBSV20Inscription;\n    } else if (protocol === TokenType.BSV21) {\n      inscription = {\n        ...transferInscription,\n        id: tokenID,\n      } as TransferBSV21Inscription;\n    } else {\n      throw new Error(\"Invalid protocol\");\n    }\n\n    tx.addOutput({\n      satoshis: 1,\n      lockingScript: new OrdLock().lock(\n        listing.ordAddress,\n        listing.payAddress,\n        listing.price,\n        {\n          dataB64: Buffer.from(JSON.stringify(inscription)).toString(\"base64\"),\n          contentType: \"application/bsv-20\",\n        },\n      ),\n    });\n    totalAmtOut += bigAmt;\n  }\n\n  // Input tokens are already adjusted for decimals\n  for (const token of inputTokens) {\n    if (signInputs) {\n      const ordKeyToUse = token.pk || ordPk;\n      if(!ordKeyToUse) {\n        throw new Error(\"Private key is required to sign the ordinal\");\n      }\n      tx.addInput(inputFromB64Utxo(\n        token,\n        new OrdP2PKH().unlock(\n          ordKeyToUse,\n          \"all\",\n          true,\n          token.satoshis,\n          Script.fromBinary(toArray(token.script, \"base64\")),\n        ),\n      ));\n    } else {\n      tx.addInput(inputFromB64Utxo(token));\n    }\n    totalAmtIn += BigInt(token.amt);\n  }\n  changeAmt = totalAmtIn - totalAmtOut;\n\n  let tokenChange: TokenUtxo[] | undefined;\n  // check that you have enough tokens to send and return change\n  if (changeAmt < 0n) {\n    throw new Error(\"Not enough tokens to send\");\n  }\n  if (changeAmt > 0n) {\n    const transferInscription: TransferTokenInscription = {\n      p: \"bsv-20\",\n      op: \"transfer\",\n      amt: changeAmt.toString(),\n    };\n    let inscription: TransferBSV20Inscription | TransferBSV21Inscription;\n    if (protocol === TokenType.BSV20) {\n      inscription = {\n        ...transferInscription,\n        tick: tokenID,\n      } as TransferBSV20Inscription;\n    } else if (protocol === TokenType.BSV21) {\n      inscription = {\n        ...transferInscription,\n        id: tokenID,\n      } as TransferBSV21Inscription;\n    } else {\n      throw new Error(\"Invalid protocol\");\n    }\n\n    const lockingScript = new OrdP2PKH().lock(tokenChangeAddress, {\n      dataB64: Buffer.from(JSON.stringify(inscription)).toString('base64'),\n      contentType: \"application/bsv-20\",\n    });\n    const vout = tx.outputs.length;\n    tx.addOutput({ lockingScript, satoshis: 1 });\n    tokenChange = [{\n      id: tokenID,\n      satoshis: 1,\n      script: Buffer.from(lockingScript.toBinary()).toString(\"base64\"),\n      txid: \"\",\n      vout,\n      amt: changeAmt.toString(),\n    }];\n  }\n\n  // Add additional payments if any\n  for (const p of additionalPayments) {\n    tx.addOutput({\n      satoshis: p.amount,\n      lockingScript: new P2PKH().lock(p.to),\n    });\n  }\n\n  // add change to the outputs\n  let payChange: Utxo | undefined;\n  const changeAddress = config.changeAddress || paymentPk?.toAddress();\n  if(!changeAddress) {\n    throw new Error(\"Either changeAddress or paymentPk is required\");\n  }\n\n  const changeScript = new P2PKH().lock(changeAddress);\n  const changeOut = {\n    lockingScript: changeScript,\n    change: true,\n  };\n  tx.addOutput(changeOut);\n\n  let totalSatsIn = 0n;\n  const totalSatsOut = tx.outputs.reduce(\n    (total, out) => total + BigInt(out.satoshis || 0),\n    0n,\n  );\n  let fee = 0;\n  for (const utxo of utxos) {\n    if (signInputs) {\n      const payKeyToUse = utxo.pk || paymentPk;\n      if(!payKeyToUse) {\n        throw new Error(\"Private key is required to sign the payment\");\n      }\n      const input = inputFromB64Utxo(utxo, new P2PKH().unlock(\n        payKeyToUse,\n        \"all\",\n        true,\n        utxo.satoshis,\n        Script.fromBinary(Utils.toArray(utxo.script, 'base64'))\n      ));\n      tx.addInput(input);\n    } else {\n      tx.addInput(inputFromB64Utxo(utxo));\n    }\n    // stop adding inputs if the total amount is enough\n    totalSatsIn += BigInt(utxo.satoshis);\n    fee = await modelOrFee.computeFee(tx);\n\n    if (totalSatsIn >= totalSatsOut + BigInt(fee)) {\n      break;\n    }\n  }\n\n  // make sure we have enough\n  if (totalSatsIn < totalSatsOut + BigInt(fee)) {\n    throw new Error(\n      `Not enough funds to create token listings. Total sats in: ${totalSatsIn}, Total sats out: ${totalSatsOut}, Fee: ${fee}`,\n    );\n  }\n\n  if (signer) {\n    tx = await signData(tx, signer);\n  }\n\n  // estimate the cost of the transaction and assign change value\n  await tx.fee(modelOrFee);\n\n  // Sign the transaction (if signInputs is true)\n  if (signInputs) {\n    await tx.sign();\n  }\n\n  const txid = tx.id(\"hex\") as string;\n  if (tokenChange) {\n    tokenChange = tokenChange.map((tc) => ({ ...tc, txid }));\n  }\n  // check for change\n  const payChangeOutIdx = tx.outputs.findIndex((o) => o.change);\n  if (payChangeOutIdx !== -1) {\n    const changeOutput = tx.outputs[payChangeOutIdx];\n    payChange = {\n      satoshis: changeOutput.satoshis as number,\n      txid,\n      vout: payChangeOutIdx,\n      script: Buffer.from(changeOutput.lockingScript.toBinary()).toString(\n        \"base64\",\n      ),\n    };\n  }\n\n  if (payChange) {\n    const changeOutput = tx.outputs[tx.outputs.length - 1];\n    payChange.satoshis = changeOutput.satoshis as number;\n    payChange.txid = tx.id(\"hex\") as string;\n  }\n\n  return {\n    tx,\n    spentOutpoints: tx.inputs.map(\n      (i) => `${i.sourceTXID}_${i.sourceOutputIndex}`,\n    ),\n    payChange,\n    tokenChange,\n  };\n};\n",
    "import { P2PKH, SatoshisPerKilobyte, Script, Transaction, Utils } from \"@bsv/sdk\";\nimport {\n\tTokenType,\n\ttype TokenUtxo,\n\ttype CancelOrdListingsConfig,\n\ttype CancelOrdTokenListingsConfig,\n\ttype Destination,\n\ttype TransferBSV20Inscription,\n\ttype TransferBSV21Inscription,\n\ttype TransferTokenInscription,\n\ttype Utxo,\n  type ChangeResult,\n  type TokenChangeResult,\n} from \"./types\";\nimport { inputFromB64Utxo } from \"./utils/utxo\";\nimport { DEFAULT_SAT_PER_KB } from \"./constants\";\nimport OrdLock from \"./templates/ordLock\";\nimport OrdP2PKH from \"./templates/ordP2pkh\";\n\n/**\n * Cancel Ordinal Listings\n * @param {CancelOrdListingsConfig} config - Configuration object for cancelling ordinals\n * @param {PrivateKey} config.paymentPk - Private key to sign payment inputs\n * @param {PrivateKey} config.ordPk - Private key to sign ordinals\n * @param {Utxo[]} config.utxos - Utxos to spend (with base64 encoded scripts)\n * @param {Utxo[]} config.listingUtxos - Listing utxos to cancel (with base64 encoded scripts)\n * @param {string} [config.changeAddress] - Optional. Address to send change to\n * @param {number} [config.satsPerKb] - Optional. Satoshis per kilobyte for fee calculation\n * @param {Payment[]} [config.additionalPayments] - Optional. Additional payments to make\n * @returns {Promise<ChangeResult>} Transaction, spent outpoints, change utxo\n */\nexport const cancelOrdListings = async (config: CancelOrdListingsConfig): Promise<ChangeResult> => {\n\tconst {\n\t\tutxos,\n\t\tlistingUtxos,\n\t\tordPk,\n\t\tpaymentPk,\n\t\tadditionalPayments = [],\n\t\tsatsPerKb = DEFAULT_SAT_PER_KB,\n\t} = config;\n\n\t// Warn if creating many inscriptions at once\n\tif (listingUtxos.length > 100) {\n\t\tconsole.warn(\n\t\t\t\"Creating many inscriptions at once can be slow. Consider using multiple transactions instead.\",\n\t\t);\n\t}\n\t\n\tconst modelOrFee = new SatoshisPerKilobyte(satsPerKb);\n\tconst tx = new Transaction();\n\n\t// Inputs\n\t// Add the locked ordinals we're cancelling\n\tfor (const listingUtxo of listingUtxos) {\n    const ordKeyToUse = listingUtxo.pk || ordPk;\n\t\tif(!ordKeyToUse) {\n\t\t\tthrow new Error(\"Private key required for token input\");\n\t\t}\n\t\ttx.addInput(inputFromB64Utxo(\n\t\t\tlistingUtxo,\n\t\t\tnew OrdLock().cancelListing(\n\t\t\t\tordKeyToUse,\n\t\t\t\t\"all\",\n\t\t\t\ttrue,\n\t\t\t\tlistingUtxo.satoshis,\n\t\t\t\tScript.fromBinary(Utils.toArray(listingUtxo.script, 'base64'))\n\t\t\t)\n\t\t));\n\t\t// Add cancel outputs returning listed ordinals\n\t\ttx.addOutput({\n\t\t\tsatoshis: 1,\n\t\t\tlockingScript: new P2PKH().lock((ordKeyToUse).toAddress().toString()),\n\t\t});\n\t}\n\n\t// Add additional payments if any\n\tfor (const p of additionalPayments) {\n\t\ttx.addOutput({\n\t\t\tsatoshis: p.amount,\n\t\t\tlockingScript: new P2PKH().lock(p.to),\n\t\t});\n\t}\n\n\t// add change to the outputs\n\tlet payChange: Utxo | undefined;\n  const changeAddress = config.changeAddress || paymentPk?.toAddress();\n\tif (!changeAddress) {\n\t\tthrow new Error(\"paymentPk or changeAddress required for payment change\");\n\t}\n\tconst change = changeAddress;\n\tconst changeScript = new P2PKH().lock(change);\n\tconst changeOut = {\n\t\tlockingScript: changeScript,\n\t\tchange: true,\n\t};\n\ttx.addOutput(changeOut);\n\n\tlet totalSatsIn = 0n;\n\tconst totalSatsOut = tx.outputs.reduce(\n\t\t(total, out) => total + BigInt(out.satoshis || 0),\n\t\t0n,\n\t);\n\tlet fee = 0;\n\tfor (const utxo of utxos) {\n    const payKeyToUse = utxo.pk || paymentPk;\n\t\tif(!payKeyToUse) {\n\t\t\tthrow new Error(\"paymentPk required for payment utxo\");\n\t\t}\n\t\tconst input = inputFromB64Utxo(\n\t\t\tutxo, \n\t\t\tnew P2PKH().unlock(\n\t\t\t\tpayKeyToUse,\n\t\t\t\t\"all\",\n\t\t\t\ttrue, \n\t\t\t\tutxo.satoshis,\n\t\t\t\tScript.fromBinary(Utils.toArray(utxo.script, 'base64'))\n\t\t\t)\n\t\t);\n\n\t\ttx.addInput(input);\n\t\t// stop adding inputs if the total amount is enough\n\t\ttotalSatsIn += BigInt(utxo.satoshis);\n\t\tfee = await modelOrFee.computeFee(tx);\n\n\t\tif (totalSatsIn >= totalSatsOut + BigInt(fee)) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// make sure we have enough\n\tif (totalSatsIn < totalSatsOut + BigInt(fee)) {\n\t\tthrow new Error(\n\t\t\t`Not enough funds to cancel ordinal listings. Total sats in: ${totalSatsIn}, Total sats out: ${totalSatsOut}, Fee: ${fee}`,\n\t\t);\n\t}\n\n\t// estimate the cost of the transaction and assign change value\n\tawait tx.fee(modelOrFee);\n\n\t// Sign the transaction\n\tawait tx.sign();\n\n\t// check for change\n\tconst payChangeOutIdx = tx.outputs.findIndex((o) => o.change);\n\tif (payChangeOutIdx !== -1) {\n\t\tconst changeOutput = tx.outputs[payChangeOutIdx];\n\t\tpayChange = {\n\t\t\tsatoshis: changeOutput.satoshis as number,\n\t\t\ttxid: tx.id(\"hex\") as string,\n\t\t\tvout: payChangeOutIdx,\n\t\t\tscript: Buffer.from(changeOutput.lockingScript.toBinary()).toString(\n\t\t\t\t\"base64\",\n\t\t\t),\n\t\t};\n\t}\n\n\tif (payChange) {\n\t\tconst changeOutput = tx.outputs[tx.outputs.length - 1];\n\t\tpayChange.satoshis = changeOutput.satoshis as number;\n\t\tpayChange.txid = tx.id(\"hex\") as string;\n\t}\n\n\treturn {\n\t\ttx,\n\t\tspentOutpoints: tx.inputs.map(\n\t\t\t(i) => `${i.sourceTXID}_${i.sourceOutputIndex}`,\n\t\t),\n\t\tpayChange,\n\t};\n};\n\n/**\n * Cancel Ordinal Token Listings\n * @param {CancelOrdTokenListingsConfig} config - Configuration object for cancelling token ordinals\n * @param {PrivateKey} config.paymentPk - Private key to sign payment inputs\n * @param {PrivateKey} config.ordPk - Private key to sign ordinals\n * @param {Utxo[]} config.utxos - Utxos to spend (with base64 encoded scripts)\n * @param {Utxo[]} config.listingUtxos - Listing utxos to cancel (with base64 encoded scripts)\n * @param {string} config.tokenID - Token ID of the token to cancel listings for\n * @param {string} config.ordAddress - Address to send the cancelled token to\n * @param {number} [config.satsPerKb] - Optional. Satoshis per kilobyte for fee calculation\n * @param {Payment[]} [config.additionalPayments] - Optional. Additional payments to make\n * @returns {Promise<TokenChangeResult>} Transaction, spent outpoints, change utxo, token change utxos\n */\nexport const cancelOrdTokenListings = async (\n\tconfig: CancelOrdTokenListingsConfig,\n): Promise<TokenChangeResult> => {\n\tconst {\n\t\tprotocol,\n\t\ttokenID,\n\t\tpaymentPk,\n\t\tordPk,\n\t\tadditionalPayments,\n\t\tlistingUtxos,\n\t\tutxos,\n\t\tsatsPerKb = DEFAULT_SAT_PER_KB,\n\t} = config;\n\t// calculate change amount\n\tlet totalAmtIn = 0;\n\n\tif (listingUtxos.length > 100) {\n\t\tconsole.warn(\n\t\t\t\"Creating many inscriptions at once can be slow. Consider using multiple transactions instead.\",\n\t\t);\n\t}\n\n\t// Ensure these inputs are for the expected token\n\tif (!listingUtxos.every((token) => token.id === tokenID)) {\n\t\tthrow new Error(\"Input tokens do not match the provided tokenID\");\n\t}\n\n\tconst modelOrFee = new SatoshisPerKilobyte(satsPerKb);\n\tconst tx = new Transaction();\n\n\t// Inputs\n\t// Add the locked ordinals we're cancelling\n\tfor (const listingUtxo of listingUtxos) {\n    const ordKeyToUse = listingUtxo.pk || ordPk;\n\t\tif(!ordKeyToUse) {\n\t\t\tthrow new Error(\"Private key required for token input\");\n\t\t}\n\t\ttx.addInput(inputFromB64Utxo(\n\t\t\tlistingUtxo,\n\t\t\tnew OrdLock().cancelListing(\n\t\t\t\tordKeyToUse,\n\t\t\t\t\"all\",\n\t\t\t\ttrue,\n\t\t\t\tlistingUtxo.satoshis,\n\t\t\t\tScript.fromBinary(Utils.toArray(listingUtxo.script, 'base64'))\n\t\t\t)\n\t\t));\n\t\ttotalAmtIn += Number.parseInt(listingUtxo.amt);\n\t}\n\n\tconst transferInscription: TransferTokenInscription = {\n\t\tp: \"bsv-20\",\n\t\top: \"transfer\",\n\t\tamt: totalAmtIn.toString(),\n\t};\n\tlet inscription: TransferBSV20Inscription | TransferBSV21Inscription;\n\tif (protocol === TokenType.BSV20) {\n\t\tinscription = {\n\t\t\t...transferInscription,\n\t\t\ttick: tokenID,\n\t\t} as TransferBSV20Inscription;\n\t} else if (protocol === TokenType.BSV21) {\n\t\tinscription = {\n\t\t\t...transferInscription,\n\t\t\tid: tokenID,\n\t\t} as TransferBSV21Inscription;\n\t} else {\n\t\tthrow new Error(\"Invalid protocol\");\n\t}\n\n  const ordAddress = config.ordAddress || ordPk?.toAddress();\n\tif(!ordAddress) {\n\t\tthrow new Error(\"ordAddress or ordPk required for token output\");\n\t}\n\tconst destination: Destination = {\n\t\taddress: ordAddress,\n\t\tinscription: {\n\t\t\tdataB64: Buffer.from(JSON.stringify(inscription)).toString(\"base64\"),\n\t\t\tcontentType: \"application/bsv-20\",\n\t\t},\n\t};\n\n  const lockingScript = new OrdP2PKH().lock(\n    destination.address,\n    destination.inscription\n  );\n\n\ttx.addOutput({\n\t\tsatoshis: 1,\n\t\tlockingScript,\n\t});\n\n\t// Add additional payments if any\n\tfor (const p of additionalPayments) {\n\t\ttx.addOutput({\n\t\t\tsatoshis: p.amount,\n\t\t\tlockingScript: new P2PKH().lock(p.to),\n\t\t});\n\t}\n\n\t// add change to the outputs\n\tlet payChange: Utxo | undefined;\n  const changeAddress = config.changeAddress || paymentPk?.toAddress();\n\tif (!changeAddress) {\n\t\tthrow new Error(\"paymentPk or changeAddress required for payment change\");\n\t}\n\tconst changeScript = new P2PKH().lock(changeAddress);\n\tconst changeOut = {\n\t\tlockingScript: changeScript,\n\t\tchange: true,\n\t};\n\ttx.addOutput(changeOut);\n\n\tlet totalSatsIn = 0n;\n\tconst totalSatsOut = tx.outputs.reduce(\n\t\t(total, out) => total + BigInt(out.satoshis || 0),\n\t\t0n,\n\t);\n\tlet fee = 0;\n\tfor (const utxo of utxos) {\n    const payKeyToUse = utxo.pk || paymentPk;\n\t\tif(!payKeyToUse) {\n\t\t\tthrow new Error(\"paymentPk required for payment utxo\");\n\t\t}\n\t\tconst input = inputFromB64Utxo(utxo, new P2PKH().unlock(\n\t\t\tpayKeyToUse, \n\t\t\t\"all\",\n\t\t\ttrue, \n\t\t\tutxo.satoshis,\n\t\t\tScript.fromBinary(Utils.toArray(utxo.script, 'base64'))\n\t\t));\n\n\t\ttx.addInput(input);\n\t\t// stop adding inputs if the total amount is enough\n\t\ttotalSatsIn += BigInt(utxo.satoshis);\n\t\tfee = await modelOrFee.computeFee(tx);\n\n\t\tif (totalSatsIn >= totalSatsOut + BigInt(fee)) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// make sure we have enough\n\tif (totalSatsIn < totalSatsOut + BigInt(fee)) {\n\t\tthrow new Error(\n\t\t\t`Not enough funds to cancel token listings. Total sats in: ${totalSatsIn}, Total sats out: ${totalSatsOut}, Fee: ${fee}`,\n\t\t);\n\t}\n\n\t// estimate the cost of the transaction and assign change value\n\tawait tx.fee(modelOrFee);\n\n\t// Sign the transaction\n\tawait tx.sign();\n\n  const tokenChange: TokenUtxo[] = [{\n    amt: totalAmtIn.toString(),\n    script: Buffer.from(lockingScript.toHex(), 'hex').toString('base64'),\n    txid: tx.id(\"hex\") as string,\n    vout: 0,\n    id: tokenID,\n    satoshis: 1\n  }];\n\n\t// check for change\n\tconst payChangeOutIdx = tx.outputs.findIndex((o) => o.change);\n\tif (payChangeOutIdx !== -1) {\n\t\tconst changeOutput = tx.outputs[payChangeOutIdx];\n\t\tpayChange = {\n\t\t\tsatoshis: changeOutput.satoshis as number,\n\t\t\ttxid: tx.id(\"hex\") as string,\n\t\t\tvout: payChangeOutIdx,\n\t\t\tscript: Buffer.from(changeOutput.lockingScript.toBinary()).toString(\n\t\t\t\t\"base64\",\n\t\t\t),\n\t\t};\n\t}\n\n\tif (payChange) {\n\t\tconst changeOutput = tx.outputs[tx.outputs.length - 1];\n\t\tpayChange.satoshis = changeOutput.satoshis as number;\n\t\tpayChange.txid = tx.id(\"hex\") as string;\n\t}\n\n\treturn {\n\t\ttx,\n\t\tspentOutpoints: tx.inputs.map(\n\t\t\t(i) => `${i.sourceTXID}_${i.sourceOutputIndex}`,\n\t\t),\n\t\tpayChange,\n    tokenChange,\n\t};\n};",
    "import {\n\tLockingScript,\n\tP2PKH,\n\tSatoshisPerKilobyte,\n\tScript,\n\tTransaction,\n\tUtils,\n} from \"@bsv/sdk\";\nimport { DEFAULT_SAT_PER_KB } from \"./constants\";\nimport OrdLock from \"./templates/ordLock\";\nimport OrdP2PKH from \"./templates/ordP2pkh\";\nimport {\n\ttype ChangeResult,\n\tRoytaltyType,\n\tTokenType,\n\ttype PurchaseOrdListingConfig,\n\ttype PurchaseOrdTokenListingConfig,\n\ttype TransferBSV20Inscription,\n\ttype TransferBSV21Inscription,\n\ttype TransferTokenInscription,\n\ttype Utxo,\n\tMAP,\n} from \"./types\";\nimport { resolvePaymail } from \"./utils/paymail\";\nimport { inputFromB64Utxo } from \"./utils/utxo\";\n\n/**\n * Purchase a listing\n * @param {PurchaseOrdListingConfig} config - Configuration object for purchasing a listing\n * @param {Utxo[]} config.utxos - Utxos to spend (with base64 encoded scripts)\n * @param {PrivateKey} config.paymentPk - Private key to sign payment inputs\n * @param {ExistingListing} config.listing - Listing to purchase\n * @param {string} config.ordAddress - Address to send the ordinal to\n * @param {string} [config.changeAddress] - Optional. Address to send change to\n * @param {number} [config.satsPerKb] - Optional. Satoshis per kilobyte for fee calculation\n * @param {Payment[]} [config.additionalPayments] - Optional. Additional payments to make\n * @param {Royalty[]} [config.royalties] - Optional. Royalties to pay\n * @param {MAP} [config.metaData] - Optional. MAP (Magic Attribute Protocol) metadata to include on purchased output\n * @returns {Promise<ChangeResult>} Transaction, spent outpoints, change utxo\n */\nexport const purchaseOrdListing = async (\n\tconfig: PurchaseOrdListingConfig,\n): Promise<ChangeResult> => {\n\tconst {\n\t\tutxos,\n\t\tpaymentPk,\n\t\tlisting,\n\t\tordAddress,\n\t\tadditionalPayments = [],\n\t\tsatsPerKb = DEFAULT_SAT_PER_KB,\n\t\troyalties = [],\n\t\tmetaData,\n\t} = config;\n\n\tconst modelOrFee = new SatoshisPerKilobyte(satsPerKb);\n\tconst tx = new Transaction();\n\n\t// Inputs\n\t// Add the locked ordinal we're purchasing\n\ttx.addInput(\n\t\tinputFromB64Utxo(\n\t\t\tlisting.listingUtxo,\n\t\t\tnew OrdLock().purchaseListing(\n\t\t\t\t1,\n\t\t\t\tScript.fromBinary(Utils.toArray(listing.listingUtxo.script, \"base64\")),\n\t\t\t),\n\t\t),\n\t);\n\n\t// Outputs\n\t// Add the purchased output\n\ttx.addOutput({\n\t\tsatoshis: 1,\n\t\tlockingScript: new OrdP2PKH().lock(ordAddress, undefined, metaData),\n\t});\n\n\t// add the payment output\n\tconst reader = new Utils.Reader(Utils.toArray(listing.payout, \"base64\"));\n\tconst satoshis = reader.readUInt64LEBn().toNumber();\n\tconst scriptLength = reader.readVarIntNum();\n\tconst scriptBin = reader.read(scriptLength);\n\tconst lockingScript = LockingScript.fromBinary(scriptBin);\n\ttx.addOutput({\n\t\tsatoshis,\n\t\tlockingScript,\n\t});\n\n\t// Add additional payments if any\n\tfor (const p of additionalPayments) {\n\t\ttx.addOutput({\n\t\t\tsatoshis: p.amount,\n\t\t\tlockingScript: new P2PKH().lock(p.to),\n\t\t});\n\t}\n\n\t// Add any royalties\n\tfor (const r of royalties) {\n\t\tlet lockingScript: LockingScript | undefined;\n\t\tconst royaltySats = Math.floor(Number(r.percentage) * satoshis);\n\n\t\tswitch (r.type as RoytaltyType) {\n\t\t\tcase RoytaltyType.Paymail:\n\t\t\t\t// resolve paymail address\n\t\t\t\tlockingScript = await resolvePaymail(r.destination, royaltySats);\n\t\t\t\tbreak;\n\t\t\tcase RoytaltyType.Script:\n\t\t\t\tlockingScript = Script.fromBinary(\n\t\t\t\t\tUtils.toArray(r.destination, \"base64\"),\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase RoytaltyType.Address:\n\t\t\t\tlockingScript = new P2PKH().lock(r.destination);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tthrow new Error(\"Invalid royalty type\");\n\t\t}\n\t\tif (!lockingScript) {\n\t\t\tthrow new Error(\"Invalid royalty destination\");\n\t\t}\n\t\ttx.addOutput({\n\t\t\tsatoshis: royaltySats,\n\t\t\tlockingScript,\n\t\t});\n\t}\n\n\t// add change to the outputs\n\tlet payChange: Utxo | undefined;\n  const changeAddress = config.changeAddress || paymentPk?.toAddress();\n\tif (!changeAddress) {\n\t\tthrow new Error(\"Either changeAddress or paymentPk is required\");\n\t}\n\tconst changeScript = new P2PKH().lock(changeAddress);\n\tconst changeOut = {\n\t\tlockingScript: changeScript,\n\t\tchange: true,\n\t};\n\ttx.addOutput(changeOut);\n\n\tlet totalSatsIn = 0n;\n\tconst totalSatsOut = tx.outputs.reduce(\n\t\t(total, out) => total + BigInt(out.satoshis || 0),\n\t\t0n,\n\t);\n\tlet fee = 0;\n\tfor (const utxo of utxos) {\n    const payKeyToUse = utxo.pk || paymentPk;\n\t\tif(!payKeyToUse) {\n\t\t\tthrow new Error(\"Private key is required to sign the payment\");\n\t\t}\n\t\tconst input = inputFromB64Utxo(\n\t\t\tutxo,\n\t\t\tnew P2PKH().unlock(\n\t\t\t\tpayKeyToUse,\n\t\t\t\t\"all\",\n\t\t\t\ttrue,\n\t\t\t\tutxo.satoshis,\n\t\t\t\tScript.fromBinary(Utils.toArray(utxo.script, \"base64\")),\n\t\t\t),\n\t\t);\n\n\t\ttx.addInput(input);\n\t\t// stop adding inputs if the total amount is enough\n\t\ttotalSatsIn += BigInt(utxo.satoshis);\n\t\tfee = await modelOrFee.computeFee(tx);\n\n\t\tif (totalSatsIn >= totalSatsOut + BigInt(fee)) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// make sure we have enough\n\tif (totalSatsIn < totalSatsOut + BigInt(fee)) {\n\t\tthrow new Error(\n\t\t\t`Not enough funds to purchase ordinal listing. Total sats in: ${totalSatsIn}, Total sats out: ${totalSatsOut}, Fee: ${fee}`,\n\t\t);\n\t}\n\n\t// estimate the cost of the transaction and assign change value\n\tawait tx.fee(modelOrFee);\n\n\t// Sign the transaction\n\tawait tx.sign();\n\n\t// check for change\n\tconst payChangeOutIdx = tx.outputs.findIndex((o) => o.change);\n\tif (payChangeOutIdx !== -1) {\n\t\tconst changeOutput = tx.outputs[payChangeOutIdx];\n\t\tpayChange = {\n\t\t\tsatoshis: changeOutput.satoshis as number,\n\t\t\ttxid: tx.id(\"hex\") as string,\n\t\t\tvout: payChangeOutIdx,\n\t\t\tscript: Buffer.from(changeOutput.lockingScript.toBinary()).toString(\n\t\t\t\t\"base64\",\n\t\t\t),\n\t\t};\n\t}\n\n\tif (payChange) {\n\t\tconst changeOutput = tx.outputs[tx.outputs.length - 1];\n\t\tpayChange.satoshis = changeOutput.satoshis as number;\n\t\tpayChange.txid = tx.id(\"hex\") as string;\n\t}\n\n\treturn {\n\t\ttx,\n\t\tspentOutpoints: tx.inputs.map(\n\t\t\t(i) => `${i.sourceTXID}_${i.sourceOutputIndex}`,\n\t\t),\n\t\tpayChange,\n\t};\n};\n\n/**\n *\n * @param {PurchaseOrdTokenListingConfig} config  - Configuration object for purchasing a token listing\n * @param {TokenType} config.protocol - Token protocol\n * @param {string} config.tokenID - Token ID\n * @param {Utxo[]} config.utxos - Utxos to spend (with base64 encoded scripts)\n * @param {PrivateKey} config.paymentPk - Private key to sign payment inputs\n * @param {Utxo} config.listingUtxo - Listing UTXO\n * @param {string} config.ordAddress - Address to send the ordinal to\n * @param {string} [config.changeAddress] - Optional. Address to send change to\n * @param {number} [config.satsPerKb] - Optional. Satoshis per kilobyte for fee calculation\n * @param {Payment[]} [config.additionalPayments] - Optional. Additional payments to make\n * @param {MAP} [config.metaData] - Optional. MAP (Magic Attribute Protocol) metadata to include on the purchased transfer inscription output\n * @returns {Promise<ChangeResult>} Transaction, spent outpoints, change utxo\n */\nexport const purchaseOrdTokenListing = async (\n\tconfig: PurchaseOrdTokenListingConfig,\n): Promise<ChangeResult> => {\n\tconst {\n\t\tprotocol,\n\t\ttokenID,\n\t\tutxos,\n\t\tpaymentPk,\n\t\tlistingUtxo,\n\t\tordAddress,\n\t\tsatsPerKb = DEFAULT_SAT_PER_KB,\n\t\tadditionalPayments = [],\n\t\tmetaData,\n\t} = config;\n\n\tconst modelOrFee = new SatoshisPerKilobyte(satsPerKb);\n\tconst tx = new Transaction();\n\n\t// Inputs\n\t// Add the locked ordinal we're purchasing\n\ttx.addInput(\n\t\tinputFromB64Utxo(\n\t\t\tlistingUtxo,\n\t\t\tnew OrdLock().purchaseListing(\n\t\t\t\t1,\n\t\t\t\tScript.fromBinary(Utils.toArray(listingUtxo.script, \"base64\")),\n\t\t\t),\n\t\t),\n\t);\n\n\t// Outputs\n\tconst transferInscription: TransferTokenInscription = {\n\t\tp: \"bsv-20\",\n\t\top: \"transfer\",\n\t\tamt: listingUtxo.amt,\n\t};\n\tlet inscription: TransferBSV20Inscription | TransferBSV21Inscription;\n\tif (protocol === TokenType.BSV20) {\n\t\tinscription = {\n\t\t\t...transferInscription,\n\t\t\ttick: tokenID,\n\t\t} as TransferBSV20Inscription;\n\t} else if (protocol === TokenType.BSV21) {\n\t\tinscription = {\n\t\t\t...transferInscription,\n\t\t\tid: tokenID,\n\t\t} as TransferBSV21Inscription;\n\t} else {\n\t\tthrow new Error(\"Invalid protocol\");\n\t}\n\tconst dataB64 = Buffer.from(JSON.stringify(inscription)).toString(\"base64\");\n\n\t// Add the purchased output\n\ttx.addOutput({\n\t\tsatoshis: 1,\n\t\tlockingScript: new OrdP2PKH().lock(\n\t\t\tordAddress,\n\t\t\t{\n\t\t\t\tdataB64,\n\t\t\t\tcontentType: \"application/bsv-20\",\n\t\t\t},\n\t\t\tmetaData,\n\t\t),\n\t});\n\n\tif (!listingUtxo.payout) {\n\t\tthrow new Error(\"Listing UTXO does not have a payout script\");\n\t}\n\n\t// Add the payment output\n\tconst reader = new Utils.Reader(Utils.toArray(listingUtxo.payout, \"base64\"));\n\tconst satoshis = reader.readUInt64LEBn().toNumber();\n\tconst scriptLength = reader.readVarIntNum();\n\tconst scriptBin = reader.read(scriptLength);\n\tconst lockingScript = LockingScript.fromBinary(scriptBin);\n\ttx.addOutput({\n\t\tsatoshis,\n\t\tlockingScript,\n\t});\n\n\t// Add additional payments if any\n\tfor (const p of additionalPayments) {\n\t\ttx.addOutput({\n\t\t\tsatoshis: p.amount,\n\t\t\tlockingScript: new P2PKH().lock(p.to),\n\t\t});\n\t}\n\n\t// add change to the outputs\n\tlet payChange: Utxo | undefined;\n  const changeAddress = config.changeAddress || paymentPk?.toAddress();\n\tif (!changeAddress) {\n\t\tthrow new Error(\"Either changeAddress or paymentPk is required\");\n\t}\n\tconst changeScript = new P2PKH().lock(changeAddress);\n\tconst changeOut = {\n\t\tlockingScript: changeScript,\n\t\tchange: true,\n\t};\n\ttx.addOutput(changeOut);\n\n\tlet totalSatsIn = 0n;\n\tconst totalSatsOut = tx.outputs.reduce(\n\t\t(total, out) => total + BigInt(out.satoshis || 0),\n\t\t0n,\n\t);\n\tlet fee = 0;\n\tfor (const utxo of utxos) {\n    const payKeyToUse = utxo.pk || paymentPk;\n\t\tif (!payKeyToUse) {\n\t\t\tthrow new Error(\"Private key is required to sign the payment\");\n\t\t}\n\t\tconst input = inputFromB64Utxo(\n\t\t\tutxo,\n\t\t\tnew P2PKH().unlock(\n\t\t\t\tpayKeyToUse,\n\t\t\t\t\"all\",\n\t\t\t\ttrue,\n\t\t\t\tutxo.satoshis,\n\t\t\t\tScript.fromBinary(Utils.toArray(utxo.script, \"base64\")),\n\t\t\t),\n\t\t);\n\n\t\ttx.addInput(input);\n\t\t// stop adding inputs if the total amount is enough\n\t\ttotalSatsIn += BigInt(utxo.satoshis);\n\t\tfee = await modelOrFee.computeFee(tx);\n\n\t\tif (totalSatsIn >= totalSatsOut + BigInt(fee)) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// make sure we have enough\n\tif (totalSatsIn < totalSatsOut + BigInt(fee)) {\n\t\tthrow new Error(\n\t\t\t`Not enough funds to purchase token listing. Total sats in: ${totalSatsIn}, Total sats out: ${totalSatsOut}, Fee: ${fee}`,\n\t\t);\n\t}\n\n\t// estimate the cost of the transaction and assign change value\n\tawait tx.fee(modelOrFee);\n\n\t// Sign the transaction\n\tawait tx.sign();\n\n\tconst payChangeOutIdx = tx.outputs.findIndex((o) => o.change);\n\tif (payChangeOutIdx !== -1) {\n\t\tconst changeOutput = tx.outputs[payChangeOutIdx];\n\t\tpayChange = {\n\t\t\tsatoshis: changeOutput.satoshis as number,\n\t\t\ttxid: tx.id(\"hex\") as string,\n\t\t\tvout: payChangeOutIdx,\n\t\t\tscript: Buffer.from(changeOutput.lockingScript.toBinary()).toString(\n\t\t\t\t\"base64\",\n\t\t\t),\n\t\t};\n\t}\n\n\tif (payChange) {\n\t\tconst changeOutput = tx.outputs[tx.outputs.length - 1];\n\t\tpayChange.satoshis = changeOutput.satoshis as number;\n\t\tpayChange.txid = tx.id(\"hex\") as string;\n\t}\n\n\treturn {\n\t\ttx,\n\t\tspentOutpoints: tx.inputs.map(\n\t\t\t(i) => `${i.sourceTXID}_${i.sourceOutputIndex}`,\n\t\t),\n\t\tpayChange,\n\t};\n};\n",
    "// import { PaymailClient } from \"@bsv/paymail\";\nimport { LockingScript } from \"@bsv/sdk\";\n\n// const client = new PaymailClient();\n\nexport const resolvePaymail = async (paymailAddress: string, amtToReceive: number): Promise<LockingScript> => {\n  // const destinationTx = await client.getP2pPaymentDestination(paymailAddress, amtToReceive);\n  // // TODO: we are assuming only one output but in reality it can be many\n  // return destinationTx.outputs[0].script as LockingScript;\n  throw new Error(\"Not implemented\");\n}",
    "import {\n\tP2PKH,\n\tSatoshisPerKilobyte,\n\tScript,\n\tTransaction,\n\ttype TransactionOutput,\n\tUtils,\n} from \"@bsv/sdk\";\nimport { DEFAULT_SAT_PER_KB } from \"./constants\";\nimport { signData } from \"./signData\";\nimport OrdP2PKH from \"./templates/ordP2pkh\";\nimport type {\n\tChangeResult,\n\tDeployBsv21TokenConfig,\n\tDeployMintTokenInscription,\n\tInscription,\n\tUtxo,\n} from \"./types\";\nimport { validIconData, validIconFormat } from \"./utils/icon\";\nimport { inputFromB64Utxo } from \"./utils/utxo\";\n\n/**\n * Deploys & Mints a BSV21 token to the given destination address\n * @param {DeployBsv21TokenConfig} config - Configuration object for deploying BSV21 token\n * @param {string} config.symbol - Token ticker symbol\n * @param {number} config.decimals - Number of decimal places to display\n * @param {string | IconInscription} config.icon - outpoint (format: txid_vout) or Inscription. If Inscription, must be a valid image type\n * @param {Utxo[]} config.utxos - Payment Utxos available to spend. Will only consume what is needed.\n * @param {Distribution} config.initialDistribution - Initial distribution with addresses and total supply (not adjusted for decimals, library will add zeros)\n * @param {PrivateKey} config.paymentPk - Private key to sign paymentUtxos\n * @param {string} config.destinationAddress - Address to deploy token to.\n * @param {string} [config.changeAddress] - Optional. Address to send payment change to, if any. If not provided, defaults to paymentPk address\n * @param {number} [config.satsPerKb] - Optional. Satoshis per kilobyte for fee calculation. Default is DEFAULT_SAT_PER_KB\n * @param {Payment[]} [config.additionalPayments] - Optional. Additional payments to include in the transaction\n * @returns {Promise<ChangeResult>} Transaction to deploy BSV 2.1 token\n */\nexport const deployBsv21Token = async (\n\tconfig: DeployBsv21TokenConfig,\n): Promise<ChangeResult> => {\n\tconst {\n\t\tsymbol,\n\t\ticon,\n\t\tdecimals,\n\t\tutxos,\n\t\tinitialDistribution,\n\t\tpaymentPk,\n\t\tdestinationAddress,\n\t\tsatsPerKb = DEFAULT_SAT_PER_KB,\n\t\tadditionalPayments = [],\n\t\tsigner,\n\t\tsignInputs = true,\n\t} = config;\n\n\tconst modelOrFee = new SatoshisPerKilobyte(satsPerKb);\n\n\tlet tx = new Transaction();\n\n\tlet iconValue: string;\n\tif (typeof icon === \"string\") {\n\t\ticonValue = icon;\n\t} else {\n\t\tconst iconError = await validIconData(icon);\n\t\tif (iconError) {\n\t\t\tthrow iconError;\n\t\t}\n\t\t// add icon inscription to the transaction\n\t\tconst iconScript = new OrdP2PKH().lock(destinationAddress, icon);\n\t\tconst iconOut = {\n\t\t\tsatoshis: 1,\n\t\t\tlockingScript: iconScript,\n\t\t};\n\t\ttx.addOutput(iconOut);\n\t\t// relative output index of the icon\n\t\ticonValue = \"_0\";\n\t}\n\n\t// Ensure the icon format\n\tif (!validIconFormat(iconValue)) {\n\t\tthrow new Error(\n\t\t\t\"Invalid icon format. Must be either outpoint (format: txid_vout) or relative output index of the icon (format _vout). examples: ecb483eda58f26da1b1f8f15b782b1186abdf9c6399a1c3e63e0d429d5092a41_0 or _1\",\n\t\t);\n\t}\n  \n\t// Outputs\n  const tsatAmt = decimals ? BigInt(initialDistribution.tokens) * 10n ** BigInt(decimals) : BigInt(initialDistribution.tokens);\n\tconst fileData: DeployMintTokenInscription = {\n\t\tp: \"bsv-20\",\n\t\top: \"deploy+mint\",\n\t\tsym: symbol,\n\t\ticon: iconValue,\n\t\tamt: tsatAmt.toString(),\n\t};\n\n  if (decimals) {\n    fileData.dec = decimals.toString();\n  }\n\n\tconst b64File = Buffer.from(JSON.stringify(fileData)).toString(\"base64\");\n\tconst sendTxOut = {\n\t\tsatoshis: 1,\n\t\tlockingScript: new OrdP2PKH().lock(destinationAddress, {\n\t\t\tdataB64: b64File,\n\t\t\tcontentType: \"application/bsv-20\",\n\t\t} as Inscription),\n\t};\n\ttx.addOutput(sendTxOut);\n\n\t// Additional payments\n\tfor (const payment of additionalPayments) {\n\t\tconst sendTxOut: TransactionOutput = {\n\t\t\tsatoshis: payment.amount,\n\t\t\tlockingScript: new P2PKH().lock(payment.to),\n\t\t};\n\t\ttx.addOutput(sendTxOut);\n\t}\n\n\t// Inputs\n\tlet totalSatsIn = 0n;\n\tconst totalSatsOut = tx.outputs.reduce(\n\t\t(total, out) => total + BigInt(out.satoshis || 0),\n\t\t0n,\n\t);\n\n\tlet fee = 0;\n\n\tif(signer) {\n\t\tconst utxo = utxos.pop() as Utxo\n\t\tif (signInputs) {\n\t\t\tconst payKeyToUse = utxo.pk || paymentPk;\n\t\t\tif(!payKeyToUse) {\n\t\t\t\tthrow new Error(\"Private key is required to sign the transaction\");\n\t\t\t}\n\t\t\ttx.addInput(inputFromB64Utxo(utxo, new P2PKH().unlock(\n\t\t\t\tpayKeyToUse,\n\t\t\t\t\"all\",\n\t\t\t\ttrue,\n\t\t\t\tutxo.satoshis,\n\t\t\t\tScript.fromBinary(Utils.toArray(utxo.script, 'base64'))\n\t\t\t)));\n\t\t} else {\n\t\t\ttx.addInput(inputFromB64Utxo(utxo));\n\t\t}\n\t\ttotalSatsIn += BigInt(utxo.satoshis);\n\t\ttx = await signData(tx, signer);\n\t\t// Calculate fee after signing since it adds OP_RETURN outputs\n\t\tfee = await modelOrFee.computeFee(tx);\n\t}\n\tfor (const utxo of utxos) {\n\t\tif (signInputs) {\n\t\t\tconst payKeyToUse = utxo.pk || paymentPk;\n\t\t\tif (!payKeyToUse) {\n\t\t\t\tthrow new Error(\"Private key is required to sign the payment\");\n\t\t\t}\n\t\t\tconst input = inputFromB64Utxo(utxo, new P2PKH().unlock(\n\t\t\t\tpayKeyToUse,\n\t\t\t\t\"all\",\n\t\t\t\ttrue,\n\t\t\t\tutxo.satoshis,\n\t\t\t\tScript.fromBinary(Utils.toArray(utxo.script, 'base64'))\n\t\t\t));\n\t\t\ttx.addInput(input);\n\t\t} else {\n\t\t\ttx.addInput(inputFromB64Utxo(utxo));\n\t\t}\n\t\t// stop adding inputs if the total amount is enough\n\t\ttotalSatsIn += BigInt(utxo.satoshis);\n\t\tfee = await modelOrFee.computeFee(tx);\n\n\t\tif (totalSatsIn >= totalSatsOut + BigInt(fee)) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// make sure we have enough\n\tif (totalSatsIn < totalSatsOut + BigInt(fee)) {\n\t\tthrow new Error(\n\t\t\t`Not enough funds to deploy token. Total sats in: ${totalSatsIn}, Total sats out: ${totalSatsOut}, Fee: ${fee}`,\n\t\t);\n\t}\n\n\t// if we need to send change, add it to the outputs\n\tlet payChange: Utxo | undefined;\n  const changeAddress = config.changeAddress || paymentPk?.toAddress();\n\tif(!changeAddress) {\n\t\tthrow new Error(\"Either changeAddress or paymentPk is required\");\n\t}\n\n\tconst changeScript = new P2PKH().lock(changeAddress);\n\tconst changeOut = {\n\t\tlockingScript: changeScript,\n\t\tchange: true,\n\t};\n\ttx.addOutput(changeOut);\n\n\t// estimate the cost of the transaction and assign change value\n\tawait tx.fee(modelOrFee);\n\n\t// Sign the transaction (if signInputs is true)\n\tif (signInputs) {\n\t\tawait tx.sign();\n\t}\n\n\t// check for change\n\tconst payChangeOutIdx = tx.outputs.findIndex((o) => o.change);\n\tif (payChangeOutIdx !== -1) {\n\t\tconst changeOutput = tx.outputs[payChangeOutIdx];\n\t\tpayChange = {\n\t\t\tsatoshis: changeOutput.satoshis as number,\n\t\t\ttxid: tx.id(\"hex\") as string,\n\t\t\tvout: payChangeOutIdx,\n\t\t\tscript: Buffer.from(changeOutput.lockingScript.toBinary()).toString(\n\t\t\t\t\"base64\",\n\t\t\t),\n\t\t};\n\t}\n\n\treturn {\n\t\ttx,\n\t\tspentOutpoints: tx.inputs.map(\n\t\t\t(i) => `${i.sourceTXID}_${i.sourceOutputIndex}`,\n\t\t),\n\t\tpayChange,\n\t};\n};\n",
    "import { imageMeta } from \"image-meta\";\nimport { Utils } from \"@bsv/sdk\";\nimport type { IconInscription, ImageContentType } from \"../types\";\nconst { toArray } = Utils;\n\nexport const ErrorOversizedIcon = new Error(\n    \"Image must be a square image with dimensions <= 400x400\",\n);\nexport const ErrorIconProportions = new Error(\"Image must be a square image\");\nexport const ErrorInvalidIconData = new Error(\"Error processing image\");\nexport const ErrorImageDimensionsUndefined = new Error(\n    \"Image dimensions are undefined\",\n);\n\nconst isImageContentType = (value: string): value is ImageContentType => {\n    return (value as ImageContentType) === value;\n};\n\nexport const validIconData = async (\n    icon: IconInscription,\n): Promise<Error | null> => {\n    const { dataB64, contentType } = icon;\n\n    if (contentType === \"image/svg+xml\") {\n        return validateSvg(dataB64);\n    }\n\n    if (!isImageContentType(contentType)) {\n        return ErrorInvalidIconData;\n    }\n\n    try {\n        const buffer = Uint8Array.from(toArray(dataB64, \"base64\"));\n\n        // Meta contains { type, width?, height?, orientation? }\n        const dimensions = imageMeta(buffer);\n\n        if (dimensions.width === undefined || dimensions.height === undefined) {\n            return ErrorImageDimensionsUndefined;\n        }\n        if (dimensions.width !== dimensions.height) {\n            return ErrorIconProportions;\n        }\n        if (dimensions.width > 400 || dimensions.height > 400) {\n            return ErrorOversizedIcon;\n        }\n\n        return null;\n    } catch (error) {\n        return ErrorInvalidIconData;\n    }\n};\n\nconst validateSvg = (svgBase64: string): Error | null => {\n    const svgString = Buffer.from(svgBase64, \"base64\").toString(\"utf-8\");\n    const widthMatch = svgString.match(/<svg[^>]*\\s+width=\"([^\"]+)\"/);\n    const heightMatch = svgString.match(/<svg[^>]*\\s+height=\"([^\"]+)\"/);\n    \n    if (!widthMatch || !heightMatch) {\n        return ErrorImageDimensionsUndefined;\n    }\n\n    const width = Number.parseInt(widthMatch[1], 10);\n    const height = Number.parseInt(heightMatch[1], 10);\n\n    if (Number.isNaN(width) || Number.isNaN(height)) {\n        return ErrorImageDimensionsUndefined;\n    }\n\n    if (width !== height) {\n        return ErrorIconProportions;\n    }\n    if (width > 400 || height > 400) {\n        return ErrorOversizedIcon;\n    }\n\n    return null;\n}\n\nexport const validIconFormat = (icon: string): boolean => {\n    if (!icon.includes(\"_\") || icon.endsWith(\"_\")) {\n        return false;\n    }\n\n    const iconVout = Number.parseInt(icon.split(\"_\")[1]);\n    if (Number.isNaN(iconVout)) {\n        return false;\n    }\n\n    if (!icon.startsWith(\"_\") && icon.split(\"_\")[0].length !== 64) {\n        return false;\n    }\n\n    return true;\n};\n\n",
    "import {\n\tTransaction,\n\tSatoshisPerKilobyte,\n\tScript,\n\tUtils,\n  PrivateKey,\n} from \"@bsv/sdk\";\nimport { DEFAULT_SAT_PER_KB, MAP_PREFIX } from \"./constants\";\nimport OrdP2PKH from \"./templates/ordP2pkh\";\nimport type {\n  BaseResult,\n\tBurnOrdinalsConfig,\n} from \"./types\";\nimport { inputFromB64Utxo } from \"./utils/utxo\";\nimport { toHex } from \"./utils/strings\";\n\n/**\n * Burn ordinals by consuming them as fees\n * @param {BurnOrdinalsConfig} config - Configuration object for sending ordinals\n * @param {PrivateKey} config.ordPk - Private key to sign ordinals\n * @param {Utxo} config.ordinals - 1Sat Ordinal Utxos to spend (with base64 encoded scripts)\n * @param {BurnMAP} [config.metaData] - Optional. MAP (Magic Attribute Protocol) metadata to include in an unspendable output OP_FALSE OP_RETURN\n * @returns {Promise<BaseResult>} Transaction, spent outpoints\n */\nexport const burnOrdinals = async (\n\tconfig: BurnOrdinalsConfig,\n): Promise<BaseResult> => {\n\tconst tx = new Transaction();\n\tconst spentOutpoints: string[] = [];\n\tconst { ordinals, metaData, ordPk } = config;\n\n\t// Inputs\n\t// Add ordinal inputs\n\tfor (const ordUtxo of ordinals) {\n\t\tif (ordUtxo.satoshis !== 1) {\n\t\t\tthrow new Error(\"1Sat Ordinal utxos must have exactly 1 satoshi\");\n\t\t}\n    const ordKeyToUse = ordUtxo.pk || ordPk;\n\t\tif(!ordKeyToUse) {\n\t\t\tthrow new Error(\"Private key is required to sign the ordinal\");\n\t\t}\n\n\t\tconst input = inputFromB64Utxo(\n\t\t\tordUtxo,\n\t\t\tnew OrdP2PKH().unlock(\n\t\t\t\tordKeyToUse,\n\t\t\t\t\"all\",\n\t\t\t\ttrue,\n\t\t\t\tordUtxo.satoshis,\n\t\t\t\tScript.fromBinary(Utils.toArray(ordUtxo.script, \"base64\")),\n\t\t\t),\n\t\t);\n\t\tspentOutpoints.push(`${ordUtxo.txid}_${ordUtxo.vout}`);\n\t\ttx.addInput(input);\n\t}\n\n\t// Outputs\n\t// Add metadata output\n\n\t// MAP.app and MAP.type keys are required\n\tif (metaData && (!metaData.app || !metaData.type)) {\n\t\tthrow new Error(\"MAP.app and MAP.type are required fields\");\n\t}\n\n\tlet metaAsm = \"\";\n\n\tif (metaData?.app && metaData?.type) {\n\t\tconst mapPrefixHex = toHex(MAP_PREFIX);\n\t\tconst mapCmdValue = toHex(\"SET\");\n\t\tmetaAsm = `OP_FALSE OP_RETURN ${mapPrefixHex} ${mapCmdValue}`;\n\n\t\tfor (const [key, value] of Object.entries(metaData)) {\n\t\t\tif (key !== \"cmd\") {\n\t\t\t\tmetaAsm = `${metaAsm} ${toHex(key)} ${toHex(value as string)}`;\n\t\t\t}\n\t\t}\n\t}\n\n\ttx.addOutput({\n\t\tsatoshis: 0,\n\t\tlockingScript: Script.fromASM(metaAsm || \"OP_FALSE OP_RETURN\"),\n\t});\n\n\t// Sign the transaction\n\tawait tx.sign();\n\n\treturn {\n\t\ttx,\n\t\tspentOutpoints,\n\t};\n};\n",
    "import {\n\ttype BroadcastFailure,\n\ttype Broadcaster,\n\ttype BroadcastResponse,\n\ttype Transaction,\n\ttype HttpClient,\n  Utils,\n} from \"@bsv/sdk\";\nimport { API_HOST } from \"../constants.js\";\nimport { defaultHttpClient } from \"./httpClient.js\";\n\nexport const oneSatBroadcaster = (): Broadcaster => {\n\treturn new OneSatBroadcaster();\n};\n\n/**\n * Represents a 1Sat API transaction broadcaster. This will broadcast through the 1Sat API.\n */\nexport default class OneSatBroadcaster implements Broadcaster {\n\tprivate readonly URL: string;\n\tprivate readonly httpClient: HttpClient;\n\n\t/**\n\t * Constructs an instance of the 1Sat API broadcaster.\n\t *\n\t * @param {HttpClient} httpClient - The HTTP client used to make requests to the API.\n\t */\n\tconstructor(\n\t\thttpClient: HttpClient = defaultHttpClient(),\n\t) {\n\t\tthis.URL = `${API_HOST}/tx`;\n\t\tthis.httpClient = httpClient;\n\t}\n\n\t/**\n\t * Broadcasts a transaction via WhatsOnChain.\n\t *\n\t * @param {Transaction} tx - The transaction to be broadcasted.\n\t * @returns {Promise<BroadcastResponse | BroadcastFailure>} A promise that resolves to either a success or failure response.\n\t */\n\tasync broadcast(\n\t\ttx: Transaction,\n\t): Promise<BroadcastResponse | BroadcastFailure> {\n\t\tconst rawtx = Utils.toBase64(tx.toBinary());\n\n\t\tconst requestOptions = {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\tAccept: \"application/json\",\n\t\t\t},\n\t\t\tdata: { rawtx },\n\t\t};\n\n\t\ttry {\n\t\t\tconst response = await this.httpClient.request<string>(\n\t\t\t\tthis.URL,\n\t\t\t\trequestOptions,\n\t\t\t);\n\t\t\tif (response.ok) {\n\t\t\t\tconst txid = response.data;\n\t\t\t\treturn {\n\t\t\t\t\tstatus: \"success\",\n\t\t\t\t\ttxid,\n\t\t\t\t\tmessage: \"broadcast successful\",\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tstatus: \"error\",\n\t\t\t\tcode: response.status.toString() ?? \"ERR_UNKNOWN\",\n\t\t\t\tdescription: response.data.message ?? \"Unknown error\",\n\t\t\t};\n\t\t} catch (error) {\n\t\t\treturn {\n\t\t\t\tstatus: \"error\",\n\t\t\t\tcode: \"500\",\n\t\t\t\tdescription: error instanceof Error\n\t\t\t\t\t? error.message\n\t\t\t\t\t: \"Internal Server Error\",\n\t\t\t};\n\t\t}\n\t}\n}\n\n",
    "import { type HttpClient, type HttpClientResponse, NodejsHttpClient } from \"@bsv/sdk\"\nimport { FetchHttpClient } from \"./fetch\"\n\nexport function defaultHttpClient (): HttpClient {\n  const noHttpClient: HttpClient = {\n    async request (..._): Promise<HttpClientResponse> {\n      throw new Error('No method available to perform HTTP request')\n    }\n  }\n\n  if (typeof window !== 'undefined' && typeof window.fetch === 'function') {\n    // Use fetch in a browser environment\n    return new FetchHttpClient(window.fetch.bind(window))\n  }\n  if (typeof require !== 'undefined') {\n    // Use Node.js https module\n    try {\n      const https = require('node:https')\n      return new NodejsHttpClient(https)\n    } catch (e) {\n      return noHttpClient\n    }\n  } else {\n    return noHttpClient\n  }\n}\n",
    "\n/** fetch function interface limited to options needed by ts-sdk */\n\nimport type { HttpClient, HttpClientRequestOptions, HttpClientResponse } from \"@bsv/sdk\"\n\n/**\n   * Makes a request to the server.\n   * @param url The URL to make the request to.\n   * @param options The request configuration.\n   */\nexport type Fetch = (url: string, options: FetchOptions) => Promise<Response>\n\n/**\n * An interface for configuration of the request to be passed to the fetch method\n * limited to options needed by ts-sdk.\n */\nexport interface FetchOptions {\n  /** A string to set request's method. */\n  method?: string\n  /** An object literal set request's headers. */\n  headers?: Record<string, string>\n  /** An object or null to set request's body. */\n  body?: string | null\n}\n\n/**\n * Adapter for Node.js Https module to be used as HttpClient\n */\nexport class FetchHttpClient implements HttpClient {\n  constructor (private readonly fetch: Fetch) {}\n\n  async request<D>(url: string, options: HttpClientRequestOptions): Promise<HttpClientResponse<D>> {\n    const fetchOptions: FetchOptions = {\n      method: options.method,\n      headers: options.headers,\n      body: JSON.stringify(options.data)\n    }\n\n    const res = await this.fetch.call(window, url, fetchOptions)\n    const mediaType = res.headers.get('Content-Type')\n    const data = mediaType?.startsWith('application/json') ? await res.json() : await res.text()\n\n    return {\n      ok: res.ok,\n      status: res.status,\n      statusText: res.statusText,\n      data: data as D\n    }\n  }\n}\n"
  ],
  "mappings": "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",
  "debugId": "D8502358B257810664756E2164756E21",
  "names": []
}