safehands-pharos 1.2.6 → 1.4.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/.env.example +64 -26
- package/README.md +333 -445
- package/dist/cli.d.ts +5 -5
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +124 -98
- 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.js +138 -87
- package/dist/index.js.map +1 -1
- package/dist/init.d.ts +1 -1
- package/dist/init.js +65 -65
- package/dist/lib/auditLog.d.ts +9 -0
- package/dist/lib/auditLog.d.ts.map +1 -0
- package/dist/lib/auditLog.js +30 -0
- package/dist/lib/auditLog.js.map +1 -0
- package/dist/lib/constants.d.ts +291 -291
- package/dist/lib/constants.js +292 -292
- package/dist/lib/dodoApi.d.ts +78 -70
- package/dist/lib/dodoApi.d.ts.map +1 -1
- package/dist/lib/dodoApi.js +196 -178
- package/dist/lib/dodoApi.js.map +1 -1
- 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.d.ts.map +1 -1
- package/dist/lib/pharosClient.js +63 -53
- package/dist/lib/pharosClient.js.map +1 -1
- package/dist/lib/policy/actionPolicyEngine.d.ts +53 -53
- package/dist/lib/policy/actionPolicyEngine.js +212 -212
- package/dist/lib/policy/actionPolicyEngine.js.map +1 -1
- package/dist/lib/riskEngine.d.ts +26 -26
- package/dist/lib/riskEngine.js +283 -283
- package/dist/lib/signer/index.d.ts +24 -24
- package/dist/lib/signer/index.d.ts.map +1 -1
- package/dist/lib/signer/index.js +88 -89
- package/dist/lib/signer/index.js.map +1 -1
- package/dist/lib/spendAccumulator.d.ts +10 -0
- package/dist/lib/spendAccumulator.d.ts.map +1 -0
- package/dist/lib/spendAccumulator.js +54 -0
- package/dist/lib/spendAccumulator.js.map +1 -0
- 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/testRpc.d.ts +1 -1
- package/dist/lib/testRpc.js +29 -29
- package/dist/lib/testRpcLive.d.ts +1 -1
- package/dist/lib/testRpcLive.js +88 -88
- package/dist/lib/testTools.d.ts +1 -1
- package/dist/lib/testTools.js +397 -397
- 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 -18
- package/dist/lib/wallet/index.d.ts.map +1 -1
- package/dist/lib/wallet/index.js +128 -70
- package/dist/lib/wallet/index.js.map +1 -1
- 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 -46
- package/dist/tools/approveToken.d.ts.map +1 -1
- package/dist/tools/approveToken.js +85 -83
- package/dist/tools/approveToken.js.map +1 -1
- package/dist/tools/assessRisk.d.ts +79 -79
- package/dist/tools/assessRisk.d.ts.map +1 -1
- package/dist/tools/assessRisk.js +104 -93
- package/dist/tools/assessRisk.js.map +1 -1
- package/dist/tools/checkAllowance.d.ts +43 -36
- package/dist/tools/checkAllowance.d.ts.map +1 -1
- package/dist/tools/checkAllowance.js +56 -42
- package/dist/tools/checkAllowance.js.map +1 -1
- package/dist/tools/checkTokenSecurity.d.ts +46 -46
- package/dist/tools/checkTokenSecurity.d.ts.map +1 -1
- package/dist/tools/checkTokenSecurity.js +95 -88
- package/dist/tools/checkTokenSecurity.js.map +1 -1
- package/dist/tools/createAgentWallet.d.ts +26 -26
- package/dist/tools/createAgentWallet.d.ts.map +1 -1
- package/dist/tools/createAgentWallet.js +58 -59
- 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 -59
- package/dist/tools/executeSwap.d.ts.map +1 -1
- package/dist/tools/executeSwap.js +141 -129
- package/dist/tools/executeSwap.js.map +1 -1
- 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 -51
- package/dist/tools/getExecutionHistory.d.ts.map +1 -1
- package/dist/tools/getExecutionHistory.js +154 -93
- package/dist/tools/getExecutionHistory.js.map +1 -1
- 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 -57
- package/dist/tools/getTransactionStatus.d.ts.map +1 -1
- package/dist/tools/getTransactionStatus.js +59 -67
- package/dist/tools/getTransactionStatus.js.map +1 -1
- 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.d.ts.map +1 -1
- package/dist/tools/publishRiskScore.js +88 -85
- package/dist/tools/publishRiskScore.js.map +1 -1
- package/dist/tools/queryRiskRegistry.d.ts +38 -48
- package/dist/tools/queryRiskRegistry.d.ts.map +1 -1
- package/dist/tools/queryRiskRegistry.js +55 -60
- package/dist/tools/queryRiskRegistry.js.map +1 -1
- 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.d.ts.map +1 -1
- package/dist/tools/safehandsSafeExecute.js +81 -75
- package/dist/tools/safehandsSafeExecute.js.map +1 -1
- 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 -58
- package/dist/tools/sendPayment.d.ts.map +1 -1
- package/dist/tools/sendPayment.js +117 -108
- package/dist/tools/sendPayment.js.map +1 -1
- package/dist/tools/simulateTransaction.d.ts +60 -81
- package/dist/tools/simulateTransaction.d.ts.map +1 -1
- package/dist/tools/simulateTransaction.js +83 -88
- package/dist/tools/simulateTransaction.js.map +1 -1
- 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.d.ts.map +1 -1
- package/dist/tools/x402PayAndFetch.js +152 -149
- package/dist/tools/x402PayAndFetch.js.map +1 -1
- package/dist/x402Server.d.ts +1 -1
- package/dist/x402Server.js +252 -252
- package/examples/dashboard/index.html +337 -0
- package/package.json +83 -82
- package/skill/SKILL.md +133 -133
package/dist/lib/signer/index.js
CHANGED
|
@@ -1,90 +1,89 @@
|
|
|
1
|
-
// ─── SignerProvider ─────────────────────────────────────────────────────
|
|
2
|
-
// Abstraction layer for signing. Tools never read process.env.PRIVATE_KEY
|
|
3
|
-
// directly — they request a signer through this provider.
|
|
4
|
-
// ────────────────────────────────────────────────────────────────────────
|
|
5
|
-
import { privateKeyToAccount } from "viem/accounts";
|
|
6
|
-
import { walletStore,
|
|
7
|
-
export function isSignerFailure(r) {
|
|
8
|
-
return "error" in r;
|
|
9
|
-
}
|
|
10
|
-
function normalizePrivateKey(pk) {
|
|
11
|
-
return (pk.startsWith("0x") ? pk : `0x${pk}`);
|
|
12
|
-
}
|
|
13
|
-
function accountFromEnvKey(envName, mode) {
|
|
14
|
-
const pk = process.env[envName];
|
|
15
|
-
if (!pk)
|
|
16
|
-
return null;
|
|
17
|
-
try {
|
|
18
|
-
const account = privateKeyToAccount(normalizePrivateKey(pk));
|
|
19
|
-
return { account, address: account.address, mode };
|
|
20
|
-
}
|
|
21
|
-
catch {
|
|
22
|
-
return {
|
|
23
|
-
error: {
|
|
24
|
-
code: "INVALID_PRIVATE_KEY",
|
|
25
|
-
message: `${envName} is not a valid private key.`,
|
|
26
|
-
},
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
async function accountFromManagedWallet(agentId) {
|
|
31
|
-
const walletMode = process.env.WALLET_MODE || "none";
|
|
32
|
-
if (walletMode !== "managed-testnet" || !agentId)
|
|
33
|
-
return null;
|
|
34
|
-
if (process.env.WALLET_STORE_PATH && !process.env.WALLET_ENCRYPTION_KEY) {
|
|
35
|
-
return {
|
|
36
|
-
error: {
|
|
37
|
-
code: "WALLET_ENCRYPTION_KEY_REQUIRED",
|
|
38
|
-
message: "WALLET_ENCRYPTION_KEY is required when WALLET_STORE_PATH is used for persistent managed-testnet wallets.",
|
|
39
|
-
},
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
const stored = await walletStore.get(agentId);
|
|
43
|
-
if (!stored)
|
|
44
|
-
return null;
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
*
|
|
62
|
-
* Priority for
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
}
|
|
1
|
+
// ─── SignerProvider ─────────────────────────────────────────────────────
|
|
2
|
+
// Abstraction layer for signing. Tools never read process.env.PRIVATE_KEY
|
|
3
|
+
// directly — they request a signer through this provider.
|
|
4
|
+
// ────────────────────────────────────────────────────────────────────────
|
|
5
|
+
import { privateKeyToAccount } from "viem/accounts";
|
|
6
|
+
import { walletStore, decryptKey, getEffectiveEncryptionKey } from "../wallet/index.js";
|
|
7
|
+
export function isSignerFailure(r) {
|
|
8
|
+
return "error" in r;
|
|
9
|
+
}
|
|
10
|
+
function normalizePrivateKey(pk) {
|
|
11
|
+
return (pk.startsWith("0x") ? pk : `0x${pk}`);
|
|
12
|
+
}
|
|
13
|
+
function accountFromEnvKey(envName, mode) {
|
|
14
|
+
const pk = process.env[envName];
|
|
15
|
+
if (!pk)
|
|
16
|
+
return null;
|
|
17
|
+
try {
|
|
18
|
+
const account = privateKeyToAccount(normalizePrivateKey(pk));
|
|
19
|
+
return { account, address: account.address, mode };
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return {
|
|
23
|
+
error: {
|
|
24
|
+
code: "INVALID_PRIVATE_KEY",
|
|
25
|
+
message: `${envName} is not a valid private key.`,
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
async function accountFromManagedWallet(agentId) {
|
|
31
|
+
const walletMode = process.env.WALLET_MODE || "none";
|
|
32
|
+
if (walletMode !== "managed-testnet" || !agentId)
|
|
33
|
+
return null;
|
|
34
|
+
if (process.env.WALLET_STORE_PATH && !process.env.WALLET_ENCRYPTION_KEY) {
|
|
35
|
+
return {
|
|
36
|
+
error: {
|
|
37
|
+
code: "WALLET_ENCRYPTION_KEY_REQUIRED",
|
|
38
|
+
message: "WALLET_ENCRYPTION_KEY is required when WALLET_STORE_PATH is used for persistent managed-testnet wallets.",
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
const stored = await walletStore.get(agentId);
|
|
43
|
+
if (!stored)
|
|
44
|
+
return null;
|
|
45
|
+
try {
|
|
46
|
+
const privateKey = decryptKey(stored.encryptedKey, getEffectiveEncryptionKey());
|
|
47
|
+
const account = privateKeyToAccount(normalizePrivateKey(privateKey));
|
|
48
|
+
return { account, address: account.address, mode: "managed-testnet" };
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return {
|
|
52
|
+
error: {
|
|
53
|
+
code: "NO_SIGNER_AVAILABLE",
|
|
54
|
+
message: "Managed wallet key could not be decrypted for signing. Check WALLET_ENCRYPTION_KEY matches the key used when the wallet was created.",
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Get a signer for write/payment operations.
|
|
61
|
+
* Priority for x402: managed wallet > X402_SIGNER_PRIVATE_KEY > PRIVATE_KEY fallback.
|
|
62
|
+
* Priority for writes: managed wallet > PRIVATE_KEY fallback.
|
|
63
|
+
*/
|
|
64
|
+
export async function getSigner(agentId, options = {}) {
|
|
65
|
+
const purpose = options.purpose || "write";
|
|
66
|
+
const managed = await accountFromManagedWallet(agentId);
|
|
67
|
+
if (managed)
|
|
68
|
+
return managed;
|
|
69
|
+
if (purpose === "x402") {
|
|
70
|
+
const x402Env = accountFromEnvKey("X402_SIGNER_PRIVATE_KEY", "x402-env");
|
|
71
|
+
if (x402Env)
|
|
72
|
+
return x402Env;
|
|
73
|
+
}
|
|
74
|
+
const walletMode = process.env.WALLET_MODE || "none";
|
|
75
|
+
if (walletMode === "env" || process.env.PRIVATE_KEY) {
|
|
76
|
+
const env = accountFromEnvKey("PRIVATE_KEY", "env");
|
|
77
|
+
if (env)
|
|
78
|
+
return env;
|
|
79
|
+
}
|
|
80
|
+
return {
|
|
81
|
+
error: {
|
|
82
|
+
code: "NO_SIGNER_AVAILABLE",
|
|
83
|
+
message: purpose === "x402"
|
|
84
|
+
? "No x402 signer available. Use WALLET_MODE=managed-testnet with agentId, X402_SIGNER_PRIVATE_KEY, or PRIVATE_KEY as testnet developer fallback."
|
|
85
|
+
: "No signer available. Use WALLET_MODE=managed-testnet with agentId, or WALLET_MODE=env with PRIVATE_KEY for testnet developer mode.",
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
}
|
|
90
89
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/signer/index.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,0EAA0E;AAC1E,0DAA0D;AAC1D,2EAA2E;AAE3E,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAEpD,OAAO,EAAE,WAAW,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/signer/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare function getMaxDailySpendUsd(): number;
|
|
2
|
+
export declare function estimateUsd(amount: string, token: "PHRS" | "USDC" | "USDT" | string): number;
|
|
3
|
+
export declare function checkDailyLimit(walletAddress: string, amountUsd: number): {
|
|
4
|
+
allowed: boolean;
|
|
5
|
+
currentUsd: number;
|
|
6
|
+
limitUsd: number;
|
|
7
|
+
remainingUsd: number;
|
|
8
|
+
};
|
|
9
|
+
export declare function recordSpend(walletAddress: string, amountUsd: number): void;
|
|
10
|
+
//# sourceMappingURL=spendAccumulator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spendAccumulator.d.ts","sourceRoot":"","sources":["../../src/lib/spendAccumulator.ts"],"names":[],"mappings":"AAqBA,wBAAgB,mBAAmB,IAAI,MAAM,CAE5C;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAO5F;AAED,wBAAgB,eAAe,CAC7B,aAAa,EAAE,MAAM,EACrB,SAAS,EAAE,MAAM,GAChB;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CAalF;AAED,wBAAgB,WAAW,CAAC,aAAa,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAU1E"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// ─── Daily Spend Accumulator ────────────────────────────────────────────
|
|
2
|
+
// In-memory per-wallet daily spend tracker. Resets at UTC midnight.
|
|
3
|
+
// Enforces MAX_DAILY_SPEND_USD across sendPayment and executeSwap.
|
|
4
|
+
// PHRS → USD conversion uses PHRS_USD_PRICE env var (default 1.0).
|
|
5
|
+
// ────────────────────────────────────────────────────────────────────────
|
|
6
|
+
const buckets = new Map();
|
|
7
|
+
function todayUtc() {
|
|
8
|
+
return new Date().toISOString().slice(0, 10);
|
|
9
|
+
}
|
|
10
|
+
function getPhrsUsdPrice() {
|
|
11
|
+
return parseFloat(process.env.PHRS_USD_PRICE || "1.0");
|
|
12
|
+
}
|
|
13
|
+
export function getMaxDailySpendUsd() {
|
|
14
|
+
return parseFloat(process.env.MAX_DAILY_SPEND_USD || "10");
|
|
15
|
+
}
|
|
16
|
+
export function estimateUsd(amount, token) {
|
|
17
|
+
const n = parseFloat(amount);
|
|
18
|
+
if (isNaN(n))
|
|
19
|
+
return 0;
|
|
20
|
+
const upper = token.toUpperCase();
|
|
21
|
+
if (upper === "PHRS")
|
|
22
|
+
return n * getPhrsUsdPrice();
|
|
23
|
+
if (upper === "USDC" || upper === "USDT")
|
|
24
|
+
return n;
|
|
25
|
+
return 0; // unknown token — do not count to avoid false blocks
|
|
26
|
+
}
|
|
27
|
+
export function checkDailyLimit(walletAddress, amountUsd) {
|
|
28
|
+
const key = walletAddress.toLowerCase();
|
|
29
|
+
const today = todayUtc();
|
|
30
|
+
const bucket = buckets.get(key);
|
|
31
|
+
const currentUsd = !bucket || bucket.dateUtc !== today ? 0 : bucket.totalUsd;
|
|
32
|
+
const limitUsd = getMaxDailySpendUsd();
|
|
33
|
+
const remainingUsd = Math.max(0, limitUsd - currentUsd);
|
|
34
|
+
return {
|
|
35
|
+
allowed: currentUsd + amountUsd <= limitUsd,
|
|
36
|
+
currentUsd,
|
|
37
|
+
limitUsd,
|
|
38
|
+
remainingUsd,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
export function recordSpend(walletAddress, amountUsd) {
|
|
42
|
+
if (amountUsd <= 0)
|
|
43
|
+
return;
|
|
44
|
+
const key = walletAddress.toLowerCase();
|
|
45
|
+
const today = todayUtc();
|
|
46
|
+
const bucket = buckets.get(key);
|
|
47
|
+
if (!bucket || bucket.dateUtc !== today) {
|
|
48
|
+
buckets.set(key, { dateUtc: today, totalUsd: amountUsd });
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
bucket.totalUsd += amountUsd;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=spendAccumulator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spendAccumulator.js","sourceRoot":"","sources":["../../src/lib/spendAccumulator.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,oEAAoE;AACpE,mEAAmE;AACnE,mEAAmE;AACnE,2EAA2E;AAO3E,MAAM,OAAO,GAAG,IAAI,GAAG,EAAqB,CAAC;AAE7C,SAAS,QAAQ;IACf,OAAO,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAC/C,CAAC;AAED,SAAS,eAAe;IACtB,OAAO,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,KAAK,CAAC,CAAC;AACzD,CAAC;AAED,MAAM,UAAU,mBAAmB;IACjC,OAAO,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,IAAI,CAAC,CAAC;AAC7D,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,MAAc,EAAE,KAAwC;IAClF,MAAM,CAAC,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;IAC7B,IAAI,KAAK,CAAC,CAAC,CAAC;QAAE,OAAO,CAAC,CAAC;IACvB,MAAM,KAAK,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;IAClC,IAAI,KAAK,KAAK,MAAM;QAAE,OAAO,CAAC,GAAG,eAAe,EAAE,CAAC;IACnD,IAAI,KAAK,KAAK,MAAM,IAAI,KAAK,KAAK,MAAM;QAAE,OAAO,CAAC,CAAC;IACnD,OAAO,CAAC,CAAC,CAAC,qDAAqD;AACjE,CAAC;AAED,MAAM,UAAU,eAAe,CAC7B,aAAqB,EACrB,SAAiB;IAEjB,MAAM,GAAG,GAAG,aAAa,CAAC,WAAW,EAAE,CAAC;IACxC,MAAM,KAAK,GAAG,QAAQ,EAAE,CAAC;IACzB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAChC,MAAM,UAAU,GAAG,CAAC,MAAM,IAAI,MAAM,CAAC,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC;IAC7E,MAAM,QAAQ,GAAG,mBAAmB,EAAE,CAAC;IACvC,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,GAAG,UAAU,CAAC,CAAC;IACxD,OAAO;QACL,OAAO,EAAE,UAAU,GAAG,SAAS,IAAI,QAAQ;QAC3C,UAAU;QACV,QAAQ;QACR,YAAY;KACb,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,aAAqB,EAAE,SAAiB;IAClE,IAAI,SAAS,IAAI,CAAC;QAAE,OAAO;IAC3B,MAAM,GAAG,GAAG,aAAa,CAAC,WAAW,EAAE,CAAC;IACxC,MAAM,KAAK,GAAG,QAAQ,EAAE,CAAC;IACzB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAChC,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,OAAO,KAAK,KAAK,EAAE,CAAC;QACxC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC;IAC5D,CAAC;SAAM,CAAC;QACN,MAAM,CAAC,QAAQ,IAAI,SAAS,CAAC;IAC/B,CAAC;AACH,CAAC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export {};
|
|
1
|
+
export {};
|
|
2
2
|
//# sourceMappingURL=testDodoLive.d.ts.map
|
package/dist/lib/testDodoLive.js
CHANGED
|
@@ -1,105 +1,105 @@
|
|
|
1
|
-
// ─── Live DODO/FaroSwap Verification ───────────────────────────────────
|
|
2
|
-
// Tests DODO API reachability if DODO_API_KEY is present.
|
|
3
|
-
// Skips cleanly if API key is missing.
|
|
4
|
-
// ────────────────────────────────────────────────────────────────────────
|
|
5
|
-
import { DODO_API_BASE, DODO_API_KEY } from "./constants.js";
|
|
6
|
-
import { getDodoRoute } from "./dodoApi.js";
|
|
7
|
-
const results = [];
|
|
8
|
-
async function main() {
|
|
9
|
-
console.log("═══════════════════════════════════════════════════════════");
|
|
10
|
-
console.log(" SafeHands — DODO/FaroSwap Live Verification");
|
|
11
|
-
console.log("═══════════════════════════════════════════════════════════");
|
|
12
|
-
console.log(` DODO API Base: ${DODO_API_BASE}`);
|
|
13
|
-
const maskedKey = DODO_API_KEY ? `pub_****${DODO_API_KEY.slice(-4)}` : "NOT SET";
|
|
14
|
-
console.log(` API Key: ${maskedKey}`);
|
|
15
|
-
console.log("");
|
|
16
|
-
if (!DODO_API_KEY) {
|
|
17
|
-
console.log(" ⏭️ SKIPPED_MISSING_DODO_API_KEY — set DODO_API_KEY to enable live DODO checks.");
|
|
18
|
-
results.push({
|
|
19
|
-
name: "dodo_api_route_check",
|
|
20
|
-
status: "SKIPPED_MISSING_DODO_API_KEY",
|
|
21
|
-
detail: "DODO_API_KEY env var not set. This is expected for CI/demo environments.",
|
|
22
|
-
});
|
|
23
|
-
}
|
|
24
|
-
else {
|
|
25
|
-
// Try a read-only route quote
|
|
26
|
-
try {
|
|
27
|
-
const quote = await getDodoRoute({
|
|
28
|
-
fromToken: "PHRS",
|
|
29
|
-
toToken: "USDC",
|
|
30
|
-
amountHuman: "0.000001",
|
|
31
|
-
walletAddress: "0x0000000000000000000000000000000000000001",
|
|
32
|
-
});
|
|
33
|
-
if (quote.routeAvailable && parseFloat(quote.amountOut) > 0) {
|
|
34
|
-
results.push({
|
|
35
|
-
name: "dodo_api_route_check",
|
|
36
|
-
status: "PASS",
|
|
37
|
-
detail: `Route found: 0.000001 PHRS → ${quote.amountOut} USDC`,
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
else {
|
|
41
|
-
results.push({
|
|
42
|
-
name: "dodo_api_route_check",
|
|
43
|
-
status: "NO_ROUTE_AVAILABLE",
|
|
44
|
-
detail: `API reachable. No route available (may be no liquidity).`,
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
catch (err) {
|
|
49
|
-
const msg = err.message || String(err);
|
|
50
|
-
if (msg.includes("DODO_API_AUTH_REQUIRED")) {
|
|
51
|
-
results.push({
|
|
52
|
-
name: "dodo_api_route_check",
|
|
53
|
-
status: "DODO_API_AUTH_REQUIRED",
|
|
54
|
-
detail: msg,
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
else if (msg.includes("DODO_API_UNAVAILABLE") || msg.includes("DODO_API_RATE_LIMITED") || msg.includes("fetch failed") || msg.includes("network timeout")) {
|
|
58
|
-
results.push({
|
|
59
|
-
name: "dodo_api_route_check",
|
|
60
|
-
status: "DODO_API_UNAVAILABLE",
|
|
61
|
-
detail: `Network/timeout/rate-limited: ${msg}`,
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
else {
|
|
65
|
-
results.push({
|
|
66
|
-
name: "dodo_api_route_check",
|
|
67
|
-
status: "FAIL",
|
|
68
|
-
detail: msg,
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
// Router address verification status
|
|
74
|
-
results.push({
|
|
75
|
-
name: "dodo_approve_address_status",
|
|
76
|
-
status: "PASS",
|
|
77
|
-
detail: "0x4Cf317b8918FbE8A890c01eDAb7d548555Ac2cE9 — PROJECT_CONFIGURED (not verified by official FaroSwap/DODO docs)",
|
|
78
|
-
});
|
|
79
|
-
results.push({
|
|
80
|
-
name: "dodo_route_proxy_status",
|
|
81
|
-
status: "PASS",
|
|
82
|
-
detail: "0x819829e5CF6e19F9fED92F6b4CC1edF45a2cC4A2 — PROJECT_CONFIGURED (not verified by official FaroSwap/DODO docs)",
|
|
83
|
-
});
|
|
84
|
-
// Print results
|
|
85
|
-
console.log(`\n${"#".padStart(2)} ${"Status".padEnd(32)} ${"Check".padEnd(34)} Detail`);
|
|
86
|
-
console.log("─".repeat(110));
|
|
87
|
-
for (const [i, r] of results.entries()) {
|
|
88
|
-
const icon = r.status === "PASS" ? "✅" : r.status.startsWith("SKIPPED") ? "⏭️" : "❌";
|
|
89
|
-
console.log(`${String(i + 1).padStart(2)} ${icon} ${r.status.padEnd(29)} ${r.name.padEnd(34)} ${r.detail.slice(0, 80)}`);
|
|
90
|
-
}
|
|
91
|
-
const failed = results.filter(r => r.status === "FAIL");
|
|
92
|
-
console.log("─".repeat(110));
|
|
93
|
-
console.log(`${results.filter(r => r.status === "PASS").length}/${results.length} checks passed, ${results.filter(r => r.status.startsWith("SKIPPED")).length} skipped.`);
|
|
94
|
-
if (failed.length > 0) {
|
|
95
|
-
console.error("\nFailed:");
|
|
96
|
-
for (const f of failed)
|
|
97
|
-
console.error(` - ${f.name}: ${f.detail}`);
|
|
98
|
-
process.exit(1);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
main().catch((err) => {
|
|
102
|
-
console.error("❌ Unexpected error:", err);
|
|
103
|
-
process.exit(1);
|
|
104
|
-
});
|
|
1
|
+
// ─── Live DODO/FaroSwap Verification ───────────────────────────────────
|
|
2
|
+
// Tests DODO API reachability if DODO_API_KEY is present.
|
|
3
|
+
// Skips cleanly if API key is missing.
|
|
4
|
+
// ────────────────────────────────────────────────────────────────────────
|
|
5
|
+
import { DODO_API_BASE, DODO_API_KEY } from "./constants.js";
|
|
6
|
+
import { getDodoRoute } from "./dodoApi.js";
|
|
7
|
+
const results = [];
|
|
8
|
+
async function main() {
|
|
9
|
+
console.log("═══════════════════════════════════════════════════════════");
|
|
10
|
+
console.log(" SafeHands — DODO/FaroSwap Live Verification");
|
|
11
|
+
console.log("═══════════════════════════════════════════════════════════");
|
|
12
|
+
console.log(` DODO API Base: ${DODO_API_BASE}`);
|
|
13
|
+
const maskedKey = DODO_API_KEY ? `pub_****${DODO_API_KEY.slice(-4)}` : "NOT SET";
|
|
14
|
+
console.log(` API Key: ${maskedKey}`);
|
|
15
|
+
console.log("");
|
|
16
|
+
if (!DODO_API_KEY) {
|
|
17
|
+
console.log(" ⏭️ SKIPPED_MISSING_DODO_API_KEY — set DODO_API_KEY to enable live DODO checks.");
|
|
18
|
+
results.push({
|
|
19
|
+
name: "dodo_api_route_check",
|
|
20
|
+
status: "SKIPPED_MISSING_DODO_API_KEY",
|
|
21
|
+
detail: "DODO_API_KEY env var not set. This is expected for CI/demo environments.",
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
// Try a read-only route quote
|
|
26
|
+
try {
|
|
27
|
+
const quote = await getDodoRoute({
|
|
28
|
+
fromToken: "PHRS",
|
|
29
|
+
toToken: "USDC",
|
|
30
|
+
amountHuman: "0.000001",
|
|
31
|
+
walletAddress: "0x0000000000000000000000000000000000000001",
|
|
32
|
+
});
|
|
33
|
+
if (quote.routeAvailable && parseFloat(quote.amountOut) > 0) {
|
|
34
|
+
results.push({
|
|
35
|
+
name: "dodo_api_route_check",
|
|
36
|
+
status: "PASS",
|
|
37
|
+
detail: `Route found: 0.000001 PHRS → ${quote.amountOut} USDC`,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
results.push({
|
|
42
|
+
name: "dodo_api_route_check",
|
|
43
|
+
status: "NO_ROUTE_AVAILABLE",
|
|
44
|
+
detail: `API reachable. No route available (may be no liquidity).`,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
const msg = err.message || String(err);
|
|
50
|
+
if (msg.includes("DODO_API_AUTH_REQUIRED")) {
|
|
51
|
+
results.push({
|
|
52
|
+
name: "dodo_api_route_check",
|
|
53
|
+
status: "DODO_API_AUTH_REQUIRED",
|
|
54
|
+
detail: msg,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
else if (msg.includes("DODO_API_UNAVAILABLE") || msg.includes("DODO_API_RATE_LIMITED") || msg.includes("fetch failed") || msg.includes("network timeout")) {
|
|
58
|
+
results.push({
|
|
59
|
+
name: "dodo_api_route_check",
|
|
60
|
+
status: "DODO_API_UNAVAILABLE",
|
|
61
|
+
detail: `Network/timeout/rate-limited: ${msg}`,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
results.push({
|
|
66
|
+
name: "dodo_api_route_check",
|
|
67
|
+
status: "FAIL",
|
|
68
|
+
detail: msg,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
// Router address verification status
|
|
74
|
+
results.push({
|
|
75
|
+
name: "dodo_approve_address_status",
|
|
76
|
+
status: "PASS",
|
|
77
|
+
detail: "0x4Cf317b8918FbE8A890c01eDAb7d548555Ac2cE9 — PROJECT_CONFIGURED (not verified by official FaroSwap/DODO docs)",
|
|
78
|
+
});
|
|
79
|
+
results.push({
|
|
80
|
+
name: "dodo_route_proxy_status",
|
|
81
|
+
status: "PASS",
|
|
82
|
+
detail: "0x819829e5CF6e19F9fED92F6b4CC1edF45a2cC4A2 — PROJECT_CONFIGURED (not verified by official FaroSwap/DODO docs)",
|
|
83
|
+
});
|
|
84
|
+
// Print results
|
|
85
|
+
console.log(`\n${"#".padStart(2)} ${"Status".padEnd(32)} ${"Check".padEnd(34)} Detail`);
|
|
86
|
+
console.log("─".repeat(110));
|
|
87
|
+
for (const [i, r] of results.entries()) {
|
|
88
|
+
const icon = r.status === "PASS" ? "✅" : r.status.startsWith("SKIPPED") ? "⏭️" : "❌";
|
|
89
|
+
console.log(`${String(i + 1).padStart(2)} ${icon} ${r.status.padEnd(29)} ${r.name.padEnd(34)} ${r.detail.slice(0, 80)}`);
|
|
90
|
+
}
|
|
91
|
+
const failed = results.filter(r => r.status === "FAIL");
|
|
92
|
+
console.log("─".repeat(110));
|
|
93
|
+
console.log(`${results.filter(r => r.status === "PASS").length}/${results.length} checks passed, ${results.filter(r => r.status.startsWith("SKIPPED")).length} skipped.`);
|
|
94
|
+
if (failed.length > 0) {
|
|
95
|
+
console.error("\nFailed:");
|
|
96
|
+
for (const f of failed)
|
|
97
|
+
console.error(` - ${f.name}: ${f.detail}`);
|
|
98
|
+
process.exit(1);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
main().catch((err) => {
|
|
102
|
+
console.error("❌ Unexpected error:", err);
|
|
103
|
+
process.exit(1);
|
|
104
|
+
});
|
|
105
105
|
//# sourceMappingURL=testDodoLive.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export {};
|
|
1
|
+
export {};
|
|
2
2
|
//# sourceMappingURL=testLiveSafehands.d.ts.map
|