@apitoll/shared 0.1.0-beta.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/README.md +39 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +65 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +134 -0
- package/dist/logger.js.map +1 -0
- package/dist/types.d.ts +268 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +50 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.d.ts +128 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +330 -0
- package/dist/utils.js.map +1 -0
- package/dist/utils.test.d.ts +2 -0
- package/dist/utils.test.d.ts.map +1 -0
- package/dist/utils.test.js +522 -0
- package/dist/utils.test.js.map +1 -0
- package/package.json +27 -0
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import type { SupportedChain, BudgetPolicy, Policy, Transaction, PlatformFeeConfig, FeeBreakdown, PlanTier, PlanLimits } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* Convert USDC human-readable amount to smallest unit (6 decimals).
|
|
4
|
+
* e.g., "1.50" → "1500000"
|
|
5
|
+
*/
|
|
6
|
+
export declare function usdcToSmallestUnit(amount: string): string;
|
|
7
|
+
/**
|
|
8
|
+
* Convert USDC smallest unit to human-readable.
|
|
9
|
+
* e.g., "1500000" → "1.500000"
|
|
10
|
+
*/
|
|
11
|
+
export declare function usdcFromSmallestUnit(amount: string): string;
|
|
12
|
+
/**
|
|
13
|
+
* Match an HTTP method + path against a route pattern.
|
|
14
|
+
* Supports patterns like "GET /api/data", "POST /inference", "* /any"
|
|
15
|
+
*/
|
|
16
|
+
export declare function matchRoute(method: string, path: string, pattern: string): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Check if a transaction would violate budget policies.
|
|
19
|
+
* Returns null if OK, or an error message string if violated.
|
|
20
|
+
*/
|
|
21
|
+
export declare function checkBudgetPolicy(policy: BudgetPolicy, amount: number, recentTransactions: Pick<Transaction, "amount" | "requestedAt">[]): string | null;
|
|
22
|
+
/**
|
|
23
|
+
* Find the first applicable budget policy from a list.
|
|
24
|
+
*/
|
|
25
|
+
export declare function findBudgetPolicy(policies: Policy[]): BudgetPolicy | undefined;
|
|
26
|
+
/**
|
|
27
|
+
* Check if a vendor/seller is allowed by vendor ACL policies.
|
|
28
|
+
*/
|
|
29
|
+
export declare function isVendorAllowed(policies: Policy[], sellerId: string): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Generate a unique ID with optional prefix.
|
|
32
|
+
*/
|
|
33
|
+
export declare function generateId(prefix?: string): string;
|
|
34
|
+
/**
|
|
35
|
+
* Determine supported chains from endpoint config.
|
|
36
|
+
*/
|
|
37
|
+
export declare function resolveChains(chains?: SupportedChain[]): SupportedChain[];
|
|
38
|
+
/**
|
|
39
|
+
* Calculate fee breakdown for a given price and platform fee config.
|
|
40
|
+
* Fee is deducted from the total — buyer pays the listed price,
|
|
41
|
+
* seller receives price minus fee, platform gets the fee.
|
|
42
|
+
*/
|
|
43
|
+
export declare function calculateFeeBreakdown(price: string, feeConfig?: PlatformFeeConfig): FeeBreakdown;
|
|
44
|
+
/**
|
|
45
|
+
* Get the platform wallet address for a given chain.
|
|
46
|
+
*/
|
|
47
|
+
export declare function getPlatformWallet(chain: SupportedChain, feeConfig?: PlatformFeeConfig): string | undefined;
|
|
48
|
+
/**
|
|
49
|
+
* Get the limits for a given plan tier.
|
|
50
|
+
*/
|
|
51
|
+
export declare function getPlanLimits(plan: PlanTier): PlanLimits;
|
|
52
|
+
/**
|
|
53
|
+
* Check if an action is within plan limits.
|
|
54
|
+
* Returns null if OK, or an error message if limit exceeded.
|
|
55
|
+
*/
|
|
56
|
+
export declare function checkPlanLimit(plan: PlanTier, metric: keyof PlanLimits, currentValue: number): string | null;
|
|
57
|
+
/**
|
|
58
|
+
* Validate an Ethereum address (0x + 40 hex chars).
|
|
59
|
+
* Does NOT verify checksum — use viem for that.
|
|
60
|
+
*/
|
|
61
|
+
export declare function isValidEvmAddress(address: string): boolean;
|
|
62
|
+
/**
|
|
63
|
+
* Validate a Solana address (base58, 32-44 chars).
|
|
64
|
+
*/
|
|
65
|
+
export declare function isValidSolanaAddress(address: string): boolean;
|
|
66
|
+
/**
|
|
67
|
+
* Validate a payment amount string.
|
|
68
|
+
* Must be a positive numeric string (integer or decimal).
|
|
69
|
+
*/
|
|
70
|
+
export declare function isValidPaymentAmount(amount: string): boolean;
|
|
71
|
+
/**
|
|
72
|
+
* Validate a hex nonce (0x + 64 hex chars = 32 bytes).
|
|
73
|
+
*/
|
|
74
|
+
export declare function isValidNonce(nonce: string): boolean;
|
|
75
|
+
/**
|
|
76
|
+
* In-memory nonce tracker for replay protection.
|
|
77
|
+
* For production, replace with a database-backed implementation.
|
|
78
|
+
*/
|
|
79
|
+
export declare class NonceTracker {
|
|
80
|
+
private used;
|
|
81
|
+
private maxSize;
|
|
82
|
+
constructor(maxSize?: number);
|
|
83
|
+
/**
|
|
84
|
+
* Check if a nonce has been used. Returns true if this is a NEW nonce.
|
|
85
|
+
* Returns false if the nonce was already seen (replay attempt).
|
|
86
|
+
*/
|
|
87
|
+
tryUse(nonce: string): boolean;
|
|
88
|
+
/**
|
|
89
|
+
* Check if a nonce was already used (without consuming it).
|
|
90
|
+
*/
|
|
91
|
+
hasBeenUsed(nonce: string): boolean;
|
|
92
|
+
get size(): number;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Compute HMAC-SHA256 signature for webhook payloads.
|
|
96
|
+
* Uses Web Crypto API (works in Node 18+, Deno, Cloudflare Workers).
|
|
97
|
+
*/
|
|
98
|
+
export declare function computeHmacSignature(payload: string, secret: string): Promise<string>;
|
|
99
|
+
/**
|
|
100
|
+
* Verify an HMAC-SHA256 webhook signature (constant-time comparison).
|
|
101
|
+
*/
|
|
102
|
+
export declare function verifyHmacSignature(payload: string, secret: string, providedSignature: string): Promise<boolean>;
|
|
103
|
+
/**
|
|
104
|
+
* Generate a cryptographically secure API key with prefix.
|
|
105
|
+
*/
|
|
106
|
+
export declare function generateSecureApiKey(prefix: string): string;
|
|
107
|
+
/**
|
|
108
|
+
* Constant-time string comparison for API keys.
|
|
109
|
+
* Prevents timing attacks.
|
|
110
|
+
*/
|
|
111
|
+
export declare function secureCompare(a: string, b: string): boolean;
|
|
112
|
+
/**
|
|
113
|
+
* Validate an origin against a list of allowed origins.
|
|
114
|
+
*/
|
|
115
|
+
export declare function isOriginAllowed(origin: string | null, allowedOrigins: string[]): boolean;
|
|
116
|
+
/**
|
|
117
|
+
* Standard security headers for HTTP responses.
|
|
118
|
+
*/
|
|
119
|
+
export declare const SECURITY_HEADERS: Record<string, string>;
|
|
120
|
+
/**
|
|
121
|
+
* Sanitize and clamp a numeric query parameter.
|
|
122
|
+
*/
|
|
123
|
+
export declare function clampInt(value: string | null, min: number, max: number, defaultVal: number): number;
|
|
124
|
+
/**
|
|
125
|
+
* Sanitize and clamp a float query parameter.
|
|
126
|
+
*/
|
|
127
|
+
export declare function clampFloat(value: string | null, min: number, max: number, defaultVal: number): number;
|
|
128
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,iBAAiB,EAAE,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAGxI;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAIzD;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAK3D;AAED;;;GAGG;AACH,wBAAgB,UAAU,CACxB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,GACd,OAAO,CAoBT;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,MAAM,EACd,kBAAkB,EAAE,IAAI,CAAC,WAAW,EAAE,QAAQ,GAAG,aAAa,CAAC,EAAE,GAChE,MAAM,GAAG,IAAI,CAmCf;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,YAAY,GAAG,SAAS,CAE7E;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAgB7E;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,MAAM,GAAE,MAAW,GAAG,MAAM,CAItD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,MAAM,CAAC,EAAE,cAAc,EAAE,GAAG,cAAc,EAAE,CAEzE;AAID;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,MAAM,EACb,SAAS,CAAC,EAAE,iBAAiB,GAC5B,YAAY,CAcd;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,cAAc,EACrB,SAAS,CAAC,EAAE,iBAAiB,GAC5B,MAAM,GAAG,SAAS,CAGpB;AAID;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,QAAQ,GAAG,UAAU,CAExD;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,QAAQ,EACd,MAAM,EAAE,MAAM,UAAU,EACxB,YAAY,EAAE,MAAM,GACnB,MAAM,GAAG,IAAI,CAaf;AAID;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAE1D;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAE7D;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAQ5D;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEnD;AAED;;;GAGG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,IAAI,CAA0B;IACtC,OAAO,CAAC,OAAO,CAAS;gBAEZ,OAAO,GAAE,MAAgB;IAIrC;;;OAGG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAkB9B;;OAEG;IACH,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAInC,IAAI,IAAI,IAAI,MAAM,CAEjB;CACF;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,CAAC,CAWjB;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,iBAAiB,EAAE,MAAM,GACxB,OAAO,CAAC,OAAO,CAAC,CAGlB;AAID;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAK3D;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAO3D;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG,OAAO,CAMxF;AAED;;GAEG;AACH,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAOnD,CAAC;AAEF;;GAEG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAKnG;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAKrG"}
|
package/dist/utils.js
ADDED
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
import { PLAN_LIMITS } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* Convert USDC human-readable amount to smallest unit (6 decimals).
|
|
4
|
+
* e.g., "1.50" → "1500000"
|
|
5
|
+
*/
|
|
6
|
+
export function usdcToSmallestUnit(amount) {
|
|
7
|
+
const [whole, frac = ""] = amount.split(".");
|
|
8
|
+
const padded = frac.padEnd(6, "0").slice(0, 6);
|
|
9
|
+
return BigInt(whole + padded).toString();
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Convert USDC smallest unit to human-readable.
|
|
13
|
+
* e.g., "1500000" → "1.500000"
|
|
14
|
+
*/
|
|
15
|
+
export function usdcFromSmallestUnit(amount) {
|
|
16
|
+
const val = BigInt(amount);
|
|
17
|
+
const whole = val / 1000000n;
|
|
18
|
+
const frac = (val % 1000000n).toString().padStart(6, "0");
|
|
19
|
+
return `${whole}.${frac}`;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Match an HTTP method + path against a route pattern.
|
|
23
|
+
* Supports patterns like "GET /api/data", "POST /inference", "* /any"
|
|
24
|
+
*/
|
|
25
|
+
export function matchRoute(method, path, pattern) {
|
|
26
|
+
const [patternMethod, patternPath] = pattern.split(" ");
|
|
27
|
+
if (!patternMethod || !patternPath)
|
|
28
|
+
return false;
|
|
29
|
+
const methodMatch = patternMethod === "*" || patternMethod.toUpperCase() === method.toUpperCase();
|
|
30
|
+
if (!methodMatch)
|
|
31
|
+
return false;
|
|
32
|
+
// Exact match
|
|
33
|
+
if (patternPath === path)
|
|
34
|
+
return true;
|
|
35
|
+
// Wildcard path matching
|
|
36
|
+
const patternParts = patternPath.split("/").filter(Boolean);
|
|
37
|
+
const pathParts = path.split("/").filter(Boolean);
|
|
38
|
+
if (patternParts.length !== pathParts.length)
|
|
39
|
+
return false;
|
|
40
|
+
return patternParts.every((part, i) => {
|
|
41
|
+
if (part.startsWith(":"))
|
|
42
|
+
return true; // path param wildcard
|
|
43
|
+
return part === pathParts[i];
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Check if a transaction would violate budget policies.
|
|
48
|
+
* Returns null if OK, or an error message string if violated.
|
|
49
|
+
*/
|
|
50
|
+
export function checkBudgetPolicy(policy, amount, recentTransactions) {
|
|
51
|
+
// Check per-request limit
|
|
52
|
+
if (amount > policy.maxPerRequest) {
|
|
53
|
+
return `Request amount $${amount} exceeds max per-request limit of $${policy.maxPerRequest}`;
|
|
54
|
+
}
|
|
55
|
+
// Check daily cap
|
|
56
|
+
const now = new Date();
|
|
57
|
+
const dayStart = new Date(now);
|
|
58
|
+
dayStart.setHours(0, 0, 0, 0);
|
|
59
|
+
const todaySpend = recentTransactions
|
|
60
|
+
.filter((tx) => new Date(tx.requestedAt) >= dayStart)
|
|
61
|
+
.reduce((sum, tx) => sum + parseFloat(tx.amount), 0);
|
|
62
|
+
if (todaySpend + amount > policy.dailyCap) {
|
|
63
|
+
return `Adding $${amount} would exceed daily cap of $${policy.dailyCap} (already spent $${todaySpend.toFixed(4)} today)`;
|
|
64
|
+
}
|
|
65
|
+
// Check weekly cap
|
|
66
|
+
if (policy.weeklyCap) {
|
|
67
|
+
const weekStart = new Date(now);
|
|
68
|
+
weekStart.setDate(weekStart.getDate() - weekStart.getDay());
|
|
69
|
+
weekStart.setHours(0, 0, 0, 0);
|
|
70
|
+
const weekSpend = recentTransactions
|
|
71
|
+
.filter((tx) => new Date(tx.requestedAt) >= weekStart)
|
|
72
|
+
.reduce((sum, tx) => sum + parseFloat(tx.amount), 0);
|
|
73
|
+
if (weekSpend + amount > policy.weeklyCap) {
|
|
74
|
+
return `Adding $${amount} would exceed weekly cap of $${policy.weeklyCap} (already spent $${weekSpend.toFixed(4)} this week)`;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Find the first applicable budget policy from a list.
|
|
81
|
+
*/
|
|
82
|
+
export function findBudgetPolicy(policies) {
|
|
83
|
+
return policies.find((p) => p.type === "budget");
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Check if a vendor/seller is allowed by vendor ACL policies.
|
|
87
|
+
*/
|
|
88
|
+
export function isVendorAllowed(policies, sellerId) {
|
|
89
|
+
const aclPolicies = policies.filter((p) => p.type === "vendor_acl");
|
|
90
|
+
if (aclPolicies.length === 0)
|
|
91
|
+
return true; // no ACL = allow all
|
|
92
|
+
for (const policy of aclPolicies) {
|
|
93
|
+
if (policy.type !== "vendor_acl")
|
|
94
|
+
continue;
|
|
95
|
+
// Check blocked first
|
|
96
|
+
if (policy.blockedVendors?.includes(sellerId))
|
|
97
|
+
return false;
|
|
98
|
+
// Check allowed
|
|
99
|
+
if (policy.allowedVendors.includes("*"))
|
|
100
|
+
return true;
|
|
101
|
+
if (policy.allowedVendors.includes(sellerId))
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Generate a unique ID with optional prefix.
|
|
108
|
+
*/
|
|
109
|
+
export function generateId(prefix = "") {
|
|
110
|
+
const timestamp = Date.now().toString(36);
|
|
111
|
+
const random = Math.random().toString(36).slice(2, 8);
|
|
112
|
+
return prefix ? `${prefix}_${timestamp}${random}` : `${timestamp}${random}`;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Determine supported chains from endpoint config.
|
|
116
|
+
*/
|
|
117
|
+
export function resolveChains(chains) {
|
|
118
|
+
return chains && chains.length > 0 ? chains : ["base"];
|
|
119
|
+
}
|
|
120
|
+
// ─── Platform Fee Utilities ──────────────────────────────────────
|
|
121
|
+
/**
|
|
122
|
+
* Calculate fee breakdown for a given price and platform fee config.
|
|
123
|
+
* Fee is deducted from the total — buyer pays the listed price,
|
|
124
|
+
* seller receives price minus fee, platform gets the fee.
|
|
125
|
+
*/
|
|
126
|
+
export function calculateFeeBreakdown(price, feeConfig) {
|
|
127
|
+
const feeBps = feeConfig?.feeBps ?? 0;
|
|
128
|
+
const totalSmallest = BigInt(usdcToSmallestUnit(price));
|
|
129
|
+
// Calculate platform fee: total * feeBps / 10000
|
|
130
|
+
const platformFeeSmallest = (totalSmallest * BigInt(feeBps)) / 10000n;
|
|
131
|
+
const sellerAmountSmallest = totalSmallest - platformFeeSmallest;
|
|
132
|
+
return {
|
|
133
|
+
totalAmount: price,
|
|
134
|
+
sellerAmount: usdcFromSmallestUnit(sellerAmountSmallest.toString()),
|
|
135
|
+
platformFee: usdcFromSmallestUnit(platformFeeSmallest.toString()),
|
|
136
|
+
feeBps,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Get the platform wallet address for a given chain.
|
|
141
|
+
*/
|
|
142
|
+
export function getPlatformWallet(chain, feeConfig) {
|
|
143
|
+
if (!feeConfig)
|
|
144
|
+
return undefined;
|
|
145
|
+
return chain === "base" ? feeConfig.platformWalletBase : feeConfig.platformWalletSolana;
|
|
146
|
+
}
|
|
147
|
+
// ─── Plan Enforcement Utilities ──────────────────────────────────
|
|
148
|
+
/**
|
|
149
|
+
* Get the limits for a given plan tier.
|
|
150
|
+
*/
|
|
151
|
+
export function getPlanLimits(plan) {
|
|
152
|
+
return PLAN_LIMITS[plan];
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Check if an action is within plan limits.
|
|
156
|
+
* Returns null if OK, or an error message if limit exceeded.
|
|
157
|
+
*/
|
|
158
|
+
export function checkPlanLimit(plan, metric, currentValue) {
|
|
159
|
+
const limits = PLAN_LIMITS[plan];
|
|
160
|
+
const limit = limits[metric];
|
|
161
|
+
if (typeof limit === "number" && currentValue >= limit) {
|
|
162
|
+
return `Plan limit exceeded: ${metric} (current: ${currentValue}, limit: ${limit}). Upgrade to a higher plan.`;
|
|
163
|
+
}
|
|
164
|
+
if (typeof limit === "boolean" && !limit) {
|
|
165
|
+
return `Feature not available on ${plan} plan: ${metric}. Upgrade to pro or enterprise.`;
|
|
166
|
+
}
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
// ─── Input Validation Utilities ──────────────────────────────────
|
|
170
|
+
/**
|
|
171
|
+
* Validate an Ethereum address (0x + 40 hex chars).
|
|
172
|
+
* Does NOT verify checksum — use viem for that.
|
|
173
|
+
*/
|
|
174
|
+
export function isValidEvmAddress(address) {
|
|
175
|
+
return /^0x[a-fA-F0-9]{40}$/.test(address);
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Validate a Solana address (base58, 32-44 chars).
|
|
179
|
+
*/
|
|
180
|
+
export function isValidSolanaAddress(address) {
|
|
181
|
+
return /^[1-9A-HJ-NP-Za-km-z]{32,44}$/.test(address);
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Validate a payment amount string.
|
|
185
|
+
* Must be a positive numeric string (integer or decimal).
|
|
186
|
+
*/
|
|
187
|
+
export function isValidPaymentAmount(amount) {
|
|
188
|
+
if (!/^\d+(\.\d+)?$/.test(amount))
|
|
189
|
+
return false;
|
|
190
|
+
try {
|
|
191
|
+
const smallest = BigInt(usdcToSmallestUnit(amount));
|
|
192
|
+
return smallest > 0n;
|
|
193
|
+
}
|
|
194
|
+
catch {
|
|
195
|
+
return false;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Validate a hex nonce (0x + 64 hex chars = 32 bytes).
|
|
200
|
+
*/
|
|
201
|
+
export function isValidNonce(nonce) {
|
|
202
|
+
return /^0x[a-fA-F0-9]{64}$/.test(nonce);
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* In-memory nonce tracker for replay protection.
|
|
206
|
+
* For production, replace with a database-backed implementation.
|
|
207
|
+
*/
|
|
208
|
+
export class NonceTracker {
|
|
209
|
+
used = new Set();
|
|
210
|
+
maxSize;
|
|
211
|
+
constructor(maxSize = 100_000) {
|
|
212
|
+
this.maxSize = maxSize;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Check if a nonce has been used. Returns true if this is a NEW nonce.
|
|
216
|
+
* Returns false if the nonce was already seen (replay attempt).
|
|
217
|
+
*/
|
|
218
|
+
tryUse(nonce) {
|
|
219
|
+
if (this.used.has(nonce))
|
|
220
|
+
return false;
|
|
221
|
+
// Prevent unbounded memory growth
|
|
222
|
+
if (this.used.size >= this.maxSize) {
|
|
223
|
+
// Evict oldest entries (Set maintains insertion order)
|
|
224
|
+
const iter = this.used.values();
|
|
225
|
+
const toDelete = Math.floor(this.maxSize * 0.1); // evict 10%
|
|
226
|
+
for (let i = 0; i < toDelete; i++) {
|
|
227
|
+
const val = iter.next().value;
|
|
228
|
+
if (val !== undefined)
|
|
229
|
+
this.used.delete(val);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
this.used.add(nonce);
|
|
233
|
+
return true;
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Check if a nonce was already used (without consuming it).
|
|
237
|
+
*/
|
|
238
|
+
hasBeenUsed(nonce) {
|
|
239
|
+
return this.used.has(nonce);
|
|
240
|
+
}
|
|
241
|
+
get size() {
|
|
242
|
+
return this.used.size;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Compute HMAC-SHA256 signature for webhook payloads.
|
|
247
|
+
* Uses Web Crypto API (works in Node 18+, Deno, Cloudflare Workers).
|
|
248
|
+
*/
|
|
249
|
+
export async function computeHmacSignature(payload, secret) {
|
|
250
|
+
const encoder = new TextEncoder();
|
|
251
|
+
const key = await crypto.subtle.importKey("raw", encoder.encode(secret), { name: "HMAC", hash: "SHA-256" }, false, ["sign"]);
|
|
252
|
+
const signature = await crypto.subtle.sign("HMAC", key, encoder.encode(payload));
|
|
253
|
+
return Array.from(new Uint8Array(signature), (b) => b.toString(16).padStart(2, "0")).join("");
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Verify an HMAC-SHA256 webhook signature (constant-time comparison).
|
|
257
|
+
*/
|
|
258
|
+
export async function verifyHmacSignature(payload, secret, providedSignature) {
|
|
259
|
+
const expected = await computeHmacSignature(payload, secret);
|
|
260
|
+
return secureCompare(expected, providedSignature);
|
|
261
|
+
}
|
|
262
|
+
// ─── Security Utilities ──────────────────────────────────────────
|
|
263
|
+
/**
|
|
264
|
+
* Generate a cryptographically secure API key with prefix.
|
|
265
|
+
*/
|
|
266
|
+
export function generateSecureApiKey(prefix) {
|
|
267
|
+
const bytes = new Uint8Array(32);
|
|
268
|
+
crypto.getRandomValues(bytes);
|
|
269
|
+
const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
270
|
+
return `${prefix}_${hex}`;
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Constant-time string comparison for API keys.
|
|
274
|
+
* Prevents timing attacks.
|
|
275
|
+
*/
|
|
276
|
+
export function secureCompare(a, b) {
|
|
277
|
+
if (a.length !== b.length)
|
|
278
|
+
return false;
|
|
279
|
+
let result = 0;
|
|
280
|
+
for (let i = 0; i < a.length; i++) {
|
|
281
|
+
result |= a.charCodeAt(i) ^ b.charCodeAt(i);
|
|
282
|
+
}
|
|
283
|
+
return result === 0;
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Validate an origin against a list of allowed origins.
|
|
287
|
+
*/
|
|
288
|
+
export function isOriginAllowed(origin, allowedOrigins) {
|
|
289
|
+
if (!origin)
|
|
290
|
+
return false;
|
|
291
|
+
return allowedOrigins.some((allowed) => {
|
|
292
|
+
if (allowed === "*")
|
|
293
|
+
return true;
|
|
294
|
+
return origin === allowed;
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Standard security headers for HTTP responses.
|
|
299
|
+
*/
|
|
300
|
+
export const SECURITY_HEADERS = {
|
|
301
|
+
"X-Content-Type-Options": "nosniff",
|
|
302
|
+
"X-Frame-Options": "DENY",
|
|
303
|
+
"X-XSS-Protection": "1; mode=block",
|
|
304
|
+
"Strict-Transport-Security": "max-age=31536000; includeSubDomains",
|
|
305
|
+
"Referrer-Policy": "strict-origin-when-cross-origin",
|
|
306
|
+
"Cache-Control": "no-store",
|
|
307
|
+
};
|
|
308
|
+
/**
|
|
309
|
+
* Sanitize and clamp a numeric query parameter.
|
|
310
|
+
*/
|
|
311
|
+
export function clampInt(value, min, max, defaultVal) {
|
|
312
|
+
if (!value)
|
|
313
|
+
return defaultVal;
|
|
314
|
+
const parsed = parseInt(value, 10);
|
|
315
|
+
if (isNaN(parsed))
|
|
316
|
+
return defaultVal;
|
|
317
|
+
return Math.max(min, Math.min(max, parsed));
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Sanitize and clamp a float query parameter.
|
|
321
|
+
*/
|
|
322
|
+
export function clampFloat(value, min, max, defaultVal) {
|
|
323
|
+
if (!value)
|
|
324
|
+
return defaultVal;
|
|
325
|
+
const parsed = parseFloat(value);
|
|
326
|
+
if (isNaN(parsed))
|
|
327
|
+
return defaultVal;
|
|
328
|
+
return Math.max(min, Math.min(max, parsed));
|
|
329
|
+
}
|
|
330
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.test.d.ts","sourceRoot":"","sources":["../src/utils.test.ts"],"names":[],"mappings":""}
|