@ghostlytools/cli 1.3.1 → 1.3.2

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 (60) hide show
  1. package/dist/assets/{api-TiB5QSG9.js → api-SYPJgFRU.js} +2 -2
  2. package/dist/assets/{api-Dq2QXQDk.js → api-aup3Amud.js} +9 -9
  3. package/dist/assets/{api-Dq2QXQDk.js.map → api-aup3Amud.js.map} +1 -1
  4. package/dist/assets/{apiKit-CA2x5GJF.js → apiKit-DYkVEs6r.js} +25 -29
  5. package/dist/assets/apiKit-DYkVEs6r.js.map +1 -0
  6. package/dist/assets/{apps-C-T8jeji.js → apps-DcZKu29s.js} +1 -1
  7. package/dist/assets/{apps-BxV9i_Y4.js → apps-Rbk2HHXb.js} +2 -2
  8. package/dist/assets/{apps-BxV9i_Y4.js.map → apps-Rbk2HHXb.js.map} +1 -1
  9. package/dist/assets/{arkade-C_qDmHnm.js → arkade-CuWlNnCz.js} +4 -4
  10. package/dist/assets/arkade-CuWlNnCz.js.map +1 -0
  11. package/dist/assets/{backup-CnMN2oUK.js → backup-CJWLDHuS.js} +4 -4
  12. package/dist/assets/{backup-CnMN2oUK.js.map → backup-CJWLDHuS.js.map} +1 -1
  13. package/dist/assets/{backup-Bugnn3Ue.js → backup-CSMw2GHv.js} +1 -1
  14. package/dist/assets/bark_ffi_wasm_bg-EY2uc0Bx.js.map +1 -1
  15. package/dist/assets/buttons-CGRqZ7z0.js +2 -0
  16. package/dist/assets/{buttons-CvNBzh2S.js → buttons-QEnAGWoC.js} +3 -3
  17. package/dist/assets/{buttons-CvNBzh2S.js.map → buttons-QEnAGWoC.js.map} +1 -1
  18. package/dist/assets/{envelope-WjingYSc.js → envelope-K27mzoyu.js} +2 -2
  19. package/dist/assets/{envelope-WjingYSc.js.map → envelope-K27mzoyu.js.map} +1 -1
  20. package/dist/assets/fedimint_client_wasm_bg-BtHHlFpp.js.map +1 -1
  21. package/dist/assets/{groupFiles-IEUW3DQz.js → groupFiles-DHTrTA4I.js} +43 -16
  22. package/dist/assets/groupFiles-DHTrTA4I.js.map +1 -0
  23. package/dist/assets/{host-CWt-jtqz.js → host-C7hA-Za7.js} +102 -34
  24. package/dist/assets/host-C7hA-Za7.js.map +1 -0
  25. package/dist/assets/{hyperdhtRelay-CPYwSLLS.js → hyperdhtRelay-BVoWY2ua.js} +2 -2
  26. package/dist/assets/{hyperdhtRelay-CPYwSLLS.js.map → hyperdhtRelay-BVoWY2ua.js.map} +1 -1
  27. package/dist/assets/{irohWeb-4oChIOIp.js → irohWeb-BJPk9bMn.js} +2 -2
  28. package/dist/assets/{irohWeb-4oChIOIp.js.map → irohWeb-BJPk9bMn.js.map} +1 -1
  29. package/dist/assets/{main-DbqcdShN.js → main-DC8cUkDx.js} +14 -14
  30. package/dist/assets/{main-DbqcdShN.js.map → main-DC8cUkDx.js.map} +1 -1
  31. package/dist/assets/{mainline-ZkiOnevs.js → mainline-CxbxpoU4.js} +2 -2
  32. package/dist/assets/{mainline-ZkiOnevs.js.map → mainline-CxbxpoU4.js.map} +1 -1
  33. package/dist/assets/{networkReason-CetKkTPo.js → networkReason-D42iNuUB.js} +2 -2
  34. package/dist/assets/{networkReason-CetKkTPo.js.map → networkReason-D42iNuUB.js.map} +1 -1
  35. package/dist/assets/{nwc-CgkqyvsE.js → nwc-Cm4sYgLv.js} +3 -3
  36. package/dist/assets/{nwc-CgkqyvsE.js.map → nwc-Cm4sYgLv.js.map} +1 -1
  37. package/dist/assets/{nwcProvider-4eVz_8HP.js → nwcProvider-0D7vdPDd.js} +2 -2
  38. package/dist/assets/{nwcProvider-4eVz_8HP.js.map → nwcProvider-0D7vdPDd.js.map} +1 -1
  39. package/dist/assets/{registry-OBJBnHVQ.js → registry-CLolR0kM.js} +1 -1
  40. package/dist/assets/{registry-DlAKO0Fy.js → registry-CVdSZW5l.js} +3 -3
  41. package/dist/assets/{registry-DlAKO0Fy.js.map → registry-CVdSZW5l.js.map} +1 -1
  42. package/dist/assets/{resolve-CouHhCpJ.js → resolve-BnlEajYz.js} +2 -2
  43. package/dist/assets/{resolve-CouHhCpJ.js.map → resolve-BnlEajYz.js.map} +1 -1
  44. package/dist/assets/{server-Ss0gJ-nw.js → server-CJNEKxzE.js} +112 -33
  45. package/dist/assets/server-CJNEKxzE.js.map +1 -0
  46. package/dist/assets/{src-DDzSERyc.js → src-yMUQvdyL.js} +157 -141
  47. package/dist/assets/src-yMUQvdyL.js.map +1 -0
  48. package/dist/assets/{turnRefs-B87dtrHM.js → turnRefs-B2a8to9q.js} +2 -2
  49. package/dist/assets/{turnRefs-B87dtrHM.js.map → turnRefs-B2a8to9q.js.map} +1 -1
  50. package/dist/assets/{usdt-Fj8CQO2z.js → usdt-DesFeDiG.js} +3 -3
  51. package/dist/assets/{usdt-Fj8CQO2z.js.map → usdt-DesFeDiG.js.map} +1 -1
  52. package/dist/ghostly.mjs +1 -1
  53. package/package.json +1 -1
  54. package/dist/assets/apiKit-CA2x5GJF.js.map +0 -1
  55. package/dist/assets/arkade-C_qDmHnm.js.map +0 -1
  56. package/dist/assets/buttons-Bj7Vf7Pn.js +0 -2
  57. package/dist/assets/groupFiles-IEUW3DQz.js.map +0 -1
  58. package/dist/assets/host-CWt-jtqz.js.map +0 -1
  59. package/dist/assets/server-Ss0gJ-nw.js.map +0 -1
  60. package/dist/assets/src-DDzSERyc.js.map +0 -1
@@ -1,4 +1,4 @@
1
- import { f as node, g as state, i as chatOrGroup, s as findGroup } from "./apiKit-CA2x5GJF.js";
1
+ import { f as node, g as state, i as chatOrGroup, s as findGroup } from "./apiKit-DYkVEs6r.js";
2
2
  import { createHash } from "node:crypto";
3
3
  //#region src/engineMethods.ts
