@botanary/agent 0.1.0-alpha.2 → 0.1.0-alpha.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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## Unreleased
4
+
5
+ - Add `prepareAction({ mandate, action })` for exact Base Sepolia transfers from a confirmed mandate projection.
6
+ - Return deterministic typed refusals for over-limit, wrong-recipient, inactive, expired, and revoked mandates before signing or transport.
7
+ - Require a trusted per-runtime native gas ceiling for the mandate facade and preserve the existing exact action hash, nonce-lane, one-shot submission, and reconciliation checks.
8
+
3
9
  ## Unreleased - protected artifact build
4
10
 
5
11
  - No public method changed. `AgentRuntime` still contains no planning, tool selection, or
package/README.md CHANGED
@@ -70,6 +70,31 @@ No mainnet grant capability is added here.
70
70
 
71
71
  ## Exact execution
72
72
 
73
+ For the developer-first mandate flow, configure one trusted native gas ceiling when constructing the
74
+ runtime, then pass the confirmed mandate projection directly. The facade accepts transfer only and
75
+ maps `amountRaw` without floating-point conversion:
76
+
77
+ ```ts
78
+ const runtime = new AgentRuntime(agentSigner, { maxGasCostWei: '10000000000000000' });
79
+ const prepared = await runtime.prepareAction({
80
+ mandate,
81
+ action: { type: 'transfer', tokenAddress, recipient, amountRaw: '1000000' },
82
+ });
83
+ if (prepared.status === 'refused') {
84
+ // No transaction was submitted. Render reason and remainingRaw as policy evidence.
85
+ return prepared;
86
+ }
87
+ remember(prepared.userOpHash);
88
+ return prepared.submit();
89
+ ```
90
+
91
+ The projection must report confirmed creation, active API access, observed active chain authority,
92
+ the exact account, agent, permission, executor, policy, and remaining limit. The package rechecks the
93
+ runtime agent identity. Over-limit, wrong-recipient, inactive, expired, and revoked requests return a
94
+ typed refusal before build or signing. An allowed request continues through the same exact call,
95
+ nonce-lane, gas-ceiling, hash, signature, one-shot submission, and reconciliation checks described
96
+ below. OpenAI integration, key loading, persistence, and retries remain host responsibilities.
97
+
73
98
  An already connected agent with an owner-signed grant can prepare an action. Obtain the delegation ID,
74
99
  permission ID and pinned executor address from that approved grant and its network deployment. The
75
100
  app key is never an execution credential. Amounts and the maximum native gas cost are integer strings.
@@ -25,11 +25,58 @@ export interface AgentSwapBinding extends AgentActionBinding {
25
25
  verifyRoute?: (facts: Readonly<SwapRouteFacts>) => boolean | Promise<boolean>;
26
26
  }
27
27
  export interface PreparedAgentAction {
28
+ readonly status: 'prepared';
28
29
  readonly userOpHash: Hex;
29
30
  readonly execution: Readonly<ExactAgentExecution>;
30
31
  submit(): Promise<Record<string, unknown>>;
31
32
  reconcile(): Promise<Record<string, unknown>>;
32
33
  }
34
+ export interface AgentMandateProjection {
35
+ readonly id: string;
36
+ readonly accountId: string;
37
+ readonly accountAddress: Hex;
38
+ readonly agentAddress: Hex;
39
+ readonly chainId: 84532;
40
+ readonly permissionId: Hex;
41
+ readonly grantExecutor: Hex;
42
+ readonly apiAccess: string;
43
+ readonly createStatus: string;
44
+ readonly revokeStatus: string | null;
45
+ readonly policy: {
46
+ readonly budgets: readonly {
47
+ readonly token: Hex;
48
+ readonly amountRaw: string;
49
+ }[];
50
+ readonly perActionMaxRaw: string | null;
51
+ readonly recipients: readonly Hex[];
52
+ readonly maxActions: number | null;
53
+ readonly expiresAt: string;
54
+ };
55
+ readonly chainState: {
56
+ readonly status: string;
57
+ readonly remaining?: readonly {
58
+ readonly token: Hex;
59
+ readonly remainingRaw: string;
60
+ }[];
61
+ };
62
+ }
63
+ export interface MandateTransferInput {
64
+ readonly mandate: AgentMandateProjection;
65
+ readonly action: {
66
+ readonly type: 'transfer';
67
+ readonly tokenAddress: Hex;
68
+ readonly recipient: Hex;
69
+ readonly amountRaw: string;
70
+ };
71
+ }
72
+ export interface AgentPolicyRefusal {
73
+ readonly status: 'refused';
74
+ readonly reason: 'over_per_action_max' | 'wrong_recipient' | 'mandate_inactive' | 'mandate_revoked' | 'mandate_expired';
75
+ readonly transactionSubmitted: false;
76
+ readonly requestedAmountRaw: string;
77
+ readonly perActionMaxRaw: string | null;
78
+ readonly remainingRaw: string | null;
79
+ }
33
80
  export declare function exactActionInput(value: ExactAgentAction): ExactAgentAction;
34
81
  export declare function actionBinding(value: AgentActionBinding | AgentSwapBinding, action: ExactAgentAction): AgentActionBinding | AgentSwapBinding;
