@fangorn-network/westmarch 2026.10.29 → 2026.11.4-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.
- package/README.md +5 -5
- package/docs/app-to-agent.md +61 -625
- package/package.json +12 -17
- package/site/dist/assets/__vite-browser-external-D2U8RZpp.js +1 -0
- package/site/dist/assets/embed.worker-CmS57Zti.js +1 -0
- package/site/dist/assets/index-Djs8f08m.js +8 -0
- package/site/dist/assets/rolldown-runtime-COiEfhsA.js +1 -0
- package/site/dist/assets/{transformers.web-BTyOEJ0C.js → transformers.web-CwR_IYQV.js} +1 -1
- package/site/dist/index.html +3 -4
- package/site/worker.js +115 -338
- package/src/agent/agent-card.js +33 -45
- package/src/agent/mcp.js +168 -371
- package/src/agent/tools.js +2 -1
- package/src/agent/view-tools.js +4 -56
- package/src/agent/x402.js +182 -369
- package/src/core/roles.js +6 -6
- package/src/core/shard.js +4 -4
- package/src/discover/apps.js +67 -81
- package/src/discover/directory.js +2 -2
- package/src/market/reactions.js +21 -15
- package/src/publish/devnet.js +69 -18
- package/src/publish/init.js +1 -1
- package/src/publish/ship.js +74 -275
- package/src/publish/view.js +52 -53
- package/template/README.md +9 -11
- package/template/package.json +1 -1
- package/plugin/scripts/fx.mjs +0 -266
- package/site/dist/assets/AccountNotFoundScreen-C4njXc69-DyVH4CEz.js +0 -1
- package/site/dist/assets/AddFundsSelectionScreen-RAoCn7ej-Dz1--SS9.js +0 -31
- package/site/dist/assets/Address-H8kD1d9O-BdFZmRwI.js +0 -17
- package/site/dist/assets/AffirmativeConsentScreen-BG0MJxku-CxaCAisL.js +0 -6
- package/site/dist/assets/AllowlistRejectionScreen-Cae6e1Od-JGk7vndN.js +0 -1
- package/site/dist/assets/ApiController-CTLbMCcH.js +0 -5
- package/site/dist/assets/ArrowsRightLeftIcon-B8g9adpz.js +0 -1
- package/site/dist/assets/AuthenticateWithWalletScreen-CU6hIcFT-CXD9_OP8.js +0 -1
- package/site/dist/assets/AwaitingEvmToSolBridgingScreen-D0e_sZMS-BtJCglvU.js +0 -1
- package/site/dist/assets/AwaitingExternalEthereumTransferScreen-ur5HL4R7-BgC2TsqH.js +0 -1
- package/site/dist/assets/AwaitingPasswordlessCodeScreen-DRHz76mM-B9OzLeEO.js +0 -103
- package/site/dist/assets/AwaitingSolToEvmBridgingScreen-CdLRrGD2-C7r5snUL.js +0 -1
- package/site/dist/assets/BridgeNetworkSelectionView-CFGjB2nO-BTV0NRio.js +0 -68
- package/site/dist/assets/CaptchaScreen-DbpvkIGx-7rSZIuM-.js +0 -1
- package/site/dist/assets/CheckCircleIcon-B1l17ioc.js +0 -1
- package/site/dist/assets/CheckCircleIcon-BGSI8nKf.js +0 -1
- package/site/dist/assets/Checkbox-D1EDeo41-BUfq0w99.js +0 -52
- package/site/dist/assets/ChevronDownIcon-B6uJvPHu.js +0 -1
- package/site/dist/assets/Chip-CZKIKt9K-r9Nk__0-.js +0 -26
- package/site/dist/assets/CoinbaseOnrampStatusScreen-BbyCJDXL-DWWNHxmR.js +0 -16
- package/site/dist/assets/ConnectEmailForm-B-VRE0MN-CRQwS0Xu.js +0 -3
- package/site/dist/assets/ConnectLedgerScreen-DWHABGot-CZcCt31O.js +0 -10
- package/site/dist/assets/ConnectOnlyLandingScreen-CZYx9Bmp-C5IOf-SQ.js +0 -1
- package/site/dist/assets/ConnectOnlyStatusScreen-DCRzjxHx-cwg74F3A.js +0 -1
- package/site/dist/assets/ConnectOrCreateScreen-CUUYUO07-D28oeK6b.js +0 -1
- package/site/dist/assets/ConnectPhoneForm-Dek5xn4C-EEdkKeTp.js +0 -95
- package/site/dist/assets/ConnectWalletView-DqI-PTvX-C2mEzukj.js +0 -74
- package/site/dist/assets/ConnectionStatusScreen-fUfROm9m-CH_7r8iV.js +0 -7
- package/site/dist/assets/ConnectionStatusScreen-fUfROm9m-Z33kis0B.js +0 -1
- package/site/dist/assets/ConnectorUtil-DH4NePk5.js +0 -21
- package/site/dist/assets/ConstantsUtil-DmLsRHAl.js +0 -198
- package/site/dist/assets/CopyToClipboard-i_OQSBJr-_G88JCVR.js +0 -39
- package/site/dist/assets/CopyableText-CQapvaMr-CGGfc_zM.js +0 -28
- package/site/dist/assets/CrossAppAuthScreen-CLw7ymZq-C9Okoc0V.js +0 -1
- package/site/dist/assets/CustomLandingScreenView-Cm_MBSyX-D2l6hdSl.js +0 -22
- package/site/dist/assets/DelegatedActionsConsentScreen-DYF2U4y5-Dda3KKqS.js +0 -1
- package/site/dist/assets/DelegatedActionsRevokeScreen-bPp6Uwyh-DG8kJPt1.js +0 -1
- package/site/dist/assets/DepositAddressAddressStepView-4vdkb55L-CcOUfn6f.js +0 -187
- package/site/dist/assets/DepositAddressScreen-DBLRs7aI-DeituDNh.js +0 -8
- package/site/dist/assets/DepositAddressV3Screen-CDqIEMQw-FDg6K14-.js +0 -1
- package/site/dist/assets/EmailInputForm-Cqo1mda8-BmbxvPHC.js +0 -124
- package/site/dist/assets/EmbeddedWalletConnectingScreen-D4T7DUzs-B05CQ9rx.js +0 -1
- package/site/dist/assets/EmbeddedWalletCreatedScreen-D7WhW5ve-Cxd1b9XH.js +0 -1
- package/site/dist/assets/EmbeddedWalletKeyExportScreen-CqV4NYQ3-CrJy0ViX.js +0 -23
- package/site/dist/assets/EmbeddedWalletOnAccountCreateScreen-BoKb3Q2S-Bakaa3zu.js +0 -1
- package/site/dist/assets/EmbeddedWalletPasswordUpdateScreen-D3rMlqS7-j78vKrcj.js +0 -1
- package/site/dist/assets/EmbeddedWalletPasswordUpdateSplashScreen-BPFkWJeE-D3dr7W9_.js +0 -1
- package/site/dist/assets/EnrollTotp-Dibew4dp-BXbYV8nI.js +0 -66
- package/site/dist/assets/EnvelopeIcon-DjPofnRI.js +0 -1
- package/site/dist/assets/ErrorBanner-BcpGRt0h-BhH6_V-9.js +0 -21
- package/site/dist/assets/ErrorMessage-D8VaAP5m-Bs7uX2a9.js +0 -8
- package/site/dist/assets/ErrorScreen-DipdTWzE-BgPRgnOb.js +0 -4
- package/site/dist/assets/ErrorScreen-DipdTWzE-CvxXC6pz.js +0 -1
- package/site/dist/assets/ExclamationCircleIcon-BE-WGrut.js +0 -1
- package/site/dist/assets/ExclamationTriangleIcon-Ca1Xlc_f.js +0 -1
- package/site/dist/assets/FarcasterConnectStatusScreen-51tjUxqq-De2JvZdV.js +0 -75
- package/site/dist/assets/FarcasterSignerStatusScreen-6x-Uh95G-bLp3hXoO.js +0 -28
- package/site/dist/assets/FiatOnrampScreen-BAhYeiTI-Jr6D6JiZ.js +0 -491
- package/site/dist/assets/FingerPrintIcon-DOCbS93y.js +0 -1
- package/site/dist/assets/FundSolWalletWithExternalSolanaWallet-WtLwYaOl-A_G5kfa1.js +0 -1
- package/site/dist/assets/FundWalletMethodHeader-BWNkokCT-LPv35wkD.js +0 -1
- package/site/dist/assets/FundWithBankDepositScreen-DajkHxBD-0hfGrfvf.js +0 -58
- package/site/dist/assets/FundingEditAmountScreen-CpvpiO4M-Dz0s_NWR.js +0 -1
- package/site/dist/assets/FundingMethodSelectionScreen-Db7vhRlE-ZGm-3-Io.js +0 -1
- package/site/dist/assets/GlobeAltIcon-BBRl2MMn.js +0 -1
- package/site/dist/assets/GooglePay-B53WnudL-BGiVpB8y.js +0 -1
- package/site/dist/assets/HCaptchaWrapper-CUi9LJsp-CHdfIeD_.js +0 -4
- package/site/dist/assets/InAppBrowserLoginNotPossible-BMR9br1T-Cgoiow3m.js +0 -1
- package/site/dist/assets/InfoBanner-Cb3p1z12-_YqQmRiu.js +0 -22
- package/site/dist/assets/InjectedWalletIcon-DLcYOGDj-tuIrKQHH.js +0 -1
- package/site/dist/assets/InstallWalletScreen-DTA8dwLv-BMU_wa61.js +0 -1
- package/site/dist/assets/JsonTree-BHzNC-ic-DcVr0YF0.js +0 -34
- package/site/dist/assets/LabelXs-oqZNqbm_-CNprGVQM.js +0 -6
- package/site/dist/assets/LandingScreen-CGWUoSUG-fH6rsQen.js +0 -1
- package/site/dist/assets/Layouts-BMRfo5hw-e-sepi6F.js +0 -77
- package/site/dist/assets/Link-BdDilT2T-BdwlRJch.js +0 -40
- package/site/dist/assets/LinkConflictScreen-C3ZEPsgl-BXKN2Qm5.js +0 -77
- package/site/dist/assets/LinkEmailScreen-dKo9frwc-Cyn7Q8p1.js +0 -1
- package/site/dist/assets/LinkPasskeyScreen-zbrl_AI_-CWiqnwLM.js +0 -117
- package/site/dist/assets/LinkPasskeyScreen-zbrl_AI_-YmDevJzf.js +0 -1
- package/site/dist/assets/LinkPhoneScreen-oIUpfj0w-h7shW-Ay.js +0 -1
- package/site/dist/assets/Loader-UAZqxsnw-DJEVblm1.js +0 -62
- package/site/dist/assets/LoadingSkeleton-BMsgO5PV-D2atjsP5.js +0 -17
- package/site/dist/assets/LockClosedIcon-9EFzWK1C.js +0 -1
- package/site/dist/assets/LoginFailedScreen-CN0dJV6U-By3Si77a.js +0 -1
- package/site/dist/assets/ManualTransferScreen-CHqcuqbs-BAHPY8rs.js +0 -1
- package/site/dist/assets/MfaAuthEnrollmentFlowScreen-Dj7gPTRC-CLjffFG1.js +0 -1
- package/site/dist/assets/MfaAuthVerifyFlowScreen-DbFpyWMy-BmQg1Y61.js +0 -1
- package/site/dist/assets/MfaEnrollmentFlowScreen-DhLnGgnr-DmBtTtlw.js +0 -1
- package/site/dist/assets/MfaVerifyFlowScreen-C_XPjMRP-4a683Bmf.js +0 -1
- package/site/dist/assets/ModalFooter-BCuEK_nz-C_71qsaz.js +0 -403
- package/site/dist/assets/MoonpayStatusScreen-CzTUtokc-DEHHcEf8.js +0 -16
- package/site/dist/assets/OAuthStatusScreen-ufbOa-da-BjAb_WsY.js +0 -1
- package/site/dist/assets/OpenLink-CUpJ1mOr-BLWFsPOW.js +0 -39
- package/site/dist/assets/PasskeySelectSignupOrLogin-xh2ScC_l-2PJTJxX-.js +0 -1
- package/site/dist/assets/PasskeyStatusScreen-Bla8MaOk-DCEg761l.js +0 -6
- package/site/dist/assets/PasswordRecoveryScreen-awGXZkQk-8nVjNc8k.js +0 -20
- package/site/dist/assets/PhArrowCircleDown-D97G-BOA.js +0 -14
- package/site/dist/assets/PhArrowClockwise-DVgyFuez.js +0 -14
- package/site/dist/assets/PhArrowDown-87b1BizM.js +0 -14
- package/site/dist/assets/PhArrowLeft-Da0MfnbK.js +0 -14
- package/site/dist/assets/PhArrowRight-AdrIL4DW.js +0 -14
- package/site/dist/assets/PhArrowSquareOut-Bk2CMG3I.js +0 -14
- package/site/dist/assets/PhArrowUp-4sgyKPGx.js +0 -14
- package/site/dist/assets/PhArrowUpRight-BNghD2zq.js +0 -14
- package/site/dist/assets/PhArrowsClockwise-BXRn1GEl.js +0 -14
- package/site/dist/assets/PhArrowsDownUp-DM09Jo_3.js +0 -14
- package/site/dist/assets/PhArrowsLeftRight-MuKBLUoF.js +0 -14
- package/site/dist/assets/PhBank-fHbgCqqZ.js +0 -14
- package/site/dist/assets/PhBrowser-2-9m-AkM.js +0 -14
- package/site/dist/assets/PhCaretDown-BDNabFuL.js +0 -14
- package/site/dist/assets/PhCaretLeft-CI460R-A.js +0 -14
- package/site/dist/assets/PhCaretRight-D7ZS3Ls8.js +0 -14
- package/site/dist/assets/PhCaretUp-C-iIfyvO.js +0 -14
- package/site/dist/assets/PhCheck-DxQXn57r.js +0 -14
- package/site/dist/assets/PhCircleHalf-MJZeRBGF.js +0 -14
- package/site/dist/assets/PhClock-x3MS3Mwi.js +0 -14
- package/site/dist/assets/PhCompass-hYn3HhGN.js +0 -14
- package/site/dist/assets/PhCopy-CWNYcABI.js +0 -14
- package/site/dist/assets/PhCreditCard-Fy4pzwtt.js +0 -14
- package/site/dist/assets/PhCurrencyDollar-BgiaenCi.js +0 -14
- package/site/dist/assets/PhDesktop-CxrzCSv5.js +0 -14
- package/site/dist/assets/PhDeviceMobile-CsyA5Goi.js +0 -14
- package/site/dist/assets/PhDotsThree-D-k1BiYg.js +0 -14
- package/site/dist/assets/PhEnvelope-D8kzeNox.js +0 -14
- package/site/dist/assets/PhFunnelSimple-CfQs5DAW.js +0 -14
- package/site/dist/assets/PhGlobe-DvmSc9_A.js +0 -14
- package/site/dist/assets/PhIdentificationCard-CfkZm-5K.js +0 -14
- package/site/dist/assets/PhImage-Cf0J2ZfJ.js +0 -14
- package/site/dist/assets/PhInfo-Bwi51-2X.js +0 -14
- package/site/dist/assets/PhLightbulb-C4FZV7Es.js +0 -14
- package/site/dist/assets/PhMagnifyingGlass-C9u8jSCJ.js +0 -14
- package/site/dist/assets/PhPaperPlaneRight-zxQVvPLX.js +0 -14
- package/site/dist/assets/PhPlus-C4UoW-2n.js +0 -14
- package/site/dist/assets/PhPower-CFyWDmgD.js +0 -14
- package/site/dist/assets/PhPuzzlePiece-BjoNVfST.js +0 -14
- package/site/dist/assets/PhQrCode-CP3tFauY.js +0 -14
- package/site/dist/assets/PhQuestion-wOWJBd3G.js +0 -14
- package/site/dist/assets/PhQuestionMark-CV0k9C0Y.js +0 -14
- package/site/dist/assets/PhSealCheck-vIKzREuN.js +0 -14
- package/site/dist/assets/PhSignOut-CxELV-i0.js +0 -14
- package/site/dist/assets/PhSpinner-CGDmbzUd.js +0 -14
- package/site/dist/assets/PhTrash-C9PD0SAt.js +0 -14
- package/site/dist/assets/PhUser-0sWNXQeZ.js +0 -14
- package/site/dist/assets/PhVault-6JTskUcC.js +0 -14
- package/site/dist/assets/PhWarning-CoKs3gz6.js +0 -14
- package/site/dist/assets/PhWarningCircle-BXHw1fCt.js +0 -14
- package/site/dist/assets/PhX-DX0SFIqC.js +0 -14
- package/site/dist/assets/PhoneIcon-CZ47md80.js +0 -1
- package/site/dist/assets/PinInput-DbZ0b1i1-BrTXu3Km.js +0 -247
- package/site/dist/assets/PrivyPluginContext-DA-yS5vO-CY60yubk.js +0 -1
- package/site/dist/assets/QrCode-DbnZwlkH-CcMrWV5D.js +0 -22
- package/site/dist/assets/RecoveryOAuthStatusScreen-CsgtTI2x-DgeDnHOK.js +0 -1
- package/site/dist/assets/RecoveryPasswordCreateScreen-Be-qJ-LU-CvJJwLhK.js +0 -1
- package/site/dist/assets/RecoverySelectionScreen-D1iGtpmi-CADtGtSV.js +0 -7
- package/site/dist/assets/SIWXUtil-Cpiv91-M.js +0 -1
- package/site/dist/assets/Screen-D30meWsY-vEusJ7KX.js +0 -175
- package/site/dist/assets/ScreenHeader-CHmc4-Lu-BvGTLg53.js +0 -31
- package/site/dist/assets/ScreenLayout-OwaQQcxH-cfOTmyl0.js +0 -1
- package/site/dist/assets/SelectSourceAsset-CWFog6gm-DxYklZYs.js +0 -140
- package/site/dist/assets/SetAutomaticRecoveryScreen-BO_OEqAZ-oeqeo05x.js +0 -14
- package/site/dist/assets/SetWalletPasswordForm-DwCTVtAh-BxFee9UA.js +0 -11
- package/site/dist/assets/ShieldCheckIcon-eFjsosCA.js +0 -1
- package/site/dist/assets/SignRequestScreen-BHKv32KR-z8ixfIma.js +0 -26
- package/site/dist/assets/SolanaWalletConnector-C7Lqk-Wz-Bc_lvdiF.js +0 -1
- package/site/dist/assets/StackedContainer-B2vaEl56-Do5dXB8-.js +0 -24
- package/site/dist/assets/StandardSignAndSendTransactionScreen-CfhIXVtd-DudetZAc.js +0 -20
- package/site/dist/assets/Subtitle-CV-2yKE4-DV0o1av3.js +0 -13
- package/site/dist/assets/TelegramAuthScreen-UL9zLfO8-Bo3sONvf.js +0 -1
- package/site/dist/assets/Title-BnzYV3Is-C3qOPnO_.js +0 -7
- package/site/dist/assets/TodoList-DnyULl18-BvxvubbF.js +0 -36
- package/site/dist/assets/TransactionDetails-e9nesl30-WWflkOIi.js +0 -109
- package/site/dist/assets/TransactionErrorView-BDBNqA_f-CotYKcgf.js +0 -178
- package/site/dist/assets/TransferFromWalletScreen-Qvn1Yuno-sVFlWqa8.js +0 -31
- package/site/dist/assets/TransferOrBridgeLoadingScreen-Dl1I_iIz-CV2-mY19.js +0 -6
- package/site/dist/assets/TurnstileWrapper-B7sNddys-oPbuMTQt.js +0 -1
- package/site/dist/assets/UpdateEmailScreen-DVOhPV0H-D_mjSpAy.js +0 -1
- package/site/dist/assets/UpdatePhoneScreen-CXRswTNZ-6RLG0ahv.js +0 -1
- package/site/dist/assets/UserLimitReachedScreen-5we2DHn8-CaVN0bti.js +0 -1
- package/site/dist/assets/Value-DTgR824E-Bp6WGZZm.js +0 -27
- package/site/dist/assets/WalletCards-DH1rqayz-D3cOTb9x.js +0 -1
- package/site/dist/assets/WalletIcon-DOIZhb2l.js +0 -1
- package/site/dist/assets/WalletInfoCard-sq_2wgFg-bOqfl5MA.js +0 -29
- package/site/dist/assets/WalletInterstitialScreen-Sh7LfsAh-DWaVkMCA.js +0 -1
- package/site/dist/assets/WalletLink-DK5LB5Ha-DjUZvqs-.js +0 -20
- package/site/dist/assets/WalletOverflowButton-bfCnp-9T-B6P7DQXA.js +0 -1
- package/site/dist/assets/WarningBanner-ZZqCEtZK-Bc2YKZb7.js +0 -21
- package/site/dist/assets/__vite-browser-external-NciY4Vu1.js +0 -1
- package/site/dist/assets/_esm-BZP3cXTv.js +0 -1
- package/site/dist/assets/_esm-ZmzBJpEs.js +0 -6
- package/site/dist/assets/accounts-D4AXF17G.js +0 -1
- package/site/dist/assets/accounts-IkdFx9nq.js +0 -1
- package/site/dist/assets/analytics-mkkvFRju-BRBcadka.js +0 -1
- package/site/dist/assets/baseSepolia-Bn1j1Ysw.js +0 -1
- package/site/dist/assets/basic-Cz1YiCSk.js +0 -1575
- package/site/dist/assets/capitalizeFirstLetter-DmLYqXsO-DtOXx-2n.js +0 -1
- package/site/dist/assets/ccip-B1J3oTZx.js +0 -7
- package/site/dist/assets/ccip-Bd7261zy.js +0 -1
- package/site/dist/assets/ccip-D6EHKpjI.js +0 -1
- package/site/dist/assets/chain-scefkYIH.js +0 -5
- package/site/dist/assets/check-DHnllI8N.js +0 -1
- package/site/dist/assets/chevron-down-1y-r4bGO.js +0 -1
- package/site/dist/assets/circle-alert-OwxamXUX.js +0 -1
- package/site/dist/assets/circle-check-big-3sZGVC10.js +0 -1
- package/site/dist/assets/circle-x-DQjNUV9J.js +0 -1
- package/site/dist/assets/client-B-BpRtwY.js +0 -1
- package/site/dist/assets/client-BfIR1FvH.js +0 -9
- package/site/dist/assets/coinbase-DCPC2L_R-YEuIn3jh.js +0 -3
- package/site/dist/assets/copy-DMOX_yn7.js +0 -1
- package/site/dist/assets/core-GIEmxmAa.js +0 -12
- package/site/dist/assets/createLucideIcon-BsERoFTA.js +0 -1
- package/site/dist/assets/defineChain-B-SQDLTG.js +0 -1
- package/site/dist/assets/dijkstra-CY95afk4.js +0 -1
- package/site/dist/assets/dist-CoS6E-3x.js +0 -1
- package/site/dist/assets/dist-Cp6IXeJd.js +0 -1
- package/site/dist/assets/dist-CrNxmdZj.js +0 -1
- package/site/dist/assets/dist-DYGtf4F0.js +0 -16
- package/site/dist/assets/embed.worker-Cnl4VGr3.js +0 -1
- package/site/dist/assets/errors-BQ3N-RVt-CZPAWCgC.js +0 -1
- package/site/dist/assets/esm-C3DslVJx.js +0 -1
- package/site/dist/assets/esm-Ci1ogKuK.js +0 -1
- package/site/dist/assets/esm-Co94ENUV.js +0 -37
- package/site/dist/assets/esm-bb8SANZh.js +0 -1
- package/site/dist/assets/esm-n2lWo7kz.js +0 -1
- package/site/dist/assets/ethers-zTjbodk5-Cs648CnD.js +0 -1
- package/site/dist/assets/eventemitter3-Dzc_0Uq2.js +0 -1
- package/site/dist/assets/external-link-BBPG3rG7.js +0 -1
- package/site/dist/assets/farcaster-DPlSjvF5-CzBCmgyL.js +0 -1
- package/site/dist/assets/features-CuiHbgEJ.js +0 -2
- package/site/dist/assets/fingerprint-pattern-CjLtyIxB.js +0 -1
- package/site/dist/assets/floating-ui.react-DmaCfayr.js +0 -1
- package/site/dist/assets/floating-ui.react-dom-CaoMF8mP.js +0 -1
- package/site/dist/assets/formatErc20TokenAmount-BuPk9xcy-BVqOKQif.js +0 -1
- package/site/dist/assets/formatter-CVbp4SlJ.js +0 -1
- package/site/dist/assets/get-entropy-details-for-user-dHRH5Gpi-BNiOFXbK.js +0 -1
- package/site/dist/assets/getChainName-DjpPdUSc-DUyKDrnp.js +0 -1
- package/site/dist/assets/getErc20Balance-jXNpFf0N-q4bV8kQq.js +0 -1
- package/site/dist/assets/getErc20TokenInfo-BNTrzLMP-DcnTFrXN.js +0 -1
- package/site/dist/assets/getFormattedUsdFromLamports-De3U9GlO-Gx4_wxON.js +0 -1
- package/site/dist/assets/getUsdcMintAddress-BVgm9GRo-r2UnDeEy.js +0 -1
- package/site/dist/assets/guards-BIW-GiMJ-D3tWTQAR.js +0 -1
- package/site/dist/assets/hooks.module-BYZGfwDl.js +0 -1
- package/site/dist/assets/hourglass-D_GfQdJr.js +0 -1
- package/site/dist/assets/id-UqEwL2BI-CTlvRMA5.js +0 -1
- package/site/dist/assets/index-BdEw5wyl-kLbhqLbv.js +0 -1
- package/site/dist/assets/index-C2h3EneX.js +0 -8
- package/site/dist/assets/index-CWARkn2w-DxuckIFn.js +0 -61
- package/site/dist/assets/index-DvMddJcd-CNBb4VUn.js +0 -12
- package/site/dist/assets/index-YiCw0Y_x-Czl0tWfF.js +0 -436
- package/site/dist/assets/index.browser-B-i-Lj3J.js +0 -1
- package/site/dist/assets/index.browser-BMmUcykv.js +0 -1
- package/site/dist/assets/index.es-Crd0TyUS.js +0 -2
- package/site/dist/assets/index.es-DQbup1WG.js +0 -3
- package/site/dist/assets/isPaymentRequestAvailable-Bq1cemEn-Cjf3l05I.js +0 -1
- package/site/dist/assets/jsx-runtime-CndCZlyt.js +0 -1
- package/site/dist/assets/landmark-BZPqMFEf.js +0 -1
- package/site/dist/assets/lib-DGtzi2DK.js +0 -1
- package/site/dist/assets/localBatchGatewayRequest-B71J8sQ9.js +0 -29
- package/site/dist/assets/lock-DyN_c-ud.js +0 -1
- package/site/dist/assets/logger-CsXm3oIv-B0UYpNFI.js +0 -1
- package/site/dist/assets/mail-V_mcPb64.js +0 -1
- package/site/dist/assets/modal-context-CwmSeFcv-DPWNJrfK.js +0 -1
- package/site/dist/assets/native-BKj27wfc.js +0 -1
- package/site/dist/assets/ofetch.CWycOUEr-Duby3iHT.js +0 -1
- package/site/dist/assets/parseAbi-Csg-8t59.js +0 -2
- package/site/dist/assets/parseAbiParameters-BWbIMYe4.js +0 -1
- package/site/dist/assets/parseEther-CHS0GNkM.js +0 -1
- package/site/dist/assets/pkce-DXF0yKjP-7_VY-d83.js +0 -1
- package/site/dist/assets/preload-helper-CRzLMJPS.js +0 -1
- package/site/dist/assets/privy-context-81KmsBw2-DiR6-Yq8.js +0 -2
- package/site/dist/assets/property-DuZ9DLP4.js +0 -3
- package/site/dist/assets/react-BfYA1q0G.js +0 -1
- package/site/dist/assets/react-CK2HRI1t.js +0 -1
- package/site/dist/assets/react-DxGeY8B8.js +0 -1
- package/site/dist/assets/react-auth-sHnipzbS.js +0 -1
- package/site/dist/assets/react-dom-BI2Koe4o.js +0 -1
- package/site/dist/assets/reservoir-x-nGuZkT-BguVFH3D.js +0 -1
- package/site/dist/assets/rolldown-runtime-Bjp52BOI.js +0 -1
- package/site/dist/assets/safe-url-D7SRPu33-CkMedGro.js +0 -1
- package/site/dist/assets/secp256k1-BeYL8aZl.js +0 -1
- package/site/dist/assets/secp256k1-Bh4MSkhz.js +0 -1
- package/site/dist/assets/secp256k1-Ci4cqHl0.js +0 -1
- package/site/dist/assets/secp256k1-DsxXqbXv.js +0 -1
- package/site/dist/assets/secp256k1-N9RUmafO.js +0 -1
- package/site/dist/assets/serializeAuthorizationList-DGMik9Wx.js +0 -1
- package/site/dist/assets/serializeSignature-CWKpxoab.js +0 -2
- package/site/dist/assets/sha2-C6s7zZmb.js +0 -1
- package/site/dist/assets/shared-DRZUmnL5-BewE5wK8.js +0 -193
- package/site/dist/assets/shared-FM0rljBt-CxLACri_.js +0 -21
- package/site/dist/assets/shouldProceedtoEmbeddedWalletCreationFlow-B3vyavrh-BkAKsRNi.js +0 -1
- package/site/dist/assets/simulateTransaction-CfuOrae4-PjA_tGjX.js +0 -1
- package/site/dist/assets/smartphone-3p8nFSTE.js +0 -1
- package/site/dist/assets/src-BBjkfi-Q.js +0 -1
- package/site/dist/assets/storage-Ufl800Ne-1qCR2JMO.js +0 -8
- package/site/dist/assets/stringify-DqUj9VzO.js +0 -20
- package/site/dist/assets/stripe.esm-DEi2D291.js +0 -2
- package/site/dist/assets/styles-BsotlekN-Aq27nZGc.js +0 -9
- package/site/dist/assets/styles-Cm9H63WO-p_ic_dxE.js +0 -92
- package/site/dist/assets/styles-DVyDvTdj-CjsWqAld.js +0 -74
- package/site/dist/assets/styles-hslXy6xG-D5QHIrJU.js +0 -164
- package/site/dist/assets/telegram-B-JqnkqZ-Dqkm4rDn.js +0 -1
- package/site/dist/assets/to-ui-error-DWe-qwS3-Bi1HUQI9.js +0 -4
- package/site/dist/assets/toViemAccount-B5iDGq1b-CdFZwv07.js +0 -2
- package/site/dist/assets/transaction-BNTP-bFm-M5tJx8vY.js +0 -1
- package/site/dist/assets/transfer-6YztDh-t-BVQkTvG-.js +0 -1
- package/site/dist/assets/triangle-alert-BG3Qw-Hq.js +0 -1
- package/site/dist/assets/twitch-5IOe4sIQ-CaXHFlAu.js +0 -1
- package/site/dist/assets/types-4CuOD23i.js +0 -1
- package/site/dist/assets/use-headless-crypto-deposit-Yn-QRLB3-CQqeyhGY.js +0 -1
- package/site/dist/assets/use-unlink-wallet-BKK4_5Ur-C0xQN_Lp.js +0 -1
- package/site/dist/assets/useActiveWallet-B-yZYGc6-BkK6rFBm.js +0 -123
- package/site/dist/assets/useGetSolPrice-x7gfUIHJ-CLVXqv6I.js +0 -1
- package/site/dist/assets/useGetTokenPrice-CaoUkb79-DAXXs3rs.js +0 -1
- package/site/dist/assets/useI18n-C-5n_noF-CGpkgIVy.js +0 -1
- package/site/dist/assets/useWalletBalance-CZnP5f_f-Cfd64m4n.js +0 -1
- package/site/dist/assets/useWallets-X1ndvJ_U-CAYqg7Za.js +0 -1
- package/site/dist/assets/utils-BkR7EQjg.js +0 -1
- package/site/dist/assets/utils-DJhBNOZA.js +0 -1
- package/site/dist/assets/utils-DdckVfQr.js +0 -1
- package/site/dist/assets/w3m-modal-B4H_uiPH.js +0 -1174
- package/site/dist/assets/wallet-BNI12IYk.js +0 -1
- package/site/dist/assets/wallet-CITSaPlB.js +0 -2
- package/site/dist/assets/wallet-connect-BvJtUsDt-CVlSNIXP.js +0 -1
- package/site/dist/assets/walletconnect-registry-xxG8XLCb-BpzpBq5s.js +0 -1
- package/site/dist/assets/walletconnect-v2-3frQFwbg-CzZ6oybX.js +0 -12
- package/site/dist/assets/wui-ux-by-reown-XyHdtV1O.js +0 -1147
- package/site/dist/assets/x-gjDrY2rk.js +0 -1
- package/src/discover/explore.js +0 -291
- package/src/market/settle.js +0 -165
- package/src/market/terms.js +0 -200
- package/src/publish/cli.js +0 -336
- package/src/publish/envelope.js +0 -185
- package/src/publish/manifest.js +0 -142
package/src/publish/envelope.js
DELETED
|
@@ -1,185 +0,0 @@
|
|
|
1
|
-
// The on-the-wire envelope format, shared by everything that writes it.
|
|
2
|
-
//
|
|
3
|
-
// `ns` — the app's namespace string — is the first argument of the two id
|
|
4
|
-
// derivations and it is NOT defaulted. It is folded into every resourceId ever
|
|
5
|
-
// minted, so it is permanent: changing an app's ns orphans everything that app
|
|
6
|
-
// already published, and two apps that accidentally share one mint into each
|
|
7
|
-
// other's id space. An app pins it once (sond3r: src/pay/envelope.js) and never
|
|
8
|
-
// again. A default here would be a way to pick it by accident.
|
|
9
|
-
//
|
|
10
|
-
// Three implementations used to need these constants to agree — server/settle.js
|
|
11
|
-
// (relay-side publish), src/pay/encrypt.js (browser-side publish) and src/pay/stream.js /
|
|
12
|
-
// src/pay/buy.js (the buyer, unpacking). They agree because they import from here.
|
|
13
|
-
// A mismatch is not a crash: chunk `i` decrypts to garbage, or a key lands where
|
|
14
|
-
// the worker's /access gate isn't looking, and the file goes dark for everyone
|
|
15
|
-
// who paid for it.
|
|
16
|
-
//
|
|
17
|
-
// Browser-safe on purpose: viem only, no node builtins.
|
|
18
|
-
import { concat, encodePacked, hexToBytes, keccak256, numberToHex, stringToBytes } from "viem";
|
|
19
|
-
|
|
20
|
-
/** The bytes32 the publisher hands createResource. Stable per manifest uid. */
|
|
21
|
-
export const uidHashFor = (ns, uid) => keccak256(stringToBytes(`${ns}:${uid}`));
|
|
22
|
-
|
|
23
|
-
/** What that uid becomes on-chain: keccak(publisher ++ uid), derived by the
|
|
24
|
-
* registry (`resource_id_of`) and reproduced here. Two publishers with the same
|
|
25
|
-
* uid get two different resources, which is what makes an id impossible to
|
|
26
|
-
* squat — and it means this derivation must match the contract exactly, or a
|
|
27
|
-
* publish uploads ciphertext to a key no on-chain resource points at.
|
|
28
|
-
*
|
|
29
|
-
* It lives here rather than in server/index.js because the BROWSER derives it
|
|
30
|
-
* too now (it names the R2 key it uploads ciphertext to) and the server derives
|
|
31
|
-
* it when minting the resource. Two copies that disagreed would put the bytes
|
|
32
|
-
* and the resource at different ids, and the file would be unbuyable. Pinned
|
|
33
|
-
* against the registry's own view in sond3r's server/index.js --selfcheck. */
|
|
34
|
-
export const resourceIdFor = (ns, owner, uid) => keccak256(concat([owner, uidHashFor(ns, uid)]));
|
|
35
|
-
|
|
36
|
-
export const NONCE_LEN = 12;
|
|
37
|
-
|
|
38
|
-
/** 64MiB — under Cloudflare's 100MB body cap with room for nonce/tag/headers. */
|
|
39
|
-
export const CHUNK_SIZE = 64 * 1024 * 1024;
|
|
40
|
-
|
|
41
|
-
/** R2 key for chunk `i`. Chunk 0 is the resourceId itself, so the sealed DEK
|
|
42
|
-
* lands exactly where the worker's /access gate looks for it and a small file
|
|
43
|
-
* is still a single object. Every buyer-side unpacker must match this. */
|
|
44
|
-
export const chunkKey = (resourceId, i) =>
|
|
45
|
-
i === 0 ? resourceId : keccak256(encodePacked(["bytes32", "uint32"], [resourceId, i]));
|
|
46
|
-
|
|
47
|
-
/** AES-GCM additional data: the chunk index, big-endian. MUST match src/pay/buy.js. */
|
|
48
|
-
export const aadFor = (i) => hexToBytes(numberToHex(i, { size: 4 }));
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Compress-then-encrypt: what gets sealed is `flag(1) || bytes`, flag 1 = gzip.
|
|
52
|
-
* ponytail: gzip only when it actually shrinks. mp4/webm/jpeg are already
|
|
53
|
-
* compressed and gzip *grows* them, so the flag makes the store-raw case the
|
|
54
|
-
* fallback instead of a 0.03% tax. MUST match unpack() in src/pay/stream.js.
|
|
55
|
-
*/
|
|
56
|
-
export async function pack(plain) {
|
|
57
|
-
const gz = new Uint8Array(await new Response(
|
|
58
|
-
new Response(plain).body.pipeThrough(new CompressionStream("gzip")),
|
|
59
|
-
).arrayBuffer());
|
|
60
|
-
const win = gz.length < plain.length;
|
|
61
|
-
const out = new Uint8Array((win ? gz.length : plain.length) + 1);
|
|
62
|
-
out[0] = win ? 1 : 0;
|
|
63
|
-
out.set(win ? gz : plain, 1);
|
|
64
|
-
return out;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* The inverse of pack(). It lives here, beside its inverse, because a packer and
|
|
69
|
-
* an unpacker in two repos is a format with two definitions — and the failure is
|
|
70
|
-
* not a crash but a file that uploads fine and is undecryptable forever.
|
|
71
|
-
*/
|
|
72
|
-
export async function unpack(bytes) {
|
|
73
|
-
if (bytes[0] === 0) return bytes.subarray(1);
|
|
74
|
-
// Not 0/1 means these bytes aren't packed at all — almost always ciphertext
|
|
75
|
-
// uploaded before the compression format landed. The publisher re-publishes;
|
|
76
|
-
// there is nothing the buyer can do.
|
|
77
|
-
if (bytes[0] !== 1) throw new Error(`unknown chunk encoding ${bytes[0]} — this file needs re-publishing`);
|
|
78
|
-
return new Uint8Array(await new Response(
|
|
79
|
-
new Response(bytes.subarray(1)).body.pipeThrough(new DecompressionStream("gzip")),
|
|
80
|
-
).arrayBuffer());
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/** GET the worker's static X25519 pubkey (what DEKs are sealed to). */
|
|
84
|
-
export async function getWorkerPubkey(workerUrl) {
|
|
85
|
-
const res = await fetch(`${workerUrl}/pubkey`);
|
|
86
|
-
if (!res.ok) throw new Error(`/pubkey failed: ${res.status}`);
|
|
87
|
-
const { pubkey } = await res.json();
|
|
88
|
-
return hexToBytes(pubkey);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* POST one already-encrypted chunk to the access worker's R2.
|
|
93
|
-
*
|
|
94
|
-
* `sealedDek` is omitted for objects that are the publisher's own state rather
|
|
95
|
-
* than something a buyer will pay for — the worker then writes no DEK object, so
|
|
96
|
-
* /access has nothing to release. See handleUpload in the worker.
|
|
97
|
-
*/
|
|
98
|
-
export async function putChunk({ workerUrl, uploadToken, key, body, sealedDek, immutable = false }) {
|
|
99
|
-
const res = await fetch(`${workerUrl}/upload/${key}`, {
|
|
100
|
-
method: "POST",
|
|
101
|
-
headers: {
|
|
102
|
-
"Content-Type": "application/octet-stream",
|
|
103
|
-
...(sealedDek ? { "X-Sealed-Dek": sealedDek } : {}),
|
|
104
|
-
// Only for a key that IS its content's digest. A resourceId is derived
|
|
105
|
-
// from (publisher, uid), so a re-publish rewrites it with new bytes
|
|
106
|
-
// under a new DEK, and an edge still serving the old ones hands every
|
|
107
|
-
// buyer ciphertext that decrypts to garbage. A shard named by its own
|
|
108
|
-
// sha256 cannot have that problem, and is the reason this flag exists.
|
|
109
|
-
...(immutable ? { "X-Immutable": "1" } : {}),
|
|
110
|
-
// The worker's upload gate. On a fresh publisher-owned worker the
|
|
111
|
-
// first request carrying this claims the bucket to it.
|
|
112
|
-
...(uploadToken ? { Authorization: `Bearer ${uploadToken}` } : {}),
|
|
113
|
-
},
|
|
114
|
-
body,
|
|
115
|
-
});
|
|
116
|
-
if (!res.ok) {
|
|
117
|
-
const text = await res.text();
|
|
118
|
-
// A quota refusal is the one upload failure a publisher can act on, so its
|
|
119
|
-
// message is passed through instead of buried in a URL and a status code.
|
|
120
|
-
const reason = (() => { try { return JSON.parse(text).error; } catch { return null; } })();
|
|
121
|
-
throw new Error(res.status === 413 && reason ? reason : `${workerUrl}/upload/${key}: ${res.status} ${text}`);
|
|
122
|
-
}
|
|
123
|
-
return res;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* Delete every chunk of a published resource, and its sealed DEK, from the
|
|
128
|
-
* worker. Returns the number of chunks it asked the worker to drop.
|
|
129
|
-
*
|
|
130
|
-
* The chunk count comes from the caller's manifest rather than from the worker,
|
|
131
|
-
* because the worker deliberately won't synthesize keys (see handleDelete in
|
|
132
|
-
* webworker/fangorn-access-worker) — the key derivation lives here, next to the
|
|
133
|
-
* upload that used it.
|
|
134
|
-
*
|
|
135
|
-
* Failures are RAISED, not swallowed. A delete that half-worked must not be
|
|
136
|
-
* reported as freed space: the operator is still paying for whatever is left,
|
|
137
|
-
* and silently crediting the publisher for it is how the storage ledger drifts
|
|
138
|
-
* away from the R2 bill.
|
|
139
|
-
*/
|
|
140
|
-
export async function deleteResource({ workerUrl, uploadToken, resourceId, chunks = 1 }) {
|
|
141
|
-
for (let i = 0; i < Math.max(1, chunks); i++) {
|
|
142
|
-
const res = await fetch(`${workerUrl}/upload/${chunkKey(resourceId, i)}`, {
|
|
143
|
-
method: "DELETE",
|
|
144
|
-
headers: uploadToken ? { Authorization: `Bearer ${uploadToken}` } : {},
|
|
145
|
-
});
|
|
146
|
-
// 404 is a worker too old to have the route; that's a real failure, since
|
|
147
|
-
// nothing was deleted and the caller is about to free the allowance.
|
|
148
|
-
if (!res.ok) throw new Error(`${workerUrl} refused to delete chunk ${i} of ${resourceId}: ${res.status} ${res.statusText}`);
|
|
149
|
-
}
|
|
150
|
-
return Math.max(1, chunks);
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
// ── self-check: `node src/publish/envelope.js` ───────────────────────────────────
|
|
154
|
-
//
|
|
155
|
-
// These vectors are PINNED to the values sond3r's own envelope.js produced before
|
|
156
|
-
// this file was extracted from it, with ns = "sond3r". They are not a style test:
|
|
157
|
-
// every resourceId ever minted by fangorn.tv is derived by this function, and a
|
|
158
|
-
// change here that shifts one byte makes ciphertext already in R2 unreachable from
|
|
159
|
-
// the resource anyone paid for. If this fails, the extraction broke money.
|
|
160
|
-
if (typeof process !== "undefined" && import.meta.url === `file://${process.argv[1]}` && process.argv[1].endsWith("/envelope.js")) {
|
|
161
|
-
const owner = `0x${"11".repeat(20)}`;
|
|
162
|
-
const uid = "Show/S1/a.mp4";
|
|
163
|
-
|
|
164
|
-
const h = uidHashFor("sond3r", uid);
|
|
165
|
-
if (h !== "0x855b20df257479ad7d5d5be0bcddc8c8554bff19edb33adb818872dd3d9e0d04") {
|
|
166
|
-
throw new Error(`uidHashFor drifted: ${h}`);
|
|
167
|
-
}
|
|
168
|
-
const r = resourceIdFor("sond3r", owner, uid);
|
|
169
|
-
if (r !== "0x0f919abdf691fae94b36395e67f7ed3301f0faea6027ffe609612656556a28a5") {
|
|
170
|
-
throw new Error(`resourceIdFor drifted: ${r}`);
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
// The namespace is what separates two apps' id spaces. Same owner, same uid,
|
|
174
|
-
// different app → different resource, or one app could mint over another's.
|
|
175
|
-
if (resourceIdFor("wiki", owner, uid) === r) throw new Error("ns does not reach the resourceId");
|
|
176
|
-
if (uidHashFor("wiki", uid) === h) throw new Error("ns does not reach the uid hash");
|
|
177
|
-
|
|
178
|
-
// Chunk 0 IS the resourceId — the worker's /access gate looks for the sealed
|
|
179
|
-
// DEK there and nowhere else.
|
|
180
|
-
if (chunkKey(r, 0) !== r) throw new Error("chunk 0 must be the resourceId itself");
|
|
181
|
-
if (chunkKey(r, 1) === r) throw new Error("chunk 1 collided with chunk 0");
|
|
182
|
-
if (aadFor(1).length !== 4) throw new Error("aad must be 4 bytes, big-endian");
|
|
183
|
-
|
|
184
|
-
console.log("envelope.js self-check ok — pinned sond3r ids, ns separation, chunk keys");
|
|
185
|
-
}
|
package/src/publish/manifest.js
DELETED
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
// The publisher's working library, kept in their own bucket.
|
|
2
|
-
//
|
|
3
|
-
// It records what a relay must never hold: the per-file price, description, and
|
|
4
|
-
// the stable `uid` that keeps a file's PAID identity across a rename. Storing it
|
|
5
|
-
// in the bucket rather than on the relay is what lets a library follow its
|
|
6
|
-
// publisher between machines, and what stops the relay from being the thing that
|
|
7
|
-
// remembers who sells what.
|
|
8
|
-
//
|
|
9
|
-
// It is a CACHE of something already public — the commit graph carries every
|
|
10
|
-
// published file's path, price, description and pointer — so an empty bucket is
|
|
11
|
-
// recoverable (`manifestFromTree`) rather than fatal.
|
|
12
|
-
//
|
|
13
|
-
// `ns` is the app's namespace and is NOT defaulted, for the same reason
|
|
14
|
-
// envelope.js refuses to default it: the key is derived from it, so a changed ns
|
|
15
|
-
// silently addresses a DIFFERENT manifest and the next publish re-mints every
|
|
16
|
-
// uid in a library that looks empty.
|
|
17
|
-
import { keccak256, stringToBytes } from "viem";
|
|
18
|
-
import { putChunk } from "./envelope.js";
|
|
19
|
-
|
|
20
|
-
/** R2 key for `owner`'s manifest under app `ns`. A bytes32, because that is the
|
|
21
|
-
* only key shape the worker accepts — see isObjectKey. */
|
|
22
|
-
export const manifestKey = (ns, owner) => keccak256(stringToBytes(`${ns}:manifest:${owner.toLowerCase()}`));
|
|
23
|
-
|
|
24
|
-
// A FUNCTION, not a constant. `{ ...EMPTY }` is a shallow copy — every caller
|
|
25
|
-
// would share one `files` object, so in any process that serves more than one
|
|
26
|
-
// publisher a first-publish read hands back the previous publisher's staged
|
|
27
|
-
// entries and the next write commits them to the wrong library.
|
|
28
|
-
const empty = () => ({ files: {} });
|
|
29
|
-
|
|
30
|
-
/** Read `owner`'s manifest back. A worker that has never seen one answers 404,
|
|
31
|
-
* which is the ordinary first-publish state, not an error. */
|
|
32
|
-
export async function readManifest({ ns, workerUrl, uploadToken, owner }) {
|
|
33
|
-
const res = await fetch(`${workerUrl}/upload/${manifestKey(ns, owner)}`, {
|
|
34
|
-
headers: uploadToken ? { Authorization: `Bearer ${uploadToken}` } : {},
|
|
35
|
-
});
|
|
36
|
-
if (res.status === 404) return empty();
|
|
37
|
-
if (!res.ok) throw new Error(`could not read your library manifest from ${workerUrl}: ${res.status} ${await res.text()}`);
|
|
38
|
-
try {
|
|
39
|
-
return JSON.parse(new TextDecoder().decode(await res.arrayBuffer()));
|
|
40
|
-
} catch {
|
|
41
|
-
// Better to say so than to hand back an empty manifest, which would look
|
|
42
|
-
// like an empty library and re-mint every uid on the next publish.
|
|
43
|
-
throw new Error(`your library manifest at ${workerUrl} is corrupt — it did not parse as JSON`);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export async function writeManifest({ ns, workerUrl, uploadToken, owner, manifest }) {
|
|
48
|
-
await putChunk({
|
|
49
|
-
workerUrl, uploadToken, key: manifestKey(ns, owner),
|
|
50
|
-
body: new TextEncoder().encode(JSON.stringify(manifest, null, 2)),
|
|
51
|
-
});
|
|
52
|
-
return manifest;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export const newUid = () => `${Date.now().toString(36)}${Math.random().toString(36).slice(2, 8)}`;
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Rebuild manifest entries from a publisher's own on-chain library tree.
|
|
59
|
-
*
|
|
60
|
-
* Two things it deliberately does not recover:
|
|
61
|
-
* - `uid`. resourceId is keccak(owner ++ keccak(ns+":"+uid)), which is one-way.
|
|
62
|
-
* It does not matter: identity is carried by `published.resourceId`, and every
|
|
63
|
-
* path that could re-derive an id prefers the recorded one. So a fresh uid on
|
|
64
|
-
* a recovered entry never changes what a buyer already paid for.
|
|
65
|
-
* - Unpublished files. They were never on-chain.
|
|
66
|
-
*/
|
|
67
|
-
export function manifestFromTree(files, { defaultPrice = "1000", newUid: uid = newUid } = {}) {
|
|
68
|
-
const out = {};
|
|
69
|
-
for (const n of files ?? []) {
|
|
70
|
-
if (!n?.path) continue;
|
|
71
|
-
out[n.path] = {
|
|
72
|
-
uid: uid(),
|
|
73
|
-
...(n.mime ? { mime: n.mime } : {}),
|
|
74
|
-
...(n.desc ? { desc: n.desc } : {}),
|
|
75
|
-
price: String(n.price ?? defaultPrice),
|
|
76
|
-
// No resourceId in the payload means a free catalog entry — that
|
|
77
|
-
// absence is the signal everywhere downstream, so it round-trips as
|
|
78
|
-
// `forSale: false` rather than as a price with nothing to buy.
|
|
79
|
-
...(n.resourceId
|
|
80
|
-
? {
|
|
81
|
-
published: {
|
|
82
|
-
resourceId: n.resourceId, workerUrl: n.workerUrl, plaintextHash: n.plaintextHash,
|
|
83
|
-
chunks: n.chunks ?? 1, size: n.size, chunkSize: n.chunkSize, mime: n.mime,
|
|
84
|
-
},
|
|
85
|
-
}
|
|
86
|
-
: { forSale: false }),
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
return out;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// ── self-check: `node src/publish/manifest.js` ───────────────────────────────────
|
|
93
|
-
if (import.meta.url === `file://${process.argv[1]}` && process.argv[1].endsWith("/manifest.js")) {
|
|
94
|
-
const assert = (c, m) => { if (!c) throw new Error(m); };
|
|
95
|
-
|
|
96
|
-
// PINNED. sond3r's manifests are already in R2 under this exact key; if this
|
|
97
|
-
// value moves, every existing publisher's library reads back as empty and the
|
|
98
|
-
// next publish re-mints every uid they own.
|
|
99
|
-
const owner = "0x147c24c5Ea2f1EE1ac42AD16820De23bBba45Ef6";
|
|
100
|
-
assert(manifestKey("sond3r", owner) === keccak256(stringToBytes(`sond3r:manifest:${owner.toLowerCase()}`)),
|
|
101
|
-
"the sond3r manifest key must not move");
|
|
102
|
-
assert(manifestKey("sond3r", owner) === manifestKey("sond3r", owner.toLowerCase()),
|
|
103
|
-
"address casing is not identity");
|
|
104
|
-
assert(manifestKey("sond3r", owner) !== manifestKey("other", owner),
|
|
105
|
-
"two apps must not share one manifest key");
|
|
106
|
-
|
|
107
|
-
// A 404 is the first-publish state, and it must not be confused with a read
|
|
108
|
-
// that failed — one returns an empty library, the other has to raise.
|
|
109
|
-
const real = globalThis.fetch;
|
|
110
|
-
try {
|
|
111
|
-
globalThis.fetch = async () => ({ status: 404 });
|
|
112
|
-
assert((await readManifest({ ns: "x", workerUrl: "http://w", owner })).files &&
|
|
113
|
-
Object.keys((await readManifest({ ns: "x", workerUrl: "http://w", owner })).files).length === 0,
|
|
114
|
-
"404 is an empty library");
|
|
115
|
-
globalThis.fetch = async () => ({ status: 500, ok: false, text: async () => "boom" });
|
|
116
|
-
await readManifest({ ns: "x", workerUrl: "http://w", owner }).then(
|
|
117
|
-
() => { throw new Error("a failed read must raise, not look empty"); },
|
|
118
|
-
(e) => assert(/could not read/.test(e.message), e.message));
|
|
119
|
-
globalThis.fetch = async () => ({ status: 200, ok: true, arrayBuffer: async () => new TextEncoder().encode("{not json").buffer });
|
|
120
|
-
await readManifest({ ns: "x", workerUrl: "http://w", owner }).then(
|
|
121
|
-
() => { throw new Error("corrupt JSON must raise — an empty manifest re-mints every uid"); },
|
|
122
|
-
(e) => assert(/corrupt/.test(e.message), e.message));
|
|
123
|
-
|
|
124
|
-
// The empty read must not be a shared object two callers can edit.
|
|
125
|
-
globalThis.fetch = async () => ({ status: 404 });
|
|
126
|
-
const a = await readManifest({ ns: "x", workerUrl: "http://w", owner });
|
|
127
|
-
a.files.poisoned = true;
|
|
128
|
-
assert(!(await readManifest({ ns: "x", workerUrl: "http://w", owner })).files.poisoned,
|
|
129
|
-
"the empty manifest must be a fresh object");
|
|
130
|
-
} finally { globalThis.fetch = real; }
|
|
131
|
-
|
|
132
|
-
// A tree with no resourceId is a free catalog entry, not a price with
|
|
133
|
-
// nothing behind it.
|
|
134
|
-
const built = manifestFromTree(
|
|
135
|
-
[{ path: "a.mp4", resourceId: "0xabc", chunks: 2, price: 500 }, { path: "b.txt" }, { bad: 1 }],
|
|
136
|
-
{ newUid: () => "uid" });
|
|
137
|
-
assert(Object.keys(built).length === 2, "a node with no path is not a file");
|
|
138
|
-
assert(built["a.mp4"].published.resourceId === "0xabc" && built["a.mp4"].price === "500", "a sold file keeps its pointer");
|
|
139
|
-
assert(built["b.txt"].forSale === false && !built["b.txt"].published, "no resourceId means a free catalog entry");
|
|
140
|
-
|
|
141
|
-
console.log("manifest.js self-check ok — key pinned + ns-scoped, 404 vs failure, corrupt read raises, free entries");
|
|
142
|
-
}
|