@mixrpay/agent-sdk 0.2.0 → 0.3.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/dist/index.js CHANGED
@@ -115,17 +115,71 @@ var X402ProtocolError = class extends MixrPayError {
115
115
  this.reason = reason;
116
116
  }
117
117
  };
118
- function isMixrPayError(error) {
119
- return error instanceof MixrPayError;
120
- }
121
- function getErrorMessage(error) {
122
- if (error instanceof MixrPayError) {
123
- return error.message;
118
+ var SessionExpiredError = class extends MixrPayError {
119
+ /** ID of the expired session */
120
+ sessionId;
121
+ /** When the session expired (ISO string or Date) */
122
+ expiredAt;
123
+ constructor(sessionId, expiredAt) {
124
+ super(
125
+ `Session ${sessionId} has expired${expiredAt ? ` at ${expiredAt}` : ""}. A new session will be created automatically on your next request.`,
126
+ "SESSION_EXPIRED"
127
+ );
128
+ this.name = "SessionExpiredError";
129
+ this.sessionId = sessionId;
130
+ this.expiredAt = expiredAt;
131
+ }
132
+ };
133
+ var SessionLimitExceededError = class extends MixrPayError {
134
+ /** ID of the session */
135
+ sessionId;
136
+ /** The session's spending limit in USD */
137
+ limit;
138
+ /** The amount requested in USD */
139
+ requested;
140
+ /** Remaining balance in the session (limit - used) */
141
+ remaining;
142
+ constructor(limit, requested, remaining, sessionId) {
143
+ super(
144
+ `Session spending limit exceeded: limit is $${limit.toFixed(2)}, requested $${requested.toFixed(2)}, remaining $${remaining.toFixed(2)}. Create a new session with a higher limit to continue.`,
145
+ "SESSION_LIMIT_EXCEEDED"
146
+ );
147
+ this.name = "SessionLimitExceededError";
148
+ this.sessionId = sessionId;
149
+ this.limit = limit;
150
+ this.requested = requested;
151
+ this.remaining = remaining;
124
152
  }
125
- if (error instanceof Error) {
126
- return error.message;
153
+ };
154
+ var SessionNotFoundError = class extends MixrPayError {
155
+ /** The session ID that was not found */
156
+ sessionId;
157
+ constructor(sessionId) {
158
+ super(
159
+ `Session ${sessionId} not found. It may have been deleted or never existed. Create a new session with getOrCreateSession().`,
160
+ "SESSION_NOT_FOUND"
161
+ );
162
+ this.name = "SessionNotFoundError";
163
+ this.sessionId = sessionId;
127
164
  }
128
- return String(error);
165
+ };
166
+ var SessionRevokedError = class extends MixrPayError {
167
+ /** The session ID that was revoked */
168
+ sessionId;
169
+ /** Optional reason for revocation */
170
+ reason;
171
+ constructor(sessionId, reason) {
172
+ super(
173
+ `Session ${sessionId} has been revoked${reason ? `: ${reason}` : ""}. Create a new session with getOrCreateSession().`,
174
+ "SESSION_REVOKED"
175
+ );
176
+ this.name = "SessionRevokedError";
177
+ this.sessionId = sessionId;
178
+ this.reason = reason;
179
+ }
180
+ };
181
+ function isMixrPayError(error) {
182
+ return error instanceof MixrPayError;
129
183
  }
130
184
 
131
185
  // src/session-key.ts
@@ -352,21 +406,10 @@ function isPaymentExpired(requirements) {
352
406
  function getAmountUsd(requirements) {
353
407
  return Number(requirements.amount) / 1e6;
354
408
  }
355
- function validatePaymentAmount(amountUsd, maxPaymentUsd) {
356
- if (amountUsd <= 0) {
357
- throw new X402ProtocolError(`Invalid payment amount: $${amountUsd.toFixed(2)}`);
358
- }
359
- if (maxPaymentUsd !== void 0 && amountUsd > maxPaymentUsd) {
360
- throw new X402ProtocolError(
361
- `Payment amount $${amountUsd.toFixed(2)} exceeds client limit $${maxPaymentUsd.toFixed(2)}`
362
- );
363
- }
364
- }
365
409
 
366
410
  // src/agent-wallet.ts
367
- var SDK_VERSION = "0.1.0";
411
+ var SDK_VERSION = "0.3.1";
368
412
  var DEFAULT_BASE_URL = process.env.MIXRPAY_BASE_URL || "https://mixrpay.com";
369
- var DEFAULT_FACILITATOR_URL = "https://x402.org/facilitator";
370
413
  var DEFAULT_TIMEOUT = 3e4;
371
414
  var NETWORKS = {
372
415
  BASE_MAINNET: { chainId: 8453, name: "Base", isTestnet: false },
@@ -1122,6 +1165,63 @@ var AgentWallet = class {
1122
1165
  this.logger.info(`Session ${sessionId} revoked`);
1123
1166
  return true;
1124
1167
  }
1168
+ /**
1169
+ * Get statistics about all session authorizations.
1170
+ *
1171
+ * This provides an overview of active, expired, and revoked sessions,
1172
+ * along with aggregate spending information.
1173
+ *
1174
+ * @returns Session statistics
1175
+ *
1176
+ * @example
1177
+ * ```typescript
1178
+ * const stats = await wallet.getSessionStats();
1179
+ * console.log(`Active sessions: ${stats.activeCount}`);
1180
+ * console.log(`Total authorized: $${stats.totalAuthorizedUsd.toFixed(2)}`);
1181
+ * console.log(`Total remaining: $${stats.totalRemainingUsd.toFixed(2)}`);
1182
+ *
1183
+ * for (const session of stats.activeSessions) {
1184
+ * console.log(`${session.merchantName}: $${session.remainingUsd} remaining`);
1185
+ * }
1186
+ * ```
1187
+ */
1188
+ async getSessionStats() {
1189
+ this.logger.debug("getSessionStats");
1190
+ const sessions = await this.listSessions();
1191
+ const now = /* @__PURE__ */ new Date();
1192
+ const active = [];
1193
+ const expired = [];
1194
+ const revoked = [];
1195
+ for (const session of sessions) {
1196
+ if (session.status === "revoked") {
1197
+ revoked.push(session);
1198
+ } else if (session.status === "expired" || session.expiresAt && session.expiresAt < now) {
1199
+ expired.push(session);
1200
+ } else if (session.status === "active") {
1201
+ active.push(session);
1202
+ }
1203
+ }
1204
+ const totalAuthorizedUsd = active.reduce((sum, s) => sum + s.spendingLimitUsd, 0);
1205
+ const totalSpentUsd = sessions.reduce((sum, s) => sum + s.amountUsedUsd, 0);
1206
+ const totalRemainingUsd = active.reduce((sum, s) => sum + s.remainingLimitUsd, 0);
1207
+ return {
1208
+ activeCount: active.length,
1209
+ expiredCount: expired.length,
1210
+ revokedCount: revoked.length,
1211
+ totalAuthorizedUsd,
1212
+ totalSpentUsd,
1213
+ totalRemainingUsd,
1214
+ activeSessions: active.map((s) => ({
1215
+ id: s.id,
1216
+ merchantName: s.merchantName,
1217
+ merchantPublicKey: s.merchantId,
1218
+ // merchantId is the public key in this context
1219
+ spendingLimitUsd: s.spendingLimitUsd,
1220
+ remainingUsd: s.remainingLimitUsd,
1221
+ expiresAt: s.expiresAt
1222
+ }))
1223
+ };
1224
+ }
1125
1225
  /**
1126
1226
  * Charge against an active session authorization.
1127
1227
  *
@@ -1162,21 +1262,29 @@ var AgentWallet = class {
1162
1262
  });
1163
1263
  if (!response.ok) {
1164
1264
  const error = await response.json().catch(() => ({}));
1265
+ const errorCode = error.error || error.error_code || "";
1165
1266
  if (response.status === 402) {
1166
- if (error.error === "session_limit_exceeded") {
1167
- throw new SpendingLimitExceededError(
1168
- "session",
1169
- error.sessionLimitUsd || error.session_limit_usd || 0,
1170
- amountUsd
1171
- );
1267
+ if (errorCode === "session_limit_exceeded") {
1268
+ const limit = error.sessionLimitUsd || error.session_limit_usd || 0;
1269
+ const remaining = error.remainingUsd || error.remaining_usd || 0;
1270
+ throw new SessionLimitExceededError(limit, amountUsd, remaining, sessionId);
1172
1271
  }
1173
- if (error.error === "insufficient_balance") {
1272
+ if (errorCode === "insufficient_balance") {
1174
1273
  throw new InsufficientBalanceError(
1175
1274
  amountUsd,
1176
1275
  error.availableUsd || error.available_usd || 0
1177
1276
  );
1178
1277
  }
1179
1278
  }
1279
+ if (response.status === 404 || errorCode === "session_not_found") {
1280
+ throw new SessionNotFoundError(sessionId);
1281
+ }
1282
+ if (errorCode === "session_expired") {
1283
+ throw new SessionExpiredError(sessionId, error.expiredAt || error.expires_at);
1284
+ }
1285
+ if (errorCode === "session_revoked") {
1286
+ throw new SessionRevokedError(sessionId, error.reason);
1287
+ }
1180
1288
  throw new MixrPayError(error.message || `Charge failed: ${response.status}`);
1181
1289
  }
1182
1290
  const data = await response.json();
@@ -1271,7 +1379,8 @@ var AgentWallet = class {
1271
1379
  }
1272
1380
  if (response.status === 402) {
1273
1381
  const errorData = await response.json().catch(() => ({}));
1274
- if (errorData.error === "session_expired") {
1382
+ const errorCode = errorData.error || errorData.error_code || "";
1383
+ if (errorCode === "session_expired") {
1275
1384
  this.logger.info("Session expired, creating new one...");
1276
1385
  const newSession = await this.getOrCreateSession({
1277
1386
  merchantPublicKey,
@@ -1286,17 +1395,21 @@ var AgentWallet = class {
1286
1395
  signal: AbortSignal.timeout(this.timeout)
1287
1396
  });
1288
1397
  }
1289
- if (errorData.error === "session_limit_exceeded") {
1290
- throw new SpendingLimitExceededError(
1291
- "session",
1292
- errorData.sessionLimitUsd || 0,
1293
- priceUsd || 0
1294
- );
1398
+ if (errorCode === "session_limit_exceeded") {
1399
+ const limit = errorData.sessionLimitUsd || errorData.session_limit_usd || 0;
1400
+ const remaining = errorData.remainingUsd || errorData.remaining_usd || 0;
1401
+ throw new SessionLimitExceededError(limit, priceUsd || 0, remaining, session.id);
1402
+ }
1403
+ if (errorCode === "session_revoked") {
1404
+ throw new SessionRevokedError(session.id, errorData.reason);
1405
+ }
1406
+ if (errorCode === "session_not_found") {
1407
+ throw new SessionNotFoundError(session.id);
1295
1408
  }
1296
- if (errorData.error === "insufficient_balance") {
1409
+ if (errorCode === "insufficient_balance") {
1297
1410
  throw new InsufficientBalanceError(
1298
1411
  priceUsd || 0,
1299
- errorData.availableUsd || 0
1412
+ errorData.availableUsd || errorData.available_usd || 0
1300
1413
  );
1301
1414
  }
1302
1415
  }
@@ -1323,26 +1436,16 @@ var AgentWallet = class {
1323
1436
  };
1324
1437
  export {
1325
1438
  AgentWallet,
1326
- DEFAULT_BASE_URL,
1327
- DEFAULT_FACILITATOR_URL,
1328
- DEFAULT_TIMEOUT,
1329
1439
  InsufficientBalanceError,
1330
1440
  InvalidSessionKeyError,
1331
1441
  MixrPayError,
1332
- NETWORKS,
1333
1442
  PaymentFailedError,
1334
1443
  SDK_VERSION,
1335
- SessionKey,
1444
+ SessionExpiredError,
1336
1445
  SessionKeyExpiredError,
1446
+ SessionLimitExceededError,
1447
+ SessionNotFoundError,
1448
+ SessionRevokedError,
1337
1449
  SpendingLimitExceededError,
1338
- X402ProtocolError,
1339
- buildTransferAuthorizationData,
1340
- buildXPaymentHeader,
1341
- generateNonce,
1342
- getAmountUsd,
1343
- getErrorMessage,
1344
- isMixrPayError,
1345
- isPaymentExpired,
1346
- parse402Response,
1347
- validatePaymentAmount
1450
+ isMixrPayError
1348
1451
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mixrpay/agent-sdk",
3
- "version": "0.2.0",
3
+ "version": "0.3.1",
4
4
  "description": "MixrPay Agent SDK - Enable AI agents to make x402 payments with session keys",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",