@1ly/mcp-server 0.1.3 → 0.1.5

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 CHANGED
@@ -6,47 +6,68 @@ MCP server for [1ly.store](https://1ly.store) — Enable AI agents to discover,
6
6
 
7
7
  This MCP server gives AI agents the ability to:
8
8
 
9
- - **Buy** — Search, discover, and pay for APIs, resources with automatic crypto payments (x402 protocol)
9
+ - **Buy** — Search, discover, and pay for APIs/resources with automatic crypto payments (x402 protocol)
10
10
  - **Sell** — Create a store, list paid API endpoints or resources, and accept payments
11
11
 
12
12
  **Supported Networks:** Solana (mainnet), Base (mainnet)
13
13
  **Payment Currency:** USDC
14
14
 
15
15
  ## What is this?
16
- This MCP server enables AI agents (Claude, GPT, Cursor, or any AI Agents etc.) to:
16
+ This MCP server enables AI agents (Claude, GPT, Cursor, and more) to:
17
17
 
18
- Create store on 1ly.store
19
- Accept payments for your own APIs/resources using 1ly as the payment layer
20
- Create paid links that any x402‑compatible agent can call and pay automatically
21
- Paid links are listed on the 1ly marketplace by default for instant agent discovery
22
- Search for APIs and services on 1ly.store
23
- Get details about pricing, reviews, and usage
24
- Call paid APIs with automatic crypto payments (x402 protocol) in secure way.
25
- Leave reviews after purchases, optional but recommended to make better experience for 1ly users
18
+ - Create a store on 1ly.store
19
+ - Accept payments for your APIs/resources using 1ly as the payment layer
20
+ - Create paid links that any x402‑compatible agent can call and pay automatically
21
+ - List paid links on the 1ly marketplace for instant agent discovery
22
+ - Search for APIs and services on 1ly.store
23
+ - Get details about pricing, reviews, and usage
24
+ - Call paid APIs with automatic crypto payments (x402 protocol) securely
25
+ - Leave reviews after purchases (optional but recommended)
26
26
 
27
27
  ---
28
28
 
29
29
  ## Quick Start
30
30
 
31
+ **Wallet path rule:** wallet files must be located in your home directory (recommended) or `/tmp`. Paths outside those locations are rejected for security. `~/` is supported and expands to your home directory.
32
+
31
33
  ### 1. Install and Run
32
34
 
35
+ #### Option A: Raw Wallet (default)
36
+
33
37
  ```bash
34
38
  # Solana wallet
35
- ONELY_WALLET_SOLANA_KEY="/path/to/solana-wallet.json" npx @1ly/mcp-server
39
+ ONELY_WALLET_SOLANA_KEY="~/.1ly/wallets/solana.json" npx @1ly/mcp-server
36
40
 
37
41
  # OR Base/EVM wallet
38
- ONELY_WALLET_EVM_KEY="/path/to/evm.key" npx @1ly/mcp-server
42
+ ONELY_WALLET_EVM_KEY="~/.1ly/wallets/evm.key" npx @1ly/mcp-server
39
43
 
40
44
  # OR both wallets
41
- ONELY_WALLET_SOLANA_KEY="/path/to/solana-wallet.json" \
42
- ONELY_WALLET_EVM_KEY="/path/to/evm.key" \
45
+ ONELY_WALLET_SOLANA_KEY="~/.1ly/wallets/solana.json" \
46
+ ONELY_WALLET_EVM_KEY="~/.1ly/wallets/evm.key" \
43
47
  npx @1ly/mcp-server
44
48
  ```
45
49
 
50
+ #### Option B: Coinbase Agentic Wallet (Base only)
51
+
52
+ ```bash
53
+ ONELY_WALLET_PROVIDER="coinbase" npx @1ly/mcp-server
54
+ ```
55
+
56
+ > When using Agentic Wallet, you **do not** pass raw private keys.
57
+ > Make sure the Coinbase Agentic Wallet app is running and authenticated.
58
+
59
+ If you haven't installed Agentic Wallet yet:
60
+ - Follow Coinbase Agentic Wallet docs: `https://docs.cdp.coinbase.com/agentic-wallet/welcome`
61
+ - Quick install:
62
+ ```bash
63
+ npx skills add coinbase/agentic-wallet-skills
64
+ npx awal show
65
+ ```
66
+
46
67
  ### 2. Verify Setup
47
68
 
48
69
  ```bash
49
- ONELY_WALLET_SOLANA_KEY="/path/to/solana-wallet.json" npx @1ly/mcp-server --self-test
70
+ ONELY_WALLET_SOLANA_KEY="~/.1ly/wallets/solana.json" npx @1ly/mcp-server --self-test
50
71
  ```
51
72
 
52
73
  ---
@@ -57,16 +78,18 @@ ONELY_WALLET_SOLANA_KEY="/path/to/solana-wallet.json" npx @1ly/mcp-server --self
57
78
 
58
79
  | Variable | Required | Description |
59
80
  |----------|----------|-------------|
60
- | `ONELY_WALLET_SOLANA_KEY` | Yes* | Path to Solana keypair JSON file, or inline JSON array |
61
- | `ONELY_WALLET_EVM_KEY` | Yes* | Path to EVM private key file, or inline hex key (with or without `0x`) |
81
+ | `ONELY_WALLET_SOLANA_KEY` | No | Path to Solana keypair JSON file, or inline JSON array |
82
+ | `ONELY_WALLET_EVM_KEY` | No | Path to EVM private key file, or inline hex key (with or without `0x`) |
62
83
  | `ONELY_API_KEY` | No | API key for seller tools. Auto-loaded after `1ly_create_store` |
63
84
  | `ONELY_BUDGET_PER_CALL` | No | Max USD per API call (default: `1.00`) |
64
85
  | `ONELY_BUDGET_DAILY` | No | Daily USD spending limit (default: `50.00`) |
65
86
  | `ONELY_BUDGET_STATE_FILE` | No | Path to local budget state file (default: `~/.1ly-mcp-budget.json`) |
66
87
  | `ONELY_NETWORK` | No | Preferred network: `solana` or `base` (default: `solana`) |
67
88
  | `ONELY_API_BASE` | No | API base URL (default: `https://1ly.store`) |
89
+ | `ONELY_WALLET_PROVIDER` | No | `raw` (default) or `coinbase` (Agentic Wallet, Base-only) |
68
90
 
69
- *At least one wallet is required for payments.
91
+ *A wallet is required only for **paid** calls. For free search/details you can run without a wallet.*
92
+ Use **one** of: `ONELY_WALLET_SOLANA_KEY`, `ONELY_WALLET_EVM_KEY`, or `ONELY_WALLET_PROVIDER=coinbase`.
70
93
 
71
94
  ### Claude Desktop Configuration
72
95
 
@@ -79,7 +102,7 @@ Add to `claude_desktop_config.json`:
79
102
  "command": "npx",
80
103
  "args": ["@1ly/mcp-server"],
81
104
  "env": {
82
- "ONELY_WALLET_SOLANA_KEY": "/absolute/path/to/solana-wallet.json",
105
+ "ONELY_WALLET_SOLANA_KEY": "~/.1ly/wallets/solana.json",
83
106
  "ONELY_BUDGET_PER_CALL": "1.00",
84
107
  "ONELY_BUDGET_DAILY": "50.00"
85
108
  }
@@ -98,7 +121,7 @@ Add to `claude_desktop_config.json`:
98
121
  "command": "npx",
99
122
  "args": ["@1ly/mcp-server"],
100
123
  "env": {
101
- "ONELY_WALLET_EVM_KEY": "/absolute/path/to/evm.key",
124
+ "ONELY_WALLET_EVM_KEY": "~/.1ly/wallets/evm.key",
102
125
  "ONELY_BUDGET_PER_CALL": "1.00",
103
126
  "ONELY_BUDGET_DAILY": "50.00"
104
127
  }
@@ -118,8 +141,8 @@ Add to `claude_desktop_config.json`:
118
141
  "command": "npx",
119
142
  "args": ["@1ly/mcp-server"],
120
143
  "env": {
121
- "ONELY_WALLET_SOLANA_KEY": "/absolute/path/to/solana-wallet.json",
122
- "ONELY_WALLET_EVM_KEY": "/absolute/path/to/evm.key",
144
+ "ONELY_WALLET_SOLANA_KEY": "~/.1ly/wallets/solana.json",
145
+ "ONELY_WALLET_EVM_KEY": "~/.1ly/wallets/evm.key",
123
146
  "ONELY_BUDGET_PER_CALL": "1.00",
124
147
  "ONELY_BUDGET_DAILY": "50.00"
125
148
  }
@@ -133,9 +156,9 @@ Add to `claude_desktop_config.json`:
133
156
 
134
157
  ## Tools Reference
135
158
 
136
- ### Buyer Tools (Pay for APIs)
159
+ ### Buyer Tools
137
160
 
138
- These tools require a **wallet** configured.
161
+ Wallet **required only for paid calls** (`1ly_call`). Search/details work without a wallet.
139
162
 
140
163
  #### `1ly_search`
141
164
 
@@ -260,6 +283,11 @@ Call a paid API with automatic crypto payment.
260
283
  > **Note:** The `_1ly` object contains tokens needed for `1ly_review`. Save these if you want to leave a review.
261
284
  > For free APIs, `_1ly` may be `{ "note": "No payment required (free API)" }`.
262
285
 
286
+ **Agentic Wallet (Base only):**
287
+ - Set `ONELY_WALLET_PROVIDER=coinbase`.
288
+ - Ensure Coinbase Agentic Wallet is installed, running, and authenticated.
289
+ - Local private keys are not required.
290
+
263
291
  ---
264
292
 
265
293
  #### `1ly_review`
@@ -684,7 +712,7 @@ Update store avatar using a public URL or base64 image.
684
712
  | Parameter | Type | Required | Description |
685
713
  |-----------|------|----------|-------------|
686
714
  | `avatarUrl` | string | No | Public image URL |
687
- | `imageBase64` | string | No | Base64-encoded image bytes |
715
+ | `imageBase64` | string | No | Base64-encoded image (max 5MB decoded) |
688
716
  | `mimeType` | string | No | `image/png`, `image/jpeg`, `image/webp`, `image/gif` |
689
717
  | `filename` | string | No | Optional filename |
690
718
 
@@ -781,16 +809,18 @@ List recent withdrawals.
781
809
 
782
810
  Create a new keypair:
783
811
  ```bash
784
- solana-keygen new -o ./wallets/solana.json
812
+ mkdir -p ~/.1ly/wallets
813
+ solana-keygen new -o ~/.1ly/wallets/solana.json
785
814
  ```
786
815
 
787
816
  Fund with USDC on Solana mainnet.
788
817
 
789
818
  ### EVM (Base)
790
819
 
791
- Export your private key from MetaMask/Rabby and save to a file:
820
+ Export your private key or Create a new keypair:
792
821
  ```bash
793
- echo "0xYOUR_PRIVATE_KEY" > ./wallets/evm.key
822
+ mkdir -p ~/.1ly/wallets
823
+ echo "0xYOUR_PRIVATE_KEY" > ~/.1ly/wallets/evm.key
794
824
  ```
795
825
 
796
826
  Fund with USDC on Base mainnet.
@@ -821,7 +851,9 @@ All responses follow this structure:
821
851
 
822
852
  | Error | Cause | Solution |
823
853
  |-------|-------|----------|
824
- | `Missing wallet config` | No wallet env var set | Set `ONELY_WALLET_SOLANA_KEY` or `ONELY_WALLET_EVM_KEY` |
854
+ | `Missing wallet config` | No wallet env var set | Set `ONELY_WALLET_SOLANA_KEY`, `ONELY_WALLET_EVM_KEY`, or `ONELY_WALLET_PROVIDER=coinbase` |
855
+ | `Agentic Wallet not running` | Wallet app not running or not authenticated | Open the Agentic Wallet app and sign in (`npx awal show`) |
856
+ | `Agentic Wallet Base-only` | API requires Solana payment | Use raw Solana wallet or a Base-compatible endpoint |
825
857
  | `Missing ONELY_API_KEY` | Seller tool called without API key | Run `1ly_create_store` first |
826
858
  | `Price exceeds per-call budget` | API costs more than limit | Increase `ONELY_BUDGET_PER_CALL` |
827
859
  | `Daily budget exceeded` | Spent more than daily limit | Wait until tomorrow or increase `ONELY_BUDGET_DAILY` |
@@ -1 +1 @@
1
- {"version":3,"file":"budget.d.ts","sourceRoot":"","sources":["../src/budget.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAmD1C;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAuB/E"}
1
+ {"version":3,"file":"budget.d.ts","sourceRoot":"","sources":["../src/budget.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AA0D1C;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAuC/E"}
package/dist/budget.js CHANGED
@@ -7,9 +7,13 @@ exports.checkAndRecordDailySpend = checkAndRecordDailySpend;
7
7
  const fs_1 = __importDefault(require("fs"));
8
8
  const os_1 = __importDefault(require("os"));
9
9
  const path_1 = __importDefault(require("path"));
10
+ const security_log_js_1 = require("./security-log.js");
10
11
  function getBudgetStatePath() {
11
12
  const envPath = process.env.ONELY_BUDGET_STATE_FILE;
12
13
  if (envPath && envPath.trim().length > 0) {
14
+ if (envPath.startsWith("~/")) {
15
+ return path_1.default.join(os_1.default.homedir(), envPath.slice(2));
16
+ }
13
17
  return envPath;
14
18
  }
15
19
  return path_1.default.join(os_1.default.homedir(), ".1ly-mcp-budget.json");
@@ -37,7 +41,10 @@ function loadBudgetState() {
37
41
  function saveBudgetState(state) {
38
42
  const filePath = getBudgetStatePath();
39
43
  try {
40
- fs_1.default.writeFileSync(filePath, JSON.stringify(state, null, 2), { encoding: "utf-8" });
44
+ fs_1.default.writeFileSync(filePath, JSON.stringify(state, null, 2), {
45
+ encoding: "utf-8",
46
+ mode: 0o600, // Owner read/write only (security: prevent other users from reading spending data)
47
+ });
41
48
  }
42
49
  catch {
43
50
  // If we cannot persist, we still allow the call; fail-open is safer for UX
@@ -53,6 +60,14 @@ function checkAndRecordDailySpend(config, priceUsd) {
53
60
  const current = state.date === today ? state.spentToday : 0;
54
61
  const next = current + priceUsd;
55
62
  if (next > config.budgets.daily) {
63
+ // Log budget violation for audit trail
64
+ (0, security_log_js_1.logSecurityEvent)("budget_exceeded", {
65
+ type: "daily",
66
+ currentSpent: current,
67
+ limit: config.budgets.daily,
68
+ attemptedAmount: priceUsd,
69
+ wouldTotal: next,
70
+ });
56
71
  throw new Error(`Price $${priceUsd.toFixed(4)} would exceed daily budget of $${config.budgets.daily} (already spent: $${current.toFixed(4)})`);
57
72
  }
58
73
  const updated = {
@@ -60,5 +75,11 @@ function checkAndRecordDailySpend(config, priceUsd) {
60
75
  spentToday: next,
61
76
  };
62
77
  saveBudgetState(updated);
78
+ // Log successful payment for audit trail
79
+ (0, security_log_js_1.logSecurityEvent)("api_call_paid", {
80
+ amount: priceUsd,
81
+ dailyTotal: next,
82
+ dailyLimit: config.budgets.daily,
83
+ });
63
84
  }
64
85
  //# sourceMappingURL=budget.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"budget.js","sourceRoot":"","sources":["../src/budget.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"budget.js","sourceRoot":"","sources":["../src/budget.ts"],"names":[],"mappings":"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"}
package/dist/config.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { z } from "zod";
2
2
  export declare const ConfigSchema: z.ZodObject<{
3
- apiBase: z.ZodDefault<z.ZodString>;
3
+ apiBase: z.ZodDefault<z.ZodEffects<z.ZodString, string, string>>;
4
4
  wallet: z.ZodNullable<z.ZodOptional<z.ZodObject<{
5
5
  type: z.ZodEnum<["solana", "evm"]>;
6
6
  key: z.ZodString;
@@ -24,6 +24,7 @@ export declare const ConfigSchema: z.ZodObject<{
24
24
  daily?: number | undefined;
25
25
  }>;
26
26
  network: z.ZodDefault<z.ZodEnum<["solana", "base"]>>;
27
+ walletProvider: z.ZodDefault<z.ZodEnum<["raw", "coinbase"]>>;
27
28
  apiKey: z.ZodNullable<z.ZodOptional<z.ZodString>>;
28
29
  }, "strip", z.ZodTypeAny, {
29
30
  apiBase: string;
@@ -32,6 +33,7 @@ export declare const ConfigSchema: z.ZodObject<{
32
33
  daily: number;
33
34
  };
34
35
  network: "solana" | "base";
36
+ walletProvider: "raw" | "coinbase";
35
37
  wallet?: {
36
38
  type: "solana" | "evm";
37
39
  key: string;
@@ -52,6 +54,7 @@ export declare const ConfigSchema: z.ZodObject<{
52
54
  walletSolana?: string | null | undefined;
53
55
  walletEvm?: string | null | undefined;
54
56
  network?: "solana" | "base" | undefined;
57
+ walletProvider?: "raw" | "coinbase" | undefined;
55
58
  apiKey?: string | null | undefined;
56
59
  }>;
57
60
  export type Config = z.infer<typeof ConfigSchema>;
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiBvB,CAAC;AAEH,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAElD,wBAAgB,UAAU,IAAI,MAAM,CAoBnC;AAED,wBAAsB,uBAAuB,IAAI,OAAO,CAAC,MAAM,CAAC,CAK/D"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+CvB,CAAC;AAEH,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAElD,wBAAgB,UAAU,IAAI,MAAM,CAqEnC;AAED,wBAAsB,uBAAuB,IAAI,OAAO,CAAC,MAAM,CAAC,CAK/D"}
package/dist/config.js CHANGED
@@ -5,8 +5,32 @@ exports.loadConfig = loadConfig;
5
5
  exports.loadConfigWithStoredKey = loadConfigWithStoredKey;
6
6
  const zod_1 = require("zod");
7
7
  const keys_js_1 = require("./keys.js");
8
+ const security_log_js_1 = require("./security-log.js");
8
9
  exports.ConfigSchema = zod_1.z.object({
9
- apiBase: zod_1.z.string().url().default("https://1ly.store"),
10
+ apiBase: zod_1.z
11
+ .string()
12
+ .url()
13
+ .refine((url) => {
14
+ try {
15
+ const parsed = new URL(url);
16
+ // Allow 1ly.store with HTTPS only
17
+ if (parsed.hostname === "1ly.store" || parsed.hostname === "www.1ly.store") {
18
+ return parsed.protocol === "https:";
19
+ }
20
+ // Allow localhost for local development (any port)
21
+ if (parsed.hostname === "localhost" || parsed.hostname === "127.0.0.1") {
22
+ return true;
23
+ }
24
+ // Block everything else
25
+ return false;
26
+ }
27
+ catch {
28
+ return false;
29
+ }
30
+ }, {
31
+ message: "API base must be https://1ly.store or http://localhost:PORT for local development",
32
+ })
33
+ .default("https://1ly.store"),
10
34
  wallet: zod_1.z
11
35
  .object({
12
36
  type: zod_1.z.enum(["solana", "evm"]),
@@ -17,10 +41,11 @@ exports.ConfigSchema = zod_1.z.object({
17
41
  walletSolana: zod_1.z.string().optional().nullable(),
18
42
  walletEvm: zod_1.z.string().optional().nullable(),
19
43
  budgets: zod_1.z.object({
20
- perCall: zod_1.z.number().positive().default(1.0),
21
- daily: zod_1.z.number().positive().default(50.0),
44
+ perCall: zod_1.z.number().positive().finite().default(1.0),
45
+ daily: zod_1.z.number().positive().finite().default(50.0),
22
46
  }),
23
47
  network: zod_1.z.enum(["solana", "base"]).default("solana"),
48
+ walletProvider: zod_1.z.enum(["raw", "coinbase"]).default("raw"),
24
49
  apiKey: zod_1.z.string().optional().nullable(),
25
50
  });
26
51
  function loadConfig() {
@@ -30,18 +55,59 @@ function loadConfig() {
30
55
  const walletEvm = process.env.ONELY_WALLET_EVM_KEY || null;
31
56
  const apiKeyEnv = process.env.ONELY_API_KEY || null;
32
57
  const apiBase = process.env.ONELY_API_BASE || "https://1ly.store";
33
- return exports.ConfigSchema.parse({
34
- apiBase,
35
- wallet: walletType && walletKey ? { type: walletType, key: walletKey } : null,
36
- walletSolana: walletSolana || (walletType === "solana" ? walletKey : null),
37
- walletEvm: walletEvm || (walletType === "evm" ? walletKey : null),
38
- budgets: {
39
- perCall: parseFloat(process.env.ONELY_BUDGET_PER_CALL || "1.0"),
40
- daily: parseFloat(process.env.ONELY_BUDGET_DAILY || "50.0"),
41
- },
42
- network: process.env.ONELY_NETWORK || "solana",
43
- apiKey: apiKeyEnv,
44
- });
58
+ const walletProvider = process.env.ONELY_WALLET_PROVIDER === "coinbase" ? "coinbase" : "raw";
59
+ // Parse and validate budget values to prevent NaN/negative bypasses
60
+ const perCallRaw = process.env.ONELY_BUDGET_PER_CALL || "1.0";
61
+ const dailyRaw = process.env.ONELY_BUDGET_DAILY || "50.0";
62
+ const perCall = parseFloat(perCallRaw);
63
+ const daily = parseFloat(dailyRaw);
64
+ // Validate parsed values are valid positive numbers
65
+ if (!Number.isFinite(perCall) || perCall <= 0) {
66
+ (0, security_log_js_1.logSecurityEvent)("invalid_budget_config", {
67
+ parameter: "ONELY_BUDGET_PER_CALL",
68
+ value: perCallRaw,
69
+ parsed: perCall,
70
+ });
71
+ throw new Error(`Invalid ONELY_BUDGET_PER_CALL: "${perCallRaw}" - must be a positive number`);
72
+ }
73
+ if (!Number.isFinite(daily) || daily <= 0) {
74
+ (0, security_log_js_1.logSecurityEvent)("invalid_budget_config", {
75
+ parameter: "ONELY_BUDGET_DAILY",
76
+ value: dailyRaw,
77
+ parsed: daily,
78
+ });
79
+ throw new Error(`Invalid ONELY_BUDGET_DAILY: "${dailyRaw}" - must be a positive number`);
80
+ }
81
+ let parsedConfig;
82
+ try {
83
+ parsedConfig = exports.ConfigSchema.parse({
84
+ apiBase,
85
+ wallet: walletType && walletKey ? { type: walletType, key: walletKey } : null,
86
+ walletSolana: walletSolana || (walletType === "solana" ? walletKey : null),
87
+ walletEvm: walletEvm || (walletType === "evm" ? walletKey : null),
88
+ budgets: {
89
+ perCall,
90
+ daily,
91
+ },
92
+ network: process.env.ONELY_NETWORK || "solana",
93
+ walletProvider,
94
+ apiKey: apiKeyEnv,
95
+ });
96
+ }
97
+ catch (err) {
98
+ // Log API base violations
99
+ if (err instanceof zod_1.z.ZodError) {
100
+ const apiBaseError = err.errors.find((e) => e.path[0] === "apiBase");
101
+ if (apiBaseError) {
102
+ (0, security_log_js_1.logSecurityEvent)("api_base_violation", {
103
+ attempted: apiBase,
104
+ error: apiBaseError.message,
105
+ });
106
+ }
107
+ }
108
+ throw err;
109
+ }
110
+ return parsedConfig;
45
111
  }
46
112
  async function loadConfigWithStoredKey() {
47
113
  const config = loadConfig();
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
package/dist/http.d.ts CHANGED
@@ -14,6 +14,7 @@ export declare class HttpError extends Error {
14
14
  }
15
15
  /**
16
16
  * fetchWithTimeout wraps the global fetch with:
17
+ * - rate limiting to prevent abuse
17
18
  * - per-request timeout using AbortController
18
19
  * - basic retry logic for network/timeout errors
19
20
  */
@@ -21,6 +22,7 @@ export declare function fetchWithTimeout(url: string, options?: FetchOptions): P
21
22
  /**
22
23
  * Helper to throw a rich HttpError when response.ok is false.
23
24
  * Reads a small snippet of the body (if any) for easier debugging.
25
+ * Redacts sensitive information before including in error message.
24
26
  */
25
27
  export declare function assertOk(response: Response, contextMessage: string): Promise<void>;
26
28
  //# sourceMappingURL=http.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,YAAa,SAAQ,WAAW;IAC/C,wDAAwD;IACxD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iEAAiE;IACjE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2DAA2D;IAC3D,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,qBAAa,SAAU,SAAQ,KAAK;aAGhB,MAAM,CAAC,EAAE,MAAM;aACf,GAAG,CAAC,EAAE,MAAM;aACZ,WAAW,CAAC,EAAE,MAAM;gBAHpC,OAAO,EAAE,MAAM,EACC,MAAM,CAAC,EAAE,MAAM,YAAA,EACf,GAAG,CAAC,EAAE,MAAM,YAAA,EACZ,WAAW,CAAC,EAAE,MAAM,YAAA;CAKvC;AAMD;;;;GAIG;AACH,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC,QAAQ,CAAC,CA4CnB;AAED;;;GAGG;AACH,wBAAsB,QAAQ,CAC5B,QAAQ,EAAE,QAAQ,EAClB,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,IAAI,CAAC,CAqBf"}
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,YAAa,SAAQ,WAAW;IAC/C,wDAAwD;IACxD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iEAAiE;IACjE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2DAA2D;IAC3D,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,qBAAa,SAAU,SAAQ,KAAK;aAGhB,MAAM,CAAC,EAAE,MAAM;aACf,GAAG,CAAC,EAAE,MAAM;aACZ,WAAW,CAAC,EAAE,MAAM;gBAHpC,OAAO,EAAE,MAAM,EACC,MAAM,CAAC,EAAE,MAAM,YAAA,EACf,GAAG,CAAC,EAAE,MAAM,YAAA,EACZ,WAAW,CAAC,EAAE,MAAM,YAAA;CAKvC;AAsBD;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC,QAAQ,CAAC,CAmDnB;AAED;;;;GAIG;AACH,wBAAsB,QAAQ,CAC5B,QAAQ,EAAE,QAAQ,EAClB,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,IAAI,CAAC,CAuBf"}
package/dist/http.js CHANGED
@@ -3,9 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.HttpError = void 0;
4
4
  exports.fetchWithTimeout = fetchWithTimeout;
5
5
  exports.assertOk = assertOk;
6
+ const rate_limit_js_1 = require("./rate-limit.js");
6
7
  const DEFAULT_TIMEOUT_MS = 15_000;
7
8
  const DEFAULT_RETRIES = 2;
8
9
  const DEFAULT_RETRY_DELAY_MS = 500;
10
+ // Global rate limiter: 100 requests per minute to prevent abuse
11
+ const globalRateLimiter = new rate_limit_js_1.RateLimiter(100, 60_000);
9
12
  class HttpError extends Error {
10
13
  status;
11
14
  url;
@@ -22,12 +25,32 @@ exports.HttpError = HttpError;
22
25
  function sleep(ms) {
23
26
  return new Promise((resolve) => setTimeout(resolve, ms));
24
27
  }
28
+ /**
29
+ * Redacts sensitive information from error messages
30
+ */
31
+ function redactSensitive(text) {
32
+ return text
33
+ .replace(/1ly_live_[a-zA-Z0-9]+/g, "1ly_live_***") // API keys
34
+ .replace(/1ly_test_[a-zA-Z0-9]+/g, "1ly_test_***") // Test API keys
35
+ .replace(/[13][a-km-zA-HJ-NP-Z1-9]{25,34}/g, "***") // Bitcoin/Solana addresses
36
+ .replace(/0x[a-fA-F0-9]{40}/g, "0x***") // Ethereum addresses
37
+ .replace(/"apiKey"\s*:\s*"[^"]+"/g, '"apiKey":"***"')
38
+ .replace(/"token"\s*:\s*"[^"]+"/g, '"token":"***"')
39
+ .replace(/"reviewToken"\s*:\s*"[^"]+"/g, '"reviewToken":"***"')
40
+ .replace(/"privateKey"\s*:\s*"[^"]+"/g, '"privateKey":"***"')
41
+ .replace(/"secretKey"\s*:\s*\[[^\]]+\]/g, '"secretKey":"***"');
42
+ }
25
43
  /**
26
44
  * fetchWithTimeout wraps the global fetch with:
45
+ * - rate limiting to prevent abuse
27
46
  * - per-request timeout using AbortController
28
47
  * - basic retry logic for network/timeout errors
29
48
  */
30
49
  async function fetchWithTimeout(url, options = {}) {
50
+ // Rate limit check
51
+ if (!globalRateLimiter.check()) {
52
+ throw new Error(`Rate limit exceeded: too many requests (max 100 per minute). Current: ${globalRateLimiter.getCurrentCount()}`);
53
+ }
31
54
  const { timeoutMs = DEFAULT_TIMEOUT_MS, retries = DEFAULT_RETRIES, retryDelayMs = DEFAULT_RETRY_DELAY_MS, ...fetchOptions } = options;
32
55
  let lastError;
33
56
  for (let attempt = 0; attempt <= retries; attempt++) {
@@ -60,6 +83,7 @@ async function fetchWithTimeout(url, options = {}) {
60
83
  /**
61
84
  * Helper to throw a rich HttpError when response.ok is false.
62
85
  * Reads a small snippet of the body (if any) for easier debugging.
86
+ * Redacts sensitive information before including in error message.
63
87
  */
64
88
  async function assertOk(response, contextMessage) {
65
89
  if (response.ok)
@@ -67,7 +91,9 @@ async function assertOk(response, contextMessage) {
67
91
  let bodySnippet;
68
92
  try {
69
93
  const text = await response.text();
70
- bodySnippet = text.slice(0, 500);
94
+ // Redact sensitive data before including in error
95
+ const redacted = redactSensitive(text.slice(0, 500));
96
+ bodySnippet = redacted;
71
97
  }
72
98
  catch {
73
99
  // Ignore body read errors
package/dist/http.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -34,7 +34,7 @@ async function main() {
34
34
  }
35
35
  const server = new index_js_1.Server({
36
36
  name: "1ly",
37
- version: "0.1.2",
37
+ version: "0.1.5",
38
38
  }, {
39
39
  capabilities: {
40
40
  tools: {},
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Simple token bucket rate limiter to prevent API abuse
3
+ * Limits number of requests within a sliding time window
4
+ */
5
+ export declare class RateLimiter {
6
+ private maxRequests;
7
+ private windowMs;
8
+ private timestamps;
9
+ constructor(maxRequests: number, windowMs: number);
10
+ /**
11
+ * Check if request is allowed. Returns true if allowed, false if rate limit exceeded.
12
+ * Automatically records the request if allowed.
13
+ */
14
+ check(): boolean;
15
+ /**
16
+ * Get current request count within the window
17
+ */
18
+ getCurrentCount(): number;
19
+ /**
20
+ * Reset the rate limiter
21
+ */
22
+ reset(): void;
23
+ }
24
+ //# sourceMappingURL=rate-limit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limit.d.ts","sourceRoot":"","sources":["../src/rate-limit.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,qBAAa,WAAW;IAIpB,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,QAAQ;IAJlB,OAAO,CAAC,UAAU,CAAgB;gBAGxB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM;IAG1B;;;OAGG;IACH,KAAK,IAAI,OAAO;IAiBhB;;OAEG;IACH,eAAe,IAAI,MAAM;IAOzB;;OAEG;IACH,KAAK,IAAI,IAAI;CAGd"}
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RateLimiter = void 0;
4
+ /**
5
+ * Simple token bucket rate limiter to prevent API abuse
6
+ * Limits number of requests within a sliding time window
7
+ */
8
+ class RateLimiter {
9
+ maxRequests;
10
+ windowMs;
11
+ timestamps = [];
12
+ constructor(maxRequests, windowMs) {
13
+ this.maxRequests = maxRequests;
14
+ this.windowMs = windowMs;
15
+ }
16
+ /**
17
+ * Check if request is allowed. Returns true if allowed, false if rate limit exceeded.
18
+ * Automatically records the request if allowed.
19
+ */
20
+ check() {
21
+ const now = Date.now();
22
+ const cutoff = now - this.windowMs;
23
+ // Remove timestamps outside the window
24
+ this.timestamps = this.timestamps.filter((t) => t > cutoff);
25
+ // Check if we're at the limit
26
+ if (this.timestamps.length >= this.maxRequests) {
27
+ return false;
28
+ }
29
+ // Record this request
30
+ this.timestamps.push(now);
31
+ return true;
32
+ }
33
+ /**
34
+ * Get current request count within the window
35
+ */
36
+ getCurrentCount() {
37
+ const now = Date.now();
38
+ const cutoff = now - this.windowMs;
39
+ this.timestamps = this.timestamps.filter((t) => t > cutoff);
40
+ return this.timestamps.length;
41
+ }
42
+ /**
43
+ * Reset the rate limiter
44
+ */
45
+ reset() {
46
+ this.timestamps = [];
47
+ }
48
+ }
49
+ exports.RateLimiter = RateLimiter;
50
+ //# sourceMappingURL=rate-limit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limit.js","sourceRoot":"","sources":["../src/rate-limit.ts"],"names":[],"mappings":";;;AAAA;;;GAGG;AACH,MAAa,WAAW;IAIZ;IACA;IAJF,UAAU,GAAa,EAAE,CAAC;IAElC,YACU,WAAmB,EACnB,QAAgB;QADhB,gBAAW,GAAX,WAAW,CAAQ;QACnB,aAAQ,GAAR,QAAQ,CAAQ;IACvB,CAAC;IAEJ;;;OAGG;IACH,KAAK;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC;QAEnC,uCAAuC;QACvC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC;QAE5D,8BAA8B;QAC9B,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YAC/C,OAAO,KAAK,CAAC;QACf,CAAC;QAED,sBAAsB;QACtB,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC1B,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;OAEG;IACH,eAAe;QACb,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC;QACnC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC;QAC5D,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC;IAChC,CAAC;IAED;;OAEG;IACH,KAAK;QACH,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC;IACvB,CAAC;CACF;AA7CD,kCA6CC"}