mppx 0.0.1 → 0.1.0
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/LICENSE +21 -0
- package/README.md +195 -0
- package/dist/BodyDigest.d.ts +42 -0
- package/dist/BodyDigest.d.ts.map +1 -0
- package/dist/BodyDigest.js +40 -0
- package/dist/BodyDigest.js.map +1 -0
- package/dist/Challenge.d.ts +271 -0
- package/dist/Challenge.d.ts.map +1 -0
- package/dist/Challenge.js +291 -0
- package/dist/Challenge.js.map +1 -0
- package/dist/Credential.d.ts +91 -0
- package/dist/Credential.d.ts.map +1 -0
- package/dist/Credential.js +122 -0
- package/dist/Credential.js.map +1 -0
- package/dist/Errors.d.ts +243 -0
- package/dist/Errors.d.ts.map +1 -0
- package/dist/Errors.js +201 -0
- package/dist/Errors.js.map +1 -0
- package/dist/Expires.d.ts +15 -0
- package/dist/Expires.d.ts.map +1 -0
- package/dist/Expires.js +29 -0
- package/dist/Expires.js.map +1 -0
- package/dist/Intent.d.ts +101 -0
- package/dist/Intent.d.ts.map +1 -0
- package/dist/Intent.js +83 -0
- package/dist/Intent.js.map +1 -0
- package/dist/Mcp.d.ts +74 -0
- package/dist/Mcp.d.ts.map +1 -0
- package/dist/Mcp.js +9 -0
- package/dist/Mcp.js.map +1 -0
- package/dist/MethodIntent.d.ts +225 -0
- package/dist/MethodIntent.d.ts.map +1 -0
- package/dist/MethodIntent.js +156 -0
- package/dist/MethodIntent.js.map +1 -0
- package/dist/PaymentRequest.d.ts +88 -0
- package/dist/PaymentRequest.d.ts.map +1 -0
- package/dist/PaymentRequest.js +81 -0
- package/dist/PaymentRequest.js.map +1 -0
- package/dist/Receipt.d.ts +110 -0
- package/dist/Receipt.d.ts.map +1 -0
- package/dist/Receipt.js +105 -0
- package/dist/Receipt.js.map +1 -0
- package/dist/Store.d.ts +28 -0
- package/dist/Store.d.ts.map +1 -0
- package/dist/Store.js +61 -0
- package/dist/Store.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +1219 -0
- package/dist/cli.js.map +1 -0
- package/dist/client/Methods.d.ts +4 -0
- package/dist/client/Methods.d.ts.map +1 -0
- package/dist/client/Methods.js +4 -0
- package/dist/client/Methods.js.map +1 -0
- package/dist/client/Mppx.d.ts +84 -0
- package/dist/client/Mppx.d.ts.map +1 -0
- package/dist/client/Mppx.js +64 -0
- package/dist/client/Mppx.js.map +1 -0
- package/dist/client/Transport.d.ts +56 -0
- package/dist/client/Transport.d.ts.map +1 -0
- package/dist/client/Transport.js +81 -0
- package/dist/client/Transport.js.map +1 -0
- package/dist/client/index.d.ts +5 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +5 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/internal/Fetch.d.ts +85 -0
- package/dist/client/internal/Fetch.d.ts.map +1 -0
- package/dist/client/internal/Fetch.js +95 -0
- package/dist/client/internal/Fetch.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/types.d.ts +302 -0
- package/dist/internal/types.d.ts.map +1 -0
- package/dist/internal/types.js +2 -0
- package/dist/internal/types.js.map +1 -0
- package/dist/mcp-sdk/client/McpClient.d.ts +78 -0
- package/dist/mcp-sdk/client/McpClient.d.ts.map +1 -0
- package/dist/mcp-sdk/client/McpClient.js +98 -0
- package/dist/mcp-sdk/client/McpClient.js.map +1 -0
- package/dist/mcp-sdk/client/index.d.ts +3 -0
- package/dist/mcp-sdk/client/index.d.ts.map +1 -0
- package/dist/mcp-sdk/client/index.js +3 -0
- package/dist/mcp-sdk/client/index.js.map +1 -0
- package/dist/mcp-sdk/server/Transport.d.ts +43 -0
- package/dist/mcp-sdk/server/Transport.d.ts.map +1 -0
- package/dist/mcp-sdk/server/Transport.js +71 -0
- package/dist/mcp-sdk/server/Transport.js.map +1 -0
- package/dist/mcp-sdk/server/index.d.ts +2 -0
- package/dist/mcp-sdk/server/index.d.ts.map +1 -0
- package/dist/mcp-sdk/server/index.js +2 -0
- package/dist/mcp-sdk/server/index.js.map +1 -0
- package/dist/middlewares/elysia.d.ts +51 -0
- package/dist/middlewares/elysia.d.ts.map +1 -0
- package/dist/middlewares/elysia.js +59 -0
- package/dist/middlewares/elysia.js.map +1 -0
- package/dist/middlewares/express.d.ts +46 -0
- package/dist/middlewares/express.d.ts.map +1 -0
- package/dist/middlewares/express.js +69 -0
- package/dist/middlewares/express.js.map +1 -0
- package/dist/middlewares/hono.d.ts +46 -0
- package/dist/middlewares/hono.d.ts.map +1 -0
- package/dist/middlewares/hono.js +57 -0
- package/dist/middlewares/hono.js.map +1 -0
- package/dist/middlewares/internal/mppx.d.ts +16 -0
- package/dist/middlewares/internal/mppx.d.ts.map +1 -0
- package/dist/middlewares/internal/mppx.js +16 -0
- package/dist/middlewares/internal/mppx.js.map +1 -0
- package/dist/middlewares/nextjs.d.ts +45 -0
- package/dist/middlewares/nextjs.d.ts.map +1 -0
- package/dist/middlewares/nextjs.js +57 -0
- package/dist/middlewares/nextjs.js.map +1 -0
- package/dist/proxy/Proxy.d.ts +47 -0
- package/dist/proxy/Proxy.d.ts.map +1 -0
- package/dist/proxy/Proxy.js +126 -0
- package/dist/proxy/Proxy.js.map +1 -0
- package/dist/proxy/Service.d.ts +100 -0
- package/dist/proxy/Service.d.ts.map +1 -0
- package/dist/proxy/Service.js +147 -0
- package/dist/proxy/Service.js.map +1 -0
- package/dist/proxy/index.d.ts +7 -0
- package/dist/proxy/index.d.ts.map +1 -0
- package/dist/proxy/index.js +7 -0
- package/dist/proxy/index.js.map +1 -0
- package/dist/proxy/internal/Headers.d.ts +3 -0
- package/dist/proxy/internal/Headers.d.ts.map +1 -0
- package/dist/proxy/internal/Headers.js +41 -0
- package/dist/proxy/internal/Headers.js.map +1 -0
- package/dist/proxy/internal/Route.d.ts +14 -0
- package/dist/proxy/internal/Route.d.ts.map +1 -0
- package/dist/proxy/internal/Route.js +47 -0
- package/dist/proxy/internal/Route.js.map +1 -0
- package/dist/proxy/services/anthropic.d.ts +29 -0
- package/dist/proxy/services/anthropic.d.ts.map +1 -0
- package/dist/proxy/services/anthropic.js +30 -0
- package/dist/proxy/services/anthropic.js.map +1 -0
- package/dist/proxy/services/openai.d.ts +29 -0
- package/dist/proxy/services/openai.d.ts.map +1 -0
- package/dist/proxy/services/openai.js +30 -0
- package/dist/proxy/services/openai.js.map +1 -0
- package/dist/proxy/services/stripe.d.ts +29 -0
- package/dist/proxy/services/stripe.d.ts.map +1 -0
- package/dist/proxy/services/stripe.js +30 -0
- package/dist/proxy/services/stripe.js.map +1 -0
- package/dist/server/Methods.d.ts +3 -0
- package/dist/server/Methods.d.ts.map +1 -0
- package/dist/server/Methods.js +3 -0
- package/dist/server/Methods.js.map +1 -0
- package/dist/server/Mppx.d.ts +116 -0
- package/dist/server/Mppx.d.ts.map +1 -0
- package/dist/server/Mppx.js +207 -0
- package/dist/server/Mppx.js.map +1 -0
- package/dist/server/NodeListener.d.ts +3 -0
- package/dist/server/NodeListener.d.ts.map +1 -0
- package/dist/server/NodeListener.js +3 -0
- package/dist/server/NodeListener.js.map +1 -0
- package/dist/server/Request.d.ts +24 -0
- package/dist/server/Request.d.ts.map +1 -0
- package/dist/server/Request.js +26 -0
- package/dist/server/Request.js.map +1 -0
- package/dist/server/Response.d.ts +10 -0
- package/dist/server/Response.d.ts.map +1 -0
- package/dist/server/Response.js +15 -0
- package/dist/server/Response.js.map +1 -0
- package/dist/server/Transport.d.ts +93 -0
- package/dist/server/Transport.d.ts.map +1 -0
- package/dist/server/Transport.js +132 -0
- package/dist/server/Transport.js.map +1 -0
- package/dist/server/index.d.ts +9 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +9 -0
- package/dist/server/index.js.map +1 -0
- package/dist/stripe/Intents.d.ts +54 -0
- package/dist/stripe/Intents.d.ts.map +1 -0
- package/dist/stripe/Intents.js +27 -0
- package/dist/stripe/Intents.js.map +1 -0
- package/dist/stripe/client/Charge.d.ts +114 -0
- package/dist/stripe/client/Charge.d.ts.map +1 -0
- package/dist/stripe/client/Charge.js +77 -0
- package/dist/stripe/client/Charge.js.map +1 -0
- package/dist/stripe/client/MethodIntents.d.ts +80 -0
- package/dist/stripe/client/MethodIntents.d.ts.map +1 -0
- package/dist/stripe/client/MethodIntents.js +34 -0
- package/dist/stripe/client/MethodIntents.js.map +1 -0
- package/dist/stripe/client/index.d.ts +3 -0
- package/dist/stripe/client/index.d.ts.map +1 -0
- package/dist/stripe/client/index.js +3 -0
- package/dist/stripe/client/index.js.map +1 -0
- package/dist/stripe/index.d.ts +2 -0
- package/dist/stripe/index.d.ts.map +1 -0
- package/dist/stripe/index.js +2 -0
- package/dist/stripe/index.js.map +1 -0
- package/dist/stripe/server/Charge.d.ts +74 -0
- package/dist/stripe/server/Charge.d.ts.map +1 -0
- package/dist/stripe/server/Charge.js +79 -0
- package/dist/stripe/server/Charge.js.map +1 -0
- package/dist/stripe/server/MethodIntents.d.ts +65 -0
- package/dist/stripe/server/MethodIntents.d.ts.map +1 -0
- package/dist/stripe/server/MethodIntents.js +21 -0
- package/dist/stripe/server/MethodIntents.js.map +1 -0
- package/dist/stripe/server/index.d.ts +3 -0
- package/dist/stripe/server/index.d.ts.map +1 -0
- package/dist/stripe/server/index.js +3 -0
- package/dist/stripe/server/index.js.map +1 -0
- package/dist/tempo/Attribution.d.ts +101 -0
- package/dist/tempo/Attribution.d.ts.map +1 -0
- package/dist/tempo/Attribution.js +124 -0
- package/dist/tempo/Attribution.js.map +1 -0
- package/dist/tempo/Intents.d.ts +132 -0
- package/dist/tempo/Intents.d.ts.map +1 -0
- package/dist/tempo/Intents.js +81 -0
- package/dist/tempo/Intents.js.map +1 -0
- package/dist/tempo/client/ChannelOps.d.ts +54 -0
- package/dist/tempo/client/ChannelOps.d.ts.map +1 -0
- package/dist/tempo/client/ChannelOps.js +138 -0
- package/dist/tempo/client/ChannelOps.js.map +1 -0
- package/dist/tempo/client/Charge.d.ts +76 -0
- package/dist/tempo/client/Charge.d.ts.map +1 -0
- package/dist/tempo/client/Charge.js +69 -0
- package/dist/tempo/client/Charge.js.map +1 -0
- package/dist/tempo/client/MethodIntents.d.ts +157 -0
- package/dist/tempo/client/MethodIntents.d.ts.map +1 -0
- package/dist/tempo/client/MethodIntents.js +25 -0
- package/dist/tempo/client/MethodIntents.js.map +1 -0
- package/dist/tempo/client/Session.d.ts +159 -0
- package/dist/tempo/client/Session.d.ts.map +1 -0
- package/dist/tempo/client/Session.js +263 -0
- package/dist/tempo/client/Session.js.map +1 -0
- package/dist/tempo/client/SessionManager.d.ts +62 -0
- package/dist/tempo/client/SessionManager.d.ts.map +1 -0
- package/dist/tempo/client/SessionManager.js +196 -0
- package/dist/tempo/client/SessionManager.js.map +1 -0
- package/dist/tempo/client/index.d.ts +6 -0
- package/dist/tempo/client/index.d.ts.map +1 -0
- package/dist/tempo/client/index.js +5 -0
- package/dist/tempo/client/index.js.map +1 -0
- package/dist/tempo/index.d.ts +3 -0
- package/dist/tempo/index.d.ts.map +1 -0
- package/dist/tempo/index.js +3 -0
- package/dist/tempo/index.js.map +1 -0
- package/dist/tempo/internal/account.d.ts +32 -0
- package/dist/tempo/internal/account.d.ts.map +1 -0
- package/dist/tempo/internal/account.js +33 -0
- package/dist/tempo/internal/account.js.map +1 -0
- package/dist/tempo/internal/defaults.d.ts +18 -0
- package/dist/tempo/internal/defaults.d.ts.map +1 -0
- package/dist/tempo/internal/defaults.js +18 -0
- package/dist/tempo/internal/defaults.js.map +1 -0
- package/dist/tempo/internal/types.d.ts +11 -0
- package/dist/tempo/internal/types.d.ts.map +1 -0
- package/dist/tempo/internal/types.js +2 -0
- package/dist/tempo/internal/types.js.map +1 -0
- package/dist/tempo/server/Charge.d.ts +77 -0
- package/dist/tempo/server/Charge.d.ts.map +1 -0
- package/dist/tempo/server/Charge.js +228 -0
- package/dist/tempo/server/Charge.js.map +1 -0
- package/dist/tempo/server/MethodIntents.d.ts +140 -0
- package/dist/tempo/server/MethodIntents.d.ts.map +1 -0
- package/dist/tempo/server/MethodIntents.js +26 -0
- package/dist/tempo/server/MethodIntents.js.map +1 -0
- package/dist/tempo/server/Session.d.ts +148 -0
- package/dist/tempo/server/Session.d.ts.map +1 -0
- package/dist/tempo/server/Session.js +529 -0
- package/dist/tempo/server/Session.js.map +1 -0
- package/dist/tempo/server/internal/transport.d.ts +47 -0
- package/dist/tempo/server/internal/transport.d.ts.map +1 -0
- package/dist/tempo/server/internal/transport.js +118 -0
- package/dist/tempo/server/internal/transport.js.map +1 -0
- package/dist/tempo/stream/Chain.d.ts +52 -0
- package/dist/tempo/stream/Chain.d.ts.map +1 -0
- package/dist/tempo/stream/Chain.js +215 -0
- package/dist/tempo/stream/Chain.js.map +1 -0
- package/dist/tempo/stream/Channel.d.ts +26 -0
- package/dist/tempo/stream/Channel.d.ts.map +1 -0
- package/dist/tempo/stream/Channel.js +27 -0
- package/dist/tempo/stream/Channel.js.map +1 -0
- package/dist/tempo/stream/ChannelStore.d.ts +103 -0
- package/dist/tempo/stream/ChannelStore.d.ts.map +1 -0
- package/dist/tempo/stream/ChannelStore.js +100 -0
- package/dist/tempo/stream/ChannelStore.js.map +1 -0
- package/dist/tempo/stream/Receipt.d.ts +22 -0
- package/dist/tempo/stream/Receipt.d.ts.map +1 -0
- package/dist/tempo/stream/Receipt.js +34 -0
- package/dist/tempo/stream/Receipt.js.map +1 -0
- package/dist/tempo/stream/Sse.d.ts +134 -0
- package/dist/tempo/stream/Sse.d.ts.map +1 -0
- package/dist/tempo/stream/Sse.js +288 -0
- package/dist/tempo/stream/Sse.js.map +1 -0
- package/dist/tempo/stream/Types.d.ts +78 -0
- package/dist/tempo/stream/Types.d.ts.map +1 -0
- package/dist/tempo/stream/Types.js +2 -0
- package/dist/tempo/stream/Types.js.map +1 -0
- package/dist/tempo/stream/Voucher.d.ts +20 -0
- package/dist/tempo/stream/Voucher.d.ts.map +1 -0
- package/dist/tempo/stream/Voucher.js +98 -0
- package/dist/tempo/stream/Voucher.js.map +1 -0
- package/dist/tempo/stream/escrow.abi.d.ts +598 -0
- package/dist/tempo/stream/escrow.abi.d.ts.map +1 -0
- package/dist/tempo/stream/escrow.abi.js +760 -0
- package/dist/tempo/stream/escrow.abi.js.map +1 -0
- package/dist/tempo/stream/index.d.ts +8 -0
- package/dist/tempo/stream/index.d.ts.map +1 -0
- package/dist/tempo/stream/index.js +8 -0
- package/dist/tempo/stream/index.js.map +1 -0
- package/dist/viem/Account.d.ts +12 -0
- package/dist/viem/Account.d.ts.map +1 -0
- package/dist/viem/Account.js +14 -0
- package/dist/viem/Account.js.map +1 -0
- package/dist/viem/Client.d.ts +21 -0
- package/dist/viem/Client.d.ts.map +1 -0
- package/dist/viem/Client.js +19 -0
- package/dist/viem/Client.js.map +1 -0
- package/dist/zod.d.ts +17 -0
- package/dist/zod.d.ts.map +1 -0
- package/dist/zod.js +35 -0
- package/dist/zod.js.map +1 -0
- package/package.json +117 -4
- package/src/BodyDigest.test.ts +43 -0
- package/src/BodyDigest.ts +53 -0
- package/src/Challenge.test-d.ts +81 -0
- package/src/Challenge.test.ts +414 -0
- package/src/Challenge.ts +429 -0
- package/src/Credential.test.ts +227 -0
- package/src/Credential.ts +154 -0
- package/src/Errors.test.ts +402 -0
- package/src/Errors.ts +348 -0
- package/src/Expires.ts +34 -0
- package/src/Intent.test.ts +180 -0
- package/src/Intent.ts +109 -0
- package/src/Mcp.ts +81 -0
- package/src/MethodIntent.test.ts +303 -0
- package/src/MethodIntent.ts +388 -0
- package/src/PaymentRequest.test.ts +152 -0
- package/src/PaymentRequest.ts +107 -0
- package/src/Receipt.test.ts +98 -0
- package/src/Receipt.ts +129 -0
- package/src/Store.ts +84 -0
- package/src/cli.test.ts +542 -0
- package/src/cli.ts +1319 -0
- package/src/client/Methods.ts +3 -0
- package/src/client/Mppx.test-d.ts +90 -0
- package/src/client/Mppx.test.ts +468 -0
- package/src/client/Mppx.ts +149 -0
- package/src/client/Transport.test.ts +283 -0
- package/src/client/Transport.ts +115 -0
- package/src/client/index.ts +4 -0
- package/src/client/internal/Fetch.test-d.ts +57 -0
- package/src/client/internal/Fetch.test.ts +281 -0
- package/src/client/internal/Fetch.ts +157 -0
- package/src/env.d.ts +11 -0
- package/src/index.ts +12 -0
- package/src/internal/types.ts +403 -0
- package/src/mcp-sdk/client/McpClient.test-d.ts +109 -0
- package/src/mcp-sdk/client/McpClient.test.ts +219 -0
- package/src/mcp-sdk/client/McpClient.ts +187 -0
- package/src/mcp-sdk/client/index.ts +2 -0
- package/src/mcp-sdk/server/Transport.ts +94 -0
- package/src/mcp-sdk/server/index.ts +1 -0
- package/src/middlewares/elysia.ts +66 -0
- package/src/middlewares/express.test.ts +155 -0
- package/src/middlewares/express.ts +82 -0
- package/src/middlewares/hono.test.ts +148 -0
- package/src/middlewares/hono.ts +62 -0
- package/src/middlewares/internal/mppx.ts +30 -0
- package/src/middlewares/nextjs.test.ts +164 -0
- package/src/middlewares/nextjs.ts +66 -0
- package/src/proxy/Proxy.test.ts +472 -0
- package/src/proxy/Proxy.ts +175 -0
- package/src/proxy/Service.test.ts +125 -0
- package/src/proxy/Service.ts +227 -0
- package/src/proxy/index.ts +6 -0
- package/src/proxy/internal/Headers.test.ts +100 -0
- package/src/proxy/internal/Headers.ts +40 -0
- package/src/proxy/internal/Route.test.ts +143 -0
- package/src/proxy/internal/Route.ts +54 -0
- package/src/proxy/services/anthropic.ts +45 -0
- package/src/proxy/services/openai.test.ts +97 -0
- package/src/proxy/services/openai.ts +48 -0
- package/src/proxy/services/stripe.ts +49 -0
- package/src/server/Methods.ts +2 -0
- package/src/server/Mppx.test-d.ts +343 -0
- package/src/server/Mppx.test.ts +342 -0
- package/src/server/Mppx.ts +378 -0
- package/src/server/NodeListener.test.ts +188 -0
- package/src/server/NodeListener.ts +3 -0
- package/src/server/Request.test.ts +102 -0
- package/src/server/Request.ts +33 -0
- package/src/server/Response.test.ts +31 -0
- package/src/server/Response.ts +27 -0
- package/src/server/Transport.test.ts +294 -0
- package/src/server/Transport.ts +222 -0
- package/src/server/index.ts +8 -0
- package/src/stripe/Charge.integration.test.ts +326 -0
- package/src/stripe/Intents.test.ts +52 -0
- package/src/stripe/Intents.ts +27 -0
- package/src/stripe/client/Charge.ts +119 -0
- package/src/stripe/client/MethodIntents.ts +37 -0
- package/src/stripe/client/index.ts +2 -0
- package/src/stripe/index.ts +1 -0
- package/src/stripe/server/Charge.ts +121 -0
- package/src/stripe/server/MethodIntents.ts +24 -0
- package/src/stripe/server/index.ts +2 -0
- package/src/tempo/Attribution.test.ts +187 -0
- package/src/tempo/Attribution.ts +156 -0
- package/src/tempo/Intents.test.ts +84 -0
- package/src/tempo/Intents.ts +93 -0
- package/src/tempo/client/ChannelOps.ts +233 -0
- package/src/tempo/client/Charge.ts +84 -0
- package/src/tempo/client/MethodIntents.ts +28 -0
- package/src/tempo/client/Session.ts +369 -0
- package/src/tempo/client/SessionManager.test.ts +223 -0
- package/src/tempo/client/SessionManager.ts +270 -0
- package/src/tempo/client/index.ts +5 -0
- package/src/tempo/index.ts +2 -0
- package/src/tempo/internal/account.ts +47 -0
- package/src/tempo/internal/defaults.ts +20 -0
- package/src/tempo/internal/types.ts +8 -0
- package/src/tempo/server/Charge.test.ts +847 -0
- package/src/tempo/server/Charge.ts +309 -0
- package/src/tempo/server/MethodIntents.ts +29 -0
- package/src/tempo/server/Session.test.ts +1349 -0
- package/src/tempo/server/Session.ts +773 -0
- package/src/tempo/server/Sse.test.ts +289 -0
- package/src/tempo/server/index.ts +5 -0
- package/src/tempo/server/internal/transport.ts +153 -0
- package/src/tempo/stream/Chain.ts +333 -0
- package/src/tempo/stream/Channel.ts +50 -0
- package/src/tempo/stream/ChannelStore.test.ts +473 -0
- package/src/tempo/stream/ChannelStore.ts +202 -0
- package/src/tempo/stream/Receipt.test.ts +84 -0
- package/src/tempo/stream/Receipt.ts +45 -0
- package/src/tempo/stream/Sse.test.ts +401 -0
- package/src/tempo/stream/Sse.ts +375 -0
- package/src/tempo/stream/Types.ts +86 -0
- package/src/tempo/stream/Voucher.test.ts +134 -0
- package/src/tempo/stream/Voucher.ts +123 -0
- package/src/tempo/stream/escrow.abi.ts +759 -0
- package/src/tempo/stream/index.ts +7 -0
- package/src/tsconfig.json +10 -0
- package/src/viem/Account.test.ts +71 -0
- package/src/viem/Account.ts +30 -0
- package/src/viem/Client.test.ts +58 -0
- package/src/viem/Client.ts +33 -0
- package/src/zod.ts +47 -0
package/src/Errors.ts
ADDED
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base class for all payment-related errors.
|
|
3
|
+
*/
|
|
4
|
+
export abstract class PaymentError extends Error {
|
|
5
|
+
/** RFC 9457 Problem Details type URI. */
|
|
6
|
+
abstract readonly type: string
|
|
7
|
+
|
|
8
|
+
/** HTTP status code. */
|
|
9
|
+
readonly status: number = 402
|
|
10
|
+
|
|
11
|
+
/** Converts the error to RFC 9457 Problem Details format. */
|
|
12
|
+
toProblemDetails(challengeId?: string): PaymentError.ProblemDetails {
|
|
13
|
+
return {
|
|
14
|
+
type: this.type,
|
|
15
|
+
title: this.name,
|
|
16
|
+
status: this.status,
|
|
17
|
+
detail: this.message,
|
|
18
|
+
...(challengeId && { challengeId }),
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export declare namespace PaymentError {
|
|
24
|
+
type ProblemDetails = {
|
|
25
|
+
/** RFC 9457 Problem Details type URI. */
|
|
26
|
+
type: string
|
|
27
|
+
/** Human-readable summary. */
|
|
28
|
+
title: string
|
|
29
|
+
/** HTTP status code. */
|
|
30
|
+
status: number
|
|
31
|
+
/** Human-readable explanation. */
|
|
32
|
+
detail: string
|
|
33
|
+
/** Associated challenge ID, if applicable. */
|
|
34
|
+
challengeId?: string
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Credential is malformed (invalid base64url, bad JSON structure).
|
|
40
|
+
*/
|
|
41
|
+
export class MalformedCredentialError extends PaymentError {
|
|
42
|
+
override readonly name = 'MalformedCredentialError'
|
|
43
|
+
readonly type = 'https://tempoxyz.github.io/payment-auth-spec/problems/malformed-credential'
|
|
44
|
+
|
|
45
|
+
constructor(options: MalformedCredentialError.Options = {}) {
|
|
46
|
+
const { reason } = options
|
|
47
|
+
super(reason ? `Credential is malformed: ${reason}.` : 'Credential is malformed.')
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export declare namespace MalformedCredentialError {
|
|
52
|
+
type Options = {
|
|
53
|
+
/** Reason the credential is malformed (e.g., "invalid base64url", "invalid JSON"). */
|
|
54
|
+
reason?: string
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Challenge ID is unknown, expired, or already used.
|
|
60
|
+
*/
|
|
61
|
+
export class InvalidChallengeError extends PaymentError {
|
|
62
|
+
override readonly name = 'InvalidChallengeError'
|
|
63
|
+
readonly type = 'https://tempoxyz.github.io/payment-auth-spec/problems/invalid-challenge'
|
|
64
|
+
|
|
65
|
+
constructor(options: InvalidChallengeError.Options = {}) {
|
|
66
|
+
const { id, reason } = options
|
|
67
|
+
const idPart = id ? ` "${id}"` : ''
|
|
68
|
+
const reasonPart = reason ? `: ${reason}` : ''
|
|
69
|
+
super(`Challenge${idPart} is invalid${reasonPart}.`)
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export declare namespace InvalidChallengeError {
|
|
74
|
+
type Options = {
|
|
75
|
+
/** The invalid challenge ID. */
|
|
76
|
+
id?: string
|
|
77
|
+
/** Reason the challenge is invalid (e.g., "expired", "already used", "unknown"). */
|
|
78
|
+
reason?: string
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Payment proof is invalid or verification failed.
|
|
84
|
+
*/
|
|
85
|
+
export class VerificationFailedError extends PaymentError {
|
|
86
|
+
override readonly name = 'VerificationFailedError'
|
|
87
|
+
readonly type = 'https://tempoxyz.github.io/payment-auth-spec/problems/verification-failed'
|
|
88
|
+
|
|
89
|
+
constructor(options: VerificationFailedError.Options = {}) {
|
|
90
|
+
const { reason } = options
|
|
91
|
+
super(reason ? `Payment verification failed: ${reason}.` : 'Payment verification failed.')
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export declare namespace VerificationFailedError {
|
|
96
|
+
type Options = {
|
|
97
|
+
/** Reason verification failed (e.g., "invalid signature", "insufficient amount"). */
|
|
98
|
+
reason?: string
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Payment requires additional action (e.g., 3DS authentication).
|
|
104
|
+
*/
|
|
105
|
+
export class PaymentActionRequiredError extends PaymentError {
|
|
106
|
+
override readonly name = 'PaymentActionRequiredError'
|
|
107
|
+
readonly type = 'https://tempoxyz.github.io/payment-auth-spec/problems/payment-action-required'
|
|
108
|
+
|
|
109
|
+
constructor(options: PaymentActionRequiredError.Options = {}) {
|
|
110
|
+
const { reason } = options
|
|
111
|
+
super(reason ? `Payment requires action: ${reason}.` : 'Payment requires action.')
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export declare namespace PaymentActionRequiredError {
|
|
116
|
+
type Options = {
|
|
117
|
+
/** Reason action is required (e.g., "requires_action"). */
|
|
118
|
+
reason?: string
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Payment has expired.
|
|
124
|
+
*/
|
|
125
|
+
export class PaymentExpiredError extends PaymentError {
|
|
126
|
+
override readonly name = 'PaymentExpiredError'
|
|
127
|
+
readonly type = 'https://tempoxyz.github.io/payment-auth-spec/problems/payment-expired'
|
|
128
|
+
|
|
129
|
+
constructor(options: PaymentExpiredError.Options = {}) {
|
|
130
|
+
const { expires } = options
|
|
131
|
+
super(expires ? `Payment expired at ${expires}.` : 'Payment has expired.')
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export declare namespace PaymentExpiredError {
|
|
136
|
+
type Options = {
|
|
137
|
+
/** ISO 8601 expiration timestamp. */
|
|
138
|
+
expires?: string
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* No credential was provided but payment is required.
|
|
144
|
+
*/
|
|
145
|
+
export class PaymentRequiredError extends PaymentError {
|
|
146
|
+
override readonly name = 'PaymentRequiredError'
|
|
147
|
+
readonly type = 'https://tempoxyz.github.io/payment-auth-spec/problems/payment-required'
|
|
148
|
+
|
|
149
|
+
constructor(options: PaymentRequiredError.Options = {}) {
|
|
150
|
+
const { description, realm } = options
|
|
151
|
+
const parts = ['Payment is required']
|
|
152
|
+
if (realm) parts.push(`for "${realm}"`)
|
|
153
|
+
if (description) parts.push(`(${description})`)
|
|
154
|
+
super(`${parts.join(' ')}.`)
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export declare namespace PaymentRequiredError {
|
|
159
|
+
type Options = {
|
|
160
|
+
/** Human-readable description of the payment. */
|
|
161
|
+
description?: string | undefined
|
|
162
|
+
/** Server realm (e.g., hostname). */
|
|
163
|
+
realm?: string | undefined
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Credential payload does not match the expected schema.
|
|
169
|
+
*/
|
|
170
|
+
export class InvalidPayloadError extends PaymentError {
|
|
171
|
+
override readonly name = 'InvalidPayloadError'
|
|
172
|
+
readonly type = 'https://tempoxyz.github.io/payment-auth-spec/problems/invalid-payload'
|
|
173
|
+
|
|
174
|
+
constructor(options: InvalidPayloadError.Options = {}) {
|
|
175
|
+
const { reason } = options
|
|
176
|
+
super(reason ? `Credential payload is invalid: ${reason}.` : 'Credential payload is invalid.')
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export declare namespace InvalidPayloadError {
|
|
181
|
+
type Options = {
|
|
182
|
+
/** Reason the payload is invalid (e.g., "missing signature field"). */
|
|
183
|
+
reason?: string
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Request is malformed or contains invalid parameters.
|
|
189
|
+
*/
|
|
190
|
+
export class BadRequestError extends PaymentError {
|
|
191
|
+
override readonly name = 'BadRequestError'
|
|
192
|
+
override readonly status = 400
|
|
193
|
+
readonly type = 'https://tempoxyz.github.io/payment-auth-spec/problems/bad-request'
|
|
194
|
+
|
|
195
|
+
constructor(options: BadRequestError.Options = {}) {
|
|
196
|
+
const { reason } = options
|
|
197
|
+
super(reason ? `Bad request: ${reason}.` : 'Bad request.')
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export declare namespace BadRequestError {
|
|
202
|
+
type Options = {
|
|
203
|
+
/** Reason the request is invalid. */
|
|
204
|
+
reason?: string
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Insufficient balance in the payment channel.
|
|
210
|
+
*/
|
|
211
|
+
export class InsufficientBalanceError extends PaymentError {
|
|
212
|
+
override readonly name = 'InsufficientBalanceError'
|
|
213
|
+
override readonly status = 402
|
|
214
|
+
readonly type = 'https://paymentauth.org/problems/stream/insufficient-balance'
|
|
215
|
+
|
|
216
|
+
constructor(options: InsufficientBalanceError.Options = {}) {
|
|
217
|
+
const { reason } = options
|
|
218
|
+
super(reason ? `Insufficient balance: ${reason}.` : 'Insufficient balance.')
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export declare namespace InsufficientBalanceError {
|
|
223
|
+
type Options = {
|
|
224
|
+
/** Reason for insufficient balance. */
|
|
225
|
+
reason?: string
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Voucher or close request signature is invalid.
|
|
231
|
+
*/
|
|
232
|
+
export class InvalidSignatureError extends PaymentError {
|
|
233
|
+
override readonly name = 'InvalidSignatureError'
|
|
234
|
+
override readonly status = 402
|
|
235
|
+
readonly type = 'https://paymentauth.org/problems/stream/invalid-signature'
|
|
236
|
+
|
|
237
|
+
constructor(options: InvalidSignatureError.Options = {}) {
|
|
238
|
+
const { reason } = options
|
|
239
|
+
super(reason ? `Invalid signature: ${reason}.` : 'Invalid signature.')
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
export declare namespace InvalidSignatureError {
|
|
244
|
+
type Options = {
|
|
245
|
+
reason?: string
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Recovered signer is not authorized for this channel.
|
|
251
|
+
*/
|
|
252
|
+
export class SignerMismatchError extends PaymentError {
|
|
253
|
+
override readonly name = 'SignerMismatchError'
|
|
254
|
+
override readonly status = 402
|
|
255
|
+
readonly type = 'https://paymentauth.org/problems/stream/signer-mismatch'
|
|
256
|
+
|
|
257
|
+
constructor(options: SignerMismatchError.Options = {}) {
|
|
258
|
+
const { reason } = options
|
|
259
|
+
super(reason ? `Signer mismatch: ${reason}.` : 'Signer is not authorized for this channel.')
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
export declare namespace SignerMismatchError {
|
|
264
|
+
type Options = {
|
|
265
|
+
reason?: string
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Voucher cumulative amount exceeds the channel deposit.
|
|
271
|
+
*/
|
|
272
|
+
export class AmountExceedsDepositError extends PaymentError {
|
|
273
|
+
override readonly name = 'AmountExceedsDepositError'
|
|
274
|
+
override readonly status = 402
|
|
275
|
+
readonly type = 'https://paymentauth.org/problems/stream/amount-exceeds-deposit'
|
|
276
|
+
|
|
277
|
+
constructor(options: AmountExceedsDepositError.Options = {}) {
|
|
278
|
+
const { reason } = options
|
|
279
|
+
super(reason ? `Amount exceeds deposit: ${reason}.` : 'Voucher amount exceeds channel deposit.')
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
export declare namespace AmountExceedsDepositError {
|
|
284
|
+
type Options = {
|
|
285
|
+
reason?: string
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Voucher amount increase is below the minimum delta.
|
|
291
|
+
*/
|
|
292
|
+
export class DeltaTooSmallError extends PaymentError {
|
|
293
|
+
override readonly name = 'DeltaTooSmallError'
|
|
294
|
+
override readonly status = 402
|
|
295
|
+
readonly type = 'https://paymentauth.org/problems/stream/delta-too-small'
|
|
296
|
+
|
|
297
|
+
constructor(options: DeltaTooSmallError.Options = {}) {
|
|
298
|
+
const { reason } = options
|
|
299
|
+
super(reason ? `Delta too small: ${reason}.` : 'Amount increase below minimum voucher delta.')
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
export declare namespace DeltaTooSmallError {
|
|
304
|
+
type Options = {
|
|
305
|
+
reason?: string
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* No channel with this ID exists.
|
|
311
|
+
*/
|
|
312
|
+
export class ChannelNotFoundError extends PaymentError {
|
|
313
|
+
override readonly name = 'ChannelNotFoundError'
|
|
314
|
+
override readonly status = 410
|
|
315
|
+
readonly type = 'https://paymentauth.org/problems/stream/channel-not-found'
|
|
316
|
+
|
|
317
|
+
constructor(options: ChannelNotFoundError.Options = {}) {
|
|
318
|
+
const { reason } = options
|
|
319
|
+
super(reason ? `Channel not found: ${reason}.` : 'No channel with this ID exists.')
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
export declare namespace ChannelNotFoundError {
|
|
324
|
+
type Options = {
|
|
325
|
+
reason?: string
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Channel is closed or finalized.
|
|
331
|
+
*/
|
|
332
|
+
export class ChannelClosedError extends PaymentError {
|
|
333
|
+
override readonly name = 'ChannelClosedError'
|
|
334
|
+
override readonly status = 410
|
|
335
|
+
readonly type = 'https://paymentauth.org/problems/stream/channel-finalized'
|
|
336
|
+
|
|
337
|
+
constructor(options: ChannelClosedError.Options = {}) {
|
|
338
|
+
const { reason } = options
|
|
339
|
+
super(reason ? `Channel closed: ${reason}.` : 'Channel is closed.')
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
export declare namespace ChannelClosedError {
|
|
344
|
+
type Options = {
|
|
345
|
+
/** Reason the channel is closed. */
|
|
346
|
+
reason?: string
|
|
347
|
+
}
|
|
348
|
+
}
|
package/src/Expires.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/** Returns an ISO 8601 datetime string `n` days from now. */
|
|
2
|
+
export function days(n: number) {
|
|
3
|
+
return new Date(Date.now() + n * 24 * 60 * 60 * 1000).toISOString()
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
/** Returns an ISO 8601 datetime string `n` hours from now. */
|
|
7
|
+
export function hours(n: number) {
|
|
8
|
+
return new Date(Date.now() + n * 60 * 60 * 1000).toISOString()
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/** Returns an ISO 8601 datetime string `n` minutes from now. */
|
|
12
|
+
export function minutes(n: number) {
|
|
13
|
+
return new Date(Date.now() + n * 60 * 1000).toISOString()
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** Returns an ISO 8601 datetime string `n` months (30 days) from now. */
|
|
17
|
+
export function months(n: number) {
|
|
18
|
+
return new Date(Date.now() + n * 30 * 24 * 60 * 60 * 1000).toISOString()
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** Returns an ISO 8601 datetime string `n` seconds from now. */
|
|
22
|
+
export function seconds(n: number) {
|
|
23
|
+
return new Date(Date.now() + n * 1000).toISOString()
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Returns an ISO 8601 datetime string `n` weeks from now. */
|
|
27
|
+
export function weeks(n: number) {
|
|
28
|
+
return new Date(Date.now() + n * 7 * 24 * 60 * 60 * 1000).toISOString()
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Returns an ISO 8601 datetime string `n` years (365 days) from now. */
|
|
32
|
+
export function years(n: number) {
|
|
33
|
+
return new Date(Date.now() + n * 365 * 24 * 60 * 60 * 1000).toISOString()
|
|
34
|
+
}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { Intent } from 'mppx'
|
|
2
|
+
import { describe, expect, test } from 'vitest'
|
|
3
|
+
|
|
4
|
+
describe('charge', () => {
|
|
5
|
+
test('behavior: validates valid request', () => {
|
|
6
|
+
const result = Intent.charge.schema.request.parse({
|
|
7
|
+
amount: '1000',
|
|
8
|
+
currency: 'USD',
|
|
9
|
+
decimals: 6,
|
|
10
|
+
})
|
|
11
|
+
expect(result.amount).toBe('1000000000')
|
|
12
|
+
expect(result.currency).toBe('USD')
|
|
13
|
+
expect(result.expires).toMatch(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/)
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
test('behavior: validates with all optional fields', () => {
|
|
17
|
+
expect(
|
|
18
|
+
Intent.charge.schema.request.parse({
|
|
19
|
+
amount: '1000',
|
|
20
|
+
currency: 'USD',
|
|
21
|
+
decimals: 6,
|
|
22
|
+
description: 'Test payment',
|
|
23
|
+
expires: '2030-01-01T00:00:00Z',
|
|
24
|
+
externalId: 'order-123',
|
|
25
|
+
recipient: '0x1234567890abcdef',
|
|
26
|
+
}),
|
|
27
|
+
).toMatchInlineSnapshot(`
|
|
28
|
+
{
|
|
29
|
+
"amount": "1000000000",
|
|
30
|
+
"currency": "USD",
|
|
31
|
+
"description": "Test payment",
|
|
32
|
+
"expires": "2030-01-01T00:00:00Z",
|
|
33
|
+
"externalId": "order-123",
|
|
34
|
+
"recipient": "0x1234567890abcdef",
|
|
35
|
+
}
|
|
36
|
+
`)
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
test('error: invalid amount (non-numeric)', () => {
|
|
40
|
+
expect(() =>
|
|
41
|
+
Intent.charge.schema.request.parse({
|
|
42
|
+
amount: 'abc',
|
|
43
|
+
currency: 'USD',
|
|
44
|
+
}),
|
|
45
|
+
).toThrowErrorMatchingInlineSnapshot(`
|
|
46
|
+
[$ZodError: [
|
|
47
|
+
{
|
|
48
|
+
"origin": "string",
|
|
49
|
+
"code": "invalid_format",
|
|
50
|
+
"format": "regex",
|
|
51
|
+
"pattern": "/^\\\\d+(\\\\.\\\\d+)?$/",
|
|
52
|
+
"path": [
|
|
53
|
+
"amount"
|
|
54
|
+
],
|
|
55
|
+
"message": "Invalid amount"
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"expected": "number",
|
|
59
|
+
"code": "invalid_type",
|
|
60
|
+
"path": [
|
|
61
|
+
"decimals"
|
|
62
|
+
],
|
|
63
|
+
"message": "Invalid input"
|
|
64
|
+
}
|
|
65
|
+
]]
|
|
66
|
+
`)
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
test('error: invalid amount (decimal)', () => {
|
|
70
|
+
expect(() =>
|
|
71
|
+
Intent.charge.schema.request.parse({
|
|
72
|
+
amount: '100.50',
|
|
73
|
+
currency: 'USD',
|
|
74
|
+
}),
|
|
75
|
+
).toThrowErrorMatchingInlineSnapshot(`
|
|
76
|
+
[$ZodError: [
|
|
77
|
+
{
|
|
78
|
+
"expected": "number",
|
|
79
|
+
"code": "invalid_type",
|
|
80
|
+
"path": [
|
|
81
|
+
"decimals"
|
|
82
|
+
],
|
|
83
|
+
"message": "Invalid input"
|
|
84
|
+
}
|
|
85
|
+
]]
|
|
86
|
+
`)
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
test('error: invalid expires (not ISO 8601)', () => {
|
|
90
|
+
expect(() =>
|
|
91
|
+
Intent.charge.schema.request.parse({
|
|
92
|
+
amount: '1000',
|
|
93
|
+
currency: 'USD',
|
|
94
|
+
expires: 'not-a-date',
|
|
95
|
+
}),
|
|
96
|
+
).toThrowErrorMatchingInlineSnapshot(`
|
|
97
|
+
[$ZodError: [
|
|
98
|
+
{
|
|
99
|
+
"expected": "number",
|
|
100
|
+
"code": "invalid_type",
|
|
101
|
+
"path": [
|
|
102
|
+
"decimals"
|
|
103
|
+
],
|
|
104
|
+
"message": "Invalid input"
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
"origin": "string",
|
|
108
|
+
"code": "invalid_format",
|
|
109
|
+
"format": "regex",
|
|
110
|
+
"pattern": "/^\\\\d{4}-\\\\d{2}-\\\\d{2}T\\\\d{2}:\\\\d{2}:\\\\d{2}(?:\\\\.\\\\d+)?(?:Z|[+-]\\\\d{2}:\\\\d{2})$/",
|
|
111
|
+
"path": [
|
|
112
|
+
"expires"
|
|
113
|
+
],
|
|
114
|
+
"message": "Invalid ISO 8601 datetime"
|
|
115
|
+
}
|
|
116
|
+
]]
|
|
117
|
+
`)
|
|
118
|
+
})
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
describe('session', () => {
|
|
122
|
+
test('behavior: converts amount to base units', () => {
|
|
123
|
+
const result = Intent.session.schema.request.parse({
|
|
124
|
+
amount: '0.000025',
|
|
125
|
+
unitType: 'llm_token',
|
|
126
|
+
currency: '0x20c0000000000000000000000000000000000001',
|
|
127
|
+
decimals: 6,
|
|
128
|
+
recipient: '0x1234567890abcdef1234567890abcdef12345678',
|
|
129
|
+
})
|
|
130
|
+
expect(result.amount).toBe('25')
|
|
131
|
+
expect(result.unitType).toBe('llm_token')
|
|
132
|
+
expect(result.currency).toBe('0x20c0000000000000000000000000000000000001')
|
|
133
|
+
expect(result).not.toHaveProperty('decimals')
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
test('behavior: converts suggestedDeposit to base units', () => {
|
|
137
|
+
const result = Intent.session.schema.request.parse({
|
|
138
|
+
amount: '0.000025',
|
|
139
|
+
unitType: 'llm_token',
|
|
140
|
+
currency: '0x20c0000000000000000000000000000000000001',
|
|
141
|
+
decimals: 6,
|
|
142
|
+
recipient: '0x1234567890abcdef1234567890abcdef12345678',
|
|
143
|
+
suggestedDeposit: '10',
|
|
144
|
+
})
|
|
145
|
+
expect(result.amount).toBe('25')
|
|
146
|
+
expect(result.suggestedDeposit).toBe('10000000')
|
|
147
|
+
})
|
|
148
|
+
|
|
149
|
+
test('behavior: works without suggestedDeposit', () => {
|
|
150
|
+
const result = Intent.session.schema.request.parse({
|
|
151
|
+
amount: '1',
|
|
152
|
+
unitType: 'request',
|
|
153
|
+
currency: '0x20c0000000000000000000000000000000000001',
|
|
154
|
+
decimals: 6,
|
|
155
|
+
})
|
|
156
|
+
expect(result.amount).toBe('1000000')
|
|
157
|
+
expect(result).not.toHaveProperty('suggestedDeposit')
|
|
158
|
+
})
|
|
159
|
+
|
|
160
|
+
test('error: rejects missing decimals', () => {
|
|
161
|
+
expect(() =>
|
|
162
|
+
Intent.session.schema.request.parse({
|
|
163
|
+
amount: '25',
|
|
164
|
+
unitType: 'llm_token',
|
|
165
|
+
currency: '0x20c0000000000000000000000000000000000001',
|
|
166
|
+
}),
|
|
167
|
+
).toThrow()
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
test('error: rejects invalid amount', () => {
|
|
171
|
+
expect(() =>
|
|
172
|
+
Intent.session.schema.request.parse({
|
|
173
|
+
amount: 'abc',
|
|
174
|
+
unitType: 'llm_token',
|
|
175
|
+
currency: '0x20c0000000000000000000000000000000000001',
|
|
176
|
+
decimals: 6,
|
|
177
|
+
}),
|
|
178
|
+
).toThrow()
|
|
179
|
+
})
|
|
180
|
+
})
|
package/src/Intent.ts
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { parseUnits } from 'viem'
|
|
2
|
+
import * as Expires from './Expires.js'
|
|
3
|
+
import * as z from './zod.js'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* A payment intent.
|
|
7
|
+
*/
|
|
8
|
+
export type Intent = {
|
|
9
|
+
name: string
|
|
10
|
+
schema: {
|
|
11
|
+
request: z.z.ZodMiniObject | z.z.ZodMiniPipe<z.z.ZodMiniObject>
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Creates an intent.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* import { z } from 'mppx'
|
|
21
|
+
*
|
|
22
|
+
* const charge = Intent.from({
|
|
23
|
+
* name: 'charge',
|
|
24
|
+
* schema: {
|
|
25
|
+
* request: z.object({
|
|
26
|
+
* amount: z.string(),
|
|
27
|
+
* currency: z.string(),
|
|
28
|
+
* recipient: z.optional(z.string()),
|
|
29
|
+
* }),
|
|
30
|
+
* },
|
|
31
|
+
* })
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export function from<const intent extends Intent>(intent: intent): intent {
|
|
35
|
+
return intent
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Charge intent for one-time immediate payments.
|
|
40
|
+
*
|
|
41
|
+
* @see https://github.com/tempoxyz/payment-auth-spec/blob/main/specs/intents/draft-payment-intent-charge-00.md
|
|
42
|
+
*/
|
|
43
|
+
export const charge = from({
|
|
44
|
+
name: 'charge',
|
|
45
|
+
schema: {
|
|
46
|
+
request: z.pipe(
|
|
47
|
+
z.object({
|
|
48
|
+
amount: z.amount(),
|
|
49
|
+
currency: z.string(),
|
|
50
|
+
decimals: z.number(),
|
|
51
|
+
description: z.optional(z.string()),
|
|
52
|
+
expires: z._default(z.datetime(), () => Expires.minutes(5)),
|
|
53
|
+
externalId: z.optional(z.string()),
|
|
54
|
+
recipient: z.optional(z.string()),
|
|
55
|
+
}),
|
|
56
|
+
// Note: Since the spec states we must have `amount` as a base unit, we
|
|
57
|
+
// will transform the amount to decimal units based on `decimals`.
|
|
58
|
+
z.transform(({ amount, decimals, ...rest }) => ({
|
|
59
|
+
...rest,
|
|
60
|
+
amount: parseUnits(amount, decimals).toString(),
|
|
61
|
+
})),
|
|
62
|
+
),
|
|
63
|
+
},
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Session intent for pay-as-you-go streaming payments.
|
|
68
|
+
*
|
|
69
|
+
* Uses cumulative vouchers over a payment channel for
|
|
70
|
+
* incremental micropayments without per-request transactions.
|
|
71
|
+
*/
|
|
72
|
+
export const session = from({
|
|
73
|
+
name: 'session',
|
|
74
|
+
schema: {
|
|
75
|
+
request: z.pipe(
|
|
76
|
+
z.object({
|
|
77
|
+
amount: z.amount(),
|
|
78
|
+
unitType: z.string(),
|
|
79
|
+
currency: z.string(),
|
|
80
|
+
decimals: z.number(),
|
|
81
|
+
recipient: z.optional(z.string()),
|
|
82
|
+
suggestedDeposit: z.optional(z.amount()),
|
|
83
|
+
}),
|
|
84
|
+
z.transform(({ amount, decimals, suggestedDeposit, ...rest }) => ({
|
|
85
|
+
...rest,
|
|
86
|
+
amount: parseUnits(amount, decimals).toString(),
|
|
87
|
+
...(suggestedDeposit
|
|
88
|
+
? { suggestedDeposit: parseUnits(suggestedDeposit, decimals).toString() }
|
|
89
|
+
: {}),
|
|
90
|
+
})),
|
|
91
|
+
),
|
|
92
|
+
},
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
/** @internal Extracts shape from an intent's request schema, supporting both object and pipe. */
|
|
96
|
+
export type ShapeOf<intent extends Intent> = intent['schema']['request'] extends z.z.ZodMiniObject
|
|
97
|
+
? intent['schema']['request']['shape']
|
|
98
|
+
: intent['schema']['request'] extends z.z.ZodMiniPipe<infer A>
|
|
99
|
+
? A extends z.z.ZodMiniObject
|
|
100
|
+
? A['shape']
|
|
101
|
+
: never
|
|
102
|
+
: never
|
|
103
|
+
|
|
104
|
+
/** @internal Extracts the inner object from a pipe or returns the schema directly. */
|
|
105
|
+
export function shapeOf(intent: Intent): Record<string, z.z.ZodMiniType> {
|
|
106
|
+
const { request } = intent.schema
|
|
107
|
+
if ('shape' in request) return request.shape as Record<string, z.z.ZodMiniType>
|
|
108
|
+
return (request as any)._zod.def.in.shape
|
|
109
|
+
}
|