@arkade-os/sdk 0.4.64 → 0.4.66

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/dist/adapters/expo.cjs +5 -5
  2. package/dist/adapters/expo.d.cts +3 -6
  3. package/dist/adapters/expo.d.ts +3 -6
  4. package/dist/adapters/expo.js +3 -3
  5. package/dist/adapters/indexedDB.cjs +5 -5
  6. package/dist/adapters/indexedDB.js +4 -4
  7. package/dist/{asyncStorageTaskQueue-Dq_UcvDx.d.ts → asyncStorageTaskQueue-B6SijMi3.d.ts} +1 -1
  8. package/dist/{asyncStorageTaskQueue-Chwe60Ce.d.cts → asyncStorageTaskQueue-BZcIN7sA.d.cts} +1 -1
  9. package/dist/{chunk-HQ2DDMQN.js → chunk-2JZGPXU4.js} +170 -6
  10. package/dist/chunk-2JZGPXU4.js.map +1 -0
  11. package/dist/{chunk-RXITDAV4.cjs → chunk-3S3JZUEN.cjs} +184 -19
  12. package/dist/chunk-3S3JZUEN.cjs.map +1 -0
  13. package/dist/{chunk-USXWE2EJ.js → chunk-55ZZ6RBL.js} +4 -4
  14. package/dist/{chunk-USXWE2EJ.js.map → chunk-55ZZ6RBL.js.map} +1 -1
  15. package/dist/{chunk-LPEE2H2M.cjs → chunk-5E6IZNRG.cjs} +656 -774
  16. package/dist/chunk-5E6IZNRG.cjs.map +1 -0
  17. package/dist/{chunk-LN2VZP63.js → chunk-CYOI4PEA.js} +162 -15
  18. package/dist/chunk-CYOI4PEA.js.map +1 -0
  19. package/dist/{chunk-WJN2BLEI.js → chunk-DSC3G6QZ.js} +253 -379
  20. package/dist/chunk-DSC3G6QZ.js.map +1 -0
  21. package/dist/{chunk-4N45WCSJ.cjs → chunk-IM6IKNSL.cjs} +17 -17
  22. package/dist/{chunk-4N45WCSJ.cjs.map → chunk-IM6IKNSL.cjs.map} +1 -1
  23. package/dist/{chunk-XJCBV4AA.js → chunk-J33ZEM3A.js} +26 -18
  24. package/dist/chunk-J33ZEM3A.js.map +1 -0
  25. package/dist/{chunk-35YIP6OA.cjs → chunk-LL47QIHD.cjs} +10 -10
  26. package/dist/{chunk-35YIP6OA.cjs.map → chunk-LL47QIHD.cjs.map} +1 -1
  27. package/dist/{chunk-WXCVS6PD.cjs → chunk-PXPPZF5K.cjs} +207 -59
  28. package/dist/chunk-PXPPZF5K.cjs.map +1 -0
  29. package/dist/{chunk-ZUEGFM3T.js → chunk-R5POS3RS.js} +4 -4
  30. package/dist/{chunk-ZUEGFM3T.js.map → chunk-R5POS3RS.js.map} +1 -1
  31. package/dist/{chunk-FZFSGOTZ.cjs → chunk-ZIRFXBKL.cjs} +26 -18
  32. package/dist/chunk-ZIRFXBKL.cjs.map +1 -0
  33. package/dist/contracts/handlers/index.cjs +9 -9
  34. package/dist/contracts/handlers/index.d.cts +3 -3
  35. package/dist/contracts/handlers/index.d.ts +3 -3
  36. package/dist/contracts/handlers/index.js +2 -2
  37. package/dist/{delegate-Dv_9OVHv.d.ts → delegate-T-vgxMYZ.d.ts} +1 -1
  38. package/dist/{delegate-BBQW61ym.d.cts → delegate-YXupcWWJ.d.cts} +1 -1
  39. package/dist/{index-Bxe9kBFs.d.ts → index-D_FgwLH9.d.ts} +111 -2
  40. package/dist/{index-aZycGEsQ.d.cts → index-e7LYXk1d.d.cts} +111 -2
  41. package/dist/{index-CFOMyVMt.d.cts → index-uUE_uQPn.d.cts} +70 -33
  42. package/dist/{index-CFOMyVMt.d.ts → index-uUE_uQPn.d.ts} +70 -33
  43. package/dist/index.cjs +308 -268
  44. package/dist/index.d.cts +214 -19
  45. package/dist/index.d.ts +214 -19
  46. package/dist/index.js +4 -4
  47. package/dist/repositories/realm/index.cjs +19 -19
  48. package/dist/repositories/realm/index.d.cts +2 -2
  49. package/dist/repositories/realm/index.d.ts +2 -2
  50. package/dist/repositories/realm/index.js +5 -5
  51. package/dist/repositories/sqlite/index.cjs +18 -18
  52. package/dist/repositories/sqlite/index.d.cts +2 -2
  53. package/dist/repositories/sqlite/index.d.ts +2 -2
  54. package/dist/repositories/sqlite/index.js +5 -5
  55. package/dist/{taskRunner-CIKOS2OO.d.cts → taskRunner-BOVcIH1N.d.cts} +1 -1
  56. package/dist/{taskRunner-BDzWbpct.d.ts → taskRunner-DNyD1kXG.d.ts} +1 -1
  57. package/dist/wallet/expo/background.cjs +14 -14
  58. package/dist/wallet/expo/background.d.cts +3 -3
  59. package/dist/wallet/expo/background.d.ts +3 -3
  60. package/dist/wallet/expo/background.js +6 -6
  61. package/dist/wallet/expo/index.cjs +14 -14
  62. package/dist/wallet/expo/index.d.cts +4 -4
  63. package/dist/wallet/expo/index.d.ts +4 -4
  64. package/dist/wallet/expo/index.js +5 -5
  65. package/dist/{wallet-C2NvHjWB.d.cts → wallet-CNibc3yJ.d.ts} +3 -3
  66. package/dist/{wallet-DJUnN939.d.ts → wallet-DJN1QgFt.d.cts} +3 -3
  67. package/dist/worker/expo/index.cjs +9 -9
  68. package/dist/worker/expo/index.d.cts +4 -4
  69. package/dist/worker/expo/index.d.ts +4 -4
  70. package/dist/worker/expo/index.js +5 -5
  71. package/package.json +1 -1
  72. package/dist/chunk-FZFSGOTZ.cjs.map +0 -1
  73. package/dist/chunk-HQ2DDMQN.js.map +0 -1
  74. package/dist/chunk-LN2VZP63.js.map +0 -1
  75. package/dist/chunk-LPEE2H2M.cjs.map +0 -1
  76. package/dist/chunk-RXITDAV4.cjs.map +0 -1
  77. package/dist/chunk-WJN2BLEI.js.map +0 -1
  78. package/dist/chunk-WXCVS6PD.cjs.map +0 -1
  79. package/dist/chunk-XJCBV4AA.js.map +0 -1
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var chunkLPEE2H2M_cjs = require('./chunk-LPEE2H2M.cjs');
4
- var chunkFZFSGOTZ_cjs = require('./chunk-FZFSGOTZ.cjs');
3
+ var chunk5E6IZNRG_cjs = require('./chunk-5E6IZNRG.cjs');
4
+ var chunkZIRFXBKL_cjs = require('./chunk-ZIRFXBKL.cjs');
5
5
 
6
6
  // src/worker/expo/taskRunner.ts
