@1ly/mcp-server 0.1.2 → 0.1.4
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 +112 -2
- package/dist/budget.d.ts.map +1 -1
- package/dist/budget.js +19 -1
- package/dist/budget.js.map +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +78 -15
- package/dist/config.js.map +1 -1
- package/dist/http.d.ts +2 -0
- package/dist/http.d.ts.map +1 -1
- package/dist/http.js +27 -1
- package/dist/http.js.map +1 -1
- package/dist/index.js +21 -1
- package/dist/index.js.map +1 -1
- package/dist/rate-limit.d.ts +24 -0
- package/dist/rate-limit.d.ts.map +1 -0
- package/dist/rate-limit.js +50 -0
- package/dist/rate-limit.js.map +1 -0
- package/dist/security-log.d.ts +55 -0
- package/dist/security-log.d.ts.map +1 -0
- package/dist/security-log.js +52 -0
- package/dist/security-log.js.map +1 -0
- package/dist/tools/create-link.d.ts +4 -0
- package/dist/tools/create-link.d.ts.map +1 -1
- package/dist/tools/create-link.js +3 -0
- package/dist/tools/create-link.js.map +1 -1
- package/dist/tools/list-withdrawals.d.ts +26 -0
- package/dist/tools/list-withdrawals.d.ts.map +1 -0
- package/dist/tools/list-withdrawals.js +43 -0
- package/dist/tools/list-withdrawals.js.map +1 -0
- package/dist/tools/update-avatar.d.ts +34 -0
- package/dist/tools/update-avatar.d.ts.map +1 -0
- package/dist/tools/update-avatar.js +89 -0
- package/dist/tools/update-avatar.js.map +1 -0
- package/dist/tools/update-link.d.ts +3 -0
- package/dist/tools/update-link.d.ts.map +1 -1
- package/dist/tools/update-link.js +3 -0
- package/dist/tools/update-link.js.map +1 -1
- package/dist/tools/update-profile.d.ts +30 -0
- package/dist/tools/update-profile.d.ts.map +1 -0
- package/dist/tools/update-profile.js +42 -0
- package/dist/tools/update-profile.js.map +1 -0
- package/dist/tools/update-socials.d.ts +41 -0
- package/dist/tools/update-socials.d.ts.map +1 -0
- package/dist/tools/update-socials.js +85 -0
- package/dist/tools/update-socials.js.map +1 -0
- package/dist/tools/withdraw.d.ts +27 -0
- package/dist/tools/withdraw.d.ts.map +1 -0
- package/dist/tools/withdraw.js +45 -0
- package/dist/tools/withdraw.js.map +1 -0
- package/dist/wallet/evm.d.ts.map +1 -1
- package/dist/wallet/evm.js +35 -0
- package/dist/wallet/evm.js.map +1 -1
- package/dist/wallet/solana.d.ts.map +1 -1
- package/dist/wallet/solana.js +32 -0
- package/dist/wallet/solana.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -362,13 +362,15 @@ Create a new API link (paid or free).
|
|
|
362
362
|
| `currency` | string | No | Always `"USDC"` |
|
|
363
363
|
| `isPublic` | boolean | No | List publicly (default: `true`) |
|
|
364
364
|
| `isStealth` | boolean | No | Hide from search (default: `false`) |
|
|
365
|
+
| `webhookUrl` | string | No | Optional webhook URL for purchase events |
|
|
365
366
|
|
|
366
367
|
```json
|
|
367
368
|
{
|
|
368
369
|
"title": "Premium Weather API",
|
|
369
370
|
"url": "https://api.example.com/weather",
|
|
370
371
|
"price": "0.05",
|
|
371
|
-
"description": "Real-time weather data"
|
|
372
|
+
"description": "Real-time weather data",
|
|
373
|
+
"webhookUrl": "https://example.com/webhooks/1ly"
|
|
372
374
|
}
|
|
373
375
|
```
|
|
374
376
|
|
|
@@ -452,6 +454,7 @@ Update an existing API link.
|
|
|
452
454
|
| `slug` | string | No | New slug |
|
|
453
455
|
| `isPublic` | boolean | No | Update visibility |
|
|
454
456
|
| `isStealth` | boolean | No | Update stealth mode |
|
|
457
|
+
| `webhookUrl` | string | No | Update webhook URL (set to `null` to clear) |
|
|
455
458
|
|
|
456
459
|
```json
|
|
457
460
|
{
|
|
@@ -636,6 +639,98 @@ Revoke an API key.
|
|
|
636
639
|
|
|
637
640
|
---
|
|
638
641
|
|
|
642
|
+
#### `1ly_update_profile`
|
|
643
|
+
|
|
644
|
+
Update basic profile fields.
|
|
645
|
+
|
|
646
|
+
| Parameter | Type | Required | Description |
|
|
647
|
+
|-----------|------|----------|-------------|
|
|
648
|
+
| `username` | string | No | New username (lowercase + underscores) |
|
|
649
|
+
| `displayName` | string | No | Public display name |
|
|
650
|
+
| `bio` | string | No | Short bio (max 160 chars) |
|
|
651
|
+
|
|
652
|
+
```json
|
|
653
|
+
{
|
|
654
|
+
"displayName": "My Store",
|
|
655
|
+
"bio": "We build paid APIs for agents."
|
|
656
|
+
}
|
|
657
|
+
```
|
|
658
|
+
|
|
659
|
+
---
|
|
660
|
+
|
|
661
|
+
#### `1ly_update_socials`
|
|
662
|
+
|
|
663
|
+
Replace socials list (up to 10).
|
|
664
|
+
|
|
665
|
+
| Parameter | Type | Required | Description |
|
|
666
|
+
|-----------|------|----------|-------------|
|
|
667
|
+
| `socials` | array | **Yes** | Social links |
|
|
668
|
+
|
|
669
|
+
```json
|
|
670
|
+
{
|
|
671
|
+
"socials": [
|
|
672
|
+
{ "type": "x", "url": "https://x.com/1ly_store", "displayOrder": 0, "isVisible": true },
|
|
673
|
+
{ "type": "website", "url": "https://1ly.store", "displayOrder": 1 }
|
|
674
|
+
]
|
|
675
|
+
}
|
|
676
|
+
```
|
|
677
|
+
|
|
678
|
+
---
|
|
679
|
+
|
|
680
|
+
#### `1ly_update_avatar`
|
|
681
|
+
|
|
682
|
+
Update store avatar using a public URL or base64 image.
|
|
683
|
+
|
|
684
|
+
| Parameter | Type | Required | Description |
|
|
685
|
+
|-----------|------|----------|-------------|
|
|
686
|
+
| `avatarUrl` | string | No | Public image URL |
|
|
687
|
+
| `imageBase64` | string | No | Base64-encoded image (max 5MB decoded) |
|
|
688
|
+
| `mimeType` | string | No | `image/png`, `image/jpeg`, `image/webp`, `image/gif` |
|
|
689
|
+
| `filename` | string | No | Optional filename |
|
|
690
|
+
|
|
691
|
+
```json
|
|
692
|
+
{
|
|
693
|
+
"avatarUrl": "https://example.com/avatar.png"
|
|
694
|
+
}
|
|
695
|
+
```
|
|
696
|
+
|
|
697
|
+
---
|
|
698
|
+
|
|
699
|
+
#### `1ly_withdraw`
|
|
700
|
+
|
|
701
|
+
Request a withdrawal (Solana only).
|
|
702
|
+
|
|
703
|
+
| Parameter | Type | Required | Description |
|
|
704
|
+
|-----------|------|----------|-------------|
|
|
705
|
+
| `amount` | string | **Yes** | Amount in USDC (min `0.1`) |
|
|
706
|
+
| `walletAddress` | string | **Yes** | Solana wallet address |
|
|
707
|
+
|
|
708
|
+
```json
|
|
709
|
+
{
|
|
710
|
+
"amount": "1.25",
|
|
711
|
+
"walletAddress": "7GmjjDitbCwW77dZmJko3pBDWhEh12soGNLR7zwAkf6M"
|
|
712
|
+
}
|
|
713
|
+
```
|
|
714
|
+
|
|
715
|
+
---
|
|
716
|
+
|
|
717
|
+
#### `1ly_list_withdrawals`
|
|
718
|
+
|
|
719
|
+
List recent withdrawals.
|
|
720
|
+
|
|
721
|
+
| Parameter | Type | Required | Description |
|
|
722
|
+
|-----------|------|----------|-------------|
|
|
723
|
+
| `limit` | number | No | Max items (default 25, max 100) |
|
|
724
|
+
| `cursor` | string | No | Pagination cursor |
|
|
725
|
+
|
|
726
|
+
```json
|
|
727
|
+
{
|
|
728
|
+
"limit": 10
|
|
729
|
+
}
|
|
730
|
+
```
|
|
731
|
+
|
|
732
|
+
---
|
|
733
|
+
|
|
639
734
|
## Common Workflows
|
|
640
735
|
|
|
641
736
|
### Workflow 1: Pay for an API
|
|
@@ -651,7 +746,7 @@ Revoke an API key.
|
|
|
651
746
|
|
|
652
747
|
```
|
|
653
748
|
1. 1ly_create_store({ "username": "mystore", "displayName": "My Store" })
|
|
654
|
-
2. 1ly_create_link({ "title": "My API", "url": "https://api.example.com", "price": "0.10" })
|
|
749
|
+
2. 1ly_create_link({ "title": "My API", "url": "https://api.example.com", "price": "0.10", "webhookUrl": "https://example.com/webhooks/1ly" })
|
|
655
750
|
3. 1ly_get_stats({ "period": "7d" })
|
|
656
751
|
```
|
|
657
752
|
|
|
@@ -663,6 +758,21 @@ Revoke an API key.
|
|
|
663
758
|
3. 1ly_delete_link({ "id": "..." })
|
|
664
759
|
```
|
|
665
760
|
|
|
761
|
+
### Workflow 4: Update Profile + Socials
|
|
762
|
+
|
|
763
|
+
```
|
|
764
|
+
1. 1ly_update_profile({ "displayName": "My Store", "bio": "We build paid APIs." })
|
|
765
|
+
2. 1ly_update_socials({ "socials": [{ "type": "x", "url": "https://x.com/1ly_store" }] })
|
|
766
|
+
3. 1ly_update_avatar({ "avatarUrl": "https://example.com/avatar.png" })
|
|
767
|
+
```
|
|
768
|
+
|
|
769
|
+
### Workflow 5: Withdraw Funds
|
|
770
|
+
|
|
771
|
+
```
|
|
772
|
+
1. 1ly_withdraw({ "amount": "1.25", "walletAddress": "7GmjjDitbCwW77dZmJko3pBDWhEh12soGNLR7zwAkf6M" })
|
|
773
|
+
2. 1ly_list_withdrawals({ "limit": 10 })
|
|
774
|
+
```
|
|
775
|
+
|
|
666
776
|
---
|
|
667
777
|
|
|
668
778
|
## Wallet Setup
|
package/dist/budget.d.ts.map
CHANGED
|
@@ -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;
|
|
1
|
+
{"version":3,"file":"budget.d.ts","sourceRoot":"","sources":["../src/budget.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAuD1C;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAuC/E"}
|
package/dist/budget.js
CHANGED
|
@@ -7,6 +7,7 @@ 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) {
|
|
@@ -37,7 +38,10 @@ function loadBudgetState() {
|
|
|
37
38
|
function saveBudgetState(state) {
|
|
38
39
|
const filePath = getBudgetStatePath();
|
|
39
40
|
try {
|
|
40
|
-
fs_1.default.writeFileSync(filePath, JSON.stringify(state, null, 2), {
|
|
41
|
+
fs_1.default.writeFileSync(filePath, JSON.stringify(state, null, 2), {
|
|
42
|
+
encoding: "utf-8",
|
|
43
|
+
mode: 0o600, // Owner read/write only (security: prevent other users from reading spending data)
|
|
44
|
+
});
|
|
41
45
|
}
|
|
42
46
|
catch {
|
|
43
47
|
// If we cannot persist, we still allow the call; fail-open is safer for UX
|
|
@@ -53,6 +57,14 @@ function checkAndRecordDailySpend(config, priceUsd) {
|
|
|
53
57
|
const current = state.date === today ? state.spentToday : 0;
|
|
54
58
|
const next = current + priceUsd;
|
|
55
59
|
if (next > config.budgets.daily) {
|
|
60
|
+
// Log budget violation for audit trail
|
|
61
|
+
(0, security_log_js_1.logSecurityEvent)("budget_exceeded", {
|
|
62
|
+
type: "daily",
|
|
63
|
+
currentSpent: current,
|
|
64
|
+
limit: config.budgets.daily,
|
|
65
|
+
attemptedAmount: priceUsd,
|
|
66
|
+
wouldTotal: next,
|
|
67
|
+
});
|
|
56
68
|
throw new Error(`Price $${priceUsd.toFixed(4)} would exceed daily budget of $${config.budgets.daily} (already spent: $${current.toFixed(4)})`);
|
|
57
69
|
}
|
|
58
70
|
const updated = {
|
|
@@ -60,5 +72,11 @@ function checkAndRecordDailySpend(config, priceUsd) {
|
|
|
60
72
|
spentToday: next,
|
|
61
73
|
};
|
|
62
74
|
saveBudgetState(updated);
|
|
75
|
+
// Log successful payment for audit trail
|
|
76
|
+
(0, security_log_js_1.logSecurityEvent)("api_call_paid", {
|
|
77
|
+
amount: priceUsd,
|
|
78
|
+
dailyTotal: next,
|
|
79
|
+
dailyLimit: config.budgets.daily,
|
|
80
|
+
});
|
|
63
81
|
}
|
|
64
82
|
//# sourceMappingURL=budget.js.map
|
package/dist/budget.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"budget.js","sourceRoot":"","sources":["../src/budget.ts"],"names":[],"mappings":";;;;;
|
|
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;
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA8CvB,CAAC;AAEH,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAElD,wBAAgB,UAAU,IAAI,MAAM,CAkEnC;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
|
|
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,8 +41,8 @@ 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"),
|
|
24
48
|
apiKey: zod_1.z.string().optional().nullable(),
|
|
@@ -30,18 +54,57 @@ function loadConfig() {
|
|
|
30
54
|
const walletEvm = process.env.ONELY_WALLET_EVM_KEY || null;
|
|
31
55
|
const apiKeyEnv = process.env.ONELY_API_KEY || null;
|
|
32
56
|
const apiBase = process.env.ONELY_API_BASE || "https://1ly.store";
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
57
|
+
// Parse and validate budget values to prevent NaN/negative bypasses
|
|
58
|
+
const perCallRaw = process.env.ONELY_BUDGET_PER_CALL || "1.0";
|
|
59
|
+
const dailyRaw = process.env.ONELY_BUDGET_DAILY || "50.0";
|
|
60
|
+
const perCall = parseFloat(perCallRaw);
|
|
61
|
+
const daily = parseFloat(dailyRaw);
|
|
62
|
+
// Validate parsed values are valid positive numbers
|
|
63
|
+
if (!Number.isFinite(perCall) || perCall <= 0) {
|
|
64
|
+
(0, security_log_js_1.logSecurityEvent)("invalid_budget_config", {
|
|
65
|
+
parameter: "ONELY_BUDGET_PER_CALL",
|
|
66
|
+
value: perCallRaw,
|
|
67
|
+
parsed: perCall,
|
|
68
|
+
});
|
|
69
|
+
throw new Error(`Invalid ONELY_BUDGET_PER_CALL: "${perCallRaw}" - must be a positive number`);
|
|
70
|
+
}
|
|
71
|
+
if (!Number.isFinite(daily) || daily <= 0) {
|
|
72
|
+
(0, security_log_js_1.logSecurityEvent)("invalid_budget_config", {
|
|
73
|
+
parameter: "ONELY_BUDGET_DAILY",
|
|
74
|
+
value: dailyRaw,
|
|
75
|
+
parsed: daily,
|
|
76
|
+
});
|
|
77
|
+
throw new Error(`Invalid ONELY_BUDGET_DAILY: "${dailyRaw}" - must be a positive number`);
|
|
78
|
+
}
|
|
79
|
+
let parsedConfig;
|
|
80
|
+
try {
|
|
81
|
+
parsedConfig = exports.ConfigSchema.parse({
|
|
82
|
+
apiBase,
|
|
83
|
+
wallet: walletType && walletKey ? { type: walletType, key: walletKey } : null,
|
|
84
|
+
walletSolana: walletSolana || (walletType === "solana" ? walletKey : null),
|
|
85
|
+
walletEvm: walletEvm || (walletType === "evm" ? walletKey : null),
|
|
86
|
+
budgets: {
|
|
87
|
+
perCall,
|
|
88
|
+
daily,
|
|
89
|
+
},
|
|
90
|
+
network: process.env.ONELY_NETWORK || "solana",
|
|
91
|
+
apiKey: apiKeyEnv,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
catch (err) {
|
|
95
|
+
// Log API base violations
|
|
96
|
+
if (err instanceof zod_1.z.ZodError) {
|
|
97
|
+
const apiBaseError = err.errors.find((e) => e.path[0] === "apiBase");
|
|
98
|
+
if (apiBaseError) {
|
|
99
|
+
(0, security_log_js_1.logSecurityEvent)("api_base_violation", {
|
|
100
|
+
attempted: apiBase,
|
|
101
|
+
error: apiBaseError.message,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
throw err;
|
|
106
|
+
}
|
|
107
|
+
return parsedConfig;
|
|
45
108
|
}
|
|
46
109
|
async function loadConfigWithStoredKey() {
|
|
47
110
|
const config = loadConfig();
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":";;;AAsDA,gCAkEC;AAED,0DAKC;AA/HD,6BAAwB;AACxB,uCAA6C;AAC7C,uDAAqD;AAExC,QAAA,YAAY,GAAG,OAAC,CAAC,MAAM,CAAC;IACnC,OAAO,EAAE,OAAC;SACP,MAAM,EAAE;SACR,GAAG,EAAE;SACL,MAAM,CACL,CAAC,GAAG,EAAE,EAAE;QACN,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;YAE5B,kCAAkC;YAClC,IAAI,MAAM,CAAC,QAAQ,KAAK,WAAW,IAAI,MAAM,CAAC,QAAQ,KAAK,eAAe,EAAE,CAAC;gBAC3E,OAAO,MAAM,CAAC,QAAQ,KAAK,QAAQ,CAAC;YACtC,CAAC;YAED,mDAAmD;YACnD,IAAI,MAAM,CAAC,QAAQ,KAAK,WAAW,IAAI,MAAM,CAAC,QAAQ,KAAK,WAAW,EAAE,CAAC;gBACvE,OAAO,IAAI,CAAC;YACd,CAAC;YAED,wBAAwB;YACxB,OAAO,KAAK,CAAC;QACf,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC,EACD;QACE,OAAO,EACL,mFAAmF;KACtF,CACF;SACA,OAAO,CAAC,mBAAmB,CAAC;IAC/B,MAAM,EAAE,OAAC;SACN,MAAM,CAAC;QACN,IAAI,EAAE,OAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QAC/B,GAAG,EAAE,OAAC,CAAC,MAAM,EAAE;KAChB,CAAC;SACD,QAAQ,EAAE;SACV,QAAQ,EAAE;IACb,YAAY,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;IAC9C,SAAS,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;IAC3C,OAAO,EAAE,OAAC,CAAC,MAAM,CAAC;QAChB,OAAO,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC;QACpD,KAAK,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;KACpD,CAAC;IACF,OAAO,EAAE,OAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC;IACrD,MAAM,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;CACzC,CAAC,CAAC;AAIH,SAAgB,UAAU;IACxB,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;IACjD,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;IAC/C,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,uBAAuB,IAAI,IAAI,CAAC;IACjE,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,IAAI,CAAC;IAC3D,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,IAAI,CAAC;IACpD,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,mBAAmB,CAAC;IAElE,oEAAoE;IACpE,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,qBAAqB,IAAI,KAAK,CAAC;IAC9D,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,MAAM,CAAC;IAE1D,MAAM,OAAO,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC;IACvC,MAAM,KAAK,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;IAEnC,oDAAoD;IACpD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,OAAO,IAAI,CAAC,EAAE,CAAC;QAC9C,IAAA,kCAAgB,EAAC,uBAAuB,EAAE;YACxC,SAAS,EAAE,uBAAuB;YAClC,KAAK,EAAE,UAAU;YACjB,MAAM,EAAE,OAAO;SAChB,CAAC,CAAC;QACH,MAAM,IAAI,KAAK,CACb,mCAAmC,UAAU,+BAA+B,CAC7E,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;QAC1C,IAAA,kCAAgB,EAAC,uBAAuB,EAAE;YACxC,SAAS,EAAE,oBAAoB;YAC/B,KAAK,EAAE,QAAQ;YACf,MAAM,EAAE,KAAK;SACd,CAAC,CAAC;QACH,MAAM,IAAI,KAAK,CACb,gCAAgC,QAAQ,+BAA+B,CACxE,CAAC;IACJ,CAAC;IAED,IAAI,YAAoB,CAAC;IACzB,IAAI,CAAC;QACH,YAAY,GAAG,oBAAY,CAAC,KAAK,CAAC;YAChC,OAAO;YACP,MAAM,EAAE,UAAU,IAAI,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,IAAI;YAC7E,YAAY,EAAE,YAAY,IAAI,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;YAC1E,SAAS,EAAE,SAAS,IAAI,CAAC,UAAU,KAAK,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;YACjE,OAAO,EAAE;gBACP,OAAO;gBACP,KAAK;aACN;YACD,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,QAAQ;YAC9C,MAAM,EAAE,SAAS;SAClB,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,0BAA0B;QAC1B,IAAI,GAAG,YAAY,OAAC,CAAC,QAAQ,EAAE,CAAC;YAC9B,MAAM,YAAY,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC;YACrE,IAAI,YAAY,EAAE,CAAC;gBACjB,IAAA,kCAAgB,EAAC,oBAAoB,EAAE;oBACrC,SAAS,EAAE,OAAO;oBAClB,KAAK,EAAE,YAAY,CAAC,OAAO;iBAC5B,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;IAED,OAAO,YAAY,CAAC;AACtB,CAAC;AAEM,KAAK,UAAU,uBAAuB;IAC3C,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,IAAI,MAAM,CAAC,MAAM;QAAE,OAAO,MAAM,CAAC;IACjC,MAAM,MAAM,GAAG,MAAM,IAAA,0BAAgB,GAAE,CAAC;IACxC,OAAO,EAAE,GAAG,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;AACvC,CAAC"}
|
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
|
package/dist/http.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"
|
|
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
|
-
|
|
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":";;;
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -17,6 +17,11 @@ const create_store_js_1 = require("./tools/create-store.js");
|
|
|
17
17
|
const list_keys_js_1 = require("./tools/list-keys.js");
|
|
18
18
|
const create_key_js_1 = require("./tools/create-key.js");
|
|
19
19
|
const revoke_key_js_1 = require("./tools/revoke-key.js");
|
|
20
|
+
const withdraw_js_1 = require("./tools/withdraw.js");
|
|
21
|
+
const list_withdrawals_js_1 = require("./tools/list-withdrawals.js");
|
|
22
|
+
const update_profile_js_1 = require("./tools/update-profile.js");
|
|
23
|
+
const update_socials_js_1 = require("./tools/update-socials.js");
|
|
24
|
+
const update_avatar_js_1 = require("./tools/update-avatar.js");
|
|
20
25
|
const config_js_1 = require("./config.js");
|
|
21
26
|
const selftest_js_1 = require("./selftest.js");
|
|
22
27
|
const mcp_js_1 = require("./mcp.js");
|
|
@@ -29,7 +34,7 @@ async function main() {
|
|
|
29
34
|
}
|
|
30
35
|
const server = new index_js_1.Server({
|
|
31
36
|
name: "1ly",
|
|
32
|
-
version: "0.1.
|
|
37
|
+
version: "0.1.4",
|
|
33
38
|
}, {
|
|
34
39
|
capabilities: {
|
|
35
40
|
tools: {},
|
|
@@ -50,6 +55,11 @@ async function main() {
|
|
|
50
55
|
list_keys_js_1.listKeysTool,
|
|
51
56
|
create_key_js_1.createKeyTool,
|
|
52
57
|
revoke_key_js_1.revokeKeyTool,
|
|
58
|
+
withdraw_js_1.withdrawTool,
|
|
59
|
+
list_withdrawals_js_1.listWithdrawalsTool,
|
|
60
|
+
update_profile_js_1.updateProfileTool,
|
|
61
|
+
update_socials_js_1.updateSocialsTool,
|
|
62
|
+
update_avatar_js_1.updateAvatarTool,
|
|
53
63
|
],
|
|
54
64
|
}));
|
|
55
65
|
server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
@@ -83,6 +93,16 @@ async function main() {
|
|
|
83
93
|
return await (0, create_key_js_1.handleCreateKey)(args, config);
|
|
84
94
|
case "1ly_revoke_key":
|
|
85
95
|
return await (0, revoke_key_js_1.handleRevokeKey)(args, config);
|
|
96
|
+
case "1ly_withdraw":
|
|
97
|
+
return await (0, withdraw_js_1.handleWithdraw)(args, config);
|
|
98
|
+
case "1ly_list_withdrawals":
|
|
99
|
+
return await (0, list_withdrawals_js_1.handleListWithdrawals)(args, config);
|
|
100
|
+
case "1ly_update_profile":
|
|
101
|
+
return await (0, update_profile_js_1.handleUpdateProfile)(args, config);
|
|
102
|
+
case "1ly_update_socials":
|
|
103
|
+
return await (0, update_socials_js_1.handleUpdateSocials)(args, config);
|
|
104
|
+
case "1ly_update_avatar":
|
|
105
|
+
return await (0, update_avatar_js_1.handleUpdateAvatar)(args, config);
|
|
86
106
|
default:
|
|
87
107
|
return {
|
|
88
108
|
content: [{ type: "text", text: `Unknown tool: ${name}` }],
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAEA,wEAAmE;AACnE,wEAAiF;AACjF,iEAG4C;AAE5C,iDAA6D;AAC7D,mDAAgE;AAChE,6CAAuD;AACvD,iDAA6D;AAC7D,2DAA0E;AAC1E,yDAAuE;AACvE,2DAA0E;AAC1E,2DAA0E;AAC1E,uDAAoE;AACpE,6DAA6E;AAC7E,uDAAoE;AACpE,yDAAuE;AACvE,yDAAuE;AACvE,2CAAsD;AACtD,+CAA4C;AAC5C,qCAAoC;AAEpC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACnC,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;AAEhD,KAAK,UAAU,IAAI;IACjB,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,IAAI,GAAG,MAAM,IAAA,yBAAW,EAAC,IAAI,CAAC,CAAC;QACrC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrB,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,iBAAM,CACvB;QACE,IAAI,EAAE,KAAK;QACX,OAAO,EAAE,OAAO;KACjB,EACD;QACE,YAAY,EAAE;YACZ,KAAK,EAAE,EAAE;SACV;KACF,CACF,CAAC;IAEF,MAAM,CAAC,iBAAiB,CAAC,iCAAsB,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;QAC5D,KAAK,EAAE;YACL,sBAAU;YACV,wBAAW;YACX,kBAAQ;YACR,sBAAU;YACV,+BAAc;YACd,6BAAa;YACb,+BAAc;YACd,+BAAc;YACd,2BAAY;YACZ,iCAAe;YACf,2BAAY;YACZ,6BAAa;YACb,6BAAa;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAEA,wEAAmE;AACnE,wEAAiF;AACjF,iEAG4C;AAE5C,iDAA6D;AAC7D,mDAAgE;AAChE,6CAAuD;AACvD,iDAA6D;AAC7D,2DAA0E;AAC1E,yDAAuE;AACvE,2DAA0E;AAC1E,2DAA0E;AAC1E,uDAAoE;AACpE,6DAA6E;AAC7E,uDAAoE;AACpE,yDAAuE;AACvE,yDAAuE;AACvE,qDAAmE;AACnE,qEAAyF;AACzF,iEAAmF;AACnF,iEAAmF;AACnF,+DAAgF;AAChF,2CAAsD;AACtD,+CAA4C;AAC5C,qCAAoC;AAEpC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACnC,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;AAEhD,KAAK,UAAU,IAAI;IACjB,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,IAAI,GAAG,MAAM,IAAA,yBAAW,EAAC,IAAI,CAAC,CAAC;QACrC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrB,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,iBAAM,CACvB;QACE,IAAI,EAAE,KAAK;QACX,OAAO,EAAE,OAAO;KACjB,EACD;QACE,YAAY,EAAE;YACZ,KAAK,EAAE,EAAE;SACV;KACF,CACF,CAAC;IAEF,MAAM,CAAC,iBAAiB,CAAC,iCAAsB,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;QAC5D,KAAK,EAAE;YACL,sBAAU;YACV,wBAAW;YACX,kBAAQ;YACR,sBAAU;YACV,+BAAc;YACd,6BAAa;YACb,+BAAc;YACd,+BAAc;YACd,2BAAY;YACZ,iCAAe;YACf,2BAAY;YACZ,6BAAa;YACb,6BAAa;YACb,0BAAY;YACZ,yCAAmB;YACnB,qCAAiB;YACjB,qCAAiB;YACjB,mCAAgB;SACjB;KACF,CAAC,CAAC,CAAC;IAEJ,MAAM,CAAC,iBAAiB,CAAC,gCAAqB,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;QAChE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;QAEjD,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAA,mCAAuB,GAAE,CAAC;YAC/C,QAAQ,IAAI,EAAE,CAAC;gBACb,KAAK,YAAY;oBACf,OAAO,MAAM,IAAA,wBAAY,EAAC,IAAI,EAAE,MAAM,CAAC,CAAC;gBAE1C,KAAK,iBAAiB;oBACpB,OAAO,MAAM,IAAA,0BAAa,EAAC,IAAI,EAAE,MAAM,CAAC,CAAC;gBAE3C,KAAK,UAAU;oBACb,OAAO,MAAM,IAAA,oBAAU,EAAC,IAAI,EAAE,MAAM,CAAC,CAAC;gBAExC,KAAK,YAAY;oBACf,OAAO,MAAM,IAAA,wBAAY,EAAC,IAAI,EAAE,MAAM,CAAC,CAAC;gBAC1C,KAAK,iBAAiB;oBACpB,OAAO,MAAM,IAAA,iCAAgB,EAAC,IAAI,EAAE,MAAM,CAAC,CAAC;gBAC9C,KAAK,gBAAgB;oBACnB,OAAO,MAAM,IAAA,+BAAe,EAAC,IAAI,EAAE,MAAM,CAAC,CAAC;gBAC7C,KAAK,iBAAiB;oBACpB,OAAO,MAAM,IAAA,iCAAgB,EAAC,IAAI,EAAE,MAAM,CAAC,CAAC;gBAC9C,KAAK,iBAAiB;oBACpB,OAAO,MAAM,IAAA,iCAAgB,EAAC,IAAI,EAAE,MAAM,CAAC,CAAC;gBAC9C,KAAK,eAAe;oBAClB,OAAO,MAAM,IAAA,6BAAc,EAAC,IAAI,EAAE,MAAM,CAAC,CAAC;gBAC5C,KAAK,kBAAkB;oBACrB,OAAO,MAAM,IAAA,mCAAiB,EAAC,IAAI,EAAE,MAAM,CAAC,CAAC;gBAC/C,KAAK,eAAe;oBAClB,OAAO,MAAM,IAAA,6BAAc,EAAC,IAAI,EAAE,MAAM,CAAC,CAAC;gBAC5C,KAAK,gBAAgB;oBACnB,OAAO,MAAM,IAAA,+BAAe,EAAC,IAAI,EAAE,MAAM,CAAC,CAAC;gBAC7C,KAAK,gBAAgB;oBACnB,OAAO,MAAM,IAAA,+BAAe,EAAC,IAAI,EAAE,MAAM,CAAC,CAAC;gBAC7C,KAAK,cAAc;oBACjB,OAAO,MAAM,IAAA,4BAAc,EAAC,IAAI,EAAE,MAAM,CAAC,CAAC;gBAC5C,KAAK,sBAAsB;oBACzB,OAAO,MAAM,IAAA,2CAAqB,EAAC,IAAI,EAAE,MAAM,CAAC,CAAC;gBACnD,KAAK,oBAAoB;oBACvB,OAAO,MAAM,IAAA,uCAAmB,EAAC,IAAI,EAAE,MAAM,CAAC,CAAC;gBACjD,KAAK,oBAAoB;oBACvB,OAAO,MAAM,IAAA,uCAAmB,EAAC,IAAI,EAAE,MAAM,CAAC,CAAC;gBACjD,KAAK,mBAAmB;oBACtB,OAAO,MAAM,IAAA,qCAAkB,EAAC,IAAI,EAAE,MAAM,CAAC,CAAC;gBAEhD;oBACE,OAAO;wBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,IAAI,EAAE,EAAE,CAAC;wBAC1D,OAAO,EAAE,IAAI;qBACd,CAAC;YACN,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;YACzE,OAAO,IAAA,iBAAQ,EAAC,OAAO,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,MAAM,SAAS,GAAG,IAAI,+BAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,OAAO,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC;AAC1C,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC"}
|
|
@@ -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"}
|