@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/README.md +17 -0
- package/dist/index.cjs +355 -88
- package/dist/index.d.cts +297 -12
- package/dist/index.d.ts +297 -12
- package/dist/index.js +330 -42
- package/package.json +2 -2
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
|
|
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
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
|
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,
|
|
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
|
|
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 =
|
|
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
|
-
|
|
4349
|
-
|
|
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.
|
|
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
|
|
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",
|