@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.

Potentially problematic release.


This version of @mixrpay/agent-sdk might be problematic. Click here for more details.

package/dist/index.js CHANGED
@@ -1,9 +1,6 @@
1
+ import { privateKeyToAccount, signMessage, signTypedData } from 'viem/accounts';
2
+
1
3
  // src/session-key.ts
2
- import {
3
- privateKeyToAccount,
4
- signTypedData,
5
- signMessage as viemSignMessage
6
- } from "viem/accounts";
7
4
 
8
5
  // src/errors.ts
9
6
  var MixrPayError = class extends Error {
@@ -352,7 +349,7 @@ var SessionKey = class _SessionKey {
352
349
  * @returns Hex-encoded signature
353
350
  */
354
351
  async signMessage(message) {
355
- return viemSignMessage({
352
+ return signMessage({
356
353
  privateKey: this.privateKey,
357
354
  message
358
355
  });
@@ -403,9 +400,6 @@ async function createSessionAuthPayload(sessionKey) {
403
400
  };
404
401
  }
405
402
 
406
- // src/agent-wallet.ts
407
- import { privateKeyToAccount as privateKeyToAccount2, signMessage } from "viem/accounts";
408
-
409
403
  // src/x402.ts
410
404
  async function parse402Response(response) {
411
405
  let paymentData = null;
@@ -767,7 +761,7 @@ var AgentWallet = class {
767
761
  /**
768
762
  * Register a new agent with MixrPay.
769
763
  *
770
- * This creates a Privy-managed embedded wallet for the agent's payments.
764
+ * This creates a platform-managed embedded wallet for the agent's payments.
771
765
  * The agent proves ownership of their external wallet by signing a challenge.
772
766
  *
773
767
  * @param options - Registration options including the private key
@@ -787,7 +781,7 @@ var AgentWallet = class {
787
781
  static async register(options) {
788
782
  const { privateKey, name } = options;
789
783
  const baseUrl = (options.baseUrl || DEFAULT_BASE_URL).replace(/\/$/, "");
790
- const account = privateKeyToAccount2(privateKey);
784
+ const account = privateKeyToAccount(privateKey);
791
785
  const walletAddress = account.address;
792
786
  const challengeResponse = await fetch(
793
787
  `${baseUrl}/api/v1/agent/challenge?wallet=${walletAddress}&action=register`
@@ -855,7 +849,7 @@ var AgentWallet = class {
855
849
  healthy: false,
856
850
  database: "unknown",
857
851
  agentRegistrationAvailable: false,
858
- privyConfigured: false,
852
+ walletServiceConfigured: false,
859
853
  error: `Health check failed with status ${response.status}`
860
854
  };
861
855
  }
@@ -864,14 +858,14 @@ var AgentWallet = class {
864
858
  healthy: data.status === "ready",
865
859
  database: data.database || "unknown",
866
860
  agentRegistrationAvailable: data.services?.agentRegistration?.available ?? false,
867
- privyConfigured: data.services?.privy?.configured ?? false
861
+ walletServiceConfigured: data.services?.wallet?.configured ?? data.services?.privy?.configured ?? false
868
862
  };
869
863
  } catch (error) {
870
864
  return {
871
865
  healthy: false,
872
866
  database: "unreachable",
873
867
  agentRegistrationAvailable: false,
874
- privyConfigured: false,
868
+ walletServiceConfigured: false,
875
869
  error: error instanceof Error ? error.message : "Failed to reach server"
876
870
  };
877
871
  }
@@ -904,7 +898,7 @@ var AgentWallet = class {
904
898
  static async getSessionKey(options) {
905
899
  const { privateKey, spendingLimitUsd, maxPerTxUsd, maxDailyUsd, durationDays } = options;
906
900
  const baseUrl = (options.baseUrl || DEFAULT_BASE_URL).replace(/\/$/, "");
907
- const account = privateKeyToAccount2(privateKey);
901
+ const account = privateKeyToAccount(privateKey);
908
902
  const walletAddress = account.address;
909
903
  const challengeResponse = await fetch(
910
904
  `${baseUrl}/api/v1/agent/challenge?wallet=${walletAddress}&action=session-key`
@@ -967,7 +961,7 @@ var AgentWallet = class {
967
961
  static async getStatus(options) {
968
962
  const { privateKey } = options;
969
963
  const baseUrl = (options.baseUrl || DEFAULT_BASE_URL).replace(/\/$/, "");
970
- const account = privateKeyToAccount2(privateKey);
964
+ const account = privateKeyToAccount(privateKey);
971
965
  const walletAddress = account.address;
972
966
  const challengeResponse = await fetch(
973
967
  `${baseUrl}/api/v1/agent/challenge?wallet=${walletAddress}&action=status`
@@ -1023,7 +1017,7 @@ var AgentWallet = class {
1023
1017
  static async revokeSessionKey(options) {
1024
1018
  const { privateKey, sessionKeyId } = options;
1025
1019
  const baseUrl = (options.baseUrl || DEFAULT_BASE_URL).replace(/\/$/, "");
1026
- const account = privateKeyToAccount2(privateKey);
1020
+ const account = privateKeyToAccount(privateKey);
1027
1021
  const walletAddress = account.address;
1028
1022
  const challengeResponse = await fetch(
1029
1023
  `${baseUrl}/api/v1/agent/challenge?wallet=${walletAddress}&action=revoke`
@@ -1077,7 +1071,7 @@ var AgentWallet = class {
1077
1071
  static async withdraw(options) {
1078
1072
  const { privateKey, amountUsd } = options;
1079
1073
  const baseUrl = (options.baseUrl || DEFAULT_BASE_URL).replace(/\/$/, "");
1080
- const account = privateKeyToAccount2(privateKey);
1074
+ const account = privateKeyToAccount(privateKey);
1081
1075
  const walletAddress = account.address;
1082
1076
  const challengeResponse = await fetch(
1083
1077
  `${baseUrl}/api/v1/agent/challenge?wallet=${walletAddress}&action=withdraw`
@@ -1143,7 +1137,7 @@ var AgentWallet = class {
1143
1137
  static async claimInvite(options) {
1144
1138
  const { inviteCode, privateKey } = options;
1145
1139
  const baseUrl = (options.baseUrl || DEFAULT_BASE_URL).replace(/\/$/, "");
1146
- const account = privateKeyToAccount2(privateKey);
1140
+ const account = privateKeyToAccount(privateKey);
1147
1141
  const walletAddress = account.address;
1148
1142
  const challengeResponse = await fetch(
1149
1143
  `${baseUrl}/api/v1/agent/challenge?wallet=${walletAddress}&action=claim-invite`
@@ -1203,7 +1197,7 @@ var AgentWallet = class {
1203
1197
  * Spawn a child invite for sub-agents.
1204
1198
  *
1205
1199
  * Allows an agent to create an invite code for a sub-agent with a portion
1206
- * of their remaining budget (max 20%). The child inherits merchant restrictions
1200
+ * of their remaining budget. The child inherits merchant restrictions
1207
1201
  * and cannot outlive the parent session.
1208
1202
  *
1209
1203
  * @param options - Spawn options
@@ -1217,7 +1211,7 @@ var AgentWallet = class {
1217
1211
  *
1218
1212
  * // Spawn a child invite for a sub-agent
1219
1213
  * const childInvite = await wallet.spawnChildInvite({
1220
- * budgetUsd: 10.00, // Max 20% of available budget
1214
+ * budgetUsd: 10.00,
1221
1215
  * name: 'Research Sub-Agent',
1222
1216
  * allowedMerchants: ['firecrawl.dev'], // Must be subset of parent
1223
1217
  * expiresInDays: 7, // Will be capped to parent's expiry
@@ -1273,8 +1267,7 @@ var AgentWallet = class {
1273
1267
  /**
1274
1268
  * Get available budget information for spawning.
1275
1269
  *
1276
- * Returns the current budget status including how much can be spawned
1277
- * to child agents (20% of available).
1270
+ * Returns the current budget status including spawn availability.
1278
1271
  *
1279
1272
  * @returns Budget information
1280
1273
  *
@@ -2686,6 +2679,317 @@ Timestamp: ${timestamp}`;
2686
2679
  return this.parseJitInstance(data.instance);
2687
2680
  }
2688
2681
  // ===========================================================================
2682
+ // Transaction Execution
2683
+ // ===========================================================================
2684
+ /**
2685
+ * Execute an on-chain transaction from the human's wallet.
2686
+ *
2687
+ * Submits arbitrary calldata to any contract, bounded by the session key's
2688
+ * budget limits (max_total, max_per_tx, max_daily). The platform validates
2689
+ * the budget, executes the transaction, and records a charge.
2690
+ *
2691
+ * @param params - Transaction parameters
2692
+ * @returns Transaction result with hash and remaining budget
2693
+ * @throws {MixrPayError} If budget exceeded, tx reverted, or auth fails
2694
+ *
2695
+ * @example
2696
+ * ```typescript
2697
+ * // Bridge USDC via deBridge
2698
+ * const quote = await deBridgeMcp.create_tx({ ... });
2699
+ * const result = await wallet.executeTransaction({
2700
+ * to: quote.contractAddress,
2701
+ * data: quote.calldata,
2702
+ * estimatedCostUsd: 25.0,
2703
+ * description: 'Bridge 25 USDC Base -> Avalanche via deBridge',
2704
+ * });
2705
+ * console.log('TX:', result.txHash);
2706
+ * console.log('Budget remaining:', result.remainingBudgetUsd);
2707
+ * ```
2708
+ */
2709
+ async executeTransaction(params) {
2710
+ this.logger.debug("executeTransaction", { to: params.to, estimatedCostUsd: params.estimatedCostUsd });
2711
+ const authHeaders = await this.getSessionAuthHeaders();
2712
+ const response = await fetch(`${this.baseUrl}/api/v2/tx/execute`, {
2713
+ method: "POST",
2714
+ headers: {
2715
+ "Content-Type": "application/json",
2716
+ ...authHeaders
2717
+ },
2718
+ body: JSON.stringify({
2719
+ to: params.to,
2720
+ data: params.data,
2721
+ value: params.value?.toString() ?? "0",
2722
+ chain_id: params.chainId,
2723
+ estimated_cost_usd: params.estimatedCostUsd,
2724
+ description: params.description,
2725
+ idempotency_key: params.idempotencyKey
2726
+ })
2727
+ });
2728
+ const result = await response.json().catch(() => ({}));
2729
+ if (!response.ok) {
2730
+ const errorCode = result.error_code || "TX_FAILED";
2731
+ const errorMessage = result.error || `Transaction execution failed: ${response.status}`;
2732
+ if (errorCode === "BUDGET_EXCEEDED") {
2733
+ throw new MixrPayError(errorMessage, "SPENDING_LIMIT_EXCEEDED");
2734
+ }
2735
+ throw new MixrPayError(errorMessage, errorCode);
2736
+ }
2737
+ this.logger.info("Transaction executed", {
2738
+ txHash: result.tx_hash,
2739
+ estimatedCostUsd: params.estimatedCostUsd,
2740
+ remainingBudgetUsd: result.remaining_budget_usd
2741
+ });
2742
+ return {
2743
+ success: true,
2744
+ txHash: result.tx_hash,
2745
+ chargeId: result.charge_id,
2746
+ estimatedCostUsd: result.estimated_cost_usd,
2747
+ remainingBudgetUsd: result.remaining_budget_usd
2748
+ };
2749
+ }
2750
+ // ===========================================================================
2751
+ // Skills Methods
2752
+ // ===========================================================================
2753
+ /**
2754
+ * Use a configured skill by deploying a JIT MCP server with your saved API keys.
2755
+ *
2756
+ * Skills are configured on the MixrPay dashboard with your API keys stored securely.
2757
+ * When you call useSkill(), MixrPay deploys an ephemeral MCP server with your keys
2758
+ * injected server-side - your keys are never exposed to the agent.
2759
+ *
2760
+ * @param skillId - The skill ID (e.g., 'github', 'notion', 'spotify')
2761
+ * @param options - Optional configuration
2762
+ * @returns Skill endpoint and available tools
2763
+ *
2764
+ * @example
2765
+ * ```typescript
2766
+ * // Use the GitHub skill
2767
+ * const github = await wallet.useSkill('github');
2768
+ *
2769
+ * console.log('Endpoint:', github.endpoint);
2770
+ * console.log('Tools:', github.tools);
2771
+ * console.log('Expires:', github.expiresAt);
2772
+ *
2773
+ * // Connect to the MCP endpoint and call tools
2774
+ * // The exact method depends on your MCP client
2775
+ * ```
2776
+ *
2777
+ * @example
2778
+ * ```typescript
2779
+ * // Use Notion with custom TTL
2780
+ * const notion = await wallet.useSkill('notion', { ttlHours: 48 });
2781
+ * ```
2782
+ *
2783
+ * @throws {MixrPayError} If skill is not configured or deployment fails
2784
+ */
2785
+ async useSkill(skillId, options) {
2786
+ this.logger.debug("useSkill", { skillId, options });
2787
+ const authHeaders = await this.getSessionAuthHeaders();
2788
+ const response = await fetch(`${this.baseUrl}/api/v2/skills/${skillId}/use`, {
2789
+ method: "POST",
2790
+ headers: {
2791
+ "Content-Type": "application/json",
2792
+ ...authHeaders
2793
+ },
2794
+ body: JSON.stringify({
2795
+ ttl_hours: options?.ttlHours || 24
2796
+ })
2797
+ });
2798
+ if (!response.ok) {
2799
+ const error = await response.json().catch(() => ({}));
2800
+ if (error.configure_url) {
2801
+ throw new MixrPayError(
2802
+ `${error.error || "Skill not configured"}. Configure at: ${this.baseUrl}${error.configure_url}`,
2803
+ "SKILL_NOT_CONFIGURED"
2804
+ );
2805
+ }
2806
+ throw new MixrPayError(error.error || `Failed to use skill: ${response.status}`);
2807
+ }
2808
+ const data = await response.json();
2809
+ return {
2810
+ skillId: data.skill_id,
2811
+ endpoint: data.endpoint,
2812
+ tools: data.tools || [],
2813
+ expiresAt: new Date(data.expires_at),
2814
+ instanceId: data.instance_id
2815
+ };
2816
+ }
2817
+ /**
2818
+ * List all available skills and their configuration status.
2819
+ *
2820
+ * @returns Array of skills with status
2821
+ *
2822
+ * @example
2823
+ * ```typescript
2824
+ * const skills = await wallet.listSkills();
2825
+ *
2826
+ * // Find configured skills
2827
+ * const configured = skills.filter(s => s.status === 'configured');
2828
+ * console.log(`${configured.length} skills ready to use`);
2829
+ *
2830
+ * // Find skills that need configuration
2831
+ * const needsConfig = skills.filter(s => s.status === 'not_configured' && s.envVars.length > 0);
2832
+ * for (const skill of needsConfig) {
2833
+ * console.log(`${skill.name} needs: ${skill.envVars.map(v => v.label).join(', ')}`);
2834
+ * }
2835
+ * ```
2836
+ */
2837
+ async listSkills() {
2838
+ this.logger.debug("listSkills");
2839
+ const authHeaders = await this.getSessionAuthHeaders();
2840
+ const response = await fetch(`${this.baseUrl}/api/v2/skills`, {
2841
+ headers: authHeaders
2842
+ });
2843
+ if (!response.ok) {
2844
+ const error = await response.json().catch(() => ({}));
2845
+ throw new MixrPayError(error.error || `Failed to list skills: ${response.status}`);
2846
+ }
2847
+ const data = await response.json();
2848
+ return data.skills || [];
2849
+ }
2850
+ /**
2851
+ * Get apps connected via Composio (Gmail, Slack, GitHub, etc.).
2852
+ *
2853
+ * Use this to discover which apps the owner has connected before
2854
+ * attempting to use them via `wallet.useSkill('composio')`.
2855
+ *
2856
+ * @returns Object with connected app names and connection details
2857
+ *
2858
+ * @example
2859
+ * ```typescript
2860
+ * const apps = await wallet.getConnectedApps();
2861
+ *
2862
+ * if (apps.connected.length === 0) {
2863
+ * console.log('No apps connected. Ask your owner to connect apps at the dashboard.');
2864
+ * } else {
2865
+ * console.log('Connected apps:', apps.connected.join(', '));
2866
+ *
2867
+ * if (apps.connected.includes('gmail')) {
2868
+ * // Safe to use Composio for Gmail
2869
+ * const { endpoint, tools } = await wallet.useSkill('composio');
2870
+ * // tools will include 'gmail_read_emails', 'gmail_send_email', etc.
2871
+ * }
2872
+ * }
2873
+ * ```
2874
+ */
2875
+ async getConnectedApps() {
2876
+ this.logger.debug("getConnectedApps");
2877
+ const authHeaders = await this.getSessionAuthHeaders();
2878
+ const response = await fetch(`${this.baseUrl}/api/v2/skills/composio/connections`, {
2879
+ headers: authHeaders
2880
+ });
2881
+ if (!response.ok) {
2882
+ const error = await response.json().catch(() => ({}));
2883
+ throw new MixrPayError(
2884
+ error.error || `Failed to get connected apps: ${response.status}`,
2885
+ "CONNECTED_APPS_FAILED"
2886
+ );
2887
+ }
2888
+ const data = await response.json();
2889
+ const connectedAppNames = (data.connections || []).filter((c) => c.status === "connected").map((c) => c.app.toLowerCase());
2890
+ return {
2891
+ connected: connectedAppNames,
2892
+ connections: data.connections || [],
2893
+ oauthConnections: data.oauth_connections || [],
2894
+ apiKeyConnections: data.api_key_connections || []
2895
+ };
2896
+ }
2897
+ /**
2898
+ * Get configuration status for a specific skill.
2899
+ *
2900
+ * @param skillId - The skill ID
2901
+ * @returns Skill configuration status
2902
+ *
2903
+ * @example
2904
+ * ```typescript
2905
+ * const status = await wallet.getSkillStatus('github');
2906
+ *
2907
+ * if (status.status === 'configured') {
2908
+ * console.log('GitHub is ready!');
2909
+ * console.log('Configured vars:', status.configuredVars);
2910
+ * } else {
2911
+ * console.log('Please configure GitHub at the MixrPay dashboard');
2912
+ * }
2913
+ * ```
2914
+ */
2915
+ async getSkillStatus(skillId) {
2916
+ this.logger.debug("getSkillStatus", { skillId });
2917
+ const authHeaders = await this.getSessionAuthHeaders();
2918
+ const response = await fetch(`${this.baseUrl}/api/v2/skills/${skillId}/configure`, {
2919
+ headers: authHeaders
2920
+ });
2921
+ if (!response.ok) {
2922
+ const error = await response.json().catch(() => ({}));
2923
+ throw new MixrPayError(error.error || `Failed to get skill status: ${response.status}`);
2924
+ }
2925
+ const data = await response.json();
2926
+ return {
2927
+ skillId: data.skill_id,
2928
+ status: data.status,
2929
+ configuredVars: data.configured_vars || [],
2930
+ lastUsedAt: data.last_used_at ? new Date(data.last_used_at) : void 0,
2931
+ errorMessage: data.error_message
2932
+ };
2933
+ }
2934
+ /**
2935
+ * Configure a skill with API keys.
2936
+ *
2937
+ * This allows agents to save API keys received via chat to the MixrPay platform.
2938
+ * Keys are encrypted at rest and will be available for use on subsequent deploy/redeploy.
2939
+ *
2940
+ * @param skillId - The skill ID (e.g., 'web-search', 'github', 'notion') or custom skill with 'custom-' prefix
2941
+ * @param envVars - Environment variables with API keys (e.g., { BRAVE_API_KEY: 'xxx' })
2942
+ * @returns Configuration result with list of configured variables
2943
+ *
2944
+ * @example Predefined skill
2945
+ * ```typescript
2946
+ * // User provides API key in chat, agent saves it
2947
+ * const result = await wallet.configureSkill('web-search', {
2948
+ * BRAVE_API_KEY: 'BSA_abc123xyz',
2949
+ * });
2950
+ *
2951
+ * console.log('Configured:', result.configuredVars);
2952
+ * // After next redeploy, the skill will be enabled with this key
2953
+ * ```
2954
+ *
2955
+ * @example Custom API key
2956
+ * ```typescript
2957
+ * // For APIs not in predefined skills, use custom- prefix
2958
+ * // User: "Here's my Polymarket API key: pk_abc123"
2959
+ * const result = await wallet.configureSkill('custom-polymarket', {
2960
+ * POLYMARKET_API_KEY: 'pk_abc123',
2961
+ * });
2962
+ *
2963
+ * // The key is now available in the agent's environment
2964
+ * // Access via: process.env.POLYMARKET_API_KEY
2965
+ * ```
2966
+ */
2967
+ async configureSkill(skillId, envVars) {
2968
+ this.logger.debug("configureSkill", { skillId, varNames: Object.keys(envVars) });
2969
+ const authHeaders = await this.getSessionAuthHeaders();
2970
+ const response = await fetch(`${this.baseUrl}/api/v2/skills/${skillId}/configure`, {
2971
+ method: "POST",
2972
+ headers: {
2973
+ "Content-Type": "application/json",
2974
+ ...authHeaders
2975
+ },
2976
+ body: JSON.stringify({ env_vars: envVars })
2977
+ });
2978
+ if (!response.ok) {
2979
+ const error = await response.json().catch(() => ({}));
2980
+ throw new MixrPayError(
2981
+ error.error || `Failed to configure skill: ${response.status}`,
2982
+ error.error_code
2983
+ );
2984
+ }
2985
+ const data = await response.json();
2986
+ return {
2987
+ success: true,
2988
+ skillId: data.skill_id,
2989
+ configuredVars: data.configured_vars || []
2990
+ };
2991
+ }
2992
+ // ===========================================================================
2689
2993
  // Glama MCP Directory Methods
2690
2994
  // ===========================================================================
2691
2995
  /**
@@ -4325,7 +4629,7 @@ Timestamp: ${timestamp}`;
4325
4629
  ...init.headers
4326
4630
  };
4327
4631
  if (this.sessionKey) {
4328
- const account = privateKeyToAccount2(this.sessionKey.rawPrivateKey);
4632
+ const account = privateKeyToAccount(this.sessionKey.rawPrivateKey);
4329
4633
  const address = account.address.toLowerCase();
4330
4634
  const timestamp = Date.now();
4331
4635
  const message = `MixrPay:${timestamp}:${address}`;
@@ -4345,21 +4649,5 @@ Timestamp: ${timestamp}`;
4345
4649
  });
4346
4650
  }
4347
4651
  };
4348
- export {
4349
- AgentWallet,
4350
- InsufficientBalanceError,
4351
- InvalidSessionKeyError,
4352
- MerchantNotAllowedError,
4353
- MixrPayError,
4354
- PaymentFailedError,
4355
- SDK_VERSION,
4356
- SessionExpiredError,
4357
- SessionKeyExpiredError,
4358
- SessionLimitExceededError,
4359
- SessionNotFoundError,
4360
- SessionRevokedError,
4361
- SpendingLimitExceededError,
4362
- X402ProtocolError,
4363
- getErrorMessage,
4364
- isMixrPayError
4365
- };
4652
+
4653
+ export { AgentWallet, InsufficientBalanceError, InvalidSessionKeyError, MerchantNotAllowedError, MixrPayError, PaymentFailedError, SDK_VERSION, SessionExpiredError, SessionKeyExpiredError, SessionLimitExceededError, SessionNotFoundError, SessionRevokedError, SpendingLimitExceededError, X402ProtocolError, getErrorMessage, isMixrPayError };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mixrpay/agent-sdk",
3
- "version": "0.8.8",
3
+ "version": "0.9.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",
@@ -19,7 +19,7 @@
19
19
  "LICENSE"
20
20
  ],
21
21
  "scripts": {
22
- "build": "tsup src/index.ts --format esm,cjs --dts --clean",
22
+ "build": "tsup --config tsup.config.ts",
23
23
  "dev": "tsup src/index.ts --format esm,cjs --dts --watch",
24
24
  "test": "vitest run",
25
25
  "test:watch": "vitest",