@mixrpay/agent-sdk 0.8.8 → 0.9.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 CHANGED
@@ -107,6 +107,9 @@ await wallet.fetch(url, options);
107
107
  // Get wallet balance
108
108
  const balance = await wallet.getBalance();
109
109
 
110
+ // Execute on-chain transactions (bridges, swaps, DeFi) from human's wallet
111
+ await wallet.executeTransaction({ to, data, estimatedCostUsd });
112
+
110
113
  // Pre-flight balance check
111
114
  const check = await wallet.canAfford(0.50);
112
115
  if (check.canAfford) { /* proceed */ }
@@ -116,6 +119,20 @@ const diag = await wallet.runDiagnostics();
116
119
  console.log(diag.recommendations);
117
120
  ```
118
121
 
122
+ ## Execute On-Chain Transactions
123
+
124
+ Agents can execute DeFi transactions (bridges, swaps) from the human's wallet, bounded by session key budget:
125
+
126
+ ```typescript
127
+ const result = await wallet.executeTransaction({
128
+ to: '0x...contractAddress',
129
+ data: '0x...calldata',
130
+ estimatedCostUsd: 25.0,
131
+ description: 'Bridge USDC via deBridge',
132
+ });
133
+ console.log(`TX: ${result.txHash}`);
134
+ ```
135
+
119
136
  ## Configuration
120
137
 
121
138
  ```typescript
package/dist/index.cjs CHANGED
@@ -1,46 +1,8 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
1
+ 'use strict';
19
2
 
20
- // src/index.ts
21
- var index_exports = {};
22
- __export(index_exports, {
23
- AgentWallet: () => AgentWallet,
24
- InsufficientBalanceError: () => InsufficientBalanceError,
25
- InvalidSessionKeyError: () => InvalidSessionKeyError,
26
- MerchantNotAllowedError: () => MerchantNotAllowedError,
27
- MixrPayError: () => MixrPayError,
28
- PaymentFailedError: () => PaymentFailedError,
29
- SDK_VERSION: () => SDK_VERSION,
30
- SessionExpiredError: () => SessionExpiredError,
31
- SessionKeyExpiredError: () => SessionKeyExpiredError,
32
- SessionLimitExceededError: () => SessionLimitExceededError,
33
- SessionNotFoundError: () => SessionNotFoundError,
34
- SessionRevokedError: () => SessionRevokedError,
35
- SpendingLimitExceededError: () => SpendingLimitExceededError,
36
- X402ProtocolError: () => X402ProtocolError,
37
- getErrorMessage: () => getErrorMessage,
38
- isMixrPayError: () => isMixrPayError
39
- });
40
- module.exports = __toCommonJS(index_exports);
3
+ var accounts = require('viem/accounts');
41
4
 
42
5
  // src/session-key.ts
43
- var import_accounts = require("viem/accounts");
44
6
 
45
7
  // src/errors.ts
