safehands-pharos 1.4.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +174 -63
- package/dist/cli.d.ts +5 -5
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +126 -124
- package/dist/cli.js.map +1 -1
- package/dist/demo.d.ts +1 -1
- package/dist/demo.js +171 -171
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +73 -65
- package/dist/index.js.map +1 -1
- package/dist/init.d.ts +1 -1
- package/dist/init.js +65 -65
- package/dist/lib/constants.d.ts +303 -291
- package/dist/lib/constants.d.ts.map +1 -1
- package/dist/lib/constants.js +302 -292
- package/dist/lib/constants.js.map +1 -1
- package/dist/lib/dodoApi.d.ts +78 -78
- package/dist/lib/dodoApi.js +196 -196
- package/dist/lib/envLoader.d.ts +2 -0
- package/dist/lib/envLoader.d.ts.map +1 -0
- package/dist/lib/envLoader.js +44 -0
- package/dist/lib/envLoader.js.map +1 -0
- package/dist/lib/http.d.ts +14 -14
- package/dist/lib/http.js +118 -118
- package/dist/lib/pharosClient.d.ts +58 -58
- package/dist/lib/pharosClient.js +63 -63
- package/dist/lib/policy/actionPolicyEngine.d.ts +53 -53
- package/dist/lib/policy/actionPolicyEngine.js +212 -212
- package/dist/lib/riskEngine.d.ts +26 -26
- package/dist/lib/riskEngine.d.ts.map +1 -1
- package/dist/lib/riskEngine.js +288 -283
- package/dist/lib/riskEngine.js.map +1 -1
- package/dist/lib/signer/index.d.ts +24 -24
- package/dist/lib/signer/index.js +88 -88
- package/dist/lib/testDodoLive.d.ts +1 -1
- package/dist/lib/testDodoLive.js +104 -104
- package/dist/lib/testLiveSafehands.d.ts +1 -1
- package/dist/lib/testLiveSafehands.js +92 -92
- package/dist/lib/testRpcLive.d.ts +1 -1
- package/dist/lib/testRpcLive.js +88 -88
- package/dist/lib/testTools.js +397 -398
- package/dist/lib/testX402Live.d.ts +1 -1
- package/dist/lib/testX402Live.js +159 -159
- package/dist/lib/toolResponse.d.ts +25 -25
- package/dist/lib/toolResponse.js +53 -53
- package/dist/lib/wallet/index.d.ts +37 -37
- package/dist/lib/wallet/index.js +128 -128
- package/dist/scripts/checkDeploy.d.ts +1 -1
- package/dist/scripts/checkDeploy.js +24 -24
- package/dist/scripts/deployRegistry.d.ts +1 -1
- package/dist/scripts/deployRegistry.js +100 -100
- package/dist/scripts/testRegistry.d.ts +1 -1
- package/dist/scripts/testRegistry.js +43 -43
- package/dist/tools/approveToken.d.ts +45 -45
- package/dist/tools/approveToken.js +85 -85
- package/dist/tools/assessRisk.d.ts +79 -79
- package/dist/tools/assessRisk.js +104 -104
- package/dist/tools/checkAllowance.d.ts +43 -43
- package/dist/tools/checkAllowance.js +56 -56
- package/dist/tools/checkTokenSecurity.d.ts +46 -46
- package/dist/tools/checkTokenSecurity.js +95 -95
- package/dist/tools/createAgentWallet.d.ts +28 -26
- package/dist/tools/createAgentWallet.d.ts.map +1 -1
- package/dist/tools/createAgentWallet.js +82 -58
- package/dist/tools/createAgentWallet.js.map +1 -1
- package/dist/tools/estimateGas.d.ts +79 -79
- package/dist/tools/estimateGas.js +124 -124
- package/dist/tools/executeSwap.d.ts +61 -61
- package/dist/tools/executeSwap.js +141 -141
- package/dist/tools/explainRisk.d.ts +29 -29
- package/dist/tools/explainRisk.js +32 -32
- package/dist/tools/getAgentWallet.d.ts +21 -21
- package/dist/tools/getAgentWallet.js +27 -27
- package/dist/tools/getAgentWalletBalance.d.ts +11 -11
- package/dist/tools/getAgentWalletBalance.js +70 -70
- package/dist/tools/getExecutionHistory.d.ts +49 -49
- package/dist/tools/getExecutionHistory.js +154 -154
- package/dist/tools/getGasPrice.d.ts +43 -43
- package/dist/tools/getGasPrice.js +59 -59
- package/dist/tools/getPoolInfo.d.ts +75 -75
- package/dist/tools/getPoolInfo.js +137 -137
- package/dist/tools/getTokenPrice.d.ts +113 -113
- package/dist/tools/getTokenPrice.js +117 -117
- package/dist/tools/getTransactionStatus.d.ts +43 -43
- package/dist/tools/getTransactionStatus.js +59 -59
- package/dist/tools/getWalletBalance.d.ts +68 -68
- package/dist/tools/getWalletBalance.js +87 -87
- package/dist/tools/publishRiskScore.d.ts +63 -63
- package/dist/tools/publishRiskScore.js +88 -88
- package/dist/tools/queryRiskRegistry.d.ts +38 -38
- package/dist/tools/queryRiskRegistry.js +55 -55
- package/dist/tools/safehandsPreflightCheck.d.ts +77 -77
- package/dist/tools/safehandsPreflightCheck.js +47 -47
- package/dist/tools/safehandsRiskReport.d.ts +81 -81
- package/dist/tools/safehandsRiskReport.js +28 -28
- package/dist/tools/safehandsSafeExecute.d.ts +20 -20
- package/dist/tools/safehandsSafeExecute.js +81 -81
- package/dist/tools/safehandsWalletHealth.d.ts +14 -14
- package/dist/tools/safehandsWalletHealth.js +103 -103
- package/dist/tools/safehandsX402Preflight.d.ts +26 -26
- package/dist/tools/safehandsX402Preflight.js +65 -65
- package/dist/tools/sendPayment.d.ts +57 -57
- package/dist/tools/sendPayment.js +117 -117
- package/dist/tools/simulateTransaction.d.ts +60 -60
- package/dist/tools/simulateTransaction.js +83 -83
- package/dist/tools/tokenRegistryStatus.d.ts +26 -26
- package/dist/tools/tokenRegistryStatus.js +96 -96
- package/dist/tools/x402PayAndFetch.d.ts +81 -81
- package/dist/tools/x402PayAndFetch.js +152 -152
- package/dist/x402Server.d.ts +1 -1
- package/dist/x402Server.js +300 -252
- package/dist/x402Server.js.map +1 -1
- package/package.json +6 -16
- package/examples/dashboard/index.html +0 -337
- package/examples/pharos-skill-engine/SKILL.safehands.md +0 -85
- package/examples/pharos-skill-engine/assets/safehands/example-actions.json +0 -49
- package/examples/pharos-skill-engine/assets/safehands/policy-defaults.json +0 -11
- package/examples/pharos-skill-engine/references/safehands.md +0 -345
- package/examples/scenario-hack.ts +0 -38
- package/skill/SKILL.md +0 -133
- package/skill/assets/safehands/example-actions.json +0 -49
- package/skill/assets/safehands/policy-defaults.json +0 -11
- package/skill/references/safehands.md +0 -345
package/dist/lib/dodoApi.d.ts
CHANGED
|
@@ -1,79 +1,79 @@
|
|
|
1
|
-
export interface DodoRouteResponse {
|
|
2
|
-
status: number;
|
|
3
|
-
data: {
|
|
4
|
-
resAmount: string | number;
|
|
5
|
-
priceImpact: string | number;
|
|
6
|
-
targetDecimals: number;
|
|
7
|
-
targetApproveAddr: string;
|
|
8
|
-
to: string;
|
|
9
|
-
data: string;
|
|
10
|
-
value: string | number;
|
|
11
|
-
gasLimit: string | number;
|
|
12
|
-
} | null;
|
|
13
|
-
message?: string;
|
|
14
|
-
}
|
|
15
|
-
export interface DodoQuote {
|
|
16
|
-
amountOut: string;
|
|
17
|
-
amountOutWei: string;
|
|
18
|
-
priceImpact: number;
|
|
19
|
-
gasLimit: string;
|
|
20
|
-
value: string;
|
|
21
|
-
calldata: string;
|
|
22
|
-
to: string;
|
|
23
|
-
approveAddress: string;
|
|
24
|
-
routeAvailable: boolean;
|
|
25
|
-
sourceStatus: "ok" | "no_route_available" | "auth_required" | "unavailable";
|
|
26
|
-
usedApiKey: boolean;
|
|
27
|
-
/** Actual on-chain address used for fromToken (may differ from input if USDC fallback triggered) */
|
|
28
|
-
usedFromToken: string;
|
|
29
|
-
/** Actual on-chain address used for toToken (may differ from input if USDC fallback triggered) */
|
|
30
|
-
usedToToken: string;
|
|
31
|
-
/** True when a silent token substitution occurred (e.g. canonical USDC → altUSDC) */
|
|
32
|
-
wasSubstituted: boolean;
|
|
33
|
-
/** Human-readable explanation when wasSubstituted is true */
|
|
34
|
-
substitutionNote?: string;
|
|
35
|
-
rawResponse: DodoRouteResponse;
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* Resolves a token symbol (e.g. "PHRS") or address to its on-chain address.
|
|
39
|
-
*/
|
|
40
|
-
export declare function resolveTokenAddress(token: string): `0x${string}`;
|
|
41
|
-
/**
|
|
42
|
-
* Resolves the decimal count for a token symbol or address.
|
|
43
|
-
*/
|
|
44
|
-
export declare function resolveTokenDecimals(token: string): number;
|
|
45
|
-
/**
|
|
46
|
-
* Converts a human-readable amount to wei string.
|
|
47
|
-
*/
|
|
48
|
-
export declare function toWei(amount: string, decimals: number): string;
|
|
49
|
-
/**
|
|
50
|
-
* Converts a wei string to human-readable amount.
|
|
51
|
-
* Also handles the case where the API returns a decimal string directly.
|
|
52
|
-
*/
|
|
53
|
-
export declare function fromWei(weiInput: string | number, decimals: number): string;
|
|
54
|
-
/**
|
|
55
|
-
* Fetches a swap route from the DODO aggregation API.
|
|
56
|
-
*/
|
|
57
|
-
export declare function _getDodoRouteCore(params: {
|
|
58
|
-
fromToken: string;
|
|
59
|
-
toToken: string;
|
|
60
|
-
amountHuman: string;
|
|
61
|
-
walletAddress: string;
|
|
62
|
-
slippage?: number;
|
|
63
|
-
}): Promise<DodoQuote>;
|
|
64
|
-
/**
|
|
65
|
-
* Smart wrapper around _getDodoRouteCore that automatically falls back to alternative token sources
|
|
66
|
-
* (like Circle USDC) if the canonical tokens have no liquidity on the testnet.
|
|
67
|
-
*/
|
|
68
|
-
export declare function getDodoRoute(params: {
|
|
69
|
-
fromToken: string;
|
|
70
|
-
toToken: string;
|
|
71
|
-
amountHuman: string;
|
|
72
|
-
walletAddress: string;
|
|
73
|
-
slippage?: number;
|
|
74
|
-
}): Promise<DodoQuote>;
|
|
75
|
-
/**
|
|
76
|
-
* Checks whether a token is the native PHRS token.
|
|
77
|
-
*/
|
|
78
|
-
export declare function isNativeToken(token: string): boolean;
|
|
1
|
+
export interface DodoRouteResponse {
|
|
2
|
+
status: number;
|
|
3
|
+
data: {
|
|
4
|
+
resAmount: string | number;
|
|
5
|
+
priceImpact: string | number;
|
|
6
|
+
targetDecimals: number;
|
|
7
|
+
targetApproveAddr: string;
|
|
8
|
+
to: string;
|
|
9
|
+
data: string;
|
|
10
|
+
value: string | number;
|
|
11
|
+
gasLimit: string | number;
|
|
12
|
+
} | null;
|
|
13
|
+
message?: string;
|
|
14
|
+
}
|
|
15
|
+
export interface DodoQuote {
|
|
16
|
+
amountOut: string;
|
|
17
|
+
amountOutWei: string;
|
|
18
|
+
priceImpact: number;
|
|
19
|
+
gasLimit: string;
|
|
20
|
+
value: string;
|
|
21
|
+
calldata: string;
|
|
22
|
+
to: string;
|
|
23
|
+
approveAddress: string;
|
|
24
|
+
routeAvailable: boolean;
|
|
25
|
+
sourceStatus: "ok" | "no_route_available" | "auth_required" | "unavailable";
|
|
26
|
+
usedApiKey: boolean;
|
|
27
|
+
/** Actual on-chain address used for fromToken (may differ from input if USDC fallback triggered) */
|
|
28
|
+
usedFromToken: string;
|
|
29
|
+
/** Actual on-chain address used for toToken (may differ from input if USDC fallback triggered) */
|
|
30
|
+
usedToToken: string;
|
|
31
|
+
/** True when a silent token substitution occurred (e.g. canonical USDC → altUSDC) */
|
|
32
|
+
wasSubstituted: boolean;
|
|
33
|
+
/** Human-readable explanation when wasSubstituted is true */
|
|
34
|
+
substitutionNote?: string;
|
|
35
|
+
rawResponse: DodoRouteResponse;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Resolves a token symbol (e.g. "PHRS") or address to its on-chain address.
|
|
39
|
+
*/
|
|
40
|
+
export declare function resolveTokenAddress(token: string): `0x${string}`;
|
|
41
|
+
/**
|
|
42
|
+
* Resolves the decimal count for a token symbol or address.
|
|
43
|
+
*/
|
|
44
|
+
export declare function resolveTokenDecimals(token: string): number;
|
|
45
|
+
/**
|
|
46
|
+
* Converts a human-readable amount to wei string.
|
|
47
|
+
*/
|
|
48
|
+
export declare function toWei(amount: string, decimals: number): string;
|
|
49
|
+
/**
|
|
50
|
+
* Converts a wei string to human-readable amount.
|
|
51
|
+
* Also handles the case where the API returns a decimal string directly.
|
|
52
|
+
*/
|
|
53
|
+
export declare function fromWei(weiInput: string | number, decimals: number): string;
|
|
54
|
+
/**
|
|
55
|
+
* Fetches a swap route from the DODO aggregation API.
|
|
56
|
+
*/
|
|
57
|
+
export declare function _getDodoRouteCore(params: {
|
|
58
|
+
fromToken: string;
|
|
59
|
+
toToken: string;
|
|
60
|
+
amountHuman: string;
|
|
61
|
+
walletAddress: string;
|
|
62
|
+
slippage?: number;
|
|
63
|
+
}): Promise<DodoQuote>;
|
|
64
|
+
/**
|
|
65
|
+
* Smart wrapper around _getDodoRouteCore that automatically falls back to alternative token sources
|
|
66
|
+
* (like Circle USDC) if the canonical tokens have no liquidity on the testnet.
|
|
67
|
+
*/
|
|
68
|
+
export declare function getDodoRoute(params: {
|
|
69
|
+
fromToken: string;
|
|
70
|
+
toToken: string;
|
|
71
|
+
amountHuman: string;
|
|
72
|
+
walletAddress: string;
|
|
73
|
+
slippage?: number;
|
|
74
|
+
}): Promise<DodoQuote>;
|
|
75
|
+
/**
|
|
76
|
+
* Checks whether a token is the native PHRS token.
|
|
77
|
+
*/
|
|
78
|
+
export declare function isNativeToken(token: string): boolean;
|
|
79
79
|
//# sourceMappingURL=dodoApi.d.ts.map
|
package/dist/lib/dodoApi.js
CHANGED
|
@@ -1,197 +1,197 @@
|
|
|
1
|
-
// ─── DODO Route API Client ─────────────────────────────────────────────
|
|
2
|
-
// Fetches swap routes from DODO's aggregation API for FaroSwap on
|
|
3
|
-
// Pharos Atlantic Testnet.
|
|
4
|
-
// ────────────────────────────────────────────────────────────────────────
|
|
5
|
-
import { isAddress } from "viem";
|
|
6
|
-
import { DODO_API_BASE, DODO_API_KEY, DODO_DEFAULT_SLIPPAGE, DODO_ROUTE_ENDPOINT, CHAIN_ID, TOKEN_MAP, TOKEN_DECIMALS, PHRS_ADDRESS, USDC_ADDRESS, CIRCLE_USDC_ADDRESS, } from "./constants.js";
|
|
7
|
-
import { fetchWithTimeoutAndRetry } from "./http.js";
|
|
8
|
-
// ─── Helpers ───────────────────────────────────────────────────────────
|
|
9
|
-
/**
|
|
10
|
-
* Resolves a token symbol (e.g. "PHRS") or address to its on-chain address.
|
|
11
|
-
*/
|
|
12
|
-
export function resolveTokenAddress(token) {
|
|
13
|
-
const upper = token.toUpperCase();
|
|
14
|
-
if (TOKEN_MAP[upper])
|
|
15
|
-
return TOKEN_MAP[upper];
|
|
16
|
-
if (isAddress(token))
|
|
17
|
-
return token;
|
|
18
|
-
throw new Error(`INVALID_TOKEN_ADDRESS: Unknown token or invalid address: ${token}`);
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* Resolves the decimal count for a token symbol or address.
|
|
22
|
-
*/
|
|
23
|
-
export function resolveTokenDecimals(token) {
|
|
24
|
-
const upper = token.toUpperCase();
|
|
25
|
-
if (TOKEN_DECIMALS[upper] !== undefined)
|
|
26
|
-
return TOKEN_DECIMALS[upper];
|
|
27
|
-
const lower = token.toLowerCase();
|
|
28
|
-
if (TOKEN_DECIMALS[lower] !== undefined)
|
|
29
|
-
return TOKEN_DECIMALS[lower];
|
|
30
|
-
return 18; // unknown custom token fallback
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Converts a human-readable amount to wei string.
|
|
34
|
-
*/
|
|
35
|
-
export function toWei(amount, decimals) {
|
|
36
|
-
if (!/^\d+(\.\d+)?$/.test(amount)) {
|
|
37
|
-
throw new Error(`INVALID_AMOUNT: ${amount}`);
|
|
38
|
-
}
|
|
39
|
-
const [whole, frac = ""] = amount.split(".");
|
|
40
|
-
const paddedFrac = frac.padEnd(decimals, "0").slice(0, decimals);
|
|
41
|
-
return BigInt(whole + paddedFrac).toString();
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* Converts a wei string to human-readable amount.
|
|
45
|
-
* Also handles the case where the API returns a decimal string directly.
|
|
46
|
-
*/
|
|
47
|
-
export function fromWei(weiInput, decimals) {
|
|
48
|
-
const weiStr = String(weiInput);
|
|
49
|
-
if (weiStr.includes("."))
|
|
50
|
-
return weiStr;
|
|
51
|
-
const wei = BigInt(weiStr);
|
|
52
|
-
const divisor = BigInt(10) ** BigInt(decimals);
|
|
53
|
-
const whole = wei / divisor;
|
|
54
|
-
const remainder = wei % divisor;
|
|
55
|
-
if (remainder === 0n)
|
|
56
|
-
return whole.toString();
|
|
57
|
-
const fracStr = remainder.toString().padStart(decimals, "0").replace(/0+$/, "");
|
|
58
|
-
return `${whole}.${fracStr}`;
|
|
59
|
-
}
|
|
60
|
-
// ─── DODO Route Fetch ──────────────────────────────────────────────────
|
|
61
|
-
/**
|
|
62
|
-
* Fetches a swap route from the DODO aggregation API.
|
|
63
|
-
*/
|
|
64
|
-
export async function _getDodoRouteCore(params) {
|
|
65
|
-
const trimmedApiKey = DODO_API_KEY?.trim();
|
|
66
|
-
const usedApiKey = Boolean(trimmedApiKey);
|
|
67
|
-
if (!isAddress(params.walletAddress)) {
|
|
68
|
-
throw new Error(`INVALID_WALLET_ADDRESS: ${params.walletAddress}`);
|
|
69
|
-
}
|
|
70
|
-
const fromAddress = resolveTokenAddress(params.fromToken);
|
|
71
|
-
const toAddress = resolveTokenAddress(params.toToken);
|
|
72
|
-
const usedFromToken = fromAddress;
|
|
73
|
-
const usedToToken = toAddress;
|
|
74
|
-
const fromDecimals = resolveTokenDecimals(params.fromToken);
|
|
75
|
-
const toDecimals = resolveTokenDecimals(params.toToken);
|
|
76
|
-
const amountInWei = toWei(params.amountHuman, fromDecimals);
|
|
77
|
-
const slippage = params.slippage ?? DODO_DEFAULT_SLIPPAGE;
|
|
78
|
-
const deadline = Math.floor(Date.now() / 1000) + 600;
|
|
79
|
-
const url = new URL(`${DODO_API_BASE}${DODO_ROUTE_ENDPOINT}`);
|
|
80
|
-
url.searchParams.set("chainId", String(CHAIN_ID));
|
|
81
|
-
url.searchParams.set("fromTokenAddress", fromAddress);
|
|
82
|
-
url.searchParams.set("toTokenAddress", toAddress);
|
|
83
|
-
url.searchParams.set("fromAmount", amountInWei);
|
|
84
|
-
url.searchParams.set("userAddr", params.walletAddress);
|
|
85
|
-
url.searchParams.set("slippage", String(slippage));
|
|
86
|
-
url.searchParams.set("source", "dodoV2AndMixWasm");
|
|
87
|
-
url.searchParams.set("estimateGas", "true");
|
|
88
|
-
// DODO/FaroSwap read-only route queries should prefer public mode when no
|
|
89
|
-
// API key is configured. Never hardcode a default credential. If the
|
|
90
|
-
// provider rejects public mode, surface a structured auth-required error
|
|
91
|
-
// at the tool layer.
|
|
92
|
-
if (trimmedApiKey) {
|
|
93
|
-
url.searchParams.set("apikey", trimmedApiKey);
|
|
94
|
-
}
|
|
95
|
-
url.searchParams.set("deadLine", String(deadline));
|
|
96
|
-
const response = await fetchWithTimeoutAndRetry(url, {
|
|
97
|
-
timeoutMs: 10_000,
|
|
98
|
-
retries: 2,
|
|
99
|
-
retryDelayMs: 300,
|
|
100
|
-
});
|
|
101
|
-
if (!response.ok) {
|
|
102
|
-
if (response.status === 401 || response.status === 403) {
|
|
103
|
-
throw new Error(`DODO_API_AUTH_REQUIRED: DODO route API rejected public mode${usedApiKey ? " or provided key" : "; configure DODO_API_KEY if this endpoint requires authentication"}`);
|
|
104
|
-
}
|
|
105
|
-
if (response.status === 429) {
|
|
106
|
-
throw new Error(`DODO_API_RATE_LIMITED: ${response.status} ${response.statusText}`);
|
|
107
|
-
}
|
|
108
|
-
throw new Error(`DODO_API_UNAVAILABLE: ${response.status} ${response.statusText}`);
|
|
109
|
-
}
|
|
110
|
-
const json = (await response.json());
|
|
111
|
-
if (!json.data || json.status !== 200) {
|
|
112
|
-
const message = (json.message || "").toLowerCase();
|
|
113
|
-
if (message.includes("api key") || message.includes("apikey") || message.includes("unauthorized") || message.includes("forbidden")) {
|
|
114
|
-
throw new Error(`DODO_API_AUTH_REQUIRED: DODO route API rejected public mode${usedApiKey ? " or provided key" : "; configure DODO_API_KEY if this endpoint requires authentication"}`);
|
|
115
|
-
}
|
|
116
|
-
return {
|
|
117
|
-
amountOut: "0",
|
|
118
|
-
amountOutWei: "0",
|
|
119
|
-
priceImpact: 100,
|
|
120
|
-
gasLimit: "0",
|
|
121
|
-
value: "0",
|
|
122
|
-
calldata: "0x",
|
|
123
|
-
to: "",
|
|
124
|
-
approveAddress: "",
|
|
125
|
-
routeAvailable: false,
|
|
126
|
-
sourceStatus: "no_route_available",
|
|
127
|
-
usedApiKey,
|
|
128
|
-
usedFromToken,
|
|
129
|
-
usedToToken,
|
|
130
|
-
wasSubstituted: false,
|
|
131
|
-
rawResponse: json,
|
|
132
|
-
};
|
|
133
|
-
}
|
|
134
|
-
const d = json.data;
|
|
135
|
-
const resAmountStr = String(d.resAmount);
|
|
136
|
-
return {
|
|
137
|
-
amountOut: fromWei(resAmountStr, toDecimals),
|
|
138
|
-
amountOutWei: resAmountStr,
|
|
139
|
-
priceImpact: parseFloat(String(d.priceImpact)) || 0,
|
|
140
|
-
gasLimit: String(d.gasLimit),
|
|
141
|
-
value: String(d.value),
|
|
142
|
-
calldata: d.data,
|
|
143
|
-
to: d.to,
|
|
144
|
-
approveAddress: d.targetApproveAddr,
|
|
145
|
-
routeAvailable: true,
|
|
146
|
-
sourceStatus: "ok",
|
|
147
|
-
usedApiKey,
|
|
148
|
-
usedFromToken,
|
|
149
|
-
usedToToken,
|
|
150
|
-
wasSubstituted: false,
|
|
151
|
-
rawResponse: json,
|
|
152
|
-
};
|
|
153
|
-
}
|
|
154
|
-
/**
|
|
155
|
-
* Smart wrapper around _getDodoRouteCore that automatically falls back to alternative token sources
|
|
156
|
-
* (like Circle USDC) if the canonical tokens have no liquidity on the testnet.
|
|
157
|
-
*/
|
|
158
|
-
export async function getDodoRoute(params) {
|
|
159
|
-
let quote = await _getDodoRouteCore(params);
|
|
160
|
-
if (!quote.routeAvailable) {
|
|
161
|
-
const fromUpper = params.fromToken.toUpperCase();
|
|
162
|
-
const toUpper = params.toToken.toUpperCase();
|
|
163
|
-
// Smart Fallback: If swapping TO canonical USDC failed, try Alternate Circle USDC
|
|
164
|
-
if (toUpper === "USDC" || toUpper === USDC_ADDRESS.toUpperCase()) {
|
|
165
|
-
const fallbackQuote = await _getDodoRouteCore({ ...params, toToken: CIRCLE_USDC_ADDRESS });
|
|
166
|
-
if (fallbackQuote.routeAvailable) {
|
|
167
|
-
return {
|
|
168
|
-
...fallbackQuote,
|
|
169
|
-
wasSubstituted: true,
|
|
170
|
-
substitutionNote: `toToken substituted: canonical USDC (${USDC_ADDRESS}) had no route; used altUSDC (${CIRCLE_USDC_ADDRESS}). Ensure your approval targets the correct address.`,
|
|
171
|
-
};
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
// Smart Fallback: If swapping FROM canonical USDC failed, try Alternate Circle USDC
|
|
175
|
-
if (fromUpper === "USDC" || fromUpper === USDC_ADDRESS.toUpperCase()) {
|
|
176
|
-
const fallbackQuote = await _getDodoRouteCore({ ...params, fromToken: CIRCLE_USDC_ADDRESS });
|
|
177
|
-
if (fallbackQuote.routeAvailable) {
|
|
178
|
-
return {
|
|
179
|
-
...fallbackQuote,
|
|
180
|
-
wasSubstituted: true,
|
|
181
|
-
substitutionNote: `fromToken substituted: canonical USDC (${USDC_ADDRESS}) had no route; used altUSDC (${CIRCLE_USDC_ADDRESS}). Ensure your allowance covers the correct address.`,
|
|
182
|
-
};
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
return quote;
|
|
187
|
-
}
|
|
188
|
-
/**
|
|
189
|
-
* Checks whether a token is the native PHRS token.
|
|
190
|
-
*/
|
|
191
|
-
export function isNativeToken(token) {
|
|
192
|
-
const upper = token.toUpperCase();
|
|
193
|
-
if (upper === "PHRS")
|
|
194
|
-
return true;
|
|
195
|
-
return token.toLowerCase() === PHRS_ADDRESS.toLowerCase();
|
|
196
|
-
}
|
|
1
|
+
// ─── DODO Route API Client ─────────────────────────────────────────────
|
|
2
|
+
// Fetches swap routes from DODO's aggregation API for FaroSwap on
|
|
3
|
+
// Pharos Atlantic Testnet.
|
|
4
|
+
// ────────────────────────────────────────────────────────────────────────
|
|
5
|
+
import { isAddress } from "viem";
|
|
6
|
+
import { DODO_API_BASE, DODO_API_KEY, DODO_DEFAULT_SLIPPAGE, DODO_ROUTE_ENDPOINT, CHAIN_ID, TOKEN_MAP, TOKEN_DECIMALS, PHRS_ADDRESS, USDC_ADDRESS, CIRCLE_USDC_ADDRESS, } from "./constants.js";
|
|
7
|
+
import { fetchWithTimeoutAndRetry } from "./http.js";
|
|
8
|
+
// ─── Helpers ───────────────────────────────────────────────────────────
|
|
9
|
+
/**
|
|
10
|
+
* Resolves a token symbol (e.g. "PHRS") or address to its on-chain address.
|
|
11
|
+
*/
|
|
12
|
+
export function resolveTokenAddress(token) {
|
|
13
|
+
const upper = token.toUpperCase();
|
|
14
|
+
if (TOKEN_MAP[upper])
|
|
15
|
+
return TOKEN_MAP[upper];
|
|
16
|
+
if (isAddress(token))
|
|
17
|
+
return token;
|
|
18
|
+
throw new Error(`INVALID_TOKEN_ADDRESS: Unknown token or invalid address: ${token}`);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Resolves the decimal count for a token symbol or address.
|
|
22
|
+
*/
|
|
23
|
+
export function resolveTokenDecimals(token) {
|
|
24
|
+
const upper = token.toUpperCase();
|
|
25
|
+
if (TOKEN_DECIMALS[upper] !== undefined)
|
|
26
|
+
return TOKEN_DECIMALS[upper];
|
|
27
|
+
const lower = token.toLowerCase();
|
|
28
|
+
if (TOKEN_DECIMALS[lower] !== undefined)
|
|
29
|
+
return TOKEN_DECIMALS[lower];
|
|
30
|
+
return 18; // unknown custom token fallback
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Converts a human-readable amount to wei string.
|
|
34
|
+
*/
|
|
35
|
+
export function toWei(amount, decimals) {
|
|
36
|
+
if (!/^\d+(\.\d+)?$/.test(amount)) {
|
|
37
|
+
throw new Error(`INVALID_AMOUNT: ${amount}`);
|
|
38
|
+
}
|
|
39
|
+
const [whole, frac = ""] = amount.split(".");
|
|
40
|
+
const paddedFrac = frac.padEnd(decimals, "0").slice(0, decimals);
|
|
41
|
+
return BigInt(whole + paddedFrac).toString();
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Converts a wei string to human-readable amount.
|
|
45
|
+
* Also handles the case where the API returns a decimal string directly.
|
|
46
|
+
*/
|
|
47
|
+
export function fromWei(weiInput, decimals) {
|
|
48
|
+
const weiStr = String(weiInput);
|
|
49
|
+
if (weiStr.includes("."))
|
|
50
|
+
return weiStr;
|
|
51
|
+
const wei = BigInt(weiStr);
|
|
52
|
+
const divisor = BigInt(10) ** BigInt(decimals);
|
|
53
|
+
const whole = wei / divisor;
|
|
54
|
+
const remainder = wei % divisor;
|
|
55
|
+
if (remainder === 0n)
|
|
56
|
+
return whole.toString();
|
|
57
|
+
const fracStr = remainder.toString().padStart(decimals, "0").replace(/0+$/, "");
|
|
58
|
+
return `${whole}.${fracStr}`;
|
|
59
|
+
}
|
|
60
|
+
// ─── DODO Route Fetch ──────────────────────────────────────────────────
|
|
61
|
+
/**
|
|
62
|
+
* Fetches a swap route from the DODO aggregation API.
|
|
63
|
+
*/
|
|
64
|
+
export async function _getDodoRouteCore(params) {
|
|
65
|
+
const trimmedApiKey = DODO_API_KEY?.trim();
|
|
66
|
+
const usedApiKey = Boolean(trimmedApiKey);
|
|
67
|
+
if (!isAddress(params.walletAddress)) {
|
|
68
|
+
throw new Error(`INVALID_WALLET_ADDRESS: ${params.walletAddress}`);
|
|
69
|
+
}
|
|
70
|
+
const fromAddress = resolveTokenAddress(params.fromToken);
|
|
71
|
+
const toAddress = resolveTokenAddress(params.toToken);
|
|
72
|
+
const usedFromToken = fromAddress;
|
|
73
|
+
const usedToToken = toAddress;
|
|
74
|
+
const fromDecimals = resolveTokenDecimals(params.fromToken);
|
|
75
|
+
const toDecimals = resolveTokenDecimals(params.toToken);
|
|
76
|
+
const amountInWei = toWei(params.amountHuman, fromDecimals);
|
|
77
|
+
const slippage = params.slippage ?? DODO_DEFAULT_SLIPPAGE;
|
|
78
|
+
const deadline = Math.floor(Date.now() / 1000) + 600;
|
|
79
|
+
const url = new URL(`${DODO_API_BASE}${DODO_ROUTE_ENDPOINT}`);
|
|
80
|
+
url.searchParams.set("chainId", String(CHAIN_ID));
|
|
81
|
+
url.searchParams.set("fromTokenAddress", fromAddress);
|
|
82
|
+
url.searchParams.set("toTokenAddress", toAddress);
|
|
83
|
+
url.searchParams.set("fromAmount", amountInWei);
|
|
84
|
+
url.searchParams.set("userAddr", params.walletAddress);
|
|
85
|
+
url.searchParams.set("slippage", String(slippage));
|
|
86
|
+
url.searchParams.set("source", "dodoV2AndMixWasm");
|
|
87
|
+
url.searchParams.set("estimateGas", "true");
|
|
88
|
+
// DODO/FaroSwap read-only route queries should prefer public mode when no
|
|
89
|
+
// API key is configured. Never hardcode a default credential. If the
|
|
90
|
+
// provider rejects public mode, surface a structured auth-required error
|
|
91
|
+
// at the tool layer.
|
|
92
|
+
if (trimmedApiKey) {
|
|
93
|
+
url.searchParams.set("apikey", trimmedApiKey);
|
|
94
|
+
}
|
|
95
|
+
url.searchParams.set("deadLine", String(deadline));
|
|
96
|
+
const response = await fetchWithTimeoutAndRetry(url, {
|
|
97
|
+
timeoutMs: 10_000,
|
|
98
|
+
retries: 2,
|
|
99
|
+
retryDelayMs: 300,
|
|
100
|
+
});
|
|
101
|
+
if (!response.ok) {
|
|
102
|
+
if (response.status === 401 || response.status === 403) {
|
|
103
|
+
throw new Error(`DODO_API_AUTH_REQUIRED: DODO route API rejected public mode${usedApiKey ? " or provided key" : "; configure DODO_API_KEY if this endpoint requires authentication"}`);
|
|
104
|
+
}
|
|
105
|
+
if (response.status === 429) {
|
|
106
|
+
throw new Error(`DODO_API_RATE_LIMITED: ${response.status} ${response.statusText}`);
|
|
107
|
+
}
|
|
108
|
+
throw new Error(`DODO_API_UNAVAILABLE: ${response.status} ${response.statusText}`);
|
|
109
|
+
}
|
|
110
|
+
const json = (await response.json());
|
|
111
|
+
if (!json.data || json.status !== 200) {
|
|
112
|
+
const message = (json.message || "").toLowerCase();
|
|
113
|
+
if (message.includes("api key") || message.includes("apikey") || message.includes("unauthorized") || message.includes("forbidden")) {
|
|
114
|
+
throw new Error(`DODO_API_AUTH_REQUIRED: DODO route API rejected public mode${usedApiKey ? " or provided key" : "; configure DODO_API_KEY if this endpoint requires authentication"}`);
|
|
115
|
+
}
|
|
116
|
+
return {
|
|
117
|
+
amountOut: "0",
|
|
118
|
+
amountOutWei: "0",
|
|
119
|
+
priceImpact: 100,
|
|
120
|
+
gasLimit: "0",
|
|
121
|
+
value: "0",
|
|
122
|
+
calldata: "0x",
|
|
123
|
+
to: "",
|
|
124
|
+
approveAddress: "",
|
|
125
|
+
routeAvailable: false,
|
|
126
|
+
sourceStatus: "no_route_available",
|
|
127
|
+
usedApiKey,
|
|
128
|
+
usedFromToken,
|
|
129
|
+
usedToToken,
|
|
130
|
+
wasSubstituted: false,
|
|
131
|
+
rawResponse: json,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
const d = json.data;
|
|
135
|
+
const resAmountStr = String(d.resAmount);
|
|
136
|
+
return {
|
|
137
|
+
amountOut: fromWei(resAmountStr, toDecimals),
|
|
138
|
+
amountOutWei: resAmountStr,
|
|
139
|
+
priceImpact: parseFloat(String(d.priceImpact)) || 0,
|
|
140
|
+
gasLimit: String(d.gasLimit),
|
|
141
|
+
value: String(d.value),
|
|
142
|
+
calldata: d.data,
|
|
143
|
+
to: d.to,
|
|
144
|
+
approveAddress: d.targetApproveAddr,
|
|
145
|
+
routeAvailable: true,
|
|
146
|
+
sourceStatus: "ok",
|
|
147
|
+
usedApiKey,
|
|
148
|
+
usedFromToken,
|
|
149
|
+
usedToToken,
|
|
150
|
+
wasSubstituted: false,
|
|
151
|
+
rawResponse: json,
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Smart wrapper around _getDodoRouteCore that automatically falls back to alternative token sources
|
|
156
|
+
* (like Circle USDC) if the canonical tokens have no liquidity on the testnet.
|
|
157
|
+
*/
|
|
158
|
+
export async function getDodoRoute(params) {
|
|
159
|
+
let quote = await _getDodoRouteCore(params);
|
|
160
|
+
if (!quote.routeAvailable) {
|
|
161
|
+
const fromUpper = params.fromToken.toUpperCase();
|
|
162
|
+
const toUpper = params.toToken.toUpperCase();
|
|
163
|
+
// Smart Fallback: If swapping TO canonical USDC failed, try Alternate Circle USDC
|
|
164
|
+
if (toUpper === "USDC" || toUpper === USDC_ADDRESS.toUpperCase()) {
|
|
165
|
+
const fallbackQuote = await _getDodoRouteCore({ ...params, toToken: CIRCLE_USDC_ADDRESS });
|
|
166
|
+
if (fallbackQuote.routeAvailable) {
|
|
167
|
+
return {
|
|
168
|
+
...fallbackQuote,
|
|
169
|
+
wasSubstituted: true,
|
|
170
|
+
substitutionNote: `toToken substituted: canonical USDC (${USDC_ADDRESS}) had no route; used altUSDC (${CIRCLE_USDC_ADDRESS}). Ensure your approval targets the correct address.`,
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
// Smart Fallback: If swapping FROM canonical USDC failed, try Alternate Circle USDC
|
|
175
|
+
if (fromUpper === "USDC" || fromUpper === USDC_ADDRESS.toUpperCase()) {
|
|
176
|
+
const fallbackQuote = await _getDodoRouteCore({ ...params, fromToken: CIRCLE_USDC_ADDRESS });
|
|
177
|
+
if (fallbackQuote.routeAvailable) {
|
|
178
|
+
return {
|
|
179
|
+
...fallbackQuote,
|
|
180
|
+
wasSubstituted: true,
|
|
181
|
+
substitutionNote: `fromToken substituted: canonical USDC (${USDC_ADDRESS}) had no route; used altUSDC (${CIRCLE_USDC_ADDRESS}). Ensure your allowance covers the correct address.`,
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return quote;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Checks whether a token is the native PHRS token.
|
|
190
|
+
*/
|
|
191
|
+
export function isNativeToken(token) {
|
|
192
|
+
const upper = token.toUpperCase();
|
|
193
|
+
if (upper === "PHRS")
|
|
194
|
+
return true;
|
|
195
|
+
return token.toLowerCase() === PHRS_ADDRESS.toLowerCase();
|
|
196
|
+
}
|
|
197
197
|
//# sourceMappingURL=dodoApi.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"envLoader.d.ts","sourceRoot":"","sources":["../../src/lib/envLoader.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// Synchronously load .env from cwd before any other module reads process.env.
|
|
2
|
+
// Must be imported as the very first import in index.ts so that wallet store,
|
|
3
|
+
// constants, and other modules that read env vars at module-init time see the values.
|
|
4
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync } from "fs";
|
|
5
|
+
import { join, resolve, dirname } from "path";
|
|
6
|
+
import { randomBytes } from "crypto";
|
|
7
|
+
// 1. Load .env
|
|
8
|
+
try {
|
|
9
|
+
const text = readFileSync(join(process.cwd(), ".env"), "utf-8");
|
|
10
|
+
for (const line of text.split(/\r?\n/)) {
|
|
11
|
+
const m = line.match(/^\s*([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*?)\s*$/);
|
|
12
|
+
if (m && m[1] && !process.env[m[1]]) {
|
|
13
|
+
// Strip surrounding quotes if present
|
|
14
|
+
process.env[m[1]] = m[2].replace(/^(['"])(.*)\1$/, "$2");
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
// No .env file — environment vars must be set externally (CI, shell, MCP host)
|
|
20
|
+
}
|
|
21
|
+
// 2. Auto-resolve wallet persistence so managed wallets survive restarts
|
|
22
|
+
// without requiring explicit config from the user.
|
|
23
|
+
if (!process.env.WALLET_STORE_PATH) {
|
|
24
|
+
process.env.WALLET_STORE_PATH = "./.agents/wallets.json";
|
|
25
|
+
}
|
|
26
|
+
if (!process.env.WALLET_ENCRYPTION_KEY) {
|
|
27
|
+
const storePath = resolve(process.cwd(), process.env.WALLET_STORE_PATH);
|
|
28
|
+
const keyPath = join(dirname(storePath), ".key");
|
|
29
|
+
try {
|
|
30
|
+
if (existsSync(keyPath)) {
|
|
31
|
+
process.env.WALLET_ENCRYPTION_KEY = readFileSync(keyPath, "utf-8").trim();
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
mkdirSync(dirname(keyPath), { recursive: true });
|
|
35
|
+
const key = randomBytes(32).toString("hex");
|
|
36
|
+
writeFileSync(keyPath, key, { mode: 0o600 });
|
|
37
|
+
process.env.WALLET_ENCRYPTION_KEY = key;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
// File ops failed (read-only FS, permission error) — fall back to in-memory behavior
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=envLoader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"envLoader.js","sourceRoot":"","sources":["../../src/lib/envLoader.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,8EAA8E;AAC9E,sFAAsF;AACtF,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AACxE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAErC,eAAe;AACf,IAAI,CAAC;IACH,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC;IAChE,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;QACvC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,8CAA8C,CAAC,CAAC;QACrE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACpC,sCAAsC;YACtC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,gBAAgB,EAAE,IAAI,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;AACH,CAAC;AAAC,MAAM,CAAC;IACP,+EAA+E;AACjF,CAAC;AAED,yEAAyE;AACzE,sDAAsD;AACtD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,CAAC;IACnC,OAAO,CAAC,GAAG,CAAC,iBAAiB,GAAG,wBAAwB,CAAC;AAC3D,CAAC;AAED,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,qBAAqB,EAAE,CAAC;IACvC,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IACxE,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC,CAAC;IACjD,IAAI,CAAC;QACH,IAAI,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YACxB,OAAO,CAAC,GAAG,CAAC,qBAAqB,GAAG,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;QAC5E,CAAC;aAAM,CAAC;YACN,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YACjD,MAAM,GAAG,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;YAC5C,aAAa,CAAC,OAAO,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;YAC7C,OAAO,CAAC,GAAG,CAAC,qBAAqB,GAAG,GAAG,CAAC;QAC1C,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,qFAAqF;IACvF,CAAC;AACH,CAAC"}
|
package/dist/lib/http.d.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
export declare class HttpError extends Error {
|
|
2
|
-
readonly status?: number | undefined;
|
|
3
|
-
readonly statusText?: string | undefined;
|
|
4
|
-
constructor(message: string, status?: number | undefined, statusText?: string | undefined);
|
|
5
|
-
}
|
|
6
|
-
export interface FetchWithRetryOptions extends RequestInit {
|
|
7
|
-
timeoutMs?: number;
|
|
8
|
-
retries?: number;
|
|
9
|
-
retryDelayMs?: number;
|
|
10
|
-
}
|
|
11
|
-
export declare function fetchWithTimeoutAndRetry(url: string | URL, options?: FetchWithRetryOptions): Promise<Response>;
|
|
12
|
-
export declare function redactSensitive(value: unknown): unknown;
|
|
13
|
-
export declare function isBlockedIp(ip: string): boolean;
|
|
14
|
-
export declare function assertSafeFetchUrl(rawUrl: string): Promise<void>;
|
|
1
|
+
export declare class HttpError extends Error {
|
|
2
|
+
readonly status?: number | undefined;
|
|
3
|
+
readonly statusText?: string | undefined;
|
|
4
|
+
constructor(message: string, status?: number | undefined, statusText?: string | undefined);
|
|
5
|
+
}
|
|
6
|
+
export interface FetchWithRetryOptions extends RequestInit {
|
|
7
|
+
timeoutMs?: number;
|
|
8
|
+
retries?: number;
|
|
9
|
+
retryDelayMs?: number;
|
|
10
|
+
}
|
|
11
|
+
export declare function fetchWithTimeoutAndRetry(url: string | URL, options?: FetchWithRetryOptions): Promise<Response>;
|
|
12
|
+
export declare function redactSensitive(value: unknown): unknown;
|
|
13
|
+
export declare function isBlockedIp(ip: string): boolean;
|
|
14
|
+
export declare function assertSafeFetchUrl(rawUrl: string): Promise<void>;
|
|
15
15
|
//# sourceMappingURL=http.d.ts.map
|