@scriptmasterlabs/mcp-x402 2.0.2 → 2.1.1
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/.well-known/x402.json +37 -0
- package/LICENSE +57 -21
- package/README.md +262 -304
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp-wrapper.d.ts +71 -0
- package/dist/mcp-wrapper.d.ts.map +1 -0
- package/dist/mcp-wrapper.js +104 -0
- package/dist/mcp-wrapper.js.map +1 -0
- package/dist/x402-middleware.d.ts +76 -0
- package/dist/x402-middleware.d.ts.map +1 -0
- package/dist/x402-middleware.js +113 -0
- package/dist/x402-middleware.js.map +1 -0
- package/dist/xrpl-facilitator.d.ts +77 -0
- package/dist/xrpl-facilitator.d.ts.map +1 -0
- package/dist/xrpl-facilitator.js +156 -0
- package/dist/xrpl-facilitator.js.map +1 -0
- package/llms.txt +108 -70
- package/package.json +65 -78
- package/schema.jsonld +97 -0
- package/.env.example +0 -35
- package/.github/workflows/ci.yml +0 -59
- package/.github/workflows/keepalive.yml +0 -31
- package/.well-known/agentcard.json +0 -34
- package/CONTRIBUTING.md +0 -76
- package/Dockerfile +0 -19
- package/agents.json +0 -67
- package/dist/lib/chains/base.d.ts +0 -10
- package/dist/lib/chains/base.d.ts.map +0 -1
- package/dist/lib/chains/base.js +0 -73
- package/dist/lib/chains/base.js.map +0 -1
- package/dist/lib/chains/solana.d.ts +0 -10
- package/dist/lib/chains/solana.d.ts.map +0 -1
- package/dist/lib/chains/solana.js +0 -49
- package/dist/lib/chains/solana.js.map +0 -1
- package/dist/lib/chains/xrpl.d.ts +0 -10
- package/dist/lib/chains/xrpl.d.ts.map +0 -1
- package/dist/lib/chains/xrpl.js +0 -55
- package/dist/lib/chains/xrpl.js.map +0 -1
- package/dist/lib/credit/bureau.d.ts +0 -10
- package/dist/lib/credit/bureau.d.ts.map +0 -1
- package/dist/lib/credit/bureau.js +0 -58
- package/dist/lib/credit/bureau.js.map +0 -1
- package/dist/lib/sml-api/agentcard.d.ts +0 -17
- package/dist/lib/sml-api/agentcard.d.ts.map +0 -1
- package/dist/lib/sml-api/agentcard.js +0 -30
- package/dist/lib/sml-api/agentcard.js.map +0 -1
- package/dist/lib/sml-api/backtest.d.ts +0 -22
- package/dist/lib/sml-api/backtest.d.ts.map +0 -1
- package/dist/lib/sml-api/backtest.js +0 -28
- package/dist/lib/sml-api/backtest.js.map +0 -1
- package/dist/lib/sml-api/brokers.d.ts +0 -40
- package/dist/lib/sml-api/brokers.d.ts.map +0 -1
- package/dist/lib/sml-api/brokers.js +0 -128
- package/dist/lib/sml-api/brokers.js.map +0 -1
- package/dist/lib/sml-api/copytrader.d.ts +0 -11
- package/dist/lib/sml-api/copytrader.d.ts.map +0 -1
- package/dist/lib/sml-api/copytrader.js +0 -30
- package/dist/lib/sml-api/copytrader.js.map +0 -1
- package/dist/lib/sml-api/crawl.d.ts +0 -20
- package/dist/lib/sml-api/crawl.d.ts.map +0 -1
- package/dist/lib/sml-api/crawl.js +0 -32
- package/dist/lib/sml-api/crawl.js.map +0 -1
- package/dist/lib/sml-api/echo.d.ts +0 -10
- package/dist/lib/sml-api/echo.d.ts.map +0 -1
- package/dist/lib/sml-api/echo.js +0 -23
- package/dist/lib/sml-api/echo.js.map +0 -1
- package/dist/lib/sml-api/forge.d.ts +0 -11
- package/dist/lib/sml-api/forge.d.ts.map +0 -1
- package/dist/lib/sml-api/forge.js +0 -29
- package/dist/lib/sml-api/forge.js.map +0 -1
- package/dist/lib/sml-api/ftd.d.ts +0 -18
- package/dist/lib/sml-api/ftd.d.ts.map +0 -1
- package/dist/lib/sml-api/ftd.js +0 -43
- package/dist/lib/sml-api/ftd.js.map +0 -1
- package/dist/lib/sml-api/ghost.d.ts +0 -13
- package/dist/lib/sml-api/ghost.d.ts.map +0 -1
- package/dist/lib/sml-api/ghost.js +0 -29
- package/dist/lib/sml-api/ghost.js.map +0 -1
- package/dist/lib/sml-api/launchpad.d.ts +0 -20
- package/dist/lib/sml-api/launchpad.d.ts.map +0 -1
- package/dist/lib/sml-api/launchpad.js +0 -31
- package/dist/lib/sml-api/launchpad.js.map +0 -1
- package/dist/lib/sml-api/leviathan.d.ts +0 -22
- package/dist/lib/sml-api/leviathan.d.ts.map +0 -1
- package/dist/lib/sml-api/leviathan.js +0 -33
- package/dist/lib/sml-api/leviathan.js.map +0 -1
- package/dist/lib/sml-api/nexus.d.ts +0 -18
- package/dist/lib/sml-api/nexus.d.ts.map +0 -1
- package/dist/lib/sml-api/nexus.js +0 -40
- package/dist/lib/sml-api/nexus.js.map +0 -1
- package/dist/lib/sml-api/proof402.d.ts +0 -6
- package/dist/lib/sml-api/proof402.d.ts.map +0 -1
- package/dist/lib/sml-api/proof402.js +0 -30
- package/dist/lib/sml-api/proof402.js.map +0 -1
- package/dist/lib/sml-api/rails.d.ts +0 -12
- package/dist/lib/sml-api/rails.d.ts.map +0 -1
- package/dist/lib/sml-api/rails.js +0 -29
- package/dist/lib/sml-api/rails.js.map +0 -1
- package/dist/lib/sml-api/shadow.d.ts +0 -15
- package/dist/lib/sml-api/shadow.d.ts.map +0 -1
- package/dist/lib/sml-api/shadow.js +0 -27
- package/dist/lib/sml-api/shadow.js.map +0 -1
- package/dist/lib/sml-api/squeezeos.d.ts +0 -21
- package/dist/lib/sml-api/squeezeos.d.ts.map +0 -1
- package/dist/lib/sml-api/squeezeos.js +0 -97
- package/dist/lib/sml-api/squeezeos.js.map +0 -1
- package/dist/lib/sml-api/xdeo.d.ts +0 -13
- package/dist/lib/sml-api/xdeo.d.ts.map +0 -1
- package/dist/lib/sml-api/xdeo.js +0 -34
- package/dist/lib/sml-api/xdeo.js.map +0 -1
- package/dist/lib/sml-api/xmit.d.ts +0 -13
- package/dist/lib/sml-api/xmit.d.ts.map +0 -1
- package/dist/lib/sml-api/xmit.js +0 -34
- package/dist/lib/sml-api/xmit.js.map +0 -1
- package/dist/server/health.d.ts +0 -16
- package/dist/server/health.d.ts.map +0 -1
- package/dist/server/health.js +0 -39
- package/dist/server/health.js.map +0 -1
- package/dist/server/index.d.ts +0 -3
- package/dist/server/index.d.ts.map +0 -1
- package/dist/server/index.js +0 -199
- package/dist/server/index.js.map +0 -1
- package/dist/server/payments/ap2.d.ts +0 -17
- package/dist/server/payments/ap2.d.ts.map +0 -1
- package/dist/server/payments/ap2.js +0 -77
- package/dist/server/payments/ap2.js.map +0 -1
- package/dist/server/payments/receipt.d.ts +0 -28
- package/dist/server/payments/receipt.d.ts.map +0 -1
- package/dist/server/payments/receipt.js +0 -60
- package/dist/server/payments/receipt.js.map +0 -1
- package/dist/server/payments/router.d.ts +0 -23
- package/dist/server/payments/router.d.ts.map +0 -1
- package/dist/server/payments/router.js +0 -69
- package/dist/server/payments/router.js.map +0 -1
- package/dist/server/payments/wallet.d.ts +0 -18
- package/dist/server/payments/wallet.d.ts.map +0 -1
- package/dist/server/payments/wallet.js +0 -107
- package/dist/server/payments/wallet.js.map +0 -1
- package/dist/server/payments/x402.d.ts +0 -29
- package/dist/server/payments/x402.d.ts.map +0 -1
- package/dist/server/payments/x402.js +0 -138
- package/dist/server/payments/x402.js.map +0 -1
- package/dist/server/registry/catalog.d.ts +0 -12
- package/dist/server/registry/catalog.d.ts.map +0 -1
- package/dist/server/registry/catalog.js +0 -55
- package/dist/server/registry/catalog.js.map +0 -1
- package/dist/server/registry/discovery.d.ts +0 -16
- package/dist/server/registry/discovery.d.ts.map +0 -1
- package/dist/server/registry/discovery.js +0 -33
- package/dist/server/registry/discovery.js.map +0 -1
- package/dist/server/registry/pricing.d.ts +0 -10
- package/dist/server/registry/pricing.d.ts.map +0 -1
- package/dist/server/registry/pricing.js +0 -123
- package/dist/server/registry/pricing.js.map +0 -1
- package/dist/server/security/acl.d.ts +0 -28
- package/dist/server/security/acl.d.ts.map +0 -1
- package/dist/server/security/acl.js +0 -36
- package/dist/server/security/acl.js.map +0 -1
- package/dist/server/security/audit.d.ts +0 -15
- package/dist/server/security/audit.d.ts.map +0 -1
- package/dist/server/security/audit.js +0 -77
- package/dist/server/security/audit.js.map +0 -1
- package/dist/server/security/rate-limit.d.ts +0 -12
- package/dist/server/security/rate-limit.d.ts.map +0 -1
- package/dist/server/security/rate-limit.js +0 -72
- package/dist/server/security/rate-limit.js.map +0 -1
- package/dist/server/security/sandbox.d.ts +0 -7
- package/dist/server/security/sandbox.d.ts.map +0 -1
- package/dist/server/security/sandbox.js +0 -42
- package/dist/server/security/sandbox.js.map +0 -1
- package/dist/server/tools/agentcard.d.ts +0 -3
- package/dist/server/tools/agentcard.d.ts.map +0 -1
- package/dist/server/tools/agentcard.js +0 -118
- package/dist/server/tools/agentcard.js.map +0 -1
- package/dist/server/tools/backtest.d.ts +0 -3
- package/dist/server/tools/backtest.d.ts.map +0 -1
- package/dist/server/tools/backtest.js +0 -112
- package/dist/server/tools/backtest.js.map +0 -1
- package/dist/server/tools/brokers.d.ts +0 -3
- package/dist/server/tools/brokers.d.ts.map +0 -1
- package/dist/server/tools/brokers.js +0 -223
- package/dist/server/tools/brokers.js.map +0 -1
- package/dist/server/tools/copytrader.d.ts +0 -3
- package/dist/server/tools/copytrader.d.ts.map +0 -1
- package/dist/server/tools/copytrader.js +0 -90
- package/dist/server/tools/copytrader.js.map +0 -1
- package/dist/server/tools/crawl.d.ts +0 -3
- package/dist/server/tools/crawl.d.ts.map +0 -1
- package/dist/server/tools/crawl.js +0 -60
- package/dist/server/tools/crawl.js.map +0 -1
- package/dist/server/tools/discovery.d.ts +0 -3
- package/dist/server/tools/discovery.d.ts.map +0 -1
- package/dist/server/tools/discovery.js +0 -188
- package/dist/server/tools/discovery.js.map +0 -1
- package/dist/server/tools/echo.d.ts +0 -3
- package/dist/server/tools/echo.d.ts.map +0 -1
- package/dist/server/tools/echo.js +0 -48
- package/dist/server/tools/echo.js.map +0 -1
- package/dist/server/tools/forge.d.ts +0 -3
- package/dist/server/tools/forge.d.ts.map +0 -1
- package/dist/server/tools/forge.js +0 -77
- package/dist/server/tools/forge.js.map +0 -1
- package/dist/server/tools/ftd.d.ts +0 -3
- package/dist/server/tools/ftd.d.ts.map +0 -1
- package/dist/server/tools/ftd.js +0 -70
- package/dist/server/tools/ftd.js.map +0 -1
- package/dist/server/tools/ghost.d.ts +0 -3
- package/dist/server/tools/ghost.d.ts.map +0 -1
- package/dist/server/tools/ghost.js +0 -83
- package/dist/server/tools/ghost.js.map +0 -1
- package/dist/server/tools/index.d.ts +0 -3
- package/dist/server/tools/index.d.ts.map +0 -1
- package/dist/server/tools/index.js +0 -44
- package/dist/server/tools/index.js.map +0 -1
- package/dist/server/tools/launchpad.d.ts +0 -3
- package/dist/server/tools/launchpad.d.ts.map +0 -1
- package/dist/server/tools/launchpad.js +0 -151
- package/dist/server/tools/launchpad.js.map +0 -1
- package/dist/server/tools/leviathan.d.ts +0 -3
- package/dist/server/tools/leviathan.d.ts.map +0 -1
- package/dist/server/tools/leviathan.js +0 -73
- package/dist/server/tools/leviathan.js.map +0 -1
- package/dist/server/tools/nexus.d.ts +0 -3
- package/dist/server/tools/nexus.d.ts.map +0 -1
- package/dist/server/tools/nexus.js +0 -65
- package/dist/server/tools/nexus.js.map +0 -1
- package/dist/server/tools/proof402.d.ts +0 -3
- package/dist/server/tools/proof402.d.ts.map +0 -1
- package/dist/server/tools/proof402.js +0 -74
- package/dist/server/tools/proof402.js.map +0 -1
- package/dist/server/tools/rails.d.ts +0 -3
- package/dist/server/tools/rails.d.ts.map +0 -1
- package/dist/server/tools/rails.js +0 -82
- package/dist/server/tools/rails.js.map +0 -1
- package/dist/server/tools/shadow.d.ts +0 -3
- package/dist/server/tools/shadow.d.ts.map +0 -1
- package/dist/server/tools/shadow.js +0 -114
- package/dist/server/tools/shadow.js.map +0 -1
- package/dist/server/tools/squeezeos.d.ts +0 -3
- package/dist/server/tools/squeezeos.d.ts.map +0 -1
- package/dist/server/tools/squeezeos.js +0 -231
- package/dist/server/tools/squeezeos.js.map +0 -1
- package/dist/server/tools/xdeo.d.ts +0 -3
- package/dist/server/tools/xdeo.d.ts.map +0 -1
- package/dist/server/tools/xdeo.js +0 -58
- package/dist/server/tools/xdeo.js.map +0 -1
- package/dist/server/tools/xmit.d.ts +0 -3
- package/dist/server/tools/xmit.d.ts.map +0 -1
- package/dist/server/tools/xmit.js +0 -59
- package/dist/server/tools/xmit.js.map +0 -1
- package/docker-compose.yml +0 -50
- package/mcp-publisher.exe +0 -0
- package/render.yaml +0 -39
- package/sdk/mcp-x402-sdk/package.json +0 -18
- package/sdk/mcp-x402-sdk/src/index.ts +0 -118
- package/sdk/mcp-x402-sdk/tsconfig.json +0 -14
- package/server.json +0 -48
- package/services/backtest_service.py +0 -176
- package/src/lib/chains/base.ts +0 -77
- package/src/lib/chains/solana.ts +0 -59
- package/src/lib/chains/xrpl.ts +0 -63
- package/src/lib/credit/bureau.ts +0 -65
- package/src/lib/sml-api/agentcard.ts +0 -40
- package/src/lib/sml-api/backtest.ts +0 -47
- package/src/lib/sml-api/brokers.ts +0 -160
- package/src/lib/sml-api/copytrader.ts +0 -33
- package/src/lib/sml-api/crawl.ts +0 -44
- package/src/lib/sml-api/echo.ts +0 -28
- package/src/lib/sml-api/forge.ts +0 -33
- package/src/lib/sml-api/ftd.ts +0 -53
- package/src/lib/sml-api/ghost.ts +0 -35
- package/src/lib/sml-api/launchpad.ts +0 -43
- package/src/lib/sml-api/leviathan.ts +0 -49
- package/src/lib/sml-api/nexus.ts +0 -50
- package/src/lib/sml-api/proof402.ts +0 -27
- package/src/lib/sml-api/rails.ts +0 -34
- package/src/lib/sml-api/shadow.ts +0 -35
- package/src/lib/sml-api/squeezeos.ts +0 -95
- package/src/lib/sml-api/xdeo.ts +0 -40
- package/src/lib/sml-api/xmit.ts +0 -40
- package/src/server/health.ts +0 -52
- package/src/server/index.ts +0 -213
- package/src/server/payments/ap2.ts +0 -101
- package/src/server/payments/receipt.ts +0 -85
- package/src/server/payments/router.ts +0 -110
- package/src/server/payments/wallet.ts +0 -123
- package/src/server/payments/x402.ts +0 -177
- package/src/server/registry/catalog.ts +0 -61
- package/src/server/registry/discovery.ts +0 -39
- package/src/server/registry/pricing.ts +0 -133
- package/src/server/security/acl.ts +0 -42
- package/src/server/security/audit.ts +0 -94
- package/src/server/security/rate-limit.ts +0 -84
- package/src/server/security/sandbox.ts +0 -40
- package/src/server/tools/agentcard.ts +0 -134
- package/src/server/tools/backtest.ts +0 -119
- package/src/server/tools/brokers.ts +0 -250
- package/src/server/tools/copytrader.ts +0 -104
- package/src/server/tools/crawl.ts +0 -70
- package/src/server/tools/discovery.ts +0 -202
- package/src/server/tools/echo.ts +0 -58
- package/src/server/tools/forge.ts +0 -87
- package/src/server/tools/ftd.ts +0 -88
- package/src/server/tools/ghost.ts +0 -93
- package/src/server/tools/index.ts +0 -42
- package/src/server/tools/launchpad.ts +0 -173
- package/src/server/tools/leviathan.ts +0 -81
- package/src/server/tools/nexus.ts +0 -76
- package/src/server/tools/proof402.ts +0 -87
- package/src/server/tools/rails.ts +0 -92
- package/src/server/tools/shadow.ts +0 -128
- package/src/server/tools/squeezeos.ts +0 -312
- package/src/server/tools/xdeo.ts +0 -67
- package/src/server/tools/xmit.ts +0 -68
- package/tests/integration/e2e.test.ts +0 -51
- package/tests/unit/payments.test.ts +0 -49
- package/tests/unit/security.test.ts +0 -92
- package/tests/unit/tools.test.ts +0 -42
- package/tsconfig.json +0 -21
- package/vitest.config.ts +0 -20
package/render.yaml
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
services:
|
|
2
|
-
- type: web
|
|
3
|
-
name: mcp-x402
|
|
4
|
-
runtime: docker
|
|
5
|
-
dockerfilePath: ./mcp-x402/Dockerfile
|
|
6
|
-
dockerContext: ./mcp-x402
|
|
7
|
-
plan: starter
|
|
8
|
-
region: oregon
|
|
9
|
-
healthCheckPath: /health
|
|
10
|
-
envVars:
|
|
11
|
-
- key: NODE_ENV
|
|
12
|
-
value: production
|
|
13
|
-
- key: MCP_TRANSPORT
|
|
14
|
-
value: sse
|
|
15
|
-
- key: MCP_SSE_PORT
|
|
16
|
-
value: 3402
|
|
17
|
-
- key: SML_API_BASE
|
|
18
|
-
sync: false
|
|
19
|
-
- key: WALLET_SEED
|
|
20
|
-
sync: false
|
|
21
|
-
- key: BASE_RPC_URL
|
|
22
|
-
sync: false
|
|
23
|
-
- key: XRPL_RPC_URL
|
|
24
|
-
sync: false
|
|
25
|
-
- key: SOLANA_RPC_URL
|
|
26
|
-
sync: false
|
|
27
|
-
- key: DAILY_SPEND_CAP_USD
|
|
28
|
-
value: "50"
|
|
29
|
-
- key: AUTO_APPROVE_THRESHOLD_USD
|
|
30
|
-
value: "1"
|
|
31
|
-
- key: PRICE_CACHE_TTL_MS
|
|
32
|
-
value: "60000"
|
|
33
|
-
- key: PROOF402_URL
|
|
34
|
-
value: https://four02proof.onrender.com
|
|
35
|
-
- key: TESTNET
|
|
36
|
-
value: "false"
|
|
37
|
-
autoDeploy: true
|
|
38
|
-
# Render restarts the service automatically on crash
|
|
39
|
-
# healthCheckPath triggers restart if /health returns non-2xx
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@scriptmasterlabs/mcp-x402-sdk",
|
|
3
|
-
"version": "1.0.0",
|
|
4
|
-
"description": "5-line drop-in x402 payment wrapper for any MCP server author.",
|
|
5
|
-
"main": "dist/index.js",
|
|
6
|
-
"types": "dist/index.d.ts",
|
|
7
|
-
"scripts": {
|
|
8
|
-
"build": "tsc",
|
|
9
|
-
"prepublishOnly": "npm run build"
|
|
10
|
-
},
|
|
11
|
-
"keywords": ["mcp", "x402", "autonomous-payments", "ai-agents"],
|
|
12
|
-
"author": "ScriptMasterLabs",
|
|
13
|
-
"license": "MIT",
|
|
14
|
-
"peerDependencies": {
|
|
15
|
-
"@modelcontextprotocol/sdk": ">=1.0.0",
|
|
16
|
-
"zod": ">=3.0.0"
|
|
17
|
-
}
|
|
18
|
-
}
|
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
|
|
3
|
-
export type SupportedCurrency = 'USDC' | 'RLUSD';
|
|
4
|
-
export type SupportedChain = 'base' | 'xrpl' | 'solana';
|
|
5
|
-
|
|
6
|
-
export interface X402PaymentConfig<TInput extends z.ZodTypeAny> {
|
|
7
|
-
price: string;
|
|
8
|
-
currency?: SupportedCurrency;
|
|
9
|
-
chain?: SupportedChain;
|
|
10
|
-
inputSchema: TInput;
|
|
11
|
-
handler: (input: z.infer<TInput>, receipt: PaymentReceipt) => Promise<ToolResult>;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export interface PaymentReceipt {
|
|
15
|
-
receipt_id: string;
|
|
16
|
-
tx_hash: string;
|
|
17
|
-
chain: string;
|
|
18
|
-
amount_paid: string;
|
|
19
|
-
currency: string;
|
|
20
|
-
timestamp: number;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export interface ToolResult {
|
|
24
|
-
content: Array<{ type: 'text'; text: string }>;
|
|
25
|
-
isError?: boolean;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const PROOF402_URL = process.env['PROOF402_URL'] ?? 'https://four02proof.onrender.com';
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* x402Payment — 5-line drop-in for any MCP server author.
|
|
32
|
-
*
|
|
33
|
-
* @example
|
|
34
|
-
* server.tool('my_tool', schema, x402Payment({
|
|
35
|
-
* price: '0.01',
|
|
36
|
-
* currency: 'USDC',
|
|
37
|
-
* inputSchema: MyInputSchema,
|
|
38
|
-
* handler: async (input, receipt) => {
|
|
39
|
-
* return { content: [{ type: 'text', text: JSON.stringify({ result: 'data', receipt }) }] };
|
|
40
|
-
* },
|
|
41
|
-
* }));
|
|
42
|
-
*/
|
|
43
|
-
export function x402Payment<TInput extends z.ZodTypeAny>(
|
|
44
|
-
config: X402PaymentConfig<TInput>,
|
|
45
|
-
): (rawArgs: unknown) => Promise<ToolResult> {
|
|
46
|
-
return async (rawArgs: unknown): Promise<ToolResult> => {
|
|
47
|
-
const parsed = config.inputSchema.safeParse(rawArgs);
|
|
48
|
-
if (!parsed.success) {
|
|
49
|
-
return {
|
|
50
|
-
content: [{ type: 'text', text: JSON.stringify({ error: 'validation_error', issues: parsed.error.issues }) }],
|
|
51
|
-
isError: true,
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const args = parsed.data as z.infer<TInput>;
|
|
56
|
-
const walletAddress = (args as Record<string, unknown>)['wallet_address'] as string | undefined;
|
|
57
|
-
|
|
58
|
-
let receipt: PaymentReceipt;
|
|
59
|
-
try {
|
|
60
|
-
receipt = await processPayment({
|
|
61
|
-
price: config.price,
|
|
62
|
-
currency: config.currency ?? 'USDC',
|
|
63
|
-
chain: config.chain,
|
|
64
|
-
walletAddress,
|
|
65
|
-
});
|
|
66
|
-
} catch (err) {
|
|
67
|
-
return {
|
|
68
|
-
content: [{ type: 'text', text: JSON.stringify({ error: 'payment_failed', message: String(err) }) }],
|
|
69
|
-
isError: true,
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
return config.handler(args, receipt);
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
async function processPayment(params: {
|
|
78
|
-
price: string;
|
|
79
|
-
currency: SupportedCurrency;
|
|
80
|
-
chain?: SupportedChain;
|
|
81
|
-
walletAddress?: string;
|
|
82
|
-
}): Promise<PaymentReceipt> {
|
|
83
|
-
// Delegates to the 402Proof payment endpoint
|
|
84
|
-
const res = await fetch(`${PROOF402_URL}/v1/pay`, {
|
|
85
|
-
method: 'POST',
|
|
86
|
-
headers: { 'Content-Type': 'application/json' },
|
|
87
|
-
body: JSON.stringify({
|
|
88
|
-
amount: params.price,
|
|
89
|
-
currency: params.currency,
|
|
90
|
-
chain: params.chain ?? 'base',
|
|
91
|
-
wallet: params.walletAddress,
|
|
92
|
-
}),
|
|
93
|
-
signal: AbortSignal.timeout(15_000),
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
if (!res.ok) {
|
|
97
|
-
throw new Error(`Payment failed: HTTP ${res.status}`);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
const body = (await res.json()) as {
|
|
101
|
-
receipt_id: string;
|
|
102
|
-
tx_hash: string;
|
|
103
|
-
chain: string;
|
|
104
|
-
amount: string;
|
|
105
|
-
currency: string;
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
return {
|
|
109
|
-
receipt_id: body.receipt_id,
|
|
110
|
-
tx_hash: body.tx_hash,
|
|
111
|
-
chain: body.chain,
|
|
112
|
-
amount_paid: body.amount,
|
|
113
|
-
currency: body.currency,
|
|
114
|
-
timestamp: Date.now(),
|
|
115
|
-
};
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
export { x402Payment as default };
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2022",
|
|
4
|
-
"module": "NodeNext",
|
|
5
|
-
"moduleResolution": "NodeNext",
|
|
6
|
-
"outDir": "./dist",
|
|
7
|
-
"rootDir": "./src",
|
|
8
|
-
"strict": true,
|
|
9
|
-
"esModuleInterop": true,
|
|
10
|
-
"skipLibCheck": true,
|
|
11
|
-
"declaration": true
|
|
12
|
-
},
|
|
13
|
-
"include": ["src/**/*"]
|
|
14
|
-
}
|
package/server.json
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
|
|
3
|
-
"name": "io.github.Timwal78/mcp-x402",
|
|
4
|
-
"description": "The x402 Amazon: 43+ MCP tools, pay-per-call. SEC, squeeze, options, FTD, XRPL/Base payments.",
|
|
5
|
-
"repository": {
|
|
6
|
-
"url": "https://github.com/timwal78/SML_Portfolio",
|
|
7
|
-
"source": "github"
|
|
8
|
-
},
|
|
9
|
-
"version": "2.0.2",
|
|
10
|
-
"packages": [
|
|
11
|
-
{
|
|
12
|
-
"registryType": "npm",
|
|
13
|
-
"identifier": "@scriptmasterlabs/mcp-x402",
|
|
14
|
-
"version": "2.0.2",
|
|
15
|
-
"runtimeHint": "node",
|
|
16
|
-
"transport": {
|
|
17
|
-
"type": "stdio"
|
|
18
|
-
},
|
|
19
|
-
"environmentVariables": [
|
|
20
|
-
{
|
|
21
|
-
"name": "MCP_TRANSPORT",
|
|
22
|
-
"description": "Transport mode. Use 'sse' for HTTP server mode.",
|
|
23
|
-
"isRequired": false
|
|
24
|
-
},
|
|
25
|
-
{
|
|
26
|
-
"name": "SML_PAYMENT_RECEIVER",
|
|
27
|
-
"description": "USDC Base address to receive payments from agent tool calls.",
|
|
28
|
-
"isRequired": false
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
"name": "WALLET_SEED",
|
|
32
|
-
"description": "BIP-39 mnemonic for the server wallet. Auto-generated if not set.",
|
|
33
|
-
"isRequired": false
|
|
34
|
-
}
|
|
35
|
-
]
|
|
36
|
-
}
|
|
37
|
-
],
|
|
38
|
-
"remotes": [
|
|
39
|
-
{
|
|
40
|
-
"type": "sse",
|
|
41
|
-
"url": "https://mcp-x402.onrender.com/sse"
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
"type": "streamable-http",
|
|
45
|
-
"url": "https://mcp-x402.onrender.com/mcp"
|
|
46
|
-
}
|
|
47
|
-
]
|
|
48
|
-
}
|
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Backtest microservice — wraps backtester-mcp + yfinance
|
|
3
|
-
POST /backtest { ticker, strategy_signals, lookback_days, fees, slippage }
|
|
4
|
-
POST /validate { ticker, lookback_days, train_ratio } — walk-forward split
|
|
5
|
-
GET /health
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
from __future__ import annotations
|
|
9
|
-
import os
|
|
10
|
-
import json
|
|
11
|
-
import numpy as np
|
|
12
|
-
from datetime import datetime, timedelta
|
|
13
|
-
from typing import Any
|
|
14
|
-
|
|
15
|
-
from flask import Flask, request, jsonify
|
|
16
|
-
import backtester_mcp as bt
|
|
17
|
-
|
|
18
|
-
# yfinance is the free price source — no API key required
|
|
19
|
-
try:
|
|
20
|
-
import yfinance as yf
|
|
21
|
-
YF_AVAILABLE = True
|
|
22
|
-
except ImportError:
|
|
23
|
-
YF_AVAILABLE = False
|
|
24
|
-
|
|
25
|
-
app = Flask(__name__)
|
|
26
|
-
|
|
27
|
-
# ── helpers ──────────────────────────────────────────────────────────────────
|
|
28
|
-
|
|
29
|
-
def _fetch_prices(ticker: str, days: int) -> np.ndarray:
|
|
30
|
-
if not YF_AVAILABLE:
|
|
31
|
-
raise RuntimeError("yfinance not installed")
|
|
32
|
-
end = datetime.utcnow()
|
|
33
|
-
start = end - timedelta(days=days + 30) # buffer for weekends/holidays
|
|
34
|
-
df = yf.download(ticker, start=start.strftime("%Y-%m-%d"),
|
|
35
|
-
end=end.strftime("%Y-%m-%d"), progress=False, auto_adjust=True)
|
|
36
|
-
if df.empty:
|
|
37
|
-
raise ValueError(f"No price data for {ticker}")
|
|
38
|
-
return df["Close"].dropna().values[-days:]
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
def _momentum_signals(prices: np.ndarray, window: int = 10, threshold: float = 0.001) -> np.ndarray:
|
|
42
|
-
"""Default long-only momentum signal for validation."""
|
|
43
|
-
returns = np.diff(np.log(prices))
|
|
44
|
-
mom = np.convolve(returns, np.ones(window) / window, mode="same")
|
|
45
|
-
signals = np.zeros(len(prices))
|
|
46
|
-
signals[1:] = np.where(mom[:-1] > threshold, 1, 0)
|
|
47
|
-
return signals
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
def _run_backtest(prices: np.ndarray, signals: np.ndarray,
|
|
51
|
-
fees: float, slippage: float) -> dict[str, Any]:
|
|
52
|
-
result = bt.backtest(prices, signals, fees=fees, slippage=slippage)
|
|
53
|
-
m = result.metrics
|
|
54
|
-
return {
|
|
55
|
-
"sharpe": round(m["sharpe"], 3),
|
|
56
|
-
"sortino": round(m["sortino"], 3),
|
|
57
|
-
"cagr": round(m["cagr"], 4),
|
|
58
|
-
"total_return": round(m["total_return"], 4),
|
|
59
|
-
"max_drawdown": round(m["max_drawdown"], 4),
|
|
60
|
-
"max_drawdown_duration_days": int(m["max_drawdown_duration"]),
|
|
61
|
-
"win_rate": round(m["win_rate"], 4),
|
|
62
|
-
"profit_factor": round(m["profit_factor"], 3),
|
|
63
|
-
"calmar": round(m["calmar"], 3),
|
|
64
|
-
"volatility": round(m["volatility"], 4),
|
|
65
|
-
"num_trades": int(m["num_trades"]),
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
# ── routes ───────────────────────────────────────────────────────────────────
|
|
70
|
-
|
|
71
|
-
@app.get("/health")
|
|
72
|
-
def health():
|
|
73
|
-
return jsonify({
|
|
74
|
-
"status": "ok",
|
|
75
|
-
"engine": f"backtester-mcp v{bt.__version__}",
|
|
76
|
-
"yfinance": YF_AVAILABLE,
|
|
77
|
-
"timestamp": datetime.utcnow().isoformat() + "Z",
|
|
78
|
-
})
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
@app.post("/backtest")
|
|
82
|
-
def backtest():
|
|
83
|
-
body = request.get_json(force=True)
|
|
84
|
-
ticker: str = body.get("ticker", "").upper()
|
|
85
|
-
custom_signals: list | None = body.get("signals") # optional float array
|
|
86
|
-
lookback: int = int(body.get("lookback_days", 252))
|
|
87
|
-
fees: float = float(body.get("fees", 0.001))
|
|
88
|
-
slippage: float = float(body.get("slippage", 0.0005))
|
|
89
|
-
window: int = int(body.get("momentum_window", 10))
|
|
90
|
-
threshold: float = float(body.get("momentum_threshold", 0.001))
|
|
91
|
-
|
|
92
|
-
if not ticker:
|
|
93
|
-
return jsonify({"error": "ticker required"}), 400
|
|
94
|
-
|
|
95
|
-
try:
|
|
96
|
-
prices = _fetch_prices(ticker, lookback)
|
|
97
|
-
except Exception as e:
|
|
98
|
-
return jsonify({"error": str(e)}), 422
|
|
99
|
-
|
|
100
|
-
if custom_signals:
|
|
101
|
-
signals = np.array(custom_signals, dtype=float)
|
|
102
|
-
if len(signals) != len(prices):
|
|
103
|
-
return jsonify({"error": f"signals length {len(signals)} != prices length {len(prices)}"}), 400
|
|
104
|
-
else:
|
|
105
|
-
signals = _momentum_signals(prices, window=window, threshold=threshold)
|
|
106
|
-
|
|
107
|
-
try:
|
|
108
|
-
metrics = _run_backtest(prices, signals, fees, slippage)
|
|
109
|
-
except Exception as e:
|
|
110
|
-
return jsonify({"error": str(e)}), 500
|
|
111
|
-
|
|
112
|
-
verdict = "ROBUST" if metrics["sharpe"] > 1.5 and metrics["max_drawdown"] > -0.25 else \
|
|
113
|
-
"MODERATE" if metrics["sharpe"] > 0.8 else \
|
|
114
|
-
"WEAK" if metrics["sharpe"] > 0 else "OVERFITTED"
|
|
115
|
-
|
|
116
|
-
return jsonify({
|
|
117
|
-
"ticker": ticker,
|
|
118
|
-
"lookback_days": len(prices),
|
|
119
|
-
"fees": fees,
|
|
120
|
-
"slippage": slippage,
|
|
121
|
-
"metrics": metrics,
|
|
122
|
-
"verdict": verdict,
|
|
123
|
-
"engine": f"backtester-mcp v{bt.__version__}",
|
|
124
|
-
})
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
@app.post("/validate")
|
|
128
|
-
def walk_forward():
|
|
129
|
-
"""Walk-forward OOS validation — splits data into train/test."""
|
|
130
|
-
body = request.get_json(force=True)
|
|
131
|
-
ticker: str = body.get("ticker", "").upper()
|
|
132
|
-
lookback: int = int(body.get("lookback_days", 504))
|
|
133
|
-
train_ratio: float = float(body.get("train_ratio", 0.7))
|
|
134
|
-
fees: float = float(body.get("fees", 0.001))
|
|
135
|
-
slippage: float = float(body.get("slippage", 0.0005))
|
|
136
|
-
|
|
137
|
-
if not ticker:
|
|
138
|
-
return jsonify({"error": "ticker required"}), 400
|
|
139
|
-
|
|
140
|
-
try:
|
|
141
|
-
prices = _fetch_prices(ticker, lookback)
|
|
142
|
-
except Exception as e:
|
|
143
|
-
return jsonify({"error": str(e)}), 422
|
|
144
|
-
|
|
145
|
-
split = int(len(prices) * train_ratio)
|
|
146
|
-
train_prices = prices[:split]
|
|
147
|
-
oos_prices = prices[split:]
|
|
148
|
-
|
|
149
|
-
train_signals = _momentum_signals(train_prices)
|
|
150
|
-
oos_signals = _momentum_signals(oos_prices)
|
|
151
|
-
|
|
152
|
-
try:
|
|
153
|
-
train_metrics = _run_backtest(train_prices, train_signals, fees, slippage)
|
|
154
|
-
oos_metrics = _run_backtest(oos_prices, oos_signals, fees, slippage)
|
|
155
|
-
except Exception as e:
|
|
156
|
-
return jsonify({"error": str(e)}), 500
|
|
157
|
-
|
|
158
|
-
# Deflated Sharpe — penalize if OOS degrades significantly
|
|
159
|
-
sharpe_degradation = train_metrics["sharpe"] - oos_metrics["sharpe"]
|
|
160
|
-
oos_verdict = "PASS" if oos_metrics["sharpe"] > 0.5 and sharpe_degradation < 1.5 else "FAIL"
|
|
161
|
-
|
|
162
|
-
return jsonify({
|
|
163
|
-
"ticker": ticker,
|
|
164
|
-
"train_days": len(train_prices),
|
|
165
|
-
"oos_days": len(oos_prices),
|
|
166
|
-
"train_metrics": train_metrics,
|
|
167
|
-
"oos_metrics": oos_metrics,
|
|
168
|
-
"sharpe_degradation": round(sharpe_degradation, 3),
|
|
169
|
-
"oos_verdict": oos_verdict,
|
|
170
|
-
"engine": f"backtester-mcp v{bt.__version__}",
|
|
171
|
-
})
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
if __name__ == "__main__":
|
|
175
|
-
port = int(os.environ.get("BACKTEST_PORT", 8300))
|
|
176
|
-
app.run(host="0.0.0.0", port=port, debug=False)
|
package/src/lib/chains/base.ts
DELETED
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import { createWalletClient, createPublicClient, http, parseUnits } from 'viem';
|
|
2
|
-
import { base, baseSepolia } from 'viem/chains';
|
|
3
|
-
import { privateKeyToAccount } from 'viem/accounts';
|
|
4
|
-
import { mnemonicToSeedSync } from 'bip39';
|
|
5
|
-
import HDKey from 'hdkey';
|
|
6
|
-
import { WalletManager } from '../../server/payments/wallet.js';
|
|
7
|
-
import type { RouteParams } from '../../server/payments/router.js';
|
|
8
|
-
|
|
9
|
-
// USDC contract on Base mainnet
|
|
10
|
-
const USDC_BASE = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913';
|
|
11
|
-
// USDC contract on Base Sepolia
|
|
12
|
-
const USDC_BASE_SEPOLIA = '0x036CbD53842c5426634e7929541eC2318f3dCF7e';
|
|
13
|
-
|
|
14
|
-
const ERC20_TRANSFER_ABI = [
|
|
15
|
-
{
|
|
16
|
-
name: 'transfer',
|
|
17
|
-
type: 'function',
|
|
18
|
-
inputs: [
|
|
19
|
-
{ name: 'to', type: 'address' },
|
|
20
|
-
{ name: 'amount', type: 'uint256' },
|
|
21
|
-
],
|
|
22
|
-
outputs: [{ name: '', type: 'bool' }],
|
|
23
|
-
stateMutability: 'nonpayable',
|
|
24
|
-
},
|
|
25
|
-
] as const;
|
|
26
|
-
|
|
27
|
-
export class BaseChain {
|
|
28
|
-
private static instance: BaseChain;
|
|
29
|
-
private readonly testnet: boolean;
|
|
30
|
-
|
|
31
|
-
private constructor() {
|
|
32
|
-
this.testnet = process.env['TESTNET'] === 'true';
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
static getInstance(): BaseChain {
|
|
36
|
-
if (!BaseChain.instance) {
|
|
37
|
-
BaseChain.instance = new BaseChain();
|
|
38
|
-
}
|
|
39
|
-
return BaseChain.instance;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
async sendPayment(params: RouteParams): Promise<string> {
|
|
43
|
-
const chain = this.testnet ? baseSepolia : base;
|
|
44
|
-
const rpcUrl = this.testnet
|
|
45
|
-
? (process.env['BASE_SEPOLIA_RPC_URL'] ?? 'https://sepolia.base.org')
|
|
46
|
-
: (process.env['BASE_RPC_URL'] ?? 'https://mainnet.base.org');
|
|
47
|
-
|
|
48
|
-
const privateKey = await this.getPrivateKey();
|
|
49
|
-
const account = privateKeyToAccount(privateKey);
|
|
50
|
-
|
|
51
|
-
const walletClient = createWalletClient({ account, chain, transport: http(rpcUrl) });
|
|
52
|
-
const publicClient = createPublicClient({ chain, transport: http(rpcUrl) });
|
|
53
|
-
|
|
54
|
-
const usdcAddress = this.testnet ? USDC_BASE_SEPOLIA : USDC_BASE;
|
|
55
|
-
const amount = parseUnits(params.amount, 6); // USDC has 6 decimals
|
|
56
|
-
|
|
57
|
-
const hash = await walletClient.writeContract({
|
|
58
|
-
address: usdcAddress,
|
|
59
|
-
abi: ERC20_TRANSFER_ABI,
|
|
60
|
-
functionName: 'transfer',
|
|
61
|
-
args: [params.to as `0x${string}`, amount],
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
// Wait for confirmation
|
|
65
|
-
await publicClient.waitForTransactionReceipt({ hash });
|
|
66
|
-
return hash;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
private async getPrivateKey(): Promise<`0x${string}`> {
|
|
70
|
-
const mnemonic = await WalletManager.getInstance().getSeed();
|
|
71
|
-
const seed = mnemonicToSeedSync(mnemonic);
|
|
72
|
-
const hdkey = HDKey.fromMasterSeed(seed);
|
|
73
|
-
const child = hdkey.derive("m/44'/60'/0'/0/0");
|
|
74
|
-
if (!child.privateKey) throw new Error('Key derivation failed');
|
|
75
|
-
return `0x${child.privateKey.toString('hex')}`;
|
|
76
|
-
}
|
|
77
|
-
}
|
package/src/lib/chains/solana.ts
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Connection,
|
|
3
|
-
Keypair,
|
|
4
|
-
PublicKey,
|
|
5
|
-
Transaction,
|
|
6
|
-
sendAndConfirmTransaction,
|
|
7
|
-
} from '@solana/web3.js';
|
|
8
|
-
import { createTransferInstruction, getAssociatedTokenAddress } from '@solana/spl-token';
|
|
9
|
-
import { mnemonicToSeedSync } from 'bip39';
|
|
10
|
-
import HDKey from 'hdkey';
|
|
11
|
-
import { WalletManager } from '../../server/payments/wallet.js';
|
|
12
|
-
import type { RouteParams } from '../../server/payments/router.js';
|
|
13
|
-
|
|
14
|
-
// USDC mint on Solana mainnet
|
|
15
|
-
const USDC_MINT = new PublicKey('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v');
|
|
16
|
-
|
|
17
|
-
export class SolanaChain {
|
|
18
|
-
private static instance: SolanaChain;
|
|
19
|
-
private readonly rpcUrl: string;
|
|
20
|
-
|
|
21
|
-
private constructor() {
|
|
22
|
-
this.rpcUrl = process.env['SOLANA_RPC_URL'] ?? 'https://api.mainnet-beta.solana.com';
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
static getInstance(): SolanaChain {
|
|
26
|
-
if (!SolanaChain.instance) {
|
|
27
|
-
SolanaChain.instance = new SolanaChain();
|
|
28
|
-
}
|
|
29
|
-
return SolanaChain.instance;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
async sendPayment(params: RouteParams): Promise<string> {
|
|
33
|
-
const connection = new Connection(this.rpcUrl, 'confirmed');
|
|
34
|
-
const payer = await this.getKeypair();
|
|
35
|
-
const destination = new PublicKey(params.to);
|
|
36
|
-
|
|
37
|
-
const fromATA = await getAssociatedTokenAddress(USDC_MINT, payer.publicKey);
|
|
38
|
-
const toATA = await getAssociatedTokenAddress(USDC_MINT, destination);
|
|
39
|
-
|
|
40
|
-
const lamports = Math.round(parseFloat(params.amount) * 1_000_000); // USDC 6 decimals
|
|
41
|
-
|
|
42
|
-
const tx = new Transaction().add(
|
|
43
|
-
createTransferInstruction(fromATA, toATA, payer.publicKey, BigInt(lamports)),
|
|
44
|
-
);
|
|
45
|
-
|
|
46
|
-
const sig = await sendAndConfirmTransaction(connection, tx, [payer]);
|
|
47
|
-
return sig;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
private async getKeypair(): Promise<Keypair> {
|
|
51
|
-
const mnemonic = await WalletManager.getInstance().getSeed();
|
|
52
|
-
const seed = mnemonicToSeedSync(mnemonic);
|
|
53
|
-
const hdkey = HDKey.fromMasterSeed(seed);
|
|
54
|
-
// BIP-44 for Solana: m/44'/501'/0'/0'
|
|
55
|
-
const child = hdkey.derive("m/44'/501'/0'/0'");
|
|
56
|
-
if (!child.privateKey) throw new Error('Solana key derivation failed');
|
|
57
|
-
return Keypair.fromSeed(child.privateKey.slice(0, 32));
|
|
58
|
-
}
|
|
59
|
-
}
|
package/src/lib/chains/xrpl.ts
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import { Client, Wallet, xrpToDrops } from 'xrpl';
|
|
2
|
-
import { WalletManager } from '../../server/payments/wallet.js';
|
|
3
|
-
import type { RouteParams } from '../../server/payments/router.js';
|
|
4
|
-
|
|
5
|
-
export class XRPLChain {
|
|
6
|
-
private static instance: XRPLChain;
|
|
7
|
-
private readonly rpcUrl: string;
|
|
8
|
-
|
|
9
|
-
private constructor() {
|
|
10
|
-
this.rpcUrl = process.env['XRPL_RPC_URL'] ?? 'wss://xrplcluster.com';
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
static getInstance(): XRPLChain {
|
|
14
|
-
if (!XRPLChain.instance) {
|
|
15
|
-
XRPLChain.instance = new XRPLChain();
|
|
16
|
-
}
|
|
17
|
-
return XRPLChain.instance;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
async sendPayment(params: RouteParams): Promise<string> {
|
|
21
|
-
const client = new Client(this.rpcUrl);
|
|
22
|
-
await client.connect();
|
|
23
|
-
|
|
24
|
-
try {
|
|
25
|
-
const wallet = await this.getWallet();
|
|
26
|
-
|
|
27
|
-
// RLUSD on XRPL or XRP-denominated drop equivalent
|
|
28
|
-
const tx = await client.submitAndWait(
|
|
29
|
-
{
|
|
30
|
-
TransactionType: 'Payment',
|
|
31
|
-
Account: wallet.address,
|
|
32
|
-
Destination: params.to,
|
|
33
|
-
Amount:
|
|
34
|
-
params.currency === 'RLUSD'
|
|
35
|
-
? {
|
|
36
|
-
currency: 'USD',
|
|
37
|
-
issuer: process.env['RLUSD_ISSUER'] ?? 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh',
|
|
38
|
-
value: params.amount,
|
|
39
|
-
}
|
|
40
|
-
: xrpToDrops(params.amount),
|
|
41
|
-
},
|
|
42
|
-
{ wallet },
|
|
43
|
-
);
|
|
44
|
-
|
|
45
|
-
if (tx.result.meta && typeof tx.result.meta === 'object' && 'TransactionResult' in tx.result.meta) {
|
|
46
|
-
const meta = tx.result.meta as { TransactionResult: string };
|
|
47
|
-
if (meta.TransactionResult !== 'tesSUCCESS') {
|
|
48
|
-
throw new Error(`XRPL transaction failed: ${meta.TransactionResult}`);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const txResult = tx.result as unknown as { hash?: string };
|
|
53
|
-
return txResult.hash ?? 'unknown';
|
|
54
|
-
} finally {
|
|
55
|
-
await client.disconnect();
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
private async getWallet(): Promise<Wallet> {
|
|
60
|
-
const mnemonic = await WalletManager.getInstance().getSeed();
|
|
61
|
-
return Wallet.fromMnemonic(mnemonic, { mnemonicEncoding: 'bip39' });
|
|
62
|
-
}
|
|
63
|
-
}
|
package/src/lib/credit/bureau.ts
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
interface ScoreCache {
|
|
2
|
-
score: number;
|
|
3
|
-
fetchedAt: number;
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
const SCORE_CACHE_TTL = 300_000; // 5 minutes
|
|
7
|
-
|
|
8
|
-
export class CreditBureau {
|
|
9
|
-
private static instance: CreditBureau;
|
|
10
|
-
private readonly cache = new Map<string, ScoreCache>();
|
|
11
|
-
private readonly baseUrl: string;
|
|
12
|
-
|
|
13
|
-
private constructor() {
|
|
14
|
-
this.baseUrl = process.env['PROOF402_URL'] ?? 'https://four02proof.onrender.com';
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
static getInstance(): CreditBureau {
|
|
18
|
-
if (!CreditBureau.instance) {
|
|
19
|
-
CreditBureau.instance = new CreditBureau();
|
|
20
|
-
}
|
|
21
|
-
return CreditBureau.instance;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
async getScore(wallet: string): Promise<number> {
|
|
25
|
-
const now = Date.now();
|
|
26
|
-
const cached = this.cache.get(wallet);
|
|
27
|
-
|
|
28
|
-
if (cached && now - cached.fetchedAt < SCORE_CACHE_TTL) {
|
|
29
|
-
return cached.score;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
try {
|
|
33
|
-
const res = await fetch(`${this.baseUrl}/v1/score/${wallet}`, {
|
|
34
|
-
signal: AbortSignal.timeout(5000),
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
if (res.ok) {
|
|
38
|
-
const body = (await res.json()) as { score: number };
|
|
39
|
-
this.cache.set(wallet, { score: body.score, fetchedAt: now });
|
|
40
|
-
return body.score;
|
|
41
|
-
}
|
|
42
|
-
} catch {
|
|
43
|
-
// Fall through to default
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// Default score for new/unknown agents
|
|
47
|
-
const defaultScore = 300;
|
|
48
|
-
this.cache.set(wallet, { score: defaultScore, fetchedAt: now });
|
|
49
|
-
return defaultScore;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
async incrementScore(wallet: string, delta: number): Promise<void> {
|
|
53
|
-
try {
|
|
54
|
-
await fetch(`${this.baseUrl}/v1/score/${wallet}/increment`, {
|
|
55
|
-
method: 'POST',
|
|
56
|
-
headers: { 'Content-Type': 'application/json' },
|
|
57
|
-
body: JSON.stringify({ delta }),
|
|
58
|
-
});
|
|
59
|
-
// Invalidate cache
|
|
60
|
-
this.cache.delete(wallet);
|
|
61
|
-
} catch {
|
|
62
|
-
// Non-fatal
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|