@fangorn-network/westmarch 0.0.19-dev → 2026.10.2-0.0-dev

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 (590) hide show
  1. package/README.md +33 -3
  2. package/docs/app-to-agent.md +100 -27
  3. package/package.json +9 -5
  4. package/plugin/scripts/fx.mjs +7 -9
  5. package/site/dist/assets/AccountNotFoundScreen-C4njXc69-RUyAWRzV.js +1 -0
  6. package/site/dist/assets/AddFundsSelectionScreen-RAoCn7ej-ZV-LlYBe.js +31 -0
  7. package/site/dist/assets/Address-H8kD1d9O-CGQnt7Pu.js +17 -0
  8. package/site/dist/assets/AffirmativeConsentScreen-BG0MJxku-CKn2JLwq.js +6 -0
  9. package/site/dist/assets/AllowlistRejectionScreen-Cae6e1Od-9oIP9fma.js +1 -0
  10. package/site/dist/assets/ArrowsRightLeftIcon-BEhBD_6N.js +1 -0
  11. package/site/dist/assets/AuthenticateWithWalletScreen-CU6hIcFT-D1wLlSJs.js +1 -0
  12. package/site/dist/assets/AwaitingEvmToSolBridgingScreen-D0e_sZMS-CSBbHTyz.js +1 -0
  13. package/site/dist/assets/AwaitingExternalEthereumTransferScreen-ur5HL4R7-BsRq-xBt.js +1 -0
  14. package/site/dist/assets/AwaitingPasswordlessCodeScreen-DRHz76mM-BPdhsKvN.js +103 -0
  15. package/site/dist/assets/AwaitingSolToEvmBridgingScreen-CdLRrGD2-CEGNdrkr.js +1 -0
  16. package/site/dist/assets/BridgeNetworkSelectionView-CFGjB2nO-Da9P7eSx.js +68 -0
  17. package/site/dist/assets/CaptchaScreen-DbpvkIGx-BecgMnD_.js +1 -0
  18. package/site/dist/assets/CheckCircleIcon-DBiWFjO6.js +1 -0
  19. package/site/dist/assets/CheckCircleIcon-DzG2ROJZ.js +1 -0
  20. package/site/dist/assets/Checkbox-D1EDeo41-DMHcj9o_.js +52 -0
  21. package/site/dist/assets/ChevronDownIcon-2Os56gUt.js +1 -0
  22. package/site/dist/assets/Chip-CZKIKt9K-BWzs9fj5.js +26 -0
  23. package/site/dist/assets/CoinbaseOnrampStatusScreen-BbyCJDXL-CFvcSiDs.js +16 -0
  24. package/site/dist/assets/ConnectEmailForm-B-VRE0MN-BozkCg8q.js +3 -0
  25. package/site/dist/assets/ConnectLedgerScreen-DWHABGot-DaCnbBzh.js +10 -0
  26. package/site/dist/assets/ConnectOnlyLandingScreen-CZYx9Bmp-DUkCLkxD.js +1 -0
  27. package/site/dist/assets/ConnectOnlyStatusScreen-DCRzjxHx-Dv_5nMkZ.js +1 -0
  28. package/site/dist/assets/ConnectOrCreateScreen-CUUYUO07-DSGEeB3Y.js +1 -0
  29. package/site/dist/assets/ConnectPhoneForm-Dek5xn4C-C-s4s_Lq.js +95 -0
  30. package/site/dist/assets/ConnectWalletView-DqI-PTvX-BKX7fdYr.js +74 -0
  31. package/site/dist/assets/ConnectionStatusScreen-fUfROm9m-DSoAuMFZ.js +7 -0
  32. package/site/dist/assets/CopyToClipboard-i_OQSBJr-CZTXyfV0.js +39 -0
  33. package/site/dist/assets/CopyableText-CQapvaMr-DHO818I0.js +28 -0
  34. package/site/dist/assets/CrossAppAuthScreen-CLw7ymZq-DW4nRGfz.js +1 -0
  35. package/site/dist/assets/CustomLandingScreenView-Cm_MBSyX-DH8Nnb4Y.js +22 -0
  36. package/site/dist/assets/DelegatedActionsConsentScreen-DYF2U4y5-gfUS_uV5.js +1 -0
  37. package/site/dist/assets/DelegatedActionsRevokeScreen-bPp6Uwyh-DZj9HTHc.js +1 -0
  38. package/site/dist/assets/DepositAddressAddressStepView-4vdkb55L-eHYsDK9W.js +187 -0
  39. package/site/dist/assets/DepositAddressScreen-DBLRs7aI-DK_XVgVk.js +8 -0
  40. package/site/dist/assets/DepositAddressV3Screen-CDqIEMQw-6gRZzhLe.js +1 -0
  41. package/site/dist/assets/{EmailInputForm-Cqo1mda8-B2NG3K5V.js → EmailInputForm-Cqo1mda8-CZD4r5LM.js} +11 -11
  42. package/site/dist/assets/EmbeddedWalletConnectingScreen-D4T7DUzs-BZu2ae0k.js +1 -0
  43. package/site/dist/assets/EmbeddedWalletCreatedScreen-D7WhW5ve-86pviemJ.js +1 -0
  44. package/site/dist/assets/EmbeddedWalletKeyExportScreen-CqV4NYQ3-vDcvT53Y.js +23 -0
  45. package/site/dist/assets/EmbeddedWalletOnAccountCreateScreen-BoKb3Q2S-rNJAtSJc.js +1 -0
  46. package/site/dist/assets/EmbeddedWalletPasswordUpdateScreen-D3rMlqS7-I8Q95280.js +1 -0
  47. package/site/dist/assets/EmbeddedWalletPasswordUpdateSplashScreen-BPFkWJeE-Coi7OxoI.js +1 -0
  48. package/site/dist/assets/EnrollTotp-Dibew4dp-DC7FrDgo.js +66 -0
  49. package/site/dist/assets/EnvelopeIcon-DY6ERnW7.js +1 -0
  50. package/site/dist/assets/ErrorBanner-BcpGRt0h-BvESwN99.js +21 -0
  51. package/site/dist/assets/{ErrorMessage-D8VaAP5m-CrZOnUyg.js → ErrorMessage-D8VaAP5m-oSruKN8L.js} +2 -2
  52. package/site/dist/assets/ErrorScreen-DipdTWzE-DnKGxH1Z.js +4 -0
  53. package/site/dist/assets/ExclamationCircleIcon-BZhlqH0r.js +1 -0
  54. package/site/dist/assets/ExclamationTriangleIcon-CkAOJIYV.js +1 -0
  55. package/site/dist/assets/FarcasterConnectStatusScreen-51tjUxqq-4pi7jooW.js +75 -0
  56. package/site/dist/assets/FarcasterSignerStatusScreen-6x-Uh95G-z2XCMaLL.js +28 -0
  57. package/site/dist/assets/FiatOnrampScreen-BAhYeiTI-CBVA9v1-.js +491 -0
  58. package/site/dist/assets/FingerPrintIcon-ra2dqmJO.js +1 -0
  59. package/site/dist/assets/FundSolWalletWithExternalSolanaWallet-WtLwYaOl-DwAwc6Ny.js +1 -0
  60. package/site/dist/assets/FundWalletMethodHeader-BWNkokCT-CZszQsZf.js +1 -0
  61. package/site/dist/assets/FundWithBankDepositScreen-DajkHxBD-DfX6nvFQ.js +58 -0
  62. package/site/dist/assets/FundingEditAmountScreen-CpvpiO4M-CDS_sk_t.js +1 -0
  63. package/site/dist/assets/FundingMethodSelectionScreen-Db7vhRlE-CPfNQemT.js +1 -0
  64. package/site/dist/assets/GlobeAltIcon-SEUEIe_E.js +1 -0
  65. package/site/dist/assets/GooglePay-B53WnudL-aap7zwag.js +1 -0
  66. package/site/dist/assets/HCaptchaWrapper-CUi9LJsp-DgSjCjQI.js +4 -0
  67. package/site/dist/assets/InAppBrowserLoginNotPossible-BMR9br1T-DO4wICml.js +1 -0
  68. package/site/dist/assets/InfoBanner-Cb3p1z12-CDWt2ADo.js +22 -0
  69. package/site/dist/assets/InjectedWalletIcon-DLcYOGDj-Ba19XoBr.js +1 -0
  70. package/site/dist/assets/InstallWalletScreen-DTA8dwLv-DGpewEch.js +1 -0
  71. package/site/dist/assets/{JsonTree-BHzNC-ic-DcNcbSoM.js → JsonTree-BHzNC-ic-pAEq1bl9.js} +3 -3
  72. package/site/dist/assets/{LabelXs-oqZNqbm_-iafrj25N.js → LabelXs-oqZNqbm_-D09YjVR4.js} +2 -2
  73. package/site/dist/assets/LandingScreen-CGWUoSUG-CUOCWUXd.js +1 -0
  74. package/site/dist/assets/{Layouts-BMRfo5hw-CeCOyCLK.js → Layouts-BMRfo5hw-D2u1-w8g.js} +16 -16
  75. package/site/dist/assets/Link-BdDilT2T-BYiP1zvW.js +40 -0
  76. package/site/dist/assets/LinkConflictScreen-C3ZEPsgl-Tb6cAepT.js +77 -0
  77. package/site/dist/assets/LinkEmailScreen-dKo9frwc-pq0NF2JO.js +1 -0
  78. package/site/dist/assets/LinkPasskeyScreen-zbrl_AI_-D9MOmDqg.js +117 -0
  79. package/site/dist/assets/LinkPhoneScreen-oIUpfj0w-B80UJqAZ.js +1 -0
  80. package/site/dist/assets/{LoadingSkeleton-BMsgO5PV-CiEyS5PZ.js → LoadingSkeleton-BMsgO5PV-BRMh4Fv4.js} +6 -6
  81. package/site/dist/assets/LockClosedIcon-BqkoEL9J.js +1 -0
  82. package/site/dist/assets/LoginFailedScreen-CN0dJV6U-DlnOM-Kh.js +1 -0
  83. package/site/dist/assets/ManualTransferScreen-CHqcuqbs-DSShupq9.js +1 -0
  84. package/site/dist/assets/MfaAuthEnrollmentFlowScreen-Dj7gPTRC-DUPV_SLA.js +1 -0
  85. package/site/dist/assets/MfaAuthVerifyFlowScreen-DbFpyWMy-D96GpzXX.js +1 -0
  86. package/site/dist/assets/MfaEnrollmentFlowScreen-DhLnGgnr-CYQDa4ND.js +1 -0
  87. package/site/dist/assets/MfaVerifyFlowScreen-C_XPjMRP-CJtSAXGN.js +1 -0
  88. package/site/dist/assets/ModalFooter-BCuEK_nz-D2I8KWtk.js +403 -0
  89. package/site/dist/assets/MoonpayStatusScreen-CzTUtokc-Bx5aHy-z.js +16 -0
  90. package/site/dist/assets/OAuthStatusScreen-ufbOa-da-CS6988X2.js +1 -0
  91. package/site/dist/assets/OpenLink-CUpJ1mOr-EZWVSX2r.js +39 -0
  92. package/site/dist/assets/PasskeySelectSignupOrLogin-xh2ScC_l-BY4eK5Jh.js +1 -0
  93. package/site/dist/assets/PasskeyStatusScreen-Bla8MaOk-LXys76u9.js +6 -0
  94. package/site/dist/assets/PasswordRecoveryScreen-awGXZkQk-RczvLvmo.js +20 -0
  95. package/site/dist/assets/{PhArrowCircleDown-D97G-BOA.js → PhArrowCircleDown-BtlNV0TZ.js} +5 -5
  96. package/site/dist/assets/PhArrowClockwise-mOiWYLMV.js +14 -0
  97. package/site/dist/assets/PhArrowDown-CkoOD89h.js +14 -0
  98. package/site/dist/assets/PhArrowLeft-C0jlxVhM.js +14 -0
  99. package/site/dist/assets/PhArrowRight-BI-V03Xf.js +14 -0
  100. package/site/dist/assets/{PhArrowSquareOut-Bk2CMG3I.js → PhArrowSquareOut-DnQ7n_B4.js} +5 -5
  101. package/site/dist/assets/PhArrowUp-izKvURUW.js +14 -0
  102. package/site/dist/assets/PhArrowUpRight-Bn-JhHsY.js +14 -0
  103. package/site/dist/assets/{PhArrowsClockwise-BXRn1GEl.js → PhArrowsClockwise-Brtx2Re-.js} +5 -5
  104. package/site/dist/assets/{PhArrowsDownUp-DM09Jo_3.js → PhArrowsDownUp-PZosTqZG.js} +5 -5
  105. package/site/dist/assets/PhArrowsLeftRight-CYsRQ2qh.js +14 -0
  106. package/site/dist/assets/{PhBank-fHbgCqqZ.js → PhBank-hhPAIPVb.js} +5 -5
  107. package/site/dist/assets/PhBrowser-BjzAmrHO.js +14 -0
  108. package/site/dist/assets/PhCaretDown-ddSjwcwm.js +14 -0
  109. package/site/dist/assets/PhCaretLeft-B7YLoNEF.js +14 -0
  110. package/site/dist/assets/PhCaretRight-BY8D5MIg.js +14 -0
  111. package/site/dist/assets/PhCaretUp-BG10nSut.js +14 -0
  112. package/site/dist/assets/PhCheck-DrKd7pBC.js +14 -0
  113. package/site/dist/assets/{PhCircleHalf-MJZeRBGF.js → PhCircleHalf-Bk9C4DvT.js} +5 -5
  114. package/site/dist/assets/PhClock-Sj17weCB.js +14 -0
  115. package/site/dist/assets/{PhCompass-hYn3HhGN.js → PhCompass-Df1ugFO-.js} +5 -5
  116. package/site/dist/assets/PhCopy-rgttky8E.js +14 -0
  117. package/site/dist/assets/{PhCreditCard-Fy4pzwtt.js → PhCreditCard-CZpdid2n.js} +5 -5
  118. package/site/dist/assets/{PhCurrencyDollar-BgiaenCi.js → PhCurrencyDollar-B6IKKjue.js} +5 -5
  119. package/site/dist/assets/{PhDesktop-CxrzCSv5.js → PhDesktop-BuCDXYJj.js} +5 -5
  120. package/site/dist/assets/PhDeviceMobile-CnybhXY-.js +14 -0
  121. package/site/dist/assets/PhDotsThree-CSAEcba1.js +14 -0
  122. package/site/dist/assets/PhEnvelope-SmaNeXoQ.js +14 -0
  123. package/site/dist/assets/PhFunnelSimple-DKx35ITq.js +14 -0
  124. package/site/dist/assets/{PhGlobe-DvmSc9_A.js → PhGlobe-q1mqj65V.js} +5 -5
  125. package/site/dist/assets/{PhIdentificationCard-CfkZm-5K.js → PhIdentificationCard-BeLXJpfZ.js} +5 -5
  126. package/site/dist/assets/{PhImage-Cf0J2ZfJ.js → PhImage-BYrKfN9k.js} +5 -5
  127. package/site/dist/assets/{PhInfo-Bwi51-2X.js → PhInfo-X33f06Ej.js} +5 -5
  128. package/site/dist/assets/{PhLightbulb-C4FZV7Es.js → PhLightbulb-DMZJsowR.js} +5 -5
  129. package/site/dist/assets/PhMagnifyingGlass-B6D0sWFL.js +14 -0
  130. package/site/dist/assets/{PhPaperPlaneRight-zxQVvPLX.js → PhPaperPlaneRight-Dvo-nXr9.js} +5 -5
  131. package/site/dist/assets/PhPlus-CBvZvLax.js +14 -0
  132. package/site/dist/assets/{PhPower-CFyWDmgD.js → PhPower-D8-AcNM6.js} +5 -5
  133. package/site/dist/assets/{PhPuzzlePiece-BjoNVfST.js → PhPuzzlePiece-C-7mYqGO.js} +5 -5
  134. package/site/dist/assets/{PhQrCode-CP3tFauY.js → PhQrCode-uIXlI5ER.js} +5 -5
  135. package/site/dist/assets/{PhQuestion-wOWJBd3G.js → PhQuestion-rUoqC2sC.js} +5 -5
  136. package/site/dist/assets/{PhQuestionMark-CV0k9C0Y.js → PhQuestionMark-W55Txvvb.js} +5 -5
  137. package/site/dist/assets/{PhSealCheck-vIKzREuN.js → PhSealCheck-BeVLq9PH.js} +5 -5
  138. package/site/dist/assets/{PhSignOut-CxELV-i0.js → PhSignOut-Cq2PivQ6.js} +5 -5
  139. package/site/dist/assets/{PhSpinner-CGDmbzUd.js → PhSpinner-CZMtAFdX.js} +5 -5
  140. package/site/dist/assets/{PhTrash-C9PD0SAt.js → PhTrash-BamrmMsN.js} +5 -5
  141. package/site/dist/assets/{PhUser-0sWNXQeZ.js → PhUser-A2fxqIV0.js} +5 -5
  142. package/site/dist/assets/{PhVault-6JTskUcC.js → PhVault-B8m1usHw.js} +5 -5
  143. package/site/dist/assets/{PhWarning-CoKs3gz6.js → PhWarning-CpkID9oi.js} +5 -5
  144. package/site/dist/assets/PhWarningCircle-Cm58gXb9.js +14 -0
  145. package/site/dist/assets/PhX-C3b4cCEy.js +14 -0
  146. package/site/dist/assets/PhoneIcon-CzbssTb8.js +1 -0
  147. package/site/dist/assets/PinInput-DbZ0b1i1-1DtLWL81.js +247 -0
  148. package/site/dist/assets/QrCode-DbnZwlkH-ChwcUk_h.js +22 -0
  149. package/site/dist/assets/RecoveryOAuthStatusScreen-CsgtTI2x-C79jd345.js +1 -0
  150. package/site/dist/assets/RecoveryPasswordCreateScreen-Be-qJ-LU-C9c0x-yq.js +1 -0
  151. package/site/dist/assets/RecoverySelectionScreen-D1iGtpmi-PNqHb6CI.js +7 -0
  152. package/site/dist/assets/{Screen-D30meWsY-CCeVNuWs.js → Screen-D30meWsY-DDum2qlY.js} +22 -22
  153. package/site/dist/assets/{ScreenHeader-CHmc4-Lu-DjyrH7IK.js → ScreenHeader-CHmc4-Lu-BqrAEXbV.js} +4 -4
  154. package/site/dist/assets/ScreenLayout-OwaQQcxH-B4Z8FjFp.js +1 -0
  155. package/site/dist/assets/{SelectSourceAsset-CWFog6gm-RKjBsB6m.js → SelectSourceAsset-CWFog6gm-8iXuqbAs.js} +18 -18
  156. package/site/dist/assets/SetAutomaticRecoveryScreen-BO_OEqAZ-CUpQZ9wq.js +14 -0
  157. package/site/dist/assets/SetWalletPasswordForm-DwCTVtAh-ZzvPLj2s.js +15 -0
  158. package/site/dist/assets/ShieldCheckIcon-Bjwe_-PV.js +1 -0
  159. package/site/dist/assets/SignRequestScreen-BHKv32KR-0qGeNipB.js +26 -0
  160. package/site/dist/assets/{StackedContainer-B2vaEl56-eQCM2cmv.js → StackedContainer-B2vaEl56-C-ojzCoQ.js} +2 -2
  161. package/site/dist/assets/StandardSignAndSendTransactionScreen-CfhIXVtd-C3lgJb68.js +20 -0
  162. package/site/dist/assets/{Subtitle-CV-2yKE4-zxWw2m1Q.js → Subtitle-CV-2yKE4-o-1FQLlX.js} +2 -2
  163. package/site/dist/assets/TelegramAuthScreen-UL9zLfO8-l35_C2DG.js +1 -0
  164. package/site/dist/assets/{Title-BnzYV3Is-B_JpTatT.js → Title-BnzYV3Is-RX1f0RV-.js} +2 -2
  165. package/site/dist/assets/TodoList-DnyULl18-JxWWU9KA.js +36 -0
  166. package/site/dist/assets/TransactionDetails-e9nesl30-C91nJPM9.js +109 -0
  167. package/site/dist/assets/TransactionErrorView-BDBNqA_f-Cpm-4xzm.js +178 -0
  168. package/site/dist/assets/TransferFromWalletScreen-Qvn1Yuno-BWCH7-Si.js +31 -0
  169. package/site/dist/assets/TransferOrBridgeLoadingScreen-Dl1I_iIz-BWMeJabk.js +6 -0
  170. package/site/dist/assets/TurnstileWrapper-B7sNddys-Dgr80Gih.js +1 -0
  171. package/site/dist/assets/UpdateEmailScreen-DVOhPV0H-Clk4zk-8.js +1 -0
  172. package/site/dist/assets/UpdatePhoneScreen-CXRswTNZ-BgRsoR3B.js +1 -0
  173. package/site/dist/assets/UserLimitReachedScreen-5we2DHn8-D-SU-vAz.js +1 -0
  174. package/site/dist/assets/{Value-DTgR824E-BRuIGiec.js → Value-DTgR824E-DZpvBCWi.js} +7 -7
  175. package/site/dist/assets/WalletCards-DH1rqayz-UuZ4i_Ze.js +1 -0
  176. package/site/dist/assets/WalletIcon-B1i03Vqc.js +1 -0
  177. package/site/dist/assets/WalletInfoCard-sq_2wgFg-TXTxmb8L.js +29 -0
  178. package/site/dist/assets/WalletInterstitialScreen-Sh7LfsAh-CbrFb0ON.js +1 -0
  179. package/site/dist/assets/WalletLink-DK5LB5Ha-BYQZV7UV.js +20 -0
  180. package/site/dist/assets/WalletOverflowButton-bfCnp-9T-CNgSPnTS.js +1 -0
  181. package/site/dist/assets/WarningBanner-ZZqCEtZK-DNZUUOph.js +21 -0
  182. package/site/dist/assets/__vite-browser-external-BIHI7g3E.js +1 -0
  183. package/site/dist/assets/analytics-mkkvFRju-DOXuftJB.js +1 -0
  184. package/site/dist/assets/basic-C9wn6QoQ.js +1575 -0
  185. package/site/dist/assets/bytes-CjWw8TJh.js +1 -0
  186. package/site/dist/assets/capitalizeFirstLetter-DmLYqXsO-tV1Idewc.js +1 -0
  187. package/site/dist/assets/ccip-BhHEqVIW.js +1 -0
  188. package/site/dist/assets/check-C_DTyjLS.js +1 -0
  189. package/site/dist/assets/chevron-down-iklXXH-z.js +1 -0
  190. package/site/dist/assets/circle-alert-KEOUF48T.js +1 -0
  191. package/site/dist/assets/circle-check-big-BJ_ADwB4.js +1 -0
  192. package/site/dist/assets/circle-x-BSfWmhYk.js +1 -0
  193. package/site/dist/assets/client-BnDcP42J.js +9 -0
  194. package/site/dist/assets/client-DH86IrJA.js +125 -0
  195. package/site/dist/assets/coinbase-DCPC2L_R-2ivYfoMv.js +3 -0
  196. package/site/dist/assets/copy-sK00DOfH.js +1 -0
  197. package/site/dist/assets/core-CRE213RM.js +211 -0
  198. package/site/dist/assets/createLucideIcon-D9OK_uxG.js +1 -0
  199. package/site/dist/assets/custom-V1wex-Di.js +1 -0
  200. package/site/dist/assets/dijkstra-COg3n3zL.js +1 -0
  201. package/site/dist/assets/embed.worker-BRIYO7m8.js +1 -0
  202. package/site/dist/assets/encodePacked-DyXYq3Cc.js +1 -0
  203. package/site/dist/assets/ethers-zTjbodk5-DSYOi6tU.js +1 -0
  204. package/site/dist/assets/external-link-Cdp8NBio.js +1 -0
  205. package/site/dist/assets/fallback-DiFue5Zm.js +1 -0
  206. package/site/dist/assets/farcaster-DPlSjvF5-DP2DLoHZ.js +1 -0
  207. package/site/dist/assets/features-B6BTj_BL.js +5 -0
  208. package/site/dist/assets/fingerprint-pattern-gFJTz5e4.js +1 -0
  209. package/site/dist/assets/floating-ui.react-D9ndYqYK.js +1 -0
  210. package/site/dist/assets/floating-ui.react-dom-CNbOgOFt.js +1 -0
  211. package/site/dist/assets/formatErc20TokenAmount-BuPk9xcy-CkAr4Oc0.js +1 -0
  212. package/site/dist/assets/getChainName-DjpPdUSc-c2urPd0g.js +1 -0
  213. package/site/dist/assets/getErc20Balance-jXNpFf0N-mFQ9Iqk-.js +1 -0
  214. package/site/dist/assets/getErc20TokenInfo-BNTrzLMP-Dx5he_uG.js +1 -0
  215. package/site/dist/assets/getFormattedUsdFromLamports-De3U9GlO-C446pzMl.js +1 -0
  216. package/site/dist/assets/getTransactionCount-80UHlwAV.js +1 -0
  217. package/site/dist/assets/getUsdcMintAddress-BVgm9GRo-FDalV59C.js +1 -0
  218. package/site/dist/assets/hashTypedData-Beq57Ogb.js +22 -0
  219. package/site/dist/assets/hooks.module-ClpaQ1Tg.js +1 -0
  220. package/site/dist/assets/hourglass-CB7z_I9H.js +1 -0
  221. package/site/dist/assets/http-BocEfKYb.js +19 -0
  222. package/site/dist/assets/index-0knDOgU9.js +1 -0
  223. package/site/dist/assets/index-9jNeS_nC.js +1 -0
  224. package/site/dist/assets/index-B--T-Fmt.js +16 -0
  225. package/site/dist/assets/index-BDkarAkX.js +2 -0
  226. package/site/dist/assets/index-BMfMy017.js +679 -0
  227. package/site/dist/assets/index-BOd8jv8-.js +1 -0
  228. package/site/dist/assets/index-BdEw5wyl-2VGMzHIs.js +1 -0
  229. package/site/dist/assets/index-C8ThRelw.js +9 -0
  230. package/site/dist/assets/{index-CWARkn2w-Cezl_uBr.js → index-CWARkn2w-D6ikWJWj.js} +7 -7
  231. package/site/dist/assets/{wui-ux-by-reown-fVu0QkI4.js → index-CztIxJB6.js} +296 -296
  232. package/site/dist/assets/index-D4LdLFDC.js +1 -0
  233. package/site/dist/assets/index-D6T-s6sR.js +1 -0
  234. package/site/dist/assets/index-D7396TWe.js +1 -0
  235. package/site/dist/assets/index-DdxtHe81.js +2 -0
  236. package/site/dist/assets/index-DvMddJcd-D7AEQrzj.js +12 -0
  237. package/site/dist/assets/index-nibyPLVP.js +1 -0
  238. package/site/dist/assets/index.browser-B6Bt5URJ.js +1 -0
  239. package/site/dist/assets/isPaymentRequestAvailable-Bq1cemEn-D7xtzRqA.js +1 -0
  240. package/site/dist/assets/landmark-CMLKifhk.js +1 -0
  241. package/site/dist/assets/lock-BkyjNE8h.js +1 -0
  242. package/site/dist/assets/mail-B6-Tq9Ld.js +1 -0
  243. package/site/dist/assets/native-CJ5et6AR.js +1 -0
  244. package/site/dist/assets/nonceManager-zkW7cM66.js +1 -0
  245. package/site/dist/assets/parseEther-C7aOvuze.js +1 -0
  246. package/site/dist/assets/parseSignature-BIjcuWdB.js +1 -0
  247. package/site/dist/assets/preload-helper-PPVm8Dsz.js +1 -0
  248. package/site/dist/assets/privateKeyToAccount-CRvvpHWf.js +1 -0
  249. package/site/dist/assets/property-CnFDNXw5.js +3 -0
  250. package/site/dist/assets/react-auth_false-DedQs79w.js +1 -0
  251. package/site/dist/assets/reservoir-x-nGuZkT-DFxAFt2v.js +1 -0
  252. package/site/dist/assets/roles-DV_6FRBZ.js +1 -0
  253. package/site/dist/assets/safe-url-D7SRPu33-A8zMgOTd.js +1 -0
  254. package/site/dist/assets/serializeErc6492Signature-CeJeL3h6.js +1 -0
  255. package/site/dist/assets/serializeTransaction-L-_Ej-jW.js +8 -0
  256. package/site/dist/assets/{shared-DRZUmnL5-xqAUARWo.js → shared-DRZUmnL5-MWD-C-pp.js} +33 -33
  257. package/site/dist/assets/{shared-FM0rljBt--Avg6q2R.js → shared-FM0rljBt-c4eSjzGj.js} +6 -6
  258. package/site/dist/assets/shouldProceedtoEmbeddedWalletCreationFlow-B3vyavrh-CF2QteTJ.js +1 -0
  259. package/site/dist/assets/simulateTransaction-CfuOrae4-BHUMPf6Q.js +1 -0
  260. package/site/dist/assets/smartphone-DAN5rY0T.js +1 -0
  261. package/site/dist/assets/stripe.esm-Dv8C3q95.js +2 -0
  262. package/site/dist/assets/styles-BsotlekN-Cjuu2SDV.js +9 -0
  263. package/site/dist/assets/{styles-Cm9H63WO-D90SsXOs.js → styles-Cm9H63WO-Cv1TbqYi.js} +17 -17
  264. package/site/dist/assets/{styles-DVyDvTdj-BTABn2K8.js → styles-DVyDvTdj-CI4xZNHp.js} +8 -8
  265. package/site/dist/assets/{styles-hslXy6xG-D-49b1rk.js → styles-hslXy6xG-DeVcFoDD.js} +23 -23
  266. package/site/dist/assets/telegram-B-JqnkqZ-DTjJLkIF.js +1 -0
  267. package/site/dist/assets/to-ui-error-DWe-qwS3-Dx3yzcV0.js +4 -0
  268. package/site/dist/assets/toAccount-Bq6rbpbI.js +1 -0
  269. package/site/dist/assets/transaction-BNTP-bFm-CrebgH-D.js +1 -0
  270. package/site/dist/assets/transactionReceipt-BwJl-gjg.js +1 -0
  271. package/site/dist/assets/transfer-6YztDh-t-DU6hH7CZ.js +1 -0
  272. package/site/dist/assets/transformers.web-BEKVh7pD.js +40 -0
  273. package/site/dist/assets/transformers.web-aWa49tv1.js +40 -0
  274. package/site/dist/assets/triangle-alert-ndoiBs4y.js +1 -0
  275. package/site/dist/assets/twitch-5IOe4sIQ-BXviIywg.js +1 -0
  276. package/site/dist/assets/useGetSolPrice-x7gfUIHJ-C7axYJ--.js +1 -0
  277. package/site/dist/assets/useGetTokenPrice-CaoUkb79-CR4CrguU.js +1 -0
  278. package/site/dist/assets/useI18n-C-5n_noF-C_t8QqBJ.js +1 -0
  279. package/site/dist/assets/useWalletBalance-CZnP5f_f-BnSHLVI_.js +1 -0
  280. package/site/dist/assets/w3m-modal-Bz5KWTQ-.js +1174 -0
  281. package/site/dist/assets/wallet-DTM31trz.js +2 -0
  282. package/site/dist/assets/wallet-UESEqPei.js +1 -0
  283. package/site/dist/assets/wallet-connect-BvJtUsDt-CnvUnFbz.js +1 -0
  284. package/site/dist/assets/walletconnect-v2-3frQFwbg-CzQk99gS.js +15 -0
  285. package/site/dist/assets/x-B2_XdOVQ.js +1 -0
  286. package/site/dist/index.html +120 -8
  287. package/site/feed.js +16 -1
  288. package/site/no-model.js +4 -0
  289. package/site/worker.js +597 -58
  290. package/src/agent/agent-card.js +20 -11
  291. package/src/agent/mcp.js +150 -316
  292. package/src/agent/view-tools.js +53 -12
  293. package/src/agent/x402.js +379 -44
  294. package/src/core/embed.js +51 -52
  295. package/src/core/embed.worker.js +1 -1
  296. package/src/core/shard.js +7 -3
  297. package/src/discover/apps.js +4 -3
  298. package/src/discover/explore.js +36 -22
  299. package/src/market/reactions.js +2 -2
  300. package/src/publish/devnet.js +95 -0
  301. package/src/publish/lint.js +2 -1
  302. package/src/publish/ship.js +517 -236
  303. package/src/publish/view-cli.js +11 -10
  304. package/src/publish/view.js +359 -206
  305. package/src/taste/taste-doc.js +3 -2
  306. package/src/taste/taste.js +2 -2
  307. package/src/taste/vault.js +3 -1
  308. package/site/dist/assets/AccountNotFoundScreen-C4njXc69-BOfmiSH1.js +0 -1
  309. package/site/dist/assets/AddFundsSelectionScreen-RAoCn7ej-B6uvYyqa.js +0 -31
  310. package/site/dist/assets/Address-H8kD1d9O-DcHv7A8C.js +0 -17
  311. package/site/dist/assets/AffirmativeConsentScreen-BG0MJxku-v2wz-N-s.js +0 -6
  312. package/site/dist/assets/AllowlistRejectionScreen-Cae6e1Od-DhVy9iGN.js +0 -1
  313. package/site/dist/assets/ApiController-BbhXeqTV.js +0 -5
  314. package/site/dist/assets/ArrowsRightLeftIcon-cp60yobq.js +0 -1
  315. package/site/dist/assets/AuthenticateWithWalletScreen-CU6hIcFT-B0eT1zE6.js +0 -1
  316. package/site/dist/assets/AwaitingEvmToSolBridgingScreen-D0e_sZMS-DL5PH-v_.js +0 -1
  317. package/site/dist/assets/AwaitingExternalEthereumTransferScreen-ur5HL4R7-n1BsRPqc.js +0 -1
  318. package/site/dist/assets/AwaitingPasswordlessCodeScreen-DRHz76mM-BVl2BJDY.js +0 -103
  319. package/site/dist/assets/AwaitingSolToEvmBridgingScreen-CdLRrGD2-BD-OZUQb.js +0 -1
  320. package/site/dist/assets/BridgeNetworkSelectionView-CFGjB2nO-CaYrzRje.js +0 -68
  321. package/site/dist/assets/CaptchaScreen-DbpvkIGx-BQJ7inx1.js +0 -1
  322. package/site/dist/assets/CheckCircleIcon-BM409mGI.js +0 -1
  323. package/site/dist/assets/CheckCircleIcon-NCOQc0Gs.js +0 -1
  324. package/site/dist/assets/Checkbox-D1EDeo41-rHlvsZzP.js +0 -52
  325. package/site/dist/assets/ChevronDownIcon-CW-4MSpE.js +0 -1
  326. package/site/dist/assets/Chip-CZKIKt9K-CutJG010.js +0 -26
  327. package/site/dist/assets/CoinbaseOnrampStatusScreen-BbyCJDXL-DDaMC7cl.js +0 -16
  328. package/site/dist/assets/ConnectEmailForm-B-VRE0MN-DVSf4tFJ.js +0 -3
  329. package/site/dist/assets/ConnectLedgerScreen-DWHABGot-h0uYIUi6.js +0 -10
  330. package/site/dist/assets/ConnectOnlyLandingScreen-CZYx9Bmp-DP19hJq5.js +0 -1
  331. package/site/dist/assets/ConnectOnlyStatusScreen-DCRzjxHx-DHvijlTx.js +0 -1
  332. package/site/dist/assets/ConnectOrCreateScreen-CUUYUO07-ewmXYPTQ.js +0 -1
  333. package/site/dist/assets/ConnectPhoneForm-Dek5xn4C-DUYdmVtr.js +0 -95
  334. package/site/dist/assets/ConnectWalletView-DqI-PTvX-RobGErVW.js +0 -74
  335. package/site/dist/assets/ConnectionStatusScreen-fUfROm9m-Bbiq3hY6.js +0 -1
  336. package/site/dist/assets/ConnectionStatusScreen-fUfROm9m-DPkOGNWl.js +0 -7
  337. package/site/dist/assets/ConnectorUtil-BO1L6VvV.js +0 -21
  338. package/site/dist/assets/ConstantsUtil-DmLsRHAl.js +0 -198
  339. package/site/dist/assets/CopyToClipboard-i_OQSBJr-DujUHNzW.js +0 -39
  340. package/site/dist/assets/CopyableText-CQapvaMr-DMIdpDaU.js +0 -28
  341. package/site/dist/assets/CrossAppAuthScreen-CLw7ymZq-DbGy4QyA.js +0 -1
  342. package/site/dist/assets/CustomLandingScreenView-Cm_MBSyX-B3WqJZBh.js +0 -22
  343. package/site/dist/assets/DelegatedActionsConsentScreen-DYF2U4y5-CmUDoS0C.js +0 -1
  344. package/site/dist/assets/DelegatedActionsRevokeScreen-bPp6Uwyh-fcO51q5H.js +0 -1
  345. package/site/dist/assets/DepositAddressAddressStepView-4vdkb55L-ClAb_j1B.js +0 -187
  346. package/site/dist/assets/DepositAddressScreen-DBLRs7aI-CN1P_KY9.js +0 -8
  347. package/site/dist/assets/DepositAddressV3Screen-CDqIEMQw-BtDZmuEN.js +0 -1
  348. package/site/dist/assets/EmbeddedWalletConnectingScreen-D4T7DUzs-D3pExuaW.js +0 -1
  349. package/site/dist/assets/EmbeddedWalletCreatedScreen-D7WhW5ve-CLsJbPYQ.js +0 -1
  350. package/site/dist/assets/EmbeddedWalletKeyExportScreen-CqV4NYQ3-DI6bu-oi.js +0 -23
  351. package/site/dist/assets/EmbeddedWalletOnAccountCreateScreen-BoKb3Q2S-BQ9Ygr0P.js +0 -1
  352. package/site/dist/assets/EmbeddedWalletPasswordUpdateScreen-D3rMlqS7-CxrfLr5q.js +0 -1
  353. package/site/dist/assets/EmbeddedWalletPasswordUpdateSplashScreen-BPFkWJeE-DHZRGoTN.js +0 -1
  354. package/site/dist/assets/EnrollTotp-Dibew4dp-7gVtJ1Jt.js +0 -66
  355. package/site/dist/assets/EnvelopeIcon-Dh2vSVj4.js +0 -1
  356. package/site/dist/assets/ErrorBanner-BcpGRt0h-BKOYTyCi.js +0 -21
  357. package/site/dist/assets/ErrorScreen-DipdTWzE-BT8TtRTx.js +0 -4
  358. package/site/dist/assets/ErrorScreen-DipdTWzE-DAam41Xl.js +0 -1
  359. package/site/dist/assets/ExclamationCircleIcon-DUA2wMfO.js +0 -1
  360. package/site/dist/assets/ExclamationTriangleIcon-eZfaqcFq.js +0 -1
  361. package/site/dist/assets/FarcasterConnectStatusScreen-51tjUxqq-BPCBi37Q.js +0 -75
  362. package/site/dist/assets/FarcasterSignerStatusScreen-6x-Uh95G-XCmWpnUd.js +0 -28
  363. package/site/dist/assets/FiatOnrampScreen-BAhYeiTI-DJRcUh2N.js +0 -491
  364. package/site/dist/assets/FingerPrintIcon-Dm6kxmg7.js +0 -1
  365. package/site/dist/assets/FundSolWalletWithExternalSolanaWallet-WtLwYaOl-BfNVSTb1.js +0 -1
  366. package/site/dist/assets/FundWalletMethodHeader-BWNkokCT-BQdbJ5Bb.js +0 -1
  367. package/site/dist/assets/FundWithBankDepositScreen-DajkHxBD-BfvMcHb6.js +0 -58
  368. package/site/dist/assets/FundingEditAmountScreen-CpvpiO4M-VBfbahnA.js +0 -1
  369. package/site/dist/assets/FundingMethodSelectionScreen-Db7vhRlE-CMuBYf64.js +0 -1
  370. package/site/dist/assets/GlobeAltIcon-vqrVV5ho.js +0 -1
  371. package/site/dist/assets/GooglePay-B53WnudL-BX5_WtCx.js +0 -1
  372. package/site/dist/assets/HCaptchaWrapper-CUi9LJsp-D-I8j7NO.js +0 -4
  373. package/site/dist/assets/InAppBrowserLoginNotPossible-BMR9br1T-BY3j50El.js +0 -1
  374. package/site/dist/assets/InfoBanner-Cb3p1z12-DLBl_Ywy.js +0 -22
  375. package/site/dist/assets/InjectedWalletIcon-DLcYOGDj-DLSV_NjP.js +0 -1
  376. package/site/dist/assets/InstallWalletScreen-DTA8dwLv-CxreyXoD.js +0 -1
  377. package/site/dist/assets/LandingScreen-CGWUoSUG-Q7hgXKvM.js +0 -1
  378. package/site/dist/assets/Link-BdDilT2T-BEDEdHuS.js +0 -40
  379. package/site/dist/assets/LinkConflictScreen-C3ZEPsgl-DK1z_v7y.js +0 -77
  380. package/site/dist/assets/LinkEmailScreen-dKo9frwc-BYYpJ5-6.js +0 -1
  381. package/site/dist/assets/LinkPasskeyScreen-zbrl_AI_-uhub9C26.js +0 -1
  382. package/site/dist/assets/LinkPasskeyScreen-zbrl_AI_-uid22VTN.js +0 -117
  383. package/site/dist/assets/LinkPhoneScreen-oIUpfj0w-CVQibNi9.js +0 -1
  384. package/site/dist/assets/Loader-UAZqxsnw-Cy7hEE2f.js +0 -62
  385. package/site/dist/assets/LockClosedIcon-BgY_5v_Z.js +0 -1
  386. package/site/dist/assets/LoginFailedScreen-CN0dJV6U-DhUMiJZJ.js +0 -1
  387. package/site/dist/assets/ManualTransferScreen-CHqcuqbs-DMygAXMU.js +0 -1
  388. package/site/dist/assets/MfaAuthEnrollmentFlowScreen-Dj7gPTRC-_1GFUSIg.js +0 -1
  389. package/site/dist/assets/MfaAuthVerifyFlowScreen-DbFpyWMy-DLnBJ5b8.js +0 -1
  390. package/site/dist/assets/MfaEnrollmentFlowScreen-DhLnGgnr-BUJY1lzs.js +0 -1
  391. package/site/dist/assets/MfaVerifyFlowScreen-C_XPjMRP-25l5fVun.js +0 -1
  392. package/site/dist/assets/ModalFooter-BCuEK_nz-c-khvG4Y.js +0 -403
  393. package/site/dist/assets/MoonpayStatusScreen-CzTUtokc-BRFN2eXr.js +0 -16
  394. package/site/dist/assets/OAuthStatusScreen-ufbOa-da-DL30vu07.js +0 -1
  395. package/site/dist/assets/OpenLink-CUpJ1mOr-DfAvJRyK.js +0 -39
  396. package/site/dist/assets/PasskeySelectSignupOrLogin-xh2ScC_l-DtxhRQyw.js +0 -1
  397. package/site/dist/assets/PasskeyStatusScreen-Bla8MaOk-CNfu8ujT.js +0 -6
  398. package/site/dist/assets/PasswordRecoveryScreen-awGXZkQk-BR6z6xE8.js +0 -20
  399. package/site/dist/assets/PhArrowClockwise-DVgyFuez.js +0 -14
  400. package/site/dist/assets/PhArrowDown-87b1BizM.js +0 -14
  401. package/site/dist/assets/PhArrowLeft-Da0MfnbK.js +0 -14
  402. package/site/dist/assets/PhArrowRight-AdrIL4DW.js +0 -14
  403. package/site/dist/assets/PhArrowUp-4sgyKPGx.js +0 -14
  404. package/site/dist/assets/PhArrowUpRight-BNghD2zq.js +0 -14
  405. package/site/dist/assets/PhArrowsLeftRight-MuKBLUoF.js +0 -14
  406. package/site/dist/assets/PhBrowser-2-9m-AkM.js +0 -14
  407. package/site/dist/assets/PhCaretDown-BDNabFuL.js +0 -14
  408. package/site/dist/assets/PhCaretLeft-CI460R-A.js +0 -14
  409. package/site/dist/assets/PhCaretRight-D7ZS3Ls8.js +0 -14
  410. package/site/dist/assets/PhCaretUp-C-iIfyvO.js +0 -14
  411. package/site/dist/assets/PhCheck-DxQXn57r.js +0 -14
  412. package/site/dist/assets/PhClock-x3MS3Mwi.js +0 -14
  413. package/site/dist/assets/PhCopy-CWNYcABI.js +0 -14
  414. package/site/dist/assets/PhDeviceMobile-CsyA5Goi.js +0 -14
  415. package/site/dist/assets/PhDotsThree-D-k1BiYg.js +0 -14
  416. package/site/dist/assets/PhEnvelope-D8kzeNox.js +0 -14
  417. package/site/dist/assets/PhFunnelSimple-CfQs5DAW.js +0 -14
  418. package/site/dist/assets/PhMagnifyingGlass-C9u8jSCJ.js +0 -14
  419. package/site/dist/assets/PhPlus-C4UoW-2n.js +0 -14
  420. package/site/dist/assets/PhWarningCircle-BXHw1fCt.js +0 -14
  421. package/site/dist/assets/PhX-DX0SFIqC.js +0 -14
  422. package/site/dist/assets/PhoneIcon-CvIiPwYQ.js +0 -1
  423. package/site/dist/assets/PinInput-DbZ0b1i1-CDXZBdQx.js +0 -247
  424. package/site/dist/assets/PrivyPluginContext-DA-yS5vO-CtQWBiV2.js +0 -1
  425. package/site/dist/assets/QrCode-DbnZwlkH-BymHrKY7.js +0 -22
  426. package/site/dist/assets/RecoveryOAuthStatusScreen-CsgtTI2x-Dro1btv5.js +0 -1
  427. package/site/dist/assets/RecoveryPasswordCreateScreen-Be-qJ-LU-C1q1hiaN.js +0 -1
  428. package/site/dist/assets/RecoverySelectionScreen-D1iGtpmi-C21D20gD.js +0 -7
  429. package/site/dist/assets/SIWXUtil-CHZVugix.js +0 -1
  430. package/site/dist/assets/ScreenLayout-OwaQQcxH-CrQM6kvA.js +0 -1
  431. package/site/dist/assets/SetAutomaticRecoveryScreen-BO_OEqAZ-BcWHJoEG.js +0 -14
  432. package/site/dist/assets/SetWalletPasswordForm-DwCTVtAh-kq1zvA7d.js +0 -11
  433. package/site/dist/assets/ShieldCheckIcon-o6RHYev1.js +0 -1
  434. package/site/dist/assets/SignRequestScreen-BHKv32KR-iQCaBkcz.js +0 -26
  435. package/site/dist/assets/SolanaWalletConnector-C7Lqk-Wz-BUdJJ0ep.js +0 -1
  436. package/site/dist/assets/StandardSignAndSendTransactionScreen-CfhIXVtd-nART-xUU.js +0 -20
  437. package/site/dist/assets/TelegramAuthScreen-UL9zLfO8-Dw9geyK3.js +0 -1
  438. package/site/dist/assets/TodoList-DnyULl18-C8Eyy28X.js +0 -36
  439. package/site/dist/assets/TransactionDetails-e9nesl30-DeEL1JQS.js +0 -109
  440. package/site/dist/assets/TransactionErrorView-BDBNqA_f-Dffuo7I4.js +0 -178
  441. package/site/dist/assets/TransferFromWalletScreen-Qvn1Yuno-CWLWUiHy.js +0 -31
  442. package/site/dist/assets/TransferOrBridgeLoadingScreen-Dl1I_iIz-Bo-tm6wr.js +0 -6
  443. package/site/dist/assets/TurnstileWrapper-B7sNddys-Jwy1tJtm.js +0 -1
  444. package/site/dist/assets/UpdateEmailScreen-DVOhPV0H-gFbSIUhh.js +0 -1
  445. package/site/dist/assets/UpdatePhoneScreen-CXRswTNZ-Coy4E1NQ.js +0 -1
  446. package/site/dist/assets/UserLimitReachedScreen-5we2DHn8-D7m70C4b.js +0 -1
  447. package/site/dist/assets/WalletCards-DH1rqayz-Bgp9Fsgs.js +0 -1
  448. package/site/dist/assets/WalletIcon-gKf0gTw6.js +0 -1
  449. package/site/dist/assets/WalletInfoCard-sq_2wgFg-ISBsQt8p.js +0 -29
  450. package/site/dist/assets/WalletInterstitialScreen-Sh7LfsAh-DG-RuO-F.js +0 -1
  451. package/site/dist/assets/WalletLink-DK5LB5Ha-CXBqCHf3.js +0 -20
  452. package/site/dist/assets/WalletOverflowButton-bfCnp-9T-DP0-PoZL.js +0 -1
  453. package/site/dist/assets/WarningBanner-ZZqCEtZK-2eU4Qo74.js +0 -21
  454. package/site/dist/assets/__vite-browser-external-CitKSmYk.js +0 -1
  455. package/site/dist/assets/_esm-CJe2F7LL.js +0 -7
  456. package/site/dist/assets/_esm-zhBBffjV.js +0 -1
  457. package/site/dist/assets/accounts-Bq8t1wAD.js +0 -1
  458. package/site/dist/assets/accounts-D96UKWkC.js +0 -1
  459. package/site/dist/assets/analytics-mkkvFRju-BRBcadka.js +0 -1
  460. package/site/dist/assets/baseSepolia-DX-qGsik.js +0 -1
  461. package/site/dist/assets/basic-MlZ7f4s9.js +0 -1575
  462. package/site/dist/assets/capitalizeFirstLetter-DmLYqXsO-DtOXx-2n.js +0 -1
  463. package/site/dist/assets/ccip-BI9LWBBg.js +0 -1
  464. package/site/dist/assets/ccip-C-59SNEF.js +0 -7
  465. package/site/dist/assets/ccip-y08wK9du.js +0 -1
  466. package/site/dist/assets/chain-DM3oH6Px.js +0 -8
  467. package/site/dist/assets/check-BPgcwEPP.js +0 -1
  468. package/site/dist/assets/chevron-down-BSsbXkK-.js +0 -1
  469. package/site/dist/assets/circle-alert-DWaeLZNj.js +0 -1
  470. package/site/dist/assets/circle-check-big-Chb1ivw9.js +0 -1
  471. package/site/dist/assets/circle-x-AV9Cet0R.js +0 -1
  472. package/site/dist/assets/client-D0IV9lV9.js +0 -2
  473. package/site/dist/assets/client-Dsa7_3V3.js +0 -9
  474. package/site/dist/assets/coinbase-DCPC2L_R-Rs9nVCfm.js +0 -3
  475. package/site/dist/assets/copy-Ckr0AkL6.js +0 -1
  476. package/site/dist/assets/core-zQ1tZtVZ.js +0 -12
  477. package/site/dist/assets/createLucideIcon-IPW50ckY.js +0 -1
  478. package/site/dist/assets/defineChain-CiuCXUZW.js +0 -1
  479. package/site/dist/assets/dijkstra-Drfl93V4.js +0 -1
  480. package/site/dist/assets/dist-BxQqwnue.js +0 -16
  481. package/site/dist/assets/dist-Cm7pNAtL.js +0 -1
  482. package/site/dist/assets/dist-CoS6E-3x.js +0 -1
  483. package/site/dist/assets/dist-Dl07uGq1.js +0 -1
  484. package/site/dist/assets/embed.worker-ugGhEqCV.js +0 -1
  485. package/site/dist/assets/errors-BQ3N-RVt-BLqjTPNR.js +0 -1
  486. package/site/dist/assets/esm-C3DslVJx.js +0 -1
  487. package/site/dist/assets/esm-Ci1ogKuK.js +0 -1
  488. package/site/dist/assets/esm-DXsETz3H.js +0 -1
  489. package/site/dist/assets/esm-n2lWo7kz.js +0 -1
  490. package/site/dist/assets/esm-vs5jNx_Y.js +0 -37
  491. package/site/dist/assets/ethers-zTjbodk5-B7BBFFKf.js +0 -1
  492. package/site/dist/assets/eventemitter3-CL76jPsW.js +0 -1
  493. package/site/dist/assets/external-link-D-uehwM2.js +0 -1
  494. package/site/dist/assets/farcaster-DPlSjvF5-BqTvDXBR.js +0 -1
  495. package/site/dist/assets/features-CYXRa3_m.js +0 -2
  496. package/site/dist/assets/fingerprint-pattern-D8ytA16Q.js +0 -1
  497. package/site/dist/assets/floating-ui.react-dom-DKWOL9UG.js +0 -1
  498. package/site/dist/assets/floating-ui.react-xRkl9O3u.js +0 -1
  499. package/site/dist/assets/formatErc20TokenAmount-BuPk9xcy-BVqOKQif.js +0 -1
  500. package/site/dist/assets/formatter-CVbp4SlJ.js +0 -1
  501. package/site/dist/assets/get-entropy-details-for-user-dHRH5Gpi-Dukf7_kJ.js +0 -1
  502. package/site/dist/assets/getChainName-DjpPdUSc-DUyKDrnp.js +0 -1
  503. package/site/dist/assets/getErc20Balance-jXNpFf0N-V2btxzrJ.js +0 -1
  504. package/site/dist/assets/getErc20TokenInfo-BNTrzLMP-CtCwQuGA.js +0 -1
  505. package/site/dist/assets/getFormattedUsdFromLamports-De3U9GlO-Gx4_wxON.js +0 -1
  506. package/site/dist/assets/getUsdcMintAddress-BVgm9GRo-r2UnDeEy.js +0 -1
  507. package/site/dist/assets/guards-BIW-GiMJ-CHfXo8XI.js +0 -1
  508. package/site/dist/assets/hooks.module-BYZGfwDl.js +0 -1
  509. package/site/dist/assets/hourglass-CPG1HZmf.js +0 -1
  510. package/site/dist/assets/id-UqEwL2BI-CdKXapd-.js +0 -1
  511. package/site/dist/assets/index-BdEw5wyl-ChSJvPZk.js +0 -1
  512. package/site/dist/assets/index-CKdAF_dK.js +0 -8
  513. package/site/dist/assets/index-DvMddJcd-D-4mRLKK.js +0 -12
  514. package/site/dist/assets/index-YiCw0Y_x-BX1zsiqG.js +0 -437
  515. package/site/dist/assets/index.browser-B-i-Lj3J.js +0 -1
  516. package/site/dist/assets/index.browser-BMmUcykv.js +0 -1
  517. package/site/dist/assets/index.es-BmqyoBEM.js +0 -2
  518. package/site/dist/assets/index.es-C1v1or--.js +0 -3
  519. package/site/dist/assets/isPaymentRequestAvailable-Bq1cemEn-By6r0dVB.js +0 -1
  520. package/site/dist/assets/jsx-runtime-BbDfbRii.js +0 -1
  521. package/site/dist/assets/landmark-CH6LV6F0.js +0 -1
  522. package/site/dist/assets/lib-BsS8z8Lj.js +0 -1
  523. package/site/dist/assets/localBatchGatewayRequest-5YxrERBj.js +0 -32
  524. package/site/dist/assets/lock-DcskI4Bb.js +0 -1
  525. package/site/dist/assets/logger-CsXm3oIv-B0UYpNFI.js +0 -1
  526. package/site/dist/assets/mail-Bs0r5yOi.js +0 -1
  527. package/site/dist/assets/modal-context-CwmSeFcv-DruX9J1E.js +0 -1
  528. package/site/dist/assets/native-BKj27wfc.js +0 -1
  529. package/site/dist/assets/ofetch.CWycOUEr-CHp-crOQ.js +0 -1
  530. package/site/dist/assets/parseAbi-Csg-8t59.js +0 -2
  531. package/site/dist/assets/parseAbiParameters-BWbIMYe4.js +0 -1
  532. package/site/dist/assets/parseEther-CGP3gnf2.js +0 -1
  533. package/site/dist/assets/pkce-DXF0yKjP-Bqz4wAsq.js +0 -1
  534. package/site/dist/assets/preload-helper-BaNbYf_w.js +0 -1
  535. package/site/dist/assets/privy-context-81KmsBw2-CjWGzyg7.js +0 -2
  536. package/site/dist/assets/property-DuZ9DLP4.js +0 -3
  537. package/site/dist/assets/react-DCXkXSrv.js +0 -1
  538. package/site/dist/assets/react-DQnMl2Xv.js +0 -1
  539. package/site/dist/assets/react-DrJ0MmMO.js +0 -1
  540. package/site/dist/assets/react-auth-sHnipzbS.js +0 -1
  541. package/site/dist/assets/react-dom-5dW7aKoP.js +0 -1
  542. package/site/dist/assets/reservoir-x-nGuZkT-BMX127i6.js +0 -1
  543. package/site/dist/assets/roles-32M1l9jI.js +0 -1
  544. package/site/dist/assets/roles-DKPW79Ca.js +0 -1
  545. package/site/dist/assets/rolldown-runtime-BcKkbAw3.js +0 -1
  546. package/site/dist/assets/safe-url-D7SRPu33-CkMedGro.js +0 -1
  547. package/site/dist/assets/secp256k1-C4nzcPo-.js +0 -1
  548. package/site/dist/assets/secp256k1-D92aGNnU.js +0 -1
  549. package/site/dist/assets/secp256k1-DmbwyFau.js +0 -1
  550. package/site/dist/assets/secp256k1-_MleGpqL.js +0 -1
  551. package/site/dist/assets/secp256k1-xl2og-wO.js +0 -1
  552. package/site/dist/assets/serializeAuthorizationList-CX8hGL56.js +0 -1
  553. package/site/dist/assets/serializeSignature-DfxkPnu-.js +0 -2
  554. package/site/dist/assets/sha2-BU_QyRTx.js +0 -1
  555. package/site/dist/assets/shouldProceedtoEmbeddedWalletCreationFlow-B3vyavrh-ByFOTrQK.js +0 -1
  556. package/site/dist/assets/simulateTransaction-CfuOrae4-CMFGDgT_.js +0 -1
  557. package/site/dist/assets/smartphone-CcEZ-XAy.js +0 -1
  558. package/site/dist/assets/src-BBjkfi-Q.js +0 -1
  559. package/site/dist/assets/storage-Ufl800Ne-EalZTH9q.js +0 -9
  560. package/site/dist/assets/stringify-BlDm7tuc.js +0 -21
  561. package/site/dist/assets/stripe.esm-CZRDpc-N.js +0 -2
  562. package/site/dist/assets/styles-BsotlekN-CXEB4Ud9.js +0 -9
  563. package/site/dist/assets/telegram-B-JqnkqZ-RBoY3PLx.js +0 -1
  564. package/site/dist/assets/to-ui-error-DWe-qwS3-DgCO-Y70.js +0 -4
  565. package/site/dist/assets/toViemAccount-B5iDGq1b-DZ1MBqUW.js +0 -2
  566. package/site/dist/assets/transaction-BNTP-bFm-M5tJx8vY.js +0 -1
  567. package/site/dist/assets/transfer-6YztDh-t-BVQkTvG-.js +0 -1
  568. package/site/dist/assets/transformers.web-D4RvOP4-.js +0 -40
  569. package/site/dist/assets/transformers.web-D8W1u_I2.js +0 -49
  570. package/site/dist/assets/triangle-alert-CWjYH75H.js +0 -1
  571. package/site/dist/assets/twitch-5IOe4sIQ-lDtgk0os.js +0 -1
  572. package/site/dist/assets/types-4CuOD23i.js +0 -1
  573. package/site/dist/assets/use-headless-crypto-deposit-Yn-QRLB3-Dn6_8w-Y.js +0 -1
  574. package/site/dist/assets/use-unlink-wallet-BKK4_5Ur-DgsQ75lh.js +0 -1
  575. package/site/dist/assets/useActiveWallet-B-yZYGc6-B6JWREbk.js +0 -123
  576. package/site/dist/assets/useGetSolPrice-x7gfUIHJ-D1hmQfpA.js +0 -1
  577. package/site/dist/assets/useGetTokenPrice-CaoUkb79-ZnbuJ-vP.js +0 -1
  578. package/site/dist/assets/useI18n-C-5n_noF-BcqC76yj.js +0 -1
  579. package/site/dist/assets/useWalletBalance-CZnP5f_f-L3V0jDjL.js +0 -1
  580. package/site/dist/assets/useWallets-X1ndvJ_U-CLwUcevw.js +0 -1
  581. package/site/dist/assets/utils-BkR7EQjg.js +0 -1
  582. package/site/dist/assets/utils-DJhBNOZA.js +0 -1
  583. package/site/dist/assets/utils-DdckVfQr.js +0 -1
  584. package/site/dist/assets/w3m-modal-BMubXAoG.js +0 -1174
  585. package/site/dist/assets/wallet-Bn85Sg2W.js +0 -1
  586. package/site/dist/assets/wallet-connect-BvJtUsDt-Y03hhqFN.js +0 -1
  587. package/site/dist/assets/wallet-uSKqQsgP.js +0 -2
  588. package/site/dist/assets/walletconnect-registry-xxG8XLCb-D1SSFvMp.js +0 -1
  589. package/site/dist/assets/walletconnect-v2-3frQFwbg-Dv6JY_ko.js +0 -12
  590. package/site/dist/assets/x-rlSp9U7W.js +0 -1