35
82
  export declare function validateExactAction(value: unknown, input: ExactAgentAction, binding: AgentActionBinding | AgentSwapBinding): Promise<{
@@ -942,12 +942,17 @@ export interface components {
942
942
  grantStatus: "none" | "pending" | "active" | "paused" | "expired" | "revoked" | "unknown";
943
943
  grants?: components["schemas"]["PublicGrant"][];
944
944
  connectionId: string | null;
945
+ embeddedBindingId?: string | null;
946
+ authorizationKind?: "hosted" | "embedded" | null;
945
947
  };
946
948
  PublicGrant: {
947
949
  id: string;
948
950
  appId: string;
949
951
  environment: "test" | "live";
950
- connectionId: string;
952
+ authorizationKind: "hosted" | "embedded";
953
+ connectionId: string | null;
954
+ embeddedBindingId: string | null;
955
+ bindingVersion: number | null;
951
956
  registrationId: string;
952
957
  agentId: string;
953
958
  accountId: string;
@@ -963,7 +968,7 @@ export interface components {
963
968
  apiAccess: "active" | "awaiting_connection" | "connection_revoked" | "key_revoked" | "disabled" | "app_disabled" | "unavailable";
964
969
  chainState: components["schemas"]["PublicGrantChainState"];
965
970
  createOperationId: string;
966
- createApprovalUrl: string;
971
+ createApprovalUrl: string | null;
967
972
  createStatus: "awaiting_approval" | "submitted" | "confirmed" | "failed" | "canceled" | "expired" | "unresolved";
968
973
  revokeOperationId: string | null;
969
974
  revokeApprovalUrl: string | null;
package/dist/index.d.ts CHANGED
@@ -7,4 +7,4 @@ export { registerAgent, type AgentRegistrationClient } from './registration.js';
7
7
  export type * from './views.js';
8
8
  export { PairingCodeManager, DEFAULT_PAIRING_CODE_TTL_MS, type PairingCode } from './pairing-code.js';
9
9
  export { crockfordBase32, deriveFingerprint, generatePairingNonce, FINGERPRINT_BYTES, NONCE_BYTES } from './fingerprint.js';
10
- export type { ExactAgentAction, ExactAgentExecution, AgentActionBinding, AgentSwapBinding, SwapRouteFacts, PreparedAgentAction } from './exact-action.js';
10
+ export type { ExactAgentAction, ExactAgentExecution, AgentActionBinding, AgentSwapBinding, SwapRouteFacts, PreparedAgentAction, AgentMandateProjection, MandateTransferInput, AgentPolicyRefusal } from './exact-action.js';
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- var m=class extends Error{constructor(t,n,i=null,c=null){super(t);this.status=n;this.details=i;this.retryAfterSeconds=c;this.name="BotanaryApiError"}requestId;code;operationId;userOpHash;requirementId;ambiguous=!1};import{encodeFunctionData as E,encodePacked as Pe,decodeFunctionData as F,parseAbi as C,getAddress as I,zeroAddress as ve,zeroHash as Re}from"viem";import{entryPoint07Address as ee,getUserOperationHash as Se}from"viem/account-abstraction";import{publicKeyToAddress as Ie}from"viem/accounts";function a(){let r=new m("Botanary returned an invalid response. Nothing was signed.",0);throw r.code="invalid_response",r}function y(r){return typeof r!="object"||r===null||Array.isArray(r)?a():r}function u(r,e){(typeof r!="string"||!/^0x(?:[0-9a-fA-F]{2})*$/.test(r)||e!==void 0&&r.length!==2+2*e)&&a()}function w(r){(typeof r!="string"||!/^[A-Za-z0-9_-]{1,128}$/.test(r)||/^(?:bsk|ags|dcs|dca|dcr)_/.test(r))&&a()}function L(r){(typeof r!="string"||!/^(0|[1-9][0-9]{0,77})$/.test(r)||BigInt(r)>=2n**256n)&&a()}function H(r){let e=y(r);return u(e.address,20),u(e.publicKey,65),(!e.publicKey.startsWith("0x04")||Ie(e.publicKey).toLowerCase()!==e.address.toLowerCase()||typeof e.fingerprint!="string"||!/^[A-Za-z0-9]{1,32}$/.test(e.fingerprint)||typeof e.backend!="string"||!/^[A-Za-z0-9_-]{1,64}$/.test(e.backend)||typeof e.createdAt!="string"||!Number.isFinite(Date.parse(e.createdAt)))&&a(),Object.freeze({address:e.address,publicKey:e.publicKey,fingerprint:e.fingerprint,backend:e.backend,createdAt:e.createdAt})}function x(r,e=256){if(typeof r!="string"||!/^(0|[1-9][0-9]{0,77}|0x[0-9a-fA-F]{1,64})$/.test(r))return a();let t=BigInt(r);return t>=2n**BigInt(e)?a():t}function T(r){let e=y(r);for(let t of["sender","entryPoint"])u(e[t],20);for(let t of["nonce","callGasLimit","verificationGasLimit","preVerificationGas","maxFeePerGas","maxPriorityFeePerGas"])x(e[t]);for(let t of["callData","signature"])u(e[t]);for(let t of["paymasterVerificationGasLimit","paymasterPostOpGasLimit"])e[t]!=null&&x(e[t],128);(!Number.isSafeInteger(e.chainId)||Number(e.chainId)<=0)&&a();for(let t of["factory","paymaster"])e[t]!=null&&u(e[t],20);for(let t of["factoryData","paymasterData"])e[t]!=null&&u(e[t]);return r}function U(r){let e=y(r);u(e.payload,32),u(e.validator,20),(!Number.isSafeInteger(e.index)||Number(e.index)<0||Number(e.index)>=2**32)&&a();let t=y(e.authorization);return u(t.from,20),u(t.to,20),u(t.nonce,32),L(t.value),L(t.validAfter),L(t.validBefore),BigInt(t.validBefore)<=BigInt(t.validAfter)&&a(),{payload:e.payload,validator:e.validator,index:Number(e.index),authorization:{from:t.from,to:t.to,nonce:t.nonce,value:t.value,validAfter:t.validAfter,validBefore:t.validBefore}}}function z(r,e){let t=y(r);(t.requirementId!==e||typeof t.simulated!="boolean")&&a();let n={ready:["not_submitted"],pending_approval:["not_submitted"],submitted:["pending"],settled:["settled"],declined:["not_submitted","not_settled"]};return(typeof t.status!="string"||!Object.hasOwn(n,t.status)||!n[t.status].includes(String(t.paymentStatus)))&&a(),t.providerStatus!==void 0&&(!Number.isSafeInteger(t.providerStatus)||Number(t.providerStatus)<100||Number(t.providerStatus)>599)&&a(),t.txHash!==void 0&&u(t.txHash,32),t.status==="settled"&&u(t.txHash,32),t.status==="ready"?U(t.ready):t.ready!==void 0&&a(),t}var te=C(["function execute(bytes32 mode, bytes executionCalldata) payable"]),j=C(["function executeUnderGrant(bytes32 permissionId, address target, uint256 value, bytes callData)","function executeUnderGrantWithAllowance(bytes32 permissionId, address target, uint256 value, address token, uint256 allowance, bytes callData)"]),Oe=C(["function transfer(address to, uint256 amount) returns (bool)"]),ne=C(["function swapExactIn(address tokenIn, address tokenOut, uint256 amountIn, uint256 minOut, address to) returns (uint256 amountOut)"]),Ee=BigInt("0x000100000000008bdaba73cd9815d79069c247eb4bda0000");function f(r,e){return typeof r=="string"&&r.toLowerCase()===e.toLowerCase()}function b(r,e=!0){if(typeof r!="string"||!/^(0|[1-9][0-9]{0,77})$/.test(r))return a();let t=BigInt(r);return t>=2n**256n||e&&t===0n?a():t}function re(r){let e=y(r),t=["accountId","accountAddress","chainId","action","tokenAddress","amount","recipient","tokenOutAddress","maxSlippageBps"];return Object.keys(e).some(n=>!t.includes(n))&&a(),w(e.accountId),u(e.accountAddress,20),u(e.tokenAddress,20),b(e.amount),(!Number.isSafeInteger(e.chainId)||Number(e.chainId)<=0)&&a(),e.action==="transfer"?(u(e.recipient,20),(e.tokenOutAddress!==void 0||e.maxSlippageBps!==void 0)&&a()):e.action==="swap"?(u(e.tokenOutAddress,20),(e.recipient!==void 0||e.maxSlippageBps!==void 0&&(!Number.isInteger(e.maxSlippageBps)||Number(e.maxSlippageBps)<1||Number(e.maxSlippageBps)>1e3))&&a()):a(),Object.freeze({...r,accountAddress:I(r.accountAddress),tokenAddress:I(r.tokenAddress),...r.recipient!==void 0?{recipient:I(r.recipient)}:{},...r.tokenOutAddress!==void 0?{tokenOutAddress:I(r.tokenOutAddress)}:{}})}function ie(r,e){if(w(r.delegationId),u(r.permissionId,32),u(r.executorAddress,20),b(r.maxGasCostWei),e.action==="swap"){let t=r;u(t.routerAddress,20),b(t.minAmountOut),t.verifyRoute!==void 0&&typeof t.verifyRoute!="function"&&a()}return Object.freeze({...r,executorAddress:I(r.executorAddress),...e.action==="swap"?{routerAddress:I(r.routerAddress)}:{}})}async function se(r,e,t){try{let n=y(r),i=y(n.execution),c=T(n.userOp),s=Object.freeze({...c,sender:I(c.sender),entryPoint:I(c.entryPoint)});u(n.userOpHash,32),(n.intentType!=="delegated_action"||y(n.simulation).willSucceed!==!0||i.accountId!==e.accountId||!f(i.accountAddress,e.accountAddress)||i.chainId!==e.chainId||i.action!==e.action||i.amount!==e.amount||!f(i.tokenAddress,e.tokenAddress)||i.delegationId!==t.delegationId||!f(i.permissionId,t.permissionId)||i.gasMethod!=="native"||!f(s.sender,e.accountAddress)||s.chainId!==e.chainId||!f(s.entryPoint,ee)||s.factory!=null||s.factoryData!=null||s.paymaster!=null||s.paymasterData!=null||s.paymasterVerificationGasLimit!=null||s.paymasterPostOpGasLimit!=null)&&a();let o=x(s.nonce);o>>64n!==Ee&&a();let d=x(s.callGasLimit,128),g=x(s.verificationGasLimit,128),p=x(s.preVerificationGas),k=x(s.maxFeePerGas,128),h=x(s.maxPriorityFeePerGas,128);(h>k||(d+g+p)*k>b(t.maxGasCostWei))&&a();let l=s.callData,P;if(e.action==="transfer"){(!f(i.recipient,e.recipient)||i.tokenOutAddress!==void 0||i.maxSlippageBps!==void 0)&&a();let A=f(e.tokenAddress,ve);P=E({abi:j,functionName:"executeUnderGrant",args:[t.permissionId,A?e.recipient:e.tokenAddress,A?b(e.amount):0n,A?"0x":E({abi:Oe,functionName:"transfer",args:[e.recipient,b(e.amount)]})]})}else{let A=t;(!f(i.tokenOutAddress,e.tokenOutAddress)||i.recipient!==void 0||i.maxSlippageBps!==(e.maxSlippageBps??50))&&a();let G=F({abi:te,data:l}).args[1],v=F({abi:j,data:`0x${G.slice(106)}`});v.functionName!=="executeUnderGrantWithAllowance"&&a();let S=v.args[5],O=Object.freeze({chainId:e.chainId,accountAddress:e.accountAddress,routerAddress:A.routerAddress,tokenAddress:e.tokenAddress,tokenOutAddress:e.tokenOutAddress,amount:e.amount,minAmountOut:A.minAmountOut,callData:S});if(A.verifyRoute)await A.verifyRoute(O)!==!0&&a();else{let J=F({abi:ne,data:S}),[Ae,we,xe,be,ke]=J.args;(!f(Ae,e.tokenAddress)||!f(we,e.tokenOutAddress)||xe!==b(e.amount)||be<b(A.minAmountOut)||!f(ke,e.accountAddress)||!f(E({abi:ne,functionName:"swapExactIn",args:J.args}),S))&&a()}P=E({abi:j,functionName:"executeUnderGrantWithAllowance",args:[t.permissionId,A.routerAddress,0n,e.tokenAddress,b(e.amount),S]})}let R=E({abi:te,functionName:"execute",args:[Re,Pe(["address","uint256","bytes"],[t.executorAddress,0n,P])]});f(l,R)||a();let N=Se({entryPointAddress:ee,entryPointVersion:"0.7",chainId:e.chainId,userOperation:{sender:s.sender,nonce:o,callData:s.callData,callGasLimit:d,verificationGasLimit:g,preVerificationGas:p,maxFeePerGas:k,maxPriorityFeePerGas:h,signature:"0x"}});f(N,n.userOpHash)||a();let $=Object.freeze({...e,delegationId:t.delegationId,permissionId:t.permissionId,gasMethod:"native",...e.action==="swap"?{maxSlippageBps:e.maxSlippageBps??50}:{}});return{userOp:Object.freeze({sender:s.sender,chainId:s.chainId,entryPoint:s.entryPoint,nonce:s.nonce,callData:s.callData,callGasLimit:s.callGasLimit,verificationGasLimit:s.verificationGasLimit,preVerificationGas:s.preVerificationGas,maxFeePerGas:s.maxFeePerGas,maxPriorityFeePerGas:s.maxPriorityFeePerGas,signature:"0x"}),userOpHash:N,execution:$}}catch{return a()}}function M(r,e){try{let t=y(r);if(w(t.id),!f(t.userOpHash,e)||!["pending","included","failed"].includes(String(t.status)))throw new Error;return t.txHash!=null&&u(t.txHash,32),t}catch{let t=new m("Botanary returned an invalid receipt. Reconcile using the original operation hash.",0);throw t.code="invalid_response",t.userOpHash=e,t.ambiguous=!0,t}}import{keccak256 as Le,toHex as ze,encodePacked as me,encodeAbiParameters as Fe}from"viem";import{randomBytes as _e}from"node:crypto";import{hexToBytes as Be}from"viem";var oe="0123456789ABCDEFGHJKMNPQRSTVWXYZ";function V(r){let e=0,t=0,n="";for(let i of r)for(e=e<<8|i,t+=8;t>=5;)n+=oe[e>>>t-5&31],t-=5;return t>0&&(n+=oe[e<<5-t&31]),n}var ae=3,ce=5;function K(r){let e=Be(r);return V(e.slice(0,ae))}function W(){return V(_e(ce))}var de=600*1e3,_=class{#r;#e;#c;#o;#i=null;constructor(e,t){this.#r=e,this.#e=t?.ttlMs??de,this.#c=t?.now??Date.now,this.#o=t?.nonce??W}current(){let e=this.#c();return(!this.#i||this.#i.expiresAt<=e)&&this.#d(e),this.#s()}regenerate(){return this.#d(this.#c()),this.#s()}#d(e){this.#i={nonce:this.#o(),issuedAt:e,expiresAt:e+this.#e}}#s(){let e=this.#i;if(!e)throw new Error("unreachable: no pairing code minted");return{code:`${this.#r}-${e.nonce}`,fingerprint:this.#r,nonce:e.nonce,issuedAt:new Date(e.issuedAt).toISOString(),expiresAt:new Date(e.expiresAt).toISOString()}}};import qe from"openapi-fetch";var ue=[{method:"post",path:"/agents/pair"},{method:"post",path:"/agents/session/nonce"},{method:"post",path:"/agents/session"},{method:"get",path:"/agents/me"},{method:"get",path:"/agents/requests"},{method:"post",path:"/agents/requests"},{method:"get",path:"/balance"},{method:"get",path:"/chains"},{method:"get",path:"/gas/methods"},{method:"get",path:"/account"},{method:"post",path:"/delegations/{delegationId}/actions"},{method:"post",path:"/delegations/{delegationId}/actions/exact"},{method:"post",path:"/userops"},{method:"get",path:"/userops/{userOpId}"},{method:"get",path:"/userops/by-hash/{chainId}/{userOpHash}"},{method:"get",path:"/apis/providers"},{method:"get",path:"/apis/providers/{providerId}"},{method:"get",path:"/apis/budget"},{method:"post",path:"/apis/calls/requirements"},{method:"get",path:"/apis/calls/requirements/{id}"},{method:"post",path:"/apis/calls/relay"},{method:"get",path:"/apis/calls/relay/{id}"}];var pe="https://botanary-canonical-path.invalid",ge="(?:[A-Za-z0-9\\-._~!$&'()*+,;=:@]|%[0-9A-Fa-f]{2})",ut=`${ge}+`,He=new RegExp(`^${ge}+$`),Te=new RegExp("^(?:[A-Za-z0-9\\-._~!$&'()*+,;=:@/?]|%[0-9A-Fa-f]{2})*$"),Ue=/^\.{1,2}$/,Ce=/[/\\#?]/,De=/[\u0000-\u001f\u007f]/,Ne=6;function $e(r){let e=r;for(let t=0;t<Ne;t+=1){if(Ue.test(e)||Ce.test(e)||De.test(e))return!0;if(!e.includes("%"))return!1;let n;try{n=decodeURIComponent(e)}catch{return!0}if(n===e)return!1;e=n}return!0}function le(r){if(typeof r!="string"||r.length===0||!r.startsWith("/")||r.startsWith("//"))return null;let e=r.indexOf("?"),t=e===-1?r:r.slice(0,e),n=e===-1?"":r.slice(e),i=t.split("/");for(let s=1;s<i.length;s+=1){let o=i[s];if(!He.test(o)||$e(o))return null}if(n!==""&&!Te.test(n.slice(1)))return null;let c;try{c=new URL(t+n,pe)}catch{return null}return c.origin!==pe||c.hash!==""||c.pathname!==t||c.search!==n?null:{path:t,query:n,full:t+n}}var D=class{#r;constructor(e,t=fetch){let n=new URL(e);if(n.username||n.password||n.search||n.hash||n.pathname!=="/"||n.protocol!=="https:"&&!(n.protocol==="http:"&&["localhost","127.0.0.1","[::1]"].includes(n.hostname)))throw new Error("Agent API origin must be HTTPS, or HTTP on loopback.");this.#r=qe({baseUrl:n.origin+"/v1",fetch:Ge(t)})}get(e,t){return this.#e("get",e,void 0,t)}post(e,t,n){return this.#e("post",e,t,n)}async#e(e,t,n,i){let c=le(t);if(!c?.path.startsWith("/v1/"))throw new Error("Invalid agent API path.");if(i!==void 0&&!/^ags_[a-f0-9]{64}$/.test(i))throw new Error("Expected an agent session credential.");let s=c.path.slice(3),o=ue.find(h=>h.method===e&&new RegExp("^"+h.path.replace(/\{[^}]+\}/g,"[A-Za-z0-9_-]+")+"$").test(s));if(!o)throw new Error("This route is outside the reviewed agent API.");let d={};o.path.split("/").forEach((h,l)=>{h.startsWith("{")&&(d[h.slice(1,-1)]=s.split("/")[l])});let g=Object.fromEntries(new URLSearchParams(c.query)),p=new AbortController,k=setTimeout(()=>p.abort(),3e4);try{let h=await this.#r.request(e,o.path,{params:{path:d,query:g},...n===void 0?{}:{body:n},headers:i?{authorization:`Bearer ${i}`}:{},credentials:"omit",redirect:"error",cache:"no-store",signal:p.signal,parseAs:"text"}),l=h.response,P=h.error;if(l.ok)try{P=h.data?JSON.parse(h.data):{}}catch{throw new Error("Invalid JSON response.")}if(!l.ok){let R=Z(Z(P)?.error),$=(typeof R?.message=="string"?R.message:`Agent request failed with ${l.status}.`).replace(/(?:bsk_(?:test|live)|ags|dcs|dca|dcr)_[A-Za-z0-9_-]+/g,"[redacted]").replace(/0x[a-fA-F0-9]{64,}/g,"[redacted]"),B=l.headers.get("retry-after"),A=B&&/^\d+(?:\.\d+)?$/.test(B)?Number(B):null,q=Z(R?.details),G=q&&Object.fromEntries(Object.entries(q).filter(([S,O])=>["missingModule","declineReason","chainId"].includes(S)&&(typeof O=="number"||typeof O=="string"&&/^[a-zA-Z0-9_-]{1,100}$/.test(O)))),v=new m($.slice(0,1e3),l.status,G,A);throw v.requestId=he(l.headers.get("x-request-id")),v.code=he(R?.code)??"http_error",v.ambiguous=e==="post"&&l.status>=500,v}return P}catch(h){if(h instanceof m)throw h;let l=new m("The agent request did not complete. Check the existing operation before retrying.",0);throw l.code=p.signal.aborted?"timeout":"transport_error",l.ambiguous=e==="post",l}finally{clearTimeout(k)}}};function Z(r){return typeof r=="object"&&r!==null&&!Array.isArray(r)?r:null}function he(r){return typeof r=="string"&&/^[a-zA-Z0-9_-]{1,128}$/.test(r)&&!/^(?:ags|bsk|dcs|dca|dcr)_/.test(r)?r:void 0}function Ge(r){return async(e,t)=>{let n=e instanceof Request?e:new Request(e,t),i=n.signal,c=()=>{},s=new Promise((d,g)=>{c=()=>g(new Error("Request aborted.")),i.aborted?c():i.addEventListener("abort",c,{once:!0})}),o;try{let d=await Promise.race([r(n),s]);if(!d.body)return d;o=d.body.getReader();let g=[],p=0;for(;;){let l=await Promise.race([o.read(),s]);if(l.done)break;if(p+=l.value.byteLength,p>4*1024*1024)throw new Error("Response too large.");g.push(l.value)}let k=new Uint8Array(p),h=0;for(let l of g)k.set(l,h),h+=l.byteLength;return new Response(k,{status:d.status,statusText:d.statusText,headers:d.headers})}finally{i.removeEventListener("abort",c),o&&o.cancel().catch(()=>{})}}}import{recoverAddress as je}from"viem";async function X(r,e,t,n,i){if(!Number.isFinite(t)||t<0||t>36e5)throw new Error("Invalid wait budget.");let c=n(),s=await r(e);for(;["pending","pending_approval","submitted","queued"].includes(String(s.status))&&n()-c<t;)await i(1500),s=await r(e);return s}var Me=3e4,fe=300*1e3,ye="https://api.app.botanary.xyz",Y=class{#r;#e;#c;#o;#i=null;#d=null;#s=null;#u=null;#p=null;#n=0;constructor(e,t={}){this.#r=e,this.#c=t.baseUrl??ye,this.#e=t.transport??new D(this.#c,t.fetch),this.#o=t.provenance??{}}get apiBaseUrl(){return this.#c}get identityMaterialized(){return this.#i!==null||this.#u!==null}setProvenance(e){this.#o=e}replaceSigner(e){if(this.identityMaterialized)throw new Error("Cannot replace a materialized agent signer.");this.#r=e,this.reset()}async identity(){if(this.#i)return this.#i;if(this.#u)return this.#u;let e=this.#n,t=(async()=>{let n;try{n=await this.#r.ensure()}catch{throw this.#a()}if(e!==this.#n)throw this.#a();let i=H(n);return this.#i=i,i})();this.#u=t;try{return await t}finally{this.#u===t&&(this.#u=null)}}#a(){let e=new m("The agent signer could not complete the request.",0);return e.code="signer_error",e}async#g(e){u(e,32);let t=this.#n,n=await this.identity();if(t!==this.#n)throw this.#a();try{let i=await this.#r.signHash(e);u(i,65);let c=await je({hash:e,signature:i});if(t!==this.#n||c.toLowerCase()!==n.address.toLowerCase())throw this.#a();return i}catch{throw this.#a()}}async pairingCode(){return(await this.#h()).current()}async regeneratePairingCode(){return(await this.#h()).regenerate()}async pair(){let e=await this.pairingCode(),t=Math.floor(Date.now()/1e3),n=await this.identity(),i=`${e.code}|${t}`,c=Le(ze(i));return await this.#e.post("/v1/agents/pair",{code:e.code,publicKey:n.publicKey,timestamp:t,signature:await this.#g(c),...this.#o.client?{client:this.#o.client}:{},...this.#o.profile?{profile:this.#o.profile}:{}}),e}async mintSession(){if(this.#p)return this.#p;let e=this.#n,t=(async()=>{let n=await this.identity(),i=y(await this.#e.post("/v1/agents/session/nonce",{address:n.address}));if(u(i.nonce,32),e!==this.#n)throw this.#a();let c=await this.#g(i.nonce),s=y(await this.#e.post("/v1/agents/session",{address:n.address,nonce:i.nonce,signature:c}));if((typeof s.token!="string"||!/^ags_[a-f0-9]{64}$/.test(s.token)||typeof s.expiresAt!="string"||!Number.isFinite(Date.parse(s.expiresAt))||Date.parse(s.expiresAt)<=Date.now()||Date.parse(s.expiresAt)>Date.now()+366e4)&&a(),e!==this.#n)throw this.#a();return this.#s={token:s.token,safeUntil:Date.parse(s.expiresAt)-Me},s.token})();this.#p=t;try{return await t}finally{this.#p===t&&(this.#p=null)}}async ensureSession(){return this.#s&&this.#s.safeUntil>Date.now()?this.#s.token:this.mintSession()}async me(){return this.#t(e=>this.#e.get("/v1/agents/me",e))}async getBalance(){return this.#t(e=>this.#e.get("/v1/balance",e))}async listRequests(){return this.#t(e=>this.#e.get("/v1/agents/requests",e))}async listChains(){return this.#t(e=>this.#e.get("/v1/chains",e))}async getGasMethods(e){let t=new URLSearchParams;e.chainId!==void 0&&t.set("chainId",String(e.chainId)),e.accountId&&t.set("accountId",e.accountId),e.key&&t.set("key",e.key);let n=t.toString();return this.#t(i=>this.#e.get(`/v1/gas/methods${n?`?${n}`:""}`,i))}async getAccount(e){let t=new URLSearchParams;e.chainId!==void 0&&t.set("chainId",String(e.chainId));let n=t.toString();return this.#t(i=>this.#e.get(`/v1/account${n?`?${n}`:""}`,i))}async prepareExactAction(e,t){let n=re(e),i=ie(t,n),c=this.#n,s=await this.#t(g=>this.#e.post(`/v1/delegations/${i.delegationId}/actions/exact`,n,g),!1),o=await se(s,n,i),d;return Object.freeze({userOpHash:o.userOpHash,execution:o.execution,submit:()=>(d||(d=(async()=>{if(c!==this.#n)throw this.#a();let g=await this.ensureSession();if(c!==this.#n)throw this.#a();return M(await this.spendUnderGrant(o.userOp,o.userOpHash,i.permissionId,g,"delegated_action"),o.userOpHash)})()),d),reconcile:()=>this.getUserOpByHash(n.chainId,o.userOpHash)})}async buildDelegatedAction(e){let t={recipient:e.recipient,amount:e.amount,...e.token?{token:e.token}:{}};return this.#t(n=>this.#e.post(`/v1/delegations/${e.delegationId}/actions`,t,n),!1)}async buildDelegatedSwap(e){let t={action:"swap",tokenIn:e.tokenIn,tokenOut:e.tokenOut,amountIn:e.amountIn,...e.maxSlippageBps!=null?{maxSlippageBps:e.maxSlippageBps}:{}};return this.#t(n=>this.#e.post(`/v1/delegations/${e.delegationId}/actions`,t,n),!1)}async raiseRequest(e,t){return this.#t(n=>this.#e.post("/v1/agents/requests",{calls:e,reason:t},n),!1)}async spendUnderGrant(e,t,n,i,c){T(e),u(t,32),u(n,32);let s=await this.#g(t),o=me(["bytes1","bytes32","bytes"],["0x00",n,s]);try{return await this.#e.post("/v1/userops",{userOp:{...e,signature:o},userOpHash:t,intentType:c},i)}catch(d){throw d instanceof m&&(d.userOpHash=t),d}}async getUserOp(e){return w(e),this.#t(t=>this.#e.get(`/v1/userops/${e}`,t))}async getUserOpByHash(e,t){return(!Number.isSafeInteger(e)||e<1)&&a(),u(t,32),M(await this.#t(n=>this.#e.get(`/v1/userops/by-hash/${e}/${t}`,n)),t)}async awaitTerminal(e,t){return X(n=>this.getUserOp(n),e,t,()=>Date.now(),n=>new Promise(i=>setTimeout(i,n)))}async listApis(e){return this.#t(t=>this.#e.get(`/v1/apis/providers?chainId=${e}`,t))}async getApiProvider(e,t){let n=t!==void 0?`?chainId=${t}`:"";return this.#t(i=>this.#e.get(`/v1/apis/providers/${e}${n}`,i))}async callApi(e){let t=await this.#t(n=>this.#e.post("/v1/apis/calls/requirements",e,n),!1);return w(t?.requirementId),["ready","pending_approval"].includes(t.status)||a(),this.#l(t)}async resumeApi(e,t=fe){w(e);let n=z(await this.#t(i=>this.#e.get(`/v1/apis/calls/relay/${e}`,i)),e);return n.status==="ready"?this.#l({requirementId:e,status:"ready",...U(n.ready)},t):n.status!=="pending_approval"?n:this.#l({requirementId:e,status:"pending_approval",approvalId:e,expiresAt:""},t)}async#l(e,t=fe){let n;if(e.status==="pending_approval"){let o=await X(d=>this.#t(g=>this.#e.get(`/v1/apis/calls/requirements/${d}`,g)),e.requirementId,t,()=>Date.now(),d=>new Promise(g=>setTimeout(g,d)));if(o.status==="approved"&&o.payload&&o.authorization&&o.index!==void 0&&o.validator)n={payload:o.payload,authorization:o.authorization,index:o.index,validator:o.validator};else{let d=o.status==="declined"?"owner_declined":o.status==="expired"?"approval_timed_out":"approval_still_pending",g=d==="owner_declined"?"The owner declined this call. Nothing was signed and nothing was charged.":d==="approval_timed_out"?"The owner did not respond before the approval window closed. Nothing was signed and nothing was charged.":"The owner has not answered yet. Nothing was signed or charged. Resume this requirement or ask the owner to check their pending approvals.";return["pending","declined","expired"].includes(o.status)||a(),{status:o.status==="pending"?"pending_approval":"declined",declineReason:d,message:g,requirementId:e.requirementId,approvalId:e.status==="pending_approval"?e.approvalId:void 0}}}else n=e;n=U(n);let i=await this.identity(),c=await this.#g(n.payload),s=me(["bytes1","address","bytes"],["0x01",n.validator,Fe([{type:"address"},{type:"tuple",components:[{name:"from",type:"address"},{name:"to",type:"address"},{name:"value",type:"uint256"},{name:"validAfter",type:"uint256"},{name:"validBefore",type:"uint256"},{name:"nonce",type:"bytes32"}]},{type:"uint32"},{type:"bytes"}],[i.address,{from:n.authorization.from,to:n.authorization.to,value:BigInt(n.authorization.value),validAfter:BigInt(n.authorization.validAfter),validBefore:BigInt(n.authorization.validBefore),nonce:n.authorization.nonce},n.index,c])]);try{return z(await this.#t(o=>this.#e.post("/v1/apis/calls/relay",{requirementId:e.requirementId,signature:s},o),!1),e.requirementId)}catch(o){throw o instanceof m&&(o.requirementId=e.requirementId),o}}async getApiBudget(e){return this.#t(t=>this.#e.get(`/v1/apis/budget?chainId=${e}`,t))}reset(){this.#n+=1,this.#u=null,this.#p=null,this.#i=null,this.#d=null,this.#s=null}async#h(){if(!this.#d){let e=await this.identity();this.#d??=new _(e.fingerprint)}return this.#d}async#t(e,t=!0){let n=await this.ensureSession();try{return await e(n)}catch(i){if(t&&i instanceof m&&i.status===401){let c=this.#s&&this.#s.token!==n?await this.ensureSession():await this.mintSession();return await e(c)}throw i}}};function Ve(r,e={}){let t={address:r.address,publicKey:r.publicKey,fingerprint:K(r.address),backend:e.backend??"injected",createdAt:e.createdAt??new Date().toISOString()};return{ensure:async()=>({...t}),sign:n=>r.signMessage({message:n}),signHash:n=>r.sign({hash:n})}}import{recoverMessageAddress as Ke}from"viem";async function We(r,e,t){if(typeof t!="string"||t.trim().length<1||t.trim().length>80)throw new Error("Agent name must contain 1 to 80 characters.");let n;try{n=H(await r.ensure())}catch{throw Q()}let i=await e.app.context();w(i.appId),w(i.keyId),["test","live"].includes(i.environment)||a();let c=n.publicKey.toLowerCase(),s=n.address.toLowerCase(),o=await e.agents.challenge({publicKey:c,name:t.trim()});(!o||o.appId!==i.appId||o.environment!==i.environment||o.publicKey!==c||o.address!==s||!/^dach_[A-Za-z0-9_-]{43}$/.test(o.id)||typeof o.expiresAt!="string"||!Number.isFinite(Date.parse(o.expiresAt))||Date.parse(o.expiresAt)<=Date.now()||Date.parse(o.expiresAt)>Date.now()+36e4)&&a();let d=["Botanary agent registration","Purpose: register-agent-key","Audience: botanary:developer-platform:2026-09-07",`Application: ${i.appId}`,`Environment: ${i.environment}`,`API key: ${i.keyId}`,`Public key: ${c}`,`Address: ${s}`,`Nonce: ${o.id}`,`Expires: ${o.expiresAt}`,"This proof does not authorize an account connection or an on-chain grant."].join(`
2
- `);o.message!==d&&a();let g;try{if(g=await r.sign(d),u(g,65),(await Ke({message:d,signature:g})).toLowerCase()!==s)throw Q()}catch{throw Q()}let p=await e.agents.complete({challengeId:o.id,signature:g});return(!p||p.appId!==i.appId||p.environment!==i.environment||p.publicKey!==c||p.address!==s||p.grantStatus!=="unknown"||!["awaiting_connection","active","disabled","app_disabled","key_revoked","connection_revoked","unavailable"].includes(p.apiAccess)||p.apiAccess==="active"&&p.connectionId===null||p.apiAccess==="awaiting_connection"&&p.connectionId!==null)&&a(),p.connectionId!==null&&w(p.connectionId),p}function Q(){let r=new m("The agent signer could not complete registration.",0);return r.code="signer_error",r}export{Y as AgentRuntime,m as BotanaryApiError,ye as DEFAULT_API_BASE_URL,de as DEFAULT_PAIRING_CODE_TTL_MS,ae as FINGERPRINT_BYTES,ce as NONCE_BYTES,_ as PairingCodeManager,X as awaitTerminalWith,Ve as createViemAgentSigner,V as crockfordBase32,K as deriveFingerprint,W as generatePairingNonce,We as registerAgent};
1
+ var h=class extends Error{constructor(t,n,i=null,o=null){super(t);this.status=n;this.details=i;this.retryAfterSeconds=o;this.name="BotanaryApiError"}requestId;code;operationId;userOpHash;requirementId;ambiguous=!1};import{encodeFunctionData as E,encodePacked as ve,decodeFunctionData as F,parseAbi as U,getAddress as I,zeroAddress as Pe,zeroHash as Re}from"viem";import{entryPoint07Address as ee,getUserOperationHash as Se}from"viem/account-abstraction";import{publicKeyToAddress as Ie}from"viem/accounts";function d(){let r=new h("Botanary returned an invalid response. Nothing was signed.",0);throw r.code="invalid_response",r}function y(r){return typeof r!="object"||r===null||Array.isArray(r)?d():r}function p(r,e){(typeof r!="string"||!/^0x(?:[0-9a-fA-F]{2})*$/.test(r)||e!==void 0&&r.length!==2+2*e)&&d()}function w(r){(typeof r!="string"||!/^[A-Za-z0-9_-]{1,128}$/.test(r)||/^(?:bsk|ags|dcs|dca|dcr)_/.test(r))&&d()}function L(r){(typeof r!="string"||!/^(0|[1-9][0-9]{0,77})$/.test(r)||BigInt(r)>=2n**256n)&&d()}function H(r){let e=y(r);return p(e.address,20),p(e.publicKey,65),(!e.publicKey.startsWith("0x04")||Ie(e.publicKey).toLowerCase()!==e.address.toLowerCase()||typeof e.fingerprint!="string"||!/^[A-Za-z0-9]{1,32}$/.test(e.fingerprint)||typeof e.backend!="string"||!/^[A-Za-z0-9_-]{1,64}$/.test(e.backend)||typeof e.createdAt!="string"||!Number.isFinite(Date.parse(e.createdAt)))&&d(),Object.freeze({address:e.address,publicKey:e.publicKey,fingerprint:e.fingerprint,backend:e.backend,createdAt:e.createdAt})}function x(r,e=256){if(typeof r!="string"||!/^(0|[1-9][0-9]{0,77}|0x[0-9a-fA-F]{1,64})$/.test(r))return d();let t=BigInt(r);return t>=2n**BigInt(e)?d():t}function C(r){let e=y(r);for(let t of["sender","entryPoint"])p(e[t],20);for(let t of["nonce","callGasLimit","verificationGasLimit","preVerificationGas","maxFeePerGas","maxPriorityFeePerGas"])x(e[t]);for(let t of["callData","signature"])p(e[t]);for(let t of["paymasterVerificationGasLimit","paymasterPostOpGasLimit"])e[t]!=null&&x(e[t],128);(!Number.isSafeInteger(e.chainId)||Number(e.chainId)<=0)&&d();for(let t of["factory","paymaster"])e[t]!=null&&p(e[t],20);for(let t of["factoryData","paymasterData"])e[t]!=null&&p(e[t]);return r}function T(r){let e=y(r);p(e.payload,32),p(e.validator,20),(!Number.isSafeInteger(e.index)||Number(e.index)<0||Number(e.index)>=2**32)&&d();let t=y(e.authorization);return p(t.from,20),p(t.to,20),p(t.nonce,32),L(t.value),L(t.validAfter),L(t.validBefore),BigInt(t.validBefore)<=BigInt(t.validAfter)&&d(),{payload:e.payload,validator:e.validator,index:Number(e.index),authorization:{from:t.from,to:t.to,nonce:t.nonce,value:t.value,validAfter:t.validAfter,validBefore:t.validBefore}}}function z(r,e){let t=y(r);(t.requirementId!==e||typeof t.simulated!="boolean")&&d();let n={ready:["not_submitted"],pending_approval:["not_submitted"],submitted:["pending"],settled:["settled"],declined:["not_submitted","not_settled"]};return(typeof t.status!="string"||!Object.hasOwn(n,t.status)||!n[t.status].includes(String(t.paymentStatus)))&&d(),t.providerStatus!==void 0&&(!Number.isSafeInteger(t.providerStatus)||Number(t.providerStatus)<100||Number(t.providerStatus)>599)&&d(),t.txHash!==void 0&&p(t.txHash,32),t.status==="settled"&&p(t.txHash,32),t.status==="ready"?T(t.ready):t.ready!==void 0&&d(),t}var te=U(["function execute(bytes32 mode, bytes executionCalldata) payable"]),M=U(["function executeUnderGrant(bytes32 permissionId, address target, uint256 value, bytes callData)","function executeUnderGrantWithAllowance(bytes32 permissionId, address target, uint256 value, address token, uint256 allowance, bytes callData)"]),_e=U(["function transfer(address to, uint256 amount) returns (bool)"]),ne=U(["function swapExactIn(address tokenIn, address tokenOut, uint256 amountIn, uint256 minOut, address to) returns (uint256 amountOut)"]),Ee=BigInt("0x000100000000008bdaba73cd9815d79069c247eb4bda0000");function f(r,e){return typeof r=="string"&&r.toLowerCase()===e.toLowerCase()}function b(r,e=!0){if(typeof r!="string"||!/^(0|[1-9][0-9]{0,77})$/.test(r))return d();let t=BigInt(r);return t>=2n**256n||e&&t===0n?d():t}function re(r){let e=y(r),t=["accountId","accountAddress","chainId","action","tokenAddress","amount","recipient","tokenOutAddress","maxSlippageBps"];return Object.keys(e).some(n=>!t.includes(n))&&d(),w(e.accountId),p(e.accountAddress,20),p(e.tokenAddress,20),b(e.amount),(!Number.isSafeInteger(e.chainId)||Number(e.chainId)<=0)&&d(),e.action==="transfer"?(p(e.recipient,20),(e.tokenOutAddress!==void 0||e.maxSlippageBps!==void 0)&&d()):e.action==="swap"?(p(e.tokenOutAddress,20),(e.recipient!==void 0||e.maxSlippageBps!==void 0&&(!Number.isInteger(e.maxSlippageBps)||Number(e.maxSlippageBps)<1||Number(e.maxSlippageBps)>1e3))&&d()):d(),Object.freeze({...r,accountAddress:I(r.accountAddress),tokenAddress:I(r.tokenAddress),...r.recipient!==void 0?{recipient:I(r.recipient)}:{},...r.tokenOutAddress!==void 0?{tokenOutAddress:I(r.tokenOutAddress)}:{}})}function ie(r,e){if(w(r.delegationId),p(r.permissionId,32),p(r.executorAddress,20),b(r.maxGasCostWei),e.action==="swap"){let t=r;p(t.routerAddress,20),b(t.minAmountOut),t.verifyRoute!==void 0&&typeof t.verifyRoute!="function"&&d()}return Object.freeze({...r,executorAddress:I(r.executorAddress),...e.action==="swap"?{routerAddress:I(r.routerAddress)}:{}})}async function se(r,e,t){try{let n=y(r),i=y(n.execution),o=C(n.userOp),s=Object.freeze({...o,sender:I(o.sender),entryPoint:I(o.entryPoint)});p(n.userOpHash,32),(n.intentType!=="delegated_action"||y(n.simulation).willSucceed!==!0||i.accountId!==e.accountId||!f(i.accountAddress,e.accountAddress)||i.chainId!==e.chainId||i.action!==e.action||i.amount!==e.amount||!f(i.tokenAddress,e.tokenAddress)||i.delegationId!==t.delegationId||!f(i.permissionId,t.permissionId)||i.gasMethod!=="native"||!f(s.sender,e.accountAddress)||s.chainId!==e.chainId||!f(s.entryPoint,ee)||s.factory!=null||s.factoryData!=null||s.paymaster!=null||s.paymasterData!=null||s.paymasterVerificationGasLimit!=null||s.paymasterPostOpGasLimit!=null)&&d();let a=x(s.nonce);a>>64n!==Ee&&d();let c=x(s.callGasLimit,128),u=x(s.verificationGasLimit,128),l=x(s.preVerificationGas),k=x(s.maxFeePerGas,128),m=x(s.maxPriorityFeePerGas,128);(m>k||(c+u+l)*k>b(t.maxGasCostWei))&&d();let g=s.callData,v;if(e.action==="transfer"){(!f(i.recipient,e.recipient)||i.tokenOutAddress!==void 0||i.maxSlippageBps!==void 0)&&d();let A=f(e.tokenAddress,Pe);v=E({abi:M,functionName:"executeUnderGrant",args:[t.permissionId,A?e.recipient:e.tokenAddress,A?b(e.amount):0n,A?"0x":E({abi:_e,functionName:"transfer",args:[e.recipient,b(e.amount)]})]})}else{let A=t;(!f(i.tokenOutAddress,e.tokenOutAddress)||i.recipient!==void 0||i.maxSlippageBps!==(e.maxSlippageBps??50))&&d();let q=F({abi:te,data:g}).args[1],P=F({abi:M,data:`0x${q.slice(106)}`});P.functionName!=="executeUnderGrantWithAllowance"&&d();let S=P.args[5],_=Object.freeze({chainId:e.chainId,accountAddress:e.accountAddress,routerAddress:A.routerAddress,tokenAddress:e.tokenAddress,tokenOutAddress:e.tokenOutAddress,amount:e.amount,minAmountOut:A.minAmountOut,callData:S});if(A.verifyRoute)await A.verifyRoute(_)!==!0&&d();else{let J=F({abi:ne,data:S}),[Ae,we,xe,be,ke]=J.args;(!f(Ae,e.tokenAddress)||!f(we,e.tokenOutAddress)||xe!==b(e.amount)||be<b(A.minAmountOut)||!f(ke,e.accountAddress)||!f(E({abi:ne,functionName:"swapExactIn",args:J.args}),S))&&d()}v=E({abi:M,functionName:"executeUnderGrantWithAllowance",args:[t.permissionId,A.routerAddress,0n,e.tokenAddress,b(e.amount),S]})}let R=E({abi:te,functionName:"execute",args:[Re,ve(["address","uint256","bytes"],[t.executorAddress,0n,v])]});f(g,R)||d();let $=Se({entryPointAddress:ee,entryPointVersion:"0.7",chainId:e.chainId,userOperation:{sender:s.sender,nonce:a,callData:s.callData,callGasLimit:c,verificationGasLimit:u,preVerificationGas:l,maxFeePerGas:k,maxPriorityFeePerGas:m,signature:"0x"}});f($,n.userOpHash)||d();let G=Object.freeze({...e,delegationId:t.delegationId,permissionId:t.permissionId,gasMethod:"native",...e.action==="swap"?{maxSlippageBps:e.maxSlippageBps??50}:{}});return{userOp:Object.freeze({sender:s.sender,chainId:s.chainId,entryPoint:s.entryPoint,nonce:s.nonce,callData:s.callData,callGasLimit:s.callGasLimit,verificationGasLimit:s.verificationGasLimit,preVerificationGas:s.preVerificationGas,maxFeePerGas:s.maxFeePerGas,maxPriorityFeePerGas:s.maxPriorityFeePerGas,signature:"0x"}),userOpHash:$,execution:G}}catch{return d()}}function j(r,e){try{let t=y(r);if(w(t.id),!f(t.userOpHash,e)||!["pending","included","failed"].includes(String(t.status)))throw new Error;return t.txHash!=null&&p(t.txHash,32),t}catch{let t=new h("Botanary returned an invalid receipt. Reconcile using the original operation hash.",0);throw t.code="invalid_response",t.userOpHash=e,t.ambiguous=!0,t}}import{keccak256 as Le,toHex as ze,encodePacked as he,encodeAbiParameters as Fe}from"viem";import{randomBytes as Oe}from"node:crypto";import{hexToBytes as Be}from"viem";var ae="0123456789ABCDEFGHJKMNPQRSTVWXYZ";function W(r){let e=0,t=0,n="";for(let i of r)for(e=e<<8|i,t+=8;t>=5;)n+=ae[e>>>t-5&31],t-=5;return t>0&&(n+=ae[e<<5-t&31]),n}var oe=3,de=5;function V(r){let e=Be(r);return W(e.slice(0,oe))}function K(){return W(Oe(de))}var ce=600*1e3,O=class{#r;#e;#d;#a;#i=null;constructor(e,t){this.#r=e,this.#e=t?.ttlMs??ce,this.#d=t?.now??Date.now,this.#a=t?.nonce??K}current(){let e=this.#d();return(!this.#i||this.#i.expiresAt<=e)&&this.#c(e),this.#s()}regenerate(){return this.#c(this.#d()),this.#s()}#c(e){this.#i={nonce:this.#a(),issuedAt:e,expiresAt:e+this.#e}}#s(){let e=this.#i;if(!e)throw new Error("unreachable: no pairing code minted");return{code:`${this.#r}-${e.nonce}`,fingerprint:this.#r,nonce:e.nonce,issuedAt:new Date(e.issuedAt).toISOString(),expiresAt:new Date(e.expiresAt).toISOString()}}};import Ne from"openapi-fetch";var ue=[{method:"post",path:"/agents/pair"},{method:"post",path:"/agents/session/nonce"},{method:"post",path:"/agents/session"},{method:"get",path:"/agents/me"},{method:"get",path:"/agents/requests"},{method:"post",path:"/agents/requests"},{method:"get",path:"/balance"},{method:"get",path:"/chains"},{method:"get",path:"/gas/methods"},{method:"get",path:"/account"},{method:"post",path:"/delegations/{delegationId}/actions"},{method:"post",path:"/delegations/{delegationId}/actions/exact"},{method:"post",path:"/userops"},{method:"get",path:"/userops/{userOpId}"},{method:"get",path:"/userops/by-hash/{chainId}/{userOpHash}"},{method:"get",path:"/apis/providers"},{method:"get",path:"/apis/providers/{providerId}"},{method:"get",path:"/apis/budget"},{method:"post",path:"/apis/calls/requirements"},{method:"get",path:"/apis/calls/requirements/{id}"},{method:"post",path:"/apis/calls/relay"},{method:"get",path:"/apis/calls/relay/{id}"}];var pe="https://botanary-canonical-path.invalid",le="(?:[A-Za-z0-9\\-._~!$&'()*+,;=:@]|%[0-9A-Fa-f]{2})",ut=`${le}+`,He=new RegExp(`^${le}+$`),Ce=new RegExp("^(?:[A-Za-z0-9\\-._~!$&'()*+,;=:@/?]|%[0-9A-Fa-f]{2})*$"),Te=/^\.{1,2}$/,Ue=/[/\\#?]/,De=/[\u0000-\u001f\u007f]/,$e=6;function Ge(r){let e=r;for(let t=0;t<$e;t+=1){if(Te.test(e)||Ue.test(e)||De.test(e))return!0;if(!e.includes("%"))return!1;let n;try{n=decodeURIComponent(e)}catch{return!0}if(n===e)return!1;e=n}return!0}function ge(r){if(typeof r!="string"||r.length===0||!r.startsWith("/")||r.startsWith("//"))return null;let e=r.indexOf("?"),t=e===-1?r:r.slice(0,e),n=e===-1?"":r.slice(e),i=t.split("/");for(let s=1;s<i.length;s+=1){let a=i[s];if(!He.test(a)||Ge(a))return null}if(n!==""&&!Ce.test(n.slice(1)))return null;let o;try{o=new URL(t+n,pe)}catch{return null}return o.origin!==pe||o.hash!==""||o.pathname!==t||o.search!==n?null:{path:t,query:n,full:t+n}}var D=class{#r;constructor(e,t=fetch){let n=new URL(e);if(n.username||n.password||n.search||n.hash||n.pathname!=="/"||n.protocol!=="https:"&&!(n.protocol==="http:"&&["localhost","127.0.0.1","[::1]"].includes(n.hostname)))throw new Error("Agent API origin must be HTTPS, or HTTP on loopback.");this.#r=Ne({baseUrl:n.origin+"/v1",fetch:qe(t)})}get(e,t){return this.#e("get",e,void 0,t)}post(e,t,n){return this.#e("post",e,t,n)}async#e(e,t,n,i){let o=ge(t);if(!o?.path.startsWith("/v1/"))throw new Error("Invalid agent API path.");if(i!==void 0&&!/^ags_[a-f0-9]{64}$/.test(i))throw new Error("Expected an agent session credential.");let s=o.path.slice(3),a=ue.find(m=>m.method===e&&new RegExp("^"+m.path.replace(/\{[^}]+\}/g,"[A-Za-z0-9_-]+")+"$").test(s));if(!a)throw new Error("This route is outside the reviewed agent API.");let c={};a.path.split("/").forEach((m,g)=>{m.startsWith("{")&&(c[m.slice(1,-1)]=s.split("/")[g])});let u=Object.fromEntries(new URLSearchParams(o.query)),l=new AbortController,k=setTimeout(()=>l.abort(),3e4);try{let m=await this.#r.request(e,a.path,{params:{path:c,query:u},...n===void 0?{}:{body:n},headers:i?{authorization:`Bearer ${i}`}:{},credentials:"omit",redirect:"error",cache:"no-store",signal:l.signal,parseAs:"text"}),g=m.response,v=m.error;if(g.ok)try{v=m.data?JSON.parse(m.data):{}}catch{throw new Error("Invalid JSON response.")}if(!g.ok){let R=Z(Z(v)?.error),G=(typeof R?.message=="string"?R.message:`Agent request failed with ${g.status}.`).replace(/(?:bsk_(?:test|live)|ags|dcs|dca|dcr)_[A-Za-z0-9_-]+/g,"[redacted]").replace(/0x[a-fA-F0-9]{64,}/g,"[redacted]"),B=g.headers.get("retry-after"),A=B&&/^\d+(?:\.\d+)?$/.test(B)?Number(B):null,N=Z(R?.details),q=N&&Object.fromEntries(Object.entries(N).filter(([S,_])=>["missingModule","declineReason","chainId"].includes(S)&&(typeof _=="number"||typeof _=="string"&&/^[a-zA-Z0-9_-]{1,100}$/.test(_)))),P=new h(G.slice(0,1e3),g.status,q,A);throw P.requestId=me(g.headers.get("x-request-id")),P.code=me(R?.code)??"http_error",P.ambiguous=e==="post"&&g.status>=500,P}return v}catch(m){if(m instanceof h)throw m;let g=new h("The agent request did not complete. Check the existing operation before retrying.",0);throw g.code=l.signal.aborted?"timeout":"transport_error",g.ambiguous=e==="post",g}finally{clearTimeout(k)}}};function Z(r){return typeof r=="object"&&r!==null&&!Array.isArray(r)?r:null}function me(r){return typeof r=="string"&&/^[a-zA-Z0-9_-]{1,128}$/.test(r)&&!/^(?:ags|bsk|dcs|dca|dcr)_/.test(r)?r:void 0}function qe(r){return async(e,t)=>{let n=e instanceof Request?e:new Request(e,t),i=n.signal,o=()=>{},s=new Promise((c,u)=>{o=()=>u(new Error("Request aborted.")),i.aborted?o():i.addEventListener("abort",o,{once:!0})}),a;try{let c=await Promise.race([r(n),s]);if(!c.body)return c;a=c.body.getReader();let u=[],l=0;for(;;){let g=await Promise.race([a.read(),s]);if(g.done)break;if(l+=g.value.byteLength,l>4*1024*1024)throw new Error("Response too large.");u.push(g.value)}let k=new Uint8Array(l),m=0;for(let g of u)k.set(g,m),m+=g.byteLength;return new Response(k,{status:c.status,statusText:c.statusText,headers:c.headers})}finally{i.removeEventListener("abort",o),a&&a.cancel().catch(()=>{})}}}import{recoverAddress as Me}from"viem";async function X(r,e,t,n,i){if(!Number.isFinite(t)||t<0||t>36e5)throw new Error("Invalid wait budget.");let o=n(),s=await r(e);for(;["pending","pending_approval","submitted","queued"].includes(String(s.status))&&n()-o<t;)await i(1500),s=await r(e);return s}var je=3e4,fe=300*1e3,ye="https://api.app.botanary.xyz",Y=class{#r;#e;#d;#a;#i=null;#c=null;#s=null;#u=null;#p=null;#n=0;#g;constructor(e,t={}){if(this.#r=e,this.#d=t.baseUrl??ye,this.#e=t.transport??new D(this.#d,t.fetch),this.#a=t.provenance??{},t.maxGasCostWei!==void 0&&(!/^[1-9][0-9]{0,77}$/.test(t.maxGasCostWei)||BigInt(t.maxGasCostWei)>=2n**256n))throw new Error("Use a positive integer agent gas ceiling in wei.");this.#g=t.maxGasCostWei??null}get apiBaseUrl(){return this.#d}get identityMaterialized(){return this.#i!==null||this.#u!==null}setProvenance(e){this.#a=e}replaceSigner(e){if(this.identityMaterialized)throw new Error("Cannot replace a materialized agent signer.");this.#r=e,this.reset()}async identity(){if(this.#i)return this.#i;if(this.#u)return this.#u;let e=this.#n,t=(async()=>{let n;try{n=await this.#r.ensure()}catch{throw this.#o()}if(e!==this.#n)throw this.#o();let i=H(n);return this.#i=i,i})();this.#u=t;try{return await t}finally{this.#u===t&&(this.#u=null)}}#o(){let e=new h("The agent signer could not complete the request.",0);return e.code="signer_error",e}async#l(e){p(e,32);let t=this.#n,n=await this.identity();if(t!==this.#n)throw this.#o();try{let i=await this.#r.signHash(e);p(i,65);let o=await Me({hash:e,signature:i});if(t!==this.#n||o.toLowerCase()!==n.address.toLowerCase())throw this.#o();return i}catch{throw this.#o()}}async pairingCode(){return(await this.#h()).current()}async regeneratePairingCode(){return(await this.#h()).regenerate()}async pair(){let e=await this.pairingCode(),t=Math.floor(Date.now()/1e3),n=await this.identity(),i=`${e.code}|${t}`,o=Le(ze(i));return await this.#e.post("/v1/agents/pair",{code:e.code,publicKey:n.publicKey,timestamp:t,signature:await this.#l(o),...this.#a.client?{client:this.#a.client}:{},...this.#a.profile?{profile:this.#a.profile}:{}}),e}async mintSession(){if(this.#p)return this.#p;let e=this.#n,t=(async()=>{let n=await this.identity(),i=y(await this.#e.post("/v1/agents/session/nonce",{address:n.address}));if(p(i.nonce,32),e!==this.#n)throw this.#o();let o=await this.#l(i.nonce),s=y(await this.#e.post("/v1/agents/session",{address:n.address,nonce:i.nonce,signature:o}));if((typeof s.token!="string"||!/^ags_[a-f0-9]{64}$/.test(s.token)||typeof s.expiresAt!="string"||!Number.isFinite(Date.parse(s.expiresAt))||Date.parse(s.expiresAt)<=Date.now()||Date.parse(s.expiresAt)>Date.now()+366e4)&&d(),e!==this.#n)throw this.#o();return this.#s={token:s.token,safeUntil:Date.parse(s.expiresAt)-je},s.token})();this.#p=t;try{return await t}finally{this.#p===t&&(this.#p=null)}}async ensureSession(){return this.#s&&this.#s.safeUntil>Date.now()?this.#s.token:this.mintSession()}async me(){return this.#t(e=>this.#e.get("/v1/agents/me",e))}async getBalance(){return this.#t(e=>this.#e.get("/v1/balance",e))}async listRequests(){return this.#t(e=>this.#e.get("/v1/agents/requests",e))}async listChains(){return this.#t(e=>this.#e.get("/v1/chains",e))}async getGasMethods(e){let t=new URLSearchParams;e.chainId!==void 0&&t.set("chainId",String(e.chainId)),e.accountId&&t.set("accountId",e.accountId),e.key&&t.set("key",e.key);let n=t.toString();return this.#t(i=>this.#e.get(`/v1/gas/methods${n?`?${n}`:""}`,i))}async getAccount(e){let t=new URLSearchParams;e.chainId!==void 0&&t.set("chainId",String(e.chainId));let n=t.toString();return this.#t(i=>this.#e.get(`/v1/account${n?`?${n}`:""}`,i))}async prepareExactAction(e,t){let n=re(e),i=ie(t,n),o=this.#n,s=await this.#t(u=>this.#e.post(`/v1/delegations/${i.delegationId}/actions/exact`,n,u),!1),a=await se(s,n,i),c;return Object.freeze({status:"prepared",userOpHash:a.userOpHash,execution:a.execution,submit:()=>(c||(c=(async()=>{if(o!==this.#n)throw this.#o();let u=await this.ensureSession();if(o!==this.#n)throw this.#o();return j(await this.spendUnderGrant(a.userOp,a.userOpHash,i.permissionId,u,"delegated_action"),a.userOpHash)})()),c),reconcile:()=>this.getUserOpByHash(n.chainId,a.userOpHash)})}async prepareAction(e){let{mandate:t,action:n}=structuredClone(e),i=/^[1-9][0-9]{0,77}$/.test(n.amountRaw)?BigInt(n.amountRaw):0n,o=t.policy.perActionMaxRaw&&/^[1-9][0-9]{0,77}$/.test(t.policy.perActionMaxRaw)?BigInt(t.policy.perActionMaxRaw):null,s=t.chainState.remaining?.find(u=>u.token.toLowerCase()===n.tokenAddress.toLowerCase())?.remainingRaw??null,a=u=>Object.freeze({status:"refused",reason:u,transactionSubmitted:!1,requestedAmountRaw:n.amountRaw,perActionMaxRaw:t.policy.perActionMaxRaw,remainingRaw:s});if(t.chainId!==84532||t.createStatus!=="confirmed"||t.chainState.status!=="active"||t.apiAccess!=="active")return a(t.revokeStatus==="confirmed"||t.chainState.status==="revoked"?"mandate_revoked":Date.parse(t.policy.expiresAt)<=Date.now()?"mandate_expired":"mandate_inactive");if(i===0n||!t.policy.budgets.some(u=>u.token.toLowerCase()===n.tokenAddress.toLowerCase()))return a("mandate_inactive");if(o!==null&&i>o)return a("over_per_action_max");if(!t.policy.recipients.some(u=>u.toLowerCase()===n.recipient.toLowerCase()))return a("wrong_recipient");if((await this.identity()).address.toLowerCase()!==t.agentAddress.toLowerCase())return a("mandate_inactive");if(!this.#g)throw new Error("Configure maxGasCostWei before preparing mandate actions.");return this.prepareExactAction({accountId:t.accountId,accountAddress:t.accountAddress,chainId:84532,action:"transfer",tokenAddress:n.tokenAddress,recipient:n.recipient,amount:n.amountRaw},{delegationId:t.id,permissionId:t.permissionId,executorAddress:t.grantExecutor,maxGasCostWei:this.#g})}async buildDelegatedAction(e){let t={recipient:e.recipient,amount:e.amount,...e.token?{token:e.token}:{}};return this.#t(n=>this.#e.post(`/v1/delegations/${e.delegationId}/actions`,t,n),!1)}async buildDelegatedSwap(e){let t={action:"swap",tokenIn:e.tokenIn,tokenOut:e.tokenOut,amountIn:e.amountIn,...e.maxSlippageBps!=null?{maxSlippageBps:e.maxSlippageBps}:{}};return this.#t(n=>this.#e.post(`/v1/delegations/${e.delegationId}/actions`,t,n),!1)}async raiseRequest(e,t){return this.#t(n=>this.#e.post("/v1/agents/requests",{calls:e,reason:t},n),!1)}async spendUnderGrant(e,t,n,i,o){C(e),p(t,32),p(n,32);let s=await this.#l(t),a=he(["bytes1","bytes32","bytes"],["0x00",n,s]);try{return await this.#e.post("/v1/userops",{userOp:{...e,signature:a},userOpHash:t,intentType:o},i)}catch(c){throw c instanceof h&&(c.userOpHash=t),c}}async getUserOp(e){return w(e),this.#t(t=>this.#e.get(`/v1/userops/${e}`,t))}async getUserOpByHash(e,t){return(!Number.isSafeInteger(e)||e<1)&&d(),p(t,32),j(await this.#t(n=>this.#e.get(`/v1/userops/by-hash/${e}/${t}`,n)),t)}async awaitTerminal(e,t){return X(n=>this.getUserOp(n),e,t,()=>Date.now(),n=>new Promise(i=>setTimeout(i,n)))}async listApis(e){return this.#t(t=>this.#e.get(`/v1/apis/providers?chainId=${e}`,t))}async getApiProvider(e,t){let n=t!==void 0?`?chainId=${t}`:"";return this.#t(i=>this.#e.get(`/v1/apis/providers/${e}${n}`,i))}async callApi(e){let t=await this.#t(n=>this.#e.post("/v1/apis/calls/requirements",e,n),!1);return w(t?.requirementId),["ready","pending_approval"].includes(t.status)||d(),this.#m(t)}async resumeApi(e,t=fe){w(e);let n=z(await this.#t(i=>this.#e.get(`/v1/apis/calls/relay/${e}`,i)),e);return n.status==="ready"?this.#m({requirementId:e,status:"ready",...T(n.ready)},t):n.status!=="pending_approval"?n:this.#m({requirementId:e,status:"pending_approval",approvalId:e,expiresAt:""},t)}async#m(e,t=fe){let n;if(e.status==="pending_approval"){let a=await X(c=>this.#t(u=>this.#e.get(`/v1/apis/calls/requirements/${c}`,u)),e.requirementId,t,()=>Date.now(),c=>new Promise(u=>setTimeout(u,c)));if(a.status==="approved"&&a.payload&&a.authorization&&a.index!==void 0&&a.validator)n={payload:a.payload,authorization:a.authorization,index:a.index,validator:a.validator};else{let c=a.status==="declined"?"owner_declined":a.status==="expired"?"approval_timed_out":"approval_still_pending",u=c==="owner_declined"?"The owner declined this call. Nothing was signed and nothing was charged.":c==="approval_timed_out"?"The owner did not respond before the approval window closed. Nothing was signed and nothing was charged.":"The owner has not answered yet. Nothing was signed or charged. Resume this requirement or ask the owner to check their pending approvals.";return["pending","declined","expired"].includes(a.status)||d(),{status:a.status==="pending"?"pending_approval":"declined",declineReason:c,message:u,requirementId:e.requirementId,approvalId:e.status==="pending_approval"?e.approvalId:void 0}}}else n=e;n=T(n);let i=await this.identity(),o=await this.#l(n.payload),s=he(["bytes1","address","bytes"],["0x01",n.validator,Fe([{type:"address"},{type:"tuple",components:[{name:"from",type:"address"},{name:"to",type:"address"},{name:"value",type:"uint256"},{name:"validAfter",type:"uint256"},{name:"validBefore",type:"uint256"},{name:"nonce",type:"bytes32"}]},{type:"uint32"},{type:"bytes"}],[i.address,{from:n.authorization.from,to:n.authorization.to,value:BigInt(n.authorization.value),validAfter:BigInt(n.authorization.validAfter),validBefore:BigInt(n.authorization.validBefore),nonce:n.authorization.nonce},n.index,o])]);try{return z(await this.#t(a=>this.#e.post("/v1/apis/calls/relay",{requirementId:e.requirementId,signature:s},a),!1),e.requirementId)}catch(a){throw a instanceof h&&(a.requirementId=e.requirementId),a}}async getApiBudget(e){return this.#t(t=>this.#e.get(`/v1/apis/budget?chainId=${e}`,t))}reset(){this.#n+=1,this.#u=null,this.#p=null,this.#i=null,this.#c=null,this.#s=null}async#h(){if(!this.#c){let e=await this.identity();this.#c??=new O(e.fingerprint)}return this.#c}async#t(e,t=!0){let n=await this.ensureSession();try{return await e(n)}catch(i){if(t&&i instanceof h&&i.status===401){let o=this.#s&&this.#s.token!==n?await this.ensureSession():await this.mintSession();return await e(o)}throw i}}};function We(r,e={}){let t={address:r.address,publicKey:r.publicKey,fingerprint:V(r.address),backend:e.backend??"injected",createdAt:e.createdAt??new Date().toISOString()};return{ensure:async()=>({...t}),sign:n=>r.signMessage({message:n}),signHash:n=>r.sign({hash:n})}}import{recoverMessageAddress as Ve}from"viem";async function Ke(r,e,t){if(typeof t!="string"||t.trim().length<1||t.trim().length>80)throw new Error("Agent name must contain 1 to 80 characters.");let n;try{n=H(await r.ensure())}catch{throw Q()}let i=await e.app.context();w(i.appId),w(i.keyId),["test","live"].includes(i.environment)||d();let o=n.publicKey.toLowerCase(),s=n.address.toLowerCase(),a=await e.agents.challenge({publicKey:o,name:t.trim()});(!a||a.appId!==i.appId||a.environment!==i.environment||a.publicKey!==o||a.address!==s||!/^dach_[A-Za-z0-9_-]{43}$/.test(a.id)||typeof a.expiresAt!="string"||!Number.isFinite(Date.parse(a.expiresAt))||Date.parse(a.expiresAt)<=Date.now()||Date.parse(a.expiresAt)>Date.now()+36e4)&&d();let c=["Botanary agent registration","Purpose: register-agent-key","Audience: botanary:developer-platform:2026-09-07",`Application: ${i.appId}`,`Environment: ${i.environment}`,`API key: ${i.keyId}`,`Public key: ${o}`,`Address: ${s}`,`Nonce: ${a.id}`,`Expires: ${a.expiresAt}`,"This proof does not authorize an account connection or an on-chain grant."].join(`
2
+ `);a.message!==c&&d();let u;try{if(u=await r.sign(c),p(u,65),(await Ve({message:c,signature:u})).toLowerCase()!==s)throw Q()}catch{throw Q()}let l=await e.agents.complete({challengeId:a.id,signature:u});return(!l||l.appId!==i.appId||l.environment!==i.environment||l.publicKey!==o||l.address!==s||l.grantStatus!=="unknown"||!["awaiting_connection","active","disabled","app_disabled","key_revoked","connection_revoked","unavailable"].includes(l.apiAccess)||l.apiAccess==="active"&&l.connectionId===null||l.apiAccess==="awaiting_connection"&&l.connectionId!==null)&&d(),l.connectionId!==null&&w(l.connectionId),l}function Q(){let r=new h("The agent signer could not complete registration.",0);return r.code="signer_error",r}export{Y as AgentRuntime,h as BotanaryApiError,ye as DEFAULT_API_BASE_URL,ce as DEFAULT_PAIRING_CODE_TTL_MS,oe as FINGERPRINT_BYTES,de as NONCE_BYTES,O as PairingCodeManager,X as awaitTerminalWith,We as createViemAgentSigner,W as crockfordBase32,V as deriveFingerprint,K as generatePairingNonce,Ke as registerAgent};
package/dist/runtime.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { type ExactAgentAction, type AgentActionBinding, type AgentSwapBinding, type PreparedAgentAction } from './exact-action.js';
1
+ import { type ExactAgentAction, type AgentActionBinding, type AgentSwapBinding, type PreparedAgentAction, type MandateTransferInput, type AgentPolicyRefusal } from './exact-action.js';
2
2
  import { type Hex } from 'viem';
3
3
  import { type PairingCode } from './pairing-code.js';
4
4
  import { type AgentTransport } from './transport.js';
@@ -16,6 +16,7 @@ export declare class AgentRuntime {
16
16
  client?: string;
17
17
  profile?: string;
18
18
  };
19
+ maxGasCostWei?: string;
19
20
  });
20
21
  get apiBaseUrl(): string;
21
22
  protected get identityMaterialized(): boolean;
@@ -43,6 +44,7 @@ export declare class AgentRuntime {
43
44
  chainId?: number;
44
45
  }): Promise<unknown>;
45
46
  prepareExactAction(input: ExactAgentAction, binding: AgentActionBinding | AgentSwapBinding): Promise<PreparedAgentAction>;
47
+ prepareAction(input: MandateTransferInput): Promise<PreparedAgentAction | AgentPolicyRefusal>;
46
48
  buildDelegatedAction(params: {
47
49
  delegationId: string;
48
50
  recipient: string;
package/package.json CHANGED
@@ -1,13 +1,12 @@
1
1
  {
2
2
  "name": "@botanary/agent",
3
- "version": "0.1.0-alpha.2",
3
+ "version": "0.1.0-alpha.4",
4
4
  "description": "Botanary agent session and execution runtime with an injected signer",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
7
  "engines": {
8
8
  "node": ">=22"
9
9
  },
10
- "packageManager": "pnpm@11.5.1",
11
10
  "sideEffects": false,
12
11
  "files": [
13
12
  "dist",
@@ -24,18 +23,6 @@
24
23
  "types": "./dist/generated/schema.d.ts"
25
24
  }
26
25
  },
27
- "scripts": {
28
- "generate": "node scripts/generate.mjs",
29
- "check:generated": "node scripts/generate.mjs --check",
30
- "check:inventory": "node ../protected-boundary/check-inventory.mjs agent",
31
- "typecheck": "tsc --noEmit",
32
- "build": "node ../protected-boundary/release-build.mjs agent",
33
- "build:tsc": "tsc",
34
- "audit:artifact": "node ../protected-boundary/audit-artifact.mjs agent",
35
- "test": "vitest run",
36
- "prepack": "pnpm check:generated && pnpm typecheck && pnpm build",
37
- "test:packed": "node scripts/verify-packed.mjs"
38
- },
39
26
  "dependencies": {
40
27
  "openapi-fetch": "0.17.0",
41
28
  "viem": "2.54.6"
@@ -50,5 +37,16 @@
50
37
  },
51
38
  "publishConfig": {
52
39
  "access": "public"
40
+ },
41
+ "scripts": {
42
+ "generate": "node scripts/generate.mjs",
43
+ "check:generated": "node scripts/generate.mjs --check",
44
+ "check:inventory": "node ../protected-boundary/check-inventory.mjs agent",
45
+ "typecheck": "tsc --noEmit",
46
+ "build": "node ../protected-boundary/release-build.mjs agent",
47
+ "build:tsc": "tsc",
48
+ "audit:artifact": "node ../protected-boundary/audit-artifact.mjs agent",
49
+ "test": "vitest run",
50
+ "test:packed": "node scripts/verify-packed.mjs"
53
51
  }
54
- }
52
+ }