@mixrpay/agent-sdk 0.5.0 → 0.6.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 +24 -4
- package/dist/index.cjs +301 -17
- package/dist/index.d.cts +210 -3
- package/dist/index.d.ts +210 -3
- package/dist/index.js +299 -17
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -9,14 +9,43 @@ import {
|
|
|
9
9
|
var MixrPayError = class extends Error {
|
|
10
10
|
/** Error code for programmatic handling */
|
|
11
11
|
code;
|
|
12
|
-
|
|
12
|
+
/** Optional hint for how long to wait before retrying (in milliseconds) */
|
|
13
|
+
retryAfterMs;
|
|
14
|
+
constructor(message, code = "MIXRPAY_ERROR", retryAfterMs) {
|
|
13
15
|
super(message);
|
|
14
16
|
this.name = "MixrPayError";
|
|
15
17
|
this.code = code;
|
|
18
|
+
this.retryAfterMs = retryAfterMs;
|
|
16
19
|
if (Error.captureStackTrace) {
|
|
17
20
|
Error.captureStackTrace(this, this.constructor);
|
|
18
21
|
}
|
|
19
22
|
}
|
|
23
|
+
/**
|
|
24
|
+
* Check if this error is retryable.
|
|
25
|
+
*
|
|
26
|
+
* Returns true if the operation might succeed on retry (e.g., transient network issues).
|
|
27
|
+
* Returns false if the error requires user action to resolve (e.g., insufficient balance).
|
|
28
|
+
*
|
|
29
|
+
* @returns true if the operation should be retried, false otherwise
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```typescript
|
|
33
|
+
* try {
|
|
34
|
+
* await wallet.fetch(...);
|
|
35
|
+
* } catch (error) {
|
|
36
|
+
* if (error instanceof MixrPayError && error.isRetryable()) {
|
|
37
|
+
* // Retry the operation
|
|
38
|
+
* await retry();
|
|
39
|
+
* } else {
|
|
40
|
+
* // Handle permanent failure
|
|
41
|
+
* throw error;
|
|
42
|
+
* }
|
|
43
|
+
* }
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
isRetryable() {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
20
49
|
};
|
|
21
50
|
var InsufficientBalanceError = class extends MixrPayError {
|
|
22
51
|
/** Amount required for the payment in USD */
|
|
@@ -74,6 +103,14 @@ var SpendingLimitExceededError = class extends MixrPayError {
|
|
|
74
103
|
this.limit = limit;
|
|
75
104
|
this.attempted = attempted;
|
|
76
105
|
}
|
|
106
|
+
/**
|
|
107
|
+
* Daily limits reset at midnight, so those are retryable (after waiting).
|
|
108
|
+
* Other limit types require user action (new session key, config change).
|
|
109
|
+
* @returns true only for daily limits
|
|
110
|
+
*/
|
|
111
|
+
isRetryable() {
|
|
112
|
+
return this.limitType === "daily";
|
|
113
|
+
}
|
|
77
114
|
};
|
|
78
115
|
var PaymentFailedError = class extends MixrPayError {
|
|
79
116
|
/** Detailed reason for the failure */
|
|
@@ -90,6 +127,13 @@ var PaymentFailedError = class extends MixrPayError {
|
|
|
90
127
|
this.reason = reason;
|
|
91
128
|
this.txHash = txHash;
|
|
92
129
|
}
|
|
130
|
+
/**
|
|
131
|
+
* Payment failures are often transient (network issues, temporary server errors).
|
|
132
|
+
* @returns true - payment failures should generally be retried
|
|
133
|
+
*/
|
|
134
|
+
isRetryable() {
|
|
135
|
+
return true;
|
|
136
|
+
}
|
|
93
137
|
};
|
|
94
138
|
var InvalidSessionKeyError = class extends MixrPayError {
|
|
95
139
|
/** Detailed reason why the key is invalid */
|
|
@@ -114,6 +158,13 @@ var X402ProtocolError = class extends MixrPayError {
|
|
|
114
158
|
this.name = "X402ProtocolError";
|
|
115
159
|
this.reason = reason;
|
|
116
160
|
}
|
|
161
|
+
/**
|
|
162
|
+
* Protocol errors may be caused by temporary server issues.
|
|
163
|
+
* @returns true - worth retrying in case server recovers
|
|
164
|
+
*/
|
|
165
|
+
isRetryable() {
|
|
166
|
+
return true;
|
|
167
|
+
}
|
|
117
168
|
};
|
|
118
169
|
var SessionExpiredError = class extends MixrPayError {
|
|
119
170
|
/** ID of the expired session */
|
|
@@ -181,6 +232,15 @@ var SessionRevokedError = class extends MixrPayError {
|
|
|
181
232
|
function isMixrPayError(error) {
|
|
182
233
|
return error instanceof MixrPayError;
|
|
183
234
|
}
|
|
235
|
+
function getErrorMessage(error) {
|
|
236
|
+
if (error instanceof MixrPayError) {
|
|
237
|
+
return error.message;
|
|
238
|
+
}
|
|
239
|
+
if (error instanceof Error) {
|
|
240
|
+
return error.message;
|
|
241
|
+
}
|
|
242
|
+
return String(error);
|
|
243
|
+
}
|
|
184
244
|
|
|
185
245
|
// src/session-key.ts
|
|
186
246
|
var USDC_ADDRESSES = {
|
|
@@ -411,7 +471,7 @@ function getAmountUsd(requirements) {
|
|
|
411
471
|
}
|
|
412
472
|
|
|
413
473
|
// src/agent-wallet.ts
|
|
414
|
-
var SDK_VERSION = "0.
|
|
474
|
+
var SDK_VERSION = "0.6.1";
|
|
415
475
|
var DEFAULT_BASE_URL = process.env.MIXRPAY_BASE_URL || "https://www.mixrpay.com";
|
|
416
476
|
var DEFAULT_TIMEOUT = 3e4;
|
|
417
477
|
var NETWORKS = {
|
|
@@ -603,7 +663,19 @@ var AgentWallet = class {
|
|
|
603
663
|
});
|
|
604
664
|
if (!registerResponse.ok) {
|
|
605
665
|
const error = await registerResponse.json().catch(() => ({}));
|
|
606
|
-
|
|
666
|
+
const errorMessage = error.error || `Registration failed with status ${registerResponse.status}`;
|
|
667
|
+
const requestId = error.request_id;
|
|
668
|
+
const errorCode = error.code;
|
|
669
|
+
let helpText = "";
|
|
670
|
+
if (registerResponse.status === 503) {
|
|
671
|
+
helpText = " The service may be temporarily unavailable. Please try again later.";
|
|
672
|
+
} else if (registerResponse.status === 500) {
|
|
673
|
+
helpText = " This is a server error. Please contact support with the request ID.";
|
|
674
|
+
} else if (errorCode === "MISSING_CHALLENGE" || errorCode === "MISSING_SIGNATURE") {
|
|
675
|
+
helpText = " This may indicate an SDK bug. Please update to the latest version.";
|
|
676
|
+
}
|
|
677
|
+
const fullMessage = requestId ? `${errorMessage} (request_id: ${requestId})${helpText}` : `${errorMessage}${helpText}`;
|
|
678
|
+
throw new MixrPayError(fullMessage);
|
|
607
679
|
}
|
|
608
680
|
const data = await registerResponse.json();
|
|
609
681
|
return {
|
|
@@ -611,6 +683,52 @@ var AgentWallet = class {
|
|
|
611
683
|
depositAddress: data.deposit_address
|
|
612
684
|
};
|
|
613
685
|
}
|
|
686
|
+
/**
|
|
687
|
+
* Check if the MixrPay server is properly configured for agent registration.
|
|
688
|
+
*
|
|
689
|
+
* Use this to diagnose registration issues before attempting to register.
|
|
690
|
+
*
|
|
691
|
+
* @param baseUrl - MixrPay API base URL (default: https://www.mixrpay.com)
|
|
692
|
+
* @returns Server health status including agent registration availability
|
|
693
|
+
*
|
|
694
|
+
* @example
|
|
695
|
+
* ```typescript
|
|
696
|
+
* const status = await AgentWallet.checkServerHealth();
|
|
697
|
+
* if (!status.agentRegistrationAvailable) {
|
|
698
|
+
* console.error('Agent registration is not available:', status);
|
|
699
|
+
* }
|
|
700
|
+
* ```
|
|
701
|
+
*/
|
|
702
|
+
static async checkServerHealth(baseUrl) {
|
|
703
|
+
const url = (baseUrl || DEFAULT_BASE_URL).replace(/\/$/, "");
|
|
704
|
+
try {
|
|
705
|
+
const response = await fetch(`${url}/api/health/ready?details=true`);
|
|
706
|
+
if (!response.ok) {
|
|
707
|
+
return {
|
|
708
|
+
healthy: false,
|
|
709
|
+
database: "unknown",
|
|
710
|
+
agentRegistrationAvailable: false,
|
|
711
|
+
privyConfigured: false,
|
|
712
|
+
error: `Health check failed with status ${response.status}`
|
|
713
|
+
};
|
|
714
|
+
}
|
|
715
|
+
const data = await response.json();
|
|
716
|
+
return {
|
|
717
|
+
healthy: data.status === "ready",
|
|
718
|
+
database: data.database || "unknown",
|
|
719
|
+
agentRegistrationAvailable: data.services?.agentRegistration?.available ?? false,
|
|
720
|
+
privyConfigured: data.services?.privy?.configured ?? false
|
|
721
|
+
};
|
|
722
|
+
} catch (error) {
|
|
723
|
+
return {
|
|
724
|
+
healthy: false,
|
|
725
|
+
database: "unreachable",
|
|
726
|
+
agentRegistrationAvailable: false,
|
|
727
|
+
privyConfigured: false,
|
|
728
|
+
error: error instanceof Error ? error.message : "Failed to reach server"
|
|
729
|
+
};
|
|
730
|
+
}
|
|
731
|
+
}
|
|
614
732
|
/**
|
|
615
733
|
* Get a session key for an already-registered agent.
|
|
616
734
|
*
|
|
@@ -785,6 +903,67 @@ var AgentWallet = class {
|
|
|
785
903
|
}
|
|
786
904
|
return true;
|
|
787
905
|
}
|
|
906
|
+
/**
|
|
907
|
+
* Withdraw USDC from agent's MixrPay wallet to their external wallet.
|
|
908
|
+
*
|
|
909
|
+
* SECURITY: Withdrawals can ONLY go to the agent's own registration wallet
|
|
910
|
+
* (the wallet used during `register()`). This prevents prompt injection
|
|
911
|
+
* attacks where a compromised agent might be tricked into withdrawing
|
|
912
|
+
* to an attacker's address.
|
|
913
|
+
*
|
|
914
|
+
* @param options - Withdrawal options
|
|
915
|
+
* @returns Withdrawal result with transaction hash
|
|
916
|
+
* @throws {MixrPayError} If withdrawal fails
|
|
917
|
+
*
|
|
918
|
+
* @example
|
|
919
|
+
* ```typescript
|
|
920
|
+
* const result = await AgentWallet.withdraw({
|
|
921
|
+
* privateKey: process.env.AGENT_WALLET_KEY as `0x${string}`,
|
|
922
|
+
* amountUsd: 50.00,
|
|
923
|
+
* });
|
|
924
|
+
*
|
|
925
|
+
* console.log(`Withdrew $${result.amountUsd}`);
|
|
926
|
+
* console.log(`Transaction: ${result.txHash}`);
|
|
927
|
+
* console.log(`Remaining balance: $${result.remainingBalanceUsd}`);
|
|
928
|
+
* ```
|
|
929
|
+
*/
|
|
930
|
+
static async withdraw(options) {
|
|
931
|
+
const { privateKey, amountUsd } = options;
|
|
932
|
+
const baseUrl = (options.baseUrl || DEFAULT_BASE_URL).replace(/\/$/, "");
|
|
933
|
+
const account = privateKeyToAccount2(privateKey);
|
|
934
|
+
const walletAddress = account.address;
|
|
935
|
+
const challengeResponse = await fetch(
|
|
936
|
+
`${baseUrl}/api/v1/agent/challenge?wallet=${walletAddress}&action=withdraw`
|
|
937
|
+
);
|
|
938
|
+
if (!challengeResponse.ok) {
|
|
939
|
+
const error = await challengeResponse.json().catch(() => ({}));
|
|
940
|
+
throw new MixrPayError(error.error || `Failed to get challenge: ${challengeResponse.status}`);
|
|
941
|
+
}
|
|
942
|
+
const { challenge, message } = await challengeResponse.json();
|
|
943
|
+
const signature = await signMessage({ message, privateKey });
|
|
944
|
+
const withdrawResponse = await fetch(`${baseUrl}/api/v1/agent/withdraw`, {
|
|
945
|
+
method: "POST",
|
|
946
|
+
headers: { "Content-Type": "application/json" },
|
|
947
|
+
body: JSON.stringify({
|
|
948
|
+
challenge,
|
|
949
|
+
external_wallet: walletAddress,
|
|
950
|
+
signature,
|
|
951
|
+
to_address: walletAddress,
|
|
952
|
+
// Always withdraw to self
|
|
953
|
+
amount_usd: amountUsd
|
|
954
|
+
})
|
|
955
|
+
});
|
|
956
|
+
if (!withdrawResponse.ok) {
|
|
957
|
+
const error = await withdrawResponse.json().catch(() => ({}));
|
|
958
|
+
throw new MixrPayError(error.error || `Withdrawal failed: ${withdrawResponse.status}`);
|
|
959
|
+
}
|
|
960
|
+
const data = await withdrawResponse.json();
|
|
961
|
+
return {
|
|
962
|
+
txHash: data.tx_hash,
|
|
963
|
+
amountUsd: data.amount_usd,
|
|
964
|
+
remainingBalanceUsd: data.remaining_balance_usd
|
|
965
|
+
};
|
|
966
|
+
}
|
|
788
967
|
// ===========================================================================
|
|
789
968
|
// Core Methods
|
|
790
969
|
// ===========================================================================
|
|
@@ -823,6 +1002,8 @@ var AgentWallet = class {
|
|
|
823
1002
|
*/
|
|
824
1003
|
async fetch(url, init) {
|
|
825
1004
|
this.logger.debug(`Fetching ${init?.method || "GET"} ${url}`);
|
|
1005
|
+
const requestId = crypto.randomUUID();
|
|
1006
|
+
const correlationId = this.extractCorrelationId(init?.headers);
|
|
826
1007
|
const controller = new AbortController();
|
|
827
1008
|
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
828
1009
|
try {
|
|
@@ -833,7 +1014,7 @@ var AgentWallet = class {
|
|
|
833
1014
|
this.logger.debug(`Initial response: ${response.status}`);
|
|
834
1015
|
if (response.status === 402) {
|
|
835
1016
|
this.logger.info(`Payment required for ${url}`);
|
|
836
|
-
response = await this.handlePaymentRequired(url, init, response);
|
|
1017
|
+
response = await this.handlePaymentRequired(url, init, response, requestId, correlationId);
|
|
837
1018
|
}
|
|
838
1019
|
return response;
|
|
839
1020
|
} catch (error) {
|
|
@@ -845,10 +1026,27 @@ var AgentWallet = class {
|
|
|
845
1026
|
clearTimeout(timeoutId);
|
|
846
1027
|
}
|
|
847
1028
|
}
|
|
1029
|
+
/**
|
|
1030
|
+
* Extract correlation ID from request headers.
|
|
1031
|
+
*/
|
|
1032
|
+
extractCorrelationId(headers) {
|
|
1033
|
+
if (!headers) return void 0;
|
|
1034
|
+
if (headers instanceof Headers) {
|
|
1035
|
+
return headers.get("X-Correlation-Id") || headers.get("x-correlation-id") || void 0;
|
|
1036
|
+
}
|
|
1037
|
+
if (Array.isArray(headers)) {
|
|
1038
|
+
const entry = headers.find(
|
|
1039
|
+
([key]) => key.toLowerCase() === "x-correlation-id"
|
|
1040
|
+
);
|
|
1041
|
+
return entry ? entry[1] : void 0;
|
|
1042
|
+
}
|
|
1043
|
+
const record = headers;
|
|
1044
|
+
return record["X-Correlation-Id"] || record["x-correlation-id"] || void 0;
|
|
1045
|
+
}
|
|
848
1046
|
/**
|
|
849
1047
|
* Handle a 402 Payment Required response.
|
|
850
1048
|
*/
|
|
851
|
-
async handlePaymentRequired(url, init, response) {
|
|
1049
|
+
async handlePaymentRequired(url, init, response, requestId, correlationId) {
|
|
852
1050
|
let requirements;
|
|
853
1051
|
try {
|
|
854
1052
|
requirements = await parse402Response(response);
|
|
@@ -904,7 +1102,9 @@ var AgentWallet = class {
|
|
|
904
1102
|
txHash: retryResponse.headers.get("X-Payment-TxHash"),
|
|
905
1103
|
timestamp: /* @__PURE__ */ new Date(),
|
|
906
1104
|
description: requirements.description,
|
|
907
|
-
url
|
|
1105
|
+
url,
|
|
1106
|
+
requestId,
|
|
1107
|
+
correlationId
|
|
908
1108
|
};
|
|
909
1109
|
this.payments.push(payment);
|
|
910
1110
|
this.totalSpentUsd += amountUsd;
|
|
@@ -1003,6 +1203,36 @@ var AgentWallet = class {
|
|
|
1003
1203
|
this.logger.debug("Using estimated balance based on tracking");
|
|
1004
1204
|
return Math.max(0, 100 - this.totalSpentUsd);
|
|
1005
1205
|
}
|
|
1206
|
+
/**
|
|
1207
|
+
* Check if the wallet can afford a specific amount.
|
|
1208
|
+
*
|
|
1209
|
+
* This is a convenience method to check balance before making a request
|
|
1210
|
+
* when you know the expected cost.
|
|
1211
|
+
*
|
|
1212
|
+
* @param amountUsd - Amount to check in USD
|
|
1213
|
+
* @returns Object with affordability information
|
|
1214
|
+
*
|
|
1215
|
+
* @example
|
|
1216
|
+
* ```typescript
|
|
1217
|
+
* const check = await wallet.canAfford(5.00);
|
|
1218
|
+
* if (check.canAfford) {
|
|
1219
|
+
* console.log(`Can afford! Will have $${check.remainingAfter.toFixed(2)} left`);
|
|
1220
|
+
* await wallet.fetch(url);
|
|
1221
|
+
* } else {
|
|
1222
|
+
* console.log(`Need $${check.shortfall.toFixed(2)} more`);
|
|
1223
|
+
* }
|
|
1224
|
+
* ```
|
|
1225
|
+
*/
|
|
1226
|
+
async canAfford(amountUsd) {
|
|
1227
|
+
const balance = await this.getBalance();
|
|
1228
|
+
const canAfford = balance >= amountUsd;
|
|
1229
|
+
return {
|
|
1230
|
+
canAfford,
|
|
1231
|
+
balance,
|
|
1232
|
+
shortfall: canAfford ? 0 : amountUsd - balance,
|
|
1233
|
+
remainingAfter: canAfford ? balance - amountUsd : 0
|
|
1234
|
+
};
|
|
1235
|
+
}
|
|
1006
1236
|
/**
|
|
1007
1237
|
* Get information about the session key.
|
|
1008
1238
|
*
|
|
@@ -1143,56 +1373,100 @@ var AgentWallet = class {
|
|
|
1143
1373
|
async runDiagnostics() {
|
|
1144
1374
|
this.logger.info("Running diagnostics...");
|
|
1145
1375
|
const issues = [];
|
|
1376
|
+
const recommendations = [];
|
|
1146
1377
|
const checks = {};
|
|
1378
|
+
let latencyMs;
|
|
1379
|
+
let sessionLimits;
|
|
1147
1380
|
checks.sessionKeyFormat = true;
|
|
1148
1381
|
try {
|
|
1382
|
+
const startTime = Date.now();
|
|
1149
1383
|
const response = await fetch(`${this.baseUrl}/health`, {
|
|
1150
1384
|
method: "GET",
|
|
1151
1385
|
signal: AbortSignal.timeout(5e3)
|
|
1152
1386
|
});
|
|
1387
|
+
latencyMs = Date.now() - startTime;
|
|
1153
1388
|
checks.apiConnectivity = response.ok;
|
|
1154
1389
|
if (!response.ok) {
|
|
1155
1390
|
issues.push(`API server returned ${response.status}. Check baseUrl configuration.`);
|
|
1391
|
+
recommendations.push("Verify the baseUrl configuration points to a valid MixrPay server.");
|
|
1392
|
+
}
|
|
1393
|
+
if (latencyMs > 2e3) {
|
|
1394
|
+
issues.push(`High API latency: ${latencyMs}ms. This may cause timeouts.`);
|
|
1395
|
+
recommendations.push("Consider using a server closer to your region or check network connectivity.");
|
|
1156
1396
|
}
|
|
1157
1397
|
} catch {
|
|
1158
1398
|
checks.apiConnectivity = false;
|
|
1159
1399
|
issues.push("Cannot connect to MixrPay API. Check your network connection and baseUrl.");
|
|
1400
|
+
recommendations.push("Verify network connectivity and that the MixrPay server is running.");
|
|
1160
1401
|
}
|
|
1161
1402
|
try {
|
|
1162
1403
|
const info = await this.getSessionKeyInfo(true);
|
|
1163
1404
|
checks.sessionKeyValid = info.isValid;
|
|
1164
1405
|
if (!info.isValid) {
|
|
1165
1406
|
issues.push("Session key is invalid or has been revoked.");
|
|
1407
|
+
recommendations.push("Request a new session key from the wallet owner or create one at /wallet/sessions.");
|
|
1408
|
+
}
|
|
1409
|
+
const now = /* @__PURE__ */ new Date();
|
|
1410
|
+
let expiresInHours = null;
|
|
1411
|
+
if (info.expiresAt) {
|
|
1412
|
+
expiresInHours = (info.expiresAt.getTime() - now.getTime()) / (1e3 * 60 * 60);
|
|
1413
|
+
if (info.expiresAt < now) {
|
|
1414
|
+
checks.sessionKeyValid = false;
|
|
1415
|
+
issues.push(`Session key expired on ${info.expiresAt.toISOString()}`);
|
|
1416
|
+
recommendations.push("Create a new session key to continue making payments.");
|
|
1417
|
+
} else if (expiresInHours < 24) {
|
|
1418
|
+
issues.push(`Session key expires in ${expiresInHours.toFixed(1)} hours.`);
|
|
1419
|
+
recommendations.push("Consider creating a new session key before the current one expires.");
|
|
1420
|
+
}
|
|
1166
1421
|
}
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1422
|
+
const stats = await this.getSpendingStats();
|
|
1423
|
+
sessionLimits = {
|
|
1424
|
+
remainingDailyUsd: stats.remainingDailyUsd,
|
|
1425
|
+
remainingTotalUsd: stats.remainingTotalUsd,
|
|
1426
|
+
expiresAt: info.expiresAt,
|
|
1427
|
+
expiresInHours
|
|
1428
|
+
};
|
|
1429
|
+
if (stats.remainingDailyUsd !== null && stats.remainingDailyUsd < 1) {
|
|
1430
|
+
issues.push(`Daily limit nearly exhausted: $${stats.remainingDailyUsd.toFixed(2)} remaining.`);
|
|
1431
|
+
recommendations.push("Wait until tomorrow for daily limit to reset, or request a higher daily limit.");
|
|
1432
|
+
}
|
|
1433
|
+
if (stats.remainingTotalUsd !== null && stats.remainingTotalUsd < 1) {
|
|
1434
|
+
issues.push(`Total limit nearly exhausted: $${stats.remainingTotalUsd.toFixed(2)} remaining.`);
|
|
1435
|
+
recommendations.push("Request a new session key with a higher total limit.");
|
|
1170
1436
|
}
|
|
1171
1437
|
} catch {
|
|
1172
1438
|
checks.sessionKeyValid = false;
|
|
1173
1439
|
issues.push("Could not verify session key validity.");
|
|
1440
|
+
recommendations.push("Check network connectivity and try again.");
|
|
1174
1441
|
}
|
|
1442
|
+
let balance = 0;
|
|
1175
1443
|
try {
|
|
1176
|
-
|
|
1444
|
+
balance = await this.getBalance();
|
|
1177
1445
|
checks.hasBalance = balance > 0;
|
|
1178
1446
|
if (balance <= 0) {
|
|
1179
1447
|
issues.push("Wallet has no USDC balance. Top up at your MixrPay server /wallet");
|
|
1448
|
+
recommendations.push("Deposit USDC to your wallet address to enable payments.");
|
|
1180
1449
|
} else if (balance < 1) {
|
|
1181
1450
|
issues.push(`Low balance: $${balance.toFixed(2)}. Consider topping up.`);
|
|
1451
|
+
recommendations.push("Top up your wallet balance to avoid payment failures.");
|
|
1182
1452
|
}
|
|
1183
1453
|
} catch {
|
|
1184
1454
|
checks.hasBalance = false;
|
|
1185
1455
|
issues.push("Could not fetch wallet balance.");
|
|
1456
|
+
recommendations.push("Check network connectivity and try again.");
|
|
1186
1457
|
}
|
|
1187
1458
|
const healthy = issues.length === 0;
|
|
1188
|
-
this.logger.info("Diagnostics complete:", { healthy, issues });
|
|
1459
|
+
this.logger.info("Diagnostics complete:", { healthy, issues, latencyMs });
|
|
1189
1460
|
return {
|
|
1190
1461
|
healthy,
|
|
1191
1462
|
issues,
|
|
1192
1463
|
checks,
|
|
1193
1464
|
sdkVersion: SDK_VERSION,
|
|
1194
1465
|
network: this.getNetwork().name,
|
|
1195
|
-
walletAddress: this.walletAddress
|
|
1466
|
+
walletAddress: this.walletAddress,
|
|
1467
|
+
sessionLimits,
|
|
1468
|
+
latencyMs,
|
|
1469
|
+
recommendations
|
|
1196
1470
|
};
|
|
1197
1471
|
}
|
|
1198
1472
|
/**
|
|
@@ -1601,7 +1875,9 @@ var AgentWallet = class {
|
|
|
1601
1875
|
txHash: response.headers.get("X-Payment-TxHash"),
|
|
1602
1876
|
timestamp: /* @__PURE__ */ new Date(),
|
|
1603
1877
|
description: feature || "API call",
|
|
1604
|
-
url
|
|
1878
|
+
url,
|
|
1879
|
+
requestId: crypto.randomUUID(),
|
|
1880
|
+
correlationId: this.extractCorrelationId(customHeaders)
|
|
1605
1881
|
};
|
|
1606
1882
|
this.payments.push(payment);
|
|
1607
1883
|
this.totalSpentUsd += amountUsd;
|
|
@@ -1800,7 +2076,8 @@ Timestamp: ${timestamp}`;
|
|
|
1800
2076
|
txHash: mixrpay.txHash,
|
|
1801
2077
|
timestamp: /* @__PURE__ */ new Date(),
|
|
1802
2078
|
description: `MCP: ${toolName}`,
|
|
1803
|
-
url: `${this.baseUrl}/api/mcp
|
|
2079
|
+
url: `${this.baseUrl}/api/mcp`,
|
|
2080
|
+
requestId: crypto.randomUUID()
|
|
1804
2081
|
};
|
|
1805
2082
|
this.payments.push(payment);
|
|
1806
2083
|
this.totalSpentUsd += mixrpay.chargedUsd;
|
|
@@ -1917,7 +2194,8 @@ Timestamp: ${timestamp}`;
|
|
|
1917
2194
|
txHash: data.tx_hash,
|
|
1918
2195
|
timestamp: /* @__PURE__ */ new Date(),
|
|
1919
2196
|
description: `Agent run: ${data.run_id}`,
|
|
1920
|
-
url: `${this.baseUrl}/api/v2/agent/run
|
|
2197
|
+
url: `${this.baseUrl}/api/v2/agent/run`,
|
|
2198
|
+
requestId: idempotencyKey || crypto.randomUUID()
|
|
1921
2199
|
};
|
|
1922
2200
|
this.payments.push(payment);
|
|
1923
2201
|
this.totalSpentUsd += data.cost.total_usd;
|
|
@@ -2009,7 +2287,8 @@ Timestamp: ${timestamp}`;
|
|
|
2009
2287
|
txHash: data.tx_hash,
|
|
2010
2288
|
timestamp: /* @__PURE__ */ new Date(),
|
|
2011
2289
|
description: `Agent run: ${data.run_id}`,
|
|
2012
|
-
url: `${this.baseUrl}/api/v2/agent/run
|
|
2290
|
+
url: `${this.baseUrl}/api/v2/agent/run`,
|
|
2291
|
+
requestId: body.idempotency_key || crypto.randomUUID()
|
|
2013
2292
|
};
|
|
2014
2293
|
this.payments.push(payment);
|
|
2015
2294
|
this.totalSpentUsd += data.total_cost_usd;
|
|
@@ -2185,7 +2464,8 @@ Timestamp: ${timestamp}`;
|
|
|
2185
2464
|
txHash: mixrpay.txHash,
|
|
2186
2465
|
timestamp: /* @__PURE__ */ new Date(),
|
|
2187
2466
|
description: `MCP: ${toolName}`,
|
|
2188
|
-
url: `${this.baseUrl}/api/mcp
|
|
2467
|
+
url: `${this.baseUrl}/api/mcp`,
|
|
2468
|
+
requestId: crypto.randomUUID()
|
|
2189
2469
|
};
|
|
2190
2470
|
this.payments.push(payment);
|
|
2191
2471
|
this.totalSpentUsd += mixrpay.chargedUsd;
|
|
@@ -2215,5 +2495,7 @@ export {
|
|
|
2215
2495
|
SessionNotFoundError,
|
|
2216
2496
|
SessionRevokedError,
|
|
2217
2497
|
SpendingLimitExceededError,
|
|
2498
|
+
X402ProtocolError,
|
|
2499
|
+
getErrorMessage,
|
|
2218
2500
|
isMixrPayError
|
|
2219
2501
|
};
|