@mixrpay/agent-sdk 0.11.3 → 0.11.4

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
@@ -12,6 +12,8 @@ yarn add @mixrpay/agent-sdk
12
12
  pnpm add @mixrpay/agent-sdk
13
13
  ```
14
14
 
15
+ The CLI binary is `mixrpay`, but the package name is **`@mixrpay/agent-sdk`**. Bare `npx mixrpay` can resolve to a different package on npm—use **`npx --package @mixrpay/agent-sdk mixrpay …`** for one-off runs, or **`npm install -g @mixrpay/agent-sdk`** so `mixrpay` is on your `PATH`.
16
+
15
17
  ## Getting Started
16
18
 
17
19
  MixrPay lets your AI agents use real non-custodial wallets with micropayment capabilities on Base and Solana.
@@ -19,7 +21,7 @@ MixrPay lets your AI agents use real non-custodial wallets with micropayment cap
19
21
  #### Option 1: Quick Start (Recommended)
20
22
 
21
23
  ```bash
22
- npx mixrpay init --name "MyAgent"
24
+ npx --package @mixrpay/agent-sdk mixrpay init --name "MyAgent"
23
25
  ```
24
26
 
25
27
  This sets up your agent and wallet locally. Fund with USDC on Base (or use an invite code) before using paid tools.
@@ -31,8 +33,9 @@ For a guided experience (especially useful when working inside Cursor or Claude)
31
33
  Follow the steps to get your agent credentials, then run:
32
34
 
33
35
  ```bash
34
- npx mixrpay install
35
- mixrpay status
36
+ npx --package @mixrpay/agent-sdk mixrpay install
37
+ npx --package @mixrpay/agent-sdk mixrpay status
38
+ # or: npm i -g @mixrpay/agent-sdk then mixrpay install && mixrpay status
36
39
  ```
37
40
 
38
41
  Your agent is then ready to use with `mixrpay run` or via the SDK.
@@ -203,16 +206,16 @@ for (const block of response.content) {
203
206
  ## MCP Server (Standalone)
204
207
 
205
208
  ```bash
206
- MIXRPAY_API_KEY=agt_live_... npx mixrpay-mcp
209
+ MIXRPAY_API_KEY=agt_live_... npx --package @mixrpay/agent-sdk mixrpay-mcp
207
210
  ```
208
211
 
209
212
  ## CLI
210
213
 
211
214
  ```bash
212
- npx mixrpay login
213
- npx mixrpay whoami
214
- npx mixrpay status
215
- npx mixrpay logout
215
+ npx --package @mixrpay/agent-sdk mixrpay login
216
+ npx --package @mixrpay/agent-sdk mixrpay whoami
217
+ npx --package @mixrpay/agent-sdk mixrpay status
218
+ npx --package @mixrpay/agent-sdk mixrpay logout
216
219
  ```
217
220
 
218
221
  ## Error Handling
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env node
2
- export{g as AgentWallet,c as DEFAULT_BASE_URL,d as DEFAULT_FACILITATOR_URL,e as DEFAULT_TIMEOUT,f as NETWORKS,b as SDK_VERSION}from'./chunk-SEL55NG5.js';
2
+ export{g as AgentWallet,c as DEFAULT_BASE_URL,d as DEFAULT_FACILITATOR_URL,e as DEFAULT_TIMEOUT,f as NETWORKS,b as SDK_VERSION}from'./chunk-TOPWZWOK.js';
@@ -1,11 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import {fileURLToPath}from'url';import {join,dirname}from'path';import {privateKeyToAccount,signMessage,generatePrivateKey,signTypedData}from'viem/accounts';import {z as z$1}from'zod';import {createWalletClient,http,parseUnits,encodeFunctionData}from'viem';import {base}from'viem/chains';import {existsSync,readFileSync,mkdirSync,writeFileSync,chmodSync}from'fs';import {homedir}from'os';var l=class extends Error{code;retryAfterMs;constructor(e,t="MIXRPAY_ERROR",s){super(e),this.name="MixrPayError",this.code=t,this.retryAfterMs=s,Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor);}isRetryable(){return false}},v=class extends l{required;available;topUpUrl;constructor(e,t){let s=e-t;super(`Insufficient balance: need $${e.toFixed(2)}, have $${t.toFixed(2)} (short $${s.toFixed(2)}). Top up your wallet to continue.`,"INSUFFICIENT_BALANCE"),this.name="InsufficientBalanceError",this.required=e,this.available=t,this.topUpUrl="https://mixr.network/manage/wallet";}},R=class extends l{expiredAt;constructor(e){super(`Session key expired at ${e}. Request a new session key from the wallet owner at https://mixrpay.com/manage/invites`,"SESSION_KEY_EXPIRED"),this.name="SessionKeyExpiredError",this.expiredAt=e;}},T=class extends l{limitType;limit;attempted;constructor(e,t,s){let a={per_tx:"Per-transaction",daily:"Daily",total:"Total",client_max:"Client-side"}[e]||e,i=e==="daily"?"Wait until tomorrow or request a higher limit.":e==="client_max"?"Increase maxPaymentUsd in your AgentWallet configuration.":"Request a new session key with a higher limit.";super(`${a} spending limit exceeded: limit is $${t.toFixed(2)}, attempted $${s.toFixed(2)}. ${i}`,"SPENDING_LIMIT_EXCEEDED"),this.name="SpendingLimitExceededError",this.limitType=e,this.limit=t,this.attempted=s;}isRetryable(){return this.limitType==="daily"}},A=class extends l{reason;txHash;constructor(e,t){let s=`Payment failed: ${e}`;t&&(s+=` (tx: ${t} - check on basescan.org)`),super(s,"PAYMENT_FAILED"),this.name="PaymentFailedError",this.reason=e,this.txHash=t;}isRetryable(){return true}},x=class extends l{reason;constructor(e="Invalid session key format"){super(`${e}. Session keys should be in format: sk_live_<64 hex chars> or sk_test_<64 hex chars>. Get one from https://mixrpay.com/manage/invites`,"INVALID_SESSION_KEY"),this.name="InvalidSessionKeyError",this.reason=e;}},P=class extends l{reason;constructor(e){super(`x402 protocol error: ${e}. This may indicate a server configuration issue. If the problem persists, contact the API provider.`,"X402_PROTOCOL_ERROR"),this.name="X402ProtocolError",this.reason=e;}isRetryable(){return true}},D=class extends l{sessionId;expiredAt;constructor(e,t){super(`Session ${e} has expired${t?` at ${t}`:""}. A new session will be created automatically on your next request.`,"SESSION_EXPIRED"),this.name="SessionExpiredError",this.sessionId=e,this.expiredAt=t;}},U=class extends l{sessionId;limit;requested;remaining;constructor(e,t,s,n){super(`Session spending limit exceeded: limit is $${e.toFixed(2)}, requested $${t.toFixed(2)}, remaining $${s.toFixed(2)}. Create a new session with a higher limit to continue.`,"SESSION_LIMIT_EXCEEDED"),this.name="SessionLimitExceededError",this.sessionId=n,this.limit=e,this.requested=t,this.remaining=s;}},I=class extends l{sessionId;constructor(e){super(`Session ${e} not found. It may have been deleted or never existed. Create a new session with getOrCreateSession().`,"SESSION_NOT_FOUND"),this.name="SessionNotFoundError",this.sessionId=e;}},C=class extends l{sessionId;reason;constructor(e,t){super(`Session ${e} has been revoked${t?`: ${t}`:""}. Create a new session with getOrCreateSession().`,"SESSION_REVOKED"),this.name="SessionRevokedError",this.sessionId=e,this.reason=t;}},E=class extends l{attempted;allowedPatterns;constructor(e,t){let s=t.slice(0,3).join(", "),n=t.length>3?"...":"";super(`Payment to "${e}" not allowed. Session allowlist: ${s}${n}. Update the session allowlist or create a new session.`,"MERCHANT_NOT_ALLOWED"),this.name="MerchantNotAllowedError",this.attempted=e,this.allowedPatterns=t;}};var Se={8453:"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",84532:"0x036CbD53842c5426634e7929541eC2318f3dCF7e"},xe={name:"USD Coin",version:"2"},Ae={TransferWithAuthorization:[{name:"from",type:"address"},{name:"to",type:"address"},{name:"value",type:"uint256"},{name:"validAfter",type:"uint256"},{name:"validBefore",type:"uint256"},{name:"nonce",type:"bytes32"}]},O=class c{privateKey;account;address;isTest;constructor(e,t){this.privateKey=e,this.account=privateKeyToAccount(e),this.address=this.account.address,this.isTest=t;}toString(){return `${this.isTest?"sk_test_":"sk_live_"}${this.privateKey.slice(2)}`}get privateKeyHex(){return this.privateKey.slice(2)}get rawPrivateKey(){return this.privateKey}static fromString(e){let t=/^sk_(live|test)_([a-fA-F0-9]{64})$/,s=e.match(t);if(!s)throw new x("Session key must be in format sk_live_{64_hex} or sk_test_{64_hex}");let n=s[1],a=s[2];try{let i=`0x${a}`;return new c(i,n==="test")}catch(i){throw new x(`Failed to decode session key: ${i}`)}}async signTransferAuthorization(e,t){return signTypedData({privateKey:this.privateKey,domain:e,types:Ae,primaryType:"TransferWithAuthorization",message:t})}async signMessage(e){return signMessage({privateKey:this.privateKey,message:e})}getDefaultChainId(){return this.isTest?84532:8453}};function q(c){let e=Se[c.chainId];if(!e)throw new Error(`USDC not supported on chain ${c.chainId}`);let t={...xe,chainId:c.chainId,verifyingContract:e},s={from:c.fromAddress,to:c.toAddress,value:c.value,validAfter:c.validAfter,validBefore:c.validBefore,nonce:c.nonce};return {domain:t,message:s}}function j(){let c=new Uint8Array(32);return crypto.getRandomValues(c),`0x${Array.from(c).map(e=>e.toString(16).padStart(2,"0")).join("")}`}function ke(c,e){return `MixrPay:${c}:${e.toLowerCase()}`}async function B(c){let e=Date.now(),t=ke(e,c.address),s=await c.signMessage(t);return {address:c.address,timestamp:e,signature:s}}var J=z$1.object({query:z$1.string().describe('Search query (e.g. "web scraping", "email", "database")')}),G=z$1.object({tool_name:z$1.string().describe('Tool name in "merchant/tool" format'),arguments:z$1.record(z$1.unknown()).optional().describe("Arguments to pass to the tool")}),X=z$1.object({url:z$1.string().url().describe("The merchant API URL to call"),merchant_public_key:z$1.string().describe("The merchant's MixrPay public key (pk_live_... or pk_test_...)"),method:z$1.enum(["GET","POST","PUT","PATCH","DELETE"]).default("POST").describe("HTTP method"),body:z$1.unknown().optional().describe("Request body (will be JSON-serialized)"),price_usd:z$1.number().optional().describe("Expected price in USD for client-side validation")}),z=z$1.object({skill_id:z$1.string().describe("The skill ID to execute"),input:z$1.record(z$1.unknown()).optional().describe("Input parameters for the skill")}),Y=z$1.object({skill_id:z$1.string().describe("The skill ID to check")}),V=z$1.object({glama_id:z$1.string().describe('Glama server ID (e.g. "notion-mcp")'),glama_namespace:z$1.string().describe('Glama namespace (e.g. "notion")'),glama_slug:z$1.string().describe('Glama slug (e.g. "notion-mcp")'),tool_name:z$1.string().describe("Human-readable name for the tool"),tool_description:z$1.string().optional().describe("Optional description"),env_vars:z$1.record(z$1.string()).optional().describe("Environment variables for the MCP server (e.g. API keys)"),ttl_hours:z$1.number().min(1).max(168).optional().describe("Time-to-live in hours (default: 24, max: 168)")}),Z=z$1.object({status:z$1.enum(["provisioning","active","stopped","expired"]).optional().describe("Filter by status")}),Q=z$1.object({instance_id:z$1.string().describe("The instance ID to stop")}),ee=z$1.object({to:z$1.string().describe("Recipient address (0x...)"),amount_usdc:z$1.number().positive().describe("Amount in USDC (e.g. 10.5)")}),te=z$1.object({name:z$1.string().describe("Name for the child agent"),budget_usd:z$1.number().positive().describe("Budget to delegate in USD"),budget_period:z$1.enum(["daily","monthly","total"]).default("total").describe("Budget period"),max_per_tx_usd:z$1.number().positive().optional().describe("Max per-transaction limit in USD"),expires_in_days:z$1.number().min(1).max(365).optional().describe("Expiry in days (default: 30)")}),se=z$1.object({title:z$1.string().describe("Task title"),description:z$1.string().describe("Detailed task description"),budget_usd:z$1.number().positive().describe("Budget for the task in USD"),skills_required:z$1.array(z$1.string()).optional().describe("Required skill IDs")}),ne=z$1.object({status:z$1.string().optional().describe('Filter by status (e.g. "open", "in_progress")'),limit:z$1.number().min(1).max(100).optional().describe("Number of results (default: 20)")});function ae(c){let e=[{name:"check_balance",title:"Check Balance",description:"Get the USDC balance of the wallet on Base.",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:null,handler:async()=>({balanceUsd:await c.getBalance(),network:c.isTestnet()?"base-sepolia":"base"})},{name:"get_spending_stats",title:"Get Spending Stats",description:"Get session key spending limits and current usage (total spent, remaining daily/total limits, expiry).",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:null,handler:async()=>c.getSpendingStats()},{name:"get_session_info",title:"Get Session Info",description:"Get detailed session key information including limits, usage, expiry, and allowed merchants.",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:null,handler:async()=>c.getSessionKeyInfo(true)},{name:"run_diagnostics",title:"Run Diagnostics",description:"Run a full health check on the wallet: API connectivity, session key validity, balance, and latency.",annotations:{readOnlyHint:true,openWorldHint:true},inputSchema:null,handler:async()=>c.runDiagnostics()},{name:"list_tools",title:"List Marketplace Tools",description:"Browse all available paid API tools on the MixrPay marketplace. Each tool includes pricing and description.",annotations:{readOnlyHint:true,openWorldHint:true},inputSchema:null,handler:async()=>c.listTools()},{name:"search_tools",title:"Search Tools",description:"Search the Glama MCP server directory for tools by keyword.",annotations:{readOnlyHint:true,openWorldHint:true},inputSchema:J,handler:async s=>{let{query:n}=J.parse(s);return c.searchGlamaDirectory(n)}},{name:"call_tool",title:"Call Marketplace Tool",description:'Call a paid API tool on the MixrPay marketplace. Payment is automatic from the wallet. Tool names are in "merchant/tool" format (e.g. "firecrawl/scrape").',annotations:{readOnlyHint:false,openWorldHint:true},inputSchema:G,handler:async s=>{let{tool_name:n,arguments:a}=G.parse(s);return c.callTool(n,a||{})}},{name:"call_merchant_api",title:"Call Merchant API",description:"Call any merchant API endpoint with x402 payment. The wallet handles authentication and payment automatically.",annotations:{readOnlyHint:false,openWorldHint:true},inputSchema:X,handler:async s=>{let{url:n,merchant_public_key:a,method:i,body:r,price_usd:o}=X.parse(s),d=await c.callMerchantApi({url:n,merchantPublicKey:a,method:i,body:r,priceUsd:o}),g=await d.json().catch(()=>d.text());return {status:d.status,data:g}}},{name:"list_skills",title:"List Skills",description:"List all available skills (pre-built integrations) that the wallet can use.",annotations:{readOnlyHint:true,openWorldHint:true},inputSchema:null,handler:async()=>c.listSkills()},{name:"use_skill",title:"Use Skill",description:"Execute a skill by ID. Skills are pre-built integrations (e.g. web scraping, email sending).",annotations:{readOnlyHint:false,openWorldHint:true},inputSchema:z,handler:async s=>{let{skill_id:n,input:a}=z.parse(s);return c.useSkill(n,{input:a})}},{name:"get_skill_status",title:"Get Skill Status",description:"Check the status and configuration of a specific skill.",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:Y,handler:async s=>{let{skill_id:n}=Y.parse(s);return c.getSkillStatus(n)}},{name:"deploy_jit_mcp",title:"Deploy JIT MCP Server",description:"Deploy a just-in-time MCP server from the Glama directory. Creates a temporary hosted MCP server instance.",annotations:{readOnlyHint:false,openWorldHint:true},inputSchema:V,handler:async s=>{let{glama_id:n,glama_namespace:a,glama_slug:i,tool_name:r,tool_description:o,env_vars:d,ttl_hours:g}=V.parse(s);return c.deployJitMcp({glamaId:n,glamaNamespace:a,glamaSlug:i,toolName:r,toolDescription:o,envVars:d,ttlHours:g})}},{name:"list_jit_instances",title:"List JIT Instances",description:"List all deployed JIT MCP server instances.",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:Z,handler:async s=>{let{status:n}=Z.parse(s);return c.listJitInstances(n?{status:n}:void 0)}},{name:"stop_jit_instance",title:"Stop JIT Instance",description:"Stop a running JIT MCP server instance.",annotations:{readOnlyHint:false,destructiveHint:true,openWorldHint:false},inputSchema:Q,handler:async s=>{let{instance_id:n}=Q.parse(s);return await c.stopJitInstance(n),{success:true,instance_id:n}}},{name:"transfer_usdc",title:"Transfer USDC",description:"Transfer USDC from the self-custody wallet to another address on Base. Only available when the wallet has a self-custody wallet (AGENT_WALLET_KEY set).",annotations:{readOnlyHint:false,destructiveHint:true,openWorldHint:true},inputSchema:ee,handler:async s=>{let{to:n,amount_usdc:a}=ee.parse(s);if(!await c.hasSelfCustodyWallet())throw new Error("No self-custody wallet configured. Set AGENT_WALLET_KEY to enable transfers.");return {success:true,txHash:await c.transferUSDC({to:n,amountUsdc:a}),to:n,amountUsdc:a}}},{name:"get_budget",title:"Get Available Budget",description:"Get the available delegation budget including remaining amount, whether spawning children is possible, and budget limits.",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:null,handler:async()=>c.getAvailableBudget()},{name:"spawn_child",title:"Spawn Child Session",description:"Create a child invite with a delegated budget from this wallet. Returns an invite code that another agent can claim.",annotations:{readOnlyHint:false,openWorldHint:false},inputSchema:te,handler:async s=>{let{name:n,budget_usd:a,budget_period:i,max_per_tx_usd:r,expires_in_days:o}=te.parse(s);return c.spawnChildInvite({name:n,budgetUsd:a,budgetPeriod:i,maxPerTxUsd:r,expiresInDays:o})}},{name:"list_children",title:"List Child Sessions",description:"List all child sessions (agents) spawned from this wallet.",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:null,handler:async()=>c.listChildSessions()},{name:"create_task",title:"Create Task",description:"Create a new task on the MixrPay marketplace for other agents to complete.",annotations:{readOnlyHint:false,openWorldHint:true},inputSchema:se,handler:async s=>{let{title:n,description:a,budget_usd:i,skills_required:r}=se.parse(s);return c.createTask({title:n,description:a,budgetUsd:i,skillsRequired:r})}},{name:"list_tasks",title:"List Tasks",description:"Browse available tasks on the MixrPay marketplace.",annotations:{readOnlyHint:true,openWorldHint:true},inputSchema:ne,handler:async s=>{let{status:n,limit:a}=ne.parse(s);return c.listTasks({status:n,limit:a})}}];return {definitions:e,execute:async(s,n)=>{let a=e.find(i=>i.name===s);if(!a)throw new Error(`Unknown tool: ${s}`);try{let i=await a.handler(n);return JSON.stringify(i,null,2)}catch(i){let r=i instanceof Error?i.message:String(i);throw new Error(r)}}}}function ie(c){if(c instanceof z$1.ZodObject){let e=c._def.shape(),t={},s=[];for(let[n,a]of Object.entries(e)){let i=a;t[n]=K(i),!(i instanceof z$1.ZodOptional)&&!(i instanceof z$1.ZodDefault)&&s.push(n);}return {type:"object",properties:t,...s.length>0?{required:s}:{}}}return {type:"object",properties:{}}}function K(c){let e=c;e instanceof z$1.ZodOptional&&(e=e._def.innerType),e instanceof z$1.ZodDefault&&(e=e._def.innerType);let t=c._def.description;if(e instanceof z$1.ZodString)return {type:"string",...t&&{description:t}};if(e instanceof z$1.ZodNumber)return {type:"number",...t&&{description:t}};if(e instanceof z$1.ZodBoolean)return {type:"boolean",...t&&{description:t}};if(e instanceof z$1.ZodEnum)return {type:"string",enum:e._def.values,...t&&{description:t}};if(e instanceof z$1.ZodArray)return {type:"array",items:K(e._def.type),...t&&{description:t}};if(e instanceof z$1.ZodRecord)return {type:"object",additionalProperties:K(e._def.valueType),...t&&{description:t}};if(e instanceof z$1.ZodObject){let s=e._def.shape(),n={};for(let[a,i]of Object.entries(s))n[a]=K(i);return {type:"object",properties:n,...t&&{description:t}}}return e instanceof z$1.ZodUnknown?{...t&&{description:t}}:{...t&&{description:t}}}var Ce="0.9.5",re=".config/mixrpay",$e="wallet.json";function oe(){let c=process.env.MIXRPAY_WORKSPACE_DIR||process.env.OPENCLAW_WORKSPACE_DIR;return c?join(c,re):join(homedir(),re)}function N(){return join(oe(),$e)}async function le(c,e){let t=oe(),s=N();existsSync(t)||mkdirSync(t,{recursive:true,mode:448});let n={address:e.toLowerCase(),privateKey:c,createdAt:new Date().toISOString(),sdkVersion:Ce};writeFileSync(s,JSON.stringify(n,null,2),{encoding:"utf-8",mode:384});try{chmodSync(s,384);}catch{}}async function L(){let c=process.env.MIXRPAY_WALLET_KEY;if(c){if(c.startsWith("0x")&&c.length===66)return c;if(c.length===64)return `0x${c}`;console.warn("[MixrPay] MIXRPAY_WALLET_KEY has invalid format, ignoring");}let e=N();if(!existsSync(e))return null;try{let t=readFileSync(e,"utf-8"),s=JSON.parse(t);return !s.privateKey||!s.privateKey.startsWith("0x")?(console.warn("[MixrPay] Wallet file has invalid format"),null):s.privateKey}catch(t){return console.warn("[MixrPay] Failed to read wallet file:",t),null}}async function ce(){let c=process.env.MIXRPAY_WALLET_KEY;return c&&(c.length===64||c.startsWith("0x")&&c.length===66)?true:existsSync(N())}async function de(c){let e=null,t=c.headers.get("X-Payment-Required");if(t)try{e=JSON.parse(t);}catch{}if(!e){let n=c.headers.get("WWW-Authenticate");if(n?.startsWith("X-402 "))try{let a=n.slice(6);e=JSON.parse(atob(a));}catch{}}if(!e)try{e=await c.json();}catch{}if(!e)throw new P("Could not parse payment requirements from 402 response");if(!e.recipient)throw new P("Missing recipient in payment requirements");if(!e.amount)throw new P("Missing amount in payment requirements");let s=Math.floor(Date.now()/1e3);return {recipient:e.recipient,amount:BigInt(e.amount),currency:e.currency||"USDC",chainId:e.chainId||e.chain_id||8453,facilitatorUrl:e.facilitatorUrl||e.facilitator_url||"https://x402.org/facilitator",nonce:e.nonce||j().slice(2),expiresAt:e.expiresAt||e.expires_at||s+300,description:e.description}}async function ue(c,e,t){let s=c.nonce.length===64?`0x${c.nonce}`:j(),a=BigInt(Math.floor(Date.now()/1e3))-60n,i=BigInt(c.expiresAt),{domain:r,message:o}=q({fromAddress:t,toAddress:c.recipient,value:c.amount,validAfter:a,validBefore:i,nonce:s,chainId:c.chainId}),d=await e.signTransferAuthorization(r,o),g={x402Version:1,scheme:"exact",network:c.chainId===8453?"base":"base-sepolia",payload:{signature:d,authorization:{from:t,to:c.recipient,value:c.amount.toString(),validAfter:a.toString(),validBefore:i.toString(),nonce:s}}};return btoa(JSON.stringify(g))}function ge(c){return Date.now()/1e3>c.expiresAt}function F(c){return Number(c.amount)/1e6}var Ne="0.11.0",_=process.env.MIXRPAY_BASE_URL||"https://mixr.network",gt="https://x402.org/facilitator",Le=3e4,me={BASE_MAINNET:{chainId:8453,name:"Base",isTestnet:false},BASE_SEPOLIA:{chainId:84532,name:"Base Sepolia",isTestnet:true}},he={debug:0,info:1,warn:2,error:3,none:4},W=class{level;prefix;constructor(e="none",t="[MixrPay]"){this.level=e,this.prefix=t;}setLevel(e){this.level=e;}shouldLog(e){return he[e]>=he[this.level]}debug(...e){this.shouldLog("debug")&&console.log(`${this.prefix} \u{1F50D}`,...e);}info(...e){this.shouldLog("info")&&console.log(`${this.prefix} \u2139\uFE0F`,...e);}warn(...e){this.shouldLog("warn")&&console.warn(`${this.prefix} \u26A0\uFE0F`,...e);}error(...e){this.shouldLog("error")&&console.error(`${this.prefix} \u274C`,...e);}payment(e,t,s){if(this.shouldLog("info")){let n=s?` for "${s}"`:"";console.log(`${this.prefix} \u{1F4B8} Paid $${e.toFixed(4)} to ${t.slice(0,10)}...${n}`);}}},ye=class c{sessionKey;walletAddress;maxPaymentUsd;onPayment;baseUrl;timeout;logger;payments=[];totalSpentUsd=0;sessionKeyInfo;sessionKeyInfoFetchedAt;allowlist;allowlistFetchedAt;selfCustodyAddress;selfCustodyKey;agentInstanceId;apiKey;sessionKeyId;constructor(e){this.validateConfig(e),this.sessionKey=O.fromString(e.sessionKey),this.walletAddress=e.walletAddress||this.sessionKey.address,this.maxPaymentUsd=e.maxPaymentUsd,this.onPayment=e.onPayment,this.baseUrl=(e.baseUrl||_).replace(/\/$/,""),this.timeout=e.timeout||Le,e.apiKey&&(this.apiKey=e.apiKey),e.sessionKeyId&&(this.sessionKeyId=e.sessionKeyId),this.logger=new W(e.logLevel||"none"),this.logger.debug("AgentWallet initialized",{walletAddress:this.walletAddress,isTestnet:this.isTestnet(),maxPaymentUsd:this.maxPaymentUsd,hasApiKey:!!this.apiKey,hasSessionKeyId:!!this.sessionKeyId});}validateConfig(e){if(!e.sessionKey)throw new x("Session key is required. Get one from the wallet owner at https://mixrpay.com/manage/invites");let t=e.sessionKey.trim();if(!t.startsWith("sk_live_")&&!t.startsWith("sk_test_")){let a=t.slice(0,8);throw new x(`Invalid session key prefix. Expected 'sk_live_' (mainnet) or 'sk_test_' (testnet), got '${a}'`)}let s=72;if(t.length!==s)throw new x(`Invalid session key length. Expected ${s} characters, got ${t.length}. Make sure you copied the complete key.`);let n=t.slice(8);if(!/^[0-9a-fA-F]+$/.test(n))throw new x("Invalid session key format. The key should contain only hexadecimal characters after the prefix.");if(e.maxPaymentUsd!==void 0){if(e.maxPaymentUsd<=0)throw new l("maxPaymentUsd must be a positive number");e.maxPaymentUsd>1e4&&this.logger?.warn("maxPaymentUsd is very high ($"+e.maxPaymentUsd+"). Consider using a lower limit for safety.");}}async fetchAllowlist(){if(this.allowlist!==void 0&&this.allowlistFetchedAt&&Date.now()-this.allowlistFetchedAt<3e5)return this.allowlist;try{let t=await this.getSessionKeyInfo();return this.allowlist=t.allowedMerchants||[],this.allowlistFetchedAt=Date.now(),this.logger.debug("Fetched allowlist",{patterns:this.allowlist.length,allowAll:this.allowlist.length===0}),this.allowlist}catch(t){return this.logger.warn("Failed to fetch allowlist, allowing all merchants",{error:t}),this.allowlist=[],this.allowlistFetchedAt=Date.now(),this.allowlist}}async validateMerchantAllowed(e,t){let s=await this.fetchAllowlist();if(s.length===0)return;if(!this.matchesAllowlist(e,s,t))throw new E(e,s)}matchesAllowlist(e,t,s){for(let n of t)if(this.matchPattern(e,n,s))return true;return false}matchPattern(e,t,s){return s==="url"?this.matchUrlPattern(e,t):this.matchToolPattern(e,t)}matchUrlPattern(e,t){let s;try{e.includes("://")?s=new URL(e).hostname.toLowerCase():s=e.toLowerCase();}catch{return false}let a=t.toLowerCase().trim();if(a.includes("://"))try{a=new URL(a).hostname;}catch{}if(s===a)return true;if(a.startsWith("*.")){let i=a.substring(2);if(s.endsWith(`.${i}`)&&s!==i)return true}return false}matchToolPattern(e,t){let s=e.toLowerCase().trim(),n=t.toLowerCase().trim();if(s===n)return true;if(n.endsWith("/*")){let a=n.substring(0,n.length-2);if(s.startsWith(`${a}/`))return true}return false}static async register(e){let{privateKey:t,name:s}=e,n=(e.baseUrl||_).replace(/\/$/,""),i=privateKeyToAccount(t).address,r=await fetch(`${n}/api/v1/agent/challenge?wallet=${i}&action=register`);if(!r.ok){let y=await r.json().catch(()=>({}));throw new l(y.error||`Failed to get challenge: ${r.status}`)}let{challenge:o,message:d}=await r.json(),g=await signMessage({message:d,privateKey:t}),u=await fetch(`${n}/api/v1/agent/register`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({challenge:o,external_wallet:i,signature:g,name:s})});if(!u.ok){let y=await u.json().catch(()=>({})),f=y.error||`Registration failed with status ${u.status}`,h=y.request_id,w=(y.code||"").toLowerCase(),b="";u.status===503?b=" The service may be temporarily unavailable. Please try again later.":u.status===500?b=" This is a server error. Please contact support with the request ID.":(w==="missing_challenge"||w==="missing_signature")&&(b=" This may indicate an SDK bug. Please update to the latest version.");let $=h?`${f} (request_id: ${h})${b}`:`${f}${b}`;throw new l($)}let p=await u.json();return {userId:p.user_id,depositAddress:p.deposit_address}}static async checkServerHealth(e){let t=(e||_).replace(/\/$/,"");try{let s=await fetch(`${t}/api/health/ready?details=true`);if(!s.ok)return {healthy:!1,database:"unknown",agentRegistrationAvailable:!1,walletServiceConfigured:!1,error:`Health check failed with status ${s.status}`};let n=await s.json();return {healthy:n.status==="ready",database:n.database||"unknown",agentRegistrationAvailable:n.services?.agentRegistration?.available??!1,walletServiceConfigured:n.services?.wallet?.configured??!1}}catch(s){return {healthy:false,database:"unreachable",agentRegistrationAvailable:false,walletServiceConfigured:false,error:s instanceof Error?s.message:"Failed to reach server"}}}static async getSessionKey(e){let{privateKey:t,spendingLimitUsd:s,maxPerTxUsd:n,maxDailyUsd:a,durationDays:i}=e,r=(e.baseUrl||_).replace(/\/$/,""),d=privateKeyToAccount(t).address,g=await fetch(`${r}/api/v1/agent/challenge?wallet=${d}&action=session-key`);if(!g.ok){let w=await g.json().catch(()=>({}));throw new l(w.error||`Failed to get challenge: ${g.status}`)}let{challenge:u,message:p}=await g.json(),y=await signMessage({message:p,privateKey:t}),f=await fetch(`${r}/api/v1/agent/session-key`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({challenge:u,external_wallet:d,signature:y,spending_limit_usd:s,max_per_tx_usd:n,max_daily_usd:a,duration_days:i})});if(!f.ok){let w=await f.json().catch(()=>({}));throw new l(w.error||`Session key creation failed: ${f.status}`)}let h=await f.json();return {sessionKey:h.session_key,address:h.address,sessionKeyId:h.session_key_id,expiresAt:new Date(h.expires_at),limits:{maxTotalUsd:h.limits.max_total_usd,maxPerTxUsd:h.limits.max_per_tx_usd,maxDailyUsd:h.limits.max_daily_usd}}}static async getStatus(e){let{privateKey:t}=e,s=(e.baseUrl||_).replace(/\/$/,""),a=privateKeyToAccount(t).address,i=await fetch(`${s}/api/v1/agent/challenge?wallet=${a}&action=status`);if(!i.ok){let p=await i.json().catch(()=>({}));throw new l(p.error||`Failed to get challenge: ${i.status}`)}let{challenge:r,message:o}=await i.json(),d=await signMessage({message:o,privateKey:t}),g=await fetch(`${s}/api/v1/agent/status?challenge=${r}&external_wallet=${a}&signature=${encodeURIComponent(d)}`);if(!g.ok){let p=await g.json().catch(()=>({}));throw new l(p.error||`Failed to get status: ${g.status}`)}let u=await g.json();return {depositAddress:u.deposit_address,balanceUsd:u.balance_usd,activeSessions:u.active_sessions.map(p=>({id:p.id,expiresAt:new Date(p.expires_at),totalSpentUsd:p.total_spent_usd,remainingUsd:p.remaining_usd,maxTotalUsd:p.max_total_usd})),totalSpentUsd:u.total_spent_usd}}static async revokeSessionKey(e){let{privateKey:t,sessionKeyId:s}=e,n=(e.baseUrl||_).replace(/\/$/,""),i=privateKeyToAccount(t).address,r=await fetch(`${n}/api/v1/agent/challenge?wallet=${i}&action=revoke`);if(!r.ok){let p=await r.json().catch(()=>({}));throw new l(p.error||`Failed to get challenge: ${r.status}`)}let{challenge:o,message:d}=await r.json(),g=await signMessage({message:d,privateKey:t}),u=await fetch(`${n}/api/v1/agent/session-key/revoke`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({challenge:o,external_wallet:i,signature:g,session_key_id:s})});if(!u.ok){let p=await u.json().catch(()=>({}));throw new l(p.error||`Revocation failed: ${u.status}`)}return true}static async withdraw(e){let{privateKey:t,amountUsd:s}=e,n=(e.baseUrl||_).replace(/\/$/,""),i=privateKeyToAccount(t).address,r=await fetch(`${n}/api/v1/agent/challenge?wallet=${i}&action=withdraw`);if(!r.ok){let y=await r.json().catch(()=>({}));throw new l(y.error||`Failed to get challenge: ${r.status}`)}let{challenge:o,message:d}=await r.json(),g=await signMessage({message:d,privateKey:t}),u=await fetch(`${n}/api/v1/agent/withdraw`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({challenge:o,external_wallet:i,signature:g,to_address:i,amount_usd:s})});if(!u.ok){let y=await u.json().catch(()=>({}));throw new l(y.error||`Withdrawal failed: ${u.status}`)}let p=await u.json();return {txHash:p.tx_hash,amountUsd:p.amount_usd,remainingBalanceUsd:p.remaining_balance_usd}}static async claimInvite(e){let{inviteCode:t,privateKey:s}=e,n=(e.baseUrl||_).replace(/\/$/,""),i=privateKeyToAccount(s).address,r=await fetch(`${n}/api/v1/agent/challenge?wallet=${i}&action=claim-invite`);if(!r.ok){let y=await r.json().catch(()=>({}));throw new l(y.error||`Failed to get challenge: ${r.status}`)}let{challenge:o,message:d}=await r.json(),g=await signMessage({message:d,privateKey:s}),u=await fetch(`${n}/api/v1/agent/claim-invite`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({invite_code:t,challenge:o,agent_wallet_address:i,signature:g})});if(!u.ok){let f=(await u.json().catch(()=>({}))).error||`Failed to claim invite: ${u.status}`,h="";throw u.status===404?h=" The invite code may be invalid or misspelled.":u.status===400&&(f.includes("already claimed")?h=" This invite has already been used by another agent.":f.includes("expired")?h=" Ask the wallet owner to create a new invite.":f.includes("revoked")&&(h=" The wallet owner has revoked this invite.")),new l(`${f}${h}`)}let p=await u.json();return {sessionKey:p.session_key,address:p.address,sessionKeyId:p.session_key_id,expiresAt:new Date(p.expires_at),limits:{budgetUsd:p.limits.budget_usd,budgetPeriod:p.limits.budget_period,maxPerTxUsd:p.limits.max_per_tx_usd},allowedMerchants:p.allowed_merchants||[],inviterName:p.inviter_name||"Anonymous"}}static async activate(e,t){let s=(t?.baseUrl||_).replace(/\/$/,""),n=new c({sessionKey:e,baseUrl:s}),a=await n.getSessionAuthHeaders(),i=await fetch(`${s}/api/v2/agent/activate`,{method:"POST",headers:{"Content-Type":"application/json",...a}});if(!i.ok){let o=await i.json().catch(()=>({}));throw new l(o.error||`Activation failed: ${i.status}`)}let r=await i.json();return {wallet:n,budget:{maxTotalUsd:r.budget.max_total_usd,maxDailyUsd:r.budget.max_daily_usd,maxPerTxUsd:r.budget.max_per_tx_usd,spentUsd:r.budget.spent_usd,remainingUsd:r.budget.remaining_usd},capabilities:{executeTransactions:r.capabilities.execute_transactions,gasSponsored:r.capabilities.gas_sponsored,batchedTx:r.capabilities.batched_tx},skills:r.skills||[],tools:r.tools||[],gatewayProviders:r.gateway_providers||[]}}static async connect(e){let t=(e?.baseUrl||process.env.MIXRPAY_BASE_URL||_).replace(/\/$/,""),s=e?.logLevel||"none",n=process.env.MIXRPAY_INSTANCE_ID;if(e?.sessionKey){let g=new c({sessionKey:e.sessionKey,sessionKeyId:e.sessionKeyId,baseUrl:t,logLevel:s,maxPaymentUsd:e?.maxPaymentUsd,onPayment:e?.onPayment});return n&&g.setAgentInstanceId(n),g}let a=process.env.MIXRPAY_SESSION_KEY;if(a){let g=process.env.MIXRPAY_SESSION_KEY_ID,u=new c({sessionKey:a,sessionKeyId:g,baseUrl:t,logLevel:s,maxPaymentUsd:e?.maxPaymentUsd,onPayment:e?.onPayment});return n&&u.setAgentInstanceId(n),u}let i=process.env.MIXRPAY_API_KEY||process.env.MIXRPAY_AGENT_TOKEN;if(i&&(i.startsWith("agt_live_")||i.startsWith("agt_test_")))return c.fromApiKey(i,{baseUrl:t,logLevel:s});let r=e?.accessCode||process.env.MIXRPAY_ACCESS_CODE;if(r)return c.fromAccessCode(r,{baseUrl:t,logLevel:s});let o=e?.masterKey||process.env.MIXRPAY_MASTER_KEY,d=e?.agentName||process.env.MIXRPAY_AGENT_NAME;if(o&&d)return c.fromMasterKey(o,d,{baseUrl:t,logLevel:s});try{let{loadCredentials:g}=await import('./credentials-ILS4YAGF.js'),u=g();if(u.success&&u.credentials.sessionKey){let p=new c({sessionKey:u.credentials.sessionKey,sessionKeyId:u.credentials.sessionKeyId,baseUrl:u.credentials.baseUrl||t,logLevel:s,maxPaymentUsd:e?.maxPaymentUsd,onPayment:e?.onPayment,apiKey:u.credentials.apiToken});return n&&p.setAgentInstanceId(n),p}if(u.success&&u.credentials.apiToken)return c.fromApiKey(u.credentials.apiToken,{baseUrl:t,logLevel:s});if(u.success&&u.credentials.masterKey&&u.credentials.defaultAgentName)return c.fromMasterKey(u.credentials.masterKey,u.credentials.defaultAgentName,{baseUrl:t,logLevel:s})}catch{}if(e?.interactive)return c.deviceFlowLogin({baseUrl:t,logLevel:s});throw new l(`No MixrPay credentials found. Options:
3
- 1. Set MIXRPAY_SESSION_KEY environment variable
4
- 2. Set MIXRPAY_API_KEY or MIXRPAY_AGENT_TOKEN environment variable (agt_live_xxx)
5
- 3. Set MIXRPAY_ACCESS_CODE environment variable (mixr-xxx)
6
- 4. Pass sessionKey or accessCode to connect()
7
- 5. Run \`npx mixrpay login\` to cache credentials
8
- 6. Use connect({ interactive: true }) for browser login`)}static async fromApiKey(e,t){let s=(t?.baseUrl||_).replace(/\/$/,"");if(!e.startsWith("agt_live_")&&!e.startsWith("agt_test_"))throw new l(`Invalid API key format. Expected 'agt_live_' or 'agt_test_' prefix, got '${e.slice(0,9)}...'`);let n=await fetch(`${s}/api/v2/agent/session-from-token`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`}});if(!n.ok){let o=await n.json().catch(()=>({}));throw new l(o.error||`Failed to exchange API key for session: ${n.status}`)}let a=await n.json(),i=a.session_key;if(!i)throw new l("No session_key in API response");let r=new c({sessionKey:i,baseUrl:s,logLevel:t?.logLevel});return r.setApiKey(e),a.agent_instance_id&&r.setAgentInstanceId(a.agent_instance_id),r}static async fromAccessCode(e,t){let s=(t?.baseUrl||_).replace(/\/$/,"");if(!e.startsWith("mixr-"))throw new l(`Invalid access code format. Expected 'mixr-' prefix, got '${e.slice(0,5)}...'`);let n=await fetch(`${s}/api/v2/agent/connect`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({code:e})});if(!n.ok){let g=await n.json().catch(()=>({})),u=(g.code||"").toLowerCase(),p="";throw n.status===404||u==="invalid_code"?p=" Check the code for typos or get a new one from the MixrPay dashboard.":n.status===400&&(u==="code_claimed"?p=" This code has already been used. Get a new code from the dashboard.":u==="code_expired"?p=" This code has expired. Get a new code from the dashboard.":u==="code_revoked"&&(p=" This code has been revoked by the owner.")),new l((g.error||`Failed to activate access code: ${n.status}`)+p)}let a=await n.json(),i=a.session_key,r=a.token,o=a.agent_id;if(!i)throw new l("No session_key in access code response");try{let{saveCredentials:g}=await import('./credentials-ILS4YAGF.js');g({sessionKey:i,apiToken:r,baseUrl:s});}catch{}let d=new c({sessionKey:i,baseUrl:s,logLevel:t?.logLevel});return r&&(d.apiKey=r),o&&(d.agentInstanceId=o),d}static async fromMasterKey(e,t,s){let n=(s?.baseUrl||_).replace(/\/$/,"");if(!e.startsWith("mk_live_")&&!e.startsWith("mk_test_"))throw new l("Invalid master key format. Expected 'mk_live_' or 'mk_test_' prefix.");let a=await fetch(`${n}/api/v2/master-keys/session`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify({agent_name:t})});if(!a.ok){let g=await a.json().catch(()=>({}));throw a.status===404?new l(`Agent '${t}' not found. Use the MixrPay dashboard to create it.`):new l(g.error||`Failed to get session from master key: ${a.status}`)}let i=await a.json(),r=i.session_key,o=i.session_key_id;if(!r)throw new l("No session_key in master key response");let d=new c({sessionKey:r,sessionKeyId:o,baseUrl:n,logLevel:s?.logLevel});return i.agent?.id&&(d.agentInstanceId=i.agent.id),d}static async deviceFlowLogin(e){let t=(e?.baseUrl||_).replace(/\/$/,""),s=await fetch(`${t}/api/v2/auth/device/authorize`,{method:"POST",headers:{"Content-Type":"application/json"}});if(!s.ok){let y=await s.json().catch(()=>({}));throw new l(y.error||`Device flow initiation failed: ${s.status}`)}let n=await s.json(),{device_code:a,user_code:i,verification_uri:r,verification_uri_complete:o,expires_in:d,interval:g}=n;console.log(`
2
+ import {fileURLToPath}from'url';import {join,dirname}from'path';import {privateKeyToAccount,signMessage,generatePrivateKey,signTypedData}from'viem/accounts';import {z as z$1}from'zod';import {createWalletClient,http,parseUnits,encodeFunctionData}from'viem';import {base}from'viem/chains';import {existsSync,readFileSync,mkdirSync,writeFileSync,chmodSync}from'fs';import {homedir}from'os';var l=class extends Error{code;retryAfterMs;constructor(e,t="MIXRPAY_ERROR",s){super(e),this.name="MixrPayError",this.code=t,this.retryAfterMs=s,Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor);}isRetryable(){return false}},v=class extends l{required;available;topUpUrl;constructor(e,t){let s=e-t;super(`Insufficient balance: need $${e.toFixed(2)}, have $${t.toFixed(2)} (short $${s.toFixed(2)}). Top up your wallet to continue.`,"INSUFFICIENT_BALANCE"),this.name="InsufficientBalanceError",this.required=e,this.available=t,this.topUpUrl="https://mixr.network/manage/wallet";}},R=class extends l{expiredAt;constructor(e){super(`Session key expired at ${e}. Request a new session key from the wallet owner at https://mixrpay.com/manage/invites`,"SESSION_KEY_EXPIRED"),this.name="SessionKeyExpiredError",this.expiredAt=e;}},T=class extends l{limitType;limit;attempted;constructor(e,t,s){let a={per_tx:"Per-transaction",daily:"Daily",total:"Total",client_max:"Client-side"}[e]||e,i=e==="daily"?"Wait until tomorrow or request a higher limit.":e==="client_max"?"Increase maxPaymentUsd in your AgentWallet configuration.":"Request a new session key with a higher limit.";super(`${a} spending limit exceeded: limit is $${t.toFixed(2)}, attempted $${s.toFixed(2)}. ${i}`,"SPENDING_LIMIT_EXCEEDED"),this.name="SpendingLimitExceededError",this.limitType=e,this.limit=t,this.attempted=s;}isRetryable(){return this.limitType==="daily"}},A=class extends l{reason;txHash;constructor(e,t){let s=`Payment failed: ${e}`;t&&(s+=` (tx: ${t} - check on basescan.org)`),super(s,"PAYMENT_FAILED"),this.name="PaymentFailedError",this.reason=e,this.txHash=t;}isRetryable(){return true}},S=class extends l{reason;constructor(e="Invalid session key format"){super(`${e}. Session keys should be in format: sk_live_<64 hex chars> or sk_test_<64 hex chars>. Get one from https://mixrpay.com/manage/invites`,"INVALID_SESSION_KEY"),this.name="InvalidSessionKeyError",this.reason=e;}},P=class extends l{reason;constructor(e){super(`x402 protocol error: ${e}. This may indicate a server configuration issue. If the problem persists, contact the API provider.`,"X402_PROTOCOL_ERROR"),this.name="X402ProtocolError",this.reason=e;}isRetryable(){return true}},D=class extends l{sessionId;expiredAt;constructor(e,t){super(`Session ${e} has expired${t?` at ${t}`:""}. A new session will be created automatically on your next request.`,"SESSION_EXPIRED"),this.name="SessionExpiredError",this.sessionId=e,this.expiredAt=t;}},U=class extends l{sessionId;limit;requested;remaining;constructor(e,t,s,n){super(`Session spending limit exceeded: limit is $${e.toFixed(2)}, requested $${t.toFixed(2)}, remaining $${s.toFixed(2)}. Create a new session with a higher limit to continue.`,"SESSION_LIMIT_EXCEEDED"),this.name="SessionLimitExceededError",this.sessionId=n,this.limit=e,this.requested=t,this.remaining=s;}},I=class extends l{sessionId;constructor(e){super(`Session ${e} not found. It may have been deleted or never existed. Create a new session with getOrCreateSession().`,"SESSION_NOT_FOUND"),this.name="SessionNotFoundError",this.sessionId=e;}},C=class extends l{sessionId;reason;constructor(e,t){super(`Session ${e} has been revoked${t?`: ${t}`:""}. Create a new session with getOrCreateSession().`,"SESSION_REVOKED"),this.name="SessionRevokedError",this.sessionId=e,this.reason=t;}},E=class extends l{attempted;allowedPatterns;constructor(e,t){let s=t.slice(0,3).join(", "),n=t.length>3?"...":"";super(`Payment to "${e}" not allowed. Session allowlist: ${s}${n}. Update the session allowlist or create a new session.`,"MERCHANT_NOT_ALLOWED"),this.name="MerchantNotAllowedError",this.attempted=e,this.allowedPatterns=t;}};var xe={8453:"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",84532:"0x036CbD53842c5426634e7929541eC2318f3dCF7e"},Se={name:"USD Coin",version:"2"},Ae={TransferWithAuthorization:[{name:"from",type:"address"},{name:"to",type:"address"},{name:"value",type:"uint256"},{name:"validAfter",type:"uint256"},{name:"validBefore",type:"uint256"},{name:"nonce",type:"bytes32"}]},O=class c{privateKey;account;address;isTest;constructor(e,t){this.privateKey=e,this.account=privateKeyToAccount(e),this.address=this.account.address,this.isTest=t;}toString(){return `${this.isTest?"sk_test_":"sk_live_"}${this.privateKey.slice(2)}`}get privateKeyHex(){return this.privateKey.slice(2)}get rawPrivateKey(){return this.privateKey}static fromString(e){let t=/^sk_(live|test)_([a-fA-F0-9]{64})$/,s=e.match(t);if(!s)throw new S("Session key must be in format sk_live_{64_hex} or sk_test_{64_hex}");let n=s[1],a=s[2];try{let i=`0x${a}`;return new c(i,n==="test")}catch(i){throw new S(`Failed to decode session key: ${i}`)}}async signTransferAuthorization(e,t){return signTypedData({privateKey:this.privateKey,domain:e,types:Ae,primaryType:"TransferWithAuthorization",message:t})}async signMessage(e){return signMessage({privateKey:this.privateKey,message:e})}getDefaultChainId(){return this.isTest?84532:8453}};function q(c){let e=xe[c.chainId];if(!e)throw new Error(`USDC not supported on chain ${c.chainId}`);let t={...Se,chainId:c.chainId,verifyingContract:e},s={from:c.fromAddress,to:c.toAddress,value:c.value,validAfter:c.validAfter,validBefore:c.validBefore,nonce:c.nonce};return {domain:t,message:s}}function j(){let c=new Uint8Array(32);return crypto.getRandomValues(c),`0x${Array.from(c).map(e=>e.toString(16).padStart(2,"0")).join("")}`}function ke(c,e){return `MixrPay:${c}:${e.toLowerCase()}`}async function B(c){let e=Date.now(),t=ke(e,c.address),s=await c.signMessage(t);return {address:c.address,timestamp:e,signature:s}}var J=z$1.object({query:z$1.string().describe('Search query (e.g. "web scraping", "email", "database")')}),G=z$1.object({tool_name:z$1.string().describe('Tool name in "merchant/tool" format'),arguments:z$1.record(z$1.unknown()).optional().describe("Arguments to pass to the tool")}),X=z$1.object({url:z$1.string().url().describe("The merchant API URL to call"),merchant_public_key:z$1.string().describe("The merchant's MixrPay public key (pk_live_... or pk_test_...)"),method:z$1.enum(["GET","POST","PUT","PATCH","DELETE"]).default("POST").describe("HTTP method"),body:z$1.unknown().optional().describe("Request body (will be JSON-serialized)"),price_usd:z$1.number().optional().describe("Expected price in USD for client-side validation")}),z=z$1.object({skill_id:z$1.string().describe("The skill ID to execute"),input:z$1.record(z$1.unknown()).optional().describe("Input parameters for the skill")}),Y=z$1.object({skill_id:z$1.string().describe("The skill ID to check")}),V=z$1.object({glama_id:z$1.string().describe('Glama server ID (e.g. "notion-mcp")'),glama_namespace:z$1.string().describe('Glama namespace (e.g. "notion")'),glama_slug:z$1.string().describe('Glama slug (e.g. "notion-mcp")'),tool_name:z$1.string().describe("Human-readable name for the tool"),tool_description:z$1.string().optional().describe("Optional description"),env_vars:z$1.record(z$1.string()).optional().describe("Environment variables for the MCP server (e.g. API keys)"),ttl_hours:z$1.number().min(1).max(168).optional().describe("Time-to-live in hours (default: 24, max: 168)")}),Z=z$1.object({status:z$1.enum(["provisioning","active","stopped","expired"]).optional().describe("Filter by status")}),Q=z$1.object({instance_id:z$1.string().describe("The instance ID to stop")}),ee=z$1.object({to:z$1.string().describe("Recipient address (0x...)"),amount_usdc:z$1.number().positive().describe("Amount in USDC (e.g. 10.5)")}),te=z$1.object({name:z$1.string().describe("Name for the child agent"),budget_usd:z$1.number().positive().describe("Budget to delegate in USD"),budget_period:z$1.enum(["daily","monthly","total"]).default("total").describe("Budget period"),max_per_tx_usd:z$1.number().positive().optional().describe("Max per-transaction limit in USD"),expires_in_days:z$1.number().min(1).max(365).optional().describe("Expiry in days (default: 30)")}),se=z$1.object({title:z$1.string().describe("Task title"),description:z$1.string().describe("Detailed task description"),budget_usd:z$1.number().positive().describe("Budget for the task in USD"),skills_required:z$1.array(z$1.string()).optional().describe("Required skill IDs")}),ne=z$1.object({status:z$1.string().optional().describe('Filter by status (e.g. "open", "in_progress")'),limit:z$1.number().min(1).max(100).optional().describe("Number of results (default: 20)")});function ae(c){let e=[{name:"check_balance",title:"Check Balance",description:"Get the USDC balance of the wallet on Base.",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:null,handler:async()=>({balanceUsd:await c.getBalance(),network:c.isTestnet()?"base-sepolia":"base"})},{name:"get_spending_stats",title:"Get Spending Stats",description:"Get session key spending limits and current usage (total spent, remaining daily/total limits, expiry).",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:null,handler:async()=>c.getSpendingStats()},{name:"get_session_info",title:"Get Session Info",description:"Get detailed session key information including limits, usage, expiry, and allowed merchants.",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:null,handler:async()=>c.getSessionKeyInfo(true)},{name:"run_diagnostics",title:"Run Diagnostics",description:"Run a full health check on the wallet: API connectivity, session key validity, balance, and latency.",annotations:{readOnlyHint:true,openWorldHint:true},inputSchema:null,handler:async()=>c.runDiagnostics()},{name:"list_tools",title:"List Marketplace Tools",description:"Browse all available paid API tools on the MixrPay marketplace. Each tool includes pricing and description.",annotations:{readOnlyHint:true,openWorldHint:true},inputSchema:null,handler:async()=>c.listTools()},{name:"search_tools",title:"Search Tools",description:"Search the Glama MCP server directory for tools by keyword.",annotations:{readOnlyHint:true,openWorldHint:true},inputSchema:J,handler:async s=>{let{query:n}=J.parse(s);return c.searchGlamaDirectory(n)}},{name:"call_tool",title:"Call Marketplace Tool",description:'Call a paid API tool on the MixrPay marketplace. Payment is automatic from the wallet. Tool names are in "merchant/tool" format (e.g. "firecrawl/scrape").',annotations:{readOnlyHint:false,openWorldHint:true},inputSchema:G,handler:async s=>{let{tool_name:n,arguments:a}=G.parse(s);return c.callTool(n,a||{})}},{name:"call_merchant_api",title:"Call Merchant API",description:"Call any merchant API endpoint with x402 payment. The wallet handles authentication and payment automatically.",annotations:{readOnlyHint:false,openWorldHint:true},inputSchema:X,handler:async s=>{let{url:n,merchant_public_key:a,method:i,body:r,price_usd:o}=X.parse(s),d=await c.callMerchantApi({url:n,merchantPublicKey:a,method:i,body:r,priceUsd:o}),g=await d.json().catch(()=>d.text());return {status:d.status,data:g}}},{name:"list_skills",title:"List Skills",description:"List all available skills (pre-built integrations) that the wallet can use.",annotations:{readOnlyHint:true,openWorldHint:true},inputSchema:null,handler:async()=>c.listSkills()},{name:"use_skill",title:"Use Skill",description:"Execute a skill by ID. Skills are pre-built integrations (e.g. web scraping, email sending).",annotations:{readOnlyHint:false,openWorldHint:true},inputSchema:z,handler:async s=>{let{skill_id:n,input:a}=z.parse(s);return c.useSkill(n,{input:a})}},{name:"get_skill_status",title:"Get Skill Status",description:"Check the status and configuration of a specific skill.",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:Y,handler:async s=>{let{skill_id:n}=Y.parse(s);return c.getSkillStatus(n)}},{name:"deploy_jit_mcp",title:"Deploy JIT MCP Server",description:"Deploy a just-in-time MCP server from the Glama directory. Creates a temporary hosted MCP server instance.",annotations:{readOnlyHint:false,openWorldHint:true},inputSchema:V,handler:async s=>{let{glama_id:n,glama_namespace:a,glama_slug:i,tool_name:r,tool_description:o,env_vars:d,ttl_hours:g}=V.parse(s);return c.deployJitMcp({glamaId:n,glamaNamespace:a,glamaSlug:i,toolName:r,toolDescription:o,envVars:d,ttlHours:g})}},{name:"list_jit_instances",title:"List JIT Instances",description:"List all deployed JIT MCP server instances.",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:Z,handler:async s=>{let{status:n}=Z.parse(s);return c.listJitInstances(n?{status:n}:void 0)}},{name:"stop_jit_instance",title:"Stop JIT Instance",description:"Stop a running JIT MCP server instance.",annotations:{readOnlyHint:false,destructiveHint:true,openWorldHint:false},inputSchema:Q,handler:async s=>{let{instance_id:n}=Q.parse(s);return await c.stopJitInstance(n),{success:true,instance_id:n}}},{name:"transfer_usdc",title:"Transfer USDC",description:"Transfer USDC from the self-custody wallet to another address on Base. Only available when the wallet has a self-custody wallet (AGENT_WALLET_KEY set).",annotations:{readOnlyHint:false,destructiveHint:true,openWorldHint:true},inputSchema:ee,handler:async s=>{let{to:n,amount_usdc:a}=ee.parse(s);if(!await c.hasSelfCustodyWallet())throw new Error("No self-custody wallet configured. Set AGENT_WALLET_KEY to enable transfers.");return {success:true,txHash:await c.transferUSDC({to:n,amountUsdc:a}),to:n,amountUsdc:a}}},{name:"get_budget",title:"Get Available Budget",description:"Get the available delegation budget including remaining amount, whether spawning children is possible, and budget limits.",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:null,handler:async()=>c.getAvailableBudget()},{name:"spawn_child",title:"Spawn Child Session",description:"Create a child invite with a delegated budget from this wallet. Returns an invite code that another agent can claim.",annotations:{readOnlyHint:false,openWorldHint:false},inputSchema:te,handler:async s=>{let{name:n,budget_usd:a,budget_period:i,max_per_tx_usd:r,expires_in_days:o}=te.parse(s);return c.spawnChildInvite({name:n,budgetUsd:a,budgetPeriod:i,maxPerTxUsd:r,expiresInDays:o})}},{name:"list_children",title:"List Child Sessions",description:"List all child sessions (agents) spawned from this wallet.",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:null,handler:async()=>c.listChildSessions()},{name:"create_task",title:"Create Task",description:"Create a new task on the MixrPay marketplace for other agents to complete.",annotations:{readOnlyHint:false,openWorldHint:true},inputSchema:se,handler:async s=>{let{title:n,description:a,budget_usd:i,skills_required:r}=se.parse(s);return c.createTask({title:n,description:a,budgetUsd:i,skillsRequired:r})}},{name:"list_tasks",title:"List Tasks",description:"Browse available tasks on the MixrPay marketplace.",annotations:{readOnlyHint:true,openWorldHint:true},inputSchema:ne,handler:async s=>{let{status:n,limit:a}=ne.parse(s);return c.listTasks({status:n,limit:a})}}];return {definitions:e,execute:async(s,n)=>{let a=e.find(i=>i.name===s);if(!a)throw new Error(`Unknown tool: ${s}`);try{let i=await a.handler(n);return JSON.stringify(i,null,2)}catch(i){let r=i instanceof Error?i.message:String(i);throw new Error(r)}}}}function ie(c){if(c instanceof z$1.ZodObject){let e=c._def.shape(),t={},s=[];for(let[n,a]of Object.entries(e)){let i=a;t[n]=K(i),!(i instanceof z$1.ZodOptional)&&!(i instanceof z$1.ZodDefault)&&s.push(n);}return {type:"object",properties:t,...s.length>0?{required:s}:{}}}return {type:"object",properties:{}}}function K(c){let e=c;e instanceof z$1.ZodOptional&&(e=e._def.innerType),e instanceof z$1.ZodDefault&&(e=e._def.innerType);let t=c._def.description;if(e instanceof z$1.ZodString)return {type:"string",...t&&{description:t}};if(e instanceof z$1.ZodNumber)return {type:"number",...t&&{description:t}};if(e instanceof z$1.ZodBoolean)return {type:"boolean",...t&&{description:t}};if(e instanceof z$1.ZodEnum)return {type:"string",enum:e._def.values,...t&&{description:t}};if(e instanceof z$1.ZodArray)return {type:"array",items:K(e._def.type),...t&&{description:t}};if(e instanceof z$1.ZodRecord)return {type:"object",additionalProperties:K(e._def.valueType),...t&&{description:t}};if(e instanceof z$1.ZodObject){let s=e._def.shape(),n={};for(let[a,i]of Object.entries(s))n[a]=K(i);return {type:"object",properties:n,...t&&{description:t}}}return e instanceof z$1.ZodUnknown?{...t&&{description:t}}:{...t&&{description:t}}}var Ce="0.9.5",re=".config/mixrpay",$e="wallet.json";function oe(){let c=process.env.MIXRPAY_WORKSPACE_DIR||process.env.OPENCLAW_WORKSPACE_DIR;return c?join(c,re):join(homedir(),re)}function N(){return join(oe(),$e)}async function le(c,e){let t=oe(),s=N();existsSync(t)||mkdirSync(t,{recursive:true,mode:448});let n={address:e.toLowerCase(),privateKey:c,createdAt:new Date().toISOString(),sdkVersion:Ce};writeFileSync(s,JSON.stringify(n,null,2),{encoding:"utf-8",mode:384});try{chmodSync(s,384);}catch{}}async function L(){let c=process.env.MIXRPAY_WALLET_KEY;if(c){if(c.startsWith("0x")&&c.length===66)return c;if(c.length===64)return `0x${c}`;console.warn("[MixrPay] MIXRPAY_WALLET_KEY has invalid format, ignoring");}let e=N();if(!existsSync(e))return null;try{let t=readFileSync(e,"utf-8"),s=JSON.parse(t);return !s.privateKey||!s.privateKey.startsWith("0x")?(console.warn("[MixrPay] Wallet file has invalid format"),null):s.privateKey}catch(t){return console.warn("[MixrPay] Failed to read wallet file:",t),null}}async function ce(){let c=process.env.MIXRPAY_WALLET_KEY;return c&&(c.length===64||c.startsWith("0x")&&c.length===66)?true:existsSync(N())}async function de(c){let e=null,t=c.headers.get("X-Payment-Required");if(t)try{e=JSON.parse(t);}catch{}if(!e){let n=c.headers.get("WWW-Authenticate");if(n?.startsWith("X-402 "))try{let a=n.slice(6);e=JSON.parse(atob(a));}catch{}}if(!e)try{e=await c.json();}catch{}if(!e)throw new P("Could not parse payment requirements from 402 response");if(!e.recipient)throw new P("Missing recipient in payment requirements");if(!e.amount)throw new P("Missing amount in payment requirements");let s=Math.floor(Date.now()/1e3);return {recipient:e.recipient,amount:BigInt(e.amount),currency:e.currency||"USDC",chainId:e.chainId||e.chain_id||8453,facilitatorUrl:e.facilitatorUrl||e.facilitator_url||"https://x402.org/facilitator",nonce:e.nonce||j().slice(2),expiresAt:e.expiresAt||e.expires_at||s+300,description:e.description}}async function ue(c,e,t){let s=c.nonce.length===64?`0x${c.nonce}`:j(),a=BigInt(Math.floor(Date.now()/1e3))-60n,i=BigInt(c.expiresAt),{domain:r,message:o}=q({fromAddress:t,toAddress:c.recipient,value:c.amount,validAfter:a,validBefore:i,nonce:s,chainId:c.chainId}),d=await e.signTransferAuthorization(r,o),g={x402Version:1,scheme:"exact",network:c.chainId===8453?"base":"base-sepolia",payload:{signature:d,authorization:{from:t,to:c.recipient,value:c.amount.toString(),validAfter:a.toString(),validBefore:i.toString(),nonce:s}}};return btoa(JSON.stringify(g))}function ge(c){return Date.now()/1e3>c.expiresAt}function F(c){return Number(c.amount)/1e6}var Ne="0.11.0",_=process.env.MIXRPAY_BASE_URL||"https://mixr.network",gt="https://x402.org/facilitator",Le=3e4,me={BASE_MAINNET:{chainId:8453,name:"Base",isTestnet:false},BASE_SEPOLIA:{chainId:84532,name:"Base Sepolia",isTestnet:true}},he={debug:0,info:1,warn:2,error:3,none:4},W=class{level;prefix;constructor(e="none",t="[MixrPay]"){this.level=e,this.prefix=t;}setLevel(e){this.level=e;}shouldLog(e){return he[e]>=he[this.level]}debug(...e){this.shouldLog("debug")&&console.log(`${this.prefix} \u{1F50D}`,...e);}info(...e){this.shouldLog("info")&&console.log(`${this.prefix} \u2139\uFE0F`,...e);}warn(...e){this.shouldLog("warn")&&console.warn(`${this.prefix} \u26A0\uFE0F`,...e);}error(...e){this.shouldLog("error")&&console.error(`${this.prefix} \u274C`,...e);}payment(e,t,s){if(this.shouldLog("info")){let n=s?` for "${s}"`:"";console.log(`${this.prefix} \u{1F4B8} Paid $${e.toFixed(4)} to ${t.slice(0,10)}...${n}`);}}},ye=class c{sessionKey;walletAddress;maxPaymentUsd;onPayment;baseUrl;timeout;logger;payments=[];totalSpentUsd=0;sessionKeyInfo;sessionKeyInfoFetchedAt;allowlist;allowlistFetchedAt;selfCustodyAddress;selfCustodyKey;agentInstanceId;apiKey;sessionKeyId;constructor(e){this.validateConfig(e),this.sessionKey=O.fromString(e.sessionKey),this.walletAddress=e.walletAddress||this.sessionKey.address,this.maxPaymentUsd=e.maxPaymentUsd,this.onPayment=e.onPayment,this.baseUrl=(e.baseUrl||_).replace(/\/$/,""),this.timeout=e.timeout||Le,e.apiKey&&(this.apiKey=e.apiKey),e.sessionKeyId&&(this.sessionKeyId=e.sessionKeyId),this.logger=new W(e.logLevel||"none"),this.logger.debug("AgentWallet initialized",{walletAddress:this.walletAddress,isTestnet:this.isTestnet(),maxPaymentUsd:this.maxPaymentUsd,hasApiKey:!!this.apiKey,hasSessionKeyId:!!this.sessionKeyId});}validateConfig(e){if(!e.sessionKey)throw new S("Session key is required. Get one from the wallet owner at https://mixrpay.com/manage/invites");let t=e.sessionKey.trim();if(!t.startsWith("sk_live_")&&!t.startsWith("sk_test_")){let a=t.slice(0,8);throw new S(`Invalid session key prefix. Expected 'sk_live_' (mainnet) or 'sk_test_' (testnet), got '${a}'`)}let s=72;if(t.length!==s)throw new S(`Invalid session key length. Expected ${s} characters, got ${t.length}. Make sure you copied the complete key.`);let n=t.slice(8);if(!/^[0-9a-fA-F]+$/.test(n))throw new S("Invalid session key format. The key should contain only hexadecimal characters after the prefix.");if(e.maxPaymentUsd!==void 0){if(e.maxPaymentUsd<=0)throw new l("maxPaymentUsd must be a positive number");e.maxPaymentUsd>1e4&&this.logger?.warn("maxPaymentUsd is very high ($"+e.maxPaymentUsd+"). Consider using a lower limit for safety.");}}async fetchAllowlist(){if(this.allowlist!==void 0&&this.allowlistFetchedAt&&Date.now()-this.allowlistFetchedAt<3e5)return this.allowlist;try{let t=await this.getSessionKeyInfo();return this.allowlist=t.allowedMerchants||[],this.allowlistFetchedAt=Date.now(),this.logger.debug("Fetched allowlist",{patterns:this.allowlist.length,allowAll:this.allowlist.length===0}),this.allowlist}catch(t){return this.logger.warn("Failed to fetch allowlist, allowing all merchants",{error:t}),this.allowlist=[],this.allowlistFetchedAt=Date.now(),this.allowlist}}async validateMerchantAllowed(e,t){let s=await this.fetchAllowlist();if(s.length===0)return;if(!this.matchesAllowlist(e,s,t))throw new E(e,s)}matchesAllowlist(e,t,s){for(let n of t)if(this.matchPattern(e,n,s))return true;return false}matchPattern(e,t,s){return s==="url"?this.matchUrlPattern(e,t):this.matchToolPattern(e,t)}matchUrlPattern(e,t){let s;try{e.includes("://")?s=new URL(e).hostname.toLowerCase():s=e.toLowerCase();}catch{return false}let a=t.toLowerCase().trim();if(a.includes("://"))try{a=new URL(a).hostname;}catch{}if(s===a)return true;if(a.startsWith("*.")){let i=a.substring(2);if(s.endsWith(`.${i}`)&&s!==i)return true}return false}matchToolPattern(e,t){let s=e.toLowerCase().trim(),n=t.toLowerCase().trim();if(s===n)return true;if(n.endsWith("/*")){let a=n.substring(0,n.length-2);if(s.startsWith(`${a}/`))return true}return false}static async register(e){let{privateKey:t,name:s}=e,n=(e.baseUrl||_).replace(/\/$/,""),i=privateKeyToAccount(t).address,r=await fetch(`${n}/api/v1/agent/challenge?wallet=${i}&action=register`);if(!r.ok){let y=await r.json().catch(()=>({}));throw new l(y.error||`Failed to get challenge: ${r.status}`)}let{challenge:o,message:d}=await r.json(),g=await signMessage({message:d,privateKey:t}),u=await fetch(`${n}/api/v1/agent/register`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({challenge:o,external_wallet:i,signature:g,name:s})});if(!u.ok){let y=await u.json().catch(()=>({})),f=y.error||`Registration failed with status ${u.status}`,h=y.request_id,w=(y.code||"").toLowerCase(),b="";u.status===503?b=" The service may be temporarily unavailable. Please try again later.":u.status===500?b=" This is a server error. Please contact support with the request ID.":(w==="missing_challenge"||w==="missing_signature")&&(b=" This may indicate an SDK bug. Please update to the latest version.");let $=h?`${f} (request_id: ${h})${b}`:`${f}${b}`;throw new l($)}let p=await u.json();return {userId:p.user_id,depositAddress:p.deposit_address}}static async checkServerHealth(e){let t=(e||_).replace(/\/$/,"");try{let s=await fetch(`${t}/api/health/ready?details=true`);if(!s.ok)return {healthy:!1,database:"unknown",agentRegistrationAvailable:!1,walletServiceConfigured:!1,error:`Health check failed with status ${s.status}`};let n=await s.json();return {healthy:n.status==="ready",database:n.database||"unknown",agentRegistrationAvailable:n.services?.agentRegistration?.available??!1,walletServiceConfigured:n.services?.wallet?.configured??!1}}catch(s){return {healthy:false,database:"unreachable",agentRegistrationAvailable:false,walletServiceConfigured:false,error:s instanceof Error?s.message:"Failed to reach server"}}}static async getSessionKey(e){let{privateKey:t,spendingLimitUsd:s,maxPerTxUsd:n,maxDailyUsd:a,durationDays:i}=e,r=(e.baseUrl||_).replace(/\/$/,""),d=privateKeyToAccount(t).address,g=await fetch(`${r}/api/v1/agent/challenge?wallet=${d}&action=session-key`);if(!g.ok){let w=await g.json().catch(()=>({}));throw new l(w.error||`Failed to get challenge: ${g.status}`)}let{challenge:u,message:p}=await g.json(),y=await signMessage({message:p,privateKey:t}),f=await fetch(`${r}/api/v1/agent/session-key`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({challenge:u,external_wallet:d,signature:y,spending_limit_usd:s,max_per_tx_usd:n,max_daily_usd:a,duration_days:i})});if(!f.ok){let w=await f.json().catch(()=>({}));throw new l(w.error||`Session key creation failed: ${f.status}`)}let h=await f.json();return {sessionKey:h.session_key,address:h.address,sessionKeyId:h.session_key_id,expiresAt:new Date(h.expires_at),limits:{maxTotalUsd:h.limits.max_total_usd,maxPerTxUsd:h.limits.max_per_tx_usd,maxDailyUsd:h.limits.max_daily_usd}}}static async getStatus(e){let{privateKey:t}=e,s=(e.baseUrl||_).replace(/\/$/,""),a=privateKeyToAccount(t).address,i=await fetch(`${s}/api/v1/agent/challenge?wallet=${a}&action=status`);if(!i.ok){let p=await i.json().catch(()=>({}));throw new l(p.error||`Failed to get challenge: ${i.status}`)}let{challenge:r,message:o}=await i.json(),d=await signMessage({message:o,privateKey:t}),g=await fetch(`${s}/api/v1/agent/status?challenge=${r}&external_wallet=${a}&signature=${encodeURIComponent(d)}`);if(!g.ok){let p=await g.json().catch(()=>({}));throw new l(p.error||`Failed to get status: ${g.status}`)}let u=await g.json();return {depositAddress:u.deposit_address,balanceUsd:u.balance_usd,activeSessions:u.active_sessions.map(p=>({id:p.id,expiresAt:new Date(p.expires_at),totalSpentUsd:p.total_spent_usd,remainingUsd:p.remaining_usd,maxTotalUsd:p.max_total_usd})),totalSpentUsd:u.total_spent_usd}}static async revokeSessionKey(e){let{privateKey:t,sessionKeyId:s}=e,n=(e.baseUrl||_).replace(/\/$/,""),i=privateKeyToAccount(t).address,r=await fetch(`${n}/api/v1/agent/challenge?wallet=${i}&action=revoke`);if(!r.ok){let p=await r.json().catch(()=>({}));throw new l(p.error||`Failed to get challenge: ${r.status}`)}let{challenge:o,message:d}=await r.json(),g=await signMessage({message:d,privateKey:t}),u=await fetch(`${n}/api/v1/agent/session-key/revoke`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({challenge:o,external_wallet:i,signature:g,session_key_id:s})});if(!u.ok){let p=await u.json().catch(()=>({}));throw new l(p.error||`Revocation failed: ${u.status}`)}return true}static async withdraw(e){let{privateKey:t,amountUsd:s}=e,n=(e.baseUrl||_).replace(/\/$/,""),i=privateKeyToAccount(t).address,r=await fetch(`${n}/api/v1/agent/challenge?wallet=${i}&action=withdraw`);if(!r.ok){let y=await r.json().catch(()=>({}));throw new l(y.error||`Failed to get challenge: ${r.status}`)}let{challenge:o,message:d}=await r.json(),g=await signMessage({message:d,privateKey:t}),u=await fetch(`${n}/api/v1/agent/withdraw`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({challenge:o,external_wallet:i,signature:g,to_address:i,amount_usd:s})});if(!u.ok){let y=await u.json().catch(()=>({}));throw new l(y.error||`Withdrawal failed: ${u.status}`)}let p=await u.json();return {txHash:p.tx_hash,amountUsd:p.amount_usd,remainingBalanceUsd:p.remaining_balance_usd}}static async claimInvite(e){let{inviteCode:t,privateKey:s}=e,n=(e.baseUrl||_).replace(/\/$/,""),i=privateKeyToAccount(s).address,r=await fetch(`${n}/api/v1/agent/challenge?wallet=${i}&action=claim-invite`);if(!r.ok){let y=await r.json().catch(()=>({}));throw new l(y.error||`Failed to get challenge: ${r.status}`)}let{challenge:o,message:d}=await r.json(),g=await signMessage({message:d,privateKey:s}),u=await fetch(`${n}/api/v1/agent/claim-invite`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({invite_code:t,challenge:o,agent_wallet_address:i,signature:g})});if(!u.ok){let f=(await u.json().catch(()=>({}))).error||`Failed to claim invite: ${u.status}`,h="";throw u.status===404?h=" The invite code may be invalid or misspelled.":u.status===400&&(f.includes("already claimed")?h=" This invite has already been used by another agent.":f.includes("expired")?h=" Ask the wallet owner to create a new invite.":f.includes("revoked")&&(h=" The wallet owner has revoked this invite.")),new l(`${f}${h}`)}let p=await u.json();return {sessionKey:p.session_key,address:p.address,sessionKeyId:p.session_key_id,expiresAt:new Date(p.expires_at),limits:{budgetUsd:p.limits.budget_usd,budgetPeriod:p.limits.budget_period,maxPerTxUsd:p.limits.max_per_tx_usd},allowedMerchants:p.allowed_merchants||[],inviterName:p.inviter_name||"Anonymous"}}static async activate(e,t){let s=(t?.baseUrl||_).replace(/\/$/,""),n=new c({sessionKey:e,baseUrl:s}),a=await n.getSessionAuthHeaders(),i=await fetch(`${s}/api/v2/agent/activate`,{method:"POST",headers:{"Content-Type":"application/json",...a}});if(!i.ok){let o=await i.json().catch(()=>({}));throw new l(o.error||`Activation failed: ${i.status}`)}let r=await i.json();return {wallet:n,budget:{maxTotalUsd:r.budget.max_total_usd,maxDailyUsd:r.budget.max_daily_usd,maxPerTxUsd:r.budget.max_per_tx_usd,spentUsd:r.budget.spent_usd,remainingUsd:r.budget.remaining_usd},capabilities:{executeTransactions:r.capabilities.execute_transactions,gasSponsored:r.capabilities.gas_sponsored,batchedTx:r.capabilities.batched_tx},skills:r.skills||[],tools:r.tools||[],gatewayProviders:r.gateway_providers||[]}}static async connect(e){let t=(e?.baseUrl||process.env.MIXRPAY_BASE_URL||_).replace(/\/$/,""),s=e?.logLevel||"none",n=process.env.MIXRPAY_INSTANCE_ID;if(e?.sessionKey){let g=new c({sessionKey:e.sessionKey,sessionKeyId:e.sessionKeyId,baseUrl:t,logLevel:s,maxPaymentUsd:e?.maxPaymentUsd,onPayment:e?.onPayment});return n&&g.setAgentInstanceId(n),g}let a=process.env.MIXRPAY_SESSION_KEY;if(a){let g=process.env.MIXRPAY_SESSION_KEY_ID,u=new c({sessionKey:a,sessionKeyId:g,baseUrl:t,logLevel:s,maxPaymentUsd:e?.maxPaymentUsd,onPayment:e?.onPayment});return n&&u.setAgentInstanceId(n),u}let i=process.env.MIXRPAY_API_KEY||process.env.MIXRPAY_AGENT_TOKEN;if(i&&(i.startsWith("agt_live_")||i.startsWith("agt_test_")))return c.fromApiKey(i,{baseUrl:t,logLevel:s});let r=e?.accessCode||process.env.MIXRPAY_ACCESS_CODE;if(r)return c.fromAccessCode(r,{baseUrl:t,logLevel:s});let o=e?.masterKey||process.env.MIXRPAY_MASTER_KEY,d=e?.agentName||process.env.MIXRPAY_AGENT_NAME;if(o&&d)return c.fromMasterKey(o,d,{baseUrl:t,logLevel:s});try{let{loadCredentials:g}=await import('./credentials-ILS4YAGF.js'),u=g();if(u.success&&u.credentials.sessionKey){let p=new c({sessionKey:u.credentials.sessionKey,sessionKeyId:u.credentials.sessionKeyId,baseUrl:u.credentials.baseUrl||t,logLevel:s,maxPaymentUsd:e?.maxPaymentUsd,onPayment:e?.onPayment,apiKey:u.credentials.apiToken});return n&&p.setAgentInstanceId(n),p}if(u.success&&u.credentials.apiToken)return c.fromApiKey(u.credentials.apiToken,{baseUrl:t,logLevel:s});if(u.success&&u.credentials.masterKey&&u.credentials.defaultAgentName)return c.fromMasterKey(u.credentials.masterKey,u.credentials.defaultAgentName,{baseUrl:t,logLevel:s})}catch{}if(e?.interactive)return c.deviceFlowLogin({baseUrl:t,logLevel:s});throw new l("No MixrPay credentials found. Options:\n 1. Set MIXRPAY_SESSION_KEY environment variable\n 2. Set MIXRPAY_API_KEY or MIXRPAY_AGENT_TOKEN environment variable (agt_live_xxx)\n 3. Set MIXRPAY_ACCESS_CODE environment variable (mixr-xxx)\n 4. Pass sessionKey or accessCode to connect()\n 5. Run `npx --package @mixrpay/agent-sdk mixrpay login` (or `npm i -g @mixrpay/agent-sdk` then `mixrpay login`)\n 6. Use connect({ interactive: true }) for browser login")}static async fromApiKey(e,t){let s=(t?.baseUrl||_).replace(/\/$/,"");if(!e.startsWith("agt_live_")&&!e.startsWith("agt_test_"))throw new l(`Invalid API key format. Expected 'agt_live_' or 'agt_test_' prefix, got '${e.slice(0,9)}...'`);let n=await fetch(`${s}/api/v2/agent/session-from-token`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`}});if(!n.ok){let o=await n.json().catch(()=>({}));throw new l(o.error||`Failed to exchange API key for session: ${n.status}`)}let a=await n.json(),i=a.session_key;if(!i)throw new l("No session_key in API response");let r=new c({sessionKey:i,baseUrl:s,logLevel:t?.logLevel});return r.setApiKey(e),a.agent_instance_id&&r.setAgentInstanceId(a.agent_instance_id),r}static async fromAccessCode(e,t){let s=(t?.baseUrl||_).replace(/\/$/,"");if(!e.startsWith("mixr-"))throw new l(`Invalid access code format. Expected 'mixr-' prefix, got '${e.slice(0,5)}...'`);let n=await fetch(`${s}/api/v2/agent/connect`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({code:e})});if(!n.ok){let g=await n.json().catch(()=>({})),u=(g.code||"").toLowerCase(),p="";throw n.status===404||u==="invalid_code"?p=" Check the code for typos or get a new one from the MixrPay dashboard.":n.status===400&&(u==="code_claimed"?p=" This code has already been used. Get a new code from the dashboard.":u==="code_expired"?p=" This code has expired. Get a new code from the dashboard.":u==="code_revoked"&&(p=" This code has been revoked by the owner.")),new l((g.error||`Failed to activate access code: ${n.status}`)+p)}let a=await n.json(),i=a.session_key,r=a.token,o=a.agent_id;if(!i)throw new l("No session_key in access code response");try{let{saveCredentials:g}=await import('./credentials-ILS4YAGF.js');g({sessionKey:i,apiToken:r,baseUrl:s});}catch{}let d=new c({sessionKey:i,baseUrl:s,logLevel:t?.logLevel});return r&&(d.apiKey=r),o&&(d.agentInstanceId=o),d}static async fromMasterKey(e,t,s){let n=(s?.baseUrl||_).replace(/\/$/,"");if(!e.startsWith("mk_live_")&&!e.startsWith("mk_test_"))throw new l("Invalid master key format. Expected 'mk_live_' or 'mk_test_' prefix.");let a=await fetch(`${n}/api/v2/master-keys/session`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify({agent_name:t})});if(!a.ok){let g=await a.json().catch(()=>({}));throw a.status===404?new l(`Agent '${t}' not found. Use the MixrPay dashboard to create it.`):new l(g.error||`Failed to get session from master key: ${a.status}`)}let i=await a.json(),r=i.session_key,o=i.session_key_id;if(!r)throw new l("No session_key in master key response");let d=new c({sessionKey:r,sessionKeyId:o,baseUrl:n,logLevel:s?.logLevel});return i.agent?.id&&(d.agentInstanceId=i.agent.id),d}static async deviceFlowLogin(e){let t=(e?.baseUrl||_).replace(/\/$/,""),s=await fetch(`${t}/api/v2/auth/device/authorize`,{method:"POST",headers:{"Content-Type":"application/json"}});if(!s.ok){let y=await s.json().catch(()=>({}));throw new l(y.error||`Device flow initiation failed: ${s.status}`)}let n=await s.json(),{device_code:a,user_code:i,verification_uri:r,verification_uri_complete:o,expires_in:d,interval:g}=n;console.log(`
9
3
  \u{1F510} MixrPay Login
10
4
  `),console.log(`Visit: ${o||r}`),console.log(`Enter code: ${i}
11
5
  `),console.log(`Waiting for authentication...
package/dist/cli.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import {b as b$1,a as a$1,e,d as d$1,c as c$1}from'./chunk-KXMATINK.js';import {c,g,a}from'./chunk-SEL55NG5.js';import {privateKeyToAccount,generatePrivateKey}from'viem/accounts';import {createWalletClient,http,createPublicClient,parseUnits,encodeFunctionData}from'viem';import {base}from'viem/chains';async function u(e){let r=e.baseUrl||e.url||c;try{return await g.connect({baseUrl:r})}catch(s){throw s instanceof a&&(console.error("Authentication required."),console.error("\nRun `mixrpay login` or set MIXRPAY_SESSION_KEY environment variable.")),s}}function d(e,r){console.log(JSON.stringify(e,null,2));}function b(e){return e.length<=16?e.slice(0,8)+"...":e.slice(0,12)+"..."+e.slice(-4)}function R(e,r){let s;try{s=JSON.parse(e);}catch{console.error(`Error: ${r}`),process.exit(1);}(typeof s!="object"||s===null||Array.isArray(s))&&(console.error(`Error: ${r} - expected a JSON object`),process.exit(1));let o=s;return ("__proto__"in o||"constructor"in o||"prototype"in o)&&(console.error("Error: Invalid JSON - contains forbidden keys"),process.exit(1)),o}function H(e,r){let s;try{s=JSON.parse(e);}catch{console.error(`Error: ${r}`),process.exit(1);}Array.isArray(s)||(console.error(`Error: ${r} - expected a JSON array`),process.exit(1));for(let o of s){(typeof o!="object"||o===null||Array.isArray(o))&&(console.error(`Error: ${r} - array elements must be objects`),process.exit(1));let t=o;("__proto__"in t||"constructor"in t||"prototype"in t)&&(console.error("Error: Invalid JSON - contains forbidden keys"),process.exit(1));}return s}function Y(e){let r={command:"",flags:{},positionals:[]},s=0;for(;s<e.length;){let o=e[s];if(o.startsWith("--")){let[t,n]=o.slice(2).split("=");n!==void 0?r.flags[t]=n:s+1<e.length&&!e[s+1].startsWith("-")?r.flags[t]=e[++s]:r.flags[t]=true;}else if(o.startsWith("-")){let t=o.slice(1);s+1<e.length&&!e[s+1].startsWith("-")?r.flags[t]=e[++s]:r.flags[t]=true;}else r.command?r.positionals.push(o):r.command=o;s++;}return r}async function V(e$1){if(e$1.help||e$1.h){console.log(`
2
+ import {b as b$1,a as a$1,e,d as d$1,c as c$1}from'./chunk-KXMATINK.js';import {c,g,a}from'./chunk-TOPWZWOK.js';import {privateKeyToAccount,generatePrivateKey}from'viem/accounts';import {createWalletClient,http,createPublicClient,parseUnits,encodeFunctionData}from'viem';import {base}from'viem/chains';async function u(e){let r=e.baseUrl||e.url||c;try{return await g.connect({baseUrl:r})}catch(s){throw s instanceof a&&(console.error("Authentication required."),console.error("\nRun `mixrpay login` or set MIXRPAY_SESSION_KEY environment variable.")),s}}function d(e,r){console.log(JSON.stringify(e,null,2));}function b(e){return e.length<=16?e.slice(0,8)+"...":e.slice(0,12)+"..."+e.slice(-4)}function R(e,r){let s;try{s=JSON.parse(e);}catch{console.error(`Error: ${r}`),process.exit(1);}(typeof s!="object"||s===null||Array.isArray(s))&&(console.error(`Error: ${r} - expected a JSON object`),process.exit(1));let o=s;return ("__proto__"in o||"constructor"in o||"prototype"in o)&&(console.error("Error: Invalid JSON - contains forbidden keys"),process.exit(1)),o}function H(e,r){let s;try{s=JSON.parse(e);}catch{console.error(`Error: ${r}`),process.exit(1);}Array.isArray(s)||(console.error(`Error: ${r} - expected a JSON array`),process.exit(1));for(let o of s){(typeof o!="object"||o===null||Array.isArray(o))&&(console.error(`Error: ${r} - array elements must be objects`),process.exit(1));let t=o;("__proto__"in t||"constructor"in t||"prototype"in t)&&(console.error("Error: Invalid JSON - contains forbidden keys"),process.exit(1));}return s}function Y(e){let r={command:"",flags:{},positionals:[]},s=0;for(;s<e.length;){let o=e[s];if(o.startsWith("--")){let[t,n]=o.slice(2).split("=");n!==void 0?r.flags[t]=n:s+1<e.length&&!e[s+1].startsWith("-")?r.flags[t]=e[++s]:r.flags[t]=true;}else if(o.startsWith("-")){let t=o.slice(1);s+1<e.length&&!e[s+1].startsWith("-")?r.flags[t]=e[++s]:r.flags[t]=true;}else r.command?r.positionals.push(o):r.command=o;s++;}return r}async function V(e$1){if(e$1.help||e$1.h){console.log(`
3
3
  mixrpay login - Authenticate via browser
4
4
 
5
5
  USAGE
@@ -691,7 +691,7 @@ USAGE
691
691
  mixrpay tool <provider> <tool_name> '<json_arguments>'
692
692
  mixrpay tool list
693
693
 
694
- For full documentation, run: npx mixrpay-tool --help
694
+ For full documentation, run: npx --package @mixrpay/agent-sdk mixrpay-tool --help
695
695
 
696
696
  QUICK EXAMPLES
697
697
  # Web search
@@ -1005,9 +1005,9 @@ EXAMPLES
1005
1005
 
1006
1006
  TOOL CLI
1007
1007
  For full tool gateway access, use:
1008
- npx mixrpay-tool <provider> <tool_name> '<json>'
1009
- npx mixrpay-tool list
1010
- npx mixrpay-tool help <provider>
1008
+ npx --package @mixrpay/agent-sdk mixrpay-tool <provider> <tool_name> '<json>'
1009
+ npx --package @mixrpay/agent-sdk mixrpay-tool list
1010
+ npx --package @mixrpay/agent-sdk mixrpay-tool help <provider>
1011
1011
 
1012
1012
  ENVIRONMENT VARIABLES
1013
1013
  MIXRPAY_SESSION_KEY Session key for authentication
@@ -1017,4 +1017,4 @@ ENVIRONMENT VARIABLES
1017
1017
  AGENT_WALLET_KEY Agent's wallet private key
1018
1018
 
1019
1019
  For more info, visit: https://docs.mixrpay.com/cli
1020
- `);}function To(){import('./agent-wallet-DD4EL57B.js').then(({SDK_VERSION:e})=>{console.log(`mixrpay v${e}`);});}async function Uo(){let e=Y(process.argv.slice(2));if(!e.command&&(e.flags.help||e.flags.h)){D();return}if(e.flags.version||e.flags.v){To();return}switch(e.command){case "init":await oe(e.flags);break;case "install":await ee(e.flags);break;case "login":await V(e.flags);break;case "logout":await z();break;case "whoami":await Q(e.flags);break;case "register":await Z(e.flags);break;case "status":await te(e.flags);break;case "wallet":await ge(e.flags,e.positionals);break;case "budget":await fe(e.flags);break;case "creds":case "credentials":case "vault":await be(e.flags,e.positionals);break;case "spawn":await me(e.flags);break;case "children":await ye(e.flags);break;case "sessions":await Oe(e.flags,e.positionals);break;case "complete":await ke(e.flags,e.positionals);break;case "run":await ve(e.flags,e.positionals);break;case "tool":await ze(e.flags,e.positionals);break;case "search":await Qe(e.flags,e.positionals);break;case "mcp":await Me(e.flags,e.positionals);break;case "skills":await Be(e.flags,e.positionals);break;case "agent":await Ve(e.flags,e.positionals);break;case "task":await co(e.flags,e.positionals);break;case "defi":await fo(e.flags,e.positionals);break;case "plan":await ko(e.flags,e.positionals);break;case "approval":await Io(e.flags,e.positionals);break;case "diagnostics":await $e(e.flags);break;case "health":await Ae(e.flags);break;case "siwe":await Ee(e.flags);break;case "":case "help":D();break;default:console.error(`Unknown command: ${e.command}`),console.error("\nRun `mixrpay --help` for usage information."),process.exit(1);}}Uo().catch(e=>{console.error("Fatal error:",e),process.exit(1);});
1020
+ `);}function To(){import('./agent-wallet-7CS7WY4F.js').then(({SDK_VERSION:e})=>{console.log(`mixrpay v${e}`);});}async function Uo(){let e=Y(process.argv.slice(2));if(!e.command&&(e.flags.help||e.flags.h)){D();return}if(e.flags.version||e.flags.v){To();return}switch(e.command){case "init":await oe(e.flags);break;case "install":await ee(e.flags);break;case "login":await V(e.flags);break;case "logout":await z();break;case "whoami":await Q(e.flags);break;case "register":await Z(e.flags);break;case "status":await te(e.flags);break;case "wallet":await ge(e.flags,e.positionals);break;case "budget":await fe(e.flags);break;case "creds":case "credentials":case "vault":await be(e.flags,e.positionals);break;case "spawn":await me(e.flags);break;case "children":await ye(e.flags);break;case "sessions":await Oe(e.flags,e.positionals);break;case "complete":await ke(e.flags,e.positionals);break;case "run":await ve(e.flags,e.positionals);break;case "tool":await ze(e.flags,e.positionals);break;case "search":await Qe(e.flags,e.positionals);break;case "mcp":await Me(e.flags,e.positionals);break;case "skills":await Be(e.flags,e.positionals);break;case "agent":await Ve(e.flags,e.positionals);break;case "task":await co(e.flags,e.positionals);break;case "defi":await fo(e.flags,e.positionals);break;case "plan":await ko(e.flags,e.positionals);break;case "approval":await Io(e.flags,e.positionals);break;case "diagnostics":await $e(e.flags);break;case "health":await Ae(e.flags);break;case "siwe":await Ee(e.flags);break;case "":case "help":D();break;default:console.error(`Unknown command: ${e.command}`),console.error("\nRun `mixrpay --help` for usage information."),process.exit(1);}}Uo().catch(e=>{console.error("Fatal error:",e),process.exit(1);});
package/dist/index.cjs CHANGED
@@ -1,10 +1,4 @@
1
- 'use strict';var b=require('fs'),D=require('path'),M=require('os'),url=require('url'),accounts=require('viem/accounts'),zod=require('zod'),viem=require('viem'),chains=require('viem/chains');var _documentCurrentScript=typeof document!=='undefined'?document.currentScript:null;function _interopNamespace(e){if(e&&e.__esModule)return e;var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var b__namespace=/*#__PURE__*/_interopNamespace(b);var D__namespace=/*#__PURE__*/_interopNamespace(D);var M__namespace=/*#__PURE__*/_interopNamespace(M);var Ke=Object.defineProperty;var je=(o,e)=>()=>(o&&(e=o(o=0)),e);var Me=(o,e)=>{for(var t in e)Ke(o,t,{get:e[t],enumerable:true});};var J={};Me(J,{deleteCredentials:()=>Ue,getCredentialsFilePath:()=>Ce,hasCredentials:()=>Ie,loadCredentials:()=>B,saveCredentials:()=>Pe});function ve(){if(M__namespace.platform()==="win32"){let t=process.env.APPDATA||D__namespace.join(M__namespace.homedir(),"AppData","Roaming");return D__namespace.join(t,"mixrpay")}let e=process.env.XDG_CONFIG_HOME||D__namespace.join(M__namespace.homedir(),".config");return D__namespace.join(e,"mixrpay")}function q(){return D__namespace.join(ve(),"credentials.json")}function nt(){let o=ve();b__namespace.existsSync(o)||b__namespace.mkdirSync(o,{recursive:true,mode:448});}function Te(o){try{b__namespace.chmodSync(o,384);}catch{}}function Pe(o){try{nt();let e=q(),t={};if(b__namespace.existsSync(e))try{let a=b__namespace.readFileSync(e,"utf-8");t=JSON.parse(a);}catch{t={};}let s={...t,...o,updatedAt:new Date().toISOString()},n=Object.fromEntries(Object.entries(s).filter(([a,r])=>r!==void 0));return b__namespace.writeFileSync(e,JSON.stringify(n,null,2),{mode:384}),Te(e),!0}catch(e){return console.error("[MixrPay] Failed to save credentials:",e),false}}function B(){try{let o=q();if(!b__namespace.existsSync(o))return {success:!0,credentials:{}};let e=b__namespace.readFileSync(o,"utf-8");return {success:!0,credentials:JSON.parse(e)}}catch(o){return {success:false,error:o instanceof Error?o.message:"Failed to load credentials"}}}function Ue(o){try{let e=q();if(!b__namespace.existsSync(e))return !0;if(!o)return b__namespace.unlinkSync(e),!0;let t=B();if(!t.success)return !1;let s={...t.credentials};for(let n of o)delete s[n];return Object.keys(s).length===0?b__namespace.unlinkSync(e):(b__namespace.writeFileSync(e,JSON.stringify(s,null,2),{mode:384}),Te(e)),!0}catch(e){return console.error("[MixrPay] Failed to delete credentials:",e),false}}function Ie(){let o=B();if(!o.success)return false;let{credentials:e}=o;return !!(e.sessionKey||e.apiToken||e.masterKey)}function Ce(){return q()}var H=je(()=>{});var c=class extends Error{code;retryAfterMs;constructor(e,t="MIXRPAY_ERROR",s){super(e),this.name="MixrPayError",this.code=t,this.retryAfterMs=s,Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor);}isRetryable(){return false}},v=class extends c{required;available;topUpUrl;constructor(e,t){let s=e-t;super(`Insufficient balance: need $${e.toFixed(2)}, have $${t.toFixed(2)} (short $${s.toFixed(2)}). Top up your wallet to continue.`,"INSUFFICIENT_BALANCE"),this.name="InsufficientBalanceError",this.required=e,this.available=t,this.topUpUrl="https://mixr.network/manage/wallet";}},E=class extends c{expiredAt;constructor(e){super(`Session key expired at ${e}. Request a new session key from the wallet owner at https://mixrpay.com/manage/invites`,"SESSION_KEY_EXPIRED"),this.name="SessionKeyExpiredError",this.expiredAt=e;}},T=class extends c{limitType;limit;attempted;constructor(e,t,s){let a={per_tx:"Per-transaction",daily:"Daily",total:"Total",client_max:"Client-side"}[e]||e,r=e==="daily"?"Wait until tomorrow or request a higher limit.":e==="client_max"?"Increase maxPaymentUsd in your AgentWallet configuration.":"Request a new session key with a higher limit.";super(`${a} spending limit exceeded: limit is $${t.toFixed(2)}, attempted $${s.toFixed(2)}. ${r}`,"SPENDING_LIMIT_EXCEEDED"),this.name="SpendingLimitExceededError",this.limitType=e,this.limit=t,this.attempted=s;}isRetryable(){return this.limitType==="daily"}},k=class extends c{reason;txHash;constructor(e,t){let s=`Payment failed: ${e}`;t&&(s+=` (tx: ${t} - check on basescan.org)`),super(s,"PAYMENT_FAILED"),this.name="PaymentFailedError",this.reason=e,this.txHash=t;}isRetryable(){return true}},x=class extends c{reason;constructor(e="Invalid session key format"){super(`${e}. Session keys should be in format: sk_live_<64 hex chars> or sk_test_<64 hex chars>. Get one from https://mixrpay.com/manage/invites`,"INVALID_SESSION_KEY"),this.name="InvalidSessionKeyError",this.reason=e;}},P=class extends c{reason;constructor(e){super(`x402 protocol error: ${e}. This may indicate a server configuration issue. If the problem persists, contact the API provider.`,"X402_PROTOCOL_ERROR"),this.name="X402ProtocolError",this.reason=e;}isRetryable(){return true}},O=class extends c{sessionId;expiredAt;constructor(e,t){super(`Session ${e} has expired${t?` at ${t}`:""}. A new session will be created automatically on your next request.`,"SESSION_EXPIRED"),this.name="SessionExpiredError",this.sessionId=e,this.expiredAt=t;}},I=class extends c{sessionId;limit;requested;remaining;constructor(e,t,s,n){super(`Session spending limit exceeded: limit is $${e.toFixed(2)}, requested $${t.toFixed(2)}, remaining $${s.toFixed(2)}. Create a new session with a higher limit to continue.`,"SESSION_LIMIT_EXCEEDED"),this.name="SessionLimitExceededError",this.sessionId=n,this.limit=e,this.requested=t,this.remaining=s;}},C=class extends c{sessionId;constructor(e){super(`Session ${e} not found. It may have been deleted or never existed. Create a new session with getOrCreateSession().`,"SESSION_NOT_FOUND"),this.name="SessionNotFoundError",this.sessionId=e;}},R=class extends c{sessionId;reason;constructor(e,t){super(`Session ${e} has been revoked${t?`: ${t}`:""}. Create a new session with getOrCreateSession().`,"SESSION_REVOKED"),this.name="SessionRevokedError",this.sessionId=e,this.reason=t;}},K=class extends c{attempted;allowedPatterns;constructor(e,t){let s=t.slice(0,3).join(", "),n=t.length>3?"...":"";super(`Payment to "${e}" not allowed. Session allowlist: ${s}${n}. Update the session allowlist or create a new session.`,"MERCHANT_NOT_ALLOWED"),this.name="MerchantNotAllowedError",this.attempted=e,this.allowedPatterns=t;}},G=class extends c{constructor(e=6e4,t){super(t||`Rate limit exceeded. Please wait ${Math.ceil(e/1e3)} seconds before retrying.`,"RATE_LIMIT_EXCEEDED",e),this.name="RateLimitError";}isRetryable(){return true}},X=class extends c{reason;constructor(e,t){super(`Network error: ${e}. Check your connection and try again.`,"NETWORK_ERROR",5e3),this.name="NetworkError",this.reason=e,t?.stack&&(this.stack=t.stack);}isRetryable(){return true}},z=class extends c{reason;statusCode;constructor(e,t=401){super(`Authentication failed: ${e}`,t===401?"UNAUTHORIZED":"FORBIDDEN"),this.name="AuthenticationError",this.reason=e,this.statusCode=t;}isRetryable(){return false}};function He(o){return o instanceof c}function Ne(o){return o instanceof c||o instanceof Error?o.message:String(o)}var qe={8453:"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",84532:"0x036CbD53842c5426634e7929541eC2318f3dCF7e"},Be={name:"USD Coin",version:"2"},Je={TransferWithAuthorization:[{name:"from",type:"address"},{name:"to",type:"address"},{name:"value",type:"uint256"},{name:"validAfter",type:"uint256"},{name:"validBefore",type:"uint256"},{name:"nonce",type:"bytes32"}]},L=class o{privateKey;account;address;isTest;constructor(e,t){this.privateKey=e,this.account=accounts.privateKeyToAccount(e),this.address=this.account.address,this.isTest=t;}toString(){return `${this.isTest?"sk_test_":"sk_live_"}${this.privateKey.slice(2)}`}get privateKeyHex(){return this.privateKey.slice(2)}get rawPrivateKey(){return this.privateKey}static fromString(e){let t=/^sk_(live|test)_([a-fA-F0-9]{64})$/,s=e.match(t);if(!s)throw new x("Session key must be in format sk_live_{64_hex} or sk_test_{64_hex}");let n=s[1],a=s[2];try{let r=`0x${a}`;return new o(r,n==="test")}catch(r){throw new x(`Failed to decode session key: ${r}`)}}async signTransferAuthorization(e,t){return accounts.signTypedData({privateKey:this.privateKey,domain:e,types:Je,primaryType:"TransferWithAuthorization",message:t})}async signMessage(e){return accounts.signMessage({privateKey:this.privateKey,message:e})}getDefaultChainId(){return this.isTest?84532:8453}};function ne(o){let e=qe[o.chainId];if(!e)throw new Error(`USDC not supported on chain ${o.chainId}`);let t={...Be,chainId:o.chainId,verifyingContract:e},s={from:o.fromAddress,to:o.toAddress,value:o.value,validAfter:o.validAfter,validBefore:o.validBefore,nonce:o.nonce};return {domain:t,message:s}}function Y(){let o=new Uint8Array(32);return crypto.getRandomValues(o),`0x${Array.from(o).map(e=>e.toString(16).padStart(2,"0")).join("")}`}function Ge(o,e){return `MixrPay:${o}:${e.toLowerCase()}`}async function ae(o){let e=Date.now(),t=Ge(e,o.address),s=await o.signMessage(t);return {address:o.address,timestamp:e,signature:s}}var re=zod.z.object({query:zod.z.string().describe('Search query (e.g. "web scraping", "email", "database")')}),ie=zod.z.object({tool_name:zod.z.string().describe('Tool name in "merchant/tool" format'),arguments:zod.z.record(zod.z.unknown()).optional().describe("Arguments to pass to the tool")}),oe=zod.z.object({url:zod.z.string().url().describe("The merchant API URL to call"),merchant_public_key:zod.z.string().describe("The merchant's MixrPay public key (pk_live_... or pk_test_...)"),method:zod.z.enum(["GET","POST","PUT","PATCH","DELETE"]).default("POST").describe("HTTP method"),body:zod.z.unknown().optional().describe("Request body (will be JSON-serialized)"),price_usd:zod.z.number().optional().describe("Expected price in USD for client-side validation")}),le=zod.z.object({skill_id:zod.z.string().describe("The skill ID to execute"),input:zod.z.record(zod.z.unknown()).optional().describe("Input parameters for the skill")}),ce=zod.z.object({skill_id:zod.z.string().describe("The skill ID to check")}),de=zod.z.object({glama_id:zod.z.string().describe('Glama server ID (e.g. "notion-mcp")'),glama_namespace:zod.z.string().describe('Glama namespace (e.g. "notion")'),glama_slug:zod.z.string().describe('Glama slug (e.g. "notion-mcp")'),tool_name:zod.z.string().describe("Human-readable name for the tool"),tool_description:zod.z.string().optional().describe("Optional description"),env_vars:zod.z.record(zod.z.string()).optional().describe("Environment variables for the MCP server (e.g. API keys)"),ttl_hours:zod.z.number().min(1).max(168).optional().describe("Time-to-live in hours (default: 24, max: 168)")}),ue=zod.z.object({status:zod.z.enum(["provisioning","active","stopped","expired"]).optional().describe("Filter by status")}),ge=zod.z.object({instance_id:zod.z.string().describe("The instance ID to stop")}),pe=zod.z.object({to:zod.z.string().describe("Recipient address (0x...)"),amount_usdc:zod.z.number().positive().describe("Amount in USDC (e.g. 10.5)")}),me=zod.z.object({name:zod.z.string().describe("Name for the child agent"),budget_usd:zod.z.number().positive().describe("Budget to delegate in USD"),budget_period:zod.z.enum(["daily","monthly","total"]).default("total").describe("Budget period"),max_per_tx_usd:zod.z.number().positive().optional().describe("Max per-transaction limit in USD"),expires_in_days:zod.z.number().min(1).max(365).optional().describe("Expiry in days (default: 30)")}),he=zod.z.object({title:zod.z.string().describe("Task title"),description:zod.z.string().describe("Detailed task description"),budget_usd:zod.z.number().positive().describe("Budget for the task in USD"),skills_required:zod.z.array(zod.z.string()).optional().describe("Required skill IDs")}),ye=zod.z.object({status:zod.z.string().optional().describe('Filter by status (e.g. "open", "in_progress")'),limit:zod.z.number().min(1).max(100).optional().describe("Number of results (default: 20)")});function fe(o){let e=[{name:"check_balance",title:"Check Balance",description:"Get the USDC balance of the wallet on Base.",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:null,handler:async()=>({balanceUsd:await o.getBalance(),network:o.isTestnet()?"base-sepolia":"base"})},{name:"get_spending_stats",title:"Get Spending Stats",description:"Get session key spending limits and current usage (total spent, remaining daily/total limits, expiry).",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:null,handler:async()=>o.getSpendingStats()},{name:"get_session_info",title:"Get Session Info",description:"Get detailed session key information including limits, usage, expiry, and allowed merchants.",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:null,handler:async()=>o.getSessionKeyInfo(true)},{name:"run_diagnostics",title:"Run Diagnostics",description:"Run a full health check on the wallet: API connectivity, session key validity, balance, and latency.",annotations:{readOnlyHint:true,openWorldHint:true},inputSchema:null,handler:async()=>o.runDiagnostics()},{name:"list_tools",title:"List Marketplace Tools",description:"Browse all available paid API tools on the MixrPay marketplace. Each tool includes pricing and description.",annotations:{readOnlyHint:true,openWorldHint:true},inputSchema:null,handler:async()=>o.listTools()},{name:"search_tools",title:"Search Tools",description:"Search the Glama MCP server directory for tools by keyword.",annotations:{readOnlyHint:true,openWorldHint:true},inputSchema:re,handler:async s=>{let{query:n}=re.parse(s);return o.searchGlamaDirectory(n)}},{name:"call_tool",title:"Call Marketplace Tool",description:'Call a paid API tool on the MixrPay marketplace. Payment is automatic from the wallet. Tool names are in "merchant/tool" format (e.g. "firecrawl/scrape").',annotations:{readOnlyHint:false,openWorldHint:true},inputSchema:ie,handler:async s=>{let{tool_name:n,arguments:a}=ie.parse(s);return o.callTool(n,a||{})}},{name:"call_merchant_api",title:"Call Merchant API",description:"Call any merchant API endpoint with x402 payment. The wallet handles authentication and payment automatically.",annotations:{readOnlyHint:false,openWorldHint:true},inputSchema:oe,handler:async s=>{let{url:n,merchant_public_key:a,method:r,body:i,price_usd:l}=oe.parse(s),d=await o.callMerchantApi({url:n,merchantPublicKey:a,method:r,body:i,priceUsd:l}),g=await d.json().catch(()=>d.text());return {status:d.status,data:g}}},{name:"list_skills",title:"List Skills",description:"List all available skills (pre-built integrations) that the wallet can use.",annotations:{readOnlyHint:true,openWorldHint:true},inputSchema:null,handler:async()=>o.listSkills()},{name:"use_skill",title:"Use Skill",description:"Execute a skill by ID. Skills are pre-built integrations (e.g. web scraping, email sending).",annotations:{readOnlyHint:false,openWorldHint:true},inputSchema:le,handler:async s=>{let{skill_id:n,input:a}=le.parse(s);return o.useSkill(n,{input:a})}},{name:"get_skill_status",title:"Get Skill Status",description:"Check the status and configuration of a specific skill.",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:ce,handler:async s=>{let{skill_id:n}=ce.parse(s);return o.getSkillStatus(n)}},{name:"deploy_jit_mcp",title:"Deploy JIT MCP Server",description:"Deploy a just-in-time MCP server from the Glama directory. Creates a temporary hosted MCP server instance.",annotations:{readOnlyHint:false,openWorldHint:true},inputSchema:de,handler:async s=>{let{glama_id:n,glama_namespace:a,glama_slug:r,tool_name:i,tool_description:l,env_vars:d,ttl_hours:g}=de.parse(s);return o.deployJitMcp({glamaId:n,glamaNamespace:a,glamaSlug:r,toolName:i,toolDescription:l,envVars:d,ttlHours:g})}},{name:"list_jit_instances",title:"List JIT Instances",description:"List all deployed JIT MCP server instances.",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:ue,handler:async s=>{let{status:n}=ue.parse(s);return o.listJitInstances(n?{status:n}:void 0)}},{name:"stop_jit_instance",title:"Stop JIT Instance",description:"Stop a running JIT MCP server instance.",annotations:{readOnlyHint:false,destructiveHint:true,openWorldHint:false},inputSchema:ge,handler:async s=>{let{instance_id:n}=ge.parse(s);return await o.stopJitInstance(n),{success:true,instance_id:n}}},{name:"transfer_usdc",title:"Transfer USDC",description:"Transfer USDC from the self-custody wallet to another address on Base. Only available when the wallet has a self-custody wallet (AGENT_WALLET_KEY set).",annotations:{readOnlyHint:false,destructiveHint:true,openWorldHint:true},inputSchema:pe,handler:async s=>{let{to:n,amount_usdc:a}=pe.parse(s);if(!await o.hasSelfCustodyWallet())throw new Error("No self-custody wallet configured. Set AGENT_WALLET_KEY to enable transfers.");return {success:true,txHash:await o.transferUSDC({to:n,amountUsdc:a}),to:n,amountUsdc:a}}},{name:"get_budget",title:"Get Available Budget",description:"Get the available delegation budget including remaining amount, whether spawning children is possible, and budget limits.",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:null,handler:async()=>o.getAvailableBudget()},{name:"spawn_child",title:"Spawn Child Session",description:"Create a child invite with a delegated budget from this wallet. Returns an invite code that another agent can claim.",annotations:{readOnlyHint:false,openWorldHint:false},inputSchema:me,handler:async s=>{let{name:n,budget_usd:a,budget_period:r,max_per_tx_usd:i,expires_in_days:l}=me.parse(s);return o.spawnChildInvite({name:n,budgetUsd:a,budgetPeriod:r,maxPerTxUsd:i,expiresInDays:l})}},{name:"list_children",title:"List Child Sessions",description:"List all child sessions (agents) spawned from this wallet.",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:null,handler:async()=>o.listChildSessions()},{name:"create_task",title:"Create Task",description:"Create a new task on the MixrPay marketplace for other agents to complete.",annotations:{readOnlyHint:false,openWorldHint:true},inputSchema:he,handler:async s=>{let{title:n,description:a,budget_usd:r,skills_required:i}=he.parse(s);return o.createTask({title:n,description:a,budgetUsd:r,skillsRequired:i})}},{name:"list_tasks",title:"List Tasks",description:"Browse available tasks on the MixrPay marketplace.",annotations:{readOnlyHint:true,openWorldHint:true},inputSchema:ye,handler:async s=>{let{status:n,limit:a}=ye.parse(s);return o.listTasks({status:n,limit:a})}}];return {definitions:e,execute:async(s,n)=>{let a=e.find(r=>r.name===s);if(!a)throw new Error(`Unknown tool: ${s}`);try{let r=await a.handler(n);return JSON.stringify(r,null,2)}catch(r){let i=r instanceof Error?r.message:String(r);throw new Error(i)}}}}function we(o){if(o instanceof zod.z.ZodObject){let e=o._def.shape(),t={},s=[];for(let[n,a]of Object.entries(e)){let r=a;t[n]=F(r),!(r instanceof zod.z.ZodOptional)&&!(r instanceof zod.z.ZodDefault)&&s.push(n);}return {type:"object",properties:t,...s.length>0?{required:s}:{}}}return {type:"object",properties:{}}}function F(o){let e=o;e instanceof zod.z.ZodOptional&&(e=e._def.innerType),e instanceof zod.z.ZodDefault&&(e=e._def.innerType);let t=o._def.description;if(e instanceof zod.z.ZodString)return {type:"string",...t&&{description:t}};if(e instanceof zod.z.ZodNumber)return {type:"number",...t&&{description:t}};if(e instanceof zod.z.ZodBoolean)return {type:"boolean",...t&&{description:t}};if(e instanceof zod.z.ZodEnum)return {type:"string",enum:e._def.values,...t&&{description:t}};if(e instanceof zod.z.ZodArray)return {type:"array",items:F(e._def.type),...t&&{description:t}};if(e instanceof zod.z.ZodRecord)return {type:"object",additionalProperties:F(e._def.valueType),...t&&{description:t}};if(e instanceof zod.z.ZodObject){let s=e._def.shape(),n={};for(let[a,r]of Object.entries(s))n[a]=F(r);return {type:"object",properties:n,...t&&{description:t}}}return e instanceof zod.z.ZodUnknown?{...t&&{description:t}}:{...t&&{description:t}}}var Ze="0.9.5",be=".config/mixrpay",Qe="wallet.json";function Se(){let o=process.env.MIXRPAY_WORKSPACE_DIR||process.env.OPENCLAW_WORKSPACE_DIR;return o?D.join(o,be):D.join(M.homedir(),be)}function $(){return D.join(Se(),Qe)}async function Z(o,e){let t=Se(),s=$();b.existsSync(t)||b.mkdirSync(t,{recursive:true,mode:448});let n={address:e.toLowerCase(),privateKey:o,createdAt:new Date().toISOString(),sdkVersion:Ze};b.writeFileSync(s,JSON.stringify(n,null,2),{encoding:"utf-8",mode:384});try{b.chmodSync(s,384);}catch{}}async function W(){let o=process.env.MIXRPAY_WALLET_KEY;if(o){if(o.startsWith("0x")&&o.length===66)return o;if(o.length===64)return `0x${o}`;console.warn("[MixrPay] MIXRPAY_WALLET_KEY has invalid format, ignoring");}let e=$();if(!b.existsSync(e))return null;try{let t=b.readFileSync(e,"utf-8"),s=JSON.parse(t);return !s.privateKey||!s.privateKey.startsWith("0x")?(console.warn("[MixrPay] Wallet file has invalid format"),null):s.privateKey}catch(t){return console.warn("[MixrPay] Failed to read wallet file:",t),null}}async function et(){let o=$();if(!b.existsSync(o)){let e=process.env.MIXRPAY_WALLET_KEY;return e&&(e.startsWith("0x")?e:`0x${e}`).length===66,null}try{let e=b.readFileSync(o,"utf-8");return JSON.parse(e)}catch{return null}}async function Q(){let o=process.env.MIXRPAY_WALLET_KEY;return o&&(o.length===64||o.startsWith("0x")&&o.length===66)?true:b.existsSync($())}function tt(){return $()}async function st(){let o=$();if(!b.existsSync(o))return false;try{let{unlinkSync:e}=await import('fs');return e(o),!0}catch{return false}}async function xe(o){let e=null,t=o.headers.get("X-Payment-Required");if(t)try{e=JSON.parse(t);}catch{}if(!e){let n=o.headers.get("WWW-Authenticate");if(n?.startsWith("X-402 "))try{let a=n.slice(6);e=JSON.parse(atob(a));}catch{}}if(!e)try{e=await o.json();}catch{}if(!e)throw new P("Could not parse payment requirements from 402 response");if(!e.recipient)throw new P("Missing recipient in payment requirements");if(!e.amount)throw new P("Missing amount in payment requirements");let s=Math.floor(Date.now()/1e3);return {recipient:e.recipient,amount:BigInt(e.amount),currency:e.currency||"USDC",chainId:e.chainId||e.chain_id||8453,facilitatorUrl:e.facilitatorUrl||e.facilitator_url||"https://x402.org/facilitator",nonce:e.nonce||Y().slice(2),expiresAt:e.expiresAt||e.expires_at||s+300,description:e.description}}async function Ae(o,e,t){let s=o.nonce.length===64?`0x${o.nonce}`:Y(),a=BigInt(Math.floor(Date.now()/1e3))-60n,r=BigInt(o.expiresAt),{domain:i,message:l}=ne({fromAddress:t,toAddress:o.recipient,value:o.amount,validAfter:a,validBefore:r,nonce:s,chainId:o.chainId}),d=await e.signTransferAuthorization(i,l),g={x402Version:1,scheme:"exact",network:o.chainId===8453?"base":"base-sepolia",payload:{signature:d,authorization:{from:t,to:o.recipient,value:o.amount.toString(),validAfter:a.toString(),validBefore:r.toString(),nonce:s}}};return btoa(JSON.stringify(g))}function ke(o){return Date.now()/1e3>o.expiresAt}function ee(o){return Number(o.amount)/1e6}var Ee="0.11.0",S=process.env.MIXRPAY_BASE_URL||"https://mixr.network";var gt=3e4,$e={BASE_MAINNET:{chainId:8453,name:"Base",isTestnet:false},BASE_SEPOLIA:{chainId:84532,name:"Base Sepolia",isTestnet:true}},De={debug:0,info:1,warn:2,error:3,none:4},te=class{level;prefix;constructor(e="none",t="[MixrPay]"){this.level=e,this.prefix=t;}setLevel(e){this.level=e;}shouldLog(e){return De[e]>=De[this.level]}debug(...e){this.shouldLog("debug")&&console.log(`${this.prefix} \u{1F50D}`,...e);}info(...e){this.shouldLog("info")&&console.log(`${this.prefix} \u2139\uFE0F`,...e);}warn(...e){this.shouldLog("warn")&&console.warn(`${this.prefix} \u26A0\uFE0F`,...e);}error(...e){this.shouldLog("error")&&console.error(`${this.prefix} \u274C`,...e);}payment(e,t,s){if(this.shouldLog("info")){let n=s?` for "${s}"`:"";console.log(`${this.prefix} \u{1F4B8} Paid $${e.toFixed(4)} to ${t.slice(0,10)}...${n}`);}}},se=class o{sessionKey;walletAddress;maxPaymentUsd;onPayment;baseUrl;timeout;logger;payments=[];totalSpentUsd=0;sessionKeyInfo;sessionKeyInfoFetchedAt;allowlist;allowlistFetchedAt;selfCustodyAddress;selfCustodyKey;agentInstanceId;apiKey;sessionKeyId;constructor(e){this.validateConfig(e),this.sessionKey=L.fromString(e.sessionKey),this.walletAddress=e.walletAddress||this.sessionKey.address,this.maxPaymentUsd=e.maxPaymentUsd,this.onPayment=e.onPayment,this.baseUrl=(e.baseUrl||S).replace(/\/$/,""),this.timeout=e.timeout||gt,e.apiKey&&(this.apiKey=e.apiKey),e.sessionKeyId&&(this.sessionKeyId=e.sessionKeyId),this.logger=new te(e.logLevel||"none"),this.logger.debug("AgentWallet initialized",{walletAddress:this.walletAddress,isTestnet:this.isTestnet(),maxPaymentUsd:this.maxPaymentUsd,hasApiKey:!!this.apiKey,hasSessionKeyId:!!this.sessionKeyId});}validateConfig(e){if(!e.sessionKey)throw new x("Session key is required. Get one from the wallet owner at https://mixrpay.com/manage/invites");let t=e.sessionKey.trim();if(!t.startsWith("sk_live_")&&!t.startsWith("sk_test_")){let a=t.slice(0,8);throw new x(`Invalid session key prefix. Expected 'sk_live_' (mainnet) or 'sk_test_' (testnet), got '${a}'`)}let s=72;if(t.length!==s)throw new x(`Invalid session key length. Expected ${s} characters, got ${t.length}. Make sure you copied the complete key.`);let n=t.slice(8);if(!/^[0-9a-fA-F]+$/.test(n))throw new x("Invalid session key format. The key should contain only hexadecimal characters after the prefix.");if(e.maxPaymentUsd!==void 0){if(e.maxPaymentUsd<=0)throw new c("maxPaymentUsd must be a positive number");e.maxPaymentUsd>1e4&&this.logger?.warn("maxPaymentUsd is very high ($"+e.maxPaymentUsd+"). Consider using a lower limit for safety.");}}async fetchAllowlist(){if(this.allowlist!==void 0&&this.allowlistFetchedAt&&Date.now()-this.allowlistFetchedAt<3e5)return this.allowlist;try{let t=await this.getSessionKeyInfo();return this.allowlist=t.allowedMerchants||[],this.allowlistFetchedAt=Date.now(),this.logger.debug("Fetched allowlist",{patterns:this.allowlist.length,allowAll:this.allowlist.length===0}),this.allowlist}catch(t){return this.logger.warn("Failed to fetch allowlist, allowing all merchants",{error:t}),this.allowlist=[],this.allowlistFetchedAt=Date.now(),this.allowlist}}async validateMerchantAllowed(e,t){let s=await this.fetchAllowlist();if(s.length===0)return;if(!this.matchesAllowlist(e,s,t))throw new K(e,s)}matchesAllowlist(e,t,s){for(let n of t)if(this.matchPattern(e,n,s))return true;return false}matchPattern(e,t,s){return s==="url"?this.matchUrlPattern(e,t):this.matchToolPattern(e,t)}matchUrlPattern(e,t){let s;try{e.includes("://")?s=new URL(e).hostname.toLowerCase():s=e.toLowerCase();}catch{return false}let a=t.toLowerCase().trim();if(a.includes("://"))try{a=new URL(a).hostname;}catch{}if(s===a)return true;if(a.startsWith("*.")){let r=a.substring(2);if(s.endsWith(`.${r}`)&&s!==r)return true}return false}matchToolPattern(e,t){let s=e.toLowerCase().trim(),n=t.toLowerCase().trim();if(s===n)return true;if(n.endsWith("/*")){let a=n.substring(0,n.length-2);if(s.startsWith(`${a}/`))return true}return false}static async register(e){let{privateKey:t,name:s}=e,n=(e.baseUrl||S).replace(/\/$/,""),r=accounts.privateKeyToAccount(t).address,i=await fetch(`${n}/api/v1/agent/challenge?wallet=${r}&action=register`);if(!i.ok){let y=await i.json().catch(()=>({}));throw new c(y.error||`Failed to get challenge: ${i.status}`)}let{challenge:l,message:d}=await i.json(),g=await accounts.signMessage({message:d,privateKey:t}),u=await fetch(`${n}/api/v1/agent/register`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({challenge:l,external_wallet:r,signature:g,name:s})});if(!u.ok){let y=await u.json().catch(()=>({})),f=y.error||`Registration failed with status ${u.status}`,h=y.request_id,w=(y.code||"").toLowerCase(),_="";u.status===503?_=" The service may be temporarily unavailable. Please try again later.":u.status===500?_=" This is a server error. Please contact support with the request ID.":(w==="missing_challenge"||w==="missing_signature")&&(_=" This may indicate an SDK bug. Please update to the latest version.");let N=h?`${f} (request_id: ${h})${_}`:`${f}${_}`;throw new c(N)}let p=await u.json();return {userId:p.user_id,depositAddress:p.deposit_address}}static async checkServerHealth(e){let t=(e||S).replace(/\/$/,"");try{let s=await fetch(`${t}/api/health/ready?details=true`);if(!s.ok)return {healthy:!1,database:"unknown",agentRegistrationAvailable:!1,walletServiceConfigured:!1,error:`Health check failed with status ${s.status}`};let n=await s.json();return {healthy:n.status==="ready",database:n.database||"unknown",agentRegistrationAvailable:n.services?.agentRegistration?.available??!1,walletServiceConfigured:n.services?.wallet?.configured??!1}}catch(s){return {healthy:false,database:"unreachable",agentRegistrationAvailable:false,walletServiceConfigured:false,error:s instanceof Error?s.message:"Failed to reach server"}}}static async getSessionKey(e){let{privateKey:t,spendingLimitUsd:s,maxPerTxUsd:n,maxDailyUsd:a,durationDays:r}=e,i=(e.baseUrl||S).replace(/\/$/,""),d=accounts.privateKeyToAccount(t).address,g=await fetch(`${i}/api/v1/agent/challenge?wallet=${d}&action=session-key`);if(!g.ok){let w=await g.json().catch(()=>({}));throw new c(w.error||`Failed to get challenge: ${g.status}`)}let{challenge:u,message:p}=await g.json(),y=await accounts.signMessage({message:p,privateKey:t}),f=await fetch(`${i}/api/v1/agent/session-key`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({challenge:u,external_wallet:d,signature:y,spending_limit_usd:s,max_per_tx_usd:n,max_daily_usd:a,duration_days:r})});if(!f.ok){let w=await f.json().catch(()=>({}));throw new c(w.error||`Session key creation failed: ${f.status}`)}let h=await f.json();return {sessionKey:h.session_key,address:h.address,sessionKeyId:h.session_key_id,expiresAt:new Date(h.expires_at),limits:{maxTotalUsd:h.limits.max_total_usd,maxPerTxUsd:h.limits.max_per_tx_usd,maxDailyUsd:h.limits.max_daily_usd}}}static async getStatus(e){let{privateKey:t}=e,s=(e.baseUrl||S).replace(/\/$/,""),a=accounts.privateKeyToAccount(t).address,r=await fetch(`${s}/api/v1/agent/challenge?wallet=${a}&action=status`);if(!r.ok){let p=await r.json().catch(()=>({}));throw new c(p.error||`Failed to get challenge: ${r.status}`)}let{challenge:i,message:l}=await r.json(),d=await accounts.signMessage({message:l,privateKey:t}),g=await fetch(`${s}/api/v1/agent/status?challenge=${i}&external_wallet=${a}&signature=${encodeURIComponent(d)}`);if(!g.ok){let p=await g.json().catch(()=>({}));throw new c(p.error||`Failed to get status: ${g.status}`)}let u=await g.json();return {depositAddress:u.deposit_address,balanceUsd:u.balance_usd,activeSessions:u.active_sessions.map(p=>({id:p.id,expiresAt:new Date(p.expires_at),totalSpentUsd:p.total_spent_usd,remainingUsd:p.remaining_usd,maxTotalUsd:p.max_total_usd})),totalSpentUsd:u.total_spent_usd}}static async revokeSessionKey(e){let{privateKey:t,sessionKeyId:s}=e,n=(e.baseUrl||S).replace(/\/$/,""),r=accounts.privateKeyToAccount(t).address,i=await fetch(`${n}/api/v1/agent/challenge?wallet=${r}&action=revoke`);if(!i.ok){let p=await i.json().catch(()=>({}));throw new c(p.error||`Failed to get challenge: ${i.status}`)}let{challenge:l,message:d}=await i.json(),g=await accounts.signMessage({message:d,privateKey:t}),u=await fetch(`${n}/api/v1/agent/session-key/revoke`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({challenge:l,external_wallet:r,signature:g,session_key_id:s})});if(!u.ok){let p=await u.json().catch(()=>({}));throw new c(p.error||`Revocation failed: ${u.status}`)}return true}static async withdraw(e){let{privateKey:t,amountUsd:s}=e,n=(e.baseUrl||S).replace(/\/$/,""),r=accounts.privateKeyToAccount(t).address,i=await fetch(`${n}/api/v1/agent/challenge?wallet=${r}&action=withdraw`);if(!i.ok){let y=await i.json().catch(()=>({}));throw new c(y.error||`Failed to get challenge: ${i.status}`)}let{challenge:l,message:d}=await i.json(),g=await accounts.signMessage({message:d,privateKey:t}),u=await fetch(`${n}/api/v1/agent/withdraw`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({challenge:l,external_wallet:r,signature:g,to_address:r,amount_usd:s})});if(!u.ok){let y=await u.json().catch(()=>({}));throw new c(y.error||`Withdrawal failed: ${u.status}`)}let p=await u.json();return {txHash:p.tx_hash,amountUsd:p.amount_usd,remainingBalanceUsd:p.remaining_balance_usd}}static async claimInvite(e){let{inviteCode:t,privateKey:s}=e,n=(e.baseUrl||S).replace(/\/$/,""),r=accounts.privateKeyToAccount(s).address,i=await fetch(`${n}/api/v1/agent/challenge?wallet=${r}&action=claim-invite`);if(!i.ok){let y=await i.json().catch(()=>({}));throw new c(y.error||`Failed to get challenge: ${i.status}`)}let{challenge:l,message:d}=await i.json(),g=await accounts.signMessage({message:d,privateKey:s}),u=await fetch(`${n}/api/v1/agent/claim-invite`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({invite_code:t,challenge:l,agent_wallet_address:r,signature:g})});if(!u.ok){let f=(await u.json().catch(()=>({}))).error||`Failed to claim invite: ${u.status}`,h="";throw u.status===404?h=" The invite code may be invalid or misspelled.":u.status===400&&(f.includes("already claimed")?h=" This invite has already been used by another agent.":f.includes("expired")?h=" Ask the wallet owner to create a new invite.":f.includes("revoked")&&(h=" The wallet owner has revoked this invite.")),new c(`${f}${h}`)}let p=await u.json();return {sessionKey:p.session_key,address:p.address,sessionKeyId:p.session_key_id,expiresAt:new Date(p.expires_at),limits:{budgetUsd:p.limits.budget_usd,budgetPeriod:p.limits.budget_period,maxPerTxUsd:p.limits.max_per_tx_usd},allowedMerchants:p.allowed_merchants||[],inviterName:p.inviter_name||"Anonymous"}}static async activate(e,t){let s=(t?.baseUrl||S).replace(/\/$/,""),n=new o({sessionKey:e,baseUrl:s}),a=await n.getSessionAuthHeaders(),r=await fetch(`${s}/api/v2/agent/activate`,{method:"POST",headers:{"Content-Type":"application/json",...a}});if(!r.ok){let l=await r.json().catch(()=>({}));throw new c(l.error||`Activation failed: ${r.status}`)}let i=await r.json();return {wallet:n,budget:{maxTotalUsd:i.budget.max_total_usd,maxDailyUsd:i.budget.max_daily_usd,maxPerTxUsd:i.budget.max_per_tx_usd,spentUsd:i.budget.spent_usd,remainingUsd:i.budget.remaining_usd},capabilities:{executeTransactions:i.capabilities.execute_transactions,gasSponsored:i.capabilities.gas_sponsored,batchedTx:i.capabilities.batched_tx},skills:i.skills||[],tools:i.tools||[],gatewayProviders:i.gateway_providers||[]}}static async connect(e){let t=(e?.baseUrl||process.env.MIXRPAY_BASE_URL||S).replace(/\/$/,""),s=e?.logLevel||"none",n=process.env.MIXRPAY_INSTANCE_ID;if(e?.sessionKey){let g=new o({sessionKey:e.sessionKey,sessionKeyId:e.sessionKeyId,baseUrl:t,logLevel:s,maxPaymentUsd:e?.maxPaymentUsd,onPayment:e?.onPayment});return n&&g.setAgentInstanceId(n),g}let a=process.env.MIXRPAY_SESSION_KEY;if(a){let g=process.env.MIXRPAY_SESSION_KEY_ID,u=new o({sessionKey:a,sessionKeyId:g,baseUrl:t,logLevel:s,maxPaymentUsd:e?.maxPaymentUsd,onPayment:e?.onPayment});return n&&u.setAgentInstanceId(n),u}let r=process.env.MIXRPAY_API_KEY||process.env.MIXRPAY_AGENT_TOKEN;if(r&&(r.startsWith("agt_live_")||r.startsWith("agt_test_")))return o.fromApiKey(r,{baseUrl:t,logLevel:s});let i=e?.accessCode||process.env.MIXRPAY_ACCESS_CODE;if(i)return o.fromAccessCode(i,{baseUrl:t,logLevel:s});let l=e?.masterKey||process.env.MIXRPAY_MASTER_KEY,d=e?.agentName||process.env.MIXRPAY_AGENT_NAME;if(l&&d)return o.fromMasterKey(l,d,{baseUrl:t,logLevel:s});try{let{loadCredentials:g}=await Promise.resolve().then(()=>(H(),J)),u=g();if(u.success&&u.credentials.sessionKey){let p=new o({sessionKey:u.credentials.sessionKey,sessionKeyId:u.credentials.sessionKeyId,baseUrl:u.credentials.baseUrl||t,logLevel:s,maxPaymentUsd:e?.maxPaymentUsd,onPayment:e?.onPayment,apiKey:u.credentials.apiToken});return n&&p.setAgentInstanceId(n),p}if(u.success&&u.credentials.apiToken)return o.fromApiKey(u.credentials.apiToken,{baseUrl:t,logLevel:s});if(u.success&&u.credentials.masterKey&&u.credentials.defaultAgentName)return o.fromMasterKey(u.credentials.masterKey,u.credentials.defaultAgentName,{baseUrl:t,logLevel:s})}catch{}if(e?.interactive)return o.deviceFlowLogin({baseUrl:t,logLevel:s});throw new c(`No MixrPay credentials found. Options:
2
- 1. Set MIXRPAY_SESSION_KEY environment variable
3
- 2. Set MIXRPAY_API_KEY or MIXRPAY_AGENT_TOKEN environment variable (agt_live_xxx)
4
- 3. Set MIXRPAY_ACCESS_CODE environment variable (mixr-xxx)
5
- 4. Pass sessionKey or accessCode to connect()
6
- 5. Run \`npx mixrpay login\` to cache credentials
7
- 6. Use connect({ interactive: true }) for browser login`)}static async fromApiKey(e,t){let s=(t?.baseUrl||S).replace(/\/$/,"");if(!e.startsWith("agt_live_")&&!e.startsWith("agt_test_"))throw new c(`Invalid API key format. Expected 'agt_live_' or 'agt_test_' prefix, got '${e.slice(0,9)}...'`);let n=await fetch(`${s}/api/v2/agent/session-from-token`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`}});if(!n.ok){let l=await n.json().catch(()=>({}));throw new c(l.error||`Failed to exchange API key for session: ${n.status}`)}let a=await n.json(),r=a.session_key;if(!r)throw new c("No session_key in API response");let i=new o({sessionKey:r,baseUrl:s,logLevel:t?.logLevel});return i.setApiKey(e),a.agent_instance_id&&i.setAgentInstanceId(a.agent_instance_id),i}static async fromAccessCode(e,t){let s=(t?.baseUrl||S).replace(/\/$/,"");if(!e.startsWith("mixr-"))throw new c(`Invalid access code format. Expected 'mixr-' prefix, got '${e.slice(0,5)}...'`);let n=await fetch(`${s}/api/v2/agent/connect`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({code:e})});if(!n.ok){let g=await n.json().catch(()=>({})),u=(g.code||"").toLowerCase(),p="";throw n.status===404||u==="invalid_code"?p=" Check the code for typos or get a new one from the MixrPay dashboard.":n.status===400&&(u==="code_claimed"?p=" This code has already been used. Get a new code from the dashboard.":u==="code_expired"?p=" This code has expired. Get a new code from the dashboard.":u==="code_revoked"&&(p=" This code has been revoked by the owner.")),new c((g.error||`Failed to activate access code: ${n.status}`)+p)}let a=await n.json(),r=a.session_key,i=a.token,l=a.agent_id;if(!r)throw new c("No session_key in access code response");try{let{saveCredentials:g}=await Promise.resolve().then(()=>(H(),J));g({sessionKey:r,apiToken:i,baseUrl:s});}catch{}let d=new o({sessionKey:r,baseUrl:s,logLevel:t?.logLevel});return i&&(d.apiKey=i),l&&(d.agentInstanceId=l),d}static async fromMasterKey(e,t,s){let n=(s?.baseUrl||S).replace(/\/$/,"");if(!e.startsWith("mk_live_")&&!e.startsWith("mk_test_"))throw new c("Invalid master key format. Expected 'mk_live_' or 'mk_test_' prefix.");let a=await fetch(`${n}/api/v2/master-keys/session`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify({agent_name:t})});if(!a.ok){let g=await a.json().catch(()=>({}));throw a.status===404?new c(`Agent '${t}' not found. Use the MixrPay dashboard to create it.`):new c(g.error||`Failed to get session from master key: ${a.status}`)}let r=await a.json(),i=r.session_key,l=r.session_key_id;if(!i)throw new c("No session_key in master key response");let d=new o({sessionKey:i,sessionKeyId:l,baseUrl:n,logLevel:s?.logLevel});return r.agent?.id&&(d.agentInstanceId=r.agent.id),d}static async deviceFlowLogin(e){let t=(e?.baseUrl||S).replace(/\/$/,""),s=await fetch(`${t}/api/v2/auth/device/authorize`,{method:"POST",headers:{"Content-Type":"application/json"}});if(!s.ok){let y=await s.json().catch(()=>({}));throw new c(y.error||`Device flow initiation failed: ${s.status}`)}let n=await s.json(),{device_code:a,user_code:r,verification_uri:i,verification_uri_complete:l,expires_in:d,interval:g}=n;console.log(`
1
+ 'use strict';var b=require('fs'),D=require('path'),M=require('os'),url=require('url'),accounts=require('viem/accounts'),zod=require('zod'),viem=require('viem'),chains=require('viem/chains');var _documentCurrentScript=typeof document!=='undefined'?document.currentScript:null;function _interopNamespace(e){if(e&&e.__esModule)return e;var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var b__namespace=/*#__PURE__*/_interopNamespace(b);var D__namespace=/*#__PURE__*/_interopNamespace(D);var M__namespace=/*#__PURE__*/_interopNamespace(M);var Ke=Object.defineProperty;var je=(o,e)=>()=>(o&&(e=o(o=0)),e);var Me=(o,e)=>{for(var t in e)Ke(o,t,{get:e[t],enumerable:true});};var J={};Me(J,{deleteCredentials:()=>Ue,getCredentialsFilePath:()=>Ce,hasCredentials:()=>Ie,loadCredentials:()=>B,saveCredentials:()=>Pe});function ve(){if(M__namespace.platform()==="win32"){let t=process.env.APPDATA||D__namespace.join(M__namespace.homedir(),"AppData","Roaming");return D__namespace.join(t,"mixrpay")}let e=process.env.XDG_CONFIG_HOME||D__namespace.join(M__namespace.homedir(),".config");return D__namespace.join(e,"mixrpay")}function q(){return D__namespace.join(ve(),"credentials.json")}function nt(){let o=ve();b__namespace.existsSync(o)||b__namespace.mkdirSync(o,{recursive:true,mode:448});}function Te(o){try{b__namespace.chmodSync(o,384);}catch{}}function Pe(o){try{nt();let e=q(),t={};if(b__namespace.existsSync(e))try{let a=b__namespace.readFileSync(e,"utf-8");t=JSON.parse(a);}catch{t={};}let s={...t,...o,updatedAt:new Date().toISOString()},n=Object.fromEntries(Object.entries(s).filter(([a,r])=>r!==void 0));return b__namespace.writeFileSync(e,JSON.stringify(n,null,2),{mode:384}),Te(e),!0}catch(e){return console.error("[MixrPay] Failed to save credentials:",e),false}}function B(){try{let o=q();if(!b__namespace.existsSync(o))return {success:!0,credentials:{}};let e=b__namespace.readFileSync(o,"utf-8");return {success:!0,credentials:JSON.parse(e)}}catch(o){return {success:false,error:o instanceof Error?o.message:"Failed to load credentials"}}}function Ue(o){try{let e=q();if(!b__namespace.existsSync(e))return !0;if(!o)return b__namespace.unlinkSync(e),!0;let t=B();if(!t.success)return !1;let s={...t.credentials};for(let n of o)delete s[n];return Object.keys(s).length===0?b__namespace.unlinkSync(e):(b__namespace.writeFileSync(e,JSON.stringify(s,null,2),{mode:384}),Te(e)),!0}catch(e){return console.error("[MixrPay] Failed to delete credentials:",e),false}}function Ie(){let o=B();if(!o.success)return false;let{credentials:e}=o;return !!(e.sessionKey||e.apiToken||e.masterKey)}function Ce(){return q()}var H=je(()=>{});var c=class extends Error{code;retryAfterMs;constructor(e,t="MIXRPAY_ERROR",s){super(e),this.name="MixrPayError",this.code=t,this.retryAfterMs=s,Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor);}isRetryable(){return false}},v=class extends c{required;available;topUpUrl;constructor(e,t){let s=e-t;super(`Insufficient balance: need $${e.toFixed(2)}, have $${t.toFixed(2)} (short $${s.toFixed(2)}). Top up your wallet to continue.`,"INSUFFICIENT_BALANCE"),this.name="InsufficientBalanceError",this.required=e,this.available=t,this.topUpUrl="https://mixr.network/manage/wallet";}},E=class extends c{expiredAt;constructor(e){super(`Session key expired at ${e}. Request a new session key from the wallet owner at https://mixrpay.com/manage/invites`,"SESSION_KEY_EXPIRED"),this.name="SessionKeyExpiredError",this.expiredAt=e;}},T=class extends c{limitType;limit;attempted;constructor(e,t,s){let a={per_tx:"Per-transaction",daily:"Daily",total:"Total",client_max:"Client-side"}[e]||e,r=e==="daily"?"Wait until tomorrow or request a higher limit.":e==="client_max"?"Increase maxPaymentUsd in your AgentWallet configuration.":"Request a new session key with a higher limit.";super(`${a} spending limit exceeded: limit is $${t.toFixed(2)}, attempted $${s.toFixed(2)}. ${r}`,"SPENDING_LIMIT_EXCEEDED"),this.name="SpendingLimitExceededError",this.limitType=e,this.limit=t,this.attempted=s;}isRetryable(){return this.limitType==="daily"}},k=class extends c{reason;txHash;constructor(e,t){let s=`Payment failed: ${e}`;t&&(s+=` (tx: ${t} - check on basescan.org)`),super(s,"PAYMENT_FAILED"),this.name="PaymentFailedError",this.reason=e,this.txHash=t;}isRetryable(){return true}},x=class extends c{reason;constructor(e="Invalid session key format"){super(`${e}. Session keys should be in format: sk_live_<64 hex chars> or sk_test_<64 hex chars>. Get one from https://mixrpay.com/manage/invites`,"INVALID_SESSION_KEY"),this.name="InvalidSessionKeyError",this.reason=e;}},P=class extends c{reason;constructor(e){super(`x402 protocol error: ${e}. This may indicate a server configuration issue. If the problem persists, contact the API provider.`,"X402_PROTOCOL_ERROR"),this.name="X402ProtocolError",this.reason=e;}isRetryable(){return true}},O=class extends c{sessionId;expiredAt;constructor(e,t){super(`Session ${e} has expired${t?` at ${t}`:""}. A new session will be created automatically on your next request.`,"SESSION_EXPIRED"),this.name="SessionExpiredError",this.sessionId=e,this.expiredAt=t;}},I=class extends c{sessionId;limit;requested;remaining;constructor(e,t,s,n){super(`Session spending limit exceeded: limit is $${e.toFixed(2)}, requested $${t.toFixed(2)}, remaining $${s.toFixed(2)}. Create a new session with a higher limit to continue.`,"SESSION_LIMIT_EXCEEDED"),this.name="SessionLimitExceededError",this.sessionId=n,this.limit=e,this.requested=t,this.remaining=s;}},C=class extends c{sessionId;constructor(e){super(`Session ${e} not found. It may have been deleted or never existed. Create a new session with getOrCreateSession().`,"SESSION_NOT_FOUND"),this.name="SessionNotFoundError",this.sessionId=e;}},R=class extends c{sessionId;reason;constructor(e,t){super(`Session ${e} has been revoked${t?`: ${t}`:""}. Create a new session with getOrCreateSession().`,"SESSION_REVOKED"),this.name="SessionRevokedError",this.sessionId=e,this.reason=t;}},K=class extends c{attempted;allowedPatterns;constructor(e,t){let s=t.slice(0,3).join(", "),n=t.length>3?"...":"";super(`Payment to "${e}" not allowed. Session allowlist: ${s}${n}. Update the session allowlist or create a new session.`,"MERCHANT_NOT_ALLOWED"),this.name="MerchantNotAllowedError",this.attempted=e,this.allowedPatterns=t;}},G=class extends c{constructor(e=6e4,t){super(t||`Rate limit exceeded. Please wait ${Math.ceil(e/1e3)} seconds before retrying.`,"RATE_LIMIT_EXCEEDED",e),this.name="RateLimitError";}isRetryable(){return true}},X=class extends c{reason;constructor(e,t){super(`Network error: ${e}. Check your connection and try again.`,"NETWORK_ERROR",5e3),this.name="NetworkError",this.reason=e,t?.stack&&(this.stack=t.stack);}isRetryable(){return true}},z=class extends c{reason;statusCode;constructor(e,t=401){super(`Authentication failed: ${e}`,t===401?"UNAUTHORIZED":"FORBIDDEN"),this.name="AuthenticationError",this.reason=e,this.statusCode=t;}isRetryable(){return false}};function He(o){return o instanceof c}function Ne(o){return o instanceof c||o instanceof Error?o.message:String(o)}var qe={8453:"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",84532:"0x036CbD53842c5426634e7929541eC2318f3dCF7e"},Be={name:"USD Coin",version:"2"},Je={TransferWithAuthorization:[{name:"from",type:"address"},{name:"to",type:"address"},{name:"value",type:"uint256"},{name:"validAfter",type:"uint256"},{name:"validBefore",type:"uint256"},{name:"nonce",type:"bytes32"}]},L=class o{privateKey;account;address;isTest;constructor(e,t){this.privateKey=e,this.account=accounts.privateKeyToAccount(e),this.address=this.account.address,this.isTest=t;}toString(){return `${this.isTest?"sk_test_":"sk_live_"}${this.privateKey.slice(2)}`}get privateKeyHex(){return this.privateKey.slice(2)}get rawPrivateKey(){return this.privateKey}static fromString(e){let t=/^sk_(live|test)_([a-fA-F0-9]{64})$/,s=e.match(t);if(!s)throw new x("Session key must be in format sk_live_{64_hex} or sk_test_{64_hex}");let n=s[1],a=s[2];try{let r=`0x${a}`;return new o(r,n==="test")}catch(r){throw new x(`Failed to decode session key: ${r}`)}}async signTransferAuthorization(e,t){return accounts.signTypedData({privateKey:this.privateKey,domain:e,types:Je,primaryType:"TransferWithAuthorization",message:t})}async signMessage(e){return accounts.signMessage({privateKey:this.privateKey,message:e})}getDefaultChainId(){return this.isTest?84532:8453}};function ne(o){let e=qe[o.chainId];if(!e)throw new Error(`USDC not supported on chain ${o.chainId}`);let t={...Be,chainId:o.chainId,verifyingContract:e},s={from:o.fromAddress,to:o.toAddress,value:o.value,validAfter:o.validAfter,validBefore:o.validBefore,nonce:o.nonce};return {domain:t,message:s}}function Y(){let o=new Uint8Array(32);return crypto.getRandomValues(o),`0x${Array.from(o).map(e=>e.toString(16).padStart(2,"0")).join("")}`}function Ge(o,e){return `MixrPay:${o}:${e.toLowerCase()}`}async function ae(o){let e=Date.now(),t=Ge(e,o.address),s=await o.signMessage(t);return {address:o.address,timestamp:e,signature:s}}var re=zod.z.object({query:zod.z.string().describe('Search query (e.g. "web scraping", "email", "database")')}),ie=zod.z.object({tool_name:zod.z.string().describe('Tool name in "merchant/tool" format'),arguments:zod.z.record(zod.z.unknown()).optional().describe("Arguments to pass to the tool")}),oe=zod.z.object({url:zod.z.string().url().describe("The merchant API URL to call"),merchant_public_key:zod.z.string().describe("The merchant's MixrPay public key (pk_live_... or pk_test_...)"),method:zod.z.enum(["GET","POST","PUT","PATCH","DELETE"]).default("POST").describe("HTTP method"),body:zod.z.unknown().optional().describe("Request body (will be JSON-serialized)"),price_usd:zod.z.number().optional().describe("Expected price in USD for client-side validation")}),le=zod.z.object({skill_id:zod.z.string().describe("The skill ID to execute"),input:zod.z.record(zod.z.unknown()).optional().describe("Input parameters for the skill")}),ce=zod.z.object({skill_id:zod.z.string().describe("The skill ID to check")}),de=zod.z.object({glama_id:zod.z.string().describe('Glama server ID (e.g. "notion-mcp")'),glama_namespace:zod.z.string().describe('Glama namespace (e.g. "notion")'),glama_slug:zod.z.string().describe('Glama slug (e.g. "notion-mcp")'),tool_name:zod.z.string().describe("Human-readable name for the tool"),tool_description:zod.z.string().optional().describe("Optional description"),env_vars:zod.z.record(zod.z.string()).optional().describe("Environment variables for the MCP server (e.g. API keys)"),ttl_hours:zod.z.number().min(1).max(168).optional().describe("Time-to-live in hours (default: 24, max: 168)")}),ue=zod.z.object({status:zod.z.enum(["provisioning","active","stopped","expired"]).optional().describe("Filter by status")}),ge=zod.z.object({instance_id:zod.z.string().describe("The instance ID to stop")}),pe=zod.z.object({to:zod.z.string().describe("Recipient address (0x...)"),amount_usdc:zod.z.number().positive().describe("Amount in USDC (e.g. 10.5)")}),me=zod.z.object({name:zod.z.string().describe("Name for the child agent"),budget_usd:zod.z.number().positive().describe("Budget to delegate in USD"),budget_period:zod.z.enum(["daily","monthly","total"]).default("total").describe("Budget period"),max_per_tx_usd:zod.z.number().positive().optional().describe("Max per-transaction limit in USD"),expires_in_days:zod.z.number().min(1).max(365).optional().describe("Expiry in days (default: 30)")}),he=zod.z.object({title:zod.z.string().describe("Task title"),description:zod.z.string().describe("Detailed task description"),budget_usd:zod.z.number().positive().describe("Budget for the task in USD"),skills_required:zod.z.array(zod.z.string()).optional().describe("Required skill IDs")}),ye=zod.z.object({status:zod.z.string().optional().describe('Filter by status (e.g. "open", "in_progress")'),limit:zod.z.number().min(1).max(100).optional().describe("Number of results (default: 20)")});function fe(o){let e=[{name:"check_balance",title:"Check Balance",description:"Get the USDC balance of the wallet on Base.",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:null,handler:async()=>({balanceUsd:await o.getBalance(),network:o.isTestnet()?"base-sepolia":"base"})},{name:"get_spending_stats",title:"Get Spending Stats",description:"Get session key spending limits and current usage (total spent, remaining daily/total limits, expiry).",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:null,handler:async()=>o.getSpendingStats()},{name:"get_session_info",title:"Get Session Info",description:"Get detailed session key information including limits, usage, expiry, and allowed merchants.",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:null,handler:async()=>o.getSessionKeyInfo(true)},{name:"run_diagnostics",title:"Run Diagnostics",description:"Run a full health check on the wallet: API connectivity, session key validity, balance, and latency.",annotations:{readOnlyHint:true,openWorldHint:true},inputSchema:null,handler:async()=>o.runDiagnostics()},{name:"list_tools",title:"List Marketplace Tools",description:"Browse all available paid API tools on the MixrPay marketplace. Each tool includes pricing and description.",annotations:{readOnlyHint:true,openWorldHint:true},inputSchema:null,handler:async()=>o.listTools()},{name:"search_tools",title:"Search Tools",description:"Search the Glama MCP server directory for tools by keyword.",annotations:{readOnlyHint:true,openWorldHint:true},inputSchema:re,handler:async s=>{let{query:n}=re.parse(s);return o.searchGlamaDirectory(n)}},{name:"call_tool",title:"Call Marketplace Tool",description:'Call a paid API tool on the MixrPay marketplace. Payment is automatic from the wallet. Tool names are in "merchant/tool" format (e.g. "firecrawl/scrape").',annotations:{readOnlyHint:false,openWorldHint:true},inputSchema:ie,handler:async s=>{let{tool_name:n,arguments:a}=ie.parse(s);return o.callTool(n,a||{})}},{name:"call_merchant_api",title:"Call Merchant API",description:"Call any merchant API endpoint with x402 payment. The wallet handles authentication and payment automatically.",annotations:{readOnlyHint:false,openWorldHint:true},inputSchema:oe,handler:async s=>{let{url:n,merchant_public_key:a,method:r,body:i,price_usd:l}=oe.parse(s),d=await o.callMerchantApi({url:n,merchantPublicKey:a,method:r,body:i,priceUsd:l}),g=await d.json().catch(()=>d.text());return {status:d.status,data:g}}},{name:"list_skills",title:"List Skills",description:"List all available skills (pre-built integrations) that the wallet can use.",annotations:{readOnlyHint:true,openWorldHint:true},inputSchema:null,handler:async()=>o.listSkills()},{name:"use_skill",title:"Use Skill",description:"Execute a skill by ID. Skills are pre-built integrations (e.g. web scraping, email sending).",annotations:{readOnlyHint:false,openWorldHint:true},inputSchema:le,handler:async s=>{let{skill_id:n,input:a}=le.parse(s);return o.useSkill(n,{input:a})}},{name:"get_skill_status",title:"Get Skill Status",description:"Check the status and configuration of a specific skill.",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:ce,handler:async s=>{let{skill_id:n}=ce.parse(s);return o.getSkillStatus(n)}},{name:"deploy_jit_mcp",title:"Deploy JIT MCP Server",description:"Deploy a just-in-time MCP server from the Glama directory. Creates a temporary hosted MCP server instance.",annotations:{readOnlyHint:false,openWorldHint:true},inputSchema:de,handler:async s=>{let{glama_id:n,glama_namespace:a,glama_slug:r,tool_name:i,tool_description:l,env_vars:d,ttl_hours:g}=de.parse(s);return o.deployJitMcp({glamaId:n,glamaNamespace:a,glamaSlug:r,toolName:i,toolDescription:l,envVars:d,ttlHours:g})}},{name:"list_jit_instances",title:"List JIT Instances",description:"List all deployed JIT MCP server instances.",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:ue,handler:async s=>{let{status:n}=ue.parse(s);return o.listJitInstances(n?{status:n}:void 0)}},{name:"stop_jit_instance",title:"Stop JIT Instance",description:"Stop a running JIT MCP server instance.",annotations:{readOnlyHint:false,destructiveHint:true,openWorldHint:false},inputSchema:ge,handler:async s=>{let{instance_id:n}=ge.parse(s);return await o.stopJitInstance(n),{success:true,instance_id:n}}},{name:"transfer_usdc",title:"Transfer USDC",description:"Transfer USDC from the self-custody wallet to another address on Base. Only available when the wallet has a self-custody wallet (AGENT_WALLET_KEY set).",annotations:{readOnlyHint:false,destructiveHint:true,openWorldHint:true},inputSchema:pe,handler:async s=>{let{to:n,amount_usdc:a}=pe.parse(s);if(!await o.hasSelfCustodyWallet())throw new Error("No self-custody wallet configured. Set AGENT_WALLET_KEY to enable transfers.");return {success:true,txHash:await o.transferUSDC({to:n,amountUsdc:a}),to:n,amountUsdc:a}}},{name:"get_budget",title:"Get Available Budget",description:"Get the available delegation budget including remaining amount, whether spawning children is possible, and budget limits.",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:null,handler:async()=>o.getAvailableBudget()},{name:"spawn_child",title:"Spawn Child Session",description:"Create a child invite with a delegated budget from this wallet. Returns an invite code that another agent can claim.",annotations:{readOnlyHint:false,openWorldHint:false},inputSchema:me,handler:async s=>{let{name:n,budget_usd:a,budget_period:r,max_per_tx_usd:i,expires_in_days:l}=me.parse(s);return o.spawnChildInvite({name:n,budgetUsd:a,budgetPeriod:r,maxPerTxUsd:i,expiresInDays:l})}},{name:"list_children",title:"List Child Sessions",description:"List all child sessions (agents) spawned from this wallet.",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:null,handler:async()=>o.listChildSessions()},{name:"create_task",title:"Create Task",description:"Create a new task on the MixrPay marketplace for other agents to complete.",annotations:{readOnlyHint:false,openWorldHint:true},inputSchema:he,handler:async s=>{let{title:n,description:a,budget_usd:r,skills_required:i}=he.parse(s);return o.createTask({title:n,description:a,budgetUsd:r,skillsRequired:i})}},{name:"list_tasks",title:"List Tasks",description:"Browse available tasks on the MixrPay marketplace.",annotations:{readOnlyHint:true,openWorldHint:true},inputSchema:ye,handler:async s=>{let{status:n,limit:a}=ye.parse(s);return o.listTasks({status:n,limit:a})}}];return {definitions:e,execute:async(s,n)=>{let a=e.find(r=>r.name===s);if(!a)throw new Error(`Unknown tool: ${s}`);try{let r=await a.handler(n);return JSON.stringify(r,null,2)}catch(r){let i=r instanceof Error?r.message:String(r);throw new Error(i)}}}}function we(o){if(o instanceof zod.z.ZodObject){let e=o._def.shape(),t={},s=[];for(let[n,a]of Object.entries(e)){let r=a;t[n]=F(r),!(r instanceof zod.z.ZodOptional)&&!(r instanceof zod.z.ZodDefault)&&s.push(n);}return {type:"object",properties:t,...s.length>0?{required:s}:{}}}return {type:"object",properties:{}}}function F(o){let e=o;e instanceof zod.z.ZodOptional&&(e=e._def.innerType),e instanceof zod.z.ZodDefault&&(e=e._def.innerType);let t=o._def.description;if(e instanceof zod.z.ZodString)return {type:"string",...t&&{description:t}};if(e instanceof zod.z.ZodNumber)return {type:"number",...t&&{description:t}};if(e instanceof zod.z.ZodBoolean)return {type:"boolean",...t&&{description:t}};if(e instanceof zod.z.ZodEnum)return {type:"string",enum:e._def.values,...t&&{description:t}};if(e instanceof zod.z.ZodArray)return {type:"array",items:F(e._def.type),...t&&{description:t}};if(e instanceof zod.z.ZodRecord)return {type:"object",additionalProperties:F(e._def.valueType),...t&&{description:t}};if(e instanceof zod.z.ZodObject){let s=e._def.shape(),n={};for(let[a,r]of Object.entries(s))n[a]=F(r);return {type:"object",properties:n,...t&&{description:t}}}return e instanceof zod.z.ZodUnknown?{...t&&{description:t}}:{...t&&{description:t}}}var Ze="0.9.5",be=".config/mixrpay",Qe="wallet.json";function Se(){let o=process.env.MIXRPAY_WORKSPACE_DIR||process.env.OPENCLAW_WORKSPACE_DIR;return o?D.join(o,be):D.join(M.homedir(),be)}function $(){return D.join(Se(),Qe)}async function Z(o,e){let t=Se(),s=$();b.existsSync(t)||b.mkdirSync(t,{recursive:true,mode:448});let n={address:e.toLowerCase(),privateKey:o,createdAt:new Date().toISOString(),sdkVersion:Ze};b.writeFileSync(s,JSON.stringify(n,null,2),{encoding:"utf-8",mode:384});try{b.chmodSync(s,384);}catch{}}async function W(){let o=process.env.MIXRPAY_WALLET_KEY;if(o){if(o.startsWith("0x")&&o.length===66)return o;if(o.length===64)return `0x${o}`;console.warn("[MixrPay] MIXRPAY_WALLET_KEY has invalid format, ignoring");}let e=$();if(!b.existsSync(e))return null;try{let t=b.readFileSync(e,"utf-8"),s=JSON.parse(t);return !s.privateKey||!s.privateKey.startsWith("0x")?(console.warn("[MixrPay] Wallet file has invalid format"),null):s.privateKey}catch(t){return console.warn("[MixrPay] Failed to read wallet file:",t),null}}async function et(){let o=$();if(!b.existsSync(o)){let e=process.env.MIXRPAY_WALLET_KEY;return e&&(e.startsWith("0x")?e:`0x${e}`).length===66,null}try{let e=b.readFileSync(o,"utf-8");return JSON.parse(e)}catch{return null}}async function Q(){let o=process.env.MIXRPAY_WALLET_KEY;return o&&(o.length===64||o.startsWith("0x")&&o.length===66)?true:b.existsSync($())}function tt(){return $()}async function st(){let o=$();if(!b.existsSync(o))return false;try{let{unlinkSync:e}=await import('fs');return e(o),!0}catch{return false}}async function xe(o){let e=null,t=o.headers.get("X-Payment-Required");if(t)try{e=JSON.parse(t);}catch{}if(!e){let n=o.headers.get("WWW-Authenticate");if(n?.startsWith("X-402 "))try{let a=n.slice(6);e=JSON.parse(atob(a));}catch{}}if(!e)try{e=await o.json();}catch{}if(!e)throw new P("Could not parse payment requirements from 402 response");if(!e.recipient)throw new P("Missing recipient in payment requirements");if(!e.amount)throw new P("Missing amount in payment requirements");let s=Math.floor(Date.now()/1e3);return {recipient:e.recipient,amount:BigInt(e.amount),currency:e.currency||"USDC",chainId:e.chainId||e.chain_id||8453,facilitatorUrl:e.facilitatorUrl||e.facilitator_url||"https://x402.org/facilitator",nonce:e.nonce||Y().slice(2),expiresAt:e.expiresAt||e.expires_at||s+300,description:e.description}}async function Ae(o,e,t){let s=o.nonce.length===64?`0x${o.nonce}`:Y(),a=BigInt(Math.floor(Date.now()/1e3))-60n,r=BigInt(o.expiresAt),{domain:i,message:l}=ne({fromAddress:t,toAddress:o.recipient,value:o.amount,validAfter:a,validBefore:r,nonce:s,chainId:o.chainId}),d=await e.signTransferAuthorization(i,l),g={x402Version:1,scheme:"exact",network:o.chainId===8453?"base":"base-sepolia",payload:{signature:d,authorization:{from:t,to:o.recipient,value:o.amount.toString(),validAfter:a.toString(),validBefore:r.toString(),nonce:s}}};return btoa(JSON.stringify(g))}function ke(o){return Date.now()/1e3>o.expiresAt}function ee(o){return Number(o.amount)/1e6}var Ee="0.11.0",S=process.env.MIXRPAY_BASE_URL||"https://mixr.network";var gt=3e4,$e={BASE_MAINNET:{chainId:8453,name:"Base",isTestnet:false},BASE_SEPOLIA:{chainId:84532,name:"Base Sepolia",isTestnet:true}},De={debug:0,info:1,warn:2,error:3,none:4},te=class{level;prefix;constructor(e="none",t="[MixrPay]"){this.level=e,this.prefix=t;}setLevel(e){this.level=e;}shouldLog(e){return De[e]>=De[this.level]}debug(...e){this.shouldLog("debug")&&console.log(`${this.prefix} \u{1F50D}`,...e);}info(...e){this.shouldLog("info")&&console.log(`${this.prefix} \u2139\uFE0F`,...e);}warn(...e){this.shouldLog("warn")&&console.warn(`${this.prefix} \u26A0\uFE0F`,...e);}error(...e){this.shouldLog("error")&&console.error(`${this.prefix} \u274C`,...e);}payment(e,t,s){if(this.shouldLog("info")){let n=s?` for "${s}"`:"";console.log(`${this.prefix} \u{1F4B8} Paid $${e.toFixed(4)} to ${t.slice(0,10)}...${n}`);}}},se=class o{sessionKey;walletAddress;maxPaymentUsd;onPayment;baseUrl;timeout;logger;payments=[];totalSpentUsd=0;sessionKeyInfo;sessionKeyInfoFetchedAt;allowlist;allowlistFetchedAt;selfCustodyAddress;selfCustodyKey;agentInstanceId;apiKey;sessionKeyId;constructor(e){this.validateConfig(e),this.sessionKey=L.fromString(e.sessionKey),this.walletAddress=e.walletAddress||this.sessionKey.address,this.maxPaymentUsd=e.maxPaymentUsd,this.onPayment=e.onPayment,this.baseUrl=(e.baseUrl||S).replace(/\/$/,""),this.timeout=e.timeout||gt,e.apiKey&&(this.apiKey=e.apiKey),e.sessionKeyId&&(this.sessionKeyId=e.sessionKeyId),this.logger=new te(e.logLevel||"none"),this.logger.debug("AgentWallet initialized",{walletAddress:this.walletAddress,isTestnet:this.isTestnet(),maxPaymentUsd:this.maxPaymentUsd,hasApiKey:!!this.apiKey,hasSessionKeyId:!!this.sessionKeyId});}validateConfig(e){if(!e.sessionKey)throw new x("Session key is required. Get one from the wallet owner at https://mixrpay.com/manage/invites");let t=e.sessionKey.trim();if(!t.startsWith("sk_live_")&&!t.startsWith("sk_test_")){let a=t.slice(0,8);throw new x(`Invalid session key prefix. Expected 'sk_live_' (mainnet) or 'sk_test_' (testnet), got '${a}'`)}let s=72;if(t.length!==s)throw new x(`Invalid session key length. Expected ${s} characters, got ${t.length}. Make sure you copied the complete key.`);let n=t.slice(8);if(!/^[0-9a-fA-F]+$/.test(n))throw new x("Invalid session key format. The key should contain only hexadecimal characters after the prefix.");if(e.maxPaymentUsd!==void 0){if(e.maxPaymentUsd<=0)throw new c("maxPaymentUsd must be a positive number");e.maxPaymentUsd>1e4&&this.logger?.warn("maxPaymentUsd is very high ($"+e.maxPaymentUsd+"). Consider using a lower limit for safety.");}}async fetchAllowlist(){if(this.allowlist!==void 0&&this.allowlistFetchedAt&&Date.now()-this.allowlistFetchedAt<3e5)return this.allowlist;try{let t=await this.getSessionKeyInfo();return this.allowlist=t.allowedMerchants||[],this.allowlistFetchedAt=Date.now(),this.logger.debug("Fetched allowlist",{patterns:this.allowlist.length,allowAll:this.allowlist.length===0}),this.allowlist}catch(t){return this.logger.warn("Failed to fetch allowlist, allowing all merchants",{error:t}),this.allowlist=[],this.allowlistFetchedAt=Date.now(),this.allowlist}}async validateMerchantAllowed(e,t){let s=await this.fetchAllowlist();if(s.length===0)return;if(!this.matchesAllowlist(e,s,t))throw new K(e,s)}matchesAllowlist(e,t,s){for(let n of t)if(this.matchPattern(e,n,s))return true;return false}matchPattern(e,t,s){return s==="url"?this.matchUrlPattern(e,t):this.matchToolPattern(e,t)}matchUrlPattern(e,t){let s;try{e.includes("://")?s=new URL(e).hostname.toLowerCase():s=e.toLowerCase();}catch{return false}let a=t.toLowerCase().trim();if(a.includes("://"))try{a=new URL(a).hostname;}catch{}if(s===a)return true;if(a.startsWith("*.")){let r=a.substring(2);if(s.endsWith(`.${r}`)&&s!==r)return true}return false}matchToolPattern(e,t){let s=e.toLowerCase().trim(),n=t.toLowerCase().trim();if(s===n)return true;if(n.endsWith("/*")){let a=n.substring(0,n.length-2);if(s.startsWith(`${a}/`))return true}return false}static async register(e){let{privateKey:t,name:s}=e,n=(e.baseUrl||S).replace(/\/$/,""),r=accounts.privateKeyToAccount(t).address,i=await fetch(`${n}/api/v1/agent/challenge?wallet=${r}&action=register`);if(!i.ok){let y=await i.json().catch(()=>({}));throw new c(y.error||`Failed to get challenge: ${i.status}`)}let{challenge:l,message:d}=await i.json(),g=await accounts.signMessage({message:d,privateKey:t}),u=await fetch(`${n}/api/v1/agent/register`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({challenge:l,external_wallet:r,signature:g,name:s})});if(!u.ok){let y=await u.json().catch(()=>({})),f=y.error||`Registration failed with status ${u.status}`,h=y.request_id,w=(y.code||"").toLowerCase(),_="";u.status===503?_=" The service may be temporarily unavailable. Please try again later.":u.status===500?_=" This is a server error. Please contact support with the request ID.":(w==="missing_challenge"||w==="missing_signature")&&(_=" This may indicate an SDK bug. Please update to the latest version.");let N=h?`${f} (request_id: ${h})${_}`:`${f}${_}`;throw new c(N)}let p=await u.json();return {userId:p.user_id,depositAddress:p.deposit_address}}static async checkServerHealth(e){let t=(e||S).replace(/\/$/,"");try{let s=await fetch(`${t}/api/health/ready?details=true`);if(!s.ok)return {healthy:!1,database:"unknown",agentRegistrationAvailable:!1,walletServiceConfigured:!1,error:`Health check failed with status ${s.status}`};let n=await s.json();return {healthy:n.status==="ready",database:n.database||"unknown",agentRegistrationAvailable:n.services?.agentRegistration?.available??!1,walletServiceConfigured:n.services?.wallet?.configured??!1}}catch(s){return {healthy:false,database:"unreachable",agentRegistrationAvailable:false,walletServiceConfigured:false,error:s instanceof Error?s.message:"Failed to reach server"}}}static async getSessionKey(e){let{privateKey:t,spendingLimitUsd:s,maxPerTxUsd:n,maxDailyUsd:a,durationDays:r}=e,i=(e.baseUrl||S).replace(/\/$/,""),d=accounts.privateKeyToAccount(t).address,g=await fetch(`${i}/api/v1/agent/challenge?wallet=${d}&action=session-key`);if(!g.ok){let w=await g.json().catch(()=>({}));throw new c(w.error||`Failed to get challenge: ${g.status}`)}let{challenge:u,message:p}=await g.json(),y=await accounts.signMessage({message:p,privateKey:t}),f=await fetch(`${i}/api/v1/agent/session-key`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({challenge:u,external_wallet:d,signature:y,spending_limit_usd:s,max_per_tx_usd:n,max_daily_usd:a,duration_days:r})});if(!f.ok){let w=await f.json().catch(()=>({}));throw new c(w.error||`Session key creation failed: ${f.status}`)}let h=await f.json();return {sessionKey:h.session_key,address:h.address,sessionKeyId:h.session_key_id,expiresAt:new Date(h.expires_at),limits:{maxTotalUsd:h.limits.max_total_usd,maxPerTxUsd:h.limits.max_per_tx_usd,maxDailyUsd:h.limits.max_daily_usd}}}static async getStatus(e){let{privateKey:t}=e,s=(e.baseUrl||S).replace(/\/$/,""),a=accounts.privateKeyToAccount(t).address,r=await fetch(`${s}/api/v1/agent/challenge?wallet=${a}&action=status`);if(!r.ok){let p=await r.json().catch(()=>({}));throw new c(p.error||`Failed to get challenge: ${r.status}`)}let{challenge:i,message:l}=await r.json(),d=await accounts.signMessage({message:l,privateKey:t}),g=await fetch(`${s}/api/v1/agent/status?challenge=${i}&external_wallet=${a}&signature=${encodeURIComponent(d)}`);if(!g.ok){let p=await g.json().catch(()=>({}));throw new c(p.error||`Failed to get status: ${g.status}`)}let u=await g.json();return {depositAddress:u.deposit_address,balanceUsd:u.balance_usd,activeSessions:u.active_sessions.map(p=>({id:p.id,expiresAt:new Date(p.expires_at),totalSpentUsd:p.total_spent_usd,remainingUsd:p.remaining_usd,maxTotalUsd:p.max_total_usd})),totalSpentUsd:u.total_spent_usd}}static async revokeSessionKey(e){let{privateKey:t,sessionKeyId:s}=e,n=(e.baseUrl||S).replace(/\/$/,""),r=accounts.privateKeyToAccount(t).address,i=await fetch(`${n}/api/v1/agent/challenge?wallet=${r}&action=revoke`);if(!i.ok){let p=await i.json().catch(()=>({}));throw new c(p.error||`Failed to get challenge: ${i.status}`)}let{challenge:l,message:d}=await i.json(),g=await accounts.signMessage({message:d,privateKey:t}),u=await fetch(`${n}/api/v1/agent/session-key/revoke`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({challenge:l,external_wallet:r,signature:g,session_key_id:s})});if(!u.ok){let p=await u.json().catch(()=>({}));throw new c(p.error||`Revocation failed: ${u.status}`)}return true}static async withdraw(e){let{privateKey:t,amountUsd:s}=e,n=(e.baseUrl||S).replace(/\/$/,""),r=accounts.privateKeyToAccount(t).address,i=await fetch(`${n}/api/v1/agent/challenge?wallet=${r}&action=withdraw`);if(!i.ok){let y=await i.json().catch(()=>({}));throw new c(y.error||`Failed to get challenge: ${i.status}`)}let{challenge:l,message:d}=await i.json(),g=await accounts.signMessage({message:d,privateKey:t}),u=await fetch(`${n}/api/v1/agent/withdraw`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({challenge:l,external_wallet:r,signature:g,to_address:r,amount_usd:s})});if(!u.ok){let y=await u.json().catch(()=>({}));throw new c(y.error||`Withdrawal failed: ${u.status}`)}let p=await u.json();return {txHash:p.tx_hash,amountUsd:p.amount_usd,remainingBalanceUsd:p.remaining_balance_usd}}static async claimInvite(e){let{inviteCode:t,privateKey:s}=e,n=(e.baseUrl||S).replace(/\/$/,""),r=accounts.privateKeyToAccount(s).address,i=await fetch(`${n}/api/v1/agent/challenge?wallet=${r}&action=claim-invite`);if(!i.ok){let y=await i.json().catch(()=>({}));throw new c(y.error||`Failed to get challenge: ${i.status}`)}let{challenge:l,message:d}=await i.json(),g=await accounts.signMessage({message:d,privateKey:s}),u=await fetch(`${n}/api/v1/agent/claim-invite`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({invite_code:t,challenge:l,agent_wallet_address:r,signature:g})});if(!u.ok){let f=(await u.json().catch(()=>({}))).error||`Failed to claim invite: ${u.status}`,h="";throw u.status===404?h=" The invite code may be invalid or misspelled.":u.status===400&&(f.includes("already claimed")?h=" This invite has already been used by another agent.":f.includes("expired")?h=" Ask the wallet owner to create a new invite.":f.includes("revoked")&&(h=" The wallet owner has revoked this invite.")),new c(`${f}${h}`)}let p=await u.json();return {sessionKey:p.session_key,address:p.address,sessionKeyId:p.session_key_id,expiresAt:new Date(p.expires_at),limits:{budgetUsd:p.limits.budget_usd,budgetPeriod:p.limits.budget_period,maxPerTxUsd:p.limits.max_per_tx_usd},allowedMerchants:p.allowed_merchants||[],inviterName:p.inviter_name||"Anonymous"}}static async activate(e,t){let s=(t?.baseUrl||S).replace(/\/$/,""),n=new o({sessionKey:e,baseUrl:s}),a=await n.getSessionAuthHeaders(),r=await fetch(`${s}/api/v2/agent/activate`,{method:"POST",headers:{"Content-Type":"application/json",...a}});if(!r.ok){let l=await r.json().catch(()=>({}));throw new c(l.error||`Activation failed: ${r.status}`)}let i=await r.json();return {wallet:n,budget:{maxTotalUsd:i.budget.max_total_usd,maxDailyUsd:i.budget.max_daily_usd,maxPerTxUsd:i.budget.max_per_tx_usd,spentUsd:i.budget.spent_usd,remainingUsd:i.budget.remaining_usd},capabilities:{executeTransactions:i.capabilities.execute_transactions,gasSponsored:i.capabilities.gas_sponsored,batchedTx:i.capabilities.batched_tx},skills:i.skills||[],tools:i.tools||[],gatewayProviders:i.gateway_providers||[]}}static async connect(e){let t=(e?.baseUrl||process.env.MIXRPAY_BASE_URL||S).replace(/\/$/,""),s=e?.logLevel||"none",n=process.env.MIXRPAY_INSTANCE_ID;if(e?.sessionKey){let g=new o({sessionKey:e.sessionKey,sessionKeyId:e.sessionKeyId,baseUrl:t,logLevel:s,maxPaymentUsd:e?.maxPaymentUsd,onPayment:e?.onPayment});return n&&g.setAgentInstanceId(n),g}let a=process.env.MIXRPAY_SESSION_KEY;if(a){let g=process.env.MIXRPAY_SESSION_KEY_ID,u=new o({sessionKey:a,sessionKeyId:g,baseUrl:t,logLevel:s,maxPaymentUsd:e?.maxPaymentUsd,onPayment:e?.onPayment});return n&&u.setAgentInstanceId(n),u}let r=process.env.MIXRPAY_API_KEY||process.env.MIXRPAY_AGENT_TOKEN;if(r&&(r.startsWith("agt_live_")||r.startsWith("agt_test_")))return o.fromApiKey(r,{baseUrl:t,logLevel:s});let i=e?.accessCode||process.env.MIXRPAY_ACCESS_CODE;if(i)return o.fromAccessCode(i,{baseUrl:t,logLevel:s});let l=e?.masterKey||process.env.MIXRPAY_MASTER_KEY,d=e?.agentName||process.env.MIXRPAY_AGENT_NAME;if(l&&d)return o.fromMasterKey(l,d,{baseUrl:t,logLevel:s});try{let{loadCredentials:g}=await Promise.resolve().then(()=>(H(),J)),u=g();if(u.success&&u.credentials.sessionKey){let p=new o({sessionKey:u.credentials.sessionKey,sessionKeyId:u.credentials.sessionKeyId,baseUrl:u.credentials.baseUrl||t,logLevel:s,maxPaymentUsd:e?.maxPaymentUsd,onPayment:e?.onPayment,apiKey:u.credentials.apiToken});return n&&p.setAgentInstanceId(n),p}if(u.success&&u.credentials.apiToken)return o.fromApiKey(u.credentials.apiToken,{baseUrl:t,logLevel:s});if(u.success&&u.credentials.masterKey&&u.credentials.defaultAgentName)return o.fromMasterKey(u.credentials.masterKey,u.credentials.defaultAgentName,{baseUrl:t,logLevel:s})}catch{}if(e?.interactive)return o.deviceFlowLogin({baseUrl:t,logLevel:s});throw new c("No MixrPay credentials found. Options:\n 1. Set MIXRPAY_SESSION_KEY environment variable\n 2. Set MIXRPAY_API_KEY or MIXRPAY_AGENT_TOKEN environment variable (agt_live_xxx)\n 3. Set MIXRPAY_ACCESS_CODE environment variable (mixr-xxx)\n 4. Pass sessionKey or accessCode to connect()\n 5. Run `npx --package @mixrpay/agent-sdk mixrpay login` (or `npm i -g @mixrpay/agent-sdk` then `mixrpay login`)\n 6. Use connect({ interactive: true }) for browser login")}static async fromApiKey(e,t){let s=(t?.baseUrl||S).replace(/\/$/,"");if(!e.startsWith("agt_live_")&&!e.startsWith("agt_test_"))throw new c(`Invalid API key format. Expected 'agt_live_' or 'agt_test_' prefix, got '${e.slice(0,9)}...'`);let n=await fetch(`${s}/api/v2/agent/session-from-token`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`}});if(!n.ok){let l=await n.json().catch(()=>({}));throw new c(l.error||`Failed to exchange API key for session: ${n.status}`)}let a=await n.json(),r=a.session_key;if(!r)throw new c("No session_key in API response");let i=new o({sessionKey:r,baseUrl:s,logLevel:t?.logLevel});return i.setApiKey(e),a.agent_instance_id&&i.setAgentInstanceId(a.agent_instance_id),i}static async fromAccessCode(e,t){let s=(t?.baseUrl||S).replace(/\/$/,"");if(!e.startsWith("mixr-"))throw new c(`Invalid access code format. Expected 'mixr-' prefix, got '${e.slice(0,5)}...'`);let n=await fetch(`${s}/api/v2/agent/connect`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({code:e})});if(!n.ok){let g=await n.json().catch(()=>({})),u=(g.code||"").toLowerCase(),p="";throw n.status===404||u==="invalid_code"?p=" Check the code for typos or get a new one from the MixrPay dashboard.":n.status===400&&(u==="code_claimed"?p=" This code has already been used. Get a new code from the dashboard.":u==="code_expired"?p=" This code has expired. Get a new code from the dashboard.":u==="code_revoked"&&(p=" This code has been revoked by the owner.")),new c((g.error||`Failed to activate access code: ${n.status}`)+p)}let a=await n.json(),r=a.session_key,i=a.token,l=a.agent_id;if(!r)throw new c("No session_key in access code response");try{let{saveCredentials:g}=await Promise.resolve().then(()=>(H(),J));g({sessionKey:r,apiToken:i,baseUrl:s});}catch{}let d=new o({sessionKey:r,baseUrl:s,logLevel:t?.logLevel});return i&&(d.apiKey=i),l&&(d.agentInstanceId=l),d}static async fromMasterKey(e,t,s){let n=(s?.baseUrl||S).replace(/\/$/,"");if(!e.startsWith("mk_live_")&&!e.startsWith("mk_test_"))throw new c("Invalid master key format. Expected 'mk_live_' or 'mk_test_' prefix.");let a=await fetch(`${n}/api/v2/master-keys/session`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify({agent_name:t})});if(!a.ok){let g=await a.json().catch(()=>({}));throw a.status===404?new c(`Agent '${t}' not found. Use the MixrPay dashboard to create it.`):new c(g.error||`Failed to get session from master key: ${a.status}`)}let r=await a.json(),i=r.session_key,l=r.session_key_id;if(!i)throw new c("No session_key in master key response");let d=new o({sessionKey:i,sessionKeyId:l,baseUrl:n,logLevel:s?.logLevel});return r.agent?.id&&(d.agentInstanceId=r.agent.id),d}static async deviceFlowLogin(e){let t=(e?.baseUrl||S).replace(/\/$/,""),s=await fetch(`${t}/api/v2/auth/device/authorize`,{method:"POST",headers:{"Content-Type":"application/json"}});if(!s.ok){let y=await s.json().catch(()=>({}));throw new c(y.error||`Device flow initiation failed: ${s.status}`)}let n=await s.json(),{device_code:a,user_code:r,verification_uri:i,verification_uri_complete:l,expires_in:d,interval:g}=n;console.log(`
8
2
  \u{1F510} MixrPay Login
9
3
  `),console.log(`Visit: ${l||i}`),console.log(`Enter code: ${r}
10
4
  `),console.log(`Waiting for authentication...
package/dist/index.js CHANGED
@@ -1,10 +1,4 @@
1
- export{c as deleteCredentials,e as getCredentialsFilePath,d as hasCredentials,b as loadCredentials,a as saveCredentials}from'./chunk-EFAKSIRR.js';import {fileURLToPath}from'url';import {join,dirname}from'path';import {privateKeyToAccount,signMessage,generatePrivateKey,signTypedData}from'viem/accounts';import {z as z$1}from'zod';import {createWalletClient,http,parseUnits,encodeFunctionData}from'viem';import {base}from'viem/chains';import {existsSync,mkdirSync,writeFileSync,chmodSync,readFileSync}from'fs';import {homedir}from'os';var l=class extends Error{code;retryAfterMs;constructor(e,t="MIXRPAY_ERROR",s){super(e),this.name="MixrPayError",this.code=t,this.retryAfterMs=s,Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor);}isRetryable(){return false}},k=class extends l{required;available;topUpUrl;constructor(e,t){let s=e-t;super(`Insufficient balance: need $${e.toFixed(2)}, have $${t.toFixed(2)} (short $${s.toFixed(2)}). Top up your wallet to continue.`,"INSUFFICIENT_BALANCE"),this.name="InsufficientBalanceError",this.required=e,this.available=t,this.topUpUrl="https://mixr.network/manage/wallet";}},$=class extends l{expiredAt;constructor(e){super(`Session key expired at ${e}. Request a new session key from the wallet owner at https://mixrpay.com/manage/invites`,"SESSION_KEY_EXPIRED"),this.name="SessionKeyExpiredError",this.expiredAt=e;}},v=class extends l{limitType;limit;attempted;constructor(e,t,s){let a={per_tx:"Per-transaction",daily:"Daily",total:"Total",client_max:"Client-side"}[e]||e,r=e==="daily"?"Wait until tomorrow or request a higher limit.":e==="client_max"?"Increase maxPaymentUsd in your AgentWallet configuration.":"Request a new session key with a higher limit.";super(`${a} spending limit exceeded: limit is $${t.toFixed(2)}, attempted $${s.toFixed(2)}. ${r}`,"SPENDING_LIMIT_EXCEEDED"),this.name="SpendingLimitExceededError",this.limitType=e,this.limit=t,this.attempted=s;}isRetryable(){return this.limitType==="daily"}},A=class extends l{reason;txHash;constructor(e,t){let s=`Payment failed: ${e}`;t&&(s+=` (tx: ${t} - check on basescan.org)`),super(s,"PAYMENT_FAILED"),this.name="PaymentFailedError",this.reason=e,this.txHash=t;}isRetryable(){return true}},S=class extends l{reason;constructor(e="Invalid session key format"){super(`${e}. Session keys should be in format: sk_live_<64 hex chars> or sk_test_<64 hex chars>. Get one from https://mixrpay.com/manage/invites`,"INVALID_SESSION_KEY"),this.name="InvalidSessionKeyError",this.reason=e;}},T=class extends l{reason;constructor(e){super(`x402 protocol error: ${e}. This may indicate a server configuration issue. If the problem persists, contact the API provider.`,"X402_PROTOCOL_ERROR"),this.name="X402ProtocolError",this.reason=e;}isRetryable(){return true}},D=class extends l{sessionId;expiredAt;constructor(e,t){super(`Session ${e} has expired${t?` at ${t}`:""}. A new session will be created automatically on your next request.`,"SESSION_EXPIRED"),this.name="SessionExpiredError",this.sessionId=e,this.expiredAt=t;}},U=class extends l{sessionId;limit;requested;remaining;constructor(e,t,s,n){super(`Session spending limit exceeded: limit is $${e.toFixed(2)}, requested $${t.toFixed(2)}, remaining $${s.toFixed(2)}. Create a new session with a higher limit to continue.`,"SESSION_LIMIT_EXCEEDED"),this.name="SessionLimitExceededError",this.sessionId=n,this.limit=e,this.requested=t,this.remaining=s;}},I=class extends l{sessionId;constructor(e){super(`Session ${e} not found. It may have been deleted or never existed. Create a new session with getOrCreateSession().`,"SESSION_NOT_FOUND"),this.name="SessionNotFoundError",this.sessionId=e;}},R=class extends l{sessionId;reason;constructor(e,t){super(`Session ${e} has been revoked${t?`: ${t}`:""}. Create a new session with getOrCreateSession().`,"SESSION_REVOKED"),this.name="SessionRevokedError",this.sessionId=e,this.reason=t;}},E=class extends l{attempted;allowedPatterns;constructor(e,t){let s=t.slice(0,3).join(", "),n=t.length>3?"...":"";super(`Payment to "${e}" not allowed. Session allowlist: ${s}${n}. Update the session allowlist or create a new session.`,"MERCHANT_NOT_ALLOWED"),this.name="MerchantNotAllowedError",this.attempted=e,this.allowedPatterns=t;}},L=class extends l{constructor(e=6e4,t){super(t||`Rate limit exceeded. Please wait ${Math.ceil(e/1e3)} seconds before retrying.`,"RATE_LIMIT_EXCEEDED",e),this.name="RateLimitError";}isRetryable(){return true}},N=class extends l{reason;constructor(e,t){super(`Network error: ${e}. Check your connection and try again.`,"NETWORK_ERROR",5e3),this.name="NetworkError",this.reason=e,t?.stack&&(this.stack=t.stack);}isRetryable(){return true}},F=class extends l{reason;statusCode;constructor(e,t=401){super(`Authentication failed: ${e}`,t===401?"UNAUTHORIZED":"FORBIDDEN"),this.name="AuthenticationError",this.reason=e,this.statusCode=t;}isRetryable(){return false}};function Ue(c){return c instanceof l}function Ie(c){return c instanceof l||c instanceof Error?c.message:String(c)}var De={8453:"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",84532:"0x036CbD53842c5426634e7929541eC2318f3dCF7e"},Ee={name:"USD Coin",version:"2"},Oe={TransferWithAuthorization:[{name:"from",type:"address"},{name:"to",type:"address"},{name:"value",type:"uint256"},{name:"validAfter",type:"uint256"},{name:"validBefore",type:"uint256"},{name:"nonce",type:"bytes32"}]},j=class c{privateKey;account;address;isTest;constructor(e,t){this.privateKey=e,this.account=privateKeyToAccount(e),this.address=this.account.address,this.isTest=t;}toString(){return `${this.isTest?"sk_test_":"sk_live_"}${this.privateKey.slice(2)}`}get privateKeyHex(){return this.privateKey.slice(2)}get rawPrivateKey(){return this.privateKey}static fromString(e){let t=/^sk_(live|test)_([a-fA-F0-9]{64})$/,s=e.match(t);if(!s)throw new S("Session key must be in format sk_live_{64_hex} or sk_test_{64_hex}");let n=s[1],a=s[2];try{let r=`0x${a}`;return new c(r,n==="test")}catch(r){throw new S(`Failed to decode session key: ${r}`)}}async signTransferAuthorization(e,t){return signTypedData({privateKey:this.privateKey,domain:e,types:Oe,primaryType:"TransferWithAuthorization",message:t})}async signMessage(e){return signMessage({privateKey:this.privateKey,message:e})}getDefaultChainId(){return this.isTest?84532:8453}};function Y(c){let e=De[c.chainId];if(!e)throw new Error(`USDC not supported on chain ${c.chainId}`);let t={...Ee,chainId:c.chainId,verifyingContract:e},s={from:c.fromAddress,to:c.toAddress,value:c.value,validAfter:c.validAfter,validBefore:c.validBefore,nonce:c.nonce};return {domain:t,message:s}}function W(){let c=new Uint8Array(32);return crypto.getRandomValues(c),`0x${Array.from(c).map(e=>e.toString(16).padStart(2,"0")).join("")}`}function Ke(c,e){return `MixrPay:${c}:${e.toLowerCase()}`}async function V(c){let e=Date.now(),t=Ke(e,c.address),s=await c.signMessage(t);return {address:c.address,timestamp:e,signature:s}}var Z=z$1.object({query:z$1.string().describe('Search query (e.g. "web scraping", "email", "database")')}),Q=z$1.object({tool_name:z$1.string().describe('Tool name in "merchant/tool" format'),arguments:z$1.record(z$1.unknown()).optional().describe("Arguments to pass to the tool")}),ee=z$1.object({url:z$1.string().url().describe("The merchant API URL to call"),merchant_public_key:z$1.string().describe("The merchant's MixrPay public key (pk_live_... or pk_test_...)"),method:z$1.enum(["GET","POST","PUT","PATCH","DELETE"]).default("POST").describe("HTTP method"),body:z$1.unknown().optional().describe("Request body (will be JSON-serialized)"),price_usd:z$1.number().optional().describe("Expected price in USD for client-side validation")}),te=z$1.object({skill_id:z$1.string().describe("The skill ID to execute"),input:z$1.record(z$1.unknown()).optional().describe("Input parameters for the skill")}),se=z$1.object({skill_id:z$1.string().describe("The skill ID to check")}),ne=z$1.object({glama_id:z$1.string().describe('Glama server ID (e.g. "notion-mcp")'),glama_namespace:z$1.string().describe('Glama namespace (e.g. "notion")'),glama_slug:z$1.string().describe('Glama slug (e.g. "notion-mcp")'),tool_name:z$1.string().describe("Human-readable name for the tool"),tool_description:z$1.string().optional().describe("Optional description"),env_vars:z$1.record(z$1.string()).optional().describe("Environment variables for the MCP server (e.g. API keys)"),ttl_hours:z$1.number().min(1).max(168).optional().describe("Time-to-live in hours (default: 24, max: 168)")}),ae=z$1.object({status:z$1.enum(["provisioning","active","stopped","expired"]).optional().describe("Filter by status")}),re=z$1.object({instance_id:z$1.string().describe("The instance ID to stop")}),ie=z$1.object({to:z$1.string().describe("Recipient address (0x...)"),amount_usdc:z$1.number().positive().describe("Amount in USDC (e.g. 10.5)")}),oe=z$1.object({name:z$1.string().describe("Name for the child agent"),budget_usd:z$1.number().positive().describe("Budget to delegate in USD"),budget_period:z$1.enum(["daily","monthly","total"]).default("total").describe("Budget period"),max_per_tx_usd:z$1.number().positive().optional().describe("Max per-transaction limit in USD"),expires_in_days:z$1.number().min(1).max(365).optional().describe("Expiry in days (default: 30)")}),le=z$1.object({title:z$1.string().describe("Task title"),description:z$1.string().describe("Detailed task description"),budget_usd:z$1.number().positive().describe("Budget for the task in USD"),skills_required:z$1.array(z$1.string()).optional().describe("Required skill IDs")}),ce=z$1.object({status:z$1.string().optional().describe('Filter by status (e.g. "open", "in_progress")'),limit:z$1.number().min(1).max(100).optional().describe("Number of results (default: 20)")});function de(c){let e=[{name:"check_balance",title:"Check Balance",description:"Get the USDC balance of the wallet on Base.",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:null,handler:async()=>({balanceUsd:await c.getBalance(),network:c.isTestnet()?"base-sepolia":"base"})},{name:"get_spending_stats",title:"Get Spending Stats",description:"Get session key spending limits and current usage (total spent, remaining daily/total limits, expiry).",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:null,handler:async()=>c.getSpendingStats()},{name:"get_session_info",title:"Get Session Info",description:"Get detailed session key information including limits, usage, expiry, and allowed merchants.",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:null,handler:async()=>c.getSessionKeyInfo(true)},{name:"run_diagnostics",title:"Run Diagnostics",description:"Run a full health check on the wallet: API connectivity, session key validity, balance, and latency.",annotations:{readOnlyHint:true,openWorldHint:true},inputSchema:null,handler:async()=>c.runDiagnostics()},{name:"list_tools",title:"List Marketplace Tools",description:"Browse all available paid API tools on the MixrPay marketplace. Each tool includes pricing and description.",annotations:{readOnlyHint:true,openWorldHint:true},inputSchema:null,handler:async()=>c.listTools()},{name:"search_tools",title:"Search Tools",description:"Search the Glama MCP server directory for tools by keyword.",annotations:{readOnlyHint:true,openWorldHint:true},inputSchema:Z,handler:async s=>{let{query:n}=Z.parse(s);return c.searchGlamaDirectory(n)}},{name:"call_tool",title:"Call Marketplace Tool",description:'Call a paid API tool on the MixrPay marketplace. Payment is automatic from the wallet. Tool names are in "merchant/tool" format (e.g. "firecrawl/scrape").',annotations:{readOnlyHint:false,openWorldHint:true},inputSchema:Q,handler:async s=>{let{tool_name:n,arguments:a}=Q.parse(s);return c.callTool(n,a||{})}},{name:"call_merchant_api",title:"Call Merchant API",description:"Call any merchant API endpoint with x402 payment. The wallet handles authentication and payment automatically.",annotations:{readOnlyHint:false,openWorldHint:true},inputSchema:ee,handler:async s=>{let{url:n,merchant_public_key:a,method:r,body:i,price_usd:o}=ee.parse(s),d=await c.callMerchantApi({url:n,merchantPublicKey:a,method:r,body:i,priceUsd:o}),g=await d.json().catch(()=>d.text());return {status:d.status,data:g}}},{name:"list_skills",title:"List Skills",description:"List all available skills (pre-built integrations) that the wallet can use.",annotations:{readOnlyHint:true,openWorldHint:true},inputSchema:null,handler:async()=>c.listSkills()},{name:"use_skill",title:"Use Skill",description:"Execute a skill by ID. Skills are pre-built integrations (e.g. web scraping, email sending).",annotations:{readOnlyHint:false,openWorldHint:true},inputSchema:te,handler:async s=>{let{skill_id:n,input:a}=te.parse(s);return c.useSkill(n,{input:a})}},{name:"get_skill_status",title:"Get Skill Status",description:"Check the status and configuration of a specific skill.",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:se,handler:async s=>{let{skill_id:n}=se.parse(s);return c.getSkillStatus(n)}},{name:"deploy_jit_mcp",title:"Deploy JIT MCP Server",description:"Deploy a just-in-time MCP server from the Glama directory. Creates a temporary hosted MCP server instance.",annotations:{readOnlyHint:false,openWorldHint:true},inputSchema:ne,handler:async s=>{let{glama_id:n,glama_namespace:a,glama_slug:r,tool_name:i,tool_description:o,env_vars:d,ttl_hours:g}=ne.parse(s);return c.deployJitMcp({glamaId:n,glamaNamespace:a,glamaSlug:r,toolName:i,toolDescription:o,envVars:d,ttlHours:g})}},{name:"list_jit_instances",title:"List JIT Instances",description:"List all deployed JIT MCP server instances.",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:ae,handler:async s=>{let{status:n}=ae.parse(s);return c.listJitInstances(n?{status:n}:void 0)}},{name:"stop_jit_instance",title:"Stop JIT Instance",description:"Stop a running JIT MCP server instance.",annotations:{readOnlyHint:false,destructiveHint:true,openWorldHint:false},inputSchema:re,handler:async s=>{let{instance_id:n}=re.parse(s);return await c.stopJitInstance(n),{success:true,instance_id:n}}},{name:"transfer_usdc",title:"Transfer USDC",description:"Transfer USDC from the self-custody wallet to another address on Base. Only available when the wallet has a self-custody wallet (AGENT_WALLET_KEY set).",annotations:{readOnlyHint:false,destructiveHint:true,openWorldHint:true},inputSchema:ie,handler:async s=>{let{to:n,amount_usdc:a}=ie.parse(s);if(!await c.hasSelfCustodyWallet())throw new Error("No self-custody wallet configured. Set AGENT_WALLET_KEY to enable transfers.");return {success:true,txHash:await c.transferUSDC({to:n,amountUsdc:a}),to:n,amountUsdc:a}}},{name:"get_budget",title:"Get Available Budget",description:"Get the available delegation budget including remaining amount, whether spawning children is possible, and budget limits.",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:null,handler:async()=>c.getAvailableBudget()},{name:"spawn_child",title:"Spawn Child Session",description:"Create a child invite with a delegated budget from this wallet. Returns an invite code that another agent can claim.",annotations:{readOnlyHint:false,openWorldHint:false},inputSchema:oe,handler:async s=>{let{name:n,budget_usd:a,budget_period:r,max_per_tx_usd:i,expires_in_days:o}=oe.parse(s);return c.spawnChildInvite({name:n,budgetUsd:a,budgetPeriod:r,maxPerTxUsd:i,expiresInDays:o})}},{name:"list_children",title:"List Child Sessions",description:"List all child sessions (agents) spawned from this wallet.",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:null,handler:async()=>c.listChildSessions()},{name:"create_task",title:"Create Task",description:"Create a new task on the MixrPay marketplace for other agents to complete.",annotations:{readOnlyHint:false,openWorldHint:true},inputSchema:le,handler:async s=>{let{title:n,description:a,budget_usd:r,skills_required:i}=le.parse(s);return c.createTask({title:n,description:a,budgetUsd:r,skillsRequired:i})}},{name:"list_tasks",title:"List Tasks",description:"Browse available tasks on the MixrPay marketplace.",annotations:{readOnlyHint:true,openWorldHint:true},inputSchema:ce,handler:async s=>{let{status:n,limit:a}=ce.parse(s);return c.listTasks({status:n,limit:a})}}];return {definitions:e,execute:async(s,n)=>{let a=e.find(r=>r.name===s);if(!a)throw new Error(`Unknown tool: ${s}`);try{let r=await a.handler(n);return JSON.stringify(r,null,2)}catch(r){let i=r instanceof Error?r.message:String(r);throw new Error(i)}}}}function ue(c){if(c instanceof z$1.ZodObject){let e=c._def.shape(),t={},s=[];for(let[n,a]of Object.entries(e)){let r=a;t[n]=M(r),!(r instanceof z$1.ZodOptional)&&!(r instanceof z$1.ZodDefault)&&s.push(n);}return {type:"object",properties:t,...s.length>0?{required:s}:{}}}return {type:"object",properties:{}}}function M(c){let e=c;e instanceof z$1.ZodOptional&&(e=e._def.innerType),e instanceof z$1.ZodDefault&&(e=e._def.innerType);let t=c._def.description;if(e instanceof z$1.ZodString)return {type:"string",...t&&{description:t}};if(e instanceof z$1.ZodNumber)return {type:"number",...t&&{description:t}};if(e instanceof z$1.ZodBoolean)return {type:"boolean",...t&&{description:t}};if(e instanceof z$1.ZodEnum)return {type:"string",enum:e._def.values,...t&&{description:t}};if(e instanceof z$1.ZodArray)return {type:"array",items:M(e._def.type),...t&&{description:t}};if(e instanceof z$1.ZodRecord)return {type:"object",additionalProperties:M(e._def.valueType),...t&&{description:t}};if(e instanceof z$1.ZodObject){let s=e._def.shape(),n={};for(let[a,r]of Object.entries(s))n[a]=M(r);return {type:"object",properties:n,...t&&{description:t}}}return e instanceof z$1.ZodUnknown?{...t&&{description:t}}:{...t&&{description:t}}}var Ne="0.9.5",ge=".config/mixrpay",Fe="wallet.json";function me(){let c=process.env.MIXRPAY_WORKSPACE_DIR||process.env.OPENCLAW_WORKSPACE_DIR;return c?join(c,ge):join(homedir(),ge)}function C(){return join(me(),Fe)}async function B(c,e){let t=me(),s=C();existsSync(t)||mkdirSync(t,{recursive:true,mode:448});let n={address:e.toLowerCase(),privateKey:c,createdAt:new Date().toISOString(),sdkVersion:Ne};writeFileSync(s,JSON.stringify(n,null,2),{encoding:"utf-8",mode:384});try{chmodSync(s,384);}catch{}}async function H(){let c=process.env.MIXRPAY_WALLET_KEY;if(c){if(c.startsWith("0x")&&c.length===66)return c;if(c.length===64)return `0x${c}`;console.warn("[MixrPay] MIXRPAY_WALLET_KEY has invalid format, ignoring");}let e=C();if(!existsSync(e))return null;try{let t=readFileSync(e,"utf-8"),s=JSON.parse(t);return !s.privateKey||!s.privateKey.startsWith("0x")?(console.warn("[MixrPay] Wallet file has invalid format"),null):s.privateKey}catch(t){return console.warn("[MixrPay] Failed to read wallet file:",t),null}}async function We(){let c=C();if(!existsSync(c)){let e=process.env.MIXRPAY_WALLET_KEY;return e&&(e.startsWith("0x")?e:`0x${e}`).length===66,null}try{let e=readFileSync(c,"utf-8");return JSON.parse(e)}catch{return null}}async function J(){let c=process.env.MIXRPAY_WALLET_KEY;return c&&(c.length===64||c.startsWith("0x")&&c.length===66)?true:existsSync(C())}function qe(){return C()}async function Be(){let c=C();if(!existsSync(c))return false;try{let{unlinkSync:e}=await import('fs');return e(c),!0}catch{return false}}async function he(c){let e=null,t=c.headers.get("X-Payment-Required");if(t)try{e=JSON.parse(t);}catch{}if(!e){let n=c.headers.get("WWW-Authenticate");if(n?.startsWith("X-402 "))try{let a=n.slice(6);e=JSON.parse(atob(a));}catch{}}if(!e)try{e=await c.json();}catch{}if(!e)throw new T("Could not parse payment requirements from 402 response");if(!e.recipient)throw new T("Missing recipient in payment requirements");if(!e.amount)throw new T("Missing amount in payment requirements");let s=Math.floor(Date.now()/1e3);return {recipient:e.recipient,amount:BigInt(e.amount),currency:e.currency||"USDC",chainId:e.chainId||e.chain_id||8453,facilitatorUrl:e.facilitatorUrl||e.facilitator_url||"https://x402.org/facilitator",nonce:e.nonce||W().slice(2),expiresAt:e.expiresAt||e.expires_at||s+300,description:e.description}}async function ye(c,e,t){let s=c.nonce.length===64?`0x${c.nonce}`:W(),a=BigInt(Math.floor(Date.now()/1e3))-60n,r=BigInt(c.expiresAt),{domain:i,message:o}=Y({fromAddress:t,toAddress:c.recipient,value:c.amount,validAfter:a,validBefore:r,nonce:s,chainId:c.chainId}),d=await e.signTransferAuthorization(i,o),g={x402Version:1,scheme:"exact",network:c.chainId===8453?"base":"base-sepolia",payload:{signature:d,authorization:{from:t,to:c.recipient,value:c.amount.toString(),validAfter:a.toString(),validBefore:r.toString(),nonce:s}}};return btoa(JSON.stringify(g))}function fe(c){return Date.now()/1e3>c.expiresAt}function G(c){return Number(c.amount)/1e6}var Se="0.11.0",_=process.env.MIXRPAY_BASE_URL||"https://mixr.network";var et=3e4,be={BASE_MAINNET:{chainId:8453,name:"Base",isTestnet:false},BASE_SEPOLIA:{chainId:84532,name:"Base Sepolia",isTestnet:true}},_e={debug:0,info:1,warn:2,error:3,none:4},X=class{level;prefix;constructor(e="none",t="[MixrPay]"){this.level=e,this.prefix=t;}setLevel(e){this.level=e;}shouldLog(e){return _e[e]>=_e[this.level]}debug(...e){this.shouldLog("debug")&&console.log(`${this.prefix} \u{1F50D}`,...e);}info(...e){this.shouldLog("info")&&console.log(`${this.prefix} \u2139\uFE0F`,...e);}warn(...e){this.shouldLog("warn")&&console.warn(`${this.prefix} \u26A0\uFE0F`,...e);}error(...e){this.shouldLog("error")&&console.error(`${this.prefix} \u274C`,...e);}payment(e,t,s){if(this.shouldLog("info")){let n=s?` for "${s}"`:"";console.log(`${this.prefix} \u{1F4B8} Paid $${e.toFixed(4)} to ${t.slice(0,10)}...${n}`);}}},z=class c{sessionKey;walletAddress;maxPaymentUsd;onPayment;baseUrl;timeout;logger;payments=[];totalSpentUsd=0;sessionKeyInfo;sessionKeyInfoFetchedAt;allowlist;allowlistFetchedAt;selfCustodyAddress;selfCustodyKey;agentInstanceId;apiKey;sessionKeyId;constructor(e){this.validateConfig(e),this.sessionKey=j.fromString(e.sessionKey),this.walletAddress=e.walletAddress||this.sessionKey.address,this.maxPaymentUsd=e.maxPaymentUsd,this.onPayment=e.onPayment,this.baseUrl=(e.baseUrl||_).replace(/\/$/,""),this.timeout=e.timeout||et,e.apiKey&&(this.apiKey=e.apiKey),e.sessionKeyId&&(this.sessionKeyId=e.sessionKeyId),this.logger=new X(e.logLevel||"none"),this.logger.debug("AgentWallet initialized",{walletAddress:this.walletAddress,isTestnet:this.isTestnet(),maxPaymentUsd:this.maxPaymentUsd,hasApiKey:!!this.apiKey,hasSessionKeyId:!!this.sessionKeyId});}validateConfig(e){if(!e.sessionKey)throw new S("Session key is required. Get one from the wallet owner at https://mixrpay.com/manage/invites");let t=e.sessionKey.trim();if(!t.startsWith("sk_live_")&&!t.startsWith("sk_test_")){let a=t.slice(0,8);throw new S(`Invalid session key prefix. Expected 'sk_live_' (mainnet) or 'sk_test_' (testnet), got '${a}'`)}let s=72;if(t.length!==s)throw new S(`Invalid session key length. Expected ${s} characters, got ${t.length}. Make sure you copied the complete key.`);let n=t.slice(8);if(!/^[0-9a-fA-F]+$/.test(n))throw new S("Invalid session key format. The key should contain only hexadecimal characters after the prefix.");if(e.maxPaymentUsd!==void 0){if(e.maxPaymentUsd<=0)throw new l("maxPaymentUsd must be a positive number");e.maxPaymentUsd>1e4&&this.logger?.warn("maxPaymentUsd is very high ($"+e.maxPaymentUsd+"). Consider using a lower limit for safety.");}}async fetchAllowlist(){if(this.allowlist!==void 0&&this.allowlistFetchedAt&&Date.now()-this.allowlistFetchedAt<3e5)return this.allowlist;try{let t=await this.getSessionKeyInfo();return this.allowlist=t.allowedMerchants||[],this.allowlistFetchedAt=Date.now(),this.logger.debug("Fetched allowlist",{patterns:this.allowlist.length,allowAll:this.allowlist.length===0}),this.allowlist}catch(t){return this.logger.warn("Failed to fetch allowlist, allowing all merchants",{error:t}),this.allowlist=[],this.allowlistFetchedAt=Date.now(),this.allowlist}}async validateMerchantAllowed(e,t){let s=await this.fetchAllowlist();if(s.length===0)return;if(!this.matchesAllowlist(e,s,t))throw new E(e,s)}matchesAllowlist(e,t,s){for(let n of t)if(this.matchPattern(e,n,s))return true;return false}matchPattern(e,t,s){return s==="url"?this.matchUrlPattern(e,t):this.matchToolPattern(e,t)}matchUrlPattern(e,t){let s;try{e.includes("://")?s=new URL(e).hostname.toLowerCase():s=e.toLowerCase();}catch{return false}let a=t.toLowerCase().trim();if(a.includes("://"))try{a=new URL(a).hostname;}catch{}if(s===a)return true;if(a.startsWith("*.")){let r=a.substring(2);if(s.endsWith(`.${r}`)&&s!==r)return true}return false}matchToolPattern(e,t){let s=e.toLowerCase().trim(),n=t.toLowerCase().trim();if(s===n)return true;if(n.endsWith("/*")){let a=n.substring(0,n.length-2);if(s.startsWith(`${a}/`))return true}return false}static async register(e){let{privateKey:t,name:s}=e,n=(e.baseUrl||_).replace(/\/$/,""),r=privateKeyToAccount(t).address,i=await fetch(`${n}/api/v1/agent/challenge?wallet=${r}&action=register`);if(!i.ok){let y=await i.json().catch(()=>({}));throw new l(y.error||`Failed to get challenge: ${i.status}`)}let{challenge:o,message:d}=await i.json(),g=await signMessage({message:d,privateKey:t}),u=await fetch(`${n}/api/v1/agent/register`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({challenge:o,external_wallet:r,signature:g,name:s})});if(!u.ok){let y=await u.json().catch(()=>({})),f=y.error||`Registration failed with status ${u.status}`,h=y.request_id,w=(y.code||"").toLowerCase(),b="";u.status===503?b=" The service may be temporarily unavailable. Please try again later.":u.status===500?b=" This is a server error. Please contact support with the request ID.":(w==="missing_challenge"||w==="missing_signature")&&(b=" This may indicate an SDK bug. Please update to the latest version.");let K=h?`${f} (request_id: ${h})${b}`:`${f}${b}`;throw new l(K)}let p=await u.json();return {userId:p.user_id,depositAddress:p.deposit_address}}static async checkServerHealth(e){let t=(e||_).replace(/\/$/,"");try{let s=await fetch(`${t}/api/health/ready?details=true`);if(!s.ok)return {healthy:!1,database:"unknown",agentRegistrationAvailable:!1,walletServiceConfigured:!1,error:`Health check failed with status ${s.status}`};let n=await s.json();return {healthy:n.status==="ready",database:n.database||"unknown",agentRegistrationAvailable:n.services?.agentRegistration?.available??!1,walletServiceConfigured:n.services?.wallet?.configured??!1}}catch(s){return {healthy:false,database:"unreachable",agentRegistrationAvailable:false,walletServiceConfigured:false,error:s instanceof Error?s.message:"Failed to reach server"}}}static async getSessionKey(e){let{privateKey:t,spendingLimitUsd:s,maxPerTxUsd:n,maxDailyUsd:a,durationDays:r}=e,i=(e.baseUrl||_).replace(/\/$/,""),d=privateKeyToAccount(t).address,g=await fetch(`${i}/api/v1/agent/challenge?wallet=${d}&action=session-key`);if(!g.ok){let w=await g.json().catch(()=>({}));throw new l(w.error||`Failed to get challenge: ${g.status}`)}let{challenge:u,message:p}=await g.json(),y=await signMessage({message:p,privateKey:t}),f=await fetch(`${i}/api/v1/agent/session-key`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({challenge:u,external_wallet:d,signature:y,spending_limit_usd:s,max_per_tx_usd:n,max_daily_usd:a,duration_days:r})});if(!f.ok){let w=await f.json().catch(()=>({}));throw new l(w.error||`Session key creation failed: ${f.status}`)}let h=await f.json();return {sessionKey:h.session_key,address:h.address,sessionKeyId:h.session_key_id,expiresAt:new Date(h.expires_at),limits:{maxTotalUsd:h.limits.max_total_usd,maxPerTxUsd:h.limits.max_per_tx_usd,maxDailyUsd:h.limits.max_daily_usd}}}static async getStatus(e){let{privateKey:t}=e,s=(e.baseUrl||_).replace(/\/$/,""),a=privateKeyToAccount(t).address,r=await fetch(`${s}/api/v1/agent/challenge?wallet=${a}&action=status`);if(!r.ok){let p=await r.json().catch(()=>({}));throw new l(p.error||`Failed to get challenge: ${r.status}`)}let{challenge:i,message:o}=await r.json(),d=await signMessage({message:o,privateKey:t}),g=await fetch(`${s}/api/v1/agent/status?challenge=${i}&external_wallet=${a}&signature=${encodeURIComponent(d)}`);if(!g.ok){let p=await g.json().catch(()=>({}));throw new l(p.error||`Failed to get status: ${g.status}`)}let u=await g.json();return {depositAddress:u.deposit_address,balanceUsd:u.balance_usd,activeSessions:u.active_sessions.map(p=>({id:p.id,expiresAt:new Date(p.expires_at),totalSpentUsd:p.total_spent_usd,remainingUsd:p.remaining_usd,maxTotalUsd:p.max_total_usd})),totalSpentUsd:u.total_spent_usd}}static async revokeSessionKey(e){let{privateKey:t,sessionKeyId:s}=e,n=(e.baseUrl||_).replace(/\/$/,""),r=privateKeyToAccount(t).address,i=await fetch(`${n}/api/v1/agent/challenge?wallet=${r}&action=revoke`);if(!i.ok){let p=await i.json().catch(()=>({}));throw new l(p.error||`Failed to get challenge: ${i.status}`)}let{challenge:o,message:d}=await i.json(),g=await signMessage({message:d,privateKey:t}),u=await fetch(`${n}/api/v1/agent/session-key/revoke`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({challenge:o,external_wallet:r,signature:g,session_key_id:s})});if(!u.ok){let p=await u.json().catch(()=>({}));throw new l(p.error||`Revocation failed: ${u.status}`)}return true}static async withdraw(e){let{privateKey:t,amountUsd:s}=e,n=(e.baseUrl||_).replace(/\/$/,""),r=privateKeyToAccount(t).address,i=await fetch(`${n}/api/v1/agent/challenge?wallet=${r}&action=withdraw`);if(!i.ok){let y=await i.json().catch(()=>({}));throw new l(y.error||`Failed to get challenge: ${i.status}`)}let{challenge:o,message:d}=await i.json(),g=await signMessage({message:d,privateKey:t}),u=await fetch(`${n}/api/v1/agent/withdraw`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({challenge:o,external_wallet:r,signature:g,to_address:r,amount_usd:s})});if(!u.ok){let y=await u.json().catch(()=>({}));throw new l(y.error||`Withdrawal failed: ${u.status}`)}let p=await u.json();return {txHash:p.tx_hash,amountUsd:p.amount_usd,remainingBalanceUsd:p.remaining_balance_usd}}static async claimInvite(e){let{inviteCode:t,privateKey:s}=e,n=(e.baseUrl||_).replace(/\/$/,""),r=privateKeyToAccount(s).address,i=await fetch(`${n}/api/v1/agent/challenge?wallet=${r}&action=claim-invite`);if(!i.ok){let y=await i.json().catch(()=>({}));throw new l(y.error||`Failed to get challenge: ${i.status}`)}let{challenge:o,message:d}=await i.json(),g=await signMessage({message:d,privateKey:s}),u=await fetch(`${n}/api/v1/agent/claim-invite`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({invite_code:t,challenge:o,agent_wallet_address:r,signature:g})});if(!u.ok){let f=(await u.json().catch(()=>({}))).error||`Failed to claim invite: ${u.status}`,h="";throw u.status===404?h=" The invite code may be invalid or misspelled.":u.status===400&&(f.includes("already claimed")?h=" This invite has already been used by another agent.":f.includes("expired")?h=" Ask the wallet owner to create a new invite.":f.includes("revoked")&&(h=" The wallet owner has revoked this invite.")),new l(`${f}${h}`)}let p=await u.json();return {sessionKey:p.session_key,address:p.address,sessionKeyId:p.session_key_id,expiresAt:new Date(p.expires_at),limits:{budgetUsd:p.limits.budget_usd,budgetPeriod:p.limits.budget_period,maxPerTxUsd:p.limits.max_per_tx_usd},allowedMerchants:p.allowed_merchants||[],inviterName:p.inviter_name||"Anonymous"}}static async activate(e,t){let s=(t?.baseUrl||_).replace(/\/$/,""),n=new c({sessionKey:e,baseUrl:s}),a=await n.getSessionAuthHeaders(),r=await fetch(`${s}/api/v2/agent/activate`,{method:"POST",headers:{"Content-Type":"application/json",...a}});if(!r.ok){let o=await r.json().catch(()=>({}));throw new l(o.error||`Activation failed: ${r.status}`)}let i=await r.json();return {wallet:n,budget:{maxTotalUsd:i.budget.max_total_usd,maxDailyUsd:i.budget.max_daily_usd,maxPerTxUsd:i.budget.max_per_tx_usd,spentUsd:i.budget.spent_usd,remainingUsd:i.budget.remaining_usd},capabilities:{executeTransactions:i.capabilities.execute_transactions,gasSponsored:i.capabilities.gas_sponsored,batchedTx:i.capabilities.batched_tx},skills:i.skills||[],tools:i.tools||[],gatewayProviders:i.gateway_providers||[]}}static async connect(e){let t=(e?.baseUrl||process.env.MIXRPAY_BASE_URL||_).replace(/\/$/,""),s=e?.logLevel||"none",n=process.env.MIXRPAY_INSTANCE_ID;if(e?.sessionKey){let g=new c({sessionKey:e.sessionKey,sessionKeyId:e.sessionKeyId,baseUrl:t,logLevel:s,maxPaymentUsd:e?.maxPaymentUsd,onPayment:e?.onPayment});return n&&g.setAgentInstanceId(n),g}let a=process.env.MIXRPAY_SESSION_KEY;if(a){let g=process.env.MIXRPAY_SESSION_KEY_ID,u=new c({sessionKey:a,sessionKeyId:g,baseUrl:t,logLevel:s,maxPaymentUsd:e?.maxPaymentUsd,onPayment:e?.onPayment});return n&&u.setAgentInstanceId(n),u}let r=process.env.MIXRPAY_API_KEY||process.env.MIXRPAY_AGENT_TOKEN;if(r&&(r.startsWith("agt_live_")||r.startsWith("agt_test_")))return c.fromApiKey(r,{baseUrl:t,logLevel:s});let i=e?.accessCode||process.env.MIXRPAY_ACCESS_CODE;if(i)return c.fromAccessCode(i,{baseUrl:t,logLevel:s});let o=e?.masterKey||process.env.MIXRPAY_MASTER_KEY,d=e?.agentName||process.env.MIXRPAY_AGENT_NAME;if(o&&d)return c.fromMasterKey(o,d,{baseUrl:t,logLevel:s});try{let{loadCredentials:g}=await import('./credentials-64ZBZ5AS.js'),u=g();if(u.success&&u.credentials.sessionKey){let p=new c({sessionKey:u.credentials.sessionKey,sessionKeyId:u.credentials.sessionKeyId,baseUrl:u.credentials.baseUrl||t,logLevel:s,maxPaymentUsd:e?.maxPaymentUsd,onPayment:e?.onPayment,apiKey:u.credentials.apiToken});return n&&p.setAgentInstanceId(n),p}if(u.success&&u.credentials.apiToken)return c.fromApiKey(u.credentials.apiToken,{baseUrl:t,logLevel:s});if(u.success&&u.credentials.masterKey&&u.credentials.defaultAgentName)return c.fromMasterKey(u.credentials.masterKey,u.credentials.defaultAgentName,{baseUrl:t,logLevel:s})}catch{}if(e?.interactive)return c.deviceFlowLogin({baseUrl:t,logLevel:s});throw new l(`No MixrPay credentials found. Options:
2
- 1. Set MIXRPAY_SESSION_KEY environment variable
3
- 2. Set MIXRPAY_API_KEY or MIXRPAY_AGENT_TOKEN environment variable (agt_live_xxx)
4
- 3. Set MIXRPAY_ACCESS_CODE environment variable (mixr-xxx)
5
- 4. Pass sessionKey or accessCode to connect()
6
- 5. Run \`npx mixrpay login\` to cache credentials
7
- 6. Use connect({ interactive: true }) for browser login`)}static async fromApiKey(e,t){let s=(t?.baseUrl||_).replace(/\/$/,"");if(!e.startsWith("agt_live_")&&!e.startsWith("agt_test_"))throw new l(`Invalid API key format. Expected 'agt_live_' or 'agt_test_' prefix, got '${e.slice(0,9)}...'`);let n=await fetch(`${s}/api/v2/agent/session-from-token`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`}});if(!n.ok){let o=await n.json().catch(()=>({}));throw new l(o.error||`Failed to exchange API key for session: ${n.status}`)}let a=await n.json(),r=a.session_key;if(!r)throw new l("No session_key in API response");let i=new c({sessionKey:r,baseUrl:s,logLevel:t?.logLevel});return i.setApiKey(e),a.agent_instance_id&&i.setAgentInstanceId(a.agent_instance_id),i}static async fromAccessCode(e,t){let s=(t?.baseUrl||_).replace(/\/$/,"");if(!e.startsWith("mixr-"))throw new l(`Invalid access code format. Expected 'mixr-' prefix, got '${e.slice(0,5)}...'`);let n=await fetch(`${s}/api/v2/agent/connect`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({code:e})});if(!n.ok){let g=await n.json().catch(()=>({})),u=(g.code||"").toLowerCase(),p="";throw n.status===404||u==="invalid_code"?p=" Check the code for typos or get a new one from the MixrPay dashboard.":n.status===400&&(u==="code_claimed"?p=" This code has already been used. Get a new code from the dashboard.":u==="code_expired"?p=" This code has expired. Get a new code from the dashboard.":u==="code_revoked"&&(p=" This code has been revoked by the owner.")),new l((g.error||`Failed to activate access code: ${n.status}`)+p)}let a=await n.json(),r=a.session_key,i=a.token,o=a.agent_id;if(!r)throw new l("No session_key in access code response");try{let{saveCredentials:g}=await import('./credentials-64ZBZ5AS.js');g({sessionKey:r,apiToken:i,baseUrl:s});}catch{}let d=new c({sessionKey:r,baseUrl:s,logLevel:t?.logLevel});return i&&(d.apiKey=i),o&&(d.agentInstanceId=o),d}static async fromMasterKey(e,t,s){let n=(s?.baseUrl||_).replace(/\/$/,"");if(!e.startsWith("mk_live_")&&!e.startsWith("mk_test_"))throw new l("Invalid master key format. Expected 'mk_live_' or 'mk_test_' prefix.");let a=await fetch(`${n}/api/v2/master-keys/session`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify({agent_name:t})});if(!a.ok){let g=await a.json().catch(()=>({}));throw a.status===404?new l(`Agent '${t}' not found. Use the MixrPay dashboard to create it.`):new l(g.error||`Failed to get session from master key: ${a.status}`)}let r=await a.json(),i=r.session_key,o=r.session_key_id;if(!i)throw new l("No session_key in master key response");let d=new c({sessionKey:i,sessionKeyId:o,baseUrl:n,logLevel:s?.logLevel});return r.agent?.id&&(d.agentInstanceId=r.agent.id),d}static async deviceFlowLogin(e){let t=(e?.baseUrl||_).replace(/\/$/,""),s=await fetch(`${t}/api/v2/auth/device/authorize`,{method:"POST",headers:{"Content-Type":"application/json"}});if(!s.ok){let y=await s.json().catch(()=>({}));throw new l(y.error||`Device flow initiation failed: ${s.status}`)}let n=await s.json(),{device_code:a,user_code:r,verification_uri:i,verification_uri_complete:o,expires_in:d,interval:g}=n;console.log(`
1
+ export{c as deleteCredentials,e as getCredentialsFilePath,d as hasCredentials,b as loadCredentials,a as saveCredentials}from'./chunk-EFAKSIRR.js';import {fileURLToPath}from'url';import {join,dirname}from'path';import {privateKeyToAccount,signMessage,generatePrivateKey,signTypedData}from'viem/accounts';import {z as z$1}from'zod';import {createWalletClient,http,parseUnits,encodeFunctionData}from'viem';import {base}from'viem/chains';import {existsSync,mkdirSync,writeFileSync,chmodSync,readFileSync}from'fs';import {homedir}from'os';var l=class extends Error{code;retryAfterMs;constructor(e,t="MIXRPAY_ERROR",s){super(e),this.name="MixrPayError",this.code=t,this.retryAfterMs=s,Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor);}isRetryable(){return false}},k=class extends l{required;available;topUpUrl;constructor(e,t){let s=e-t;super(`Insufficient balance: need $${e.toFixed(2)}, have $${t.toFixed(2)} (short $${s.toFixed(2)}). Top up your wallet to continue.`,"INSUFFICIENT_BALANCE"),this.name="InsufficientBalanceError",this.required=e,this.available=t,this.topUpUrl="https://mixr.network/manage/wallet";}},$=class extends l{expiredAt;constructor(e){super(`Session key expired at ${e}. Request a new session key from the wallet owner at https://mixrpay.com/manage/invites`,"SESSION_KEY_EXPIRED"),this.name="SessionKeyExpiredError",this.expiredAt=e;}},v=class extends l{limitType;limit;attempted;constructor(e,t,s){let a={per_tx:"Per-transaction",daily:"Daily",total:"Total",client_max:"Client-side"}[e]||e,r=e==="daily"?"Wait until tomorrow or request a higher limit.":e==="client_max"?"Increase maxPaymentUsd in your AgentWallet configuration.":"Request a new session key with a higher limit.";super(`${a} spending limit exceeded: limit is $${t.toFixed(2)}, attempted $${s.toFixed(2)}. ${r}`,"SPENDING_LIMIT_EXCEEDED"),this.name="SpendingLimitExceededError",this.limitType=e,this.limit=t,this.attempted=s;}isRetryable(){return this.limitType==="daily"}},A=class extends l{reason;txHash;constructor(e,t){let s=`Payment failed: ${e}`;t&&(s+=` (tx: ${t} - check on basescan.org)`),super(s,"PAYMENT_FAILED"),this.name="PaymentFailedError",this.reason=e,this.txHash=t;}isRetryable(){return true}},S=class extends l{reason;constructor(e="Invalid session key format"){super(`${e}. Session keys should be in format: sk_live_<64 hex chars> or sk_test_<64 hex chars>. Get one from https://mixrpay.com/manage/invites`,"INVALID_SESSION_KEY"),this.name="InvalidSessionKeyError",this.reason=e;}},T=class extends l{reason;constructor(e){super(`x402 protocol error: ${e}. This may indicate a server configuration issue. If the problem persists, contact the API provider.`,"X402_PROTOCOL_ERROR"),this.name="X402ProtocolError",this.reason=e;}isRetryable(){return true}},D=class extends l{sessionId;expiredAt;constructor(e,t){super(`Session ${e} has expired${t?` at ${t}`:""}. A new session will be created automatically on your next request.`,"SESSION_EXPIRED"),this.name="SessionExpiredError",this.sessionId=e,this.expiredAt=t;}},U=class extends l{sessionId;limit;requested;remaining;constructor(e,t,s,n){super(`Session spending limit exceeded: limit is $${e.toFixed(2)}, requested $${t.toFixed(2)}, remaining $${s.toFixed(2)}. Create a new session with a higher limit to continue.`,"SESSION_LIMIT_EXCEEDED"),this.name="SessionLimitExceededError",this.sessionId=n,this.limit=e,this.requested=t,this.remaining=s;}},I=class extends l{sessionId;constructor(e){super(`Session ${e} not found. It may have been deleted or never existed. Create a new session with getOrCreateSession().`,"SESSION_NOT_FOUND"),this.name="SessionNotFoundError",this.sessionId=e;}},R=class extends l{sessionId;reason;constructor(e,t){super(`Session ${e} has been revoked${t?`: ${t}`:""}. Create a new session with getOrCreateSession().`,"SESSION_REVOKED"),this.name="SessionRevokedError",this.sessionId=e,this.reason=t;}},E=class extends l{attempted;allowedPatterns;constructor(e,t){let s=t.slice(0,3).join(", "),n=t.length>3?"...":"";super(`Payment to "${e}" not allowed. Session allowlist: ${s}${n}. Update the session allowlist or create a new session.`,"MERCHANT_NOT_ALLOWED"),this.name="MerchantNotAllowedError",this.attempted=e,this.allowedPatterns=t;}},L=class extends l{constructor(e=6e4,t){super(t||`Rate limit exceeded. Please wait ${Math.ceil(e/1e3)} seconds before retrying.`,"RATE_LIMIT_EXCEEDED",e),this.name="RateLimitError";}isRetryable(){return true}},N=class extends l{reason;constructor(e,t){super(`Network error: ${e}. Check your connection and try again.`,"NETWORK_ERROR",5e3),this.name="NetworkError",this.reason=e,t?.stack&&(this.stack=t.stack);}isRetryable(){return true}},F=class extends l{reason;statusCode;constructor(e,t=401){super(`Authentication failed: ${e}`,t===401?"UNAUTHORIZED":"FORBIDDEN"),this.name="AuthenticationError",this.reason=e,this.statusCode=t;}isRetryable(){return false}};function Ue(c){return c instanceof l}function Ie(c){return c instanceof l||c instanceof Error?c.message:String(c)}var De={8453:"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",84532:"0x036CbD53842c5426634e7929541eC2318f3dCF7e"},Ee={name:"USD Coin",version:"2"},Oe={TransferWithAuthorization:[{name:"from",type:"address"},{name:"to",type:"address"},{name:"value",type:"uint256"},{name:"validAfter",type:"uint256"},{name:"validBefore",type:"uint256"},{name:"nonce",type:"bytes32"}]},j=class c{privateKey;account;address;isTest;constructor(e,t){this.privateKey=e,this.account=privateKeyToAccount(e),this.address=this.account.address,this.isTest=t;}toString(){return `${this.isTest?"sk_test_":"sk_live_"}${this.privateKey.slice(2)}`}get privateKeyHex(){return this.privateKey.slice(2)}get rawPrivateKey(){return this.privateKey}static fromString(e){let t=/^sk_(live|test)_([a-fA-F0-9]{64})$/,s=e.match(t);if(!s)throw new S("Session key must be in format sk_live_{64_hex} or sk_test_{64_hex}");let n=s[1],a=s[2];try{let r=`0x${a}`;return new c(r,n==="test")}catch(r){throw new S(`Failed to decode session key: ${r}`)}}async signTransferAuthorization(e,t){return signTypedData({privateKey:this.privateKey,domain:e,types:Oe,primaryType:"TransferWithAuthorization",message:t})}async signMessage(e){return signMessage({privateKey:this.privateKey,message:e})}getDefaultChainId(){return this.isTest?84532:8453}};function Y(c){let e=De[c.chainId];if(!e)throw new Error(`USDC not supported on chain ${c.chainId}`);let t={...Ee,chainId:c.chainId,verifyingContract:e},s={from:c.fromAddress,to:c.toAddress,value:c.value,validAfter:c.validAfter,validBefore:c.validBefore,nonce:c.nonce};return {domain:t,message:s}}function W(){let c=new Uint8Array(32);return crypto.getRandomValues(c),`0x${Array.from(c).map(e=>e.toString(16).padStart(2,"0")).join("")}`}function Ke(c,e){return `MixrPay:${c}:${e.toLowerCase()}`}async function V(c){let e=Date.now(),t=Ke(e,c.address),s=await c.signMessage(t);return {address:c.address,timestamp:e,signature:s}}var Z=z$1.object({query:z$1.string().describe('Search query (e.g. "web scraping", "email", "database")')}),Q=z$1.object({tool_name:z$1.string().describe('Tool name in "merchant/tool" format'),arguments:z$1.record(z$1.unknown()).optional().describe("Arguments to pass to the tool")}),ee=z$1.object({url:z$1.string().url().describe("The merchant API URL to call"),merchant_public_key:z$1.string().describe("The merchant's MixrPay public key (pk_live_... or pk_test_...)"),method:z$1.enum(["GET","POST","PUT","PATCH","DELETE"]).default("POST").describe("HTTP method"),body:z$1.unknown().optional().describe("Request body (will be JSON-serialized)"),price_usd:z$1.number().optional().describe("Expected price in USD for client-side validation")}),te=z$1.object({skill_id:z$1.string().describe("The skill ID to execute"),input:z$1.record(z$1.unknown()).optional().describe("Input parameters for the skill")}),se=z$1.object({skill_id:z$1.string().describe("The skill ID to check")}),ne=z$1.object({glama_id:z$1.string().describe('Glama server ID (e.g. "notion-mcp")'),glama_namespace:z$1.string().describe('Glama namespace (e.g. "notion")'),glama_slug:z$1.string().describe('Glama slug (e.g. "notion-mcp")'),tool_name:z$1.string().describe("Human-readable name for the tool"),tool_description:z$1.string().optional().describe("Optional description"),env_vars:z$1.record(z$1.string()).optional().describe("Environment variables for the MCP server (e.g. API keys)"),ttl_hours:z$1.number().min(1).max(168).optional().describe("Time-to-live in hours (default: 24, max: 168)")}),ae=z$1.object({status:z$1.enum(["provisioning","active","stopped","expired"]).optional().describe("Filter by status")}),re=z$1.object({instance_id:z$1.string().describe("The instance ID to stop")}),ie=z$1.object({to:z$1.string().describe("Recipient address (0x...)"),amount_usdc:z$1.number().positive().describe("Amount in USDC (e.g. 10.5)")}),oe=z$1.object({name:z$1.string().describe("Name for the child agent"),budget_usd:z$1.number().positive().describe("Budget to delegate in USD"),budget_period:z$1.enum(["daily","monthly","total"]).default("total").describe("Budget period"),max_per_tx_usd:z$1.number().positive().optional().describe("Max per-transaction limit in USD"),expires_in_days:z$1.number().min(1).max(365).optional().describe("Expiry in days (default: 30)")}),le=z$1.object({title:z$1.string().describe("Task title"),description:z$1.string().describe("Detailed task description"),budget_usd:z$1.number().positive().describe("Budget for the task in USD"),skills_required:z$1.array(z$1.string()).optional().describe("Required skill IDs")}),ce=z$1.object({status:z$1.string().optional().describe('Filter by status (e.g. "open", "in_progress")'),limit:z$1.number().min(1).max(100).optional().describe("Number of results (default: 20)")});function de(c){let e=[{name:"check_balance",title:"Check Balance",description:"Get the USDC balance of the wallet on Base.",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:null,handler:async()=>({balanceUsd:await c.getBalance(),network:c.isTestnet()?"base-sepolia":"base"})},{name:"get_spending_stats",title:"Get Spending Stats",description:"Get session key spending limits and current usage (total spent, remaining daily/total limits, expiry).",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:null,handler:async()=>c.getSpendingStats()},{name:"get_session_info",title:"Get Session Info",description:"Get detailed session key information including limits, usage, expiry, and allowed merchants.",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:null,handler:async()=>c.getSessionKeyInfo(true)},{name:"run_diagnostics",title:"Run Diagnostics",description:"Run a full health check on the wallet: API connectivity, session key validity, balance, and latency.",annotations:{readOnlyHint:true,openWorldHint:true},inputSchema:null,handler:async()=>c.runDiagnostics()},{name:"list_tools",title:"List Marketplace Tools",description:"Browse all available paid API tools on the MixrPay marketplace. Each tool includes pricing and description.",annotations:{readOnlyHint:true,openWorldHint:true},inputSchema:null,handler:async()=>c.listTools()},{name:"search_tools",title:"Search Tools",description:"Search the Glama MCP server directory for tools by keyword.",annotations:{readOnlyHint:true,openWorldHint:true},inputSchema:Z,handler:async s=>{let{query:n}=Z.parse(s);return c.searchGlamaDirectory(n)}},{name:"call_tool",title:"Call Marketplace Tool",description:'Call a paid API tool on the MixrPay marketplace. Payment is automatic from the wallet. Tool names are in "merchant/tool" format (e.g. "firecrawl/scrape").',annotations:{readOnlyHint:false,openWorldHint:true},inputSchema:Q,handler:async s=>{let{tool_name:n,arguments:a}=Q.parse(s);return c.callTool(n,a||{})}},{name:"call_merchant_api",title:"Call Merchant API",description:"Call any merchant API endpoint with x402 payment. The wallet handles authentication and payment automatically.",annotations:{readOnlyHint:false,openWorldHint:true},inputSchema:ee,handler:async s=>{let{url:n,merchant_public_key:a,method:r,body:i,price_usd:o}=ee.parse(s),d=await c.callMerchantApi({url:n,merchantPublicKey:a,method:r,body:i,priceUsd:o}),g=await d.json().catch(()=>d.text());return {status:d.status,data:g}}},{name:"list_skills",title:"List Skills",description:"List all available skills (pre-built integrations) that the wallet can use.",annotations:{readOnlyHint:true,openWorldHint:true},inputSchema:null,handler:async()=>c.listSkills()},{name:"use_skill",title:"Use Skill",description:"Execute a skill by ID. Skills are pre-built integrations (e.g. web scraping, email sending).",annotations:{readOnlyHint:false,openWorldHint:true},inputSchema:te,handler:async s=>{let{skill_id:n,input:a}=te.parse(s);return c.useSkill(n,{input:a})}},{name:"get_skill_status",title:"Get Skill Status",description:"Check the status and configuration of a specific skill.",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:se,handler:async s=>{let{skill_id:n}=se.parse(s);return c.getSkillStatus(n)}},{name:"deploy_jit_mcp",title:"Deploy JIT MCP Server",description:"Deploy a just-in-time MCP server from the Glama directory. Creates a temporary hosted MCP server instance.",annotations:{readOnlyHint:false,openWorldHint:true},inputSchema:ne,handler:async s=>{let{glama_id:n,glama_namespace:a,glama_slug:r,tool_name:i,tool_description:o,env_vars:d,ttl_hours:g}=ne.parse(s);return c.deployJitMcp({glamaId:n,glamaNamespace:a,glamaSlug:r,toolName:i,toolDescription:o,envVars:d,ttlHours:g})}},{name:"list_jit_instances",title:"List JIT Instances",description:"List all deployed JIT MCP server instances.",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:ae,handler:async s=>{let{status:n}=ae.parse(s);return c.listJitInstances(n?{status:n}:void 0)}},{name:"stop_jit_instance",title:"Stop JIT Instance",description:"Stop a running JIT MCP server instance.",annotations:{readOnlyHint:false,destructiveHint:true,openWorldHint:false},inputSchema:re,handler:async s=>{let{instance_id:n}=re.parse(s);return await c.stopJitInstance(n),{success:true,instance_id:n}}},{name:"transfer_usdc",title:"Transfer USDC",description:"Transfer USDC from the self-custody wallet to another address on Base. Only available when the wallet has a self-custody wallet (AGENT_WALLET_KEY set).",annotations:{readOnlyHint:false,destructiveHint:true,openWorldHint:true},inputSchema:ie,handler:async s=>{let{to:n,amount_usdc:a}=ie.parse(s);if(!await c.hasSelfCustodyWallet())throw new Error("No self-custody wallet configured. Set AGENT_WALLET_KEY to enable transfers.");return {success:true,txHash:await c.transferUSDC({to:n,amountUsdc:a}),to:n,amountUsdc:a}}},{name:"get_budget",title:"Get Available Budget",description:"Get the available delegation budget including remaining amount, whether spawning children is possible, and budget limits.",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:null,handler:async()=>c.getAvailableBudget()},{name:"spawn_child",title:"Spawn Child Session",description:"Create a child invite with a delegated budget from this wallet. Returns an invite code that another agent can claim.",annotations:{readOnlyHint:false,openWorldHint:false},inputSchema:oe,handler:async s=>{let{name:n,budget_usd:a,budget_period:r,max_per_tx_usd:i,expires_in_days:o}=oe.parse(s);return c.spawnChildInvite({name:n,budgetUsd:a,budgetPeriod:r,maxPerTxUsd:i,expiresInDays:o})}},{name:"list_children",title:"List Child Sessions",description:"List all child sessions (agents) spawned from this wallet.",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:null,handler:async()=>c.listChildSessions()},{name:"create_task",title:"Create Task",description:"Create a new task on the MixrPay marketplace for other agents to complete.",annotations:{readOnlyHint:false,openWorldHint:true},inputSchema:le,handler:async s=>{let{title:n,description:a,budget_usd:r,skills_required:i}=le.parse(s);return c.createTask({title:n,description:a,budgetUsd:r,skillsRequired:i})}},{name:"list_tasks",title:"List Tasks",description:"Browse available tasks on the MixrPay marketplace.",annotations:{readOnlyHint:true,openWorldHint:true},inputSchema:ce,handler:async s=>{let{status:n,limit:a}=ce.parse(s);return c.listTasks({status:n,limit:a})}}];return {definitions:e,execute:async(s,n)=>{let a=e.find(r=>r.name===s);if(!a)throw new Error(`Unknown tool: ${s}`);try{let r=await a.handler(n);return JSON.stringify(r,null,2)}catch(r){let i=r instanceof Error?r.message:String(r);throw new Error(i)}}}}function ue(c){if(c instanceof z$1.ZodObject){let e=c._def.shape(),t={},s=[];for(let[n,a]of Object.entries(e)){let r=a;t[n]=M(r),!(r instanceof z$1.ZodOptional)&&!(r instanceof z$1.ZodDefault)&&s.push(n);}return {type:"object",properties:t,...s.length>0?{required:s}:{}}}return {type:"object",properties:{}}}function M(c){let e=c;e instanceof z$1.ZodOptional&&(e=e._def.innerType),e instanceof z$1.ZodDefault&&(e=e._def.innerType);let t=c._def.description;if(e instanceof z$1.ZodString)return {type:"string",...t&&{description:t}};if(e instanceof z$1.ZodNumber)return {type:"number",...t&&{description:t}};if(e instanceof z$1.ZodBoolean)return {type:"boolean",...t&&{description:t}};if(e instanceof z$1.ZodEnum)return {type:"string",enum:e._def.values,...t&&{description:t}};if(e instanceof z$1.ZodArray)return {type:"array",items:M(e._def.type),...t&&{description:t}};if(e instanceof z$1.ZodRecord)return {type:"object",additionalProperties:M(e._def.valueType),...t&&{description:t}};if(e instanceof z$1.ZodObject){let s=e._def.shape(),n={};for(let[a,r]of Object.entries(s))n[a]=M(r);return {type:"object",properties:n,...t&&{description:t}}}return e instanceof z$1.ZodUnknown?{...t&&{description:t}}:{...t&&{description:t}}}var Ne="0.9.5",ge=".config/mixrpay",Fe="wallet.json";function me(){let c=process.env.MIXRPAY_WORKSPACE_DIR||process.env.OPENCLAW_WORKSPACE_DIR;return c?join(c,ge):join(homedir(),ge)}function C(){return join(me(),Fe)}async function B(c,e){let t=me(),s=C();existsSync(t)||mkdirSync(t,{recursive:true,mode:448});let n={address:e.toLowerCase(),privateKey:c,createdAt:new Date().toISOString(),sdkVersion:Ne};writeFileSync(s,JSON.stringify(n,null,2),{encoding:"utf-8",mode:384});try{chmodSync(s,384);}catch{}}async function H(){let c=process.env.MIXRPAY_WALLET_KEY;if(c){if(c.startsWith("0x")&&c.length===66)return c;if(c.length===64)return `0x${c}`;console.warn("[MixrPay] MIXRPAY_WALLET_KEY has invalid format, ignoring");}let e=C();if(!existsSync(e))return null;try{let t=readFileSync(e,"utf-8"),s=JSON.parse(t);return !s.privateKey||!s.privateKey.startsWith("0x")?(console.warn("[MixrPay] Wallet file has invalid format"),null):s.privateKey}catch(t){return console.warn("[MixrPay] Failed to read wallet file:",t),null}}async function We(){let c=C();if(!existsSync(c)){let e=process.env.MIXRPAY_WALLET_KEY;return e&&(e.startsWith("0x")?e:`0x${e}`).length===66,null}try{let e=readFileSync(c,"utf-8");return JSON.parse(e)}catch{return null}}async function J(){let c=process.env.MIXRPAY_WALLET_KEY;return c&&(c.length===64||c.startsWith("0x")&&c.length===66)?true:existsSync(C())}function qe(){return C()}async function Be(){let c=C();if(!existsSync(c))return false;try{let{unlinkSync:e}=await import('fs');return e(c),!0}catch{return false}}async function he(c){let e=null,t=c.headers.get("X-Payment-Required");if(t)try{e=JSON.parse(t);}catch{}if(!e){let n=c.headers.get("WWW-Authenticate");if(n?.startsWith("X-402 "))try{let a=n.slice(6);e=JSON.parse(atob(a));}catch{}}if(!e)try{e=await c.json();}catch{}if(!e)throw new T("Could not parse payment requirements from 402 response");if(!e.recipient)throw new T("Missing recipient in payment requirements");if(!e.amount)throw new T("Missing amount in payment requirements");let s=Math.floor(Date.now()/1e3);return {recipient:e.recipient,amount:BigInt(e.amount),currency:e.currency||"USDC",chainId:e.chainId||e.chain_id||8453,facilitatorUrl:e.facilitatorUrl||e.facilitator_url||"https://x402.org/facilitator",nonce:e.nonce||W().slice(2),expiresAt:e.expiresAt||e.expires_at||s+300,description:e.description}}async function ye(c,e,t){let s=c.nonce.length===64?`0x${c.nonce}`:W(),a=BigInt(Math.floor(Date.now()/1e3))-60n,r=BigInt(c.expiresAt),{domain:i,message:o}=Y({fromAddress:t,toAddress:c.recipient,value:c.amount,validAfter:a,validBefore:r,nonce:s,chainId:c.chainId}),d=await e.signTransferAuthorization(i,o),g={x402Version:1,scheme:"exact",network:c.chainId===8453?"base":"base-sepolia",payload:{signature:d,authorization:{from:t,to:c.recipient,value:c.amount.toString(),validAfter:a.toString(),validBefore:r.toString(),nonce:s}}};return btoa(JSON.stringify(g))}function fe(c){return Date.now()/1e3>c.expiresAt}function G(c){return Number(c.amount)/1e6}var Se="0.11.0",_=process.env.MIXRPAY_BASE_URL||"https://mixr.network";var et=3e4,be={BASE_MAINNET:{chainId:8453,name:"Base",isTestnet:false},BASE_SEPOLIA:{chainId:84532,name:"Base Sepolia",isTestnet:true}},_e={debug:0,info:1,warn:2,error:3,none:4},X=class{level;prefix;constructor(e="none",t="[MixrPay]"){this.level=e,this.prefix=t;}setLevel(e){this.level=e;}shouldLog(e){return _e[e]>=_e[this.level]}debug(...e){this.shouldLog("debug")&&console.log(`${this.prefix} \u{1F50D}`,...e);}info(...e){this.shouldLog("info")&&console.log(`${this.prefix} \u2139\uFE0F`,...e);}warn(...e){this.shouldLog("warn")&&console.warn(`${this.prefix} \u26A0\uFE0F`,...e);}error(...e){this.shouldLog("error")&&console.error(`${this.prefix} \u274C`,...e);}payment(e,t,s){if(this.shouldLog("info")){let n=s?` for "${s}"`:"";console.log(`${this.prefix} \u{1F4B8} Paid $${e.toFixed(4)} to ${t.slice(0,10)}...${n}`);}}},z=class c{sessionKey;walletAddress;maxPaymentUsd;onPayment;baseUrl;timeout;logger;payments=[];totalSpentUsd=0;sessionKeyInfo;sessionKeyInfoFetchedAt;allowlist;allowlistFetchedAt;selfCustodyAddress;selfCustodyKey;agentInstanceId;apiKey;sessionKeyId;constructor(e){this.validateConfig(e),this.sessionKey=j.fromString(e.sessionKey),this.walletAddress=e.walletAddress||this.sessionKey.address,this.maxPaymentUsd=e.maxPaymentUsd,this.onPayment=e.onPayment,this.baseUrl=(e.baseUrl||_).replace(/\/$/,""),this.timeout=e.timeout||et,e.apiKey&&(this.apiKey=e.apiKey),e.sessionKeyId&&(this.sessionKeyId=e.sessionKeyId),this.logger=new X(e.logLevel||"none"),this.logger.debug("AgentWallet initialized",{walletAddress:this.walletAddress,isTestnet:this.isTestnet(),maxPaymentUsd:this.maxPaymentUsd,hasApiKey:!!this.apiKey,hasSessionKeyId:!!this.sessionKeyId});}validateConfig(e){if(!e.sessionKey)throw new S("Session key is required. Get one from the wallet owner at https://mixrpay.com/manage/invites");let t=e.sessionKey.trim();if(!t.startsWith("sk_live_")&&!t.startsWith("sk_test_")){let a=t.slice(0,8);throw new S(`Invalid session key prefix. Expected 'sk_live_' (mainnet) or 'sk_test_' (testnet), got '${a}'`)}let s=72;if(t.length!==s)throw new S(`Invalid session key length. Expected ${s} characters, got ${t.length}. Make sure you copied the complete key.`);let n=t.slice(8);if(!/^[0-9a-fA-F]+$/.test(n))throw new S("Invalid session key format. The key should contain only hexadecimal characters after the prefix.");if(e.maxPaymentUsd!==void 0){if(e.maxPaymentUsd<=0)throw new l("maxPaymentUsd must be a positive number");e.maxPaymentUsd>1e4&&this.logger?.warn("maxPaymentUsd is very high ($"+e.maxPaymentUsd+"). Consider using a lower limit for safety.");}}async fetchAllowlist(){if(this.allowlist!==void 0&&this.allowlistFetchedAt&&Date.now()-this.allowlistFetchedAt<3e5)return this.allowlist;try{let t=await this.getSessionKeyInfo();return this.allowlist=t.allowedMerchants||[],this.allowlistFetchedAt=Date.now(),this.logger.debug("Fetched allowlist",{patterns:this.allowlist.length,allowAll:this.allowlist.length===0}),this.allowlist}catch(t){return this.logger.warn("Failed to fetch allowlist, allowing all merchants",{error:t}),this.allowlist=[],this.allowlistFetchedAt=Date.now(),this.allowlist}}async validateMerchantAllowed(e,t){let s=await this.fetchAllowlist();if(s.length===0)return;if(!this.matchesAllowlist(e,s,t))throw new E(e,s)}matchesAllowlist(e,t,s){for(let n of t)if(this.matchPattern(e,n,s))return true;return false}matchPattern(e,t,s){return s==="url"?this.matchUrlPattern(e,t):this.matchToolPattern(e,t)}matchUrlPattern(e,t){let s;try{e.includes("://")?s=new URL(e).hostname.toLowerCase():s=e.toLowerCase();}catch{return false}let a=t.toLowerCase().trim();if(a.includes("://"))try{a=new URL(a).hostname;}catch{}if(s===a)return true;if(a.startsWith("*.")){let r=a.substring(2);if(s.endsWith(`.${r}`)&&s!==r)return true}return false}matchToolPattern(e,t){let s=e.toLowerCase().trim(),n=t.toLowerCase().trim();if(s===n)return true;if(n.endsWith("/*")){let a=n.substring(0,n.length-2);if(s.startsWith(`${a}/`))return true}return false}static async register(e){let{privateKey:t,name:s}=e,n=(e.baseUrl||_).replace(/\/$/,""),r=privateKeyToAccount(t).address,i=await fetch(`${n}/api/v1/agent/challenge?wallet=${r}&action=register`);if(!i.ok){let y=await i.json().catch(()=>({}));throw new l(y.error||`Failed to get challenge: ${i.status}`)}let{challenge:o,message:d}=await i.json(),g=await signMessage({message:d,privateKey:t}),u=await fetch(`${n}/api/v1/agent/register`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({challenge:o,external_wallet:r,signature:g,name:s})});if(!u.ok){let y=await u.json().catch(()=>({})),f=y.error||`Registration failed with status ${u.status}`,h=y.request_id,w=(y.code||"").toLowerCase(),b="";u.status===503?b=" The service may be temporarily unavailable. Please try again later.":u.status===500?b=" This is a server error. Please contact support with the request ID.":(w==="missing_challenge"||w==="missing_signature")&&(b=" This may indicate an SDK bug. Please update to the latest version.");let K=h?`${f} (request_id: ${h})${b}`:`${f}${b}`;throw new l(K)}let p=await u.json();return {userId:p.user_id,depositAddress:p.deposit_address}}static async checkServerHealth(e){let t=(e||_).replace(/\/$/,"");try{let s=await fetch(`${t}/api/health/ready?details=true`);if(!s.ok)return {healthy:!1,database:"unknown",agentRegistrationAvailable:!1,walletServiceConfigured:!1,error:`Health check failed with status ${s.status}`};let n=await s.json();return {healthy:n.status==="ready",database:n.database||"unknown",agentRegistrationAvailable:n.services?.agentRegistration?.available??!1,walletServiceConfigured:n.services?.wallet?.configured??!1}}catch(s){return {healthy:false,database:"unreachable",agentRegistrationAvailable:false,walletServiceConfigured:false,error:s instanceof Error?s.message:"Failed to reach server"}}}static async getSessionKey(e){let{privateKey:t,spendingLimitUsd:s,maxPerTxUsd:n,maxDailyUsd:a,durationDays:r}=e,i=(e.baseUrl||_).replace(/\/$/,""),d=privateKeyToAccount(t).address,g=await fetch(`${i}/api/v1/agent/challenge?wallet=${d}&action=session-key`);if(!g.ok){let w=await g.json().catch(()=>({}));throw new l(w.error||`Failed to get challenge: ${g.status}`)}let{challenge:u,message:p}=await g.json(),y=await signMessage({message:p,privateKey:t}),f=await fetch(`${i}/api/v1/agent/session-key`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({challenge:u,external_wallet:d,signature:y,spending_limit_usd:s,max_per_tx_usd:n,max_daily_usd:a,duration_days:r})});if(!f.ok){let w=await f.json().catch(()=>({}));throw new l(w.error||`Session key creation failed: ${f.status}`)}let h=await f.json();return {sessionKey:h.session_key,address:h.address,sessionKeyId:h.session_key_id,expiresAt:new Date(h.expires_at),limits:{maxTotalUsd:h.limits.max_total_usd,maxPerTxUsd:h.limits.max_per_tx_usd,maxDailyUsd:h.limits.max_daily_usd}}}static async getStatus(e){let{privateKey:t}=e,s=(e.baseUrl||_).replace(/\/$/,""),a=privateKeyToAccount(t).address,r=await fetch(`${s}/api/v1/agent/challenge?wallet=${a}&action=status`);if(!r.ok){let p=await r.json().catch(()=>({}));throw new l(p.error||`Failed to get challenge: ${r.status}`)}let{challenge:i,message:o}=await r.json(),d=await signMessage({message:o,privateKey:t}),g=await fetch(`${s}/api/v1/agent/status?challenge=${i}&external_wallet=${a}&signature=${encodeURIComponent(d)}`);if(!g.ok){let p=await g.json().catch(()=>({}));throw new l(p.error||`Failed to get status: ${g.status}`)}let u=await g.json();return {depositAddress:u.deposit_address,balanceUsd:u.balance_usd,activeSessions:u.active_sessions.map(p=>({id:p.id,expiresAt:new Date(p.expires_at),totalSpentUsd:p.total_spent_usd,remainingUsd:p.remaining_usd,maxTotalUsd:p.max_total_usd})),totalSpentUsd:u.total_spent_usd}}static async revokeSessionKey(e){let{privateKey:t,sessionKeyId:s}=e,n=(e.baseUrl||_).replace(/\/$/,""),r=privateKeyToAccount(t).address,i=await fetch(`${n}/api/v1/agent/challenge?wallet=${r}&action=revoke`);if(!i.ok){let p=await i.json().catch(()=>({}));throw new l(p.error||`Failed to get challenge: ${i.status}`)}let{challenge:o,message:d}=await i.json(),g=await signMessage({message:d,privateKey:t}),u=await fetch(`${n}/api/v1/agent/session-key/revoke`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({challenge:o,external_wallet:r,signature:g,session_key_id:s})});if(!u.ok){let p=await u.json().catch(()=>({}));throw new l(p.error||`Revocation failed: ${u.status}`)}return true}static async withdraw(e){let{privateKey:t,amountUsd:s}=e,n=(e.baseUrl||_).replace(/\/$/,""),r=privateKeyToAccount(t).address,i=await fetch(`${n}/api/v1/agent/challenge?wallet=${r}&action=withdraw`);if(!i.ok){let y=await i.json().catch(()=>({}));throw new l(y.error||`Failed to get challenge: ${i.status}`)}let{challenge:o,message:d}=await i.json(),g=await signMessage({message:d,privateKey:t}),u=await fetch(`${n}/api/v1/agent/withdraw`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({challenge:o,external_wallet:r,signature:g,to_address:r,amount_usd:s})});if(!u.ok){let y=await u.json().catch(()=>({}));throw new l(y.error||`Withdrawal failed: ${u.status}`)}let p=await u.json();return {txHash:p.tx_hash,amountUsd:p.amount_usd,remainingBalanceUsd:p.remaining_balance_usd}}static async claimInvite(e){let{inviteCode:t,privateKey:s}=e,n=(e.baseUrl||_).replace(/\/$/,""),r=privateKeyToAccount(s).address,i=await fetch(`${n}/api/v1/agent/challenge?wallet=${r}&action=claim-invite`);if(!i.ok){let y=await i.json().catch(()=>({}));throw new l(y.error||`Failed to get challenge: ${i.status}`)}let{challenge:o,message:d}=await i.json(),g=await signMessage({message:d,privateKey:s}),u=await fetch(`${n}/api/v1/agent/claim-invite`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({invite_code:t,challenge:o,agent_wallet_address:r,signature:g})});if(!u.ok){let f=(await u.json().catch(()=>({}))).error||`Failed to claim invite: ${u.status}`,h="";throw u.status===404?h=" The invite code may be invalid or misspelled.":u.status===400&&(f.includes("already claimed")?h=" This invite has already been used by another agent.":f.includes("expired")?h=" Ask the wallet owner to create a new invite.":f.includes("revoked")&&(h=" The wallet owner has revoked this invite.")),new l(`${f}${h}`)}let p=await u.json();return {sessionKey:p.session_key,address:p.address,sessionKeyId:p.session_key_id,expiresAt:new Date(p.expires_at),limits:{budgetUsd:p.limits.budget_usd,budgetPeriod:p.limits.budget_period,maxPerTxUsd:p.limits.max_per_tx_usd},allowedMerchants:p.allowed_merchants||[],inviterName:p.inviter_name||"Anonymous"}}static async activate(e,t){let s=(t?.baseUrl||_).replace(/\/$/,""),n=new c({sessionKey:e,baseUrl:s}),a=await n.getSessionAuthHeaders(),r=await fetch(`${s}/api/v2/agent/activate`,{method:"POST",headers:{"Content-Type":"application/json",...a}});if(!r.ok){let o=await r.json().catch(()=>({}));throw new l(o.error||`Activation failed: ${r.status}`)}let i=await r.json();return {wallet:n,budget:{maxTotalUsd:i.budget.max_total_usd,maxDailyUsd:i.budget.max_daily_usd,maxPerTxUsd:i.budget.max_per_tx_usd,spentUsd:i.budget.spent_usd,remainingUsd:i.budget.remaining_usd},capabilities:{executeTransactions:i.capabilities.execute_transactions,gasSponsored:i.capabilities.gas_sponsored,batchedTx:i.capabilities.batched_tx},skills:i.skills||[],tools:i.tools||[],gatewayProviders:i.gateway_providers||[]}}static async connect(e){let t=(e?.baseUrl||process.env.MIXRPAY_BASE_URL||_).replace(/\/$/,""),s=e?.logLevel||"none",n=process.env.MIXRPAY_INSTANCE_ID;if(e?.sessionKey){let g=new c({sessionKey:e.sessionKey,sessionKeyId:e.sessionKeyId,baseUrl:t,logLevel:s,maxPaymentUsd:e?.maxPaymentUsd,onPayment:e?.onPayment});return n&&g.setAgentInstanceId(n),g}let a=process.env.MIXRPAY_SESSION_KEY;if(a){let g=process.env.MIXRPAY_SESSION_KEY_ID,u=new c({sessionKey:a,sessionKeyId:g,baseUrl:t,logLevel:s,maxPaymentUsd:e?.maxPaymentUsd,onPayment:e?.onPayment});return n&&u.setAgentInstanceId(n),u}let r=process.env.MIXRPAY_API_KEY||process.env.MIXRPAY_AGENT_TOKEN;if(r&&(r.startsWith("agt_live_")||r.startsWith("agt_test_")))return c.fromApiKey(r,{baseUrl:t,logLevel:s});let i=e?.accessCode||process.env.MIXRPAY_ACCESS_CODE;if(i)return c.fromAccessCode(i,{baseUrl:t,logLevel:s});let o=e?.masterKey||process.env.MIXRPAY_MASTER_KEY,d=e?.agentName||process.env.MIXRPAY_AGENT_NAME;if(o&&d)return c.fromMasterKey(o,d,{baseUrl:t,logLevel:s});try{let{loadCredentials:g}=await import('./credentials-64ZBZ5AS.js'),u=g();if(u.success&&u.credentials.sessionKey){let p=new c({sessionKey:u.credentials.sessionKey,sessionKeyId:u.credentials.sessionKeyId,baseUrl:u.credentials.baseUrl||t,logLevel:s,maxPaymentUsd:e?.maxPaymentUsd,onPayment:e?.onPayment,apiKey:u.credentials.apiToken});return n&&p.setAgentInstanceId(n),p}if(u.success&&u.credentials.apiToken)return c.fromApiKey(u.credentials.apiToken,{baseUrl:t,logLevel:s});if(u.success&&u.credentials.masterKey&&u.credentials.defaultAgentName)return c.fromMasterKey(u.credentials.masterKey,u.credentials.defaultAgentName,{baseUrl:t,logLevel:s})}catch{}if(e?.interactive)return c.deviceFlowLogin({baseUrl:t,logLevel:s});throw new l("No MixrPay credentials found. Options:\n 1. Set MIXRPAY_SESSION_KEY environment variable\n 2. Set MIXRPAY_API_KEY or MIXRPAY_AGENT_TOKEN environment variable (agt_live_xxx)\n 3. Set MIXRPAY_ACCESS_CODE environment variable (mixr-xxx)\n 4. Pass sessionKey or accessCode to connect()\n 5. Run `npx --package @mixrpay/agent-sdk mixrpay login` (or `npm i -g @mixrpay/agent-sdk` then `mixrpay login`)\n 6. Use connect({ interactive: true }) for browser login")}static async fromApiKey(e,t){let s=(t?.baseUrl||_).replace(/\/$/,"");if(!e.startsWith("agt_live_")&&!e.startsWith("agt_test_"))throw new l(`Invalid API key format. Expected 'agt_live_' or 'agt_test_' prefix, got '${e.slice(0,9)}...'`);let n=await fetch(`${s}/api/v2/agent/session-from-token`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`}});if(!n.ok){let o=await n.json().catch(()=>({}));throw new l(o.error||`Failed to exchange API key for session: ${n.status}`)}let a=await n.json(),r=a.session_key;if(!r)throw new l("No session_key in API response");let i=new c({sessionKey:r,baseUrl:s,logLevel:t?.logLevel});return i.setApiKey(e),a.agent_instance_id&&i.setAgentInstanceId(a.agent_instance_id),i}static async fromAccessCode(e,t){let s=(t?.baseUrl||_).replace(/\/$/,"");if(!e.startsWith("mixr-"))throw new l(`Invalid access code format. Expected 'mixr-' prefix, got '${e.slice(0,5)}...'`);let n=await fetch(`${s}/api/v2/agent/connect`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({code:e})});if(!n.ok){let g=await n.json().catch(()=>({})),u=(g.code||"").toLowerCase(),p="";throw n.status===404||u==="invalid_code"?p=" Check the code for typos or get a new one from the MixrPay dashboard.":n.status===400&&(u==="code_claimed"?p=" This code has already been used. Get a new code from the dashboard.":u==="code_expired"?p=" This code has expired. Get a new code from the dashboard.":u==="code_revoked"&&(p=" This code has been revoked by the owner.")),new l((g.error||`Failed to activate access code: ${n.status}`)+p)}let a=await n.json(),r=a.session_key,i=a.token,o=a.agent_id;if(!r)throw new l("No session_key in access code response");try{let{saveCredentials:g}=await import('./credentials-64ZBZ5AS.js');g({sessionKey:r,apiToken:i,baseUrl:s});}catch{}let d=new c({sessionKey:r,baseUrl:s,logLevel:t?.logLevel});return i&&(d.apiKey=i),o&&(d.agentInstanceId=o),d}static async fromMasterKey(e,t,s){let n=(s?.baseUrl||_).replace(/\/$/,"");if(!e.startsWith("mk_live_")&&!e.startsWith("mk_test_"))throw new l("Invalid master key format. Expected 'mk_live_' or 'mk_test_' prefix.");let a=await fetch(`${n}/api/v2/master-keys/session`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify({agent_name:t})});if(!a.ok){let g=await a.json().catch(()=>({}));throw a.status===404?new l(`Agent '${t}' not found. Use the MixrPay dashboard to create it.`):new l(g.error||`Failed to get session from master key: ${a.status}`)}let r=await a.json(),i=r.session_key,o=r.session_key_id;if(!i)throw new l("No session_key in master key response");let d=new c({sessionKey:i,sessionKeyId:o,baseUrl:n,logLevel:s?.logLevel});return r.agent?.id&&(d.agentInstanceId=r.agent.id),d}static async deviceFlowLogin(e){let t=(e?.baseUrl||_).replace(/\/$/,""),s=await fetch(`${t}/api/v2/auth/device/authorize`,{method:"POST",headers:{"Content-Type":"application/json"}});if(!s.ok){let y=await s.json().catch(()=>({}));throw new l(y.error||`Device flow initiation failed: ${s.status}`)}let n=await s.json(),{device_code:a,user_code:r,verification_uri:i,verification_uri_complete:o,expires_in:d,interval:g}=n;console.log(`
8
2
  \u{1F510} MixrPay Login
9
3
  `),console.log(`Visit: ${o||i}`),console.log(`Enter code: ${r}
10
4
  `),console.log(`Waiting for authentication...
@@ -1,16 +1,10 @@
1
1
  #!/usr/bin/env node
2
- import {McpServer}from'@modelcontextprotocol/sdk/server/mcp.js';import {StdioServerTransport}from'@modelcontextprotocol/sdk/server/stdio.js';import {fileURLToPath}from'url';import {join,dirname}from'path';import {privateKeyToAccount,signMessage,generatePrivateKey,signTypedData}from'viem/accounts';import {z as z$1}from'zod';import {createWalletClient,http,parseUnits,encodeFunctionData}from'viem';import {base}from'viem/chains';import {existsSync,readFileSync,mkdirSync,writeFileSync,chmodSync}from'fs';import {homedir}from'os';var l=class extends Error{code;retryAfterMs;constructor(e,t="MIXRPAY_ERROR",s){super(e),this.name="MixrPayError",this.code=t,this.retryAfterMs=s,Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor);}isRetryable(){return false}},k=class extends l{required;available;topUpUrl;constructor(e,t){let s=e-t;super(`Insufficient balance: need $${e.toFixed(2)}, have $${t.toFixed(2)} (short $${s.toFixed(2)}). Top up your wallet to continue.`,"INSUFFICIENT_BALANCE"),this.name="InsufficientBalanceError",this.required=e,this.available=t,this.topUpUrl="https://mixr.network/manage/wallet";}},$=class extends l{expiredAt;constructor(e){super(`Session key expired at ${e}. Request a new session key from the wallet owner at https://mixrpay.com/manage/invites`,"SESSION_KEY_EXPIRED"),this.name="SessionKeyExpiredError",this.expiredAt=e;}},T=class extends l{limitType;limit;attempted;constructor(e,t,s){let a={per_tx:"Per-transaction",daily:"Daily",total:"Total",client_max:"Client-side"}[e]||e,r=e==="daily"?"Wait until tomorrow or request a higher limit.":e==="client_max"?"Increase maxPaymentUsd in your AgentWallet configuration.":"Request a new session key with a higher limit.";super(`${a} spending limit exceeded: limit is $${t.toFixed(2)}, attempted $${s.toFixed(2)}. ${r}`,"SPENDING_LIMIT_EXCEEDED"),this.name="SpendingLimitExceededError",this.limitType=e,this.limit=t,this.attempted=s;}isRetryable(){return this.limitType==="daily"}},x=class extends l{reason;txHash;constructor(e,t){let s=`Payment failed: ${e}`;t&&(s+=` (tx: ${t} - check on basescan.org)`),super(s,"PAYMENT_FAILED"),this.name="PaymentFailedError",this.reason=e,this.txHash=t;}isRetryable(){return true}},A=class extends l{reason;constructor(e="Invalid session key format"){super(`${e}. Session keys should be in format: sk_live_<64 hex chars> or sk_test_<64 hex chars>. Get one from https://mixrpay.com/manage/invites`,"INVALID_SESSION_KEY"),this.name="InvalidSessionKeyError",this.reason=e;}},P=class extends l{reason;constructor(e){super(`x402 protocol error: ${e}. This may indicate a server configuration issue. If the problem persists, contact the API provider.`,"X402_PROTOCOL_ERROR"),this.name="X402ProtocolError",this.reason=e;}isRetryable(){return true}},D=class extends l{sessionId;expiredAt;constructor(e,t){super(`Session ${e} has expired${t?` at ${t}`:""}. A new session will be created automatically on your next request.`,"SESSION_EXPIRED"),this.name="SessionExpiredError",this.sessionId=e,this.expiredAt=t;}},U=class extends l{sessionId;limit;requested;remaining;constructor(e,t,s,n){super(`Session spending limit exceeded: limit is $${e.toFixed(2)}, requested $${t.toFixed(2)}, remaining $${s.toFixed(2)}. Create a new session with a higher limit to continue.`,"SESSION_LIMIT_EXCEEDED"),this.name="SessionLimitExceededError",this.sessionId=n,this.limit=e,this.requested=t,this.remaining=s;}},I=class extends l{sessionId;constructor(e){super(`Session ${e} not found. It may have been deleted or never existed. Create a new session with getOrCreateSession().`,"SESSION_NOT_FOUND"),this.name="SessionNotFoundError",this.sessionId=e;}},R=class extends l{sessionId;reason;constructor(e,t){super(`Session ${e} has been revoked${t?`: ${t}`:""}. Create a new session with getOrCreateSession().`,"SESSION_REVOKED"),this.name="SessionRevokedError",this.sessionId=e,this.reason=t;}},E=class extends l{attempted;allowedPatterns;constructor(e,t){let s=t.slice(0,3).join(", "),n=t.length>3?"...":"";super(`Payment to "${e}" not allowed. Session allowlist: ${s}${n}. Update the session allowlist or create a new session.`,"MERCHANT_NOT_ALLOWED"),this.name="MerchantNotAllowedError",this.attempted=e,this.allowedPatterns=t;}};var ke={8453:"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",84532:"0x036CbD53842c5426634e7929541eC2318f3dCF7e"},Te={name:"USD Coin",version:"2"},Pe={TransferWithAuthorization:[{name:"from",type:"address"},{name:"to",type:"address"},{name:"value",type:"uint256"},{name:"validAfter",type:"uint256"},{name:"validBefore",type:"uint256"},{name:"nonce",type:"bytes32"}]},O=class c{privateKey;account;address;isTest;constructor(e,t){this.privateKey=e,this.account=privateKeyToAccount(e),this.address=this.account.address,this.isTest=t;}toString(){return `${this.isTest?"sk_test_":"sk_live_"}${this.privateKey.slice(2)}`}get privateKeyHex(){return this.privateKey.slice(2)}get rawPrivateKey(){return this.privateKey}static fromString(e){let t=/^sk_(live|test)_([a-fA-F0-9]{64})$/,s=e.match(t);if(!s)throw new A("Session key must be in format sk_live_{64_hex} or sk_test_{64_hex}");let n=s[1],a=s[2];try{let r=`0x${a}`;return new c(r,n==="test")}catch(r){throw new A(`Failed to decode session key: ${r}`)}}async signTransferAuthorization(e,t){return signTypedData({privateKey:this.privateKey,domain:e,types:Pe,primaryType:"TransferWithAuthorization",message:t})}async signMessage(e){return signMessage({privateKey:this.privateKey,message:e})}getDefaultChainId(){return this.isTest?84532:8453}};function X(c){let e=ke[c.chainId];if(!e)throw new Error(`USDC not supported on chain ${c.chainId}`);let t={...Te,chainId:c.chainId,verifyingContract:e},s={from:c.fromAddress,to:c.toAddress,value:c.value,validAfter:c.validAfter,validBefore:c.validBefore,nonce:c.nonce};return {domain:t,message:s}}function N(){let c=new Uint8Array(32);return crypto.getRandomValues(c),`0x${Array.from(c).map(e=>e.toString(16).padStart(2,"0")).join("")}`}function Ue(c,e){return `MixrPay:${c}:${e.toLowerCase()}`}async function Y(c){let e=Date.now(),t=Ue(e,c.address),s=await c.signMessage(t);return {address:c.address,timestamp:e,signature:s}}var z=z$1.object({query:z$1.string().describe('Search query (e.g. "web scraping", "email", "database")')}),V=z$1.object({tool_name:z$1.string().describe('Tool name in "merchant/tool" format'),arguments:z$1.record(z$1.unknown()).optional().describe("Arguments to pass to the tool")}),Z=z$1.object({url:z$1.string().url().describe("The merchant API URL to call"),merchant_public_key:z$1.string().describe("The merchant's MixrPay public key (pk_live_... or pk_test_...)"),method:z$1.enum(["GET","POST","PUT","PATCH","DELETE"]).default("POST").describe("HTTP method"),body:z$1.unknown().optional().describe("Request body (will be JSON-serialized)"),price_usd:z$1.number().optional().describe("Expected price in USD for client-side validation")}),Q=z$1.object({skill_id:z$1.string().describe("The skill ID to execute"),input:z$1.record(z$1.unknown()).optional().describe("Input parameters for the skill")}),ee=z$1.object({skill_id:z$1.string().describe("The skill ID to check")}),te=z$1.object({glama_id:z$1.string().describe('Glama server ID (e.g. "notion-mcp")'),glama_namespace:z$1.string().describe('Glama namespace (e.g. "notion")'),glama_slug:z$1.string().describe('Glama slug (e.g. "notion-mcp")'),tool_name:z$1.string().describe("Human-readable name for the tool"),tool_description:z$1.string().optional().describe("Optional description"),env_vars:z$1.record(z$1.string()).optional().describe("Environment variables for the MCP server (e.g. API keys)"),ttl_hours:z$1.number().min(1).max(168).optional().describe("Time-to-live in hours (default: 24, max: 168)")}),se=z$1.object({status:z$1.enum(["provisioning","active","stopped","expired"]).optional().describe("Filter by status")}),ne=z$1.object({instance_id:z$1.string().describe("The instance ID to stop")}),ae=z$1.object({to:z$1.string().describe("Recipient address (0x...)"),amount_usdc:z$1.number().positive().describe("Amount in USDC (e.g. 10.5)")}),re=z$1.object({name:z$1.string().describe("Name for the child agent"),budget_usd:z$1.number().positive().describe("Budget to delegate in USD"),budget_period:z$1.enum(["daily","monthly","total"]).default("total").describe("Budget period"),max_per_tx_usd:z$1.number().positive().optional().describe("Max per-transaction limit in USD"),expires_in_days:z$1.number().min(1).max(365).optional().describe("Expiry in days (default: 30)")}),ie=z$1.object({title:z$1.string().describe("Task title"),description:z$1.string().describe("Detailed task description"),budget_usd:z$1.number().positive().describe("Budget for the task in USD"),skills_required:z$1.array(z$1.string()).optional().describe("Required skill IDs")}),oe=z$1.object({status:z$1.string().optional().describe('Filter by status (e.g. "open", "in_progress")'),limit:z$1.number().min(1).max(100).optional().describe("Number of results (default: 20)")});function j(c){let e=[{name:"check_balance",title:"Check Balance",description:"Get the USDC balance of the wallet on Base.",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:null,handler:async()=>({balanceUsd:await c.getBalance(),network:c.isTestnet()?"base-sepolia":"base"})},{name:"get_spending_stats",title:"Get Spending Stats",description:"Get session key spending limits and current usage (total spent, remaining daily/total limits, expiry).",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:null,handler:async()=>c.getSpendingStats()},{name:"get_session_info",title:"Get Session Info",description:"Get detailed session key information including limits, usage, expiry, and allowed merchants.",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:null,handler:async()=>c.getSessionKeyInfo(true)},{name:"run_diagnostics",title:"Run Diagnostics",description:"Run a full health check on the wallet: API connectivity, session key validity, balance, and latency.",annotations:{readOnlyHint:true,openWorldHint:true},inputSchema:null,handler:async()=>c.runDiagnostics()},{name:"list_tools",title:"List Marketplace Tools",description:"Browse all available paid API tools on the MixrPay marketplace. Each tool includes pricing and description.",annotations:{readOnlyHint:true,openWorldHint:true},inputSchema:null,handler:async()=>c.listTools()},{name:"search_tools",title:"Search Tools",description:"Search the Glama MCP server directory for tools by keyword.",annotations:{readOnlyHint:true,openWorldHint:true},inputSchema:z,handler:async s=>{let{query:n}=z.parse(s);return c.searchGlamaDirectory(n)}},{name:"call_tool",title:"Call Marketplace Tool",description:'Call a paid API tool on the MixrPay marketplace. Payment is automatic from the wallet. Tool names are in "merchant/tool" format (e.g. "firecrawl/scrape").',annotations:{readOnlyHint:false,openWorldHint:true},inputSchema:V,handler:async s=>{let{tool_name:n,arguments:a}=V.parse(s);return c.callTool(n,a||{})}},{name:"call_merchant_api",title:"Call Merchant API",description:"Call any merchant API endpoint with x402 payment. The wallet handles authentication and payment automatically.",annotations:{readOnlyHint:false,openWorldHint:true},inputSchema:Z,handler:async s=>{let{url:n,merchant_public_key:a,method:r,body:i,price_usd:o}=Z.parse(s),d=await c.callMerchantApi({url:n,merchantPublicKey:a,method:r,body:i,priceUsd:o}),g=await d.json().catch(()=>d.text());return {status:d.status,data:g}}},{name:"list_skills",title:"List Skills",description:"List all available skills (pre-built integrations) that the wallet can use.",annotations:{readOnlyHint:true,openWorldHint:true},inputSchema:null,handler:async()=>c.listSkills()},{name:"use_skill",title:"Use Skill",description:"Execute a skill by ID. Skills are pre-built integrations (e.g. web scraping, email sending).",annotations:{readOnlyHint:false,openWorldHint:true},inputSchema:Q,handler:async s=>{let{skill_id:n,input:a}=Q.parse(s);return c.useSkill(n,{input:a})}},{name:"get_skill_status",title:"Get Skill Status",description:"Check the status and configuration of a specific skill.",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:ee,handler:async s=>{let{skill_id:n}=ee.parse(s);return c.getSkillStatus(n)}},{name:"deploy_jit_mcp",title:"Deploy JIT MCP Server",description:"Deploy a just-in-time MCP server from the Glama directory. Creates a temporary hosted MCP server instance.",annotations:{readOnlyHint:false,openWorldHint:true},inputSchema:te,handler:async s=>{let{glama_id:n,glama_namespace:a,glama_slug:r,tool_name:i,tool_description:o,env_vars:d,ttl_hours:g}=te.parse(s);return c.deployJitMcp({glamaId:n,glamaNamespace:a,glamaSlug:r,toolName:i,toolDescription:o,envVars:d,ttlHours:g})}},{name:"list_jit_instances",title:"List JIT Instances",description:"List all deployed JIT MCP server instances.",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:se,handler:async s=>{let{status:n}=se.parse(s);return c.listJitInstances(n?{status:n}:void 0)}},{name:"stop_jit_instance",title:"Stop JIT Instance",description:"Stop a running JIT MCP server instance.",annotations:{readOnlyHint:false,destructiveHint:true,openWorldHint:false},inputSchema:ne,handler:async s=>{let{instance_id:n}=ne.parse(s);return await c.stopJitInstance(n),{success:true,instance_id:n}}},{name:"transfer_usdc",title:"Transfer USDC",description:"Transfer USDC from the self-custody wallet to another address on Base. Only available when the wallet has a self-custody wallet (AGENT_WALLET_KEY set).",annotations:{readOnlyHint:false,destructiveHint:true,openWorldHint:true},inputSchema:ae,handler:async s=>{let{to:n,amount_usdc:a}=ae.parse(s);if(!await c.hasSelfCustodyWallet())throw new Error("No self-custody wallet configured. Set AGENT_WALLET_KEY to enable transfers.");return {success:true,txHash:await c.transferUSDC({to:n,amountUsdc:a}),to:n,amountUsdc:a}}},{name:"get_budget",title:"Get Available Budget",description:"Get the available delegation budget including remaining amount, whether spawning children is possible, and budget limits.",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:null,handler:async()=>c.getAvailableBudget()},{name:"spawn_child",title:"Spawn Child Session",description:"Create a child invite with a delegated budget from this wallet. Returns an invite code that another agent can claim.",annotations:{readOnlyHint:false,openWorldHint:false},inputSchema:re,handler:async s=>{let{name:n,budget_usd:a,budget_period:r,max_per_tx_usd:i,expires_in_days:o}=re.parse(s);return c.spawnChildInvite({name:n,budgetUsd:a,budgetPeriod:r,maxPerTxUsd:i,expiresInDays:o})}},{name:"list_children",title:"List Child Sessions",description:"List all child sessions (agents) spawned from this wallet.",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:null,handler:async()=>c.listChildSessions()},{name:"create_task",title:"Create Task",description:"Create a new task on the MixrPay marketplace for other agents to complete.",annotations:{readOnlyHint:false,openWorldHint:true},inputSchema:ie,handler:async s=>{let{title:n,description:a,budget_usd:r,skills_required:i}=ie.parse(s);return c.createTask({title:n,description:a,budgetUsd:r,skillsRequired:i})}},{name:"list_tasks",title:"List Tasks",description:"Browse available tasks on the MixrPay marketplace.",annotations:{readOnlyHint:true,openWorldHint:true},inputSchema:oe,handler:async s=>{let{status:n,limit:a}=oe.parse(s);return c.listTasks({status:n,limit:a})}}];return {definitions:e,execute:async(s,n)=>{let a=e.find(r=>r.name===s);if(!a)throw new Error(`Unknown tool: ${s}`);try{let r=await a.handler(n);return JSON.stringify(r,null,2)}catch(r){let i=r instanceof Error?r.message:String(r);throw new Error(i)}}}}function le(c){if(c instanceof z$1.ZodObject){let e=c._def.shape(),t={},s=[];for(let[n,a]of Object.entries(e)){let r=a;t[n]=K(r),!(r instanceof z$1.ZodOptional)&&!(r instanceof z$1.ZodDefault)&&s.push(n);}return {type:"object",properties:t,...s.length>0?{required:s}:{}}}return {type:"object",properties:{}}}function K(c){let e=c;e instanceof z$1.ZodOptional&&(e=e._def.innerType),e instanceof z$1.ZodDefault&&(e=e._def.innerType);let t=c._def.description;if(e instanceof z$1.ZodString)return {type:"string",...t&&{description:t}};if(e instanceof z$1.ZodNumber)return {type:"number",...t&&{description:t}};if(e instanceof z$1.ZodBoolean)return {type:"boolean",...t&&{description:t}};if(e instanceof z$1.ZodEnum)return {type:"string",enum:e._def.values,...t&&{description:t}};if(e instanceof z$1.ZodArray)return {type:"array",items:K(e._def.type),...t&&{description:t}};if(e instanceof z$1.ZodRecord)return {type:"object",additionalProperties:K(e._def.valueType),...t&&{description:t}};if(e instanceof z$1.ZodObject){let s=e._def.shape(),n={};for(let[a,r]of Object.entries(s))n[a]=K(r);return {type:"object",properties:n,...t&&{description:t}}}return e instanceof z$1.ZodUnknown?{...t&&{description:t}}:{...t&&{description:t}}}var Ee="0.9.5",ce=".config/mixrpay",Oe="wallet.json";function de(){let c=process.env.MIXRPAY_WORKSPACE_DIR||process.env.OPENCLAW_WORKSPACE_DIR;return c?join(c,ce):join(homedir(),ce)}function W(){return join(de(),Oe)}async function ue(c,e){let t=de(),s=W();existsSync(t)||mkdirSync(t,{recursive:true,mode:448});let n={address:e.toLowerCase(),privateKey:c,createdAt:new Date().toISOString(),sdkVersion:Ee};writeFileSync(s,JSON.stringify(n,null,2),{encoding:"utf-8",mode:384});try{chmodSync(s,384);}catch{}}async function q(){let c=process.env.MIXRPAY_WALLET_KEY;if(c){if(c.startsWith("0x")&&c.length===66)return c;if(c.length===64)return `0x${c}`;console.warn("[MixrPay] MIXRPAY_WALLET_KEY has invalid format, ignoring");}let e=W();if(!existsSync(e))return null;try{let t=readFileSync(e,"utf-8"),s=JSON.parse(t);return !s.privateKey||!s.privateKey.startsWith("0x")?(console.warn("[MixrPay] Wallet file has invalid format"),null):s.privateKey}catch(t){return console.warn("[MixrPay] Failed to read wallet file:",t),null}}async function ge(){let c=process.env.MIXRPAY_WALLET_KEY;return c&&(c.length===64||c.startsWith("0x")&&c.length===66)?true:existsSync(W())}async function pe(c){let e=null,t=c.headers.get("X-Payment-Required");if(t)try{e=JSON.parse(t);}catch{}if(!e){let n=c.headers.get("WWW-Authenticate");if(n?.startsWith("X-402 "))try{let a=n.slice(6);e=JSON.parse(atob(a));}catch{}}if(!e)try{e=await c.json();}catch{}if(!e)throw new P("Could not parse payment requirements from 402 response");if(!e.recipient)throw new P("Missing recipient in payment requirements");if(!e.amount)throw new P("Missing amount in payment requirements");let s=Math.floor(Date.now()/1e3);return {recipient:e.recipient,amount:BigInt(e.amount),currency:e.currency||"USDC",chainId:e.chainId||e.chain_id||8453,facilitatorUrl:e.facilitatorUrl||e.facilitator_url||"https://x402.org/facilitator",nonce:e.nonce||N().slice(2),expiresAt:e.expiresAt||e.expires_at||s+300,description:e.description}}async function me(c,e,t){let s=c.nonce.length===64?`0x${c.nonce}`:N(),a=BigInt(Math.floor(Date.now()/1e3))-60n,r=BigInt(c.expiresAt),{domain:i,message:o}=X({fromAddress:t,toAddress:c.recipient,value:c.amount,validAfter:a,validBefore:r,nonce:s,chainId:c.chainId}),d=await e.signTransferAuthorization(i,o),g={x402Version:1,scheme:"exact",network:c.chainId===8453?"base":"base-sepolia",payload:{signature:d,authorization:{from:t,to:c.recipient,value:c.amount.toString(),validAfter:a.toString(),validBefore:r.toString(),nonce:s}}};return btoa(JSON.stringify(g))}function he(c){return Date.now()/1e3>c.expiresAt}function B(c){return Number(c.amount)/1e6}var H="0.11.0",_=process.env.MIXRPAY_BASE_URL||"https://mixr.network";var qe=3e4,fe={BASE_MAINNET:{chainId:8453,name:"Base",isTestnet:false},BASE_SEPOLIA:{chainId:84532,name:"Base Sepolia",isTestnet:true}},we={debug:0,info:1,warn:2,error:3,none:4},J=class{level;prefix;constructor(e="none",t="[MixrPay]"){this.level=e,this.prefix=t;}setLevel(e){this.level=e;}shouldLog(e){return we[e]>=we[this.level]}debug(...e){this.shouldLog("debug")&&console.log(`${this.prefix} \u{1F50D}`,...e);}info(...e){this.shouldLog("info")&&console.log(`${this.prefix} \u2139\uFE0F`,...e);}warn(...e){this.shouldLog("warn")&&console.warn(`${this.prefix} \u26A0\uFE0F`,...e);}error(...e){this.shouldLog("error")&&console.error(`${this.prefix} \u274C`,...e);}payment(e,t,s){if(this.shouldLog("info")){let n=s?` for "${s}"`:"";console.log(`${this.prefix} \u{1F4B8} Paid $${e.toFixed(4)} to ${t.slice(0,10)}...${n}`);}}},M=class c{sessionKey;walletAddress;maxPaymentUsd;onPayment;baseUrl;timeout;logger;payments=[];totalSpentUsd=0;sessionKeyInfo;sessionKeyInfoFetchedAt;allowlist;allowlistFetchedAt;selfCustodyAddress;selfCustodyKey;agentInstanceId;apiKey;sessionKeyId;constructor(e){this.validateConfig(e),this.sessionKey=O.fromString(e.sessionKey),this.walletAddress=e.walletAddress||this.sessionKey.address,this.maxPaymentUsd=e.maxPaymentUsd,this.onPayment=e.onPayment,this.baseUrl=(e.baseUrl||_).replace(/\/$/,""),this.timeout=e.timeout||qe,e.apiKey&&(this.apiKey=e.apiKey),e.sessionKeyId&&(this.sessionKeyId=e.sessionKeyId),this.logger=new J(e.logLevel||"none"),this.logger.debug("AgentWallet initialized",{walletAddress:this.walletAddress,isTestnet:this.isTestnet(),maxPaymentUsd:this.maxPaymentUsd,hasApiKey:!!this.apiKey,hasSessionKeyId:!!this.sessionKeyId});}validateConfig(e){if(!e.sessionKey)throw new A("Session key is required. Get one from the wallet owner at https://mixrpay.com/manage/invites");let t=e.sessionKey.trim();if(!t.startsWith("sk_live_")&&!t.startsWith("sk_test_")){let a=t.slice(0,8);throw new A(`Invalid session key prefix. Expected 'sk_live_' (mainnet) or 'sk_test_' (testnet), got '${a}'`)}let s=72;if(t.length!==s)throw new A(`Invalid session key length. Expected ${s} characters, got ${t.length}. Make sure you copied the complete key.`);let n=t.slice(8);if(!/^[0-9a-fA-F]+$/.test(n))throw new A("Invalid session key format. The key should contain only hexadecimal characters after the prefix.");if(e.maxPaymentUsd!==void 0){if(e.maxPaymentUsd<=0)throw new l("maxPaymentUsd must be a positive number");e.maxPaymentUsd>1e4&&this.logger?.warn("maxPaymentUsd is very high ($"+e.maxPaymentUsd+"). Consider using a lower limit for safety.");}}async fetchAllowlist(){if(this.allowlist!==void 0&&this.allowlistFetchedAt&&Date.now()-this.allowlistFetchedAt<3e5)return this.allowlist;try{let t=await this.getSessionKeyInfo();return this.allowlist=t.allowedMerchants||[],this.allowlistFetchedAt=Date.now(),this.logger.debug("Fetched allowlist",{patterns:this.allowlist.length,allowAll:this.allowlist.length===0}),this.allowlist}catch(t){return this.logger.warn("Failed to fetch allowlist, allowing all merchants",{error:t}),this.allowlist=[],this.allowlistFetchedAt=Date.now(),this.allowlist}}async validateMerchantAllowed(e,t){let s=await this.fetchAllowlist();if(s.length===0)return;if(!this.matchesAllowlist(e,s,t))throw new E(e,s)}matchesAllowlist(e,t,s){for(let n of t)if(this.matchPattern(e,n,s))return true;return false}matchPattern(e,t,s){return s==="url"?this.matchUrlPattern(e,t):this.matchToolPattern(e,t)}matchUrlPattern(e,t){let s;try{e.includes("://")?s=new URL(e).hostname.toLowerCase():s=e.toLowerCase();}catch{return false}let a=t.toLowerCase().trim();if(a.includes("://"))try{a=new URL(a).hostname;}catch{}if(s===a)return true;if(a.startsWith("*.")){let r=a.substring(2);if(s.endsWith(`.${r}`)&&s!==r)return true}return false}matchToolPattern(e,t){let s=e.toLowerCase().trim(),n=t.toLowerCase().trim();if(s===n)return true;if(n.endsWith("/*")){let a=n.substring(0,n.length-2);if(s.startsWith(`${a}/`))return true}return false}static async register(e){let{privateKey:t,name:s}=e,n=(e.baseUrl||_).replace(/\/$/,""),r=privateKeyToAccount(t).address,i=await fetch(`${n}/api/v1/agent/challenge?wallet=${r}&action=register`);if(!i.ok){let y=await i.json().catch(()=>({}));throw new l(y.error||`Failed to get challenge: ${i.status}`)}let{challenge:o,message:d}=await i.json(),g=await signMessage({message:d,privateKey:t}),u=await fetch(`${n}/api/v1/agent/register`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({challenge:o,external_wallet:r,signature:g,name:s})});if(!u.ok){let y=await u.json().catch(()=>({})),f=y.error||`Registration failed with status ${u.status}`,h=y.request_id,w=(y.code||"").toLowerCase(),b="";u.status===503?b=" The service may be temporarily unavailable. Please try again later.":u.status===500?b=" This is a server error. Please contact support with the request ID.":(w==="missing_challenge"||w==="missing_signature")&&(b=" This may indicate an SDK bug. Please update to the latest version.");let C=h?`${f} (request_id: ${h})${b}`:`${f}${b}`;throw new l(C)}let p=await u.json();return {userId:p.user_id,depositAddress:p.deposit_address}}static async checkServerHealth(e){let t=(e||_).replace(/\/$/,"");try{let s=await fetch(`${t}/api/health/ready?details=true`);if(!s.ok)return {healthy:!1,database:"unknown",agentRegistrationAvailable:!1,walletServiceConfigured:!1,error:`Health check failed with status ${s.status}`};let n=await s.json();return {healthy:n.status==="ready",database:n.database||"unknown",agentRegistrationAvailable:n.services?.agentRegistration?.available??!1,walletServiceConfigured:n.services?.wallet?.configured??!1}}catch(s){return {healthy:false,database:"unreachable",agentRegistrationAvailable:false,walletServiceConfigured:false,error:s instanceof Error?s.message:"Failed to reach server"}}}static async getSessionKey(e){let{privateKey:t,spendingLimitUsd:s,maxPerTxUsd:n,maxDailyUsd:a,durationDays:r}=e,i=(e.baseUrl||_).replace(/\/$/,""),d=privateKeyToAccount(t).address,g=await fetch(`${i}/api/v1/agent/challenge?wallet=${d}&action=session-key`);if(!g.ok){let w=await g.json().catch(()=>({}));throw new l(w.error||`Failed to get challenge: ${g.status}`)}let{challenge:u,message:p}=await g.json(),y=await signMessage({message:p,privateKey:t}),f=await fetch(`${i}/api/v1/agent/session-key`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({challenge:u,external_wallet:d,signature:y,spending_limit_usd:s,max_per_tx_usd:n,max_daily_usd:a,duration_days:r})});if(!f.ok){let w=await f.json().catch(()=>({}));throw new l(w.error||`Session key creation failed: ${f.status}`)}let h=await f.json();return {sessionKey:h.session_key,address:h.address,sessionKeyId:h.session_key_id,expiresAt:new Date(h.expires_at),limits:{maxTotalUsd:h.limits.max_total_usd,maxPerTxUsd:h.limits.max_per_tx_usd,maxDailyUsd:h.limits.max_daily_usd}}}static async getStatus(e){let{privateKey:t}=e,s=(e.baseUrl||_).replace(/\/$/,""),a=privateKeyToAccount(t).address,r=await fetch(`${s}/api/v1/agent/challenge?wallet=${a}&action=status`);if(!r.ok){let p=await r.json().catch(()=>({}));throw new l(p.error||`Failed to get challenge: ${r.status}`)}let{challenge:i,message:o}=await r.json(),d=await signMessage({message:o,privateKey:t}),g=await fetch(`${s}/api/v1/agent/status?challenge=${i}&external_wallet=${a}&signature=${encodeURIComponent(d)}`);if(!g.ok){let p=await g.json().catch(()=>({}));throw new l(p.error||`Failed to get status: ${g.status}`)}let u=await g.json();return {depositAddress:u.deposit_address,balanceUsd:u.balance_usd,activeSessions:u.active_sessions.map(p=>({id:p.id,expiresAt:new Date(p.expires_at),totalSpentUsd:p.total_spent_usd,remainingUsd:p.remaining_usd,maxTotalUsd:p.max_total_usd})),totalSpentUsd:u.total_spent_usd}}static async revokeSessionKey(e){let{privateKey:t,sessionKeyId:s}=e,n=(e.baseUrl||_).replace(/\/$/,""),r=privateKeyToAccount(t).address,i=await fetch(`${n}/api/v1/agent/challenge?wallet=${r}&action=revoke`);if(!i.ok){let p=await i.json().catch(()=>({}));throw new l(p.error||`Failed to get challenge: ${i.status}`)}let{challenge:o,message:d}=await i.json(),g=await signMessage({message:d,privateKey:t}),u=await fetch(`${n}/api/v1/agent/session-key/revoke`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({challenge:o,external_wallet:r,signature:g,session_key_id:s})});if(!u.ok){let p=await u.json().catch(()=>({}));throw new l(p.error||`Revocation failed: ${u.status}`)}return true}static async withdraw(e){let{privateKey:t,amountUsd:s}=e,n=(e.baseUrl||_).replace(/\/$/,""),r=privateKeyToAccount(t).address,i=await fetch(`${n}/api/v1/agent/challenge?wallet=${r}&action=withdraw`);if(!i.ok){let y=await i.json().catch(()=>({}));throw new l(y.error||`Failed to get challenge: ${i.status}`)}let{challenge:o,message:d}=await i.json(),g=await signMessage({message:d,privateKey:t}),u=await fetch(`${n}/api/v1/agent/withdraw`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({challenge:o,external_wallet:r,signature:g,to_address:r,amount_usd:s})});if(!u.ok){let y=await u.json().catch(()=>({}));throw new l(y.error||`Withdrawal failed: ${u.status}`)}let p=await u.json();return {txHash:p.tx_hash,amountUsd:p.amount_usd,remainingBalanceUsd:p.remaining_balance_usd}}static async claimInvite(e){let{inviteCode:t,privateKey:s}=e,n=(e.baseUrl||_).replace(/\/$/,""),r=privateKeyToAccount(s).address,i=await fetch(`${n}/api/v1/agent/challenge?wallet=${r}&action=claim-invite`);if(!i.ok){let y=await i.json().catch(()=>({}));throw new l(y.error||`Failed to get challenge: ${i.status}`)}let{challenge:o,message:d}=await i.json(),g=await signMessage({message:d,privateKey:s}),u=await fetch(`${n}/api/v1/agent/claim-invite`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({invite_code:t,challenge:o,agent_wallet_address:r,signature:g})});if(!u.ok){let f=(await u.json().catch(()=>({}))).error||`Failed to claim invite: ${u.status}`,h="";throw u.status===404?h=" The invite code may be invalid or misspelled.":u.status===400&&(f.includes("already claimed")?h=" This invite has already been used by another agent.":f.includes("expired")?h=" Ask the wallet owner to create a new invite.":f.includes("revoked")&&(h=" The wallet owner has revoked this invite.")),new l(`${f}${h}`)}let p=await u.json();return {sessionKey:p.session_key,address:p.address,sessionKeyId:p.session_key_id,expiresAt:new Date(p.expires_at),limits:{budgetUsd:p.limits.budget_usd,budgetPeriod:p.limits.budget_period,maxPerTxUsd:p.limits.max_per_tx_usd},allowedMerchants:p.allowed_merchants||[],inviterName:p.inviter_name||"Anonymous"}}static async activate(e,t){let s=(t?.baseUrl||_).replace(/\/$/,""),n=new c({sessionKey:e,baseUrl:s}),a=await n.getSessionAuthHeaders(),r=await fetch(`${s}/api/v2/agent/activate`,{method:"POST",headers:{"Content-Type":"application/json",...a}});if(!r.ok){let o=await r.json().catch(()=>({}));throw new l(o.error||`Activation failed: ${r.status}`)}let i=await r.json();return {wallet:n,budget:{maxTotalUsd:i.budget.max_total_usd,maxDailyUsd:i.budget.max_daily_usd,maxPerTxUsd:i.budget.max_per_tx_usd,spentUsd:i.budget.spent_usd,remainingUsd:i.budget.remaining_usd},capabilities:{executeTransactions:i.capabilities.execute_transactions,gasSponsored:i.capabilities.gas_sponsored,batchedTx:i.capabilities.batched_tx},skills:i.skills||[],tools:i.tools||[],gatewayProviders:i.gateway_providers||[]}}static async connect(e){let t=(e?.baseUrl||process.env.MIXRPAY_BASE_URL||_).replace(/\/$/,""),s=e?.logLevel||"none",n=process.env.MIXRPAY_INSTANCE_ID;if(e?.sessionKey){let g=new c({sessionKey:e.sessionKey,sessionKeyId:e.sessionKeyId,baseUrl:t,logLevel:s,maxPaymentUsd:e?.maxPaymentUsd,onPayment:e?.onPayment});return n&&g.setAgentInstanceId(n),g}let a=process.env.MIXRPAY_SESSION_KEY;if(a){let g=process.env.MIXRPAY_SESSION_KEY_ID,u=new c({sessionKey:a,sessionKeyId:g,baseUrl:t,logLevel:s,maxPaymentUsd:e?.maxPaymentUsd,onPayment:e?.onPayment});return n&&u.setAgentInstanceId(n),u}let r=process.env.MIXRPAY_API_KEY||process.env.MIXRPAY_AGENT_TOKEN;if(r&&(r.startsWith("agt_live_")||r.startsWith("agt_test_")))return c.fromApiKey(r,{baseUrl:t,logLevel:s});let i=e?.accessCode||process.env.MIXRPAY_ACCESS_CODE;if(i)return c.fromAccessCode(i,{baseUrl:t,logLevel:s});let o=e?.masterKey||process.env.MIXRPAY_MASTER_KEY,d=e?.agentName||process.env.MIXRPAY_AGENT_NAME;if(o&&d)return c.fromMasterKey(o,d,{baseUrl:t,logLevel:s});try{let{loadCredentials:g}=await import('./credentials-2PX5YXGV.js'),u=g();if(u.success&&u.credentials.sessionKey){let p=new c({sessionKey:u.credentials.sessionKey,sessionKeyId:u.credentials.sessionKeyId,baseUrl:u.credentials.baseUrl||t,logLevel:s,maxPaymentUsd:e?.maxPaymentUsd,onPayment:e?.onPayment,apiKey:u.credentials.apiToken});return n&&p.setAgentInstanceId(n),p}if(u.success&&u.credentials.apiToken)return c.fromApiKey(u.credentials.apiToken,{baseUrl:t,logLevel:s});if(u.success&&u.credentials.masterKey&&u.credentials.defaultAgentName)return c.fromMasterKey(u.credentials.masterKey,u.credentials.defaultAgentName,{baseUrl:t,logLevel:s})}catch{}if(e?.interactive)return c.deviceFlowLogin({baseUrl:t,logLevel:s});throw new l(`No MixrPay credentials found. Options:
3
- 1. Set MIXRPAY_SESSION_KEY environment variable
4
- 2. Set MIXRPAY_API_KEY or MIXRPAY_AGENT_TOKEN environment variable (agt_live_xxx)
5
- 3. Set MIXRPAY_ACCESS_CODE environment variable (mixr-xxx)
6
- 4. Pass sessionKey or accessCode to connect()
7
- 5. Run \`npx mixrpay login\` to cache credentials
8
- 6. Use connect({ interactive: true }) for browser login`)}static async fromApiKey(e,t){let s=(t?.baseUrl||_).replace(/\/$/,"");if(!e.startsWith("agt_live_")&&!e.startsWith("agt_test_"))throw new l(`Invalid API key format. Expected 'agt_live_' or 'agt_test_' prefix, got '${e.slice(0,9)}...'`);let n=await fetch(`${s}/api/v2/agent/session-from-token`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`}});if(!n.ok){let o=await n.json().catch(()=>({}));throw new l(o.error||`Failed to exchange API key for session: ${n.status}`)}let a=await n.json(),r=a.session_key;if(!r)throw new l("No session_key in API response");let i=new c({sessionKey:r,baseUrl:s,logLevel:t?.logLevel});return i.setApiKey(e),a.agent_instance_id&&i.setAgentInstanceId(a.agent_instance_id),i}static async fromAccessCode(e,t){let s=(t?.baseUrl||_).replace(/\/$/,"");if(!e.startsWith("mixr-"))throw new l(`Invalid access code format. Expected 'mixr-' prefix, got '${e.slice(0,5)}...'`);let n=await fetch(`${s}/api/v2/agent/connect`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({code:e})});if(!n.ok){let g=await n.json().catch(()=>({})),u=(g.code||"").toLowerCase(),p="";throw n.status===404||u==="invalid_code"?p=" Check the code for typos or get a new one from the MixrPay dashboard.":n.status===400&&(u==="code_claimed"?p=" This code has already been used. Get a new code from the dashboard.":u==="code_expired"?p=" This code has expired. Get a new code from the dashboard.":u==="code_revoked"&&(p=" This code has been revoked by the owner.")),new l((g.error||`Failed to activate access code: ${n.status}`)+p)}let a=await n.json(),r=a.session_key,i=a.token,o=a.agent_id;if(!r)throw new l("No session_key in access code response");try{let{saveCredentials:g}=await import('./credentials-2PX5YXGV.js');g({sessionKey:r,apiToken:i,baseUrl:s});}catch{}let d=new c({sessionKey:r,baseUrl:s,logLevel:t?.logLevel});return i&&(d.apiKey=i),o&&(d.agentInstanceId=o),d}static async fromMasterKey(e,t,s){let n=(s?.baseUrl||_).replace(/\/$/,"");if(!e.startsWith("mk_live_")&&!e.startsWith("mk_test_"))throw new l("Invalid master key format. Expected 'mk_live_' or 'mk_test_' prefix.");let a=await fetch(`${n}/api/v2/master-keys/session`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify({agent_name:t})});if(!a.ok){let g=await a.json().catch(()=>({}));throw a.status===404?new l(`Agent '${t}' not found. Use the MixrPay dashboard to create it.`):new l(g.error||`Failed to get session from master key: ${a.status}`)}let r=await a.json(),i=r.session_key,o=r.session_key_id;if(!i)throw new l("No session_key in master key response");let d=new c({sessionKey:i,sessionKeyId:o,baseUrl:n,logLevel:s?.logLevel});return r.agent?.id&&(d.agentInstanceId=r.agent.id),d}static async deviceFlowLogin(e){let t=(e?.baseUrl||_).replace(/\/$/,""),s=await fetch(`${t}/api/v2/auth/device/authorize`,{method:"POST",headers:{"Content-Type":"application/json"}});if(!s.ok){let y=await s.json().catch(()=>({}));throw new l(y.error||`Device flow initiation failed: ${s.status}`)}let n=await s.json(),{device_code:a,user_code:r,verification_uri:i,verification_uri_complete:o,expires_in:d,interval:g}=n;console.log(`
2
+ import {McpServer}from'@modelcontextprotocol/sdk/server/mcp.js';import {StdioServerTransport}from'@modelcontextprotocol/sdk/server/stdio.js';import {fileURLToPath}from'url';import {join,dirname}from'path';import {privateKeyToAccount,signMessage,generatePrivateKey,signTypedData}from'viem/accounts';import {z as z$1}from'zod';import {createWalletClient,http,parseUnits,encodeFunctionData}from'viem';import {base}from'viem/chains';import {existsSync,readFileSync,mkdirSync,writeFileSync,chmodSync}from'fs';import {homedir}from'os';var l=class extends Error{code;retryAfterMs;constructor(e,t="MIXRPAY_ERROR",s){super(e),this.name="MixrPayError",this.code=t,this.retryAfterMs=s,Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor);}isRetryable(){return false}},k=class extends l{required;available;topUpUrl;constructor(e,t){let s=e-t;super(`Insufficient balance: need $${e.toFixed(2)}, have $${t.toFixed(2)} (short $${s.toFixed(2)}). Top up your wallet to continue.`,"INSUFFICIENT_BALANCE"),this.name="InsufficientBalanceError",this.required=e,this.available=t,this.topUpUrl="https://mixr.network/manage/wallet";}},$=class extends l{expiredAt;constructor(e){super(`Session key expired at ${e}. Request a new session key from the wallet owner at https://mixrpay.com/manage/invites`,"SESSION_KEY_EXPIRED"),this.name="SessionKeyExpiredError",this.expiredAt=e;}},T=class extends l{limitType;limit;attempted;constructor(e,t,s){let a={per_tx:"Per-transaction",daily:"Daily",total:"Total",client_max:"Client-side"}[e]||e,r=e==="daily"?"Wait until tomorrow or request a higher limit.":e==="client_max"?"Increase maxPaymentUsd in your AgentWallet configuration.":"Request a new session key with a higher limit.";super(`${a} spending limit exceeded: limit is $${t.toFixed(2)}, attempted $${s.toFixed(2)}. ${r}`,"SPENDING_LIMIT_EXCEEDED"),this.name="SpendingLimitExceededError",this.limitType=e,this.limit=t,this.attempted=s;}isRetryable(){return this.limitType==="daily"}},A=class extends l{reason;txHash;constructor(e,t){let s=`Payment failed: ${e}`;t&&(s+=` (tx: ${t} - check on basescan.org)`),super(s,"PAYMENT_FAILED"),this.name="PaymentFailedError",this.reason=e,this.txHash=t;}isRetryable(){return true}},x=class extends l{reason;constructor(e="Invalid session key format"){super(`${e}. Session keys should be in format: sk_live_<64 hex chars> or sk_test_<64 hex chars>. Get one from https://mixrpay.com/manage/invites`,"INVALID_SESSION_KEY"),this.name="InvalidSessionKeyError",this.reason=e;}},P=class extends l{reason;constructor(e){super(`x402 protocol error: ${e}. This may indicate a server configuration issue. If the problem persists, contact the API provider.`,"X402_PROTOCOL_ERROR"),this.name="X402ProtocolError",this.reason=e;}isRetryable(){return true}},D=class extends l{sessionId;expiredAt;constructor(e,t){super(`Session ${e} has expired${t?` at ${t}`:""}. A new session will be created automatically on your next request.`,"SESSION_EXPIRED"),this.name="SessionExpiredError",this.sessionId=e,this.expiredAt=t;}},U=class extends l{sessionId;limit;requested;remaining;constructor(e,t,s,n){super(`Session spending limit exceeded: limit is $${e.toFixed(2)}, requested $${t.toFixed(2)}, remaining $${s.toFixed(2)}. Create a new session with a higher limit to continue.`,"SESSION_LIMIT_EXCEEDED"),this.name="SessionLimitExceededError",this.sessionId=n,this.limit=e,this.requested=t,this.remaining=s;}},I=class extends l{sessionId;constructor(e){super(`Session ${e} not found. It may have been deleted or never existed. Create a new session with getOrCreateSession().`,"SESSION_NOT_FOUND"),this.name="SessionNotFoundError",this.sessionId=e;}},R=class extends l{sessionId;reason;constructor(e,t){super(`Session ${e} has been revoked${t?`: ${t}`:""}. Create a new session with getOrCreateSession().`,"SESSION_REVOKED"),this.name="SessionRevokedError",this.sessionId=e,this.reason=t;}},E=class extends l{attempted;allowedPatterns;constructor(e,t){let s=t.slice(0,3).join(", "),n=t.length>3?"...":"";super(`Payment to "${e}" not allowed. Session allowlist: ${s}${n}. Update the session allowlist or create a new session.`,"MERCHANT_NOT_ALLOWED"),this.name="MerchantNotAllowedError",this.attempted=e,this.allowedPatterns=t;}};var ke={8453:"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",84532:"0x036CbD53842c5426634e7929541eC2318f3dCF7e"},Te={name:"USD Coin",version:"2"},Pe={TransferWithAuthorization:[{name:"from",type:"address"},{name:"to",type:"address"},{name:"value",type:"uint256"},{name:"validAfter",type:"uint256"},{name:"validBefore",type:"uint256"},{name:"nonce",type:"bytes32"}]},O=class c{privateKey;account;address;isTest;constructor(e,t){this.privateKey=e,this.account=privateKeyToAccount(e),this.address=this.account.address,this.isTest=t;}toString(){return `${this.isTest?"sk_test_":"sk_live_"}${this.privateKey.slice(2)}`}get privateKeyHex(){return this.privateKey.slice(2)}get rawPrivateKey(){return this.privateKey}static fromString(e){let t=/^sk_(live|test)_([a-fA-F0-9]{64})$/,s=e.match(t);if(!s)throw new x("Session key must be in format sk_live_{64_hex} or sk_test_{64_hex}");let n=s[1],a=s[2];try{let r=`0x${a}`;return new c(r,n==="test")}catch(r){throw new x(`Failed to decode session key: ${r}`)}}async signTransferAuthorization(e,t){return signTypedData({privateKey:this.privateKey,domain:e,types:Pe,primaryType:"TransferWithAuthorization",message:t})}async signMessage(e){return signMessage({privateKey:this.privateKey,message:e})}getDefaultChainId(){return this.isTest?84532:8453}};function X(c){let e=ke[c.chainId];if(!e)throw new Error(`USDC not supported on chain ${c.chainId}`);let t={...Te,chainId:c.chainId,verifyingContract:e},s={from:c.fromAddress,to:c.toAddress,value:c.value,validAfter:c.validAfter,validBefore:c.validBefore,nonce:c.nonce};return {domain:t,message:s}}function N(){let c=new Uint8Array(32);return crypto.getRandomValues(c),`0x${Array.from(c).map(e=>e.toString(16).padStart(2,"0")).join("")}`}function Ue(c,e){return `MixrPay:${c}:${e.toLowerCase()}`}async function Y(c){let e=Date.now(),t=Ue(e,c.address),s=await c.signMessage(t);return {address:c.address,timestamp:e,signature:s}}var z=z$1.object({query:z$1.string().describe('Search query (e.g. "web scraping", "email", "database")')}),V=z$1.object({tool_name:z$1.string().describe('Tool name in "merchant/tool" format'),arguments:z$1.record(z$1.unknown()).optional().describe("Arguments to pass to the tool")}),Z=z$1.object({url:z$1.string().url().describe("The merchant API URL to call"),merchant_public_key:z$1.string().describe("The merchant's MixrPay public key (pk_live_... or pk_test_...)"),method:z$1.enum(["GET","POST","PUT","PATCH","DELETE"]).default("POST").describe("HTTP method"),body:z$1.unknown().optional().describe("Request body (will be JSON-serialized)"),price_usd:z$1.number().optional().describe("Expected price in USD for client-side validation")}),Q=z$1.object({skill_id:z$1.string().describe("The skill ID to execute"),input:z$1.record(z$1.unknown()).optional().describe("Input parameters for the skill")}),ee=z$1.object({skill_id:z$1.string().describe("The skill ID to check")}),te=z$1.object({glama_id:z$1.string().describe('Glama server ID (e.g. "notion-mcp")'),glama_namespace:z$1.string().describe('Glama namespace (e.g. "notion")'),glama_slug:z$1.string().describe('Glama slug (e.g. "notion-mcp")'),tool_name:z$1.string().describe("Human-readable name for the tool"),tool_description:z$1.string().optional().describe("Optional description"),env_vars:z$1.record(z$1.string()).optional().describe("Environment variables for the MCP server (e.g. API keys)"),ttl_hours:z$1.number().min(1).max(168).optional().describe("Time-to-live in hours (default: 24, max: 168)")}),se=z$1.object({status:z$1.enum(["provisioning","active","stopped","expired"]).optional().describe("Filter by status")}),ne=z$1.object({instance_id:z$1.string().describe("The instance ID to stop")}),ae=z$1.object({to:z$1.string().describe("Recipient address (0x...)"),amount_usdc:z$1.number().positive().describe("Amount in USDC (e.g. 10.5)")}),re=z$1.object({name:z$1.string().describe("Name for the child agent"),budget_usd:z$1.number().positive().describe("Budget to delegate in USD"),budget_period:z$1.enum(["daily","monthly","total"]).default("total").describe("Budget period"),max_per_tx_usd:z$1.number().positive().optional().describe("Max per-transaction limit in USD"),expires_in_days:z$1.number().min(1).max(365).optional().describe("Expiry in days (default: 30)")}),ie=z$1.object({title:z$1.string().describe("Task title"),description:z$1.string().describe("Detailed task description"),budget_usd:z$1.number().positive().describe("Budget for the task in USD"),skills_required:z$1.array(z$1.string()).optional().describe("Required skill IDs")}),oe=z$1.object({status:z$1.string().optional().describe('Filter by status (e.g. "open", "in_progress")'),limit:z$1.number().min(1).max(100).optional().describe("Number of results (default: 20)")});function j(c){let e=[{name:"check_balance",title:"Check Balance",description:"Get the USDC balance of the wallet on Base.",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:null,handler:async()=>({balanceUsd:await c.getBalance(),network:c.isTestnet()?"base-sepolia":"base"})},{name:"get_spending_stats",title:"Get Spending Stats",description:"Get session key spending limits and current usage (total spent, remaining daily/total limits, expiry).",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:null,handler:async()=>c.getSpendingStats()},{name:"get_session_info",title:"Get Session Info",description:"Get detailed session key information including limits, usage, expiry, and allowed merchants.",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:null,handler:async()=>c.getSessionKeyInfo(true)},{name:"run_diagnostics",title:"Run Diagnostics",description:"Run a full health check on the wallet: API connectivity, session key validity, balance, and latency.",annotations:{readOnlyHint:true,openWorldHint:true},inputSchema:null,handler:async()=>c.runDiagnostics()},{name:"list_tools",title:"List Marketplace Tools",description:"Browse all available paid API tools on the MixrPay marketplace. Each tool includes pricing and description.",annotations:{readOnlyHint:true,openWorldHint:true},inputSchema:null,handler:async()=>c.listTools()},{name:"search_tools",title:"Search Tools",description:"Search the Glama MCP server directory for tools by keyword.",annotations:{readOnlyHint:true,openWorldHint:true},inputSchema:z,handler:async s=>{let{query:n}=z.parse(s);return c.searchGlamaDirectory(n)}},{name:"call_tool",title:"Call Marketplace Tool",description:'Call a paid API tool on the MixrPay marketplace. Payment is automatic from the wallet. Tool names are in "merchant/tool" format (e.g. "firecrawl/scrape").',annotations:{readOnlyHint:false,openWorldHint:true},inputSchema:V,handler:async s=>{let{tool_name:n,arguments:a}=V.parse(s);return c.callTool(n,a||{})}},{name:"call_merchant_api",title:"Call Merchant API",description:"Call any merchant API endpoint with x402 payment. The wallet handles authentication and payment automatically.",annotations:{readOnlyHint:false,openWorldHint:true},inputSchema:Z,handler:async s=>{let{url:n,merchant_public_key:a,method:r,body:i,price_usd:o}=Z.parse(s),d=await c.callMerchantApi({url:n,merchantPublicKey:a,method:r,body:i,priceUsd:o}),g=await d.json().catch(()=>d.text());return {status:d.status,data:g}}},{name:"list_skills",title:"List Skills",description:"List all available skills (pre-built integrations) that the wallet can use.",annotations:{readOnlyHint:true,openWorldHint:true},inputSchema:null,handler:async()=>c.listSkills()},{name:"use_skill",title:"Use Skill",description:"Execute a skill by ID. Skills are pre-built integrations (e.g. web scraping, email sending).",annotations:{readOnlyHint:false,openWorldHint:true},inputSchema:Q,handler:async s=>{let{skill_id:n,input:a}=Q.parse(s);return c.useSkill(n,{input:a})}},{name:"get_skill_status",title:"Get Skill Status",description:"Check the status and configuration of a specific skill.",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:ee,handler:async s=>{let{skill_id:n}=ee.parse(s);return c.getSkillStatus(n)}},{name:"deploy_jit_mcp",title:"Deploy JIT MCP Server",description:"Deploy a just-in-time MCP server from the Glama directory. Creates a temporary hosted MCP server instance.",annotations:{readOnlyHint:false,openWorldHint:true},inputSchema:te,handler:async s=>{let{glama_id:n,glama_namespace:a,glama_slug:r,tool_name:i,tool_description:o,env_vars:d,ttl_hours:g}=te.parse(s);return c.deployJitMcp({glamaId:n,glamaNamespace:a,glamaSlug:r,toolName:i,toolDescription:o,envVars:d,ttlHours:g})}},{name:"list_jit_instances",title:"List JIT Instances",description:"List all deployed JIT MCP server instances.",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:se,handler:async s=>{let{status:n}=se.parse(s);return c.listJitInstances(n?{status:n}:void 0)}},{name:"stop_jit_instance",title:"Stop JIT Instance",description:"Stop a running JIT MCP server instance.",annotations:{readOnlyHint:false,destructiveHint:true,openWorldHint:false},inputSchema:ne,handler:async s=>{let{instance_id:n}=ne.parse(s);return await c.stopJitInstance(n),{success:true,instance_id:n}}},{name:"transfer_usdc",title:"Transfer USDC",description:"Transfer USDC from the self-custody wallet to another address on Base. Only available when the wallet has a self-custody wallet (AGENT_WALLET_KEY set).",annotations:{readOnlyHint:false,destructiveHint:true,openWorldHint:true},inputSchema:ae,handler:async s=>{let{to:n,amount_usdc:a}=ae.parse(s);if(!await c.hasSelfCustodyWallet())throw new Error("No self-custody wallet configured. Set AGENT_WALLET_KEY to enable transfers.");return {success:true,txHash:await c.transferUSDC({to:n,amountUsdc:a}),to:n,amountUsdc:a}}},{name:"get_budget",title:"Get Available Budget",description:"Get the available delegation budget including remaining amount, whether spawning children is possible, and budget limits.",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:null,handler:async()=>c.getAvailableBudget()},{name:"spawn_child",title:"Spawn Child Session",description:"Create a child invite with a delegated budget from this wallet. Returns an invite code that another agent can claim.",annotations:{readOnlyHint:false,openWorldHint:false},inputSchema:re,handler:async s=>{let{name:n,budget_usd:a,budget_period:r,max_per_tx_usd:i,expires_in_days:o}=re.parse(s);return c.spawnChildInvite({name:n,budgetUsd:a,budgetPeriod:r,maxPerTxUsd:i,expiresInDays:o})}},{name:"list_children",title:"List Child Sessions",description:"List all child sessions (agents) spawned from this wallet.",annotations:{readOnlyHint:true,openWorldHint:false},inputSchema:null,handler:async()=>c.listChildSessions()},{name:"create_task",title:"Create Task",description:"Create a new task on the MixrPay marketplace for other agents to complete.",annotations:{readOnlyHint:false,openWorldHint:true},inputSchema:ie,handler:async s=>{let{title:n,description:a,budget_usd:r,skills_required:i}=ie.parse(s);return c.createTask({title:n,description:a,budgetUsd:r,skillsRequired:i})}},{name:"list_tasks",title:"List Tasks",description:"Browse available tasks on the MixrPay marketplace.",annotations:{readOnlyHint:true,openWorldHint:true},inputSchema:oe,handler:async s=>{let{status:n,limit:a}=oe.parse(s);return c.listTasks({status:n,limit:a})}}];return {definitions:e,execute:async(s,n)=>{let a=e.find(r=>r.name===s);if(!a)throw new Error(`Unknown tool: ${s}`);try{let r=await a.handler(n);return JSON.stringify(r,null,2)}catch(r){let i=r instanceof Error?r.message:String(r);throw new Error(i)}}}}function le(c){if(c instanceof z$1.ZodObject){let e=c._def.shape(),t={},s=[];for(let[n,a]of Object.entries(e)){let r=a;t[n]=K(r),!(r instanceof z$1.ZodOptional)&&!(r instanceof z$1.ZodDefault)&&s.push(n);}return {type:"object",properties:t,...s.length>0?{required:s}:{}}}return {type:"object",properties:{}}}function K(c){let e=c;e instanceof z$1.ZodOptional&&(e=e._def.innerType),e instanceof z$1.ZodDefault&&(e=e._def.innerType);let t=c._def.description;if(e instanceof z$1.ZodString)return {type:"string",...t&&{description:t}};if(e instanceof z$1.ZodNumber)return {type:"number",...t&&{description:t}};if(e instanceof z$1.ZodBoolean)return {type:"boolean",...t&&{description:t}};if(e instanceof z$1.ZodEnum)return {type:"string",enum:e._def.values,...t&&{description:t}};if(e instanceof z$1.ZodArray)return {type:"array",items:K(e._def.type),...t&&{description:t}};if(e instanceof z$1.ZodRecord)return {type:"object",additionalProperties:K(e._def.valueType),...t&&{description:t}};if(e instanceof z$1.ZodObject){let s=e._def.shape(),n={};for(let[a,r]of Object.entries(s))n[a]=K(r);return {type:"object",properties:n,...t&&{description:t}}}return e instanceof z$1.ZodUnknown?{...t&&{description:t}}:{...t&&{description:t}}}var Ee="0.9.5",ce=".config/mixrpay",Oe="wallet.json";function de(){let c=process.env.MIXRPAY_WORKSPACE_DIR||process.env.OPENCLAW_WORKSPACE_DIR;return c?join(c,ce):join(homedir(),ce)}function W(){return join(de(),Oe)}async function ue(c,e){let t=de(),s=W();existsSync(t)||mkdirSync(t,{recursive:true,mode:448});let n={address:e.toLowerCase(),privateKey:c,createdAt:new Date().toISOString(),sdkVersion:Ee};writeFileSync(s,JSON.stringify(n,null,2),{encoding:"utf-8",mode:384});try{chmodSync(s,384);}catch{}}async function q(){let c=process.env.MIXRPAY_WALLET_KEY;if(c){if(c.startsWith("0x")&&c.length===66)return c;if(c.length===64)return `0x${c}`;console.warn("[MixrPay] MIXRPAY_WALLET_KEY has invalid format, ignoring");}let e=W();if(!existsSync(e))return null;try{let t=readFileSync(e,"utf-8"),s=JSON.parse(t);return !s.privateKey||!s.privateKey.startsWith("0x")?(console.warn("[MixrPay] Wallet file has invalid format"),null):s.privateKey}catch(t){return console.warn("[MixrPay] Failed to read wallet file:",t),null}}async function ge(){let c=process.env.MIXRPAY_WALLET_KEY;return c&&(c.length===64||c.startsWith("0x")&&c.length===66)?true:existsSync(W())}async function pe(c){let e=null,t=c.headers.get("X-Payment-Required");if(t)try{e=JSON.parse(t);}catch{}if(!e){let n=c.headers.get("WWW-Authenticate");if(n?.startsWith("X-402 "))try{let a=n.slice(6);e=JSON.parse(atob(a));}catch{}}if(!e)try{e=await c.json();}catch{}if(!e)throw new P("Could not parse payment requirements from 402 response");if(!e.recipient)throw new P("Missing recipient in payment requirements");if(!e.amount)throw new P("Missing amount in payment requirements");let s=Math.floor(Date.now()/1e3);return {recipient:e.recipient,amount:BigInt(e.amount),currency:e.currency||"USDC",chainId:e.chainId||e.chain_id||8453,facilitatorUrl:e.facilitatorUrl||e.facilitator_url||"https://x402.org/facilitator",nonce:e.nonce||N().slice(2),expiresAt:e.expiresAt||e.expires_at||s+300,description:e.description}}async function me(c,e,t){let s=c.nonce.length===64?`0x${c.nonce}`:N(),a=BigInt(Math.floor(Date.now()/1e3))-60n,r=BigInt(c.expiresAt),{domain:i,message:o}=X({fromAddress:t,toAddress:c.recipient,value:c.amount,validAfter:a,validBefore:r,nonce:s,chainId:c.chainId}),d=await e.signTransferAuthorization(i,o),g={x402Version:1,scheme:"exact",network:c.chainId===8453?"base":"base-sepolia",payload:{signature:d,authorization:{from:t,to:c.recipient,value:c.amount.toString(),validAfter:a.toString(),validBefore:r.toString(),nonce:s}}};return btoa(JSON.stringify(g))}function he(c){return Date.now()/1e3>c.expiresAt}function B(c){return Number(c.amount)/1e6}var H="0.11.0",_=process.env.MIXRPAY_BASE_URL||"https://mixr.network";var qe=3e4,fe={BASE_MAINNET:{chainId:8453,name:"Base",isTestnet:false},BASE_SEPOLIA:{chainId:84532,name:"Base Sepolia",isTestnet:true}},we={debug:0,info:1,warn:2,error:3,none:4},J=class{level;prefix;constructor(e="none",t="[MixrPay]"){this.level=e,this.prefix=t;}setLevel(e){this.level=e;}shouldLog(e){return we[e]>=we[this.level]}debug(...e){this.shouldLog("debug")&&console.log(`${this.prefix} \u{1F50D}`,...e);}info(...e){this.shouldLog("info")&&console.log(`${this.prefix} \u2139\uFE0F`,...e);}warn(...e){this.shouldLog("warn")&&console.warn(`${this.prefix} \u26A0\uFE0F`,...e);}error(...e){this.shouldLog("error")&&console.error(`${this.prefix} \u274C`,...e);}payment(e,t,s){if(this.shouldLog("info")){let n=s?` for "${s}"`:"";console.log(`${this.prefix} \u{1F4B8} Paid $${e.toFixed(4)} to ${t.slice(0,10)}...${n}`);}}},M=class c{sessionKey;walletAddress;maxPaymentUsd;onPayment;baseUrl;timeout;logger;payments=[];totalSpentUsd=0;sessionKeyInfo;sessionKeyInfoFetchedAt;allowlist;allowlistFetchedAt;selfCustodyAddress;selfCustodyKey;agentInstanceId;apiKey;sessionKeyId;constructor(e){this.validateConfig(e),this.sessionKey=O.fromString(e.sessionKey),this.walletAddress=e.walletAddress||this.sessionKey.address,this.maxPaymentUsd=e.maxPaymentUsd,this.onPayment=e.onPayment,this.baseUrl=(e.baseUrl||_).replace(/\/$/,""),this.timeout=e.timeout||qe,e.apiKey&&(this.apiKey=e.apiKey),e.sessionKeyId&&(this.sessionKeyId=e.sessionKeyId),this.logger=new J(e.logLevel||"none"),this.logger.debug("AgentWallet initialized",{walletAddress:this.walletAddress,isTestnet:this.isTestnet(),maxPaymentUsd:this.maxPaymentUsd,hasApiKey:!!this.apiKey,hasSessionKeyId:!!this.sessionKeyId});}validateConfig(e){if(!e.sessionKey)throw new x("Session key is required. Get one from the wallet owner at https://mixrpay.com/manage/invites");let t=e.sessionKey.trim();if(!t.startsWith("sk_live_")&&!t.startsWith("sk_test_")){let a=t.slice(0,8);throw new x(`Invalid session key prefix. Expected 'sk_live_' (mainnet) or 'sk_test_' (testnet), got '${a}'`)}let s=72;if(t.length!==s)throw new x(`Invalid session key length. Expected ${s} characters, got ${t.length}. Make sure you copied the complete key.`);let n=t.slice(8);if(!/^[0-9a-fA-F]+$/.test(n))throw new x("Invalid session key format. The key should contain only hexadecimal characters after the prefix.");if(e.maxPaymentUsd!==void 0){if(e.maxPaymentUsd<=0)throw new l("maxPaymentUsd must be a positive number");e.maxPaymentUsd>1e4&&this.logger?.warn("maxPaymentUsd is very high ($"+e.maxPaymentUsd+"). Consider using a lower limit for safety.");}}async fetchAllowlist(){if(this.allowlist!==void 0&&this.allowlistFetchedAt&&Date.now()-this.allowlistFetchedAt<3e5)return this.allowlist;try{let t=await this.getSessionKeyInfo();return this.allowlist=t.allowedMerchants||[],this.allowlistFetchedAt=Date.now(),this.logger.debug("Fetched allowlist",{patterns:this.allowlist.length,allowAll:this.allowlist.length===0}),this.allowlist}catch(t){return this.logger.warn("Failed to fetch allowlist, allowing all merchants",{error:t}),this.allowlist=[],this.allowlistFetchedAt=Date.now(),this.allowlist}}async validateMerchantAllowed(e,t){let s=await this.fetchAllowlist();if(s.length===0)return;if(!this.matchesAllowlist(e,s,t))throw new E(e,s)}matchesAllowlist(e,t,s){for(let n of t)if(this.matchPattern(e,n,s))return true;return false}matchPattern(e,t,s){return s==="url"?this.matchUrlPattern(e,t):this.matchToolPattern(e,t)}matchUrlPattern(e,t){let s;try{e.includes("://")?s=new URL(e).hostname.toLowerCase():s=e.toLowerCase();}catch{return false}let a=t.toLowerCase().trim();if(a.includes("://"))try{a=new URL(a).hostname;}catch{}if(s===a)return true;if(a.startsWith("*.")){let r=a.substring(2);if(s.endsWith(`.${r}`)&&s!==r)return true}return false}matchToolPattern(e,t){let s=e.toLowerCase().trim(),n=t.toLowerCase().trim();if(s===n)return true;if(n.endsWith("/*")){let a=n.substring(0,n.length-2);if(s.startsWith(`${a}/`))return true}return false}static async register(e){let{privateKey:t,name:s}=e,n=(e.baseUrl||_).replace(/\/$/,""),r=privateKeyToAccount(t).address,i=await fetch(`${n}/api/v1/agent/challenge?wallet=${r}&action=register`);if(!i.ok){let y=await i.json().catch(()=>({}));throw new l(y.error||`Failed to get challenge: ${i.status}`)}let{challenge:o,message:d}=await i.json(),g=await signMessage({message:d,privateKey:t}),u=await fetch(`${n}/api/v1/agent/register`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({challenge:o,external_wallet:r,signature:g,name:s})});if(!u.ok){let y=await u.json().catch(()=>({})),f=y.error||`Registration failed with status ${u.status}`,h=y.request_id,w=(y.code||"").toLowerCase(),b="";u.status===503?b=" The service may be temporarily unavailable. Please try again later.":u.status===500?b=" This is a server error. Please contact support with the request ID.":(w==="missing_challenge"||w==="missing_signature")&&(b=" This may indicate an SDK bug. Please update to the latest version.");let C=h?`${f} (request_id: ${h})${b}`:`${f}${b}`;throw new l(C)}let p=await u.json();return {userId:p.user_id,depositAddress:p.deposit_address}}static async checkServerHealth(e){let t=(e||_).replace(/\/$/,"");try{let s=await fetch(`${t}/api/health/ready?details=true`);if(!s.ok)return {healthy:!1,database:"unknown",agentRegistrationAvailable:!1,walletServiceConfigured:!1,error:`Health check failed with status ${s.status}`};let n=await s.json();return {healthy:n.status==="ready",database:n.database||"unknown",agentRegistrationAvailable:n.services?.agentRegistration?.available??!1,walletServiceConfigured:n.services?.wallet?.configured??!1}}catch(s){return {healthy:false,database:"unreachable",agentRegistrationAvailable:false,walletServiceConfigured:false,error:s instanceof Error?s.message:"Failed to reach server"}}}static async getSessionKey(e){let{privateKey:t,spendingLimitUsd:s,maxPerTxUsd:n,maxDailyUsd:a,durationDays:r}=e,i=(e.baseUrl||_).replace(/\/$/,""),d=privateKeyToAccount(t).address,g=await fetch(`${i}/api/v1/agent/challenge?wallet=${d}&action=session-key`);if(!g.ok){let w=await g.json().catch(()=>({}));throw new l(w.error||`Failed to get challenge: ${g.status}`)}let{challenge:u,message:p}=await g.json(),y=await signMessage({message:p,privateKey:t}),f=await fetch(`${i}/api/v1/agent/session-key`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({challenge:u,external_wallet:d,signature:y,spending_limit_usd:s,max_per_tx_usd:n,max_daily_usd:a,duration_days:r})});if(!f.ok){let w=await f.json().catch(()=>({}));throw new l(w.error||`Session key creation failed: ${f.status}`)}let h=await f.json();return {sessionKey:h.session_key,address:h.address,sessionKeyId:h.session_key_id,expiresAt:new Date(h.expires_at),limits:{maxTotalUsd:h.limits.max_total_usd,maxPerTxUsd:h.limits.max_per_tx_usd,maxDailyUsd:h.limits.max_daily_usd}}}static async getStatus(e){let{privateKey:t}=e,s=(e.baseUrl||_).replace(/\/$/,""),a=privateKeyToAccount(t).address,r=await fetch(`${s}/api/v1/agent/challenge?wallet=${a}&action=status`);if(!r.ok){let p=await r.json().catch(()=>({}));throw new l(p.error||`Failed to get challenge: ${r.status}`)}let{challenge:i,message:o}=await r.json(),d=await signMessage({message:o,privateKey:t}),g=await fetch(`${s}/api/v1/agent/status?challenge=${i}&external_wallet=${a}&signature=${encodeURIComponent(d)}`);if(!g.ok){let p=await g.json().catch(()=>({}));throw new l(p.error||`Failed to get status: ${g.status}`)}let u=await g.json();return {depositAddress:u.deposit_address,balanceUsd:u.balance_usd,activeSessions:u.active_sessions.map(p=>({id:p.id,expiresAt:new Date(p.expires_at),totalSpentUsd:p.total_spent_usd,remainingUsd:p.remaining_usd,maxTotalUsd:p.max_total_usd})),totalSpentUsd:u.total_spent_usd}}static async revokeSessionKey(e){let{privateKey:t,sessionKeyId:s}=e,n=(e.baseUrl||_).replace(/\/$/,""),r=privateKeyToAccount(t).address,i=await fetch(`${n}/api/v1/agent/challenge?wallet=${r}&action=revoke`);if(!i.ok){let p=await i.json().catch(()=>({}));throw new l(p.error||`Failed to get challenge: ${i.status}`)}let{challenge:o,message:d}=await i.json(),g=await signMessage({message:d,privateKey:t}),u=await fetch(`${n}/api/v1/agent/session-key/revoke`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({challenge:o,external_wallet:r,signature:g,session_key_id:s})});if(!u.ok){let p=await u.json().catch(()=>({}));throw new l(p.error||`Revocation failed: ${u.status}`)}return true}static async withdraw(e){let{privateKey:t,amountUsd:s}=e,n=(e.baseUrl||_).replace(/\/$/,""),r=privateKeyToAccount(t).address,i=await fetch(`${n}/api/v1/agent/challenge?wallet=${r}&action=withdraw`);if(!i.ok){let y=await i.json().catch(()=>({}));throw new l(y.error||`Failed to get challenge: ${i.status}`)}let{challenge:o,message:d}=await i.json(),g=await signMessage({message:d,privateKey:t}),u=await fetch(`${n}/api/v1/agent/withdraw`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({challenge:o,external_wallet:r,signature:g,to_address:r,amount_usd:s})});if(!u.ok){let y=await u.json().catch(()=>({}));throw new l(y.error||`Withdrawal failed: ${u.status}`)}let p=await u.json();return {txHash:p.tx_hash,amountUsd:p.amount_usd,remainingBalanceUsd:p.remaining_balance_usd}}static async claimInvite(e){let{inviteCode:t,privateKey:s}=e,n=(e.baseUrl||_).replace(/\/$/,""),r=privateKeyToAccount(s).address,i=await fetch(`${n}/api/v1/agent/challenge?wallet=${r}&action=claim-invite`);if(!i.ok){let y=await i.json().catch(()=>({}));throw new l(y.error||`Failed to get challenge: ${i.status}`)}let{challenge:o,message:d}=await i.json(),g=await signMessage({message:d,privateKey:s}),u=await fetch(`${n}/api/v1/agent/claim-invite`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({invite_code:t,challenge:o,agent_wallet_address:r,signature:g})});if(!u.ok){let f=(await u.json().catch(()=>({}))).error||`Failed to claim invite: ${u.status}`,h="";throw u.status===404?h=" The invite code may be invalid or misspelled.":u.status===400&&(f.includes("already claimed")?h=" This invite has already been used by another agent.":f.includes("expired")?h=" Ask the wallet owner to create a new invite.":f.includes("revoked")&&(h=" The wallet owner has revoked this invite.")),new l(`${f}${h}`)}let p=await u.json();return {sessionKey:p.session_key,address:p.address,sessionKeyId:p.session_key_id,expiresAt:new Date(p.expires_at),limits:{budgetUsd:p.limits.budget_usd,budgetPeriod:p.limits.budget_period,maxPerTxUsd:p.limits.max_per_tx_usd},allowedMerchants:p.allowed_merchants||[],inviterName:p.inviter_name||"Anonymous"}}static async activate(e,t){let s=(t?.baseUrl||_).replace(/\/$/,""),n=new c({sessionKey:e,baseUrl:s}),a=await n.getSessionAuthHeaders(),r=await fetch(`${s}/api/v2/agent/activate`,{method:"POST",headers:{"Content-Type":"application/json",...a}});if(!r.ok){let o=await r.json().catch(()=>({}));throw new l(o.error||`Activation failed: ${r.status}`)}let i=await r.json();return {wallet:n,budget:{maxTotalUsd:i.budget.max_total_usd,maxDailyUsd:i.budget.max_daily_usd,maxPerTxUsd:i.budget.max_per_tx_usd,spentUsd:i.budget.spent_usd,remainingUsd:i.budget.remaining_usd},capabilities:{executeTransactions:i.capabilities.execute_transactions,gasSponsored:i.capabilities.gas_sponsored,batchedTx:i.capabilities.batched_tx},skills:i.skills||[],tools:i.tools||[],gatewayProviders:i.gateway_providers||[]}}static async connect(e){let t=(e?.baseUrl||process.env.MIXRPAY_BASE_URL||_).replace(/\/$/,""),s=e?.logLevel||"none",n=process.env.MIXRPAY_INSTANCE_ID;if(e?.sessionKey){let g=new c({sessionKey:e.sessionKey,sessionKeyId:e.sessionKeyId,baseUrl:t,logLevel:s,maxPaymentUsd:e?.maxPaymentUsd,onPayment:e?.onPayment});return n&&g.setAgentInstanceId(n),g}let a=process.env.MIXRPAY_SESSION_KEY;if(a){let g=process.env.MIXRPAY_SESSION_KEY_ID,u=new c({sessionKey:a,sessionKeyId:g,baseUrl:t,logLevel:s,maxPaymentUsd:e?.maxPaymentUsd,onPayment:e?.onPayment});return n&&u.setAgentInstanceId(n),u}let r=process.env.MIXRPAY_API_KEY||process.env.MIXRPAY_AGENT_TOKEN;if(r&&(r.startsWith("agt_live_")||r.startsWith("agt_test_")))return c.fromApiKey(r,{baseUrl:t,logLevel:s});let i=e?.accessCode||process.env.MIXRPAY_ACCESS_CODE;if(i)return c.fromAccessCode(i,{baseUrl:t,logLevel:s});let o=e?.masterKey||process.env.MIXRPAY_MASTER_KEY,d=e?.agentName||process.env.MIXRPAY_AGENT_NAME;if(o&&d)return c.fromMasterKey(o,d,{baseUrl:t,logLevel:s});try{let{loadCredentials:g}=await import('./credentials-2PX5YXGV.js'),u=g();if(u.success&&u.credentials.sessionKey){let p=new c({sessionKey:u.credentials.sessionKey,sessionKeyId:u.credentials.sessionKeyId,baseUrl:u.credentials.baseUrl||t,logLevel:s,maxPaymentUsd:e?.maxPaymentUsd,onPayment:e?.onPayment,apiKey:u.credentials.apiToken});return n&&p.setAgentInstanceId(n),p}if(u.success&&u.credentials.apiToken)return c.fromApiKey(u.credentials.apiToken,{baseUrl:t,logLevel:s});if(u.success&&u.credentials.masterKey&&u.credentials.defaultAgentName)return c.fromMasterKey(u.credentials.masterKey,u.credentials.defaultAgentName,{baseUrl:t,logLevel:s})}catch{}if(e?.interactive)return c.deviceFlowLogin({baseUrl:t,logLevel:s});throw new l("No MixrPay credentials found. Options:\n 1. Set MIXRPAY_SESSION_KEY environment variable\n 2. Set MIXRPAY_API_KEY or MIXRPAY_AGENT_TOKEN environment variable (agt_live_xxx)\n 3. Set MIXRPAY_ACCESS_CODE environment variable (mixr-xxx)\n 4. Pass sessionKey or accessCode to connect()\n 5. Run `npx --package @mixrpay/agent-sdk mixrpay login` (or `npm i -g @mixrpay/agent-sdk` then `mixrpay login`)\n 6. Use connect({ interactive: true }) for browser login")}static async fromApiKey(e,t){let s=(t?.baseUrl||_).replace(/\/$/,"");if(!e.startsWith("agt_live_")&&!e.startsWith("agt_test_"))throw new l(`Invalid API key format. Expected 'agt_live_' or 'agt_test_' prefix, got '${e.slice(0,9)}...'`);let n=await fetch(`${s}/api/v2/agent/session-from-token`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`}});if(!n.ok){let o=await n.json().catch(()=>({}));throw new l(o.error||`Failed to exchange API key for session: ${n.status}`)}let a=await n.json(),r=a.session_key;if(!r)throw new l("No session_key in API response");let i=new c({sessionKey:r,baseUrl:s,logLevel:t?.logLevel});return i.setApiKey(e),a.agent_instance_id&&i.setAgentInstanceId(a.agent_instance_id),i}static async fromAccessCode(e,t){let s=(t?.baseUrl||_).replace(/\/$/,"");if(!e.startsWith("mixr-"))throw new l(`Invalid access code format. Expected 'mixr-' prefix, got '${e.slice(0,5)}...'`);let n=await fetch(`${s}/api/v2/agent/connect`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({code:e})});if(!n.ok){let g=await n.json().catch(()=>({})),u=(g.code||"").toLowerCase(),p="";throw n.status===404||u==="invalid_code"?p=" Check the code for typos or get a new one from the MixrPay dashboard.":n.status===400&&(u==="code_claimed"?p=" This code has already been used. Get a new code from the dashboard.":u==="code_expired"?p=" This code has expired. Get a new code from the dashboard.":u==="code_revoked"&&(p=" This code has been revoked by the owner.")),new l((g.error||`Failed to activate access code: ${n.status}`)+p)}let a=await n.json(),r=a.session_key,i=a.token,o=a.agent_id;if(!r)throw new l("No session_key in access code response");try{let{saveCredentials:g}=await import('./credentials-2PX5YXGV.js');g({sessionKey:r,apiToken:i,baseUrl:s});}catch{}let d=new c({sessionKey:r,baseUrl:s,logLevel:t?.logLevel});return i&&(d.apiKey=i),o&&(d.agentInstanceId=o),d}static async fromMasterKey(e,t,s){let n=(s?.baseUrl||_).replace(/\/$/,"");if(!e.startsWith("mk_live_")&&!e.startsWith("mk_test_"))throw new l("Invalid master key format. Expected 'mk_live_' or 'mk_test_' prefix.");let a=await fetch(`${n}/api/v2/master-keys/session`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify({agent_name:t})});if(!a.ok){let g=await a.json().catch(()=>({}));throw a.status===404?new l(`Agent '${t}' not found. Use the MixrPay dashboard to create it.`):new l(g.error||`Failed to get session from master key: ${a.status}`)}let r=await a.json(),i=r.session_key,o=r.session_key_id;if(!i)throw new l("No session_key in master key response");let d=new c({sessionKey:i,sessionKeyId:o,baseUrl:n,logLevel:s?.logLevel});return r.agent?.id&&(d.agentInstanceId=r.agent.id),d}static async deviceFlowLogin(e){let t=(e?.baseUrl||_).replace(/\/$/,""),s=await fetch(`${t}/api/v2/auth/device/authorize`,{method:"POST",headers:{"Content-Type":"application/json"}});if(!s.ok){let y=await s.json().catch(()=>({}));throw new l(y.error||`Device flow initiation failed: ${s.status}`)}let n=await s.json(),{device_code:a,user_code:r,verification_uri:i,verification_uri_complete:o,expires_in:d,interval:g}=n;console.log(`
9
3
  \u{1F510} MixrPay Login
10
4
  `),console.log(`Visit: ${o||i}`),console.log(`Enter code: ${r}
11
5
  `),console.log(`Waiting for authentication...
12
6
  `);let u=(g||5)*1e3,p=Date.now()+(d||300)*1e3;for(;Date.now()<p;){await new Promise(w=>setTimeout(w,u));let y=await fetch(`${t}/api/v2/auth/device/token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({device_code:a})});if(y.ok){let w=await y.json(),b=w.session_key,C=w.session_key_id;if(b){console.log(`\u2705 Authenticated successfully!
13
- `);try{let{saveCredentials:Se}=await import('./credentials-2PX5YXGV.js');Se({sessionKey:b,sessionKeyId:C,baseUrl:t});}catch{}return new c({sessionKey:b,sessionKeyId:C,baseUrl:t,logLevel:e?.logLevel})}}let h=(await y.json().catch(()=>({}))).error;if(h!=="authorization_pending")if(h==="slow_down"){await new Promise(w=>setTimeout(w,u));continue}else {if(h==="expired_token")throw new l("Device code expired. Please try again.");if(h==="access_denied")throw new l("Authentication was denied by the user.");if(h)throw new l(`Device flow error: ${h}`)}}throw new l("Device flow timed out. Please try again.")}async spawnChildInvite(e){let{budgetUsd:t,name:s,allowedMerchants:n,expiresInDays:a}=e,r=await this.getSessionAuthHeaders(),i=await fetch(`${this.baseUrl}/api/v1/agent/spawn`,{method:"POST",headers:{"Content-Type":"application/json",...r},body:JSON.stringify({budget_usd:t,name:s,allowed_merchants:n,expires_in_days:a})});if(!i.ok){let d=await i.json().catch(()=>({}));throw i.status===409?new l("Concurrent modification - please retry"):i.status===429?new l("Rate limited - too many spawn attempts"):new l(d.error||`Failed to spawn child: ${i.status}`)}let o=await i.json();return {inviteCode:o.invite_code,inviteId:o.invite_id,budgetUsd:o.budget_usd,expiresAt:new Date(o.expires_at),depth:o.depth,maxSpawnBudget:o.max_spawn_budget,allowedMerchants:o.allowed_merchants||[]}}async getAvailableBudget(){let e=await this.getSessionAuthHeaders(),t=await fetch(`${this.baseUrl}/api/v1/agent/descendants`,{method:"GET",headers:e});if(!t.ok){let n=await t.json().catch(()=>({}));throw new l(n.error||`Failed to get budget: ${t.status}`)}let s=await t.json();return {totalBudget:s.budget.total_usd,spent:s.budget.spent_usd,allocatedToChildren:s.budget.allocated_to_children_usd,available:s.budget.available_usd,maxSpawnBudget:s.max_spawn_budget,canSpawn:s.can_spawn}}async getChildSessions(){let e=await this.getSessionAuthHeaders(),t=await fetch(`${this.baseUrl}/api/v1/agent/descendants`,{method:"GET",headers:e});if(!t.ok){let n=await t.json().catch(()=>({}));throw new l(n.error||`Failed to get children: ${t.status}`)}return (await t.json()).children||[]}async listChildSessions(){return this.getChildSessions()}async fetch(e,t){this.logger.debug(`Fetching ${t?.method||"GET"} ${e}`),await this.validateMerchantAllowed(e,"url");let s=crypto.randomUUID(),n=this.extractCorrelationId(t?.headers),a=new AbortController,r=setTimeout(()=>a.abort(),this.timeout);try{let i=await fetch(e,{...t,signal:a.signal});return this.logger.debug(`Initial response: ${i.status}`),i.status===402&&(this.logger.info(`Payment required for ${e}`),i=await this.handlePaymentRequired(e,t,i,s,n)),i}catch(i){throw i instanceof Error&&i.name==="AbortError"?new l(`Request timeout after ${this.timeout}ms`):i}finally{clearTimeout(r);}}extractCorrelationId(e){if(!e)return;if(e instanceof Headers)return e.get("X-Correlation-Id")||e.get("x-correlation-id")||void 0;if(Array.isArray(e)){let s=e.find(([n])=>n.toLowerCase()==="x-correlation-id");return s?s[1]:void 0}let t=e;return t["X-Correlation-Id"]||t["x-correlation-id"]||void 0}async handlePaymentRequired(e,t,s,n,a){let r;try{r=await pe(s),this.logger.debug("Payment requirements:",{amount:`$${B(r).toFixed(4)}`,recipient:r.recipient,description:r.description});}catch(u){throw this.logger.error("Failed to parse payment requirements:",u),new x(`Failed to parse payment requirements: ${u}. The server may not be properly configured for x402 payments.`)}if(he(r))throw new x("Payment requirements have expired. This usually means the request took too long. Try again.");let i=B(r);if(this.maxPaymentUsd!==void 0&&i>this.maxPaymentUsd)throw new T("client_max",this.maxPaymentUsd,i);let o;try{this.logger.debug("Signing payment authorization..."),o=await me(r,this.sessionKey,this.walletAddress);}catch(u){throw this.logger.error("Failed to sign payment:",u),new x(`Failed to sign payment: ${u}. This may indicate an issue with the session key.`)}this.logger.debug("Retrying request with payment...");let d=new Headers(t?.headers);d.set("X-PAYMENT",o);let g=await fetch(e,{...t,headers:d});if(g.status!==402){let u={amountUsd:i,recipient:r.recipient,txHash:g.headers.get("X-Payment-TxHash"),timestamp:new Date,description:r.description,url:e,requestId:n,correlationId:a};this.payments.push(u),this.totalSpentUsd+=i,this.logger.payment(i,r.recipient,r.description),this.onPayment&&this.onPayment(u);}else await this.handlePaymentError(g);return g}async handlePaymentError(e){let t={};try{t=await e.json();}catch{}let s=(t.error_code||"").toLowerCase(),n=t.error||t.message||"Payment required";if(this.logger.error("Payment failed:",{errorCode:s,errorMessage:n,errorData:t}),s==="insufficient_balance"){let a=t.required||0,r=t.available||0;throw new k(a,r)}else throw s==="session_key_expired"?new $(t.expired_at||"unknown"):s==="spending_limit_exceeded"?new T(t.limit_type||"unknown",t.limit||0,t.attempted||0):new x(n)}getWalletAddress(){return this.walletAddress}getSessionKeyId(){return this.sessionKeyId}isTestnet(){return this.sessionKey.isTest}getNetwork(){return this.isTestnet()?fe.BASE_SEPOLIA:fe.BASE_MAINNET}async getBalance(){this.logger.debug("Fetching wallet balance...");try{let e=await fetch(`${this.baseUrl}/api/v1/session-key/info`,{headers:{"X-Session-Key":this.sessionKey.address.toLowerCase()}});if(!e.ok)throw new Error("Failed to get session key info");let t=await e.json(),s=t.wallet_address||t.walletAddress;if(!s)throw new Error("No wallet address in session key info");let n=await fetch(`${this.baseUrl}/api/wallet/balance?address=${s}&chain=base`);if(n.ok){let a=await n.json(),r=a.balance_usdc||a.balance_usd||0;return this.logger.debug(`Balance: $${r}`),r}}catch(e){this.logger.warn("Failed to fetch balance:",e);}return this.logger.debug("Using estimated balance based on tracking"),Math.max(0,100-this.totalSpentUsd)}async canAfford(e){let t=await this.getBalance(),s=t>=e;return {canAfford:s,balance:t,shortfall:s?0:e-t,remainingAfter:s?t-e:0}}async getSessionKeyInfo(e=false){let t=this.sessionKeyInfoFetchedAt?Date.now()-this.sessionKeyInfoFetchedAt:1/0;if(!e&&this.sessionKeyInfo&&t<6e4)return this.sessionKeyInfo;this.logger.debug("Fetching session key info...");try{let s=await fetch(`${this.baseUrl}/api/v1/session-key/info`,{headers:{"X-Session-Key":this.sessionKey.address.toLowerCase()}});if(s.ok){let n=await s.json();return this.sessionKeyInfo={address:this.sessionKey.address,walletAddress:n.wallet_address??n.walletAddress??null,isValid:n.is_valid??n.isValid??!0,limits:{perTxUsd:n.per_tx_limit_usd??n.perTxLimitUsd??null,dailyUsd:n.daily_limit_usd??n.dailyLimitUsd??null,totalUsd:n.total_limit_usd??n.totalLimitUsd??null},usage:{todayUsd:n.today_spent_usd??n.todaySpentUsd??0,totalUsd:n.total_spent_usd??n.totalSpentUsd??0,txCount:n.tx_count??n.txCount??0},expiresAt:n.expires_at?new Date(n.expires_at):null,createdAt:n.created_at?new Date(n.created_at):null,name:n.name,allowedMerchants:n.allowed_merchants??n.allowedMerchants??[]},this.sessionKeyInfoFetchedAt=Date.now(),this.sessionKeyInfo}}catch(s){this.logger.warn("Failed to fetch session key info:",s);}return {address:this.sessionKey.address,walletAddress:null,isValid:true,limits:{perTxUsd:null,dailyUsd:null,totalUsd:null},usage:{todayUsd:this.totalSpentUsd,totalUsd:this.totalSpentUsd,txCount:this.payments.length},expiresAt:null,createdAt:null}}async getSpendingStats(){this.logger.debug("Fetching spending stats...");try{let e=await fetch(`${this.baseUrl}/api/v1/session-key/stats`,{headers:{"X-Session-Key":this.sessionKey.address.toLowerCase()}});if(e.ok){let t=await e.json();return {totalSpentUsd:t.total_spent_usd||t.totalSpentUsd||this.totalSpentUsd,txCount:t.tx_count||t.txCount||this.payments.length,remainingDailyUsd:t.remaining_daily_usd||t.remainingDailyUsd||null,remainingTotalUsd:t.remaining_total_usd||t.remainingTotalUsd||null,expiresAt:t.expires_at?new Date(t.expires_at):null}}}catch(e){this.logger.warn("Failed to fetch spending stats:",e);}return {totalSpentUsd:this.totalSpentUsd,txCount:this.payments.length,remainingDailyUsd:null,remainingTotalUsd:null,expiresAt:null}}getPaymentHistory(){return [...this.payments]}getTotalSpent(){return this.totalSpentUsd}async createSelfCustodyWallet(){if(!this.agentInstanceId)throw new l("Agent instance ID is required for self-custody wallet. Use AgentWallet.fromApiKey() or set MIXRPAY_INSTANCE_ID environment variable.","NO_AGENT_INSTANCE_ID");let e=await q();if(e){let i=privateKeyToAccount(e);return this.selfCustodyAddress=i.address,this.selfCustodyKey=e,this.logger.info("Loaded existing self-custody wallet",{address:i.address}),{address:i.address,privateKey:e}}let t=generatePrivateKey(),s=privateKeyToAccount(t),n=Date.now(),a=`MixrPay Wallet Registration
7
+ `);try{let{saveCredentials:Se}=await import('./credentials-2PX5YXGV.js');Se({sessionKey:b,sessionKeyId:C,baseUrl:t});}catch{}return new c({sessionKey:b,sessionKeyId:C,baseUrl:t,logLevel:e?.logLevel})}}let h=(await y.json().catch(()=>({}))).error;if(h!=="authorization_pending")if(h==="slow_down"){await new Promise(w=>setTimeout(w,u));continue}else {if(h==="expired_token")throw new l("Device code expired. Please try again.");if(h==="access_denied")throw new l("Authentication was denied by the user.");if(h)throw new l(`Device flow error: ${h}`)}}throw new l("Device flow timed out. Please try again.")}async spawnChildInvite(e){let{budgetUsd:t,name:s,allowedMerchants:n,expiresInDays:a}=e,r=await this.getSessionAuthHeaders(),i=await fetch(`${this.baseUrl}/api/v1/agent/spawn`,{method:"POST",headers:{"Content-Type":"application/json",...r},body:JSON.stringify({budget_usd:t,name:s,allowed_merchants:n,expires_in_days:a})});if(!i.ok){let d=await i.json().catch(()=>({}));throw i.status===409?new l("Concurrent modification - please retry"):i.status===429?new l("Rate limited - too many spawn attempts"):new l(d.error||`Failed to spawn child: ${i.status}`)}let o=await i.json();return {inviteCode:o.invite_code,inviteId:o.invite_id,budgetUsd:o.budget_usd,expiresAt:new Date(o.expires_at),depth:o.depth,maxSpawnBudget:o.max_spawn_budget,allowedMerchants:o.allowed_merchants||[]}}async getAvailableBudget(){let e=await this.getSessionAuthHeaders(),t=await fetch(`${this.baseUrl}/api/v1/agent/descendants`,{method:"GET",headers:e});if(!t.ok){let n=await t.json().catch(()=>({}));throw new l(n.error||`Failed to get budget: ${t.status}`)}let s=await t.json();return {totalBudget:s.budget.total_usd,spent:s.budget.spent_usd,allocatedToChildren:s.budget.allocated_to_children_usd,available:s.budget.available_usd,maxSpawnBudget:s.max_spawn_budget,canSpawn:s.can_spawn}}async getChildSessions(){let e=await this.getSessionAuthHeaders(),t=await fetch(`${this.baseUrl}/api/v1/agent/descendants`,{method:"GET",headers:e});if(!t.ok){let n=await t.json().catch(()=>({}));throw new l(n.error||`Failed to get children: ${t.status}`)}return (await t.json()).children||[]}async listChildSessions(){return this.getChildSessions()}async fetch(e,t){this.logger.debug(`Fetching ${t?.method||"GET"} ${e}`),await this.validateMerchantAllowed(e,"url");let s=crypto.randomUUID(),n=this.extractCorrelationId(t?.headers),a=new AbortController,r=setTimeout(()=>a.abort(),this.timeout);try{let i=await fetch(e,{...t,signal:a.signal});return this.logger.debug(`Initial response: ${i.status}`),i.status===402&&(this.logger.info(`Payment required for ${e}`),i=await this.handlePaymentRequired(e,t,i,s,n)),i}catch(i){throw i instanceof Error&&i.name==="AbortError"?new l(`Request timeout after ${this.timeout}ms`):i}finally{clearTimeout(r);}}extractCorrelationId(e){if(!e)return;if(e instanceof Headers)return e.get("X-Correlation-Id")||e.get("x-correlation-id")||void 0;if(Array.isArray(e)){let s=e.find(([n])=>n.toLowerCase()==="x-correlation-id");return s?s[1]:void 0}let t=e;return t["X-Correlation-Id"]||t["x-correlation-id"]||void 0}async handlePaymentRequired(e,t,s,n,a){let r;try{r=await pe(s),this.logger.debug("Payment requirements:",{amount:`$${B(r).toFixed(4)}`,recipient:r.recipient,description:r.description});}catch(u){throw this.logger.error("Failed to parse payment requirements:",u),new A(`Failed to parse payment requirements: ${u}. The server may not be properly configured for x402 payments.`)}if(he(r))throw new A("Payment requirements have expired. This usually means the request took too long. Try again.");let i=B(r);if(this.maxPaymentUsd!==void 0&&i>this.maxPaymentUsd)throw new T("client_max",this.maxPaymentUsd,i);let o;try{this.logger.debug("Signing payment authorization..."),o=await me(r,this.sessionKey,this.walletAddress);}catch(u){throw this.logger.error("Failed to sign payment:",u),new A(`Failed to sign payment: ${u}. This may indicate an issue with the session key.`)}this.logger.debug("Retrying request with payment...");let d=new Headers(t?.headers);d.set("X-PAYMENT",o);let g=await fetch(e,{...t,headers:d});if(g.status!==402){let u={amountUsd:i,recipient:r.recipient,txHash:g.headers.get("X-Payment-TxHash"),timestamp:new Date,description:r.description,url:e,requestId:n,correlationId:a};this.payments.push(u),this.totalSpentUsd+=i,this.logger.payment(i,r.recipient,r.description),this.onPayment&&this.onPayment(u);}else await this.handlePaymentError(g);return g}async handlePaymentError(e){let t={};try{t=await e.json();}catch{}let s=(t.error_code||"").toLowerCase(),n=t.error||t.message||"Payment required";if(this.logger.error("Payment failed:",{errorCode:s,errorMessage:n,errorData:t}),s==="insufficient_balance"){let a=t.required||0,r=t.available||0;throw new k(a,r)}else throw s==="session_key_expired"?new $(t.expired_at||"unknown"):s==="spending_limit_exceeded"?new T(t.limit_type||"unknown",t.limit||0,t.attempted||0):new A(n)}getWalletAddress(){return this.walletAddress}getSessionKeyId(){return this.sessionKeyId}isTestnet(){return this.sessionKey.isTest}getNetwork(){return this.isTestnet()?fe.BASE_SEPOLIA:fe.BASE_MAINNET}async getBalance(){this.logger.debug("Fetching wallet balance...");try{let e=await fetch(`${this.baseUrl}/api/v1/session-key/info`,{headers:{"X-Session-Key":this.sessionKey.address.toLowerCase()}});if(!e.ok)throw new Error("Failed to get session key info");let t=await e.json(),s=t.wallet_address||t.walletAddress;if(!s)throw new Error("No wallet address in session key info");let n=await fetch(`${this.baseUrl}/api/wallet/balance?address=${s}&chain=base`);if(n.ok){let a=await n.json(),r=a.balance_usdc||a.balance_usd||0;return this.logger.debug(`Balance: $${r}`),r}}catch(e){this.logger.warn("Failed to fetch balance:",e);}return this.logger.debug("Using estimated balance based on tracking"),Math.max(0,100-this.totalSpentUsd)}async canAfford(e){let t=await this.getBalance(),s=t>=e;return {canAfford:s,balance:t,shortfall:s?0:e-t,remainingAfter:s?t-e:0}}async getSessionKeyInfo(e=false){let t=this.sessionKeyInfoFetchedAt?Date.now()-this.sessionKeyInfoFetchedAt:1/0;if(!e&&this.sessionKeyInfo&&t<6e4)return this.sessionKeyInfo;this.logger.debug("Fetching session key info...");try{let s=await fetch(`${this.baseUrl}/api/v1/session-key/info`,{headers:{"X-Session-Key":this.sessionKey.address.toLowerCase()}});if(s.ok){let n=await s.json();return this.sessionKeyInfo={address:this.sessionKey.address,walletAddress:n.wallet_address??n.walletAddress??null,isValid:n.is_valid??n.isValid??!0,limits:{perTxUsd:n.per_tx_limit_usd??n.perTxLimitUsd??null,dailyUsd:n.daily_limit_usd??n.dailyLimitUsd??null,totalUsd:n.total_limit_usd??n.totalLimitUsd??null},usage:{todayUsd:n.today_spent_usd??n.todaySpentUsd??0,totalUsd:n.total_spent_usd??n.totalSpentUsd??0,txCount:n.tx_count??n.txCount??0},expiresAt:n.expires_at?new Date(n.expires_at):null,createdAt:n.created_at?new Date(n.created_at):null,name:n.name,allowedMerchants:n.allowed_merchants??n.allowedMerchants??[]},this.sessionKeyInfoFetchedAt=Date.now(),this.sessionKeyInfo}}catch(s){this.logger.warn("Failed to fetch session key info:",s);}return {address:this.sessionKey.address,walletAddress:null,isValid:true,limits:{perTxUsd:null,dailyUsd:null,totalUsd:null},usage:{todayUsd:this.totalSpentUsd,totalUsd:this.totalSpentUsd,txCount:this.payments.length},expiresAt:null,createdAt:null}}async getSpendingStats(){this.logger.debug("Fetching spending stats...");try{let e=await fetch(`${this.baseUrl}/api/v1/session-key/stats`,{headers:{"X-Session-Key":this.sessionKey.address.toLowerCase()}});if(e.ok){let t=await e.json();return {totalSpentUsd:t.total_spent_usd||t.totalSpentUsd||this.totalSpentUsd,txCount:t.tx_count||t.txCount||this.payments.length,remainingDailyUsd:t.remaining_daily_usd||t.remainingDailyUsd||null,remainingTotalUsd:t.remaining_total_usd||t.remainingTotalUsd||null,expiresAt:t.expires_at?new Date(t.expires_at):null}}}catch(e){this.logger.warn("Failed to fetch spending stats:",e);}return {totalSpentUsd:this.totalSpentUsd,txCount:this.payments.length,remainingDailyUsd:null,remainingTotalUsd:null,expiresAt:null}}getPaymentHistory(){return [...this.payments]}getTotalSpent(){return this.totalSpentUsd}async createSelfCustodyWallet(){if(!this.agentInstanceId)throw new l("Agent instance ID is required for self-custody wallet. Use AgentWallet.fromApiKey() or set MIXRPAY_INSTANCE_ID environment variable.","NO_AGENT_INSTANCE_ID");let e=await q();if(e){let i=privateKeyToAccount(e);return this.selfCustodyAddress=i.address,this.selfCustodyKey=e,this.logger.info("Loaded existing self-custody wallet",{address:i.address}),{address:i.address,privateKey:e}}let t=generatePrivateKey(),s=privateKeyToAccount(t),n=Date.now(),a=`MixrPay Wallet Registration
14
8
  Address: ${s.address}
15
9
  Timestamp: ${n}`,r=await s.signMessage({message:a});return await this.registerWalletAddress(s.address,r,n),await ue(t,s.address),this.selfCustodyAddress=s.address,this.selfCustodyKey=t,this.logger.info("Created self-custody wallet",{address:s.address}),{address:s.address,privateKey:t}}async registerWalletAddress(e,t,s){if(!this.apiKey)throw new l("API key is required for wallet registration. Use AgentWallet.fromApiKey() to initialize.","NO_API_KEY");let n=await fetch(`${this.baseUrl}/api/v2/agent/wallet/register`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.apiKey}`},body:JSON.stringify({address:e,signature:t,timestamp:s})});if(!n.ok){let a=await n.json().catch(()=>({}));throw new l(a.error||`Failed to register wallet: ${n.status}`,"WALLET_REGISTRATION_FAILED")}}async loadSelfCustodyWallet(){let e=await q();if(!e)return false;let t=privateKeyToAccount(e);return this.selfCustodyAddress=t.address,this.selfCustodyKey=e,this.logger.debug("Loaded self-custody wallet",{address:t.address}),true}async hasSelfCustodyWallet(){return await ge()}getSelfCustodyAddress(){return this.selfCustodyAddress||null}async executeFromOwnWallet(e){if(!this.selfCustodyKey||!this.selfCustodyAddress)throw new l("Self-custody wallet not loaded. Call loadSelfCustodyWallet() or createSelfCustodyWallet() first.","WALLET_NOT_LOADED");let{to:t,value:s,data:n,gasLimit:a}=e,r=privateKeyToAccount(this.selfCustodyKey),i=createWalletClient({account:r,chain:base,transport:http()});this.logger.debug("Executing transaction from self-custody wallet",{from:this.selfCustodyAddress,to:t,value:s?.toString()});try{let o=await i.sendTransaction({to:t,value:s??BigInt(0),data:n,gas:a});this.logger.info("Transaction submitted",{txHash:o});let d=!1;try{await this.reportTransaction(o,t,s??BigInt(0)),d=!0;}catch(g){this.logger.warn("Failed to report transaction to MixrPay",{txHash:o,error:g instanceof Error?g.message:g});}return {txHash:o,reportedToMixrPay:d}}catch(o){throw this.logger.error("Transaction failed",{error:o instanceof Error?o.message:o}),new l(`Transaction failed: ${o instanceof Error?o.message:"Unknown error"}`,"TRANSACTION_FAILED")}}async transferUSDC(e){if(!this.selfCustodyKey||!this.selfCustodyAddress)throw new l("Self-custody wallet not loaded. Call loadSelfCustodyWallet() or createSelfCustodyWallet() first.","WALLET_NOT_LOADED");let{to:t,amountUsdc:s}=e,n="0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",a=6,r=parseUnits(s.toFixed(a),a),i=encodeFunctionData({abi:[{name:"transfer",type:"function",inputs:[{name:"to",type:"address"},{name:"amount",type:"uint256"}],outputs:[{type:"bool"}]}],functionName:"transfer",args:[t,r]});return this.logger.debug("Transferring USDC",{from:this.selfCustodyAddress,to:t,amountUsdc:s,amountMinorUnits:r.toString()}),(await this.executeFromOwnWallet({to:n,data:i})).txHash}async reportTransaction(e,t,s){if(!this.apiKey){this.logger.warn("Cannot report transaction - no API key set");return}let n=await fetch(`${this.baseUrl}/api/v2/agent/tx/report`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.apiKey}`},body:JSON.stringify({tx_hash:e,to_address:t,value:s.toString(),chain_id:base.id})});if(!n.ok){let a=await n.json().catch(()=>({}));throw new l(a.error||`Failed to report transaction: ${n.status}`,"TX_REPORT_FAILED")}}getAgentInstanceId(){return this.agentInstanceId}setAgentInstanceId(e){this.agentInstanceId=e;}setApiKey(e){this.apiKey=e;}mcp(){let e=join(dirname(fileURLToPath(import.meta.url)),"mcp-server.js"),t={MIXRPAY_SESSION_KEY:this.sessionKey.toString(),MIXRPAY_BASE_URL:this.baseUrl};return this.apiKey&&(t.MIXRPAY_API_KEY=this.apiKey),this.agentInstanceId&&(t.MIXRPAY_INSTANCE_ID=this.agentInstanceId),this.selfCustodyKey&&(t.AGENT_WALLET_KEY=this.selfCustodyKey),this.maxPaymentUsd&&(t.MIXRPAY_MAX_PAYMENT_USD=String(this.maxPaymentUsd)),{command:"node",args:[e],env:t}}tools(){let{definitions:e,execute:t}=j(this);return {definitions:e.map(n=>({name:n.name,description:n.description,input_schema:n.inputSchema?le(n.inputSchema):{type:"object",properties:{}}})),execute:t}}async runDiagnostics(){this.logger.info("Running diagnostics...");let e=[],t=[],s={},n,a;s.sessionKeyFormat=true;try{let o=Date.now(),d=await fetch(`${this.baseUrl}/health`,{method:"GET",signal:AbortSignal.timeout(5e3)});n=Date.now()-o,s.apiConnectivity=d.ok,d.ok||(e.push(`API server returned ${d.status}. Check baseUrl configuration.`),t.push("Verify the baseUrl configuration points to a valid MixrPay server.")),n>2e3&&(e.push(`High API latency: ${n}ms. This may cause timeouts.`),t.push("Consider using a server closer to your region or check network connectivity."));}catch{s.apiConnectivity=false,e.push("Cannot connect to MixrPay API. Check your network connection and baseUrl."),t.push("Verify network connectivity and that the MixrPay server is running.");}try{let o=await this.getSessionKeyInfo(!0);s.sessionKeyValid=o.isValid,o.isValid||(e.push("Session key is invalid or has been revoked."),t.push("Request a new session key from the wallet owner at https://mixrpay.com/manage/invites"));let d=new Date,g=null;o.expiresAt&&(g=(o.expiresAt.getTime()-d.getTime())/(1e3*60*60),o.expiresAt<d?(s.sessionKeyValid=!1,e.push(`Session key expired on ${o.expiresAt.toISOString()}`),t.push("Create a new session key to continue making payments.")):g<24&&(e.push(`Session key expires in ${g.toFixed(1)} hours.`),t.push("Consider creating a new session key before the current one expires.")));let u=await this.getSpendingStats();a={remainingDailyUsd:u.remainingDailyUsd,remainingTotalUsd:u.remainingTotalUsd,expiresAt:o.expiresAt,expiresInHours:g},u.remainingDailyUsd!==null&&u.remainingDailyUsd<1&&(e.push(`Daily limit nearly exhausted: $${u.remainingDailyUsd.toFixed(2)} remaining.`),t.push("Wait until tomorrow for daily limit to reset, or request a higher daily limit.")),u.remainingTotalUsd!==null&&u.remainingTotalUsd<1&&(e.push(`Total limit nearly exhausted: $${u.remainingTotalUsd.toFixed(2)} remaining.`),t.push("Request a new session key with a higher total limit."));}catch{s.sessionKeyValid=false,e.push("Could not verify session key validity."),t.push("Check network connectivity and try again.");}let r=0;try{r=await this.getBalance(),s.hasBalance=r>0,r<=0?(e.push("Wallet has no USDC balance. Top up at https://mixrpay.com/manage/wallet"),t.push("Deposit USDC to your wallet address to enable payments.")):r<1&&(e.push(`Low balance: $${r.toFixed(2)}. Consider topping up.`),t.push("Top up your wallet balance to avoid payment failures."));}catch{s.hasBalance=false,e.push("Could not fetch wallet balance."),t.push("Check network connectivity and try again.");}let i=e.length===0;return this.logger.info("Diagnostics complete:",{healthy:i,issues:e,latencyMs:n}),{healthy:i,issues:e,checks:s,sdkVersion:H,network:this.getNetwork().name,walletAddress:this.walletAddress,sessionLimits:a,latencyMs:n,recommendations:t}}async generateSiwe(e){let{domain:t,uri:s,statement:n,nonce:a=crypto.randomUUID(),issuedAt:r=new Date,expirationTime:i,notBefore:o,requestId:d,resources:g}=e,u=this.sessionKey.address,p=this.getNetwork().chainId,y="1",f=`${t} wants you to sign in with your Ethereum account:
16
10
  `;if(f+=`${u}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mixrpay/agent-sdk",
3
- "version": "0.11.3",
3
+ "version": "0.11.4",
4
4
  "description": "Non-custodial wallet and payments SDK for AI agents with MCP and Claude integration",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",