4
4
  /**
@@ -320,4 +320,4 @@ async function withStoredIds(ctx, params) {
320
320
  //#endregion
321
321
  export { SECRET_RESULTS as a, ENGINE_READS as i, withStoredIds as n, ENGINE_METHODS as r, turnRef as t };
322
322
 
323
- //# sourceMappingURL=turnRefs-B87dtrHM.js.map
323
+ //# sourceMappingURL=turnRefs-B2a8to9q.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"turnRefs-B87dtrHM.js","names":[],"sources":["../../src/engineMethods.ts","../../src/turnRefs.ts"],"sourcesContent":["/**\n * The engine's calls the daemon passes through as `engine.<method>` (WISP 1100 § Local control API): exactly the\n * app's `EngineApi` (packages/browser/src/shared/rpc.ts; `engineMethods.test.ts` keeps the two equal), plus two\n * reads every host has. Nothing else on the engine object is reachable.\n */\nexport const ENGINE_METHODS: readonly string[] = [\n \"usdtCreate\", \"usdtUnlock\", \"usdtReveal\", \"usdtLock\", \"usdtRefresh\", \"usdtExportBackup\", \"usdtRestoreBackup\",\n \"arkCreate\", \"arkUnlock\", \"arkLock\", \"arkBackup\", \"arkExportBackup\", \"arkRestoreBackup\", \"arkRefresh\", \"arkRecover\",\n \"barkCreate\", \"barkBackup\", \"barkExportBackup\", \"barkRestoreBackup\", \"barkRefresh\", \"barkBoard\", \"fedimintPreview\",\n \"fedimintJoin\", \"fedimintLeave\", \"fedimintRefresh\", \"fedimintSpendNotes\", \"fedimintReceiveNotes\", \"fedimintInvoice\",\n \"fedimintTakeBack\", \"fedimintBackup\", \"fedimintExportBackup\", \"fedimintRestoreBackup\", \"fedimintRestorePhrase\",\n \"sparkCreate\", \"sparkBackup\", \"sparkExportBackup\", \"sparkRestoreBackup\", \"sparkRefresh\", \"sparkUseForLightning\",\n \"preparePayment\", \"approvePayment\", \"reconcilePayment\", \"cancelPayment\", \"refreshPublicProfiles\",\n \"choosePublicProfile\", \"preparePeerProof\", \"submitPeerProof\", \"withdrawPeerProof\", \"beginIdentityProof\",\n \"completeIdentityProof\", \"cancelIdentityProof\", \"removeIdentityProof\", \"shareIdentityProof\",\n \"withdrawIdentityProof\", \"recheckIdentityProof\", \"lookupIdentityDisplay\", \"loadPublicProfile\", \"loadPublicPosts\",\n \"loadPublicGraph\", \"loadPublicPostImage\", \"clearProfileData\", \"setDidListed\", \"nostrLoadContact\", \"nostrForgetContact\", \"nostrLoadOwn\",\n \"nostrLookup\", \"nostrDraft\", \"nostrPublish\", \"createLink\", \"takeInvite\", \"joinLink\", \"ensureLink\", \"confirmPair\",\n \"pollNow\", \"removeLink\", \"renameLink\", \"setActiveLink\", \"sendMessage\", \"editMessage\", \"retryMessage\", \"react\", \"pinMessage\", \"appId\", \"appOpen\", \"appClose\", \"appSend\", \"messageDetails\",\n \"deleteMessage\", \"exportLinks\", \"sendFile\", \"forwardMessages\", \"fileAction\", \"setDeliveryMode\", \"setTransportPreference\",\n \"setChatTransport\", \"setChatPaymentMethods\", \"setChatHold\", \"connect\", \"walletAddMint\", \"walletCreate\",\n \"walletRemove\", \"walletTestCoins\", \"walletSetupRetry\", \"walletSetupDismiss\", \"wake\", \"peekProfile\", \"walletSetPrimaryMint\", \"walletRemoveMint\", \"walletReceiveLightning\",\n \"walletQuoteInvoice\", \"walletPayQuote\", \"lnurlResolve\", \"lnurlInvoice\", \"checkPayment\", \"lightningSetSource\",\n \"lightningClearSource\", \"lightningRetrySource\", \"lightningReconfigureSource\", \"lightningRefresh\",\n \"lightningSetReceive\", \"lightningRename\", \"bitcoinSetSource\", \"bitcoinClearSource\", \"bitcoinRetrySource\",\n \"bitcoinReconfigureSource\", \"bitcoinReceiveAddress\", \"bitcoinRefresh\", \"walletReceiveToken\", \"walletInspectCashu\",\n \"walletExport\", \"walletBackupReminder\", \"sendPayment\", \"requestPayment\", \"requestGroupPayment\", \"groupPaymentHello\", \"askToPay\",\n \"payRequest\", \"reclaimPayment\", \"disconnect\", \"addService\", \"removeService\", \"setServiceEnabled\",\n \"setServiceShared\", \"updateSettings\", \"setCallSignal\", \"setTyping\", \"setWakeSubscription\", \"setWakeMuted\", \"wakeForCall\", \"setCallOn\", \"wakeConfirm\", \"setFastPoll\", \"createGroup\", \"inviteToGroup\",\n \"acceptGroupInvitation\", \"declineGroupInvitation\", \"enableGroupLink\", \"disableGroupLink\", \"joinGroupByLink\",\n \"sendGroupMessage\", \"sendGroupFile\", \"groupFileCheck\", \"pressButton\", \"groupMessages\", \"messagePage\", \"statusCardIndex\", \"groupTaken\", \"leaveGroup\", \"removeGroupMember\", \"makeGroupAdmin\", \"setGroupHub\", \"rotateGroup\",\n \"setGroupPicture\", \"renameGroup\", \"setGroupTyping\", \"forgetGroup\", \"setGroupManage\",\n // One profile on several devices (WISP 06): a CLI profile is always on one device, so these answer `single` or refuse.\n \"deviceEnrollInvite\", \"deviceEnrollConfirm\", \"deviceEnrollCancel\", \"deviceEnrollView\", \"deviceEnrollJoin\", \"deviceEnrollReady\", \"deviceEnrollFinish\",\n \"deviceEnrollRemove\", \"deviceSet\", \"devicePing\", \"deviceHandoffVerifier\", \"deviceHandoffPush\", \"deviceHandoffPull\", \"deviceHandoffAccept\",\n \"deviceHandoffSettle\", \"deviceHandoffCancel\", \"deviceHandoffView\", \"deviceHandoffAllow\", \"deviceTakeoverInfo\", \"deviceTakeover\", \"deviceTurnPeek\", \"deviceForkDiscard\", \"deviceRestoreStartOwn\",\n \"deviceRemove\", \"deviceNewSecret\", \"deviceSecretOfferDismiss\", \"deviceSetNoticeSeen\", \"deviceTurnCheck\", \"devicePushState\", \"devicePushSet\",\n \"appList\", \"appBuiltIns\", \"appStoreList\", \"appStorePreview\", \"appStoreAdd\", \"appStoreRemove\", \"appStoreRefresh\", \"appPreview\", \"appInstall\",\n \"appUpdateAccept\", \"appCheckUpdates\", \"appUninstall\", \"appRunCheck\", \"appFetchFiles\", \"appEntry\", \"appFile\", \"appFileAt\", \"appStorageGet\", \"appStorageSet\",\n \"appStorageDelete\", \"appStorageKeys\", \"appDataExport\", \"appDataExportText\",\n];\n\n/** Reads the hosts use outside `EngineApi`: the whole state, and one chat's stored messages. */\nexport const ENGINE_READS: readonly string[] = [\"getState\", \"getMessages\"];\n\n/**\n * Calls whose answer holds a secret (chat seeds, wallet phrases and keys, ecash, backups): the CLI prints their\n * result only with `--show-secret`.\n */\nexport const SECRET_RESULTS: ReadonlySet<string> = new Set([\n \"exportLinks\", \"takeInvite\", \"walletExport\", \"usdtReveal\",\n \"arkBackup\", \"barkBackup\", \"sparkBackup\", \"fedimintBackup\",\n \"usdtExportBackup\", \"arkExportBackup\", \"barkExportBackup\", \"sparkExportBackup\", \"fedimintExportBackup\",\n \"fedimintSpendNotes\",\n]);\n","import { createHash } from \"node:crypto\";\nimport { chatOrGroup, findGroup, node, state, type ApiContext, type Params } from \"./apiKit\";\n\n/**\n * The id an agent turn names its message by (docs/CLI.md § Agent turns). A message is stored under an id its sender\n * chose most of (`peer_<the id they sent>`), so a turn carries this one instead, made here from the chat (or group) and\n * that id: `t_` and 32 hex digits, in which nobody can write a word. Every command that takes a message's id takes it.\n */\nexport function turnRef(where: string, messageId: string): string {\n return \"t_\" + createHash(\"sha256\").update(`${where}\\n${messageId}`).digest(\"hex\").slice(0, 32);\n}\n\nconst TURN_REF = /^t_[0-9a-f]{32}$/;\nconst isRef = (value: unknown): value is string => typeof value === \"string\" && TURN_REF.test(value);\n\n/**\n * `params` with each turn's id in `message`, `reply` and `messages` as the id its message is stored under: looked for\n * among the chat's (or group's) newest messages first, where a turn's almost always is, then in all of them. One that\n * names no message stays as given, and its command says so as for any unknown id.\n */\nexport async function withStoredIds(ctx: ApiContext, params: Params): Promise<Params> {\n const wanted = new Set([params.message, params.reply, ...(Array.isArray(params.messages) ? params.messages : [])].filter(isRef));\n if (!wanted.size) return params;\n let target: { id: string; linkId: string; group: boolean } | null = null;\n try {\n if (typeof params.group === \"string\") { const group = findGroup(state(ctx).groups, params.group); target = { id: group.id, linkId: `group:${group.id}`, group: true }; }\n else if (typeof params.chat === \"string\") target = chatOrGroup(ctx, params.chat);\n } catch { /* the command says what is wrong with its chat or group */ }\n if (!target) return params;\n const { id, linkId, group } = target;\n const found = new Map<string, string>();\n const look = (messages: readonly { id: string }[]) => {\n for (const message of messages) { const ref = turnRef(id, message.id); if (wanted.has(ref)) found.set(ref, message.id); }\n return found.size === wanted.size;\n };\n if (!look((await node(ctx).messagePage({ linkId, limit: 200 })).messages)) look(group ? await node(ctx).groupMessages({ groupId: id }) : await node(ctx).getMessages(linkId));\n const stored = (value: unknown) => (isRef(value) ? found.get(value) ?? value : value);\n return {\n ...params,\n ...(params.message !== undefined && { message: stored(params.message) }),\n ...(params.reply !== undefined && { reply: stored(params.reply) }),\n ...(Array.isArray(params.messages) && { messages: params.messages.map(stored) }),\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"turnRefs-B2a8to9q.js","names":[],"sources":["../../src/engineMethods.ts","../../src/turnRefs.ts"],"sourcesContent":["/**\n * The engine's calls the daemon passes through as `engine.<method>` (WISP 1100 § Local control API): exactly the\n * app's `EngineApi` (packages/browser/src/shared/rpc.ts; `engineMethods.test.ts` keeps the two equal), plus two\n * reads every host has. Nothing else on the engine object is reachable.\n */\nexport const ENGINE_METHODS: readonly string[] = [\n \"usdtCreate\", \"usdtUnlock\", \"usdtReveal\", \"usdtLock\", \"usdtRefresh\", \"usdtExportBackup\", \"usdtRestoreBackup\",\n \"arkCreate\", \"arkUnlock\", \"arkLock\", \"arkBackup\", \"arkExportBackup\", \"arkRestoreBackup\", \"arkRefresh\", \"arkRecover\",\n \"barkCreate\", \"barkBackup\", \"barkExportBackup\", \"barkRestoreBackup\", \"barkRefresh\", \"barkBoard\", \"fedimintPreview\",\n \"fedimintJoin\", \"fedimintLeave\", \"fedimintRefresh\", \"fedimintSpendNotes\", \"fedimintReceiveNotes\", \"fedimintInvoice\",\n \"fedimintTakeBack\", \"fedimintBackup\", \"fedimintExportBackup\", \"fedimintRestoreBackup\", \"fedimintRestorePhrase\",\n \"sparkCreate\", \"sparkBackup\", \"sparkExportBackup\", \"sparkRestoreBackup\", \"sparkRefresh\", \"sparkUseForLightning\",\n \"preparePayment\", \"approvePayment\", \"reconcilePayment\", \"cancelPayment\", \"refreshPublicProfiles\",\n \"choosePublicProfile\", \"preparePeerProof\", \"submitPeerProof\", \"withdrawPeerProof\", \"beginIdentityProof\",\n \"completeIdentityProof\", \"cancelIdentityProof\", \"removeIdentityProof\", \"shareIdentityProof\",\n \"withdrawIdentityProof\", \"recheckIdentityProof\", \"lookupIdentityDisplay\", \"loadPublicProfile\", \"loadPublicPosts\",\n \"loadPublicGraph\", \"loadPublicPostImage\", \"clearProfileData\", \"setDidListed\", \"nostrLoadContact\", \"nostrForgetContact\", \"nostrLoadOwn\",\n \"nostrLookup\", \"nostrDraft\", \"nostrPublish\", \"createLink\", \"takeInvite\", \"joinLink\", \"ensureLink\", \"confirmPair\",\n \"pollNow\", \"removeLink\", \"renameLink\", \"setActiveLink\", \"sendMessage\", \"editMessage\", \"retryMessage\", \"react\", \"pinMessage\", \"appId\", \"appOpen\", \"appClose\", \"appSend\", \"messageDetails\",\n \"deleteMessage\", \"exportLinks\", \"sendFile\", \"forwardMessages\", \"fileAction\", \"setDeliveryMode\", \"setTransportPreference\",\n \"setChatTransport\", \"setChatPaymentMethods\", \"setChatHold\", \"connect\", \"walletAddMint\", \"walletCreate\",\n \"walletRemove\", \"walletTestCoins\", \"walletSetupRetry\", \"walletSetupDismiss\", \"wake\", \"peekProfile\", \"walletSetPrimaryMint\", \"walletRemoveMint\", \"walletReceiveLightning\",\n \"walletQuoteInvoice\", \"walletPayQuote\", \"lnurlResolve\", \"lnurlInvoice\", \"checkPayment\", \"lightningSetSource\",\n \"lightningClearSource\", \"lightningRetrySource\", \"lightningReconfigureSource\", \"lightningRefresh\",\n \"lightningSetReceive\", \"lightningRename\", \"bitcoinSetSource\", \"bitcoinClearSource\", \"bitcoinRetrySource\",\n \"bitcoinReconfigureSource\", \"bitcoinReceiveAddress\", \"bitcoinRefresh\", \"walletReceiveToken\", \"walletInspectCashu\",\n \"walletExport\", \"walletBackupReminder\", \"sendPayment\", \"requestPayment\", \"requestGroupPayment\", \"groupPaymentHello\", \"askToPay\",\n \"payRequest\", \"reclaimPayment\", \"disconnect\", \"addService\", \"removeService\", \"setServiceEnabled\",\n \"setServiceShared\", \"updateSettings\", \"setCallSignal\", \"setTyping\", \"setWakeSubscription\", \"setWakeMuted\", \"wakeForCall\", \"setCallOn\", \"wakeConfirm\", \"setFastPoll\", \"createGroup\", \"inviteToGroup\",\n \"acceptGroupInvitation\", \"declineGroupInvitation\", \"enableGroupLink\", \"disableGroupLink\", \"joinGroupByLink\",\n \"sendGroupMessage\", \"sendGroupFile\", \"groupFileCheck\", \"pressButton\", \"groupMessages\", \"messagePage\", \"statusCardIndex\", \"groupTaken\", \"leaveGroup\", \"removeGroupMember\", \"makeGroupAdmin\", \"setGroupHub\", \"rotateGroup\",\n \"setGroupPicture\", \"renameGroup\", \"setGroupTyping\", \"forgetGroup\", \"setGroupManage\",\n // One profile on several devices (WISP 06): a CLI profile is always on one device, so these answer `single` or refuse.\n \"deviceEnrollInvite\", \"deviceEnrollConfirm\", \"deviceEnrollCancel\", \"deviceEnrollView\", \"deviceEnrollJoin\", \"deviceEnrollReady\", \"deviceEnrollFinish\",\n \"deviceEnrollRemove\", \"deviceSet\", \"devicePing\", \"deviceHandoffVerifier\", \"deviceHandoffPush\", \"deviceHandoffPull\", \"deviceHandoffAccept\",\n \"deviceHandoffSettle\", \"deviceHandoffCancel\", \"deviceHandoffView\", \"deviceHandoffAllow\", \"deviceTakeoverInfo\", \"deviceTakeover\", \"deviceTurnPeek\", \"deviceForkDiscard\", \"deviceRestoreStartOwn\",\n \"deviceRemove\", \"deviceNewSecret\", \"deviceSecretOfferDismiss\", \"deviceSetNoticeSeen\", \"deviceTurnCheck\", \"devicePushState\", \"devicePushSet\",\n \"appList\", \"appBuiltIns\", \"appStoreList\", \"appStorePreview\", \"appStoreAdd\", \"appStoreRemove\", \"appStoreRefresh\", \"appPreview\", \"appInstall\",\n \"appUpdateAccept\", \"appCheckUpdates\", \"appUninstall\", \"appRunCheck\", \"appFetchFiles\", \"appEntry\", \"appFile\", \"appFileAt\", \"appStorageGet\", \"appStorageSet\",\n \"appStorageDelete\", \"appStorageKeys\", \"appDataExport\", \"appDataExportText\",\n];\n\n/** Reads the hosts use outside `EngineApi`: the whole state, and one chat's stored messages. */\nexport const ENGINE_READS: readonly string[] = [\"getState\", \"getMessages\"];\n\n/**\n * Calls whose answer holds a secret (chat seeds, wallet phrases and keys, ecash, backups): the CLI prints their\n * result only with `--show-secret`.\n */\nexport const SECRET_RESULTS: ReadonlySet<string> = new Set([\n \"exportLinks\", \"takeInvite\", \"walletExport\", \"usdtReveal\",\n \"arkBackup\", \"barkBackup\", \"sparkBackup\", \"fedimintBackup\",\n \"usdtExportBackup\", \"arkExportBackup\", \"barkExportBackup\", \"sparkExportBackup\", \"fedimintExportBackup\",\n \"fedimintSpendNotes\",\n]);\n","import { createHash } from \"node:crypto\";\nimport { chatOrGroup, findGroup, node, state, type ApiContext, type Params } from \"./apiKit\";\n\n/**\n * The id an agent turn names its message by (docs/CLI.md § Agent turns). A message is stored under an id its sender\n * chose most of (`peer_<the id they sent>`), so a turn carries this one instead, made here from the chat (or group) and\n * that id: `t_` and 32 hex digits, in which nobody can write a word. Every command that takes a message's id takes it.\n */\nexport function turnRef(where: string, messageId: string): string {\n return \"t_\" + createHash(\"sha256\").update(`${where}\\n${messageId}`).digest(\"hex\").slice(0, 32);\n}\n\nconst TURN_REF = /^t_[0-9a-f]{32}$/;\nconst isRef = (value: unknown): value is string => typeof value === \"string\" && TURN_REF.test(value);\n\n/**\n * `params` with each turn's id in `message`, `reply` and `messages` as the id its message is stored under: looked for\n * among the chat's (or group's) newest messages first, where a turn's almost always is, then in all of them. One that\n * names no message stays as given, and its command says so as for any unknown id.\n */\nexport async function withStoredIds(ctx: ApiContext, params: Params): Promise<Params> {\n const wanted = new Set([params.message, params.reply, ...(Array.isArray(params.messages) ? params.messages : [])].filter(isRef));\n if (!wanted.size) return params;\n let target: { id: string; linkId: string; group: boolean } | null = null;\n try {\n if (typeof params.group === \"string\") { const group = findGroup(state(ctx).groups, params.group); target = { id: group.id, linkId: `group:${group.id}`, group: true }; }\n else if (typeof params.chat === \"string\") target = chatOrGroup(ctx, params.chat);\n } catch { /* the command says what is wrong with its chat or group */ }\n if (!target) return params;\n const { id, linkId, group } = target;\n const found = new Map<string, string>();\n const look = (messages: readonly { id: string }[]) => {\n for (const message of messages) { const ref = turnRef(id, message.id); if (wanted.has(ref)) found.set(ref, message.id); }\n return found.size === wanted.size;\n };\n if (!look((await node(ctx).messagePage({ linkId, limit: 200 })).messages)) look(group ? await node(ctx).groupMessages({ groupId: id }) : await node(ctx).getMessages(linkId));\n const stored = (value: unknown) => (isRef(value) ? found.get(value) ?? value : value);\n return {\n ...params,\n ...(params.message !== undefined && { message: stored(params.message) }),\n ...(params.reply !== undefined && { reply: stored(params.reply) }),\n ...(Array.isArray(params.messages) && { messages: params.messages.map(stored) }),\n };\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
- import { Yn as engineError, an as EVM_TEST_CHAINS, cn as SEPOLIA_TEST_USDT, dn as USDT_PUBLIC_RPC, gn as validatePaymentTarget, ln as SEPOLIA_TEST_USDT_FAUCET, sn as PaymentPreflightError, un as TEST_USDT_FAUCET_AMOUNT } from "./src-DDzSERyc.js";
2
- import { a as sealSeed, n as rpcHost, o as unsealSeed, t as networkReason } from "./networkReason-CetKkTPo.js";
1
+ import { Xn as engineError, _n as validatePaymentTarget, an as EVM_TEST_CHAINS, cn as SEPOLIA_TEST_USDT, dn as USDT_PUBLIC_RPC, ln as SEPOLIA_TEST_USDT_FAUCET, sn as PaymentPreflightError, un as TEST_USDT_FAUCET_AMOUNT } from "./src-yMUQvdyL.js";
2
+ import { a as sealSeed, n as rpcHost, o as unsealSeed, t as networkReason } from "./networkReason-D42iNuUB.js";
3
3
  import { mnemonicToSeedSync } from "@scure/bip39";
4
4
  import WalletManagerEvm from "@tetherto/wdk-wallet-evm";
5
5
  import { Interface, Transaction, getAddress, keccak256 } from "ethers";
@@ -407,4 +407,4 @@ var UsdtAdapter = class UsdtAdapter {
407
407
  //#endregion
408
408
  export { UsdtAdapter, wireProvider };
409
409
 
410
- //# sourceMappingURL=usdt-Fj8CQO2z.js.map
410
+ //# sourceMappingURL=usdt-DesFeDiG.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"usdt-Fj8CQO2z.js","names":[],"sources":["../../../browser/src/engine/paymentAdapters/usdt.ts"],"sourcesContent":["import { mnemonicToSeedSync } from '@scure/bip39';\nimport WalletManagerEvm, { type WalletAccountEvm } from '@tetherto/wdk-wallet-evm';\nimport { Interface, Transaction, getAddress, keccak256 } from 'ethers';\nimport { ETHEREUM_USDT, EVM_TEST_CHAINS, USDT_PUBLIC_RPC, SEPOLIA_TEST_USDT, SEPOLIA_TEST_USDT_FAUCET, TEST_USDT_FAUCET_AMOUNT, PaymentPreflightError, engineError, validatePaymentTarget, type PaymentAdapter, type PaymentExecution, type PaymentReview, type PaymentTarget } from '@ghostly/core';\nimport { sealSeed, unsealSeed, type EncryptedSeed } from './persistence';\nimport { networkReason, rpcHost } from './networkReason';\n\nexport interface UsdtConfig {\n network: 'ethereum' | 'sepolia' | 'evm-local';\n provider: string;\n chainId: 1 | 11155111 | 31337;\n token: string;\n decimals: number;\n codeHash: string;\n}\nexport interface UsdtPrepared {\n from: string; to: string; data: string; value: string; chainId: number; nonce: number;\n gasLimit: string; maxFeePerGas: string; maxPriorityFeePerGas: string;\n signed?: EncryptedSeed; hash?: string;\n}\nconst faucet = new Interface(['function mint(address token,address to,uint256 amount) returns (uint256)']);\nconst erc20 = new Interface(['function decimals() view returns(uint8)', 'function balanceOf(address) view returns(uint256)', 'function transfer(address,uint256) returns(bool)', 'event Transfer(address indexed from,address indexed to,uint256 value)']);\nconst same = (a: string, b: string) => a.toLowerCase() === b.toLowerCase();\nconst CONFIRMATIONS = 2;\n/** The JSON-RPC methods that only read: asked again once when they fail (see `UsdtAdapter.rpc`). */\nconst RETRIED_READS = new Set(['eth_chainId', 'eth_getCode', 'eth_call', 'eth_getBalance', 'eth_blockNumber', 'eth_getLogs', 'eth_getTransactionCount', 'eth_estimateGas', 'eth_getBlockByNumber', 'eth_maxPriorityFeePerGas', 'eth_gasPrice', 'eth_feeHistory', 'eth_getTransactionByHash', 'eth_getTransactionReceipt']);\nconst RETRY_AFTER_MS = 1000;\n/** Failures that would fail the same way again at once: not retried. */\nconst FINAL = new WeakSet<object>();\nconst timedOut = (error: unknown) => error instanceof Error && (error.name === 'AbortError' || error.name === 'TimeoutError');\n\n/**\n * The `provider` a request carries to the contact. Which RPC pays is the payer's own choice, so it names none of\n * this wallet's: a typed RPC URL may hold an API key (`/v3/<key>`), and every contact would read it. Older apps\n * require a URL here and pay only when it equals their own RPC, so it is the chain's public RPC (the default both\n * start with), and a local test chain's origin, without its path.\n */\nexport function wireProvider(config: Pick<UsdtConfig, 'network' | 'provider'>): string {\n return config.network === 'evm-local' ? new URL(config.provider).origin : USDT_PUBLIC_RPC[config.network];\n}\n\n/** WDK signs locally. Every network call uses the configured RPC, never a peer-supplied URL. */\nexport class UsdtAdapter implements PaymentAdapter<UsdtPrepared> {\n readonly method = 'usdt' as const;\n private manager?: WalletManagerEvm;\n private account?: WalletAccountEvm;\n private mnemonic = '';\n private nextId = 0;\n private queue: Promise<unknown> = Promise.resolve();\n private constructor(readonly config: UsdtConfig) {}\n\n static async inspect(config: Omit<UsdtConfig, 'decimals' | 'codeHash'>): Promise<UsdtConfig> {\n if (config.network === 'ethereum' ? config.chainId !== 1 || !same(config.token, ETHEREUM_USDT) : !(config.network in EVM_TEST_CHAINS) || config.chainId !== EVM_TEST_CHAINS[config.network]) throw new Error('Unsupported USDT network or contract');\n const token = getAddress(config.token);\n const url = new URL(config.provider);\n if (url.username || url.password || url.search || url.hash || (url.protocol !== 'https:' && !(url.protocol === 'http:' && ['localhost','127.0.0.1','[::1]'].includes(url.hostname)))) throw new Error('Use HTTPS or a loopback test RPC');\n const adapter = new UsdtAdapter({...config, token, decimals: 6, codeHash: ''});\n await adapter.chain();\n const code = await adapter.rpc<string>('eth_getCode', [token, 'latest']);\n if (code === '0x') throw new Error('No token contract exists on this chain');\n const result = await adapter.rpc<string>('eth_call', [{to: token, data: erc20.encodeFunctionData('decimals')}, 'latest']);\n const decimals = Number(erc20.decodeFunctionResult('decimals', result)[0]);\n if (!Number.isInteger(decimals) || decimals < 0 || decimals > 18 || (config.chainId === 1 && decimals !== 6)) throw new Error('Unexpected token decimals');\n return {...config, token, decimals, codeHash: keccak256(code)};\n }\n static async connect(config: UsdtConfig, mnemonic: string): Promise<UsdtAdapter> {\n const inspected = await UsdtAdapter.inspect(config);\n if (inspected.decimals !== config.decimals || inspected.codeHash !== config.codeHash) throw new Error('Token metadata changed; do not use this wallet configuration');\n const adapter = new UsdtAdapter(config);\n adapter.mnemonic = mnemonic;\n // Pass standard BIP-39 seed bytes: WDK's string helper assumes a Node Buffer global.\n const seed = mnemonicToSeedSync(mnemonic);\n try { adapter.manager = new WalletManagerEvm(seed, {provider: {request: ({method, params}) => adapter.rpc(method, params as unknown[] ?? [])}, chainId: config.chainId}); } finally { seed.fill(0); }\n adapter.account = await adapter.manager.getAccount(0);\n return adapter;\n }\n /**\n * A read that fails is asked again, once, a moment later: a public RPC drops a request now and then, and a chain that\n * just made a block can refuse a read of \"latest\" it no longer holds. Without it a network switch, a restore or New\n * gave up on the first such answer. Never a broadcast or anything else that writes, nor a request that did not answer\n * in time (the person would wait twice as long), nor one the server refused as such (4xx).\n */\n async rpc<T>(method: string, params: unknown[] = []): Promise<T> {\n try { return await this.ask<T>(method, params); }\n catch (error) {\n if (!RETRIED_READS.has(method) || FINAL.has(error as object)) throw error;\n await new Promise((resolve) => setTimeout(resolve, RETRY_AFTER_MS));\n return this.ask<T>(method, params);\n }\n }\n private async ask<T>(method: string, params: unknown[]): Promise<T> {\n let response: Response;\n // The browser's words for a request that got no answer (\"Fetch is aborted\") say nothing: the RPC's host does.\n try { response = await fetch(this.config.provider, {method:'POST', headers:{'Content-Type':'application/json'}, body:JSON.stringify({jsonrpc:'2.0',id:++this.nextId,method,params}), signal:AbortSignal.timeout(15000)}); }\n catch (error) {\n const reason = networkReason(error, rpcHost(this.config.provider));\n const thrown = reason ? Object.assign(new Error(reason), {cause: error}) : error;\n if (timedOut(error) && thrown && typeof thrown === 'object') FINAL.add(thrown);\n throw thrown;\n }\n if (!response.ok) { const error = engineError('usdtRpcUnavailable'); if (response.status !== 429 && response.status < 500) FINAL.add(error); throw error; }\n const result = await response.json();\n if (result.error || !Object.prototype.hasOwnProperty.call(result, 'result')) throw new Error('USDT RPC rejected the operation');\n return result.result as T;\n }\n private async chain() {\n if (BigInt(await this.rpc<string>('eth_chainId')) !== BigInt(this.config.chainId)) throw new Error('RPC chain does not match this wallet');\n }\n private async assertToken() {\n await this.chain();\n const code = await this.rpc<string>('eth_getCode', [this.config.token, 'latest']);\n if (code === '0x' || keccak256(code) !== this.config.codeHash) throw new Error('Token contract changed');\n }\n /**\n * Sepolia only: asks Aave's public faucet for test USDT, to this wallet, paid with its own test ETH.\n * Everything is fixed here (chain, contract, token, amount, recipient): nothing comes from outside.\n */\n mintTestTokens(): Promise<string> { return this.serial(async () => {\n if (this.config.chainId !== EVM_TEST_CHAINS.sepolia || !same(this.config.token, SEPOLIA_TEST_USDT)) throw new Error('Test USDT comes from a faucet on Sepolia only');\n await this.chain();\n const account = this.current(), from = await account.getAddress();\n const data = faucet.encodeFunctionData('mint', [SEPOLIA_TEST_USDT, from, BigInt(TEST_USDT_FAUCET_AMOUNT)]);\n const nonce = Number(BigInt(await this.rpc<string>('eth_getTransactionCount', [from, 'pending'])));\n const estimate = BigInt(await this.rpc<string>('eth_estimateGas', [{ from, to: SEPOLIA_TEST_USDT_FAUCET, data, value: '0x0' }]));\n const block = await this.rpc<{ baseFeePerGas?: string }>('eth_getBlockByNumber', ['latest', false]);\n if (!block.baseFeePerGas) throw new Error('This wallet requires an EIP-1559 chain');\n const priority = BigInt(await this.rpc<string>('eth_maxPriorityFeePerGas'));\n const maxFeePerGas = BigInt(block.baseFeePerGas) * 2n + priority, gasLimit = (estimate * 120n + 99n) / 100n;\n if (BigInt((await this.balances()).gasBalance) < gasLimit * maxFeePerGas) throw engineError('usdtNeedsSepoliaGas');\n const raw = await account.signTransaction({ type: 2, to: SEPOLIA_TEST_USDT_FAUCET, data, value: 0n, chainId: this.config.chainId, nonce, gasLimit, maxFeePerGas, maxPriorityFeePerGas: priority });\n await account.sendTransaction(raw);\n return Transaction.from(raw).hash!;\n }); }\n private current(): WalletAccountEvm { if (!this.account) throw new Error('Unlock the USDT wallet first'); return this.account; }\n address() { return this.current().getAddress(); }\n async balances() {\n await this.assertToken();\n const address = await this.address();\n const [token, gas] = await Promise.all([this.rpc<string>('eth_call',[{to:this.config.token,data:erc20.encodeFunctionData('balanceOf',[address])},'latest']),this.rpc<string>('eth_getBalance',[address,'pending'])]);\n return {balance:erc20.decodeFunctionResult('balanceOf',token)[0].toString(),gasBalance:BigInt(gas).toString()};\n }\n async target(): Promise<PaymentTarget> {\n const now = Date.now();\n return {method:'usdt',network:this.config.network,provider:wireProvider(this.config),asset:this.config.chainId === 1 ? 'USDT':'TEST-USDT',unit:'token-base',address:await this.address(),chainId:this.config.chainId,token:this.config.token,decimals:this.config.decimals,issuedAt:now,expiresAt:now+15*60*1000};\n }\n /** The request is for this wallet's token on its chain. Its `provider` is not compared: this wallet's own RPC pays. */\n private matches(target: PaymentTarget) {\n validatePaymentTarget(target);\n if (target.method !== 'usdt' || target.network !== this.config.network || target.chainId !== this.config.chainId || !same(target.token!,this.config.token) || target.decimals !== this.config.decimals) throw new Error('Request does not match the configured token and network');\n }\n prepare(target: PaymentTarget, amount: number, feeCap: number) { return this.serial(async () => {\n this.matches(target);\n await this.assertToken();\n const from = await this.address(), to = this.config.token;\n if (same(target.address, from) || same(target.address, to)) throw new Error('Choose a different recipient address');\n const {balance,gasBalance} = await this.balances();\n if (BigInt(balance) < BigInt(amount)) throw engineError('usdtNotEnoughTokens');\n const data = erc20.encodeFunctionData('transfer', [getAddress(target.address),BigInt(amount)]);\n const nonce = Number(BigInt(await this.rpc<string>('eth_getTransactionCount',[from,'pending'])));\n if (!Number.isSafeInteger(nonce)) throw new Error('Invalid account nonce');\n const estimate = BigInt(await this.rpc<string>('eth_estimateGas',[{from,to,data,value:'0x0'}]));\n const block = await this.rpc<{baseFeePerGas?:string}>('eth_getBlockByNumber',['latest',false]);\n if (!block.baseFeePerGas) throw new Error('This wallet requires an EIP-1559 chain');\n const priority = BigInt(await this.rpc<string>('eth_maxPriorityFeePerGas'));\n const maxFee = BigInt(block.baseFeePerGas)*2n + priority;\n const gasLimit = (estimate*120n+99n)/100n;\n const maximum = gasLimit*maxFee;\n if (maximum > BigInt(feeCap) || maximum > BigInt(Number.MAX_SAFE_INTEGER)) throw engineError('usdtGasAboveLimit');\n if (BigInt(gasBalance) < maximum) throw engineError('usdtNotEnoughGas');\n const prepared:UsdtPrepared = {from,to,data,value:'0',chainId:this.config.chainId,nonce,gasLimit:gasLimit.toString(),maxFeePerGas:maxFee.toString(),maxPriorityFeePerGas:priority.toString()};\n return {fee:Number(maximum),prepared,evm:{from,nonce,gasLimit:prepared.gasLimit,maxFeePerGas:prepared.maxFeePerGas,maxPriorityFeePerGas:prepared.maxPriorityFeePerGas,confirmations:CONFIRMATIONS}};\n }); }\n private verifyPrepared(review: PaymentReview, tx: UsdtPrepared) {\n if (tx.chainId !== this.config.chainId || !same(tx.to,this.config.token) || tx.value !== '0' || tx.data !== erc20.encodeFunctionData('transfer',[getAddress(review.address),BigInt(review.amount)]) || BigInt(tx.gasLimit)*BigInt(tx.maxFeePerGas) !== BigInt(review.fee) || review.fee > review.feeCap || tx.nonce !== review.evm?.nonce || !same(tx.from,review.evm?.from ?? '')) throw new Error('Transaction no longer matches the approved review');\n }\n private verifySigned(raw: string, saved: UsdtPrepared) {\n const tx = Transaction.from(raw);\n if (!tx.hash || !tx.from || !same(tx.from,saved.from) || tx.chainId !== BigInt(saved.chainId) || !tx.to || !same(tx.to,saved.to) || tx.data !== saved.data || tx.value !== 0n || tx.nonce !== saved.nonce || tx.gasLimit !== BigInt(saved.gasLimit) || tx.maxFeePerGas !== BigInt(saved.maxFeePerGas) || tx.maxPriorityFeePerGas !== BigInt(saved.maxPriorityFeePerGas)) throw new Error('Signature does not match the approved transaction');\n return tx.hash;\n }\n execute(review: PaymentReview, prepared: UsdtPrepared, persist?:()=>Promise<void>) { return this.serial(async () => {\n let account:WalletAccountEvm;\n try {\n this.matches(review); this.verifyPrepared(review,prepared);\n await this.assertToken(); account=this.current();\n if (!same(await account.getAddress(),prepared.from)) throw new Error('Wrong wallet');\n const nonce = Number(BigInt(await this.rpc<string>('eth_getTransactionCount',[prepared.from,'pending'])));\n if (nonce !== prepared.nonce) throw new Error('Account nonce changed. Create a new review');\n const balances = await this.balances();\n if (BigInt(balances.balance)<BigInt(review.amount) || BigInt(balances.gasBalance)<BigInt(review.fee)) throw new Error('Token or gas balance changed. Create a new review');\n if (!persist) throw new Error('Durable payment journal required');\n } catch (error) { throw new PaymentPreflightError(error instanceof Error ? error.message : 'Could not validate payment'); }\n const raw = await account.signTransaction({type:2,to:prepared.to,data:prepared.data,value:0n,chainId:prepared.chainId,nonce:prepared.nonce,gasLimit:BigInt(prepared.gasLimit),maxFeePerGas:BigInt(prepared.maxFeePerGas),maxPriorityFeePerGas:BigInt(prepared.maxPriorityFeePerGas)});\n prepared.hash = this.verifySigned(raw,prepared);\n prepared.signed = await sealSeed(raw,this.mnemonic);\n await persist!(); // Nothing may broadcast before the encrypted bytes are durable.\n await account.sendTransaction(raw);\n return this.receipt(prepared.hash,review,prepared.from);\n }); }\n reconcile(review: PaymentReview, prepared: UsdtPrepared) { return this.serial(async () => {\n await this.assertToken(); this.verifyPrepared(review,prepared);\n if (!prepared.signed || !prepared.hash) return {settled:false,failed:true,error:'No signed transaction was submitted. Create a new review.'};\n const result = await this.receipt(prepared.hash,review,prepared.from);\n if (result.settled || result.failed || result.pending) return result;\n // An uncertain network response permits only replay of exactly the saved bytes.\n const nonce = Number(BigInt(await this.rpc<string>('eth_getTransactionCount',[prepared.from,'pending'])));\n if (nonce > prepared.nonce) return result;\n const raw = await unsealSeed(prepared.signed,this.mnemonic);\n if (this.verifySigned(raw,prepared) !== prepared.hash || !same(await this.address(),prepared.from)) throw new Error('Recovery wallet mismatch');\n await this.current().sendTransaction(raw);\n return this.receipt(prepared.hash,review,prepared.from);\n }); }\n async receipt(hash: string, target: PaymentTarget & {amount:number}, expectedFrom?:string): Promise<PaymentExecution> {\n if (!/^0x[0-9a-fA-F]{64}$/.test(hash) || target.chainId !== this.config.chainId || !same(target.token ?? '',this.config.token) || target.decimals !== this.config.decimals) throw new Error('Invalid receipt target');\n await this.assertToken();\n const tx = await this.rpc<{from:string;to:string;input:string;value:string;nonce:string}|null>('eth_getTransactionByHash',[hash]);\n if (!tx) return {txid:hash,settled:false};\n if (!same(tx.to,this.config.token) || (expectedFrom && !same(tx.from,expectedFrom)) || BigInt(tx.value)!==0n || tx.input !== erc20.encodeFunctionData('transfer',[getAddress(target.address),BigInt(target.amount)])) throw new Error('Transaction is not the requested token transfer');\n const receipt = await this.rpc<{status:string;blockNumber:string;blockHash:string;logs:Array<{address:string;topics:string[];data:string}>}|null>('eth_getTransactionReceipt',[hash]);\n if (!receipt) return {txid:hash,settled:false,pending:true};\n const block = await this.rpc<{hash:string;timestamp:string}>('eth_getBlockByNumber',[receipt.blockNumber,false]);\n if (!block || block.hash !== receipt.blockHash || BigInt(block.timestamp)*1000n < BigInt((target.issuedAt ?? 0)-1000)) return {txid:hash,settled:false};\n const height = BigInt(await this.rpc<string>('eth_blockNumber'));\n if (height-BigInt(receipt.blockNumber)+1n < BigInt(CONFIRMATIONS)) return {txid:hash,settled:false,pending:true};\n if (BigInt(receipt.status)!==1n) return {txid:hash,settled:false,failed:true,error:'Transaction reverted. Tokens were not sent; gas was spent.'};\n const transfer = receipt.logs.some(log=>{\n if (!same(log.address,this.config.token)) return false;\n try {const event=erc20.parseLog(log);return event?.name==='Transfer' && same(event.args[0],tx.from) && same(event.args[1],target.address) && event.args[2]===BigInt(target.amount);} catch {return false;}\n });\n if (!transfer) throw new Error('Receipt has no matching token Transfer');\n return {txid:hash,settled:true};\n }\n async dispose() { await this.queue.catch(()=>{}); this.account=undefined;this.manager?.dispose();this.manager=undefined;this.mnemonic=''; }\n private serial<T>(work:()=>Promise<T>):Promise<T> { const operation=this.queue.then(work,work);this.queue=operation.catch(()=>{});return operation; }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"usdt-DesFeDiG.js","names":[],"sources":["../../../browser/src/engine/paymentAdapters/usdt.ts"],"sourcesContent":["import { mnemonicToSeedSync } from '@scure/bip39';\nimport WalletManagerEvm, { type WalletAccountEvm } from '@tetherto/wdk-wallet-evm';\nimport { Interface, Transaction, getAddress, keccak256 } from 'ethers';\nimport { ETHEREUM_USDT, EVM_TEST_CHAINS, USDT_PUBLIC_RPC, SEPOLIA_TEST_USDT, SEPOLIA_TEST_USDT_FAUCET, TEST_USDT_FAUCET_AMOUNT, PaymentPreflightError, engineError, validatePaymentTarget, type PaymentAdapter, type PaymentExecution, type PaymentReview, type PaymentTarget } from '@ghostly/core';\nimport { sealSeed, unsealSeed, type EncryptedSeed } from './persistence';\nimport { networkReason, rpcHost } from './networkReason';\n\nexport interface UsdtConfig {\n network: 'ethereum' | 'sepolia' | 'evm-local';\n provider: string;\n chainId: 1 | 11155111 | 31337;\n token: string;\n decimals: number;\n codeHash: string;\n}\nexport interface UsdtPrepared {\n from: string; to: string; data: string; value: string; chainId: number; nonce: number;\n gasLimit: string; maxFeePerGas: string; maxPriorityFeePerGas: string;\n signed?: EncryptedSeed; hash?: string;\n}\nconst faucet = new Interface(['function mint(address token,address to,uint256 amount) returns (uint256)']);\nconst erc20 = new Interface(['function decimals() view returns(uint8)', 'function balanceOf(address) view returns(uint256)', 'function transfer(address,uint256) returns(bool)', 'event Transfer(address indexed from,address indexed to,uint256 value)']);\nconst same = (a: string, b: string) => a.toLowerCase() === b.toLowerCase();\nconst CONFIRMATIONS = 2;\n/** The JSON-RPC methods that only read: asked again once when they fail (see `UsdtAdapter.rpc`). */\nconst RETRIED_READS = new Set(['eth_chainId', 'eth_getCode', 'eth_call', 'eth_getBalance', 'eth_blockNumber', 'eth_getLogs', 'eth_getTransactionCount', 'eth_estimateGas', 'eth_getBlockByNumber', 'eth_maxPriorityFeePerGas', 'eth_gasPrice', 'eth_feeHistory', 'eth_getTransactionByHash', 'eth_getTransactionReceipt']);\nconst RETRY_AFTER_MS = 1000;\n/** Failures that would fail the same way again at once: not retried. */\nconst FINAL = new WeakSet<object>();\nconst timedOut = (error: unknown) => error instanceof Error && (error.name === 'AbortError' || error.name === 'TimeoutError');\n\n/**\n * The `provider` a request carries to the contact. Which RPC pays is the payer's own choice, so it names none of\n * this wallet's: a typed RPC URL may hold an API key (`/v3/<key>`), and every contact would read it. Older apps\n * require a URL here and pay only when it equals their own RPC, so it is the chain's public RPC (the default both\n * start with), and a local test chain's origin, without its path.\n */\nexport function wireProvider(config: Pick<UsdtConfig, 'network' | 'provider'>): string {\n return config.network === 'evm-local' ? new URL(config.provider).origin : USDT_PUBLIC_RPC[config.network];\n}\n\n/** WDK signs locally. Every network call uses the configured RPC, never a peer-supplied URL. */\nexport class UsdtAdapter implements PaymentAdapter<UsdtPrepared> {\n readonly method = 'usdt' as const;\n private manager?: WalletManagerEvm;\n private account?: WalletAccountEvm;\n private mnemonic = '';\n private nextId = 0;\n private queue: Promise<unknown> = Promise.resolve();\n private constructor(readonly config: UsdtConfig) {}\n\n static async inspect(config: Omit<UsdtConfig, 'decimals' | 'codeHash'>): Promise<UsdtConfig> {\n if (config.network === 'ethereum' ? config.chainId !== 1 || !same(config.token, ETHEREUM_USDT) : !(config.network in EVM_TEST_CHAINS) || config.chainId !== EVM_TEST_CHAINS[config.network]) throw new Error('Unsupported USDT network or contract');\n const token = getAddress(config.token);\n const url = new URL(config.provider);\n if (url.username || url.password || url.search || url.hash || (url.protocol !== 'https:' && !(url.protocol === 'http:' && ['localhost','127.0.0.1','[::1]'].includes(url.hostname)))) throw new Error('Use HTTPS or a loopback test RPC');\n const adapter = new UsdtAdapter({...config, token, decimals: 6, codeHash: ''});\n await adapter.chain();\n const code = await adapter.rpc<string>('eth_getCode', [token, 'latest']);\n if (code === '0x') throw new Error('No token contract exists on this chain');\n const result = await adapter.rpc<string>('eth_call', [{to: token, data: erc20.encodeFunctionData('decimals')}, 'latest']);\n const decimals = Number(erc20.decodeFunctionResult('decimals', result)[0]);\n if (!Number.isInteger(decimals) || decimals < 0 || decimals > 18 || (config.chainId === 1 && decimals !== 6)) throw new Error('Unexpected token decimals');\n return {...config, token, decimals, codeHash: keccak256(code)};\n }\n static async connect(config: UsdtConfig, mnemonic: string): Promise<UsdtAdapter> {\n const inspected = await UsdtAdapter.inspect(config);\n if (inspected.decimals !== config.decimals || inspected.codeHash !== config.codeHash) throw new Error('Token metadata changed; do not use this wallet configuration');\n const adapter = new UsdtAdapter(config);\n adapter.mnemonic = mnemonic;\n // Pass standard BIP-39 seed bytes: WDK's string helper assumes a Node Buffer global.\n const seed = mnemonicToSeedSync(mnemonic);\n try { adapter.manager = new WalletManagerEvm(seed, {provider: {request: ({method, params}) => adapter.rpc(method, params as unknown[] ?? [])}, chainId: config.chainId}); } finally { seed.fill(0); }\n adapter.account = await adapter.manager.getAccount(0);\n return adapter;\n }\n /**\n * A read that fails is asked again, once, a moment later: a public RPC drops a request now and then, and a chain that\n * just made a block can refuse a read of \"latest\" it no longer holds. Without it a network switch, a restore or New\n * gave up on the first such answer. Never a broadcast or anything else that writes, nor a request that did not answer\n * in time (the person would wait twice as long), nor one the server refused as such (4xx).\n */\n async rpc<T>(method: string, params: unknown[] = []): Promise<T> {\n try { return await this.ask<T>(method, params); }\n catch (error) {\n if (!RETRIED_READS.has(method) || FINAL.has(error as object)) throw error;\n await new Promise((resolve) => setTimeout(resolve, RETRY_AFTER_MS));\n return this.ask<T>(method, params);\n }\n }\n private async ask<T>(method: string, params: unknown[]): Promise<T> {\n let response: Response;\n // The browser's words for a request that got no answer (\"Fetch is aborted\") say nothing: the RPC's host does.\n try { response = await fetch(this.config.provider, {method:'POST', headers:{'Content-Type':'application/json'}, body:JSON.stringify({jsonrpc:'2.0',id:++this.nextId,method,params}), signal:AbortSignal.timeout(15000)}); }\n catch (error) {\n const reason = networkReason(error, rpcHost(this.config.provider));\n const thrown = reason ? Object.assign(new Error(reason), {cause: error}) : error;\n if (timedOut(error) && thrown && typeof thrown === 'object') FINAL.add(thrown);\n throw thrown;\n }\n if (!response.ok) { const error = engineError('usdtRpcUnavailable'); if (response.status !== 429 && response.status < 500) FINAL.add(error); throw error; }\n const result = await response.json();\n if (result.error || !Object.prototype.hasOwnProperty.call(result, 'result')) throw new Error('USDT RPC rejected the operation');\n return result.result as T;\n }\n private async chain() {\n if (BigInt(await this.rpc<string>('eth_chainId')) !== BigInt(this.config.chainId)) throw new Error('RPC chain does not match this wallet');\n }\n private async assertToken() {\n await this.chain();\n const code = await this.rpc<string>('eth_getCode', [this.config.token, 'latest']);\n if (code === '0x' || keccak256(code) !== this.config.codeHash) throw new Error('Token contract changed');\n }\n /**\n * Sepolia only: asks Aave's public faucet for test USDT, to this wallet, paid with its own test ETH.\n * Everything is fixed here (chain, contract, token, amount, recipient): nothing comes from outside.\n */\n mintTestTokens(): Promise<string> { return this.serial(async () => {\n if (this.config.chainId !== EVM_TEST_CHAINS.sepolia || !same(this.config.token, SEPOLIA_TEST_USDT)) throw new Error('Test USDT comes from a faucet on Sepolia only');\n await this.chain();\n const account = this.current(), from = await account.getAddress();\n const data = faucet.encodeFunctionData('mint', [SEPOLIA_TEST_USDT, from, BigInt(TEST_USDT_FAUCET_AMOUNT)]);\n const nonce = Number(BigInt(await this.rpc<string>('eth_getTransactionCount', [from, 'pending'])));\n const estimate = BigInt(await this.rpc<string>('eth_estimateGas', [{ from, to: SEPOLIA_TEST_USDT_FAUCET, data, value: '0x0' }]));\n const block = await this.rpc<{ baseFeePerGas?: string }>('eth_getBlockByNumber', ['latest', false]);\n if (!block.baseFeePerGas) throw new Error('This wallet requires an EIP-1559 chain');\n const priority = BigInt(await this.rpc<string>('eth_maxPriorityFeePerGas'));\n const maxFeePerGas = BigInt(block.baseFeePerGas) * 2n + priority, gasLimit = (estimate * 120n + 99n) / 100n;\n if (BigInt((await this.balances()).gasBalance) < gasLimit * maxFeePerGas) throw engineError('usdtNeedsSepoliaGas');\n const raw = await account.signTransaction({ type: 2, to: SEPOLIA_TEST_USDT_FAUCET, data, value: 0n, chainId: this.config.chainId, nonce, gasLimit, maxFeePerGas, maxPriorityFeePerGas: priority });\n await account.sendTransaction(raw);\n return Transaction.from(raw).hash!;\n }); }\n private current(): WalletAccountEvm { if (!this.account) throw new Error('Unlock the USDT wallet first'); return this.account; }\n address() { return this.current().getAddress(); }\n async balances() {\n await this.assertToken();\n const address = await this.address();\n const [token, gas] = await Promise.all([this.rpc<string>('eth_call',[{to:this.config.token,data:erc20.encodeFunctionData('balanceOf',[address])},'latest']),this.rpc<string>('eth_getBalance',[address,'pending'])]);\n return {balance:erc20.decodeFunctionResult('balanceOf',token)[0].toString(),gasBalance:BigInt(gas).toString()};\n }\n async target(): Promise<PaymentTarget> {\n const now = Date.now();\n return {method:'usdt',network:this.config.network,provider:wireProvider(this.config),asset:this.config.chainId === 1 ? 'USDT':'TEST-USDT',unit:'token-base',address:await this.address(),chainId:this.config.chainId,token:this.config.token,decimals:this.config.decimals,issuedAt:now,expiresAt:now+15*60*1000};\n }\n /** The request is for this wallet's token on its chain. Its `provider` is not compared: this wallet's own RPC pays. */\n private matches(target: PaymentTarget) {\n validatePaymentTarget(target);\n if (target.method !== 'usdt' || target.network !== this.config.network || target.chainId !== this.config.chainId || !same(target.token!,this.config.token) || target.decimals !== this.config.decimals) throw new Error('Request does not match the configured token and network');\n }\n prepare(target: PaymentTarget, amount: number, feeCap: number) { return this.serial(async () => {\n this.matches(target);\n await this.assertToken();\n const from = await this.address(), to = this.config.token;\n if (same(target.address, from) || same(target.address, to)) throw new Error('Choose a different recipient address');\n const {balance,gasBalance} = await this.balances();\n if (BigInt(balance) < BigInt(amount)) throw engineError('usdtNotEnoughTokens');\n const data = erc20.encodeFunctionData('transfer', [getAddress(target.address),BigInt(amount)]);\n const nonce = Number(BigInt(await this.rpc<string>('eth_getTransactionCount',[from,'pending'])));\n if (!Number.isSafeInteger(nonce)) throw new Error('Invalid account nonce');\n const estimate = BigInt(await this.rpc<string>('eth_estimateGas',[{from,to,data,value:'0x0'}]));\n const block = await this.rpc<{baseFeePerGas?:string}>('eth_getBlockByNumber',['latest',false]);\n if (!block.baseFeePerGas) throw new Error('This wallet requires an EIP-1559 chain');\n const priority = BigInt(await this.rpc<string>('eth_maxPriorityFeePerGas'));\n const maxFee = BigInt(block.baseFeePerGas)*2n + priority;\n const gasLimit = (estimate*120n+99n)/100n;\n const maximum = gasLimit*maxFee;\n if (maximum > BigInt(feeCap) || maximum > BigInt(Number.MAX_SAFE_INTEGER)) throw engineError('usdtGasAboveLimit');\n if (BigInt(gasBalance) < maximum) throw engineError('usdtNotEnoughGas');\n const prepared:UsdtPrepared = {from,to,data,value:'0',chainId:this.config.chainId,nonce,gasLimit:gasLimit.toString(),maxFeePerGas:maxFee.toString(),maxPriorityFeePerGas:priority.toString()};\n return {fee:Number(maximum),prepared,evm:{from,nonce,gasLimit:prepared.gasLimit,maxFeePerGas:prepared.maxFeePerGas,maxPriorityFeePerGas:prepared.maxPriorityFeePerGas,confirmations:CONFIRMATIONS}};\n }); }\n private verifyPrepared(review: PaymentReview, tx: UsdtPrepared) {\n if (tx.chainId !== this.config.chainId || !same(tx.to,this.config.token) || tx.value !== '0' || tx.data !== erc20.encodeFunctionData('transfer',[getAddress(review.address),BigInt(review.amount)]) || BigInt(tx.gasLimit)*BigInt(tx.maxFeePerGas) !== BigInt(review.fee) || review.fee > review.feeCap || tx.nonce !== review.evm?.nonce || !same(tx.from,review.evm?.from ?? '')) throw new Error('Transaction no longer matches the approved review');\n }\n private verifySigned(raw: string, saved: UsdtPrepared) {\n const tx = Transaction.from(raw);\n if (!tx.hash || !tx.from || !same(tx.from,saved.from) || tx.chainId !== BigInt(saved.chainId) || !tx.to || !same(tx.to,saved.to) || tx.data !== saved.data || tx.value !== 0n || tx.nonce !== saved.nonce || tx.gasLimit !== BigInt(saved.gasLimit) || tx.maxFeePerGas !== BigInt(saved.maxFeePerGas) || tx.maxPriorityFeePerGas !== BigInt(saved.maxPriorityFeePerGas)) throw new Error('Signature does not match the approved transaction');\n return tx.hash;\n }\n execute(review: PaymentReview, prepared: UsdtPrepared, persist?:()=>Promise<void>) { return this.serial(async () => {\n let account:WalletAccountEvm;\n try {\n this.matches(review); this.verifyPrepared(review,prepared);\n await this.assertToken(); account=this.current();\n if (!same(await account.getAddress(),prepared.from)) throw new Error('Wrong wallet');\n const nonce = Number(BigInt(await this.rpc<string>('eth_getTransactionCount',[prepared.from,'pending'])));\n if (nonce !== prepared.nonce) throw new Error('Account nonce changed. Create a new review');\n const balances = await this.balances();\n if (BigInt(balances.balance)<BigInt(review.amount) || BigInt(balances.gasBalance)<BigInt(review.fee)) throw new Error('Token or gas balance changed. Create a new review');\n if (!persist) throw new Error('Durable payment journal required');\n } catch (error) { throw new PaymentPreflightError(error instanceof Error ? error.message : 'Could not validate payment'); }\n const raw = await account.signTransaction({type:2,to:prepared.to,data:prepared.data,value:0n,chainId:prepared.chainId,nonce:prepared.nonce,gasLimit:BigInt(prepared.gasLimit),maxFeePerGas:BigInt(prepared.maxFeePerGas),maxPriorityFeePerGas:BigInt(prepared.maxPriorityFeePerGas)});\n prepared.hash = this.verifySigned(raw,prepared);\n prepared.signed = await sealSeed(raw,this.mnemonic);\n await persist!(); // Nothing may broadcast before the encrypted bytes are durable.\n await account.sendTransaction(raw);\n return this.receipt(prepared.hash,review,prepared.from);\n }); }\n reconcile(review: PaymentReview, prepared: UsdtPrepared) { return this.serial(async () => {\n await this.assertToken(); this.verifyPrepared(review,prepared);\n if (!prepared.signed || !prepared.hash) return {settled:false,failed:true,error:'No signed transaction was submitted. Create a new review.'};\n const result = await this.receipt(prepared.hash,review,prepared.from);\n if (result.settled || result.failed || result.pending) return result;\n // An uncertain network response permits only replay of exactly the saved bytes.\n const nonce = Number(BigInt(await this.rpc<string>('eth_getTransactionCount',[prepared.from,'pending'])));\n if (nonce > prepared.nonce) return result;\n const raw = await unsealSeed(prepared.signed,this.mnemonic);\n if (this.verifySigned(raw,prepared) !== prepared.hash || !same(await this.address(),prepared.from)) throw new Error('Recovery wallet mismatch');\n await this.current().sendTransaction(raw);\n return this.receipt(prepared.hash,review,prepared.from);\n }); }\n async receipt(hash: string, target: PaymentTarget & {amount:number}, expectedFrom?:string): Promise<PaymentExecution> {\n if (!/^0x[0-9a-fA-F]{64}$/.test(hash) || target.chainId !== this.config.chainId || !same(target.token ?? '',this.config.token) || target.decimals !== this.config.decimals) throw new Error('Invalid receipt target');\n await this.assertToken();\n const tx = await this.rpc<{from:string;to:string;input:string;value:string;nonce:string}|null>('eth_getTransactionByHash',[hash]);\n if (!tx) return {txid:hash,settled:false};\n if (!same(tx.to,this.config.token) || (expectedFrom && !same(tx.from,expectedFrom)) || BigInt(tx.value)!==0n || tx.input !== erc20.encodeFunctionData('transfer',[getAddress(target.address),BigInt(target.amount)])) throw new Error('Transaction is not the requested token transfer');\n const receipt = await this.rpc<{status:string;blockNumber:string;blockHash:string;logs:Array<{address:string;topics:string[];data:string}>}|null>('eth_getTransactionReceipt',[hash]);\n if (!receipt) return {txid:hash,settled:false,pending:true};\n const block = await this.rpc<{hash:string;timestamp:string}>('eth_getBlockByNumber',[receipt.blockNumber,false]);\n if (!block || block.hash !== receipt.blockHash || BigInt(block.timestamp)*1000n < BigInt((target.issuedAt ?? 0)-1000)) return {txid:hash,settled:false};\n const height = BigInt(await this.rpc<string>('eth_blockNumber'));\n if (height-BigInt(receipt.blockNumber)+1n < BigInt(CONFIRMATIONS)) return {txid:hash,settled:false,pending:true};\n if (BigInt(receipt.status)!==1n) return {txid:hash,settled:false,failed:true,error:'Transaction reverted. Tokens were not sent; gas was spent.'};\n const transfer = receipt.logs.some(log=>{\n if (!same(log.address,this.config.token)) return false;\n try {const event=erc20.parseLog(log);return event?.name==='Transfer' && same(event.args[0],tx.from) && same(event.args[1],target.address) && event.args[2]===BigInt(target.amount);} catch {return false;}\n });\n if (!transfer) throw new Error('Receipt has no matching token Transfer');\n return {txid:hash,settled:true};\n }\n async dispose() { await this.queue.catch(()=>{}); this.account=undefined;this.manager?.dispose();this.manager=undefined;this.mnemonic=''; }\n private serial<T>(work:()=>Promise<T>):Promise<T> { const operation=this.queue.then(work,work);this.queue=operation.catch(()=>{});return operation; }\n}\n"],"mappings":"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"}
package/dist/ghostly.mjs CHANGED
@@ -24,7 +24,7 @@ function quietWebStorage(scope = globalThis, execArgv = process.execArgv, nodeOp
24
24
  //#region src/bin.ts
25
25
  quietWebStorage();
26
26
  enableCompileCache();
27
- var { run } = await import("./assets/main-DbqcdShN.js");
27
+ var { run } = await import("./assets/main-DC8cUkDx.js");
28
28
  run(process.argv.slice(2));
29
29
  //#endregion
30
30
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ghostlytools/cli",
3
- "version": "1.3.1",
3
+ "version": "1.3.2",
4
4
  "type": "module",
5
5
  "description": "Ghostly for bots and terminals: the app's own engine, headless on Node, behind a daemon and a `ghostly` command with JSON output.",
6
6
  "license": "MIT",
@@ -1 +0,0 @@
1
- {"version":3,"file":"apiKit-CA2x5GJF.js","names":[],"sources":["../../src/apiKit.ts"],"sourcesContent":["import { INVITE_TAKEN } from \"@ghostly/core\";\nimport type { GhostlyNode } from \"@ghostly/browser/engine/node\";\nimport type { EngineState, GroupView, LinkView, StoredMessage } from \"@ghostly/browser/shared/types\";\nimport { CliError } from \"./errors\";\nimport type { CallManager } from \"./calls/manager\";\nimport type { EventHub } from \"./events\";\nimport type { Runtime } from \"./runtime/engine\";\n\n/**\n * The methods of the local control API (WISP 1100): the daemon answers them over its socket, and a one-shot\n * command calls them in its own process. Parameters come from JSON: every one is checked here.\n */\nexport interface ApiContext {\n runtime: Runtime;\n hub: EventHub;\n /** Voice calls (WISP 1100 § Calls). */\n calls: CallManager;\n /** How the host runs: a daemon stays; a one-shot leaves when its command is done. */\n mode: \"daemon\" | \"one-shot\";\n version: string;\n /** The daemon asks to stop (answered first). */\n stop?: () => void;\n}\n\nexport type Params = Record<string, unknown>;\nexport type Method = (ctx: ApiContext, params: Params) => Promise<unknown>;\n\nexport const node = (ctx: ApiContext): GhostlyNode => ctx.runtime.server.node;\nexport const state = (ctx: ApiContext): EngineState => node(ctx).getState();\n\n/**\n * The time of a send the engine names its row after (`me_<timestamp>`: a file, a payment, a request), its own even\n * within one millisecond (a bot paying or sending several times at once over the socket, `file send` run in\n * parallel), or the chat keeps only one. One clock for all of them: they share the row names. A file's resend after a\n * drop finds its row by it, as a forward does.\n */\nlet lastSentAt = 0;\nexport const sentAt = () => (lastSentAt = Math.max(Date.now(), lastSentAt + 1));\n\n// ---------- parameters ----------\n\nexport function str(params: Params, name: string, required: true): string;\nexport function str(params: Params, name: string, required?: false): string | undefined;\nexport function str(params: Params, name: string, required = false): string | undefined {\n const value = params[name];\n if (value === undefined || value === null || value === \"\") {\n if (required) throw new CliError(\"bad_request\", `${name} is required`);\n return undefined;\n }\n if (typeof value !== \"string\") throw new CliError(\"bad_request\", `${name} must be a string`);\n return value;\n}\n/** A number in `[min, max]`; `whole` takes only whole ones (a count of messages), as the engine needs them. */\nexport function num(params: Params, name: string, fallback: number, { min = 0, max = Number.MAX_SAFE_INTEGER, whole = false } = {}): number {\n const value = params[name];\n if (value === undefined || value === null) return fallback;\n if (typeof value !== \"number\" || !Number.isFinite(value) || value < min || value > max) throw new CliError(\"bad_request\", `${name} must be a ${whole ? \"whole \" : \"\"}number from ${min} to ${max}`);\n if (whole && !Number.isSafeInteger(value)) throw new CliError(\"bad_request\", `${name} must be a whole number from ${min} to ${max}`);\n return value;\n}\nexport function bool(params: Params, name: string): boolean {\n const value = params[name];\n if (value === undefined || value === null) return false;\n if (typeof value !== \"boolean\") throw new CliError(\"bad_request\", `${name} must be true or false`);\n return value;\n}\nexport function list(params: Params, name: string): string[] {\n const value = params[name];\n if (value === undefined || value === null) return [];\n if (!Array.isArray(value) || value.some((item) => typeof item !== \"string\")) throw new CliError(\"bad_request\", `${name} must be a list of strings`);\n return value as string[];\n}\nexport function oneOf<T extends string>(params: Params, name: string, values: readonly T[], fallback: T): T {\n const value = str(params, name) ?? fallback;\n if (!values.includes(value as T)) throw new CliError(\"bad_request\", `${name} must be one of ${values.join(\", \")}`);\n return value as T;\n}\n\n// ---------- finding things ----------\n\n/** A contact key as chats show it (`peer`): 52 characters of z-base-32. */\nexport const CONTACT_KEY = /^[ybndrfg8ejkmcpqxot1uwisza345h769]{52}$/;\n\n/**\n * A chat by its id; by its contact's key (only by the key: a name is never taken for one); by a unique prefix of its\n * id; or by its name: the label this side gave it first, and only when no label matches, the name the contact gave\n * itself (which the contact controls, so it never wins over a label).\n */\nexport function findChat(links: readonly LinkView[], ref: string): LinkView {\n return chatBy(links, ref).link;\n}\n\n/** `findChat`, and whether only the name the contact gave itself (`theirName`) found the chat. */\nfunction chatBy(links: readonly LinkView[], ref: string): { link: LinkView; theirName: boolean } {\n const exact = links.find((link) => link.id === ref);\n if (exact) return { link: exact, theirName: false };\n if (CONTACT_KEY.test(ref)) {\n const byKey = links.filter((link) => link.peerPubKeyZ32 === ref);\n if (byKey.length === 1) return { link: byKey[0], theirName: false };\n if (byKey.length > 1) throw new CliError(\"bad_request\", `${JSON.stringify(ref)} names more than one chat: use its id`, { matches: byKey.map((link) => link.id) });\n throw new CliError(\"not_found\", `No chat with ${JSON.stringify(ref)}`);\n }\n const byPrefix = links.filter((link) => link.id.startsWith(ref));\n if (byPrefix.length === 1) return { link: byPrefix[0], theirName: false };\n const lower = ref.toLowerCase();\n const named = (name: string | null | undefined) => name?.trim().toLowerCase() === lower;\n const byLabel = links.filter((link) => named(link.label));\n const byName = byLabel.length ? byLabel : links.filter((link) => named(link.peerNick));\n if (byName.length === 1) return { link: byName[0], theirName: !byLabel.length };\n if (byPrefix.length > 1 || byName.length > 1) throw new CliError(\"bad_request\", `${JSON.stringify(ref)} names more than one chat: use its id`, { matches: [...byPrefix, ...byName].map((link) => link.id) });\n throw new CliError(\"not_found\", `No chat ${JSON.stringify(ref)}`);\n}\n\n/** Only an invitation so far: this profile is not in the group (yet), and whoever invited chose its name. */\nconst invitedOnly = (group: GroupView) => group.status === undefined && !!group.invitation;\n\n/**\n * A group by its id, by a unique prefix of its id, or by its name. A group this profile is in wins over an invitation\n * with the same prefix or name (the one who invites chooses those); an invitation is still found by its id, and by\n * prefix or name where no group of this profile has it.\n */\nexport function findGroup(groups: readonly GroupView[], ref: string): GroupView {\n const exact = groups.find((group) => group.id === ref);\n if (exact) return exact;\n const mineFirst = (found: GroupView[]) => { const mine = found.filter((group) => !invitedOnly(group)); return mine.length ? mine : found; };\n const byPrefix = mineFirst(groups.filter((group) => group.id.startsWith(ref)));\n if (byPrefix.length === 1) return byPrefix[0];\n const byName = mineFirst(groups.filter((group) => group.name.trim().toLowerCase() === ref.toLowerCase()));\n if (byName.length === 1) return byName[0];\n if (byPrefix.length > 1 || byName.length > 1) throw new CliError(\"bad_request\", `${JSON.stringify(ref)} names more than one group: use its id`, { matches: [...byPrefix, ...byName].map((group) => group.id) });\n throw new CliError(\"not_found\", `No group ${JSON.stringify(ref)}`);\n}\n\n/**\n * A chat or a group, where a command takes either: `group:<id>` is a group; anything else a chat first (`findChat`),\n * then a group. A chat found only by the name its contact gave itself never takes what also names a group: a group's\n * own id is that group, and a prefix or the name of a group this profile is in is refused, with both ids. With neither,\n * one `not_found` names both and where to look (a contact's key: no chat with it); a name that matches more than one\n * chat or group stays that error.\n */\nexport function findChatOrGroup(links: readonly LinkView[], groups: readonly GroupView[], ref: string): { link: LinkView } | { group: GroupView } {\n if (ref.startsWith(\"group:\")) return { group: findGroup(groups, ref.slice(\"group:\".length)) };\n let chat: ReturnType<typeof chatBy>;\n try {\n chat = chatBy(links, ref);\n } catch (error) {\n if (!(error instanceof CliError) || error.code !== \"not_found\") throw error;\n try { return { group: findGroup(groups, ref) }; } catch (inner) {\n if (!(inner instanceof CliError) || inner.code !== \"not_found\") throw inner;\n if (CONTACT_KEY.test(ref)) throw error;\n throw new CliError(\"not_found\", `No chat or group ${JSON.stringify(ref)} (ghostly chat list, ghostly group list)`);\n }\n }\n if (!chat.theirName) return { link: chat.link };\n const exact = groups.find((group) => group.id === ref);\n if (exact) return { group: exact };\n const lower = ref.toLowerCase();\n const also = groups.filter((group) => !invitedOnly(group) && (group.id.startsWith(ref) || group.name.trim().toLowerCase() === lower));\n if (also.length) throw new CliError(\"bad_request\", `${JSON.stringify(ref)} names a chat (the name its contact chose) and a group: use the chat's id or group:<id>`, { chat: chat.link.id, groups: also.map((group) => group.id) });\n return { link: chat.link };\n}\n\nexport const chatOf = (ctx: ApiContext, params: Params) => findChat(state(ctx).links, str(params, \"chat\", true));\n\n/**\n * A chat whose invite nobody took yet: nobody is there to pay or to dial, and its stage says so. Before, `chat pay`\n * waited 15 s and `chat connect` 25 s for the contact, then answered `engine`. A chat whose invite someone else used\n * first is refused too, with the sentence `send` gives: its contact seals everything to them (`connect` waited 120 s,\n * then answered `timeout`, a code a bot retries).\n */\nexport function inviteTaken(link: LinkView): void {\n if (link.profile && link.inviteCode && !link.peerParticipationKey) throw new CliError(\"unavailable\", \"Nobody joined this chat yet: its invite is still waiting to be taken\");\n if (link.dhtDelivery?.inviteTaken && link.textDelivery !== \"stream\") throw new CliError(\"refused\", INVITE_TAKEN);\n}\n\n/** A chat or a group as `findChatOrGroup` reads it. `linkId` is what the engine calls it. */\nexport function chatOrGroup(ctx: ApiContext, ref: string): { id: string; linkId: string; group: boolean } {\n const found = findChatOrGroup(state(ctx).links, state(ctx).groups, ref);\n return \"group\" in found ? { id: found.group.id, linkId: `group:${found.group.id}`, group: true } : { id: found.link.id, linkId: found.link.id, group: false };\n}\n\nexport const groupOf = (ctx: ApiContext, params: Params) => findGroup(state(ctx).groups, str(params, \"group\", true));\n\n/**\n * A message of a chat or a group (`group:<id>`) named by its id here, read as one row; only a name that is no such\n * row's key (the id both sides know, `wireId`) reads the whole history. `keep`: only a message it accepts (mine, or\n * someone else's). The history is synchronous work on the daemon's one thread, about 120 ms at 10,000 messages.\n */\nexport async function messageOf(ctx: ApiContext, linkId: string, ref: string, keep: (message: StoredMessage) => boolean = () => true): Promise<StoredMessage | undefined> {\n const found = await node(ctx).getMessage(linkId, ref);\n if (found && keep(found)) return found;\n const all = linkId.startsWith(\"group:\") ? await node(ctx).groupMessages({ groupId: linkId.slice(\"group:\".length) }) : await node(ctx).getMessages(linkId);\n return all.find((m) => keep(m) && m.wireId === ref);\n}\n\n// ---------- waiting ----------\n\n/** Resolves with `check`'s first defined answer: now, or on a later state; `timeout` error after `ms`. */\nexport function waitForState<T>(ctx: ApiContext, check: (state: EngineState) => T | undefined, ms: number, what: string): Promise<T> {\n const now = check(state(ctx));\n if (now !== undefined) return Promise.resolve(now);\n return new Promise<T>((resolve, reject) => {\n const timer = setTimeout(() => { off(); reject(new CliError(\"timeout\", `Timed out after ${Math.round(ms / 1000)} s waiting for ${what}`)); }, ms);\n const off = ctx.hub.onState((next) => {\n const value = check(next);\n if (value === undefined) return;\n clearTimeout(timer);\n off();\n resolve(value);\n });\n });\n}\n\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"arkade-C_qDmHnm.js","names":[],"sources":["../../../browser/src/engine/paymentAdapters/arkade.ts"],"sourcesContent":["import {\n Wallet, MnemonicIdentity, RestArkProvider, RestIndexerProvider, EsploraProvider,\n IndexedDBWalletRepository, IndexedDBContractRepository, ArkAddress, Transaction,\n assertSubmittedArkTxid, matchServerCheckpoints, assertAllowedSighashTypes, verifyTapscriptSignatures,\n isRecoverable, canRecoverOnchain, type StorageConfig,\n} from \"@arkade-os/sdk\";\nimport { tapLeafHash } from \"@scure/btc-signer/payment.js\";\nimport { assertWholeSats, validatePaymentTarget, type PaymentAdapter, type PaymentReview, type PaymentTarget } from \"@ghostly/core\";\n\nexport interface ArkConfig { network: \"bitcoin\" | \"regtest\" | \"signet\" | \"mutinynet\"; provider: string; explorer: string; serverKey: string; walletId: string }\nexport interface ArkPrepared { signedTx: string; checkpoints: string[]; txid: string; address: string; amount: number; fee: number; finalCheckpoints?: string[] }\nconst unbase64 = (s: string) => Uint8Array.from(atob(s),c=>c.charCodeAt(0));\nconst base64 = (bytes: Uint8Array) => btoa(Array.from(bytes,b=>String.fromCharCode(b)).join(\"\"));\nconst hex = (bytes: Uint8Array) => Array.from(bytes,b=>b.toString(16).padStart(2,\"0\")).join(\"\");\nclass PreparedOnly extends Error {}\nexport const ARK_NETWORKS: ArkConfig[\"network\"][] = [\"bitcoin\", \"mutinynet\", \"signet\", \"regtest\"];\n/** Payments go through review and approval; only the SDK's own settlement (renewal, onboarding) reaches the provider directly. */\nclass PreviewProvider extends RestArkProvider {\n authorizedFinalize?:{txid:string;run:(checkpoints:string[])=>Promise<void>};\n captured?: { signedTx:string; checkpoints:string[] };\n take() { return this.captured; }\n override async submitTx(signedTx:string,checkpoints:string[]):Promise<never> { this.captured={signedTx,checkpoints};throw new PreparedOnly(); }\n override async finalizeTx(txid:string,checkpoints:string[]):Promise<void> {\n if(this.authorizedFinalize?.txid!==txid)throw new Error(\"Preview cannot finalize an unapproved payment\");\n await this.authorizedFinalize.run(checkpoints);\n }\n}\nexport class ArkadeAdapter implements PaymentAdapter<ArkPrepared> {\n readonly method = \"arkade\" as const;\n private pending:Promise<unknown>=Promise.resolve();\n private serial<T>(run:()=>Promise<T>):Promise<T>{const next=this.pending.then(run,run);this.pending=next.catch(()=>{});return next;}\n prepare(target:PaymentTarget,amount:number,feeCap:number){return this.serial(()=>this.prepareOperation(target,amount,feeCap));}\n execute(review:PaymentReview,prepared:ArkPrepared,persist?:()=>Promise<void>){return this.serial(()=>this.executeOperation(review,prepared,persist));}\n reconcile(review:PaymentReview,prepared:ArkPrepared,persist?:()=>Promise<void>){return this.serial(()=>this.reconcileOperation(review,prepared,persist));}\n private constructor(readonly config: ArkConfig, private identity: MnemonicIdentity, private wallet: Wallet, private preview: PreviewProvider, private provider: RestArkProvider, private indexer: RestIndexerProvider,private repository:NonNullable<StorageConfig[\"walletRepository\"]>) {}\n static async connect(config: ArkConfig, mnemonic: string, storage?: StorageConfig): Promise<ArkadeAdapter> {\n if (!ARK_NETWORKS.includes(config.network)) throw new Error(\"Unsupported Ark network\");\n validatePaymentTarget({method:\"arkade\",network:config.network,provider:config.provider,asset:\"BTC\",unit:\"sat\",address:\"configuration\",expiresAt:Date.now()+60000});\n validatePaymentTarget({method:\"arkade\",network:config.network,provider:config.explorer,asset:\"BTC\",unit:\"sat\",address:\"configuration\",expiresAt:Date.now()+60000});\n const provider=new RestArkProvider(config.provider);\n const info=await provider.getInfo();\n if(info.network!==config.network || info.signerPubkey!==config.serverKey) throw new Error(\"Ark provider network or signing key changed. Review the wallet configuration.\");\n const identity=MnemonicIdentity.fromMnemonic(mnemonic,{isMainnet:config.network===\"bitcoin\"});\n const preview=new PreviewProvider(config.provider);\n const indexer=new RestIndexerProvider(config.provider);\n const repositories={...storage,walletRepository:storage?.walletRepository??new IndexedDBWalletRepository(`ghostly-ark-${config.walletId}`),contractRepository:storage?.contractRepository??new IndexedDBContractRepository(`ghostly-ark-${config.walletId}`)};\n const wallet=await Wallet.create({identity,arkProvider:preview,indexerProvider:indexer,onchainProvider:new EsploraProvider(config.explorer),\n // Renews VTXOs before they expire and settles on-chain deposits into Ark, so a wallet left alone keeps its funds.\n // A local regtest server expires batches within minutes; there the test drives settlement itself.\n settlementConfig:config.network===\"regtest\"?false:{boardingUtxoSweep:true},walletMode:\"hd\",storage:repositories});\n return new ArkadeAdapter(config,identity,wallet,preview,provider,indexer,repositories.walletRepository);\n }\n async address() { return this.wallet.getAddress(); }\n requestAddress() { return this.serial(async()=>(await this.wallet.getNewAddresses({types:[\"default\"],forceNew:true}))[0].address); }\n async balance() { return (await this.wallet.getBalance()).available; }\n /**\n * Sats whose batch expired before they were renewed, in three kinds, as a person can act on them:\n * - `sweeping`: past their expiry, but the server has not swept their batch yet (with any swept ones: none can be\n * recovered meanwhile). The SDK (0.4.76) counts them as\n * recoverable already, but it settles an unswept coin without the forfeit the server still asks for (arkd wants\n * one until the sweep): the batch fails (\"missing forfeit transactions\") and the server bans the coin for a while.\n * The sweep waits for the chain's time to pass the expiry: an hour or more on a real network, the expiry's blocks\n * on regtest.\n * - `recoverable`: swept, and a recovery takes them now.\n * - `small`: swept, but together under the server's dust limit: a recovery makes one new coin and the server makes\n * none that small, so `recoverVtxos` answers \"No recoverable VTXOs found\". They wait for more coins to expire.\n */\n async expired() {\n const now={timestamp:new Date()};\n let swept=0,sweeping=0;\n for(const vtxo of await this.wallet.getVtxos({withRecoverable:true,withUnrolled:false})) {\n if(isRecoverable(vtxo))swept+=vtxo.value;\n else if(!vtxo.isSwept&&canRecoverOnchain(vtxo,now))sweeping+=vtxo.value;\n }\n // What a recovery would hand back, over the same coins it would take (only asked when none is still sweeping),\n // net of the server's fees: `recoverVtxos` refuses under the dust limit, where this still answers above 0.\n const takes=!sweeping&&swept>0&&(await (await this.wallet.getVtxoManager()).getRecoverableBalance()).recoverable>=this.wallet.dustAmount;\n // While any waits for the sweep, none can be recovered: all of them wait.\n return sweeping?{recoverable:0,sweeping:sweeping+swept,small:0}:{recoverable:takes?swept:0,sweeping:0,small:takes?0:swept};\n }\n /**\n * When the first coin still spendable expires (ms), or undefined with none: a coin left alone past it is swept by the\n * server and comes back only through a recovery. An expiry in blocks is read against the explorer's tip, at about ten\n * minutes a block.\n */\n async expiresAt():Promise<number|undefined> {\n let at:number|undefined, height:number|undefined;\n for(const vtxo of await this.wallet.getVtxos({withRecoverable:false,withUnrolled:false})) {\n if(vtxo.isSwept||vtxo.isSpent)continue;\n if(vtxo.expiresAt instanceof Date){const ms=vtxo.expiresAt.getTime();if(Number.isFinite(ms))at=Math.min(at??ms,ms);}\n else if(typeof vtxo.expiresAtHeight===\"number\")height=Math.min(height??vtxo.expiresAtHeight,vtxo.expiresAtHeight);\n }\n if(height!==undefined){\n const tip=(await new EsploraProvider(this.config.explorer).getChainTip()).height;\n const ms=Date.now()+Math.max(0,height-tip)*600_000;\n at=Math.min(at??ms,ms);\n }\n return at;\n }\n /**\n * Moves swept outputs back into the balance, through the server's next batch. Refused while any expired coin is\n * not swept yet (`recoverVtxos` would name it too, and that batch fails for all of them), and when what is swept\n * is too little for a batch.\n */\n recover() { return this.serial(async()=>{\n const {recoverable,sweeping,small}=await this.expired();\n if(sweeping)throw new Error(\"Expired coins can be recovered once the Ark server has swept their batch. Try again later.\");\n if(small)throw new Error(\"Too few expired sats to recover on their own. They are recovered with the next coins that expire.\");\n if(!recoverable)throw new Error(\"Nothing to recover\");\n return (await this.wallet.getVtxoManager()).recoverVtxos();\n }); }\n /** On-chain deposits land here; the SDK's settlement moves them into Ark once confirmed. */\n boardingAddress() { return this.wallet.getBoardingAddress(); }\n /** Sats sent on-chain to the boarding address that are not in Ark yet. */\n async incoming() { return (await this.wallet.getBalance()).boarding.total; }\n async dispose() { await this.wallet.dispose(); }\n private async prepareOperation(target:PaymentTarget,amount:number,feeCap:number):Promise<{fee:number;prepared:ArkPrepared}> {\n validatePaymentTarget(target); assertWholeSats(amount); this.checkTarget(target);\n const info=await this.provider.getInfo();\n if(info.network!==this.config.network || info.signerPubkey!==this.config.serverKey)throw new Error(\"Ark provider configuration changed\");\n if(await this.balance()<amount)throw new Error(\"Insufficient Ark balance\");\n this.preview.captured=undefined;\n try { await this.wallet.send({address:target.address,amount}); }\n catch(error) {\n if(!(error instanceof PreparedOnly)) {\n // Provider errors may embed signed payment material; expose only this bounded message.\n // eslint-disable-next-line preserve-caught-error\n throw new Error(\"Could not prepare this Ark payment. Check funds, address and provider.\");\n }\n }\n const capture=this.preview.take();\n if(!capture)throw new Error(\"The Ark adapter did not prepare a transaction\");\n const tx=Transaction.fromPSBT(unbase64(capture.signedTx));\n const destination=ArkAddress.decode(target.address);\n let received=0n,input=0n,output=0n;\n for(let i=0;i<tx.inputsLength;i++){const prev=tx.getInput(i).witnessUtxo;if(!prev)throw new Error(\"Missing Ark input amount\");input+=prev.amount;}\n for(let i=0;i<tx.outputsLength;i++){const out=tx.getOutput(i);output+=out.amount??0n;if(out.script && [hex(destination.pkScript),hex(destination.subdustPkScript)].includes(hex(out.script)))received+=out.amount??0n;}\n const fee=Number(input-output);\n if(received!==BigInt(amount) || !Number.isSafeInteger(fee) || fee<0 || fee>feeCap)throw new Error(\"Prepared amount or fee does not match your review\");\n return {fee,prepared:{...capture,txid:tx.id,address:target.address,amount,fee}};\n }\n private async executeOperation(review:PaymentReview,p:ArkPrepared,persist?:()=>Promise<void>) {\n this.checkPrepared(review,p);\n const info=await this.provider.getInfo();\n if(info.network!==this.config.network || info.signerPubkey!==this.config.serverKey)throw new Error(\"Ark provider configuration changed\");\n const tx=Transaction.fromPSBT(unbase64(p.signedTx));\n const response=await this.provider.submitTx(p.signedTx,p.checkpoints);\n assertSubmittedArkTxid(response,tx,\"Ghostly Ark submission\");\n if(!response.finalArkTx)throw new Error(\"Provider returned no signed transaction\");\n this.verifyServer(Transaction.fromPSBT(unbase64(response.finalArkTx)),tx);\n const matched=matchServerCheckpoints(response.signedCheckpointTxs,p.checkpoints.map(c=>Transaction.fromPSBT(unbase64(c))),\"Ghostly Ark checkpoints\");\n const contracts=await (await this.wallet.getContractManager()).getContracts();\n const final=await Promise.all(matched.map(async ({server,local})=>{\n assertAllowedSighashTypes(server);this.verifyServer(server,local);\n let signed=server;\n for(let index=0;index<local.inputsLength;index++){\n const script=local.getInput(index).witnessUtxo?.script;\n const contract=script && contracts.find(c=>c.script===hex(script));\n if(!contract || contract.type!==\"default\")throw new Error(\"Checkpoint is not owned by this wallet profile\");\n const descriptor=contract.metadata?.signingDescriptor;\n const signer=typeof descriptor===\"string\" ? await this.wallet.signerForDescriptor(descriptor) : contract.params.pubKey===hex(await this.identity.xOnlyPublicKey()) ? this.identity : undefined;\n if(!signer)throw new Error(\"Checkpoint signing descriptor missing\");\n signed=await signer.sign(signed,[index]);\n }\n return base64(signed.toPSBT());\n }));\n p.finalCheckpoints=final;\n await persist?.();\n await this.provider.finalizeTx(p.txid,final);\n return {txid:p.txid,settled:true};\n }\n private async reconcileOperation(review:PaymentReview,p:ArkPrepared,persist?:()=>Promise<void>) {\n this.checkPrepared(review,p);\n if(await this.verifyReceipt(p.txid,p.address,p.amount))return {txid:p.txid,settled:true};\n if(!p.finalCheckpoints){\n // An empty, lagging indexer result can clear the SDK hint. The durable\n // Ghostly journal is authoritative that this approved attempt is unresolved.\n const state=await this.repository.getWalletState();\n if(!state)throw new Error(\"Ark wallet state is unavailable\");\n await this.repository.saveWalletState({...state,settings:{...state.settings,hasPendingTx:true}});\n // Ask for pending transactions using SDK ownership proofs. Only the previously\n // approved transaction may finalize; submitTx remains permanently blocked here.\n this.preview.authorizedFinalize={txid:p.txid,run:async checkpoints=>{\n const matched=matchServerCheckpoints(checkpoints,p.checkpoints.map(c=>Transaction.fromPSBT(unbase64(c))),\"Ghostly pending recovery\");\n for(const {server,local} of matched){assertAllowedSighashTypes(server);this.verifyServer(server,local);}\n p.finalCheckpoints=checkpoints;await persist?.();\n await this.provider.finalizeTx(p.txid,checkpoints);\n }};\n try {await this.wallet.finalizePendingTxs();}finally{this.preview.authorizedFinalize=undefined;}\n }\n // Resume only the same finalization, never a new send/submit after ambiguity.\n if(p.finalCheckpoints) {\n try {await this.provider.finalizeTx(p.txid,p.finalCheckpoints);}\n catch { /* A finalized transaction can reject repeated finalization; verify its receipt. */ }\n }\n return {txid:p.txid,settled:await this.verifyReceipt(p.txid,p.address,p.amount)};\n }\n /**\n * A virtual output paying `address` at least `amount`, made after `since` and none of `claimed`: how a\n * request paid from another Ark wallet is seen, with no receipt from the payer.\n */\n async received(address:string,amount:number,since:number,claimed:ReadonlySet<string>):Promise<string|undefined> {\n const destination=ArkAddress.decode(address);\n const scripts=[hex(destination.pkScript),hex(destination.subdustPkScript)];\n const {vtxos}=await this.indexer.getVtxos({scripts});\n return vtxos.find(v=>/^[a-f0-9]{64}$/.test(v.txid) && v.value>=amount && scripts.includes(v.script) && !claimed.has(v.txid) && v.createdAt.getTime()>=since-60_000)?.txid;\n }\n async verifyReceipt(txid:string,address:string,amount:number):Promise<boolean> {\n if(!/^[a-f0-9]{64}$/.test(txid))return false;\n const destination=ArkAddress.decode(address);\n const result=await this.indexer.getVtxos({outpoints:[{txid,vout:0}]});\n return result.vtxos.some(v=>v.txid===txid && v.value===amount && [hex(destination.pkScript),hex(destination.subdustPkScript)].includes(v.script));\n }\n private checkTarget(t:PaymentTarget) {\n if(t.method!==this.method || t.provider!==this.config.provider || t.network!==this.config.network || t.asset!==\"BTC\" || t.unit!==\"sat\")throw new Error(\"Payment method, network or provider does not match this wallet\");\n const decoded=ArkAddress.decode(t.address);\n const pinned=this.config.serverKey.replace(/^(02|03)(?=[a-f0-9]{64}$)/,\"\");\n if(hex(decoded.serverPubKey)!==pinned || decoded.hrp!==(this.config.network===\"bitcoin\"?\"ark\":\"tark\"))throw new Error(\"Ark address belongs to another provider or network\");\n }\n private verifyServer(server:Transaction,local:Transaction) {\n const key=this.config.serverKey.replace(/^(02|03)(?=[a-f0-9]{64}$)/,\"\");\n for(let index=0;index<local.inputsLength;index++){\n const leaf=local.getInput(index).tapLeafScript?.[0]?.[1];\n if(!leaf)throw new Error(\"Missing reviewed spend leaf\");\n verifyTapscriptSignatures(server,index,[key],undefined,undefined,tapLeafHash(leaf.subarray(0,-1),leaf[leaf.length-1]));\n }\n }\n private checkPrepared(r:PaymentReview,p:ArkPrepared) {\n this.checkTarget(r);\n if(p.address!==r.address || p.amount!==r.amount || p.fee!==r.fee || p.fee>r.feeCap || Transaction.fromPSBT(unbase64(p.signedTx)).id!==p.txid)throw new Error(\"Prepared payment does not match the approved review\");\n }\n}\n"],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- import { r as buttonsOf } from "./buttons-CvNBzh2S.js";
2
- export { buttonsOf };