@@ -69,9 +69,10 @@ const WHERE = { type: "object", description: 'Equality filters, e.g. {"phase":"P
69
69
  * The tools for one app, or null when its card names no views.
70
70
  * `app` is `{ name, desc, views }` from a verified card. `fetchCatalog(url)` may
71
71
  * answer from a stale copy: the survey only describes and routes, and loading a
72
- * view re-reads its catalog through shard.js either way.
72
+ * view re-reads its catalog through shard.js either way. `queryVector(q)` embeds a
73
+ * query (null to rank by words); a Worker passes its own encoder.
73
74
  */
74
- export function viewTools(app, { fetchCatalog = fetch } = {}) {
75
+ export function viewTools(app, { fetchCatalog = fetch, queryVector: embedQ = queryVector } = {}) {
75
76
  if (!app.views?.length) return null;
76
77
  const names = new Map(); // view url → its name in every result
77
78
  const label = (url) => names.get(url) ?? url.split("/").pop();
@@ -115,7 +116,7 @@ export function viewTools(app, { fetchCatalog = fetch } = {}) {
115
116
  }),
116
117
  search: async ({ query, limit = 10, views, where: w }) => {
117
118
  if (!query) throw new Error("query is required");
118
- const qv = await queryVector(query);
119
+ const qv = await embedQ(query);
119
120
  const ranked = views?.length ? await pick(views) : (await route(query, qv)).slice(0, ROUTE_TOP);
120
121
  const others = views?.length ? [] : (await route(query, qv)).slice(ROUTE_TOP, ROUTE_TOP + 5).map((v) => v.name);
121
122
  const per = await Promise.all(ranked.map(async (v) =>
@@ -125,7 +126,9 @@ export function viewTools(app, { fetchCatalog = fetch } = {}) {
125
126
  next_views: others, hits };
126
127
  },
127
128
  get: async ({ id, view }) => {
128
- if (view) for (const v of await pick([view])) await load(v);
129
+ // Nothing loaded (a fresh Worker isolate: each request may land on a new one): load every view.
130
+ // ponytail: downloads every view for an app with many; route by id when that shows.
131
+ for (const v of view ? await pick([view]) : loaded.size ? [] : await survey()) await load(v);
129
132
  for (const [v, rows] of loaded) { const r = getRow(rows, id, rolesOf(v)); if (r) return r; }
130
133
  return { error: `${id} is not in a loaded view. Search for it, or pass its view.`, loaded: [...loaded.keys()].map(label) };
131
134
  },
@@ -180,21 +183,59 @@ export function viewTools(app, { fetchCatalog = fetch } = {}) {
180
183
  const p = app.paid, dec = p.decimals ?? 6;
181
184
  const price = `${(Number(p.price) / 10 ** dec).toFixed(dec).replace(/0+$/, "").replace(/\.$/, "")} ${p.symbol ?? "USDC"}`;
182
185
  const cap = BigInt(Math.round(Number(process.env.FANGORN_MCP_MAX_PRICE ?? "0.10") * 10 ** dec));
183
- run.buy = async ({ id }) => {
184
- if (!id) throw new Error("id is required");
186
+ const resolve = (id) => {
185
187
  const hit = loadedRows().find(({ r, view }) => r.id === id || r[rolesOf(view).identity] === id);
186
- const key = hit ? hit.r[rolesOf(hit.view).identity] ?? id : id;
188
+ return { key: hit ? hit.r[rolesOf(hit.view).identity] ?? id : id, want: hit?.r.paid_sha256, ct: hit?.r.paid_ct };
189
+ };
190
+ run.buy = async ({ id, ids }) => {
191
+ const { buyBatch, withLock, readAsMember } = await import("./x402.js");
192
+ const rs = (ids?.length ? ids : id ? [id] : []).map(resolve);
193
+ const ct = Object.fromEntries(rs.filter((r) => r.ct).map((r) => [r.key, r.ct]));
194
+ const want = Object.fromEntries(rs.filter((r) => r.want).map((r) => [r.key, r.want]));
195
+ const verdict = (records) => { const bad = records.filter((x) => x.verified === false).map((x) => x.id);
196
+ return bad.length ? `MISMATCH for ${bad.join(", ")}` : "every record opened matches its published sha256"; };
197
+ // A membership the agent was named on (FANGORN_MCP_READER_KEY + FANGORN_MCP_MEMBERSHIP,
198
+ // the token id): read for free, nothing paid.
199
+ if (process.env.FANGORN_MCP_READER_KEY && process.env.FANGORN_MCP_MEMBERSHIP && p.membership) {
200
+ const { privateKeyToAccount } = await import("viem/accounts");
201
+ const r = await readAsMember(p, rs.map((r) => r.key).filter((k) => ct[k]), { reader: privateKeyToAccount(process.env.FANGORN_MCP_READER_KEY),
202
+ tokenId: process.env.FANGORN_MCP_MEMBERSHIP, ct, want });
203
+ return { read: r.records.length, with: "membership", until: r.until, verified: verdict(r.records), records: r.records.map(({ id, record, error }) => ({ id, record, error })) };
204
+ }
205
+ if (ids?.length) {
206
+ // Many at once, one price: from the allowance file (FANGORN_MCP_VOUCHERS, vouchers the
207
+ // person's wallet signed) if there is one, else one payment from the wallet key.
208
+ const fs = await import("node:fs");
209
+ const vf = process.env.FANGORN_MCP_VOUCHERS;
210
+ const opts = { ct, want, privateKey: process.env.FANGORN_MCP_WALLET_KEY, maxPrice: cap * BigInt(rs.length) };
211
+ // The file is read, spent from and saved under one lock, and saved even when the
212
+ // purchase fails: buyBatch drops the vouchers the seller settled or refused either way.
213
+ const r = vf
214
+ ? await withLock(vf, async () => {
215
+ const vouchers = JSON.parse(fs.readFileSync(vf, "utf8"));
216
+ try { return await buyBatch(p, rs.map((r) => r.key), { ...opts, vouchers }); }
217
+ finally { fs.writeFileSync(vf, JSON.stringify(vouchers)); }
218
+ })
219
+ : await buyBatch(p, rs.map((r) => r.key), opts);
220
+ return { bought: r.records.length, missing: r.missing, verified: verdict(r.records),
221
+ ...(r.undelivered.length ? { not_bought: r.undelivered, why: r.error } : {}),
222
+ manifest: r.manifest, records: r.records.map(({ id, record, error }) => ({ id, record, error })) };
223
+ }
224
+ if (!id) throw new Error("id or ids is required");
225
+ const { key, want: w, ct: c } = resolve(id);
226
+ if (!c) return { id: key, error: "search for the record first: its sealed copy (paid_ct) comes from the row, and nothing is bought without it" };
187
227
  const { buyRecord } = await import("./x402.js");
188
- const want = hit?.r.paid_sha256;
189
- const r = await buyRecord(p, key, { want, privateKey: process.env.FANGORN_MCP_WALLET_KEY, maxPrice: cap });
228
+ const r = await buyRecord(p, key, { ct: c, want: w, privateKey: process.env.FANGORN_MCP_WALLET_KEY, maxPrice: cap });
190
229
  if (r.error) return r;
191
230
  return { id: key, paid: r.price ? price : "free", transaction: r.receipt?.transaction ?? null, network: r.receipt?.network ?? p.network,
192
- verified: want ? (r.verified ? "matches the published sha256" : `MISMATCH: published ${want}, got ${r.digest}`) : "not checked (search for the record first)",
231
+ verified: w ? (r.verified ? "matches the published sha256" : `MISMATCH: published ${w}, got ${r.digest}`) : "not checked (the row has no paid_sha256)",
193
232
  record: r.record };
194
233
  };
195
234
  tools.push({ name: "buy", description: `Buy one ${n} record's paid detail for ${price} (x402 on ${p.network}): ${p.description || "the structured record"}. ` +
196
- "Pass an id from search. Paid from this server's wallet (FANGORN_MCP_WALLET_KEY), never above FANGORN_MCP_MAX_PRICE.",
197
- inputSchema: { type: "object", properties: { id: str("A record id from search or get") }, required: ["id"] } });
235
+ "Pass an id from search, or ids for up to 1000 at once (one price, one manifest of hashes and transactions). " +
236
+ "The record is already in the row, sealed; this buys its key and opens it. " +
237
+ "Read free with a membership the agent was named on (FANGORN_MCP_READER_KEY + FANGORN_MCP_MEMBERSHIP); otherwise paid from the allowance (FANGORN_MCP_VOUCHERS) or this server's wallet (FANGORN_MCP_WALLET_KEY), never above FANGORN_MCP_MAX_PRICE a record.",
238
+ inputSchema: { type: "object", properties: { id: str("A record id from search or get"), ids: { type: "array", items: { type: "string" }, description: "Several record ids, bought together" } } } });
198
239
  }
199
240
 
200
241
  return { tools, call: async (name, args = {}) => {
package/src/agent/x402.js CHANGED
@@ -1,76 +1,300 @@
1
- // Paying for a resource over x402 (v1, "exact" scheme): the buyer's half.
1
+ // Paying for a resource over x402 (v2, "exact" scheme on an EVM chain): the buyer's half.
2
2
  //
3
3
  // const { body, receipt, price } = await payAndFetch(url, { privateKey, maxPrice: 50000n });
4
4
  //
5
- // 1. GET url → 402 with `accepts`: what it costs, in which token, on which chain, to whom.
5
+ // 1. GET url → 402 with its PaymentRequired in the PAYMENT-REQUIRED header (base64 JSON):
6
+ // `accepts` says what it costs, in which token, on which chain ("eip155:84532"), to whom.
6
7
  // 2. Sign an EIP-3009 transferWithAuthorization for exactly that (EIP-712, the token's own
7
- // domain). Nothing is sent on chain by the buyer: the seller's facilitator submits it.
8
- // 3. GET url again with X-PAYMENT: the seller verifies, settles, and returns the resource,
9
- // with the settlement (the tx hash) in X-PAYMENT-RESPONSE.
8
+ // domain, named in `extra`). Nothing is sent on chain by the buyer: the seller's facilitator
9
+ // submits it.
10
+ // 3. GET url again with PAYMENT-SIGNATURE: the seller verifies, settles, and returns the
11
+ // resource, with the settlement (the tx hash) in PAYMENT-RESPONSE.
10
12
  //
11
13
  // `maxPrice` (token base units) is checked BEFORE signing: a seller cannot ask for more
12
14
  // than the caller agreed to, whatever its 402 says.
13
15
 
14
- const CHAIN_IDS = { "arbitrum-sepolia": 421614, arbitrum: 42161, "base-sepolia": 84532, base: 8453 };
15
16
  const b64 = (s) => (typeof btoa === "function" ? btoa(s) : Buffer.from(s, "utf8").toString("base64"));
16
17
  const unb64 = (s) => (typeof atob === "function" ? atob(s) : Buffer.from(s, "base64").toString("utf8"));
18
+ const EVM = /^eip155:(\d+)$/;
17
19
 
18
- /** The one requirement we can pay: exact scheme, a chain we know, within `maxPrice`. */
19
- export function choose(accepts = [], { maxPrice, networks = Object.keys(CHAIN_IDS) } = {}) {
20
- const ok = accepts.filter((a) => a.scheme === "exact" && networks.includes(a.network));
20
+ /** The one requirement we can pay: exact scheme, an EVM chain, within `maxPrice`. */
21
+ export function choose(accepts = [], { maxPrice } = {}) {
22
+ const ok = accepts.filter((a) => a.scheme === "exact" && EVM.test(a.network));
21
23
  if (!ok.length) throw new Error(`no payable option: ${JSON.stringify(accepts.map((a) => `${a.scheme}/${a.network}`))}`);
22
- const cheapest = ok.sort((a, b) => (BigInt(a.maxAmountRequired) < BigInt(b.maxAmountRequired) ? -1 : 1))[0];
23
- if (maxPrice != null && BigInt(cheapest.maxAmountRequired) > BigInt(maxPrice))
24
- throw new Error(`price ${cheapest.maxAmountRequired} exceeds the cap ${maxPrice} (token base units)`);
24
+ const cheapest = ok.sort((a, b) => (BigInt(a.amount) < BigInt(b.amount) ? -1 : 1))[0];
25
+ if (maxPrice != null && BigInt(cheapest.amount) > BigInt(maxPrice))
26
+ throw new Error(`price ${cheapest.amount} exceeds the cap ${maxPrice} (token base units)`);
25
27
  return cheapest;
26
28
  }
27
29
 
28
- /** The X-PAYMENT header value for requirement `req`, signed by `account` (a viem account). */
29
- export async function paymentHeader(req, account, { now = Math.floor(Date.now() / 1000) } = {}) {
30
- const chainId = CHAIN_IDS[req.network];
31
- if (!chainId) throw new Error(`unknown network ${req.network}`);
30
+ /** A 402's PaymentRequired, from its PAYMENT-REQUIRED header. */
31
+ export function paymentRequired(res) {
32
+ const h = res.headers.get("PAYMENT-REQUIRED");
33
+ if (!h) throw new Error(`HTTP ${res.status} has no PAYMENT-REQUIRED header (not x402 v2)`);
34
+ return JSON.parse(unb64(h));
35
+ }
36
+
37
+ /** The PAYMENT-SIGNATURE header value for requirement `req`, signed by `account` (a viem account). */
38
+ export async function paymentHeader(req, account, opts) {
39
+ return b64(JSON.stringify(await signPayment(req, account, opts)));
40
+ }
41
+
42
+ /** A PaymentPayload for `req` (one of a 402's `accepts`), for the 402's `resource`. */
43
+ export async function signPayment(req, account, { resource, now = Math.floor(Date.now() / 1000) } = {}) {
44
+ const chainId = Number((EVM.exec(req.network) ?? [])[1]);
45
+ if (!chainId) throw new Error(`not an EVM network: ${req.network}`);
32
46
  const nonce = `0x${[...crypto.getRandomValues(new Uint8Array(32))].map((b) => b.toString(16).padStart(2, "0")).join("")}`;
33
47
  const authorization = {
34
- from: account.address, to: req.payTo, value: String(req.maxAmountRequired),
48
+ from: account.address, to: req.payTo, value: String(req.amount),
35
49
  validAfter: String(now - 600), validBefore: String(now + (req.maxTimeoutSeconds ?? 120)), nonce,
36
50
  };
51
+ // The token's EIP-712 name differs by chain (Base Sepolia's USDC is "USDC", Base's "USD
52
+ // Coin"), so a seller that names none is refused rather than guessed at.
53
+ if (!req.extra?.name || !req.extra?.version) throw new Error(`${req.network}: the seller names no EIP-712 domain for ${req.asset} (extra.name, extra.version)`);
37
54
  const signature = await account.signTypedData({
38
- domain: { name: req.extra?.name ?? "USD Coin", version: req.extra?.version ?? "2", chainId, verifyingContract: req.asset },
55
+ domain: { name: req.extra.name, version: req.extra.version, chainId, verifyingContract: req.asset },
39
56
  types: { TransferWithAuthorization: [
40
57
  { name: "from", type: "address" }, { name: "to", type: "address" }, { name: "value", type: "uint256" },
41
58
  { name: "validAfter", type: "uint256" }, { name: "validBefore", type: "uint256" }, { name: "nonce", type: "bytes32" }] },
42
59
  primaryType: "TransferWithAuthorization",
43
60
  message: { ...authorization, value: BigInt(authorization.value), validAfter: BigInt(authorization.validAfter), validBefore: BigInt(authorization.validBefore) },
44
61
  });
45
- return b64(JSON.stringify({ x402Version: 1, scheme: "exact", network: req.network, payload: { signature, authorization } }));
62
+ return { x402Version: 2, ...(resource ? { resource } : {}), accepted: req, payload: { signature, authorization } };
46
63
  }
47
64
 
48
- /** GET `url`, paying once if it answers 402. Returns { status, body, price, receipt }. */
49
- export async function payAndFetch(url, { privateKey, account, maxPrice, fetchImpl = fetch } = {}) {
50
- const first = await fetchImpl(url);
65
+ /** GET `url` (or `method` it), paying once if it answers 402. Returns { status, body, price, receipt }. */
66
+ export async function payAndFetch(url, { privateKey, account, maxPrice, fetchImpl = fetch, method = "GET" } = {}) {
67
+ const first = await fetchImpl(url, { method });
51
68
  if (first.status !== 402) return { status: first.status, body: await first.text(), price: null, receipt: null };
52
- const offer = await first.json();
69
+ const offer = paymentRequired(first);
53
70
  const req = choose(offer.accepts, { maxPrice });
54
71
  if (!account) {
55
- if (!privateKey) throw new Error(`${url} costs ${req.maxAmountRequired} (base units of ${req.asset} on ${req.network}); no wallet configured to pay`);
72
+ if (!privateKey) throw new Error(`${url} costs ${req.amount} (base units of ${req.asset} on ${req.network}); no wallet configured to pay`);
56
73
  account = (await import("viem/accounts")).privateKeyToAccount(privateKey);
57
74
  }
58
- const paid = await fetchImpl(url, { headers: { "X-PAYMENT": await paymentHeader(req, account) } });
59
- const receiptHeader = paid.headers.get("X-PAYMENT-RESPONSE");
75
+ const paid = await fetchImpl(url, { method, headers: { "PAYMENT-SIGNATURE": await paymentHeader(req, account, { resource: offer.resource }) } });
76
+ const receiptHeader = paid.headers.get("PAYMENT-RESPONSE");
60
77
  const body = await paid.text();
61
- if (paid.status === 402) throw new Error(`payment refused: ${JSON.parse(body).error ?? body}`);
62
- return { status: paid.status, body, price: req.maxAmountRequired, receipt: receiptHeader ? JSON.parse(unb64(receiptHeader)) : null };
78
+ if (paid.status === 402) throw new Error(`payment refused: ${paymentRequired(paid).error ?? body}`);
79
+ return { status: paid.status, body, price: req.amount, receipt: receiptHeader ? JSON.parse(unb64(receiptHeader)) : null };
80
+ }
81
+
82
+ // ── Sealed records ────────────────────────────────────────────────────────────────────────
83
+ // An app's paid record is in its committed rows already, sealed: `paid_ct` is
84
+ // base64(nonce[12] ‖ AES-256-GCM(key, record)), with key = HMAC-SHA256(PAID_SECRET, id), and
85
+ // `paid_sha256` is the sha256 of the record itself. A purchase buys the key, never the data,
86
+ // so the buyer has the ciphertext (and so knows the record exists) before paying, and checks
87
+ // what it decrypts against the committed hash after. Sources seal with the same derivation.
88
+
89
+ const hex = (u8) => [...u8].map((b) => b.toString(16).padStart(2, "0")).join("");
90
+ const unhex = (h) => Uint8Array.from(h.match(/../g).map((x) => parseInt(x, 16)));
91
+ const fromB64 = (s) => Uint8Array.from(unb64bytes(s));
92
+ function unb64bytes(s) { return typeof atob === "function" ? [...atob(s)].map((c) => c.charCodeAt(0)) : [...Buffer.from(s, "base64")]; }
93
+ const toB64 = (u8) => (typeof btoa === "function" ? btoa(String.fromCharCode(...u8)) : Buffer.from(u8).toString("base64"));
94
+ const sha256 = async (bytes) => hex(new Uint8Array(await crypto.subtle.digest("SHA-256", bytes)));
95
+
96
+ /** A record's key, hex: HMAC-SHA256(secret, id). The worker's keyFor; here for sources and tests. */
97
+ export async function paidKey(secret, id) {
98
+ const k = await crypto.subtle.importKey("raw", new TextEncoder().encode(secret), { name: "HMAC", hash: "SHA-256" }, false, ["sign"]);
99
+ return hex(new Uint8Array(await crypto.subtle.sign("HMAC", k, new TextEncoder().encode(id))));
100
+ }
101
+
102
+ /** Seal `text` under `keyHex`: what a source writes as `paid_ct`. */
103
+ export async function sealPaid(keyHex, text, nonce = crypto.getRandomValues(new Uint8Array(12))) {
104
+ const k = await crypto.subtle.importKey("raw", unhex(keyHex), "AES-GCM", false, ["encrypt"]);
105
+ const ct = new Uint8Array(await crypto.subtle.encrypt({ name: "AES-GCM", iv: nonce }, k, new TextEncoder().encode(text)));
106
+ const out = new Uint8Array(12 + ct.length);
107
+ out.set(nonce); out.set(ct, 12);
108
+ return toB64(out);
109
+ }
110
+
111
+ /** Open a sealed record and check it against the committed sha256 (`want`, if known). */
112
+ export async function openPaid(ct, keyHex, want) {
113
+ const bytes = fromB64(ct);
114
+ const k = await crypto.subtle.importKey("raw", unhex(keyHex), "AES-GCM", false, ["decrypt"]);
115
+ const plain = new Uint8Array(await crypto.subtle.decrypt({ name: "AES-GCM", iv: bytes.slice(0, 12) }, k, bytes.slice(12)));
116
+ const sha = await sha256(plain);
117
+ return { sha256: sha, verified: want ? want === sha : null, record: JSON.parse(new TextDecoder().decode(plain)) };
63
118
  }
64
119
 
65
- /** Buy one record an app sells (its agent card's `paid`) and check it against the sha256 the
66
- * app published for it (`want`, the row's `paid_sha256`): what was paid for is what was
67
- * committed. Shared by fangorn-mcp's `buy` and the stock page. */
68
- export async function buyRecord(paid, key, { want, account, privateKey, maxPrice = paid.price, fetchImpl } = {}) {
120
+ /** A private app's pass (its card's `access`): one payment at POST `pass_url`, a bearer token back. */
121
+ export async function buyPass(access, { account, privateKey, maxPrice = access.pass, fetchImpl } = {}) {
122
+ const r = await payAndFetch(access.pass_url, { method: "POST", account, privateKey, maxPrice, fetchImpl });
123
+ if (r.status !== 200) throw new Error(`no pass: HTTP ${r.status} ${r.body.slice(0, 200)}`);
124
+ return { ...JSON.parse(r.body), price: r.price, receipt: r.receipt };
125
+ }
126
+
127
+ // ── Private apps ──────────────────────────────────────────────────────────────────────────
128
+ // A private app's rows are sealed whole before they reach IPFS: the payload on chain is
129
+ // `{sealed}`, base64(nonce[12] ‖ AES-256-GCM(rowKey, JSON(payload))), with rowKey =
130
+ // HMAC-SHA256(PAID_SECRET, "fangorn.row.v1"). The app's Worker holds the secret, opens the rows
131
+ // in its cron and serves the view only to those who pay. The nonce is the first 12 bytes of
132
+ // HMAC(rowKey, plaintext): an unchanged row seals to the same bytes, so the same CID, and is not
133
+ // embedded again; two different rows never share a nonce. (Equal rows look equal: that is all.)
134
+
135
+ const ROW = "fangorn.row.v1";
136
+ async function rowNonce(keyHex, text) {
137
+ const k = await crypto.subtle.importKey("raw", unhex(keyHex), { name: "HMAC", hash: "SHA-256" }, false, ["sign"]);
138
+ return new Uint8Array(await crypto.subtle.sign("HMAC", k, new TextEncoder().encode(text))).slice(0, 12);
139
+ }
140
+
141
+ /** The payload a private app commits for `payload`. */
142
+ export async function sealRow(secret, payload) {
143
+ const key = await paidKey(secret, ROW), text = JSON.stringify(payload);
144
+ return { sealed: await sealPaid(key, text, await rowNonce(key, text)) };
145
+ }
146
+
147
+ /** A row as committed, opened; a payload that is not sealed comes back as it is. */
148
+ export async function openRow(secret, payload) {
149
+ if (typeof payload?.sealed !== "string") return payload;
150
+ return (await openPaid(payload.sealed, await paidKey(secret, ROW))).record;
151
+ }
152
+
153
+ /** Open every record a seller sent a key for. `ct[id]` is the row's paid_ct, `want[id]` its paid_sha256. */
154
+ async function openAll(keys, ct, want) {
155
+ const out = [];
156
+ for (const [id, key] of Object.entries(keys ?? {})) {
157
+ if (!ct[id]) { out.push({ id, key, error: "no sealed record for this id in the rows read" }); continue; }
158
+ try { out.push({ id, ...(await openPaid(ct[id], key, want[id])) }); }
159
+ catch (e) { out.push({ id, key, error: `could not open: ${e.message}` }); }
160
+ }
161
+ return out;
162
+ }
163
+
164
+ /** Buy one record an app sells (its agent card's `paid`): pay for its key, open `ct` (the
165
+ * row's paid_ct) and check it against `want` (its paid_sha256). Shared by fangorn-mcp and the page. */
166
+ export async function buyRecord(paid, key, { ct, want, account, privateKey, maxPrice = paid.price, fetchImpl } = {}) {
167
+ if (!ct) return { id: key, error: "this row carries no sealed record (paid_ct): nothing to buy" };
69
168
  const r = await payAndFetch(paid.url.replace("{id}", encodeURIComponent(key)), { account, privateKey, maxPrice, fetchImpl });
70
169
  if (r.status !== 200) return { id: key, error: `HTTP ${r.status}: ${r.body.slice(0, 200)}` };
71
- const digest = [...new Uint8Array(await crypto.subtle.digest("SHA-256", new TextEncoder().encode(r.body)))]
72
- .map((b) => b.toString(16).padStart(2, "0")).join("");
73
- return { id: key, price: r.price, receipt: r.receipt, digest, verified: want ? want === digest : null, record: JSON.parse(r.body) };
170
+ const opened = await openPaid(ct, JSON.parse(r.body).key, want);
171
+ return { id: key, price: r.price, receipt: r.receipt, digest: opened.sha256, verified: opened.verified, record: opened.record };
172
+ }
173
+
174
+ /** The typed data a reader signs to read with a membership: a copy of @fangorn-network/barliman's
175
+ * src/read.js, which its /check verifies. ponytail: import it once barliman is on npm. */
176
+ export const readTypedData = ({ registry, chainId, appId, tokenId, ids, issuedAt }) => ({
177
+ domain: { name: "Fangorn Read", version: "1", chainId: Number(chainId), verifyingContract: registry },
178
+ types: { Read: [{ name: "app", type: "bytes32" }, { name: "tokenId", type: "uint256" }, { name: "ids", type: "string[]" }, { name: "issuedAt", type: "uint256" }] },
179
+ primaryType: "Read",
180
+ message: { app: appId, tokenId: BigInt(tokenId), ids, issuedAt: BigInt(issuedAt) },
181
+ });
182
+
183
+ /** Read records with a membership: `reader` (the holder, or the agent it named) signs the
184
+ * request, the app's worker has Barliman check it, and the keys come back. Nothing is paid. */
185
+ export async function readAsMember(paid, ids, { reader, tokenId, ct = {}, want = {}, fetchImpl = fetch } = {}) {
186
+ const m = paid.membership;
187
+ if (!m) throw new Error("this app sells no memberships");
188
+ const issuedAt = Math.floor(Date.now() / 1000);
189
+ const signature = await reader.signTypedData(readTypedData({ registry: m.registry, chainId: m.chainId, appId: m.appId, tokenId, ids, issuedAt }));
190
+ const url = paid.key_url ?? paid.url.replace(/\/paid\/\{id\}$/, "/key");
191
+ const res = await fetchImpl(url, { method: "POST", headers: { "content-type": "application/json" },
192
+ body: JSON.stringify({ ids, tokenId: String(tokenId), issuedAt, signature }) });
193
+ const body = await res.json();
194
+ if (res.status !== 200) throw new Error(`membership refused: ${body.error ?? res.status}`);
195
+ return { records: await openAll(body.keys, ct, want), until: body.until };
196
+ }
197
+
198
+ // ── Batches and vouchers ──────────────────────────────────────────────────────────────────
199
+ // `POST <app>/paid {ids}` answers 402 with one price for every record it has; PAYMENT-SIGNATURE may then
200
+ // carry several payments (a JSON array) that add up to exactly that price. A payment signs
201
+ // payee, amount and expiry but not the resource (checked against the PayAI facilitator,
202
+ // 2026-10-07), so a person's wallet can sign a stack of them ahead of time ("vouchers") and an
203
+ // agent spends them later with no key: each pays only the app, for a fixed amount, until it
204
+ // expires. Holding them is holding the right to that much of the person's money, nothing more.
205
+
206
+ /** Sign vouchers worth `total` (base units) in `denominations` (ascending), payable to `req.payTo`
207
+ * for `days`. Enough of each small one to make any multiple of the smallest up to `total`. */
208
+ export async function signVouchers(req, account, { total, denominations, days = 30 } = {}) {
209
+ const out = [], ds = denominations.map(BigInt);
210
+ let left = BigInt(total);
211
+ for (let i = 0; i < ds.length; i++) {
212
+ let n = left / ds[i];
213
+ if (i < ds.length - 1) { // keep a full set of this size, the rest in multiples of the next
214
+ const keep = ds[i + 1] / ds[i] - 1n; // ponytail: assumes each denomination divides the next
215
+ n = (left - (left - (keep < n ? keep : n) * ds[i]) / ds[i + 1] * ds[i + 1]) / ds[i];
216
+ }
217
+ for (let k = 0n; k < n; k++)
218
+ out.push(await signPayment({ ...req, amount: String(ds[i]), maxTimeoutSeconds: days * 86400 }, account));
219
+ left -= n * ds[i];
220
+ }
221
+ return out;
222
+ }
223
+
224
+ /** Vouchers adding up to exactly `amount`, largest first; null if they cannot. */
225
+ export function pick(vouchers, amount) {
226
+ let left = BigInt(amount);
227
+ const out = [];
228
+ for (const v of [...vouchers].sort((a, b) => { const x = BigInt(a.payload.authorization.value), y = BigInt(b.payload.authorization.value); return x > y ? -1 : x < y ? 1 : 0; })) { // largest first; equal ones keep their order
229
+ const x = BigInt(v.payload.authorization.value);
230
+ if (x <= left) { out.push(v); left -= x; }
231
+ }
232
+ return left === 0n ? out : null; // ponytail: greedy; exact for denominations that divide each other
233
+ }
234
+
235
+ /** Run `fn` holding `<path>.lock` (Node only): two fangorn-mcp processes sharing one allowance
236
+ * file would otherwise pick the same vouchers and race. A lock older than `staleMs` belongs to
237
+ * a crashed purchase and is taken over.
238
+ * ponytail: a takeover can race a third process for the same stale lock; add a pid check if
239
+ * more than two servers ever share a file. */
240
+ export async function withLock(path, fn, { staleMs = 120_000, waitMs = 30_000 } = {}) {
241
+ const fs = await import("node:fs"), lock = `${path}.lock`, start = Date.now();
242
+ for (;;) {
243
+ try { fs.closeSync(fs.openSync(lock, "wx")); break; } catch (e) {
244
+ if (e.code !== "EEXIST") throw e;
245
+ let age = 0;
246
+ try { age = Date.now() - fs.statSync(lock).mtimeMs; } catch { continue; } // released meanwhile
247
+ if (age > staleMs) { fs.rmSync(lock, { force: true }); continue; }
248
+ if (Date.now() - start > waitMs) throw new Error(`the allowance is in use by another purchase (${lock})`);
249
+ await new Promise((ok) => setTimeout(ok, 100));
250
+ }
251
+ }
252
+ try { return await fn(); } finally { fs.rmSync(lock, { force: true }); }
253
+ }
254
+
255
+ /** Buy many records at once. Pays from `vouchers` (spent ones are removed from the array) or
256
+ * signs one exact payment with `account`/`privateKey`. Each key opens `ct[id]` (the row's
257
+ * paid_ct), checked against `want[id]` (its paid_sha256). Returns the records and a manifest a
258
+ * third party can check. */
259
+ export async function buyBatch(paid, allIds, { ct = {}, want = {}, vouchers, account, privateKey, maxPrice, fetchImpl = fetch } = {}) {
260
+ const url = paid.url.replace(/\/\{id\}$/, "");
261
+ // Only ids whose sealed record is in hand are bought: anything else would pay for nothing.
262
+ const ids = allIds.filter((id) => ct[id]), unsealed = allIds.filter((id) => !ct[id]);
263
+ if (!ids.length) throw new Error(`none of these rows carries a sealed record (paid_ct): ${unsealed.join(", ")}`);
264
+ const post = (headers = {}) => fetchImpl(url, { method: "POST", headers: { "content-type": "application/json", ...headers }, body: JSON.stringify({ ids }) });
265
+ const first = await post();
266
+ const body0 = await first.json();
267
+ if (first.status !== 402) throw new Error(`expected a price, got HTTP ${first.status}: ${JSON.stringify(body0).slice(0, 200)}`);
268
+ const offer = { ...body0, ...paymentRequired(first) };
269
+ const req = choose(offer.accepts, { maxPrice });
270
+ let payments;
271
+ if (vouchers) {
272
+ payments = pick(vouchers, req.amount);
273
+ if (!payments) throw new Error(`the allowance cannot pay exactly ${req.amount} (base units); add funds or buy fewer records`);
274
+ } else {
275
+ account ??= privateKey ? (await import("viem/accounts")).privateKeyToAccount(privateKey) : null;
276
+ if (!account) throw new Error(`${offer.found.length} record(s) cost ${req.amount} (base units); no wallet or allowance to pay`);
277
+ payments = [await signPayment(req, account, { resource: offer.resource })];
278
+ }
279
+ const res = await post({ "PAYMENT-SIGNATURE": b64(JSON.stringify(payments)) });
280
+ const body = await res.json();
281
+ // Drop every voucher the seller says it settled (`paid`) or could not (`rejected`: spent, or
282
+ // the wallet cannot cover it), on success, partial delivery and refusal alike, so a dead
283
+ // voucher is never offered twice. A seller that names none: all of them on a 200.
284
+ const nonce = (p) => p.payload.authorization.nonce;
285
+ const paidNonces = new Set(body.paid ?? (res.status === 200 ? payments.map(nonce) : []));
286
+ if (vouchers) for (const n of [...paidNonces, ...(body.rejected ?? [])]) {
287
+ const k = vouchers.findIndex((v) => nonce(v) === n);
288
+ if (k >= 0) vouchers.splice(k, 1);
289
+ }
290
+ if (res.status !== 200) throw new Error(`payment refused: ${body.error ?? JSON.stringify(body).slice(0, 200)}`);
291
+ const spent = payments.filter((p) => paidNonces.has(nonce(p))).reduce((s, p) => s + BigInt(p.payload.authorization.value), 0n);
292
+ const records = await openAll(body.keys, ct, want);
293
+ // `undelivered` + `error`: a payment failed after others settled; these ids were not paid for.
294
+ return { records, missing: [...unsealed, ...(body.missing ?? [])], undelivered: body.undelivered ?? [], error: body.error ?? null,
295
+ manifest: { app: url, bought: new Date().toISOString(), price: String(spent),
296
+ asset: req.asset, network: req.network, transactions: body.receipts.map((r) => r.transaction),
297
+ records: records.map(({ id, sha256 }) => ({ id, sha256 })) } };
74
298
  }
75
299
 
76
300
  // ── self-check: `node src/agent/x402.js` — a stand-in seller that checks the signature ──
@@ -78,28 +302,139 @@ if (typeof process !== "undefined" && import.meta.url === `file://${process.argv
78
302
  const { privateKeyToAccount, generatePrivateKey } = await import("viem/accounts");
79
303
  const { verifyTypedData } = await import("viem");
80
304
  const buyer = privateKeyToAccount(generatePrivateKey());
81
- const USDC = "0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d", SELLER = `0x${"5e".repeat(20)}`;
82
- const req = { scheme: "exact", network: "arbitrum-sepolia", maxAmountRequired: "10000", resource: "https://x/paid/1",
83
- payTo: SELLER, asset: USDC, maxTimeoutSeconds: 120, extra: { name: "USD Coin", version: "2" } };
305
+ // Base Sepolia's USDC, whose EIP-712 name is "USDC" (Base's is "USD Coin").
306
+ const USDC = "0x036CbD53842c5426634e7929541eC2318f3dCF7e", SELLER = `0x${"5e".repeat(20)}`, CHAIN = 84532, DOMAIN = { name: "USDC", version: "2" };
307
+ const req = { scheme: "exact", network: `eip155:${CHAIN}`, amount: "10000", payTo: SELLER, asset: USDC, maxTimeoutSeconds: 120, extra: DOMAIN };
84
308
  let settled = null;
85
309
  const seller = async (url, init = {}) => {
86
- const h = init.headers?.["X-PAYMENT"];
87
- if (!h) return new Response(JSON.stringify({ x402Version: 1, accepts: [req] }), { status: 402 });
88
- const p = JSON.parse(unb64(h)).payload, a = p.authorization;
310
+ const h = init.headers?.["PAYMENT-SIGNATURE"];
311
+ if (!h) return new Response("{}", { status: 402, headers: { "PAYMENT-REQUIRED": b64(JSON.stringify({ x402Version: 2, resource: { url }, accepts: [req] })) } });
312
+ const sent = JSON.parse(unb64(h)), p = sent.payload, a = p.authorization;
313
+ if (sent.x402Version !== 2 || sent.resource?.url !== url || sent.accepted?.amount !== "10000") return new Response("{}", { status: 400 });
89
314
  const ok = await verifyTypedData({ address: a.from, signature: p.signature,
90
- domain: { name: "USD Coin", version: "2", chainId: 421614, verifyingContract: USDC },
315
+ domain: { ...DOMAIN, chainId: CHAIN, verifyingContract: USDC },
91
316
  types: { TransferWithAuthorization: [{ name: "from", type: "address" }, { name: "to", type: "address" }, { name: "value", type: "uint256" },
92
317
  { name: "validAfter", type: "uint256" }, { name: "validBefore", type: "uint256" }, { name: "nonce", type: "bytes32" }] },
93
318
  primaryType: "TransferWithAuthorization",
94
319
  message: { ...a, value: BigInt(a.value), validAfter: BigInt(a.validAfter), validBefore: BigInt(a.validBefore) } });
95
- if (!ok || a.to !== SELLER || a.value !== "10000") return new Response(JSON.stringify({ error: "bad payment" }), { status: 402 });
320
+ if (!ok || a.to !== SELLER || a.value !== "10000") return new Response("{}", { status: 402, headers: { "PAYMENT-REQUIRED": b64(JSON.stringify({ x402Version: 2, error: "bad payment", accepts: [req] })) } });
96
321
  settled = a;
97
- return new Response('{"secret":42}', { status: 200, headers: { "X-PAYMENT-RESPONSE": b64(JSON.stringify({ success: true, transaction: "0xabc" })) } });
322
+ return new Response('{"secret":42}', { status: 200, headers: { "PAYMENT-RESPONSE": b64(JSON.stringify({ success: true, transaction: "0xabc" })) } });
98
323
  };
99
324
  const r = await payAndFetch("https://x/paid/1", { account: buyer, maxPrice: 10000n, fetchImpl: seller });
100
325
  if (r.body !== '{"secret":42}' || r.receipt.transaction !== "0xabc" || settled.from !== buyer.address) throw new Error(`paid fetch: ${JSON.stringify(r)}`);
101
326
  let refused = false;
102
327
  try { await payAndFetch("https://x/paid/1", { account: buyer, maxPrice: 9999n, fetchImpl: seller }); } catch (e) { refused = /exceeds the cap/.test(e.message); }
103
328
  if (!refused) throw new Error("a price over the cap must be refused before signing");
329
+
330
+ // Batches through the real worker (CONFIG as ship deploys it), a stand-in facilitator
331
+ // that checks signatures and refuses a nonce settled twice, and vouchers signed ahead.
332
+ const { mkdtempSync, writeFileSync } = await import("node:fs");
333
+ const { tmpdir } = await import("node:os");
334
+ const membership = { registry: `0x${"12".repeat(20)}`, barliman: "https://barliman", chainId: CHAIN, appId: `0x${"ab".repeat(32)}` };
335
+ const sale = { price: "100000", network: `eip155:${CHAIN}`, asset: USDC, payTo: SELLER, facilitator: "https://fac", ...DOMAIN, description: "", membership };
336
+ // Not a literal: the page bundles this module, and a bundler would follow it into the Worker.
337
+ const WORKER = "../../site/worker.js";
338
+ const worker = (await import(/* @vite-ignore */ WORKER)).default;
339
+ // The rows as a buyer reads them: each record sealed under its key, with the plaintext's sha256.
340
+ const SECRET = "s3cret", ct = {}, want = {};
341
+ for (const id of ["a", "b", "c"]) {
342
+ const plain = JSON.stringify({ id, amount: 1 });
343
+ ct[id] = await sealPaid(await paidKey(SECRET, id), plain);
344
+ want[id] = await sha256(new TextEncoder().encode(plain));
345
+ }
346
+ const env = { PAID_SECRET: SECRET, CONFIG: { name: "Test", paid: sale } };
347
+ const member = privateKeyToAccount(generatePrivateKey()), memberToken = "77";
348
+ const spent = new Set(), facilitated = [];
349
+ const realFetch = globalThis.fetch;
350
+ const { recoverTypedDataAddress } = await import("viem");
351
+ globalThis.fetch = async (u, init) => {
352
+ if (u === "https://barliman/check") { // a stand-in Barliman: the member's token reads, nobody else's
353
+ const b = JSON.parse(init.body);
354
+ const reader = await recoverTypedDataAddress({ ...readTypedData({ registry: membership.registry, chainId: CHAIN, ...b }), signature: b.signature });
355
+ const ok = reader === member.address && b.tokenId === memberToken && b.appId === membership.appId;
356
+ return new Response(JSON.stringify({ ok, reader, until: ok ? "1900000000" : "0" }));
357
+ }
358
+ const { x402Version, paymentPayload: p, paymentRequirements: q } = JSON.parse(init.body), a = p.payload.authorization;
359
+ if (x402Version !== 2 || p.x402Version !== 2) throw new Error("the facilitator is spoken to in v2");
360
+ facilitated.push(p);
361
+ if (u.endsWith("/verify")) {
362
+ const ok = await verifyTypedData({ address: a.from, signature: p.payload.signature,
363
+ domain: { ...DOMAIN, chainId: CHAIN, verifyingContract: USDC },
364
+ types: { TransferWithAuthorization: [{ name: "from", type: "address" }, { name: "to", type: "address" }, { name: "value", type: "uint256" },
365
+ { name: "validAfter", type: "uint256" }, { name: "validBefore", type: "uint256" }, { name: "nonce", type: "bytes32" }] },
366
+ primaryType: "TransferWithAuthorization",
367
+ message: { ...a, value: BigInt(a.value), validAfter: BigInt(a.validAfter), validBefore: BigInt(a.validBefore) } });
368
+ return new Response(JSON.stringify({ isValid: ok && a.value === q.amount, invalidReason: "bad" }));
369
+ }
370
+ if (spent.has(a.nonce)) return new Response(JSON.stringify({ success: false, errorReason: "nonce used" }));
371
+ spent.add(a.nonce);
372
+ return new Response(JSON.stringify({ success: true, transaction: `0x${spent.size}` }));
373
+ };
374
+ const viaWorker = (u, init) => worker.fetch(new Request(u, init), env);
375
+ const paidCard = { url: "https://x/paid/{id}", key_url: "https://x/key", price: sale.price, membership };
376
+ try {
377
+ // One record, one payment: the key opens the row's sealed record, which matches its hash.
378
+ const single = await buyRecord(paidCard, "a", { ct: ct.a, want: want.a, account: buyer, maxPrice: 100000n, fetchImpl: viaWorker });
379
+ if (single.verified !== true || single.record.id !== "a") throw new Error(`single key: ${JSON.stringify(single)}`);
380
+ if (facilitated.some((p) => p.extensions)) throw new Error("GET /paid/<id> must not ask to be listed: its URL differs per record");
381
+ // A probe with no body (x402scan, a Bazaar crawler) gets a 402 for one record, Bazaar extension and all.
382
+ const probe = await viaWorker("https://x/paid", { method: "POST" });
383
+ const asked = paymentRequired(probe);
384
+ if (probe.status !== 402 || asked.accepts[0].amount !== sale.price || asked.extensions?.bazaar?.info?.input?.method !== "POST")
385
+ throw new Error(`probe: ${probe.status} ${JSON.stringify(asked)}`);
386
+ // One exact payment from a wallet: 2 of 3 ids are sealed in the rows, 2 × $0.10, the
387
+ // third is never quoted (no ciphertext in hand, nothing to pay for).
388
+ const one = await buyBatch(paidCard, ["a", "b", "zz"], { account: buyer, maxPrice: 200000n, ct, want, fetchImpl: viaWorker });
389
+ if (one.records.length !== 2 || one.missing[0] !== "zz" || one.manifest.price !== "200000" || !one.records.every((r) => r.verified === true))
390
+ throw new Error(`batch with a wallet: ${JSON.stringify(one)}`);
391
+ // The facilitator lists what it settles with the Bazaar extension: every batch payment carries it.
392
+ const batchSent = facilitated.slice(-2); // its one payment: verify, settle
393
+ if (!batchSent.every((p) => p.extensions?.bazaar && p.resource.url === "https://x/paid" && p.accepted.amount === "200000"))
394
+ throw new Error(`batch payloads: ${JSON.stringify(batchSent.map((p) => [p.resource?.url, p.accepted?.amount, !!p.extensions]))}`);
395
+ // $2 of vouchers in $0.10 / $1, 30 days: any multiple of $0.10 can be paid exactly.
396
+ const vs = await signVouchers({ ...paidCard, scheme: "exact", network: sale.network, payTo: SELLER, asset: USDC, extra: DOMAIN },
397
+ buyer, { total: 2000000n, denominations: [100000n, 1000000n] });
398
+ if (vs.length !== 11 || pick(vs, 1700000n).length !== 8 || pick(vs, 2100000n) !== null) throw new Error(`vouchers: ${vs.length}`);
399
+ const before = [...vs];
400
+ const three = await buyBatch(paidCard, ["a", "b", "c"], { vouchers: vs, ct, want, fetchImpl: viaWorker });
401
+ if (three.records.length !== 3 || vs.length !== 8 || three.manifest.transactions.length !== 3) throw new Error(`batch with vouchers: ${JSON.stringify(three.manifest)}`);
402
+ // A spent $0.10 voucher riding along with a fresh one: both verify, settle refuses, nothing sent.
403
+ const usedOne = before.find((v) => !vs.includes(v) && v.payload.authorization.value === "100000");
404
+ const fresh = vs.find((v) => v.payload.authorization.value === "100000");
405
+ const replay = await viaWorker("https://x/paid", { method: "POST", body: JSON.stringify({ ids: ["a", "b"] }), headers: { "PAYMENT-SIGNATURE": b64(JSON.stringify([usedOne, fresh])) } });
406
+ if (replay.status !== 402 || (await replay.json()).keys) throw new Error("a spent voucher must not buy anything");
407
+ const short = await viaWorker("https://x/paid", { method: "POST", body: JSON.stringify({ ids: ["a", "b"] }), headers: { "PAYMENT-SIGNATURE": b64(JSON.stringify([fresh])) } });
408
+ if (short.status !== 402) throw new Error("payments short of the price must be refused");
409
+ // A spent voucher still in the stack, behind a fresh one (a crash before the file was
410
+ // saved): the fresh one settles and buys one record, the spent one is refused, and both
411
+ // leave the stack so neither is offered again.
412
+ const fresh2 = vs.find((v) => v !== fresh && v.payload.authorization.value === "100000");
413
+ const stack = [fresh2, usedOne];
414
+ const half = await buyBatch(paidCard, ["a", "b"], { vouchers: stack, ct, want, fetchImpl: viaWorker });
415
+ if (half.records.length !== 1 || half.undelivered[0] !== "b" || !half.error || half.manifest.price !== "100000" || stack.length !== 0)
416
+ throw new Error(`partial settle: ${JSON.stringify({ ...half, stack: stack.length })}`);
417
+ // The spent voucher first: nothing settles, nothing is sent, and it is dropped.
418
+ const stack2 = [usedOne, fresh];
419
+ let threw = false;
420
+ try { await buyBatch(paidCard, ["a", "b"], { vouchers: stack2, ct, want, fetchImpl: viaWorker }); } catch { threw = true; }
421
+ if (!threw || stack2.length !== 1 || stack2[0] !== fresh) throw new Error(`refused batch must drop only the spent voucher: ${stack2.length}`);
422
+ // A member reads for free: the signed request names the token; a stranger's is refused.
423
+ const read = await readAsMember(paidCard, ["a", "c"], { reader: member, tokenId: memberToken, ct, want, fetchImpl: viaWorker });
424
+ if (read.records.length !== 2 || !read.records.every((r) => r.verified === true)) throw new Error(`member read: ${JSON.stringify(read)}`);
425
+ let stranger = false;
426
+ try { await readAsMember(paidCard, ["a"], { reader: buyer, tokenId: memberToken, ct, want, fetchImpl: viaWorker }); } catch { stranger = true; }
427
+ if (!stranger) throw new Error("a reader the membership does not name must be refused");
428
+ // The allowance lock: two purchases at once take turns; a crashed one's lock is taken over.
429
+ const vfile = `${mkdtempSync(`${tmpdir()}/wm-`)}/vouchers.json`, order = [];
430
+ const turn = (name) => withLock(vfile, async () => { order.push(`${name}+`); await new Promise((ok) => setTimeout(ok, 50)); order.push(`${name}-`); });
431
+ await Promise.all([turn("a"), turn("b")]);
432
+ if (order.join() !== "a+,a-,b+,b-" && order.join() !== "b+,b-,a+,a-") throw new Error(`lock interleaved: ${order}`);
433
+ writeFileSync(`${vfile}.lock`, "");
434
+ const { utimesSync, existsSync } = await import("node:fs");
435
+ utimesSync(`${vfile}.lock`, new Date(Date.now() - 300_000), new Date(Date.now() - 300_000));
436
+ if (await withLock(vfile, async () => 7) !== 7 || existsSync(`${vfile}.lock`)) throw new Error("a stale lock must be taken over and released");
437
+ } finally { globalThis.fetch = realFetch; }
438
+ console.log("x402.js batch self-check ok — keys, not records: each opens the row's sealed record and matches its hash; a member reads free and a stranger is refused; one price for the ids sealed in the rows, paid by one signature or by vouchers signed ahead, spent vouchers removed and refused if replayed, short payment refused, a half-settled batch delivers what was paid and drops spent vouchers, the allowance file is locked per purchase");
104
439
  console.log("x402.js self-check ok — a signed EIP-3009 authorization the seller can verify, exactly the asked amount to the asked payee, the receipt read back, and a price over the cap refused before signing");
105
440
  }