7
7
  async function runTasks(queue, processors, deps) {
@@ -33,7 +33,7 @@ async function runTasks(queue, processors, deps) {
33
33
  }
34
34
  const result = {
35
35
  ...partial,
36
- id: chunkLPEE2H2M_cjs.getRandomId(),
36
+ id: chunk5E6IZNRG_cjs.getRandomId(),
37
37
  executedAt: Date.now()
38
38
  };
39
39
  await queue.pushResult(result);
@@ -45,7 +45,7 @@ async function runTasks(queue, processors, deps) {
45
45
  function createTaskDependencies(options) {
46
46
  return {
47
47
  ...options,
48
- extendVtxo: (vtxo, contract) => chunkLPEE2H2M_cjs.extendVirtualCoinForContract(vtxo, contract)
48
+ extendVtxo: (vtxo, contract) => chunk5E6IZNRG_cjs.extendVirtualCoinForContract(vtxo, contract)
49
49
  };
50
50
  }
51
51
 
@@ -55,7 +55,7 @@ var contractPollProcessor = {
55
55
  taskType: CONTRACT_POLL_TASK_TYPE,
56
56
  async execute(item, deps) {
57
57
  const { contractRepository, walletRepository, indexerProvider, extendVtxo } = deps;
58
- const contracts = (await contractRepository.getContracts()).filter(chunkLPEE2H2M_cjs.isWatchedContract);
58
+ const contracts = (await contractRepository.getContracts()).filter(chunk5E6IZNRG_cjs.isWatchedContract);
59
59
  let contractsProcessed = 0;
60
60
  let vtxosSaved = 0;
61
61
  for (const contract of contracts) {
@@ -64,7 +64,7 @@ var contractPollProcessor = {
64
64
  let hasMore = true;
65
65
  const allVtxos = [];
66
66
  while (hasMore) {
67
- const { vtxos, page } = await chunkFZFSGOTZ_cjs.getNormalizedVtxos(indexerProvider, {
67
+ const { vtxos, page } = await chunkZIRFXBKL_cjs.getNormalizedVtxos(indexerProvider, {
68
68
  scripts: [contract.script],
69
69
  pageIndex,
70
70
  pageSize
@@ -75,12 +75,12 @@ var contractPollProcessor = {
75
75
  hasMore = page ? vtxos.length === pageSize : false;
76
76
  pageIndex++;
77
77
  }
78
- const filtered = chunkLPEE2H2M_cjs.warnAndFilterVtxosForScript(
78
+ const filtered = chunk5E6IZNRG_cjs.warnAndFilterVtxosForScript(
79
79
  allVtxos,
80
80
  contract.script,
81
81
  "contractPollProcessor"
82
82
  );
83
- await chunkLPEE2H2M_cjs.saveVtxosForContract(walletRepository, contract, filtered);
83
+ await chunk5E6IZNRG_cjs.saveVtxosForContract(walletRepository, contract, filtered);
84
84
  vtxosSaved += filtered.length;
85
85
  contractsProcessed++;
86
86
  }
@@ -97,5 +97,5 @@ exports.CONTRACT_POLL_TASK_TYPE = CONTRACT_POLL_TASK_TYPE;
97
97
  exports.contractPollProcessor = contractPollProcessor;
98
98
  exports.createTaskDependencies = createTaskDependencies;
99
99
  exports.runTasks = runTasks;
100
- //# sourceMappingURL=chunk-35YIP6OA.cjs.map
101
- //# sourceMappingURL=chunk-35YIP6OA.cjs.map
100
+ //# sourceMappingURL=chunk-LL47QIHD.cjs.map
101
+ //# sourceMappingURL=chunk-LL47QIHD.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/worker/expo/taskRunner.ts","../src/worker/expo/processors/contractPollProcessor.ts"],"names":["getRandomId","extendVirtualCoinForContract","isWatchedContract","getNormalizedVtxos","warnAndFilterVtxosForScript","saveVtxosForContract"],"mappings":"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","file":"chunk-35YIP6OA.cjs","sourcesContent":["import type { TaskItem, TaskResult, TaskQueue } from \"./taskQueue\";\nimport type { WalletRepository } from \"../../repositories/walletRepository\";\nimport type { ContractRepository } from \"../../repositories/contractRepository\";\nimport type { IndexerProvider } from \"../../providers/indexer\";\nimport type { ArkProvider } from \"../../providers/ark\";\nimport type { ExtendedVirtualCoin, VirtualCoin } from \"../../wallet\";\nimport type { Contract } from \"../../contracts/types\";\nimport { getRandomId, extendVirtualCoinForContract } from \"../../wallet/utils\";\n\n/**\n * Shared dependencies injected into every processor at runtime.\n *\n * `extendVtxo` requires the owning contract — processors must resolve each\n * vtxo's `script` to a known contract (via the contract repository) before\n * calling this. The strict signature prevents the footgun where a missing\n * contract silently falls back to the wallet's default tapscript.\n */\nexport interface TaskDependencies {\n walletRepository: WalletRepository;\n contractRepository: ContractRepository;\n indexerProvider: IndexerProvider;\n arkProvider: ArkProvider;\n extendVtxo: (vtxo: VirtualCoin, contract: Contract) => ExtendedVirtualCoin;\n}\n\n/**\n * A stateless unit that handles one type of task item.\n *\n * Processors must not keep in-memory state across invocations —\n * all coordination lives in the @see TaskQueue and repositories.\n *\n * The `TDeps` parameter defaults to @see TaskDependencies but\n * can be overridden for domain-specific processors (e.g. swap processing).\n */\nexport interface TaskProcessor<TDeps = TaskDependencies> {\n readonly taskType: string;\n execute(item: TaskItem, deps: TDeps): Promise<Omit<TaskResult, \"id\" | \"executedAt\">>;\n}\n\n/**\n * Run all pending tasks from the queue through matching processors.\n *\n * For each task in the inbox:\n * 1. Find the processor whose `taskType` matches `task.type`.\n * 2. Execute it, producing a @see TaskResult.\n * 3. Push the result to the outbox and remove the task from the inbox.\n *\n * Tasks with no matching processor produce a `\"noop\"` result.\n * Processor errors produce a `\"failed\"` result with the error message.\n */\nexport async function runTasks<TDeps = TaskDependencies>(\n queue: TaskQueue,\n processors: TaskProcessor<TDeps>[],\n deps: TDeps,\n): Promise<TaskResult[]> {\n const tasks = await queue.getTasks();\n const processorMap = new Map(processors.map((p) => [p.taskType, p]));\n const results: TaskResult[] = [];\n\n for (const task of tasks) {\n const processor = processorMap.get(task.type);\n\n let partial: Omit<TaskResult, \"id\" | \"executedAt\">;\n\n if (!processor) {\n partial = {\n taskItemId: task.id,\n type: task.type,\n status: \"noop\",\n };\n } else {\n try {\n partial = await processor.execute(task, deps);\n } catch (error) {\n partial = {\n taskItemId: task.id,\n type: task.type,\n status: \"failed\",\n data: {\n error: error instanceof Error ? error.message : String(error),\n },\n };\n }\n }\n\n const result: TaskResult = {\n ...partial,\n id: getRandomId(),\n executedAt: Date.now(),\n };\n\n await queue.pushResult(result);\n await queue.removeTask(task.id);\n results.push(result);\n }\n\n return results;\n}\n\n/**\n * Options for @see createTaskDependencies.\n */\nexport interface CreateTaskDependenciesOptions {\n walletRepository: WalletRepository;\n contractRepository: ContractRepository;\n indexerProvider: IndexerProvider;\n arkProvider: ArkProvider;\n}\n\n/**\n * Build the @see TaskDependencies needed by task processors\n * (e.g. `src/worker/expo/processors/contractPollProcessor.ts`)\n *\n * This is the same construction that `defineExpoBackgroundTask` does\n * internally, extracted so that consumers with custom schedulers\n * (e.g. bare React Native with `react-native-background-fetch`)\n * can build deps without depending on Expo.\n */\nexport function createTaskDependencies(options: CreateTaskDependenciesOptions): TaskDependencies {\n return {\n ...options,\n extendVtxo: (vtxo: VirtualCoin, contract: Contract) =>\n extendVirtualCoinForContract(vtxo, contract),\n };\n}\n","import type { TaskItem, TaskResult } from \"../taskQueue\";\nimport type { TaskProcessor, TaskDependencies } from \"../taskRunner\";\nimport type { ExtendedVirtualCoin } from \"../../../wallet\";\nimport { getNormalizedVtxos } from \"../../../wallet/vtxo\";\nimport {\n warnAndFilterVtxosForScript,\n saveVtxosForContract,\n} from \"../../../contracts/vtxoOwnership\";\nimport { isWatchedContract } from \"../../../contracts/types\";\n\nexport const CONTRACT_POLL_TASK_TYPE = \"contract-poll\";\n\n/**\n * Polls the indexer for the latest VTXO state of every contract and\n * persists the results to the wallet repository.\n *\n * Replicates the polling subset of @see ContractManager.initialize:\n * 1. Load every watched contract from the contract repository.\n * 2. Paginated fetch of every VTXO (including spent) from the indexer.\n * 3. Extend each VTXO with tapscript data.\n * 4. Save to the wallet repository.\n *\n * NOTE: the indexer query deliberately omits `spendableOnly`. Every\n * repository implements `saveVtxos` as an upsert with no batch delete,\n * so filtering to spendable-only would leave VTXOs that became spent\n * between polls marked as spendable forever. Fetching the full set lets\n * the upsert overwrite stale records with their latest state.\n */\nexport const contractPollProcessor: TaskProcessor = {\n taskType: CONTRACT_POLL_TASK_TYPE,\n\n async execute(\n item: TaskItem,\n deps: TaskDependencies,\n ): Promise<Omit<TaskResult, \"id\" | \"executedAt\">> {\n const { contractRepository, walletRepository, indexerProvider, extendVtxo } = deps;\n\n // Background channel, so it covers exactly what the watcher's\n // subscription covers: `retained` rows are kept for reads only.\n const contracts = (await contractRepository.getContracts()).filter(isWatchedContract);\n let contractsProcessed = 0;\n let vtxosSaved = 0;\n\n for (const contract of contracts) {\n // Paginated fetch of spendable virtual outputs\n const pageSize = 100;\n let pageIndex = 0;\n let hasMore = true;\n const allVtxos: ExtendedVirtualCoin[] = [];\n\n while (hasMore) {\n const { vtxos, page } = await getNormalizedVtxos(indexerProvider, {\n scripts: [contract.script],\n pageIndex,\n pageSize,\n });\n\n for (const vtxo of vtxos) {\n allVtxos.push(extendVtxo(vtxo, contract));\n }\n\n hasMore = page ? vtxos.length === pageSize : false;\n pageIndex++;\n }\n\n // Skip wrong-script rows (legacy duplicates or indexer drift)\n // before persisting; the loop must keep going for the remaining\n // contracts even when one row is rejected.\n const filtered = warnAndFilterVtxosForScript(\n allVtxos,\n contract.script,\n \"contractPollProcessor\",\n );\n await saveVtxosForContract(walletRepository, contract, filtered);\n vtxosSaved += filtered.length;\n contractsProcessed++;\n }\n\n return {\n taskItemId: item.id,\n type: CONTRACT_POLL_TASK_TYPE,\n status: \"success\",\n data: { contractsProcessed, vtxosSaved },\n };\n },\n};\n"]}
1
+ {"version":3,"sources":["../src/worker/expo/taskRunner.ts","../src/worker/expo/processors/contractPollProcessor.ts"],"names":["getRandomId","extendVirtualCoinForContract","isWatchedContract","getNormalizedVtxos","warnAndFilterVtxosForScript","saveVtxosForContract"],"mappings":"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","file":"chunk-LL47QIHD.cjs","sourcesContent":["import type { TaskItem, TaskResult, TaskQueue } from \"./taskQueue\";\nimport type { WalletRepository } from \"../../repositories/walletRepository\";\nimport type { ContractRepository } from \"../../repositories/contractRepository\";\nimport type { IndexerProvider } from \"../../providers/indexer\";\nimport type { ArkProvider } from \"../../providers/ark\";\nimport type { ExtendedVirtualCoin, VirtualCoin } from \"../../wallet\";\nimport type { Contract } from \"../../contracts/types\";\nimport { getRandomId, extendVirtualCoinForContract } from \"../../wallet/utils\";\n\n/**\n * Shared dependencies injected into every processor at runtime.\n *\n * `extendVtxo` requires the owning contract — processors must resolve each\n * vtxo's `script` to a known contract (via the contract repository) before\n * calling this. The strict signature prevents the footgun where a missing\n * contract silently falls back to the wallet's default tapscript.\n */\nexport interface TaskDependencies {\n walletRepository: WalletRepository;\n contractRepository: ContractRepository;\n indexerProvider: IndexerProvider;\n arkProvider: ArkProvider;\n extendVtxo: (vtxo: VirtualCoin, contract: Contract) => ExtendedVirtualCoin;\n}\n\n/**\n * A stateless unit that handles one type of task item.\n *\n * Processors must not keep in-memory state across invocations —\n * all coordination lives in the @see TaskQueue and repositories.\n *\n * The `TDeps` parameter defaults to @see TaskDependencies but\n * can be overridden for domain-specific processors (e.g. swap processing).\n */\nexport interface TaskProcessor<TDeps = TaskDependencies> {\n readonly taskType: string;\n execute(item: TaskItem, deps: TDeps): Promise<Omit<TaskResult, \"id\" | \"executedAt\">>;\n}\n\n/**\n * Run all pending tasks from the queue through matching processors.\n *\n * For each task in the inbox:\n * 1. Find the processor whose `taskType` matches `task.type`.\n * 2. Execute it, producing a @see TaskResult.\n * 3. Push the result to the outbox and remove the task from the inbox.\n *\n * Tasks with no matching processor produce a `\"noop\"` result.\n * Processor errors produce a `\"failed\"` result with the error message.\n */\nexport async function runTasks<TDeps = TaskDependencies>(\n queue: TaskQueue,\n processors: TaskProcessor<TDeps>[],\n deps: TDeps,\n): Promise<TaskResult[]> {\n const tasks = await queue.getTasks();\n const processorMap = new Map(processors.map((p) => [p.taskType, p]));\n const results: TaskResult[] = [];\n\n for (const task of tasks) {\n const processor = processorMap.get(task.type);\n\n let partial: Omit<TaskResult, \"id\" | \"executedAt\">;\n\n if (!processor) {\n partial = {\n taskItemId: task.id,\n type: task.type,\n status: \"noop\",\n };\n } else {\n try {\n partial = await processor.execute(task, deps);\n } catch (error) {\n partial = {\n taskItemId: task.id,\n type: task.type,\n status: \"failed\",\n data: {\n error: error instanceof Error ? error.message : String(error),\n },\n };\n }\n }\n\n const result: TaskResult = {\n ...partial,\n id: getRandomId(),\n executedAt: Date.now(),\n };\n\n await queue.pushResult(result);\n await queue.removeTask(task.id);\n results.push(result);\n }\n\n return results;\n}\n\n/**\n * Options for @see createTaskDependencies.\n */\nexport interface CreateTaskDependenciesOptions {\n walletRepository: WalletRepository;\n contractRepository: ContractRepository;\n indexerProvider: IndexerProvider;\n arkProvider: ArkProvider;\n}\n\n/**\n * Build the @see TaskDependencies needed by task processors\n * (e.g. `src/worker/expo/processors/contractPollProcessor.ts`)\n *\n * This is the same construction that `defineExpoBackgroundTask` does\n * internally, extracted so that consumers with custom schedulers\n * (e.g. bare React Native with `react-native-background-fetch`)\n * can build deps without depending on Expo.\n */\nexport function createTaskDependencies(options: CreateTaskDependenciesOptions): TaskDependencies {\n return {\n ...options,\n extendVtxo: (vtxo: VirtualCoin, contract: Contract) =>\n extendVirtualCoinForContract(vtxo, contract),\n };\n}\n","import type { TaskItem, TaskResult } from \"../taskQueue\";\nimport type { TaskProcessor, TaskDependencies } from \"../taskRunner\";\nimport type { ExtendedVirtualCoin } from \"../../../wallet\";\nimport { getNormalizedVtxos } from \"../../../wallet/vtxo\";\nimport {\n warnAndFilterVtxosForScript,\n saveVtxosForContract,\n} from \"../../../contracts/vtxoOwnership\";\nimport { isWatchedContract } from \"../../../contracts/types\";\n\nexport const CONTRACT_POLL_TASK_TYPE = \"contract-poll\";\n\n/**\n * Polls the indexer for the latest VTXO state of every contract and\n * persists the results to the wallet repository.\n *\n * Replicates the polling subset of @see ContractManager.initialize:\n * 1. Load every watched contract from the contract repository.\n * 2. Paginated fetch of every VTXO (including spent) from the indexer.\n * 3. Extend each VTXO with tapscript data.\n * 4. Save to the wallet repository.\n *\n * NOTE: the indexer query deliberately omits `spendableOnly`. Every\n * repository implements `saveVtxos` as an upsert with no batch delete,\n * so filtering to spendable-only would leave VTXOs that became spent\n * between polls marked as spendable forever. Fetching the full set lets\n * the upsert overwrite stale records with their latest state.\n */\nexport const contractPollProcessor: TaskProcessor = {\n taskType: CONTRACT_POLL_TASK_TYPE,\n\n async execute(\n item: TaskItem,\n deps: TaskDependencies,\n ): Promise<Omit<TaskResult, \"id\" | \"executedAt\">> {\n const { contractRepository, walletRepository, indexerProvider, extendVtxo } = deps;\n\n // Background channel, so it covers exactly what the watcher's\n // subscription covers: `retained` rows are kept for reads only.\n const contracts = (await contractRepository.getContracts()).filter(isWatchedContract);\n let contractsProcessed = 0;\n let vtxosSaved = 0;\n\n for (const contract of contracts) {\n // Paginated fetch of spendable virtual outputs\n const pageSize = 100;\n let pageIndex = 0;\n let hasMore = true;\n const allVtxos: ExtendedVirtualCoin[] = [];\n\n while (hasMore) {\n const { vtxos, page } = await getNormalizedVtxos(indexerProvider, {\n scripts: [contract.script],\n pageIndex,\n pageSize,\n });\n\n for (const vtxo of vtxos) {\n allVtxos.push(extendVtxo(vtxo, contract));\n }\n\n hasMore = page ? vtxos.length === pageSize : false;\n pageIndex++;\n }\n\n // Skip wrong-script rows (legacy duplicates or indexer drift)\n // before persisting; the loop must keep going for the remaining\n // contracts even when one row is rejected.\n const filtered = warnAndFilterVtxosForScript(\n allVtxos,\n contract.script,\n \"contractPollProcessor\",\n );\n await saveVtxosForContract(walletRepository, contract, filtered);\n vtxosSaved += filtered.length;\n contractsProcessed++;\n }\n\n return {\n taskItemId: item.id,\n type: CONTRACT_POLL_TASK_TYPE,\n status: \"success\",\n data: { contractsProcessed, vtxosSaved },\n };\n },\n};\n"]}
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkFZFSGOTZ_cjs = require('./chunk-FZFSGOTZ.cjs');
3
+ var chunkZIRFXBKL_cjs = require('./chunk-ZIRFXBKL.cjs');
4
4
  var chunk5BLDMQED_cjs = require('./chunk-5BLDMQED.cjs');
5
5
  var base = require('@scure/base');
6
6
  var descriptorsScure = require('@bitcoinerlab/descriptors-scure');
@@ -76,14 +76,14 @@ var ContractHandlerRegistry = class {
76
76
  var contractHandlers = new ContractHandlerRegistry();
77
77
  exports.DefaultVtxo = void 0;
78
78
  ((DefaultVtxo2) => {
79
- class Script3 extends chunkFZFSGOTZ_cjs.VtxoScript {
79
+ class Script3 extends chunkZIRFXBKL_cjs.VtxoScript {
80
80
  /** Create the default virtual output script with one forfeit path and one exit path. */
81
81
  constructor(options) {
82
82
  const { pubKey, serverPubKey, csvTimelock } = options;
83
- const forfeitScript = chunkFZFSGOTZ_cjs.MultisigTapscript.encode({
83
+ const forfeitScript = chunkZIRFXBKL_cjs.MultisigTapscript.encode({
84
84
  pubkeys: [pubKey, serverPubKey]
85
85
  }).script;
86
- const exitScript = chunkFZFSGOTZ_cjs.CSVMultisigTapscript.encode({
86
+ const exitScript = chunkZIRFXBKL_cjs.CSVMultisigTapscript.encode({
87
87
  timelock: csvTimelock,
88
88
  pubkeys: [pubKey]
89
89
  }).script;
@@ -288,7 +288,7 @@ function extractPubKeyBytes(value) {
288
288
  return base.hex.decode(extractPubKey(normalizeToDescriptor(value)));
289
289
  }
290
290
  function deserializeCsvTimelock(value) {
291
- return value !== void 0 && value !== "" ? chunkFZFSGOTZ_cjs.sequenceToTimelock(Number(value)) : exports.DefaultVtxo.Script.DEFAULT_TIMELOCK;
291
+ return value !== void 0 && value !== "" ? chunkZIRFXBKL_cjs.sequenceToTimelock(Number(value)) : exports.DefaultVtxo.Script.DEFAULT_TIMELOCK;
292
292
  }
293
293
  var CLTV_HEIGHT_THRESHOLD = 500000000n;
294
294
  function isCltvSatisfied(context, locktime) {
@@ -330,7 +330,7 @@ function assertVhtlcSpendableNow(contract, context) {
330
330
  function isCsvSpendable(context, sequence) {
331
331
  if (sequence === void 0) return true;
332
332
  if (!context.vtxo) return false;
333
- const timelock = chunkFZFSGOTZ_cjs.sequenceToTimelock(sequence);
333
+ const timelock = chunkZIRFXBKL_cjs.sequenceToTimelock(sequence);
334
334
  if (timelock.type === "blocks") {
335
335
  if (context.blockHeight === void 0 || context.vtxo.status.block_height === void 0) {
336
336
  return false;
@@ -388,21 +388,21 @@ function forfeitExitSpendablePaths(script, contract, context) {
388
388
  async function detectUsedScripts(indexerProvider, scriptHexes) {
389
389
  const used = /* @__PURE__ */ new Set();
390
390
  const unique = [...new Set(scriptHexes)];
391
- for (let offset = 0; offset < unique.length; offset += chunkFZFSGOTZ_cjs.SCRIPT_QUERY_CHUNK_SIZE) {
392
- const scripts = unique.slice(offset, offset + chunkFZFSGOTZ_cjs.SCRIPT_QUERY_CHUNK_SIZE);
391
+ for (let offset = 0; offset < unique.length; offset += chunkZIRFXBKL_cjs.SCRIPT_QUERY_CHUNK_SIZE) {
392
+ const scripts = unique.slice(offset, offset + chunkZIRFXBKL_cjs.SCRIPT_QUERY_CHUNK_SIZE);
393
393
  const remaining = new Set(scripts);
394
394
  let pageIndex = 0;
395
395
  let hasMore = true;
396
396
  while (hasMore && remaining.size > 0) {
397
- const { vtxos, page } = await chunkFZFSGOTZ_cjs.getNormalizedVtxos(indexerProvider, {
397
+ const { vtxos, page } = await chunkZIRFXBKL_cjs.getNormalizedVtxos(indexerProvider, {
398
398
  scripts,
399
399
  pageIndex,
400
- pageSize: chunkFZFSGOTZ_cjs.DEFAULT_PAGE_SIZE
400
+ pageSize: chunkZIRFXBKL_cjs.DEFAULT_PAGE_SIZE
401
401
  });
402
402
  for (const vtxo of vtxos) {
403
403
  if (remaining.delete(vtxo.script)) used.add(vtxo.script);
404
404
  }
405
- hasMore = page ? vtxos.length === chunkFZFSGOTZ_cjs.DEFAULT_PAGE_SIZE : false;
405
+ hasMore = page ? vtxos.length === chunkZIRFXBKL_cjs.DEFAULT_PAGE_SIZE : false;
406
406
  pageIndex++;
407
407
  }
408
408
  }
@@ -463,7 +463,7 @@ var DefaultContractHandler = {
463
463
  return {
464
464
  pubKey: base.hex.encode(params.pubKey),
465
465
  serverPubKey: base.hex.encode(params.serverPubKey),
466
- csvTimelock: chunkFZFSGOTZ_cjs.timelockToSequence(params.csvTimelock).toString()
466
+ csvTimelock: chunkZIRFXBKL_cjs.timelockToSequence(params.csvTimelock).toString()
467
467
  };
468
468
  },
469
469
  deserializeParams(params) {
@@ -498,7 +498,7 @@ function defaultCandidatesAt(_index, descriptor, deps) {
498
498
  params: {
499
499
  pubKey: base.hex.encode(c.pubKey),
500
500
  serverPubKey: base.hex.encode(c.serverPubKey),
501
- csvTimelock: chunkFZFSGOTZ_cjs.timelockToSequence(c.csvTimelock).toString()
501
+ csvTimelock: chunkZIRFXBKL_cjs.timelockToSequence(c.csvTimelock).toString()
502
502
  },
503
503
  script: c.scriptHex,
504
504
  address: c.script.address(deps.network.hrp, c.serverPubKey).encode()
@@ -514,12 +514,12 @@ function discoverDefaultRange(entries, deps) {
514
514
  }
515
515
  exports.DelegateVtxo = void 0;
516
516
  ((DelegateVtxo2) => {
517
- class Script3 extends chunkFZFSGOTZ_cjs.VtxoScript {
517
+ class Script3 extends chunkZIRFXBKL_cjs.VtxoScript {
518
518
  /** Create a delegated virtual output script with forfeit, exit, and delegate paths. */
519
519
  constructor(options) {
520
520
  const defaultVtxo = new exports.DefaultVtxo.Script(options);
521
521
  const { delegatePubKey, pubKey, serverPubKey } = options;
522
- const delegateScript = chunkFZFSGOTZ_cjs.MultisigTapscript.encode({
522
+ const delegateScript = chunkZIRFXBKL_cjs.MultisigTapscript.encode({
523
523
  pubkeys: [pubKey, delegatePubKey, serverPubKey]
524
524
  }).script;
525
525
  super([...defaultVtxo.scripts, delegateScript]);
@@ -558,7 +558,7 @@ var DelegateContractHandler = {
558
558
  pubKey: base.hex.encode(params.pubKey),
559
559
  serverPubKey: base.hex.encode(params.serverPubKey),
560
560
  delegatePubKey: base.hex.encode(params.delegatePubKey),
561
- csvTimelock: chunkFZFSGOTZ_cjs.timelockToSequence(params.csvTimelock).toString()
561
+ csvTimelock: chunkZIRFXBKL_cjs.timelockToSequence(params.csvTimelock).toString()
562
562
  };
563
563
  },
564
564
  deserializeParams(params) {
@@ -602,7 +602,7 @@ function delegateCandidatesAt(_index, descriptor, deps) {
602
602
  pubKey: base.hex.encode(c.pubKey),
603
603
  serverPubKey: base.hex.encode(c.serverPubKey),
604
604
  delegatePubKey: base.hex.encode(delegatePubKey),
605
- csvTimelock: chunkFZFSGOTZ_cjs.timelockToSequence(c.csvTimelock).toString()
605
+ csvTimelock: chunkZIRFXBKL_cjs.timelockToSequence(c.csvTimelock).toString()
606
606
  },
607
607
  script: c.scriptHex,
608
608
  address: c.script.address(deps.network.hrp, c.serverPubKey).encode()
@@ -1414,6 +1414,15 @@ function asmToBytes(asm) {
1414
1414
  function bytesToASM(script) {
1415
1415
  return toASM(ArkadeScript.decode(script));
1416
1416
  }
1417
+
1418
+ // src/utils/keys.ts
1419
+ function toXOnly(key, label = "public key") {
1420
+ if (key.length === 32) return key;
1421
+ if (key.length === 33 && (key[0] === 2 || key[0] === 3)) return key.subarray(1);
1422
+ throw new Error(`${label} is not a compressed or x-only public key`);
1423
+ }
1424
+
1425
+ // src/arkade/tweak.ts
1417
1426
  var TAG_SCRIPT = "ArkScriptHash";
1418
1427
  var TAG_WITNESS = "ArkWitnessHash";
1419
1428
  function arkadeScriptHash(script) {
@@ -1427,8 +1436,7 @@ function arkadeWitnessHash(witness) {
1427
1436
  }
1428
1437
  function computeArkadeScriptPublicKey(pubKey, script) {
1429
1438
  const hash = arkadeScriptHash(script);
1430
- const xOnly = pubKey.length === 33 ? pubKey.subarray(1) : pubKey;
1431
- const point = secp256k1_js.schnorr.utils.lift_x(utils_js.bytesToNumberBE(xOnly));
1439
+ const point = secp256k1_js.schnorr.utils.lift_x(utils_js.bytesToNumberBE(toXOnly(pubKey, "emulator key")));
1432
1440
  const scalar = utils_js.bytesToNumberBE(hash) % secp256k1_js.secp256k1.Point.CURVE().n;
1433
1441
  const tweak = secp256k1_js.secp256k1.Point.BASE.multiply(scalar);
1434
1442
  return secp256k1_js.schnorr.utils.pointToBytes(point.add(tweak));
@@ -1437,7 +1445,7 @@ function computeArkadeScriptPublicKey(pubKey, script) {
1437
1445
  // src/script/vhtlc.ts
1438
1446
  exports.VHTLC = void 0;
1439
1447
  ((VHTLC2) => {
1440
- class BaseScript extends chunkFZFSGOTZ_cjs.VtxoScript {
1448
+ class BaseScript extends chunkZIRFXBKL_cjs.VtxoScript {
1441
1449
  options;
1442
1450
  claimScript;
1443
1451
  refundScript;
@@ -1462,27 +1470,27 @@ exports.VHTLC = void 0;
1462
1470
  unilateralRefundWithoutReceiverDelay
1463
1471
  } = options;
1464
1472
  const conditionScript = preimageCondition(preimageHash);
1465
- const claimScript = chunkFZFSGOTZ_cjs.ConditionMultisigTapscript.encode({
1473
+ const claimScript = chunkZIRFXBKL_cjs.ConditionMultisigTapscript.encode({
1466
1474
  conditionScript,
1467
1475
  pubkeys: [receiver, server]
1468
1476
  }).script;
1469
- const refundScript = chunkFZFSGOTZ_cjs.MultisigTapscript.encode({
1477
+ const refundScript = chunkZIRFXBKL_cjs.MultisigTapscript.encode({
1470
1478
  pubkeys: [sender, receiver, server]
1471
1479
  }).script;
1472
- const refundWithoutReceiverScript = chunkFZFSGOTZ_cjs.CLTVMultisigTapscript.encode({
1480
+ const refundWithoutReceiverScript = chunkZIRFXBKL_cjs.CLTVMultisigTapscript.encode({
1473
1481
  absoluteTimelock: refundLocktime,
1474
1482
  pubkeys: [sender, server]
1475
1483
  }).script;
1476
- const unilateralClaimScript = chunkFZFSGOTZ_cjs.ConditionCSVMultisigTapscript.encode({
1484
+ const unilateralClaimScript = chunkZIRFXBKL_cjs.ConditionCSVMultisigTapscript.encode({
1477
1485
  conditionScript,
1478
1486
  timelock: unilateralClaimDelay,
1479
1487
  pubkeys: [receiver]
1480
1488
  }).script;
1481
- const unilateralRefundScript = chunkFZFSGOTZ_cjs.CSVMultisigTapscript.encode({
1489
+ const unilateralRefundScript = chunkZIRFXBKL_cjs.CSVMultisigTapscript.encode({
1482
1490
  timelock: unilateralRefundDelay,
1483
1491
  pubkeys: [sender, receiver]
1484
1492
  }).script;
1485
- const unilateralRefundWithoutReceiverScript = chunkFZFSGOTZ_cjs.CSVMultisigTapscript.encode({
1493
+ const unilateralRefundWithoutReceiverScript = chunkZIRFXBKL_cjs.CSVMultisigTapscript.encode({
1486
1494
  timelock: unilateralRefundWithoutReceiverDelay,
1487
1495
  pubkeys: [sender]
1488
1496
  }).script;
@@ -1497,8 +1505,12 @@ exports.VHTLC = void 0;
1497
1505
  let arkadeScriptNic;
1498
1506
  let nonInteractiveClaimScript;
1499
1507
  if (options.nonInteractiveClaim) {
1500
- arkadeScriptNic = enforcePayTo(options.nonInteractiveClaim.receiverPkScript);
1501
- nonInteractiveClaimScript = chunkFZFSGOTZ_cjs.ConditionMultisigTapscript.encode({
1508
+ arkadeScriptNic = enforcePayToMaybeAsset(
1509
+ options.nonInteractiveClaim.receiverPkScript,
1510
+ options.asset,
1511
+ options.nonInteractiveClaim.strict
1512
+ );
1513
+ nonInteractiveClaimScript = chunkZIRFXBKL_cjs.ConditionMultisigTapscript.encode({
1502
1514
  conditionScript,
1503
1515
  pubkeys: [
1504
1516
  server,
@@ -1513,8 +1525,11 @@ exports.VHTLC = void 0;
1513
1525
  let arkadeScriptNir;
1514
1526
  let nonInteractiveRefundScript;
1515
1527
  if (options.nonInteractiveRefund) {
1516
- arkadeScriptNir = enforcePayTo(options.nonInteractiveRefund.senderPkScript);
1517
- nonInteractiveRefundScript = chunkFZFSGOTZ_cjs.MultisigTapscript.encode({
1528
+ arkadeScriptNir = enforcePayToMaybeAsset(
1529
+ options.nonInteractiveRefund.senderPkScript,
1530
+ options.asset
1531
+ );
1532
+ nonInteractiveRefundScript = chunkZIRFXBKL_cjs.MultisigTapscript.encode({
1518
1533
  pubkeys: [
1519
1534
  server,
1520
1535
  receiver,
@@ -1616,6 +1631,30 @@ exports.VHTLC = void 0;
1616
1631
  if (!preimageHash || preimageHash.length !== 20) {
1617
1632
  throw new Error("preimage hash must be 20 bytes");
1618
1633
  }
1634
+ if (options.asset !== void 0 && !options.nonInteractiveClaim && !options.nonInteractiveRefund) {
1635
+ throw new Error(
1636
+ "asset has no effect without nonInteractiveClaim or nonInteractiveRefund"
1637
+ );
1638
+ }
1639
+ const strict = options.nonInteractiveClaim?.strict;
1640
+ if (strict !== void 0) {
1641
+ if (strict.amount <= 0n) {
1642
+ throw new Error(`strict claim amount must be positive, got ${strict.amount}`);
1643
+ }
1644
+ if (options.asset !== void 0 && strict.assetAmount === void 0) {
1645
+ throw new Error(
1646
+ "strict claim needs assetAmount when the contract is denominated in an asset: bounding only the sats would leave the asset amount unenforced"
1647
+ );
1648
+ }
1649
+ if (options.asset === void 0 && strict.assetAmount !== void 0) {
1650
+ throw new Error("strict claim assetAmount has no effect without asset");
1651
+ }
1652
+ if (strict.assetAmount !== void 0 && strict.assetAmount <= 0n) {
1653
+ throw new Error(
1654
+ `strict claim assetAmount must be positive, got ${strict.assetAmount}`
1655
+ );
1656
+ }
1657
+ }
1619
1658
  if (options.nonInteractiveClaim) {
1620
1659
  const { emulatorPubkey, receiverPkScript } = options.nonInteractiveClaim;
1621
1660
  if (!emulatorPubkey || emulatorPubkey.length !== 32 && emulatorPubkey.length !== 33) {
@@ -1684,11 +1723,8 @@ function preimageConditionScriptV2(preimageHash) {
1684
1723
  function isP2trPkScript(pkScript) {
1685
1724
  return pkScript.length === 34 && pkScript[0] === 81 && pkScript[1] === 32;
1686
1725
  }
1687
- function enforcePayTo(destinationPkScript) {
1688
- if (!isP2trPkScript(destinationPkScript)) {
1689
- throw new Error("invalid P2TR script");
1690
- }
1691
- return ArkadeScript.encode([
1726
+ function satClause(destinationPkScript, quotedSats) {
1727
+ return [
1692
1728
  "PUSHCURRENTINPUTINDEX",
1693
1729
  "DUP",
1694
1730
  "INSPECTOUTPUTSCRIPTPUBKEY",
@@ -1697,11 +1733,68 @@ function enforcePayTo(destinationPkScript) {
1697
1733
  destinationPkScript.subarray(2),
1698
1734
  "EQUALVERIFY",
1699
1735
  "INSPECTOUTPUTVALUE",
1736
+ // `DUP` because the output value is needed twice: once against the
1737
+ // quote, once against the input.
1738
+ ...quotedSats === void 0 ? [] : ["DUP", quotedSats, "GREATERTHANOREQUAL", "VERIFY"],
1700
1739
  "PUSHCURRENTINPUTINDEX",
1701
1740
  "INSPECTINPUTVALUE",
1702
1741
  "GREATERTHANOREQUAL"
1742
+ ];
1743
+ }
1744
+ function enforcePayTo(destinationPkScript, quotedSats) {
1745
+ if (!isP2trPkScript(destinationPkScript)) {
1746
+ throw new Error("invalid P2TR script");
1747
+ }
1748
+ return ArkadeScript.encode(satClause(destinationPkScript, quotedSats));
1749
+ }
1750
+ function enforcePayToAsset(destinationPkScript, asset, strict) {
1751
+ if (!isP2trPkScript(destinationPkScript)) {
1752
+ throw new Error("invalid P2TR script");
1753
+ }
1754
+ if (asset.txid.length !== 32) {
1755
+ throw new Error(`asset txid must be 32 bytes, got ${asset.txid.length}`);
1756
+ }
1757
+ if (!Number.isInteger(asset.groupIndex) || asset.groupIndex < 0 || asset.groupIndex > 65535) {
1758
+ throw new Error(
1759
+ `asset group index must be an integer in [0, 65535], got ${asset.groupIndex}`
1760
+ );
1761
+ }
1762
+ const inspectionTxid = Uint8Array.from(asset.txid).reverse();
1763
+ return ArkadeScript.encode([
1764
+ // The output carries at least as much of the asset as the input did.
1765
+ // Output index is the input's -- the same index alignment the sat
1766
+ // covenant relies on, and the same liveness obligation on whoever
1767
+ // assembles the spend.
1768
+ "PUSHCURRENTINPUTINDEX",
1769
+ inspectionTxid,
1770
+ asset.groupIndex,
1771
+ "INSPECTOUTASSETLOOKUP",
1772
+ "VERIFY",
1773
+ // PRESENT on the output, not merely "zero of it"
1774
+ // The quoted bound, when the caller opted in — added to the input
1775
+ // comparison below, not substituted for it. `DUP` because the output's
1776
+ // asset amount is needed twice.
1777
+ ...strict?.assetAmount === void 0 ? [] : ["DUP", strict.assetAmount, "GREATERTHANOREQUAL", "VERIFY"],
1778
+ "PUSHCURRENTINPUTINDEX",
1779
+ inspectionTxid,
1780
+ asset.groupIndex,
1781
+ "INSPECTINASSETLOOKUP",
1782
+ "VERIFY",
1783
+ // ...and on the input, so the comparison means something
1784
+ "GREATERTHANOREQUAL",
1785
+ "VERIFY",
1786
+ // Exactly one asset out: nothing injected alongside the one bound.
1787
+ "PUSHCURRENTINPUTINDEX",
1788
+ "INSPECTOUTASSETCOUNT",
1789
+ 1,
1790
+ "EQUALVERIFY",
1791
+ // ...then the sat covenant, the same tokens `enforcePayTo` emits.
1792
+ ...satClause(destinationPkScript, strict?.amount)
1703
1793
  ]);
1704
1794
  }
1795
+ function enforcePayToMaybeAsset(destinationPkScript, asset, strict) {
1796
+ return asset === void 0 ? enforcePayTo(destinationPkScript, strict?.amount) : enforcePayToAsset(destinationPkScript, asset, strict);
1797
+ }
1705
1798
 
1706
1799
  // src/contracts/handlers/vhtlc.ts
1707
1800
  var VHTLCContractHandler = {
@@ -1717,9 +1810,9 @@ var VHTLCContractHandler = {
1717
1810
  server: base.hex.encode(params.server),
1718
1811
  hash: base.hex.encode(params.preimageHash),
1719
1812
  refundLocktime: params.refundLocktime.toString(),
1720
- claimDelay: chunkFZFSGOTZ_cjs.timelockToSequence(params.unilateralClaimDelay).toString(),
1721
- refundDelay: chunkFZFSGOTZ_cjs.timelockToSequence(params.unilateralRefundDelay).toString(),
1722
- refundNoReceiverDelay: chunkFZFSGOTZ_cjs.timelockToSequence(
1813
+ claimDelay: chunkZIRFXBKL_cjs.timelockToSequence(params.unilateralClaimDelay).toString(),
1814
+ refundDelay: chunkZIRFXBKL_cjs.timelockToSequence(params.unilateralRefundDelay).toString(),
1815
+ refundNoReceiverDelay: chunkZIRFXBKL_cjs.timelockToSequence(
1723
1816
  params.unilateralRefundWithoutReceiverDelay
1724
1817
  ).toString()
1725
1818
  };
@@ -1731,9 +1824,9 @@ var VHTLCContractHandler = {
1731
1824
  server: base.hex.decode(params.server),
1732
1825
  preimageHash: base.hex.decode(params.hash),
1733
1826
  refundLocktime: BigInt(params.refundLocktime),
1734
- unilateralClaimDelay: chunkFZFSGOTZ_cjs.sequenceToTimelock(Number(params.claimDelay)),
1735
- unilateralRefundDelay: chunkFZFSGOTZ_cjs.sequenceToTimelock(Number(params.refundDelay)),
1736
- unilateralRefundWithoutReceiverDelay: chunkFZFSGOTZ_cjs.sequenceToTimelock(
1827
+ unilateralClaimDelay: chunkZIRFXBKL_cjs.sequenceToTimelock(Number(params.claimDelay)),
1828
+ unilateralRefundDelay: chunkZIRFXBKL_cjs.sequenceToTimelock(Number(params.refundDelay)),
1829
+ unilateralRefundWithoutReceiverDelay: chunkZIRFXBKL_cjs.sequenceToTimelock(
1737
1830
  Number(params.refundNoReceiverDelay)
1738
1831
  )
1739
1832
  };
@@ -1948,6 +2041,14 @@ var VHTLCContractHandler = {
1948
2041
  };
1949
2042
  }
1950
2043
  };
2044
+ var parseGroupIndex = (raw) => {
2045
+ if (!/^(0|[1-9][0-9]*)$/.test(raw)) {
2046
+ throw new Error(
2047
+ `assetGroupIndex must be a canonical decimal integer, got ${JSON.stringify(raw)}`
2048
+ );
2049
+ }
2050
+ return Number(raw);
2051
+ };
1951
2052
  function decodeCovenantLeaf(params, destinationKey, emulatorKey, label) {
1952
2053
  const destination = params[destinationKey];
1953
2054
  const emulator = params[emulatorKey];
@@ -1970,9 +2071,9 @@ var VHTLCV2ContractHandler = {
1970
2071
  server: base.hex.encode(params.server),
1971
2072
  hash: base.hex.encode(params.preimageHash),
1972
2073
  refundLocktime: params.refundLocktime.toString(),
1973
- claimDelay: chunkFZFSGOTZ_cjs.timelockToSequence(params.unilateralClaimDelay).toString(),
1974
- refundDelay: chunkFZFSGOTZ_cjs.timelockToSequence(params.unilateralRefundDelay).toString(),
1975
- refundNoReceiverDelay: chunkFZFSGOTZ_cjs.timelockToSequence(
2074
+ claimDelay: chunkZIRFXBKL_cjs.timelockToSequence(params.unilateralClaimDelay).toString(),
2075
+ refundDelay: chunkZIRFXBKL_cjs.timelockToSequence(params.unilateralRefundDelay).toString(),
2076
+ refundNoReceiverDelay: chunkZIRFXBKL_cjs.timelockToSequence(
1976
2077
  params.unilateralRefundWithoutReceiverDelay
1977
2078
  ).toString(),
1978
2079
  // Spread rather than written as `undefined`: a `Record<string,
@@ -1984,7 +2085,17 @@ var VHTLCV2ContractHandler = {
1984
2085
  ),
1985
2086
  nonInteractiveClaimEmulatorPubkey: base.hex.encode(
1986
2087
  params.nonInteractiveClaim.emulatorPubkey
1987
- )
2088
+ ),
2089
+ // The opt-in quoted bound. Dropping it re-derives the DEFAULT
2090
+ // claim covenant — a strictly weaker one — and registration dies
2091
+ // at `upsertContractRow` with an opaque `Script mismatch`. Same
2092
+ // silent-drop class as the asset keys above.
2093
+ ...params.nonInteractiveClaim.strict && {
2094
+ strictClaimAmount: params.nonInteractiveClaim.strict.amount.toString(),
2095
+ ...params.nonInteractiveClaim.strict.assetAmount !== void 0 && {
2096
+ strictClaimAssetAmount: params.nonInteractiveClaim.strict.assetAmount.toString()
2097
+ }
2098
+ }
1988
2099
  },
1989
2100
  ...params.nonInteractiveRefund && {
1990
2101
  nonInteractiveRefundSenderPkScript: base.hex.encode(
@@ -1993,6 +2104,19 @@ var VHTLCV2ContractHandler = {
1993
2104
  nonInteractiveRefundEmulatorPubkey: base.hex.encode(
1994
2105
  params.nonInteractiveRefund.emulatorPubkey
1995
2106
  )
2107
+ },
2108
+ // The asset must round-trip, and its absence here used to be silent
2109
+ // in the worst way. `ContractManager` re-derives a contract from
2110
+ // these params; dropping the asset derives the SAT-ONLY script, so
2111
+ // registration died at `upsertContractRow` with a `Script mismatch`
2112
+ // naming two hex strings and no cause. Same silent-drop class
2113
+ // `validateOptions` refuses one layer up.
2114
+ //
2115
+ // Two keys rather than one blob, mirroring the script's own view of
2116
+ // an Asset ID as a (txid, groupIndex) pair.
2117
+ ...params.asset && {
2118
+ assetTxid: base.hex.encode(params.asset.txid),
2119
+ assetGroupIndex: params.asset.groupIndex.toString()
1996
2120
  }
1997
2121
  };
1998
2122
  },
@@ -2009,21 +2133,44 @@ var VHTLCV2ContractHandler = {
2009
2133
  "nonInteractiveRefundEmulatorPubkey",
2010
2134
  "nonInteractiveRefund"
2011
2135
  );
2136
+ if (params.assetTxid === void 0 !== (params.assetGroupIndex === void 0)) {
2137
+ throw new Error(
2138
+ "asset params are incomplete: assetTxid and assetGroupIndex must both be present or both absent"
2139
+ );
2140
+ }
2141
+ if (params.strictClaimAssetAmount !== void 0 && params.strictClaimAmount === void 0) {
2142
+ throw new Error(
2143
+ "strictClaimAssetAmount without strictClaimAmount: reading this as 'not strict' would re-derive the default claim covenant, which is weaker than the row asked for"
2144
+ );
2145
+ }
2146
+ const asset = params.assetTxid !== void 0 && params.assetGroupIndex !== void 0 ? {
2147
+ txid: base.hex.decode(params.assetTxid),
2148
+ groupIndex: parseGroupIndex(params.assetGroupIndex)
2149
+ } : void 0;
2012
2150
  return {
2013
2151
  sender: base.hex.decode(params.sender),
2014
2152
  receiver: base.hex.decode(params.receiver),
2015
2153
  server: base.hex.decode(params.server),
2016
2154
  preimageHash: base.hex.decode(params.hash),
2017
2155
  refundLocktime: BigInt(params.refundLocktime),
2018
- unilateralClaimDelay: chunkFZFSGOTZ_cjs.sequenceToTimelock(Number(params.claimDelay)),
2019
- unilateralRefundDelay: chunkFZFSGOTZ_cjs.sequenceToTimelock(Number(params.refundDelay)),
2020
- unilateralRefundWithoutReceiverDelay: chunkFZFSGOTZ_cjs.sequenceToTimelock(
2156
+ ...asset && { asset },
2157
+ unilateralClaimDelay: chunkZIRFXBKL_cjs.sequenceToTimelock(Number(params.claimDelay)),
2158
+ unilateralRefundDelay: chunkZIRFXBKL_cjs.sequenceToTimelock(Number(params.refundDelay)),
2159
+ unilateralRefundWithoutReceiverDelay: chunkZIRFXBKL_cjs.sequenceToTimelock(
2021
2160
  Number(params.refundNoReceiverDelay)
2022
2161
  ),
2023
2162
  ...claim && {
2024
2163
  nonInteractiveClaim: {
2025
2164
  receiverPkScript: claim.destination,
2026
- emulatorPubkey: claim.emulatorPubkey
2165
+ emulatorPubkey: claim.emulatorPubkey,
2166
+ ...params.strictClaimAmount !== void 0 && {
2167
+ strict: {
2168
+ amount: BigInt(params.strictClaimAmount),
2169
+ ...params.strictClaimAssetAmount !== void 0 && {
2170
+ assetAmount: BigInt(params.strictClaimAssetAmount)
2171
+ }
2172
+ }
2173
+ }
2027
2174
  }
2028
2175
  },
2029
2176
  ...refund && {
@@ -2290,7 +2437,7 @@ var BoardingContractHandler = {
2290
2437
  const coins = await deps.onchainProvider.getCoins(onchainAddress);
2291
2438
  if (coins.length === 0) return [];
2292
2439
  const scriptHex = base.hex.encode(script.pkScript);
2293
- const boardingSeq = chunkFZFSGOTZ_cjs.timelockToSequence(deps.boardingTimelock);
2440
+ const boardingSeq = chunkZIRFXBKL_cjs.timelockToSequence(deps.boardingTimelock);
2294
2441
  return [
2295
2442
  {
2296
2443
  type: "boarding",
@@ -2451,27 +2598,27 @@ function encodeTapscriptSegment(seg, pubkeys, args) {
2451
2598
  if (seg.csv) {
2452
2599
  const timelock = { type: seg.csv.type, value: resolveTimelockValue(seg.csv.value, args) };
2453
2600
  if (seg.asm) {
2454
- return chunkFZFSGOTZ_cjs.ConditionCSVMultisigTapscript.encode({
2601
+ return chunkZIRFXBKL_cjs.ConditionCSVMultisigTapscript.encode({
2455
2602
  conditionScript: resolveAsm(seg.asm, args),
2456
2603
  timelock,
2457
2604
  pubkeys
2458
2605
  });
2459
2606
  }
2460
- return chunkFZFSGOTZ_cjs.CSVMultisigTapscript.encode({ timelock, pubkeys });
2607
+ return chunkZIRFXBKL_cjs.CSVMultisigTapscript.encode({ timelock, pubkeys });
2461
2608
  }
2462
2609
  if (seg.cltv !== void 0) {
2463
- return chunkFZFSGOTZ_cjs.CLTVMultisigTapscript.encode({
2610
+ return chunkZIRFXBKL_cjs.CLTVMultisigTapscript.encode({
2464
2611
  absoluteTimelock: resolveTimelockValue(seg.cltv, args),
2465
2612
  pubkeys
2466
2613
  });
2467
2614
  }
2468
2615
  if (seg.asm) {
2469
- return chunkFZFSGOTZ_cjs.ConditionMultisigTapscript.encode({
2616
+ return chunkZIRFXBKL_cjs.ConditionMultisigTapscript.encode({
2470
2617
  conditionScript: resolveAsm(seg.asm, args),
2471
2618
  pubkeys
2472
2619
  });
2473
2620
  }
2474
- return chunkFZFSGOTZ_cjs.MultisigTapscript.encode({ pubkeys });
2621
+ return chunkZIRFXBKL_cjs.MultisigTapscript.encode({ pubkeys });
2475
2622
  }
2476
2623
  function compileFunctions(program, args, keys) {
2477
2624
  if (program.version !== SUPPORTED_PROGRAM_VERSION) {
@@ -2501,7 +2648,7 @@ function compileFunctions(program, args, keys) {
2501
2648
  return { name: names[i], def, leafScript, arkadeScript, signerKeys: pubkeys };
2502
2649
  });
2503
2650
  }
2504
- var ArkadeProgramScript = class extends chunkFZFSGOTZ_cjs.VtxoScript {
2651
+ var ArkadeProgramScript = class extends chunkZIRFXBKL_cjs.VtxoScript {
2505
2652
  constructor(program, args, keys) {
2506
2653
  const partial = compileFunctions(program, args, keys);
2507
2654
  super(partial.map((p) => p.leafScript));
@@ -2714,7 +2861,7 @@ function pathsFor(script, context, opts) {
2714
2861
  continue;
2715
2862
  }
2716
2863
  if (requiresServer) continue;
2717
- const sequence = csv ? Number(chunkFZFSGOTZ_cjs.timelockToSequence(csv)) : void 0;
2864
+ const sequence = csv ? Number(chunkZIRFXBKL_cjs.timelockToSequence(csv)) : void 0;
2718
2865
  if (opts.checkTimelocks && csv && !isCsvSpendable(context, sequence)) continue;
2719
2866
  if (opts.checkTimelocks && cltv !== void 0 && !isCltvSatisfied(context, cltv)) {
2720
2867
  continue;
@@ -2840,7 +2987,8 @@ exports.serializeArkadeContractParams = serializeArkadeContractParams;
2840
2987
  exports.speculativeReceiveMetadata = speculativeReceiveMetadata;
2841
2988
  exports.stringifyArtifact = stringifyArtifact;
2842
2989
  exports.toASM = toASM;
2990
+ exports.toXOnly = toXOnly;
2843
2991
  exports.validateProgram = validateProgram;
2844
2992
  exports.witnessRefToBytes = witnessRefToBytes;
2845
- //# sourceMappingURL=chunk-WXCVS6PD.cjs.map
2846
- //# sourceMappingURL=chunk-WXCVS6PD.cjs.map
2993
+ //# sourceMappingURL=chunk-PXPPZF5K.cjs.map
2994
+ //# sourceMappingURL=chunk-PXPPZF5K.cjs.map