46
8
  var MixrPayError = class extends Error {
@@ -324,7 +286,7 @@ var SessionKey = class _SessionKey {
324
286
  isTest;
325
287
  constructor(privateKey, isTest) {
326
288
  this.privateKey = privateKey;
327
- this.account = (0, import_accounts.privateKeyToAccount)(privateKey);
289
+ this.account = accounts.privateKeyToAccount(privateKey);
328
290
  this.address = this.account.address;
329
291
  this.isTest = isTest;
330
292
  }
@@ -374,7 +336,7 @@ var SessionKey = class _SessionKey {
374
336
  * @returns Hex-encoded signature
375
337
  */
376
338
  async signTransferAuthorization(domain, message) {
377
- return (0, import_accounts.signTypedData)({
339
+ return accounts.signTypedData({
378
340
  privateKey: this.privateKey,
379
341
  domain,
380
342
  types: TRANSFER_WITH_AUTHORIZATION_TYPES,
@@ -389,7 +351,7 @@ var SessionKey = class _SessionKey {
389
351
  * @returns Hex-encoded signature
390
352
  */
391
353
  async signMessage(message) {
392
- return (0, import_accounts.signMessage)({
354
+ return accounts.signMessage({
393
355
  privateKey: this.privateKey,
394
356
  message
395
357
  });
@@ -440,9 +402,6 @@ async function createSessionAuthPayload(sessionKey) {
440
402
  };
441
403
  }
442
404
 
443
- // src/agent-wallet.ts
444
- var import_accounts2 = require("viem/accounts");
445
-
446
405
  // src/x402.ts
447
406
  async function parse402Response(response) {
448
407
  let paymentData = null;
@@ -804,7 +763,7 @@ var AgentWallet = class {
804
763
  /**
805
764
  * Register a new agent with MixrPay.
806
765
  *
807
- * This creates a Privy-managed embedded wallet for the agent's payments.
766
+ * This creates a platform-managed embedded wallet for the agent's payments.
808
767
  * The agent proves ownership of their external wallet by signing a challenge.
809
768
  *
810
769
  * @param options - Registration options including the private key
@@ -824,7 +783,7 @@ var AgentWallet = class {
824
783
  static async register(options) {
825
784
  const { privateKey, name } = options;
826
785
  const baseUrl = (options.baseUrl || DEFAULT_BASE_URL).replace(/\/$/, "");
827
- const account = (0, import_accounts2.privateKeyToAccount)(privateKey);
786
+ const account = accounts.privateKeyToAccount(privateKey);
828
787
  const walletAddress = account.address;
829
788
  const challengeResponse = await fetch(
830
789
  `${baseUrl}/api/v1/agent/challenge?wallet=${walletAddress}&action=register`
@@ -834,7 +793,7 @@ var AgentWallet = class {
834
793
  throw new MixrPayError(error.error || `Failed to get challenge: ${challengeResponse.status}`);
835
794
  }
836
795
  const { challenge, message } = await challengeResponse.json();
837
- const signature = await (0, import_accounts2.signMessage)({ message, privateKey });
796
+ const signature = await accounts.signMessage({ message, privateKey });
838
797
  const registerResponse = await fetch(`${baseUrl}/api/v1/agent/register`, {
839
798
  method: "POST",
840
799
  headers: { "Content-Type": "application/json" },
@@ -892,7 +851,7 @@ var AgentWallet = class {
892
851
  healthy: false,
893
852
  database: "unknown",
894
853
  agentRegistrationAvailable: false,
895
- privyConfigured: false,
854
+ walletServiceConfigured: false,
896
855
  error: `Health check failed with status ${response.status}`
897
856
  };
898
857
  }
@@ -901,14 +860,14 @@ var AgentWallet = class {
901
860
  healthy: data.status === "ready",
902
861
  database: data.database || "unknown",
903
862
  agentRegistrationAvailable: data.services?.agentRegistration?.available ?? false,
904
- privyConfigured: data.services?.privy?.configured ?? false
863
+ walletServiceConfigured: data.services?.wallet?.configured ?? data.services?.privy?.configured ?? false
905
864
  };
906
865
  } catch (error) {
907
866
  return {
908
867
  healthy: false,
909
868
  database: "unreachable",
910
869
  agentRegistrationAvailable: false,
911
- privyConfigured: false,
870
+ walletServiceConfigured: false,
912
871
  error: error instanceof Error ? error.message : "Failed to reach server"
913
872
  };
914
873
  }
@@ -941,7 +900,7 @@ var AgentWallet = class {
941
900
  static async getSessionKey(options) {
942
901
  const { privateKey, spendingLimitUsd, maxPerTxUsd, maxDailyUsd, durationDays } = options;
943
902
  const baseUrl = (options.baseUrl || DEFAULT_BASE_URL).replace(/\/$/, "");
944
- const account = (0, import_accounts2.privateKeyToAccount)(privateKey);
903
+ const account = accounts.privateKeyToAccount(privateKey);
945
904
  const walletAddress = account.address;
946
905
  const challengeResponse = await fetch(
947
906
  `${baseUrl}/api/v1/agent/challenge?wallet=${walletAddress}&action=session-key`
@@ -951,7 +910,7 @@ var AgentWallet = class {
951
910
  throw new MixrPayError(error.error || `Failed to get challenge: ${challengeResponse.status}`);
952
911
  }
953
912
  const { challenge, message } = await challengeResponse.json();
954
- const signature = await (0, import_accounts2.signMessage)({ message, privateKey });
913
+ const signature = await accounts.signMessage({ message, privateKey });
955
914
  const sessionKeyResponse = await fetch(`${baseUrl}/api/v1/agent/session-key`, {
956
915
  method: "POST",
957
916
  headers: { "Content-Type": "application/json" },
@@ -1004,7 +963,7 @@ var AgentWallet = class {
1004
963
  static async getStatus(options) {
1005
964
  const { privateKey } = options;
1006
965
  const baseUrl = (options.baseUrl || DEFAULT_BASE_URL).replace(/\/$/, "");
1007
- const account = (0, import_accounts2.privateKeyToAccount)(privateKey);
966
+ const account = accounts.privateKeyToAccount(privateKey);
1008
967
  const walletAddress = account.address;
1009
968
  const challengeResponse = await fetch(
1010
969
  `${baseUrl}/api/v1/agent/challenge?wallet=${walletAddress}&action=status`
@@ -1014,7 +973,7 @@ var AgentWallet = class {
1014
973
  throw new MixrPayError(error.error || `Failed to get challenge: ${challengeResponse.status}`);
1015
974
  }
1016
975
  const { challenge, message } = await challengeResponse.json();
1017
- const signature = await (0, import_accounts2.signMessage)({ message, privateKey });
976
+ const signature = await accounts.signMessage({ message, privateKey });
1018
977
  const statusResponse = await fetch(
1019
978
  `${baseUrl}/api/v1/agent/status?challenge=${challenge}&external_wallet=${walletAddress}&signature=${encodeURIComponent(signature)}`
1020
979
  );
@@ -1060,7 +1019,7 @@ var AgentWallet = class {
1060
1019
  static async revokeSessionKey(options) {
1061
1020
  const { privateKey, sessionKeyId } = options;
1062
1021
  const baseUrl = (options.baseUrl || DEFAULT_BASE_URL).replace(/\/$/, "");
1063
- const account = (0, import_accounts2.privateKeyToAccount)(privateKey);
1022
+ const account = accounts.privateKeyToAccount(privateKey);
1064
1023
  const walletAddress = account.address;
1065
1024
  const challengeResponse = await fetch(
1066
1025
  `${baseUrl}/api/v1/agent/challenge?wallet=${walletAddress}&action=revoke`
@@ -1070,7 +1029,7 @@ var AgentWallet = class {
1070
1029
  throw new MixrPayError(error.error || `Failed to get challenge: ${challengeResponse.status}`);
1071
1030
  }
1072
1031
  const { challenge, message } = await challengeResponse.json();
1073
- const signature = await (0, import_accounts2.signMessage)({ message, privateKey });
1032
+ const signature = await accounts.signMessage({ message, privateKey });
1074
1033
  const revokeResponse = await fetch(`${baseUrl}/api/v1/agent/session-key/revoke`, {
1075
1034
  method: "POST",
1076
1035
  headers: { "Content-Type": "application/json" },
@@ -1114,7 +1073,7 @@ var AgentWallet = class {
1114
1073
  static async withdraw(options) {
1115
1074
  const { privateKey, amountUsd } = options;
1116
1075
  const baseUrl = (options.baseUrl || DEFAULT_BASE_URL).replace(/\/$/, "");
1117
- const account = (0, import_accounts2.privateKeyToAccount)(privateKey);
1076
+ const account = accounts.privateKeyToAccount(privateKey);
1118
1077
  const walletAddress = account.address;
1119
1078
  const challengeResponse = await fetch(
1120
1079
  `${baseUrl}/api/v1/agent/challenge?wallet=${walletAddress}&action=withdraw`
@@ -1124,7 +1083,7 @@ var AgentWallet = class {
1124
1083
  throw new MixrPayError(error.error || `Failed to get challenge: ${challengeResponse.status}`);
1125
1084
  }
1126
1085
  const { challenge, message } = await challengeResponse.json();
1127
- const signature = await (0, import_accounts2.signMessage)({ message, privateKey });
1086
+ const signature = await accounts.signMessage({ message, privateKey });
1128
1087
  const withdrawResponse = await fetch(`${baseUrl}/api/v1/agent/withdraw`, {
1129
1088
  method: "POST",
1130
1089
  headers: { "Content-Type": "application/json" },
@@ -1180,7 +1139,7 @@ var AgentWallet = class {
1180
1139
  static async claimInvite(options) {
1181
1140
  const { inviteCode, privateKey } = options;
1182
1141
  const baseUrl = (options.baseUrl || DEFAULT_BASE_URL).replace(/\/$/, "");
1183
- const account = (0, import_accounts2.privateKeyToAccount)(privateKey);
1142
+ const account = accounts.privateKeyToAccount(privateKey);
1184
1143
  const walletAddress = account.address;
1185
1144
  const challengeResponse = await fetch(
1186
1145
  `${baseUrl}/api/v1/agent/challenge?wallet=${walletAddress}&action=claim-invite`
@@ -1190,7 +1149,7 @@ var AgentWallet = class {
1190
1149
  throw new MixrPayError(error.error || `Failed to get challenge: ${challengeResponse.status}`);
1191
1150
  }
1192
1151
  const { challenge, message } = await challengeResponse.json();
1193
- const signature = await (0, import_accounts2.signMessage)({ message, privateKey });
1152
+ const signature = await accounts.signMessage({ message, privateKey });
1194
1153
  const claimResponse = await fetch(`${baseUrl}/api/v1/agent/claim-invite`, {
1195
1154
  method: "POST",
1196
1155
  headers: { "Content-Type": "application/json" },
@@ -1240,7 +1199,7 @@ var AgentWallet = class {
1240
1199
  * Spawn a child invite for sub-agents.
1241
1200
  *
1242
1201
  * Allows an agent to create an invite code for a sub-agent with a portion
1243
- * of their remaining budget (max 20%). The child inherits merchant restrictions
1202
+ * of their remaining budget. The child inherits merchant restrictions
1244
1203
  * and cannot outlive the parent session.
1245
1204
  *
1246
1205
  * @param options - Spawn options
@@ -1254,7 +1213,7 @@ var AgentWallet = class {
1254
1213
  *
1255
1214
  * // Spawn a child invite for a sub-agent
1256
1215
  * const childInvite = await wallet.spawnChildInvite({
1257
- * budgetUsd: 10.00, // Max 20% of available budget
1216
+ * budgetUsd: 10.00,
1258
1217
  * name: 'Research Sub-Agent',
1259
1218
  * allowedMerchants: ['firecrawl.dev'], // Must be subset of parent
1260
1219
  * expiresInDays: 7, // Will be capped to parent's expiry
@@ -1269,7 +1228,7 @@ var AgentWallet = class {
1269
1228
  const timestamp = Date.now();
1270
1229
  const nonce = crypto.randomUUID();
1271
1230
  const message = `spawn:${timestamp}:${nonce}`;
1272
- const signature = await (0, import_accounts2.signMessage)({
1231
+ const signature = await accounts.signMessage({
1273
1232
  message,
1274
1233
  privateKey: this.sessionKey.rawPrivateKey
1275
1234
  });
@@ -1310,8 +1269,7 @@ var AgentWallet = class {
1310
1269
  /**
1311
1270
  * Get available budget information for spawning.
1312
1271
  *
1313
- * Returns the current budget status including how much can be spawned
1314
- * to child agents (20% of available).
1272
+ * Returns the current budget status including spawn availability.
1315
1273
  *
1316
1274
  * @returns Budget information
1317
1275
  *
@@ -2723,6 +2681,317 @@ Timestamp: ${timestamp}`;
2723
2681
  return this.parseJitInstance(data.instance);
2724
2682
  }
2725
2683
  // ===========================================================================
2684
+ // Transaction Execution
2685
+ // ===========================================================================
2686
+ /**
2687
+ * Execute an on-chain transaction from the human's wallet.
2688
+ *
2689
+ * Submits arbitrary calldata to any contract, bounded by the session key's
2690
+ * budget limits (max_total, max_per_tx, max_daily). The platform validates
2691
+ * the budget, executes the transaction, and records a charge.
2692
+ *
2693
+ * @param params - Transaction parameters
2694
+ * @returns Transaction result with hash and remaining budget
2695
+ * @throws {MixrPayError} If budget exceeded, tx reverted, or auth fails
2696
+ *
2697
+ * @example
2698
+ * ```typescript
2699
+ * // Bridge USDC via deBridge
2700
+ * const quote = await deBridgeMcp.create_tx({ ... });
2701
+ * const result = await wallet.executeTransaction({
2702
+ * to: quote.contractAddress,
2703
+ * data: quote.calldata,
2704
+ * estimatedCostUsd: 25.0,
2705
+ * description: 'Bridge 25 USDC Base -> Avalanche via deBridge',
2706
+ * });
2707
+ * console.log('TX:', result.txHash);
2708
+ * console.log('Budget remaining:', result.remainingBudgetUsd);
2709
+ * ```
2710
+ */
2711
+ async executeTransaction(params) {
2712
+ this.logger.debug("executeTransaction", { to: params.to, estimatedCostUsd: params.estimatedCostUsd });
2713
+ const authHeaders = await this.getSessionAuthHeaders();
2714
+ const response = await fetch(`${this.baseUrl}/api/v2/tx/execute`, {
2715
+ method: "POST",
2716
+ headers: {
2717
+ "Content-Type": "application/json",
2718
+ ...authHeaders
2719
+ },
2720
+ body: JSON.stringify({
2721
+ to: params.to,
2722
+ data: params.data,
2723
+ value: params.value?.toString() ?? "0",
2724
+ chain_id: params.chainId,
2725
+ estimated_cost_usd: params.estimatedCostUsd,
2726
+ description: params.description,
2727
+ idempotency_key: params.idempotencyKey
2728
+ })
2729
+ });
2730
+ const result = await response.json().catch(() => ({}));
2731
+ if (!response.ok) {
2732
+ const errorCode = result.error_code || "TX_FAILED";
2733
+ const errorMessage = result.error || `Transaction execution failed: ${response.status}`;
2734
+ if (errorCode === "BUDGET_EXCEEDED") {
2735
+ throw new MixrPayError(errorMessage, "SPENDING_LIMIT_EXCEEDED");
2736
+ }
2737
+ throw new MixrPayError(errorMessage, errorCode);
2738
+ }
2739
+ this.logger.info("Transaction executed", {
2740
+ txHash: result.tx_hash,
2741
+ estimatedCostUsd: params.estimatedCostUsd,
2742
+ remainingBudgetUsd: result.remaining_budget_usd
2743
+ });
2744
+ return {
2745
+ success: true,
2746
+ txHash: result.tx_hash,
2747
+ chargeId: result.charge_id,
2748
+ estimatedCostUsd: result.estimated_cost_usd,
2749
+ remainingBudgetUsd: result.remaining_budget_usd
2750
+ };
2751
+ }
2752
+ // ===========================================================================
2753
+ // Skills Methods
2754
+ // ===========================================================================
2755
+ /**
2756
+ * Use a configured skill by deploying a JIT MCP server with your saved API keys.
2757
+ *
2758
+ * Skills are configured on the MixrPay dashboard with your API keys stored securely.
2759
+ * When you call useSkill(), MixrPay deploys an ephemeral MCP server with your keys
2760
+ * injected server-side - your keys are never exposed to the agent.
2761
+ *
2762
+ * @param skillId - The skill ID (e.g., 'github', 'notion', 'spotify')
2763
+ * @param options - Optional configuration
2764
+ * @returns Skill endpoint and available tools
2765
+ *
2766
+ * @example
2767
+ * ```typescript
2768
+ * // Use the GitHub skill
2769
+ * const github = await wallet.useSkill('github');
2770
+ *
2771
+ * console.log('Endpoint:', github.endpoint);
2772
+ * console.log('Tools:', github.tools);
2773
+ * console.log('Expires:', github.expiresAt);
2774
+ *
2775
+ * // Connect to the MCP endpoint and call tools
2776
+ * // The exact method depends on your MCP client
2777
+ * ```
2778
+ *
2779
+ * @example
2780
+ * ```typescript
2781
+ * // Use Notion with custom TTL
2782
+ * const notion = await wallet.useSkill('notion', { ttlHours: 48 });
2783
+ * ```
2784
+ *
2785
+ * @throws {MixrPayError} If skill is not configured or deployment fails
2786
+ */
2787
+ async useSkill(skillId, options) {
2788
+ this.logger.debug("useSkill", { skillId, options });
2789
+ const authHeaders = await this.getSessionAuthHeaders();
2790
+ const response = await fetch(`${this.baseUrl}/api/v2/skills/${skillId}/use`, {
2791
+ method: "POST",
2792
+ headers: {
2793
+ "Content-Type": "application/json",
2794
+ ...authHeaders
2795
+ },
2796
+ body: JSON.stringify({
2797
+ ttl_hours: options?.ttlHours || 24
2798
+ })
2799
+ });
2800
+ if (!response.ok) {
2801
+ const error = await response.json().catch(() => ({}));
2802
+ if (error.configure_url) {
2803
+ throw new MixrPayError(
2804
+ `${error.error || "Skill not configured"}. Configure at: ${this.baseUrl}${error.configure_url}`,
2805
+ "SKILL_NOT_CONFIGURED"
2806
+ );
2807
+ }
2808
+ throw new MixrPayError(error.error || `Failed to use skill: ${response.status}`);
2809
+ }
2810
+ const data = await response.json();
2811
+ return {
2812
+ skillId: data.skill_id,
2813
+ endpoint: data.endpoint,
2814
+ tools: data.tools || [],
2815
+ expiresAt: new Date(data.expires_at),
2816
+ instanceId: data.instance_id
2817
+ };
2818
+ }
2819
+ /**
2820
+ * List all available skills and their configuration status.
2821
+ *
2822
+ * @returns Array of skills with status
2823
+ *
2824
+ * @example
2825
+ * ```typescript
2826
+ * const skills = await wallet.listSkills();
2827
+ *
2828
+ * // Find configured skills
2829
+ * const configured = skills.filter(s => s.status === 'configured');
2830
+ * console.log(`${configured.length} skills ready to use`);
2831
+ *
2832
+ * // Find skills that need configuration
2833
+ * const needsConfig = skills.filter(s => s.status === 'not_configured' && s.envVars.length > 0);
2834
+ * for (const skill of needsConfig) {
2835
+ * console.log(`${skill.name} needs: ${skill.envVars.map(v => v.label).join(', ')}`);
2836
+ * }
2837
+ * ```
2838
+ */
2839
+ async listSkills() {
2840
+ this.logger.debug("listSkills");
2841
+ const authHeaders = await this.getSessionAuthHeaders();
2842
+ const response = await fetch(`${this.baseUrl}/api/v2/skills`, {
2843
+ headers: authHeaders
2844
+ });
2845
+ if (!response.ok) {
2846
+ const error = await response.json().catch(() => ({}));
2847
+ throw new MixrPayError(error.error || `Failed to list skills: ${response.status}`);
2848
+ }
2849
+ const data = await response.json();
2850
+ return data.skills || [];
2851
+ }
2852
+ /**
2853
+ * Get apps connected via Composio (Gmail, Slack, GitHub, etc.).
2854
+ *
2855
+ * Use this to discover which apps the owner has connected before
2856
+ * attempting to use them via `wallet.useSkill('composio')`.
2857
+ *
2858
+ * @returns Object with connected app names and connection details
2859
+ *
2860
+ * @example
2861
+ * ```typescript
2862
+ * const apps = await wallet.getConnectedApps();
2863
+ *
2864
+ * if (apps.connected.length === 0) {
2865
+ * console.log('No apps connected. Ask your owner to connect apps at the dashboard.');
2866
+ * } else {
2867
+ * console.log('Connected apps:', apps.connected.join(', '));
2868
+ *
2869
+ * if (apps.connected.includes('gmail')) {
2870
+ * // Safe to use Composio for Gmail
2871
+ * const { endpoint, tools } = await wallet.useSkill('composio');
2872
+ * // tools will include 'gmail_read_emails', 'gmail_send_email', etc.
2873
+ * }
2874
+ * }
2875
+ * ```
2876
+ */
2877
+ async getConnectedApps() {
2878
+ this.logger.debug("getConnectedApps");
2879
+ const authHeaders = await this.getSessionAuthHeaders();
2880
+ const response = await fetch(`${this.baseUrl}/api/v2/skills/composio/connections`, {
2881
+ headers: authHeaders
2882
+ });
2883
+ if (!response.ok) {
2884
+ const error = await response.json().catch(() => ({}));
2885
+ throw new MixrPayError(
2886
+ error.error || `Failed to get connected apps: ${response.status}`,
2887
+ "CONNECTED_APPS_FAILED"
2888
+ );
2889
+ }
2890
+ const data = await response.json();
2891
+ const connectedAppNames = (data.connections || []).filter((c) => c.status === "connected").map((c) => c.app.toLowerCase());
2892
+ return {
2893
+ connected: connectedAppNames,
2894
+ connections: data.connections || [],
2895
+ oauthConnections: data.oauth_connections || [],
2896
+ apiKeyConnections: data.api_key_connections || []
2897
+ };
2898
+ }
2899
+ /**
2900
+ * Get configuration status for a specific skill.
2901
+ *
2902
+ * @param skillId - The skill ID
2903
+ * @returns Skill configuration status
2904
+ *
2905
+ * @example
2906
+ * ```typescript
2907
+ * const status = await wallet.getSkillStatus('github');
2908
+ *
2909
+ * if (status.status === 'configured') {
2910
+ * console.log('GitHub is ready!');
2911
+ * console.log('Configured vars:', status.configuredVars);
2912
+ * } else {
2913
+ * console.log('Please configure GitHub at the MixrPay dashboard');
2914
+ * }
2915
+ * ```
2916
+ */
2917
+ async getSkillStatus(skillId) {
2918
+ this.logger.debug("getSkillStatus", { skillId });
2919
+ const authHeaders = await this.getSessionAuthHeaders();
2920
+ const response = await fetch(`${this.baseUrl}/api/v2/skills/${skillId}/configure`, {
2921
+ headers: authHeaders
2922
+ });
2923
+ if (!response.ok) {
2924
+ const error = await response.json().catch(() => ({}));
2925
+ throw new MixrPayError(error.error || `Failed to get skill status: ${response.status}`);
2926
+ }
2927
+ const data = await response.json();
2928
+ return {
2929
+ skillId: data.skill_id,
2930
+ status: data.status,
2931
+ configuredVars: data.configured_vars || [],
2932
+ lastUsedAt: data.last_used_at ? new Date(data.last_used_at) : void 0,
2933
+ errorMessage: data.error_message
2934
+ };
2935
+ }
2936
+ /**
2937
+ * Configure a skill with API keys.
2938
+ *
2939
+ * This allows agents to save API keys received via chat to the MixrPay platform.
2940
+ * Keys are encrypted at rest and will be available for use on subsequent deploy/redeploy.
2941
+ *
2942
+ * @param skillId - The skill ID (e.g., 'web-search', 'github', 'notion') or custom skill with 'custom-' prefix
2943
+ * @param envVars - Environment variables with API keys (e.g., { BRAVE_API_KEY: 'xxx' })
2944
+ * @returns Configuration result with list of configured variables
2945
+ *
2946
+ * @example Predefined skill
2947
+ * ```typescript
2948
+ * // User provides API key in chat, agent saves it
2949
+ * const result = await wallet.configureSkill('web-search', {
2950
+ * BRAVE_API_KEY: 'BSA_abc123xyz',
2951
+ * });
2952
+ *
2953
+ * console.log('Configured:', result.configuredVars);
2954
+ * // After next redeploy, the skill will be enabled with this key
2955
+ * ```
2956
+ *
2957
+ * @example Custom API key
2958
+ * ```typescript
2959
+ * // For APIs not in predefined skills, use custom- prefix
2960
+ * // User: "Here's my Polymarket API key: pk_abc123"
2961
+ * const result = await wallet.configureSkill('custom-polymarket', {
2962
+ * POLYMARKET_API_KEY: 'pk_abc123',
2963
+ * });
2964
+ *
2965
+ * // The key is now available in the agent's environment
2966
+ * // Access via: process.env.POLYMARKET_API_KEY
2967
+ * ```
2968
+ */
2969
+ async configureSkill(skillId, envVars) {
2970
+ this.logger.debug("configureSkill", { skillId, varNames: Object.keys(envVars) });
2971
+ const authHeaders = await this.getSessionAuthHeaders();
2972
+ const response = await fetch(`${this.baseUrl}/api/v2/skills/${skillId}/configure`, {
2973
+ method: "POST",
2974
+ headers: {
2975
+ "Content-Type": "application/json",
2976
+ ...authHeaders
2977
+ },
2978
+ body: JSON.stringify({ env_vars: envVars })
2979
+ });
2980
+ if (!response.ok) {
2981
+ const error = await response.json().catch(() => ({}));
2982
+ throw new MixrPayError(
2983
+ error.error || `Failed to configure skill: ${response.status}`,
2984
+ error.error_code
2985
+ );
2986
+ }
2987
+ const data = await response.json();
2988
+ return {
2989
+ success: true,
2990
+ skillId: data.skill_id,
2991
+ configuredVars: data.configured_vars || []
2992
+ };
2993
+ }
2994
+ // ===========================================================================
2726
2995
  // Glama MCP Directory Methods
2727
2996
  // ===========================================================================
2728
2997
  /**
@@ -4362,11 +4631,11 @@ Timestamp: ${timestamp}`;
4362
4631
  ...init.headers
4363
4632
  };
4364
4633
  if (this.sessionKey) {
4365
- const account = (0, import_accounts2.privateKeyToAccount)(this.sessionKey.rawPrivateKey);
4634
+ const account = accounts.privateKeyToAccount(this.sessionKey.rawPrivateKey);
4366
4635
  const address = account.address.toLowerCase();
4367
4636
  const timestamp = Date.now();
4368
4637
  const message = `MixrPay:${timestamp}:${address}`;
4369
- const signature = await (0, import_accounts2.signMessage)({
4638
+ const signature = await accounts.signMessage({
4370
4639
  message,
4371
4640
  privateKey: this.sessionKey.rawPrivateKey
4372
4641
  });
@@ -4382,22 +4651,20 @@ Timestamp: ${timestamp}`;
4382
4651
  });
4383
4652
  }
4384
4653
  };
4385
- // Annotate the CommonJS export names for ESM import in node:
4386
- 0 && (module.exports = {
4387
- AgentWallet,
4388
- InsufficientBalanceError,
4389
- InvalidSessionKeyError,
4390
- MerchantNotAllowedError,
4391
- MixrPayError,
4392
- PaymentFailedError,
4393
- SDK_VERSION,
4394
- SessionExpiredError,
4395
- SessionKeyExpiredError,
4396
- SessionLimitExceededError,
4397
- SessionNotFoundError,
4398
- SessionRevokedError,
4399
- SpendingLimitExceededError,
4400
- X402ProtocolError,
4401
- getErrorMessage,
4402
- isMixrPayError
4403
- });
4654
+
4655
+ exports.AgentWallet = AgentWallet;
4656
+ exports.InsufficientBalanceError = InsufficientBalanceError;
4657
+ exports.InvalidSessionKeyError = InvalidSessionKeyError;
4658
+ exports.MerchantNotAllowedError = MerchantNotAllowedError;
4659
+ exports.MixrPayError = MixrPayError;
4660
+ exports.PaymentFailedError = PaymentFailedError;
4661
+ exports.SDK_VERSION = SDK_VERSION;
4662
+ exports.SessionExpiredError = SessionExpiredError;
4663
+ exports.SessionKeyExpiredError = SessionKeyExpiredError;
4664
+ exports.SessionLimitExceededError = SessionLimitExceededError;
4665
+ exports.SessionNotFoundError = SessionNotFoundError;
4666
+ exports.SessionRevokedError = SessionRevokedError;
4667
+ exports.SpendingLimitExceededError = SpendingLimitExceededError;
4668
+ exports.X402ProtocolError = X402ProtocolError;
4669
+ exports.getErrorMessage = getErrorMessage;
4670
+ exports.isMixrPayError = isMixrPayError;