@botanary/agent 0.1.0-alpha.1 → 0.1.0-alpha.11
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 +36 -0
- package/README.md +43 -5
- package/dist/errors.d.ts +1 -38
- package/dist/exact-action.d.ts +47 -8
- package/dist/fingerprint.d.ts +0 -15
- package/dist/generated/routes.d.ts +0 -1
- package/dist/generated/schema.d.ts +8 -1092
- package/dist/http-path.d.ts +0 -81
- package/dist/index.d.ts +1 -2
- package/dist/index.js +2 -7
- package/dist/pairing-code.d.ts +0 -23
- package/dist/registration.d.ts +0 -3
- package/dist/runtime.d.ts +3 -128
- package/dist/signer.d.ts +0 -7
- package/dist/transport.d.ts +0 -3
- package/dist/validation.d.ts +4 -3
- package/dist/views.d.ts +0 -54
- package/package.json +6 -2
- package/dist/errors.d.ts.map +0 -1
- package/dist/errors.js +0 -40
- package/dist/errors.js.map +0 -1
- package/dist/exact-action.d.ts.map +0 -1
- package/dist/exact-action.js +0 -178
- package/dist/exact-action.js.map +0 -1
- package/dist/fingerprint.d.ts.map +0 -1
- package/dist/fingerprint.js +0 -47
- package/dist/fingerprint.js.map +0 -1
- package/dist/generated/routes.d.ts.map +0 -1
- package/dist/generated/routes.js +0 -92
- package/dist/generated/routes.js.map +0 -1
- package/dist/generated/schema.d.ts.map +0 -1
- package/dist/generated/schema.js +0 -2
- package/dist/generated/schema.js.map +0 -1
- package/dist/http-path.d.ts.map +0 -1
- package/dist/http-path.js +0 -201
- package/dist/http-path.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/pairing-code.d.ts.map +0 -1
- package/dist/pairing-code.js +0 -60
- package/dist/pairing-code.js.map +0 -1
- package/dist/registration.d.ts.map +0 -1
- package/dist/registration.js +0 -62
- package/dist/registration.js.map +0 -1
- package/dist/runtime.d.ts.map +0 -1
- package/dist/runtime.js +0 -559
- package/dist/runtime.js.map +0 -1
- package/dist/signer.d.ts.map +0 -1
- package/dist/signer.js +0 -13
- package/dist/signer.js.map +0 -1
- package/dist/transport.d.ts.map +0 -1
- package/dist/transport.js +0 -135
- package/dist/transport.js.map +0 -1
- package/dist/validation.d.ts.map +0 -1
- package/dist/validation.js +0 -108
- package/dist/validation.js.map +0 -1
- package/dist/views.d.ts.map +0 -1
- package/dist/views.js +0 -2
- package/dist/views.js.map +0 -1
package/dist/http-path.d.ts
CHANGED
|
@@ -1,92 +1,11 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ONE PARSE. The string that is validated is the string that is requested.
|
|
3
|
-
*
|
|
4
|
-
* ------------------------------------------------------------------------------------------------
|
|
5
|
-
* THE BUG THIS EXISTS TO CLOSE
|
|
6
|
-
* ------------------------------------------------------------------------------------------------
|
|
7
|
-
* `wallet_api_get` and `wallet_api_write` both take a free-form, model-supplied `path` and check it
|
|
8
|
-
* against a generated manifest by compiling each manifest template into a regex, with a `{param}`
|
|
9
|
-
* segment becoming `[^/]+`. The compiled string was then re-assembled and handed to `fetch`, whose
|
|
10
|
-
* WHATWG URL parser re-parses it - and that parser does NOT agree with `[^/]+` about what a path
|
|
11
|
-
* segment is. It normalises `\` to `/`, resolves `.` and `..` (including their percent-encoded forms
|
|
12
|
-
* `%2e` / `%2e%2e`), and truncates everything from the first `#`. So:
|
|
13
|
-
*
|
|
14
|
-
* isKnownWritePath('/notifications/..\\userops#/read', 'POST') -> true
|
|
15
|
-
* ...and the request actually issued was POST /v1/userops
|
|
16
|
-
*
|
|
17
|
-
* Two different strings: the one the allowlist inspected, and the one that went on the wire. Every
|
|
18
|
-
* denylist entry in both manifests - the `/userops` relay boundary, `/approvals/{digest}/relay`,
|
|
19
|
-
* `/solana/transactions`, `/agent-wallets/partner-provision`, and on the read side `/auth/session`,
|
|
20
|
-
* which hands back the owner's live session token - was reachable through that gap.
|
|
21
|
-
*
|
|
22
|
-
* ------------------------------------------------------------------------------------------------
|
|
23
|
-
* WHY THIS CLOSES THE CLASS RATHER THAN THE INSTANCES
|
|
24
|
-
* ------------------------------------------------------------------------------------------------
|
|
25
|
-
* Blocklisting the tokens (`..`, `\`, `#`) loses: there is always another encoding (`%2e%2e`, `%5c`,
|
|
26
|
-
* `%23`, `%252e%252e`, and whatever the next parser quirk turns out to be). The root cause is not any
|
|
27
|
-
* particular character - it is that VALIDATION AND REQUEST OPERATED ON DIFFERENT STRINGS. So this
|
|
28
|
-
* module removes the difference instead of enumerating it:
|
|
29
|
-
*
|
|
30
|
-
* 1. The caller's path is canonicalised ONCE, up front, before anything looks at a manifest.
|
|
31
|
-
* 2. Canonicalisation is a FIXED-POINT test against the very parser `fetch` uses: the path is
|
|
32
|
-
* re-parsed with `new URL(...)`, and if `pathname + search` is not byte-identical to the input,
|
|
33
|
-
* the path is refused. Anything the URL parser would rewrite - a traversal in any encoding, a
|
|
34
|
-
* backslash, a fragment, a character it would percent-encode, a `//` that changes the host - is
|
|
35
|
-
* by definition not a fixed point, and is rejected without this module ever having to know that
|
|
36
|
-
* particular trick's name.
|
|
37
|
-
* 3. A structural charset allowlist runs first, per segment, so the fixed-point test is a second
|
|
38
|
-
* opinion rather than the only one: a segment may contain only unreserved/sub-delim characters
|
|
39
|
-
* and well-formed `%XX` triplets, and must not decode - through as many layers of encoding as it
|
|
40
|
-
* carries - to a separator, a fragment marker, or `.`/`..`.
|
|
41
|
-
* 4. The single canonical result is what the caller then matches AND requests. There is no second
|
|
42
|
-
* re-assembly step for the two to drift apart in.
|
|
43
|
-
*
|
|
44
|
-
* The `{param}` compilation is tightened to match: `PARAM_SEGMENT_PATTERN` is the same charset, so a
|
|
45
|
-
* parameter structurally cannot hold a separator or a fragment marker even before rule 2 speaks.
|
|
46
|
-
*/
|
|
47
|
-
/**
|
|
48
|
-
* What a `{param}` in a manifest template compiles to. The old `[^/]+` was the bug: to a regex, `\`,
|
|
49
|
-
* `#` and `..` are ordinary characters, and to the URL parser they are separators. This charset holds
|
|
50
|
-
* no separator and no fragment marker in any form the URL parser recognises.
|
|
51
|
-
*/
|
|
52
1
|
export declare const PARAM_SEGMENT_PATTERN = "(?:[A-Za-z0-9\\-._~!$&'()*+,;=:@]|%[0-9A-Fa-f]{2})+";
|
|
53
|
-
/** The canonical form of a caller-supplied path: one object, carried from validation to `fetch`. */
|
|
54
2
|
export interface CanonicalHttpPath {
|
|
55
|
-
/** The path, no query string. Byte-identical to what will be requested. */
|
|
56
3
|
readonly path: string;
|
|
57
|
-
/** The query string including its leading `?`, or `''`. Byte-identical to what will be requested. */
|
|
58
4
|
readonly query: string;
|
|
59
|
-
/** `path + query` - exactly the string that goes on the wire after the base URL. */
|
|
60
5
|
readonly full: string;
|
|
61
6
|
}
|
|
62
|
-
/**
|
|
63
|
-
* Canonicalise a caller-supplied request path, or return null if it is not canonical.
|
|
64
|
-
*
|
|
65
|
-
* "Canonical" means: an absolute path (never protocol-relative, which would change the HOST), every
|
|
66
|
-
* segment drawn from the safe charset and free of any encoded separator or traversal, an optional
|
|
67
|
-
* query drawn from its own charset, no fragment at all - and, as the final word, a string the WHATWG
|
|
68
|
-
* URL parser reproduces unchanged. Callers must use the returned strings, never their own input.
|
|
69
|
-
*/
|
|
70
7
|
export declare function canonicalizeHttpPath(raw: unknown): CanonicalHttpPath | null;
|
|
71
|
-
/**
|
|
72
|
-
* Strip the `/v1` prefix, if present, so `/balance` and `/v1/balance` resolve to the same manifest
|
|
73
|
-
* entry. The OpenAPI contract declares paths WITHOUT the version prefix (`/v1` lives in
|
|
74
|
-
* `servers[].url`), so the generated manifests are un-prefixed - this is where the two conventions
|
|
75
|
-
* meet. Operates on an ALREADY-CANONICAL path; the old code did this to the raw input, which is how a
|
|
76
|
-
* `/v1`-prefixed bypass got a second bite.
|
|
77
|
-
*/
|
|
78
8
|
export declare function stripVersionPrefix(canonicalPath: string): string;
|
|
79
|
-
/**
|
|
80
|
-
* Compile one manifest template (`/agents/{id}`) into a matcher for a concrete canonical path
|
|
81
|
-
* (`/agents/agt_1`). Shared by both allowlists so they cannot drift into two different ideas of what a
|
|
82
|
-
* path parameter may contain - which is how one of them ends up with the other's hole.
|
|
83
|
-
*/
|
|
84
9
|
export declare function compileRoutePattern(template: string): RegExp;
|
|
85
|
-
/** Cap what a refusal echoes back, so a pathological input cannot flood a tool result. */
|
|
86
10
|
export declare function describePath(raw: unknown): string;
|
|
87
|
-
/**
|
|
88
|
-
* The refusal text every caller shares, so the reason a path was rejected reads the same wherever it
|
|
89
|
-
* is rejected - and names the real cause rather than the character that happened to trip it.
|
|
90
|
-
*/
|
|
91
11
|
export declare function nonCanonicalPathMessage(raw: unknown, tool: string): string;
|
|
92
|
-
//# sourceMappingURL=http-path.d.ts.map
|
package/dist/index.d.ts
CHANGED
|
@@ -7,5 +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';
|
|
11
|
-
//# sourceMappingURL=index.d.ts.map
|
|
10
|
+
export type { ExactAgentAction, ExactAgentExecution, AgentActionBinding, AgentSwapBinding, SwapRouteFacts, PreparedAgentAction, AgentMandateProjection, MandateTransferInput, AgentPolicyRefusal } from './exact-action.js';
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,2 @@
|
|
|
1
|
-
export { AgentRuntime, awaitTerminalWith, DEFAULT_API_BASE_URL } from './runtime.js';
|
|
2
|
-
|
|
3
|
-
export { createViemAgentSigner } from './signer.js';
|
|
4
|
-
export { registerAgent } from './registration.js';
|
|
5
|
-
export { PairingCodeManager, DEFAULT_PAIRING_CODE_TTL_MS } from './pairing-code.js';
|
|
6
|
-
export { crockfordBase32, deriveFingerprint, generatePairingNonce, FINGERPRINT_BYTES, NONCE_BYTES } from './fingerprint.js';
|
|
7
|
-
//# sourceMappingURL=index.js.map
|
|
1
|
+
var h=class extends Error{constructor(t,n,i=null,d=null){super(t);this.status=n;this.details=i;this.retryAfterSeconds=d;this.name="BotanaryApiError"}requestId;code;operationId;userOpHash;requirementId;ambiguous=!1};import{encodeFunctionData as O,encodePacked as Oe,decodeFunctionData as j,parseAbi as D,getAddress as v,zeroAddress as Be,zeroHash as Te}from"viem";import{entryPoint07Address as oe,getUserOperationHash as He}from"viem/account-abstraction";import{publicKeyToAddress as _e}from"viem/accounts";function a(){let r=new h("Botanary returned an invalid response. Nothing was signed.",0);throw r.code="invalid_response",r}function m(r){return typeof r!="object"||r===null||Array.isArray(r)?a():r}function c(r,e){(typeof r!="string"||!/^0x(?:[0-9a-fA-F]{2})*$/.test(r)||e!==void 0&&r.length!==2+2*e)&&a()}function A(r){(typeof r!="string"||!/^[A-Za-z0-9_-]{1,128}$/.test(r)||/^(?:bsk|deo|ags|dcs|dca|dcr|dcc|dcq|din)_/.test(r))&&a()}function k(r){if(typeof r!="string")return!1;let e=/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/.exec(r);if(!e)return!1;let t=Number(e[1]),n=Number(e[2]),i=Number(e[3]),s=[31,t%4===0&&(t%100!==0||t%400===0)?29:28,31,30,31,30,31,31,30,31,30,31];return t>=1&&n>=1&&n<=12&&i>=1&&i<=s[n-1]&&Number(e[4])<=23&&Number(e[5])<=59&&Number(e[6])<=59&&Number.isFinite(Date.parse(r))}function N(r){(typeof r!="string"||!/^(0|[1-9][0-9]{0,77})$/.test(r)||BigInt(r)>=2n**256n)&&a()}function U(r){let e=m(r);return c(e.address,20),c(e.publicKey,65),(!e.publicKey.startsWith("0x04")||_e(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)||!k(e.createdAt))&&a(),Object.freeze({address:e.address,publicKey:e.publicKey,fingerprint:e.fingerprint,backend:e.backend,createdAt:e.createdAt})}function M(r){let e=m(r);return(typeof e.intentType!="string"||!e.intentType||typeof e.userOpHash!="string")&&a(),c(e.userOpHash,32),E(e.userOp),e}function Ee(r){let e=m(r);return c(e.to,20),c(e.data),N(e.value),(!Number.isSafeInteger(e.chainId)||Number(e.chainId)<1)&&a(),{to:e.to,data:e.data,value:e.value,chainId:Number(e.chainId)}}function ie(r){let e=m(r);return(!["id","agentId","accountId","declineReason","reason"].every(t=>typeof e[t]=="string"&&e[t].length>0)||!Array.isArray(e.calls)||!k(e.raisedAt)||!k(e.expiresAt)||Date.parse(e.expiresAt)<=Date.parse(e.raisedAt)||!["open","approved","expired","withdrawn"].includes(String(e.status)))&&a(),{...e,calls:e.calls.map(Ee)}}function se(r){let e=m(r);if(c(e.address,20),(!["id","name","fingerprint","accountId"].every(t=>typeof e[t]=="string"&&e[t].length>0)||!k(e.connectedAt)||!(e.accountAddress==null||typeof e.accountAddress=="string")||e.accountAddress!=null&&!/^0x[0-9a-fA-F]{40}$/.test(e.accountAddress))&&a(),e.grant!==null){let t=m(e.grant);c(t.permissionId,32),(typeof t.id!="string"||!t.id||typeof t.status!="string"||!t.status||typeof t.humanSummary!="string"||typeof t.chain!="string"||!Number.isSafeInteger(t.chainId)||!m(t.policySet)||!Array.isArray(t.spentToDate))&&a()}if(e.accountSetup!=null){let t=m(e.accountSetup);(typeof t.ready!="boolean"||!Array.isArray(t.missing)||!t.missing.every(n=>typeof n=="string")||t.ready!==(t.missing.length===0)||!Number.isSafeInteger(t.chainId)||Number(t.chainId)<1)&&a()}return e}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 E(r){let e=m(r);for(let t of["sender","entryPoint"])c(e[t],20);for(let t of["nonce","callGasLimit","verificationGasLimit","preVerificationGas","maxFeePerGas","maxPriorityFeePerGas"])x(e[t]);for(let t of["callData","signature"])c(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&&c(e[t],20);for(let t of["factoryData","paymasterData"])e[t]!=null&&c(e[t]);return r}function $(r){let e=m(r);c(e.payload,32),c(e.validator,20),(!Number.isSafeInteger(e.index)||Number(e.index)<0||Number(e.index)>=2**32)&&a();let t=m(e.authorization);return c(t.from,20),c(t.to,20),c(t.nonce,32),N(t.value),N(t.validAfter),N(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 F(r,e){let t=m(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&&c(t.txHash,32),t.status==="settled"&&c(t.txHash,32),t.status==="ready"?$(t.ready):t.ready!==void 0&&a(),t}var ae=D(["function execute(bytes32 mode, bytes executionCalldata) payable"]),W=D(["function executeUnderGrant(bytes32 permissionId, address target, uint256 value, bytes callData)","function executeUnderGrantWithAllowance(bytes32 permissionId, address target, uint256 value, address token, uint256 allowance, bytes callData)"]),Ce=D(["function transfer(address to, uint256 amount) returns (bool)"]),de=D(["function swapExactIn(address tokenIn, address tokenOut, uint256 amountIn, uint256 minOut, address to) returns (uint256 amountOut)"]),Ne=BigInt("0x000100000000008bdaba73cd9815d79069c247eb4bda0000");function y(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 ce(r){let e=m(r),t=["accountId","accountAddress","chainId","action","tokenAddress","amount","recipient","tokenOutAddress","maxSlippageBps"];return Object.keys(e).some(n=>!t.includes(n))&&a(),A(e.accountId),c(e.accountAddress,20),c(e.tokenAddress,20),b(e.amount),(!Number.isSafeInteger(e.chainId)||Number(e.chainId)<=0)&&a(),e.action==="transfer"?(c(e.recipient,20),(e.tokenOutAddress!==void 0||e.maxSlippageBps!==void 0)&&a()):e.action==="swap"?(c(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:v(r.accountAddress),tokenAddress:v(r.tokenAddress),...r.recipient!==void 0?{recipient:v(r.recipient)}:{},...r.tokenOutAddress!==void 0?{tokenOutAddress:v(r.tokenOutAddress)}:{}})}function ue(r,e){if(A(r.delegationId),c(r.permissionId,32),c(r.executorAddress,20),b(r.maxGasCostWei),e.action==="swap"){let t=r;c(t.routerAddress,20),b(t.minAmountOut),t.verifyRoute!==void 0&&typeof t.verifyRoute!="function"&&a()}return Object.freeze({...r,executorAddress:v(r.executorAddress),...e.action==="swap"?{routerAddress:v(r.routerAddress)}:{}})}async function pe(r,e,t){try{let n=m(r),i=m(n.execution),d=E(n.userOp),s=Object.freeze({...d,sender:v(d.sender),entryPoint:v(d.entryPoint)});c(n.userOpHash,32),(n.intentType!=="delegated_action"||m(n.simulation).willSucceed!==!0||i.accountId!==e.accountId||!y(i.accountAddress,e.accountAddress)||i.chainId!==e.chainId||i.action!==e.action||i.amount!==e.amount||!y(i.tokenAddress,e.tokenAddress)||i.delegationId!==t.delegationId||!y(i.permissionId,t.permissionId)||i.gasMethod!=="native"||!y(s.sender,e.accountAddress)||s.chainId!==e.chainId||!y(s.entryPoint,oe)||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!==Ne&&a();let u=x(s.callGasLimit,128),p=x(s.verificationGasLimit,128),l=x(s.preVerificationGas),I=x(s.maxFeePerGas,128),f=x(s.maxPriorityFeePerGas,128);(f>I||(u+p+l)*I>b(t.maxGasCostWei))&&a();let g=s.callData,R;if(e.action==="transfer"){(!y(i.recipient,e.recipient)||i.tokenOutAddress!==void 0||i.maxSlippageBps!==void 0)&&a();let w=y(e.tokenAddress,Be);R=O({abi:W,functionName:"executeUnderGrant",args:[t.permissionId,w?e.recipient:e.tokenAddress,w?b(e.amount):0n,w?"0x":O({abi:Ce,functionName:"transfer",args:[e.recipient,b(e.amount)]})]})}else{let w=t;(!y(i.tokenOutAddress,e.tokenOutAddress)||i.recipient!==void 0||i.maxSlippageBps!==(e.maxSlippageBps??50))&&a();let z=j({abi:ae,data:g}).args[1],P=j({abi:W,data:`0x${z.slice(106)}`});P.functionName!=="executeUnderGrantWithAllowance"&&a();let _=P.args[5],C=Object.freeze({chainId:e.chainId,accountAddress:e.accountAddress,routerAddress:w.routerAddress,tokenAddress:e.tokenAddress,tokenOutAddress:e.tokenOutAddress,amount:e.amount,minAmountOut:w.minAmountOut,callData:_});if(w.verifyRoute)await w.verifyRoute(C)!==!0&&a();else{let re=j({abi:de,data:_}),[ke,ve,Re,Pe,Se]=re.args;(!y(ke,e.tokenAddress)||!y(ve,e.tokenOutAddress)||Re!==b(e.amount)||Pe<b(w.minAmountOut)||!y(Se,e.accountAddress)||!y(O({abi:de,functionName:"swapExactIn",args:re.args}),_))&&a()}R=O({abi:W,functionName:"executeUnderGrantWithAllowance",args:[t.permissionId,w.routerAddress,0n,e.tokenAddress,b(e.amount),_]})}let S=O({abi:ae,functionName:"execute",args:[Te,Oe(["address","uint256","bytes"],[t.executorAddress,0n,R])]});y(g,S)||a();let T=He({entryPointAddress:oe,entryPointVersion:"0.7",chainId:e.chainId,userOperation:{sender:s.sender,nonce:o,callData:s.callData,callGasLimit:u,verificationGasLimit:p,preVerificationGas:l,maxFeePerGas:I,maxPriorityFeePerGas:f,signature:"0x"}});y(T,n.userOpHash)||a();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:T,execution:G}}catch{return a()}}function V(r,e){try{let t=m(r);if(A(t.id),!y(t.userOpHash,e)||!["pending","included","failed"].includes(String(t.status)))throw new Error;return t.txHash!=null&&c(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 Ye,toHex as Je,encodePacked as xe,encodeAbiParameters as Qe}from"viem";import{randomBytes as Ue}from"node:crypto";import{hexToBytes as $e}from"viem";var le="0123456789ABCDEFGHJKMNPQRSTVWXYZ";function K(r){let e=0,t=0,n="";for(let i of r)for(e=e<<8|i,t+=8;t>=5;)n+=le[e>>>t-5&31],t-=5;return t>0&&(n+=le[e<<5-t&31]),n}var ge=3,me=5;function Z(r){let e=$e(r);return K(e.slice(0,ge))}function X(){return K(Ue(me))}var fe=600*1e3,B=class{#r;#e;#d;#o;#i=null;constructor(e,t){if(!/^[0-9A-HJKMNP-TV-Z]{5}$/.test(e))throw new TypeError("Invalid agent fingerprint.");if(t?.ttlMs!==void 0&&(!Number.isSafeInteger(t.ttlMs)||t.ttlMs<1e3||t.ttlMs>36e5))throw new TypeError("Invalid pairing code lifetime.");this.#r=e,this.#e=t?.ttlMs??fe,this.#d=t?.now??Date.now,this.#o=t?.nonce??X}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){if(!Number.isSafeInteger(e)||e<0||e>864e13)throw new TypeError("Invalid pairing clock.");let t=this.#o();if(!/^[0-9A-HJKMNP-TV-Z]{8}$/.test(t))throw new TypeError("Invalid pairing nonce.");this.#i={nonce:t,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 je from"openapi-fetch";var he=[{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 ye="https://botanary-canonical-path.invalid",Ae="(?:[A-Za-z0-9\\-._~!$&'()*+,;=:@]|%[0-9A-Fa-f]{2})",xt=`${Ae}+`,De=new RegExp(`^${Ae}+$`),qe=new RegExp("^(?:[A-Za-z0-9\\-._~!$&'()*+,;=:@/?]|%[0-9A-Fa-f]{2})*$"),Ge=/^\.{1,2}$/,Le=/[/\\#?]/,ze=/[\u0000-\u001f\u007f]/,Me=6;function Fe(r){let e=r;for(let t=0;t<Me;t+=1){if(Ge.test(e)||Le.test(e)||ze.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 we(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(!De.test(o)||Fe(o))return null}if(n!==""&&!qe.test(n.slice(1)))return null;let d;try{d=new URL(t+n,ye)}catch{return null}return d.origin!==ye||d.hash!==""||d.pathname!==t||d.search!==n?null:{path:t,query:n,full:t+n}}var q=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=je({baseUrl:n.origin+"/v1",fetch:Xe(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 d=we(t);if(!d?.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=d.path.slice(3),o=he.find(f=>f.method===e&&new RegExp("^"+f.path.replace(/\{[^}]+\}/g,"[A-Za-z0-9_-]+")+"$").test(s));if(!o)throw new Error("This route is outside the reviewed agent API.");let u={};o.path.split("/").forEach((f,g)=>{f.startsWith("{")&&(u[f.slice(1,-1)]=s.split("/")[g])});let p=Object.fromEntries(new URLSearchParams(d.query)),l=new AbortController,I=setTimeout(()=>l.abort(),3e4);try{let f=await this.#r.request(e,o.path,{params:{path:u,query:p},...n===void 0?{}:{body:n},headers:i?{authorization:`Bearer ${i}`}:{},credentials:"omit",redirect:"error",cache:"no-store",signal:l.signal,parseAs:"text"}),g=f.response,R=f.error;if(g.ok)try{R=f.data?JSON.parse(f.data):{}}catch{throw new Error("Invalid JSON response.")}if(!g.ok){let S=Y(Y(R)?.error),T=typeof S?.message=="string"?S.message:`Agent request failed with ${g.status}.`,G=We(T).replace(/0x[a-fA-F0-9]{64,}/g,"[redacted]"),H=g.headers.get("retry-after"),w=H&&/^\d+(?:\.\d+)?$/.test(H)?Number(H):null,L=Y(S?.details),z=L&&Object.fromEntries(Object.entries(L).filter(([_,C])=>["missingModule","declineReason","chainId"].includes(_)&&(typeof C=="number"||Ze(C)))),P=new h(G.slice(0,1e3),g.status,z,w);throw P.requestId=Ve(g.headers.get("x-request-id")),P.code=Ke(S?.code)??"http_error",P.ambiguous=e==="post"&&g.status>=500,P}return R}catch(f){if(f instanceof h)throw f;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(I)}}};function Y(r){return typeof r=="object"&&r!==null&&!Array.isArray(r)?r:null}var J=/(?:bsk_(?:test|live)|deo_(?:test|live)|dcs|dca|dcr|dcc|dcq|ags|din|whsec)_[A-Za-z0-9_+/=-]+/g;function Q(r){return J.lastIndex=0,!J.test(r)}function We(r){return r.replace(J,"[redacted]")}function Ve(r){return typeof r=="string"&&/^req_[A-Za-z0-9_-]{1,124}$/.test(r)&&Q(r)?r:void 0}function Ke(r){return typeof r=="string"&&/^[a-z][a-z0-9_]{0,63}$/.test(r)&&Q(r)?r:void 0}function Ze(r){return typeof r=="string"&&/^[a-zA-Z0-9_-]{1,100}$/.test(r)&&Q(r)}function Xe(r){return async(e,t)=>{let n=e instanceof Request?e:new Request(e,t),i=n.signal,d=()=>{},s=new Promise((u,p)=>{d=()=>p(new Error("Request aborted.")),i.aborted?d():i.addEventListener("abort",d,{once:!0})}),o;try{let u=await Promise.race([r(n),s]);if(!u.body)return u;o=u.body.getReader();let p=[],l=0;for(;;){let g=await Promise.race([o.read(),s]);if(g.done)break;if(l+=g.value.byteLength,l>4*1024*1024)throw new Error("Response too large.");p.push(g.value)}let I=new Uint8Array(l),f=0;for(let g of p)I.set(g,f),f+=g.byteLength;return new Response(I,{status:u.status,statusText:u.statusText,headers:u.headers})}finally{i.removeEventListener("abort",d),o&&o.cancel().catch(()=>{})}}}import{recoverAddress as et}from"viem";async function ee(r,e,t,n,i){if(!Number.isFinite(t)||t<0||t>36e5)throw new Error("Invalid wait budget.");let d=n(),s=await r(e);for(;["pending","pending_approval","submitted","queued"].includes(String(s.status))&&n()-d<t;)await i(1500),s=await r(e);return s}var tt=3e4,be=300*1e3,Ie="https://api.app.botanary.xyz",te=class{#r;#e;#d;#o;#i=null;#c=null;#s=null;#u=null;#p=null;#n=0;#g;constructor(e,t={}){if(this.#r=e,this.#d=t.baseUrl??Ie,this.#e=t.transport??new q(this.#d,t.fetch),this.#o=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.#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=U(n);return this.#i=i,i})();this.#u=t;try{return await t}finally{this.#u===t&&(this.#u=null)}}#a(){let e=new h("The agent signer could not complete the request.",0);return e.code="signer_error",e}async#l(e){c(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);c(i,65);let d=await et({hash:e,signature:i});if(t!==this.#n||d.toLowerCase()!==n.address.toLowerCase())throw this.#a();return i}catch{throw this.#a()}}async pairingCode(){return(await this.#f()).current()}async regeneratePairingCode(){return(await this.#f()).regenerate()}async pair(){let e=await this.pairingCode(),t=Math.floor(Date.now()/1e3),n=await this.identity(),i=`${e.code}|${t}`,d=Ye(Je(i));return await this.#e.post("/v1/agents/pair",{code:e.code,publicKey:n.publicKey,timestamp:t,signature:await this.#l(d),...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=m(await this.#e.post("/v1/agents/session/nonce",{address:n.address}));if(c(i.nonce,32),e!==this.#n)throw this.#a();let d=await this.#l(i.nonce),s=m(await this.#e.post("/v1/agents/session",{address:n.address,nonce:i.nonce,signature:d}));if((typeof s.token!="string"||!/^ags_[a-f0-9]{64}$/.test(s.token)||!k(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)-tt},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 se(await 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=ce(e),i=ue(t,n),d=this.#n,s=await this.#t(p=>this.#e.post(`/v1/delegations/${i.delegationId}/actions/exact`,n,p),!1),o=await pe(s,n,i),u;return Object.freeze({status:"prepared",userOpHash:o.userOpHash,execution:o.execution,submit:()=>(u||(u=(async()=>{if(d!==this.#n)throw this.#a();let p=await this.ensureSession();if(d!==this.#n)throw this.#a();return V(await this.spendUnderGrant(o.userOp,o.userOpHash,i.permissionId,p,"delegated_action"),o.userOpHash)})()),u),reconcile:()=>this.getUserOpByHash(n.chainId,o.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,d=t.policy.perActionMaxRaw&&/^[1-9][0-9]{0,77}$/.test(t.policy.perActionMaxRaw)?BigInt(t.policy.perActionMaxRaw):null,s=t.chainState.remaining?.find(p=>p.token.toLowerCase()===n.tokenAddress.toLowerCase())?.remainingRaw??null,o=p=>Object.freeze({status:"refused",reason:p,transactionSubmitted:!1,requestedAmountRaw:n.amountRaw,perActionMaxRaw:t.policy.perActionMaxRaw,remainingRaw:s});if(t.chainId!==84532||!["submitted","unresolved","confirmed"].includes(t.createStatus)||t.chainState.status!=="active"||t.apiAccess!=="active")return o(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(p=>p.token.toLowerCase()===n.tokenAddress.toLowerCase()))return o("mandate_inactive");if(d!==null&&i>d)return o("over_per_action_max");if(t.policy.recipients.length>0&&!t.policy.recipients.some(p=>p.toLowerCase()===n.recipient.toLowerCase()))return o("wrong_recipient");if((await this.identity()).address.toLowerCase()!==t.agentAddress.toLowerCase())return o("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){A(e.delegationId),c(e.recipient,20),(!Number.isFinite(e.amount)||e.amount<=0||e.amount>Number.MAX_SAFE_INTEGER)&&a(),e.token!==void 0&&(typeof e.token!="string"||!e.token||e.token.length>256)&&a();let t={recipient:e.recipient,amount:e.amount,...e.token?{token:e.token}:{}};return M(await this.#t(n=>this.#e.post(`/v1/delegations/${e.delegationId}/actions`,t,n),!1))}async buildDelegatedSwap(e){A(e.delegationId),(![e.tokenIn,e.tokenOut].every(n=>typeof n=="string"&&n.length>0&&n.length<=64)||!Number.isFinite(e.amountIn)||e.amountIn<=0||e.amountIn>Number.MAX_SAFE_INTEGER||e.maxSlippageBps!==void 0&&(!Number.isSafeInteger(e.maxSlippageBps)||e.maxSlippageBps<0||e.maxSlippageBps>1e4))&&a();let t={action:"swap",tokenIn:e.tokenIn,tokenOut:e.tokenOut,amountIn:e.amountIn,...e.maxSlippageBps!=null?{maxSlippageBps:e.maxSlippageBps}:{}};return M(await this.#t(n=>this.#e.post(`/v1/delegations/${e.delegationId}/actions`,t,n),!1))}async raiseRequest(e,t){return(!Array.isArray(e)||!e.length||e.length>100||typeof t!="string"||!t.trim()||t.length>2e3)&&a(),ie(await this.#t(n=>this.#e.post("/v1/agents/requests",{calls:e,reason:t},n),!1))}async spendUnderGrant(e,t,n,i,d){E(e),c(t,32),c(n,32);let s=await this.#l(t),o=xe(["bytes1","bytes32","bytes"],["0x00",n,s]);try{return await this.#e.post("/v1/userops",{userOp:{...e,signature:o},userOpHash:t,intentType:d},i)}catch(u){throw u instanceof h&&(u.userOpHash=t),u}}async getUserOp(e){return A(e),this.#t(t=>this.#e.get(`/v1/userops/${e}`,t))}async getUserOpByHash(e,t){return(!Number.isSafeInteger(e)||e<1)&&a(),c(t,32),V(await this.#t(n=>this.#e.get(`/v1/userops/by-hash/${e}/${t}`,n)),t)}async awaitTerminal(e,t){return ee(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 A(t?.requirementId),["ready","pending_approval"].includes(t.status)||a(),this.#m(t)}async resumeApi(e,t=be){A(e);let n=F(await this.#t(i=>this.#e.get(`/v1/apis/calls/relay/${e}`,i)),e);return n.status==="ready"?this.#m({requirementId:e,status:"ready",...$(n.ready)},t):n.status!=="pending_approval"?n:this.#m({requirementId:e,status:"pending_approval",approvalId:e,expiresAt:""},t)}async#m(e,t=be){let n;if(e.status==="pending_approval"){let o=await ee(u=>this.#t(p=>this.#e.get(`/v1/apis/calls/requirements/${u}`,p)),e.requirementId,t,()=>Date.now(),u=>new Promise(p=>setTimeout(p,u)));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 u=o.status==="declined"?"owner_declined":o.status==="expired"?"approval_timed_out":"approval_still_pending",p=u==="owner_declined"?"The owner declined this call. Nothing was signed and nothing was charged.":u==="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:u,message:p,requirementId:e.requirementId,approvalId:e.status==="pending_approval"?e.approvalId:void 0}}}else n=e;n=$(n);let i=await this.identity(),d=await this.#l(n.payload),s=xe(["bytes1","address","bytes"],["0x01",n.validator,Qe([{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,d])]);try{return F(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 h&&(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.#c=null,this.#s=null}async#f(){if(!this.#c){let e=await this.identity();this.#c??=new B(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 d=this.#s&&this.#s.token!==n?await this.ensureSession():await this.mintSession();return await e(d)}throw i}}};function nt(r,e={}){let t={address:r.address,publicKey:r.publicKey,fingerprint:Z(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 rt}from"viem";async function it(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=U(await r.ensure())}catch{throw ne()}let i=await e.app.context();A(i.appId),A(i.keyId),["test","live"].includes(i.environment)||a();let d=n.publicKey.toLowerCase(),s=n.address.toLowerCase(),o=await e.agents.challenge({publicKey:d,name:t.trim()});(!o||o.appId!==i.appId||o.environment!==i.environment||o.publicKey!==d||o.address!==s||!/^dach_[A-Za-z0-9_-]{43}$/.test(o.id)||!k(o.expiresAt)||Date.parse(o.expiresAt)<=Date.now()||Date.parse(o.expiresAt)>Date.now()+36e4)&&a();let u=["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: ${d}`,`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!==u&&a();let p;try{if(p=await r.sign(u),c(p,65),(await rt({message:u,signature:p})).toLowerCase()!==s)throw ne()}catch{throw ne()}let l=await e.agents.complete({challengeId:o.id,signature:p});return(!l||l.appId!==i.appId||l.environment!==i.environment||l.publicKey!==d||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)&&a(),l.connectionId!==null&&A(l.connectionId),l}function ne(){let r=new h("The agent signer could not complete registration.",0);return r.code="signer_error",r}export{te as AgentRuntime,h as BotanaryApiError,Ie as DEFAULT_API_BASE_URL,fe as DEFAULT_PAIRING_CODE_TTL_MS,ge as FINGERPRINT_BYTES,me as NONCE_BYTES,B as PairingCodeManager,ee as awaitTerminalWith,nt as createViemAgentSigner,K as crockfordBase32,Z as deriveFingerprint,X as generatePairingNonce,it as registerAgent};
|
package/dist/pairing-code.d.ts
CHANGED
|
@@ -1,41 +1,18 @@
|
|
|
1
|
-
/** 10 minutes: long enough to alt-tab to the Botanary app and type ~13 characters, short enough that a
|
|
2
|
-
* code nobody redeemed stops being worth anything on its own quickly. See README for the full
|
|
3
|
-
* "why intercepting the code alone grants nothing" argument - the TTL is one layer of it, not the
|
|
4
|
-
* whole thing. */
|
|
5
1
|
export declare const DEFAULT_PAIRING_CODE_TTL_MS: number;
|
|
6
2
|
export interface PairingCode {
|
|
7
|
-
/** What the agent shows the user, and what they type into Connected agents: `${fingerprint}-${nonce}`. */
|
|
8
3
|
code: string;
|
|
9
|
-
/** The stable, non-secret address fingerprint half (see fingerprint.ts). */
|
|
10
4
|
fingerprint: string;
|
|
11
|
-
/** The fresh-per-code random half - this is what makes the code single-use/short-lived. */
|
|
12
5
|
nonce: string;
|
|
13
6
|
issuedAt: string;
|
|
14
7
|
expiresAt: string;
|
|
15
8
|
}
|
|
16
|
-
/**
|
|
17
|
-
* Owns exactly one pairing attempt at a time for this process, keyed off a fixed address fingerprint.
|
|
18
|
-
* `current()` is idempotent while the code is still valid - Flow 7d step 1 is "the agent ... shows the
|
|
19
|
-
* short code, and waits", which only makes sense if the code stays put while the owner is busy typing
|
|
20
|
-
* it, rather than rotating out from under them on every tool call. It mints automatically once the
|
|
21
|
-
* previous code expires, and `regenerate()` lets the owner (via the agent) burn a code early - e.g. if
|
|
22
|
-
* they suspect it was seen by someone else - without waiting out the TTL.
|
|
23
|
-
*
|
|
24
|
-
* Deliberately in-memory only: a pairing code is not part of the identity (see store.ts) and is not
|
|
25
|
-
* meant to survive a restart - a fresh process showing a fresh code is the correct behavior, not a bug.
|
|
26
|
-
*/
|
|
27
9
|
export declare class PairingCodeManager {
|
|
28
10
|
#private;
|
|
29
11
|
constructor(fingerprint: string, options?: {
|
|
30
12
|
ttlMs?: number;
|
|
31
|
-
/** injectable for deterministic tests */
|
|
32
13
|
now?: () => number;
|
|
33
|
-
/** injectable for deterministic tests */
|
|
34
14
|
nonce?: () => string;
|
|
35
15
|
});
|
|
36
|
-
/** The active code, minting a fresh one if there is none yet or the previous one expired. */
|
|
37
16
|
current(): PairingCode;
|
|
38
|
-
/** Always mints a fresh code, invalidating whatever was active. */
|
|
39
17
|
regenerate(): PairingCode;
|
|
40
18
|
}
|
|
41
|
-
//# sourceMappingURL=pairing-code.d.ts.map
|
package/dist/registration.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { AgentSigner } from './signer.js';
|
|
2
2
|
import type { components } from './generated/schema.js';
|
|
3
3
|
type Schemas = components['schemas'];
|
|
4
|
-
/** Structurally compatible with @botanary/sdk. Only the server client handles its app credential. */
|
|
5
4
|
export interface AgentRegistrationClient {
|
|
6
5
|
app: {
|
|
7
6
|
context(): Promise<{
|
|
@@ -15,7 +14,5 @@ export interface AgentRegistrationClient {
|
|
|
15
14
|
complete(input: Schemas['DeveloperAgentRegistrationInput']): Promise<Schemas['DeveloperAgentRegistration']>;
|
|
16
15
|
};
|
|
17
16
|
}
|
|
18
|
-
/** Registration proves possession of this agent key. It creates neither owner consent nor a grant. */
|
|
19
17
|
export declare function registerAgent(signer: AgentSigner, client: AgentRegistrationClient, name: string): Promise<Schemas['DeveloperAgentRegistration']>;
|
|
20
18
|
export {};
|
|
21
|
-
//# sourceMappingURL=registration.d.ts.map
|
package/dist/runtime.d.ts
CHANGED
|
@@ -1,20 +1,11 @@
|
|
|
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';
|
|
5
5
|
import type { AgentIdentity, AgentSigner } from './signer.js';
|
|
6
6
|
import type { AgentSelf, AgentRequestView, UnsignedCallView, UserOpBuildResult, UnsignedUserOp } from './views.js';
|
|
7
|
-
/**
|
|
8
|
-
* Poll `get` until the op reports a terminal status or `budgetMs` is spent, then return whatever the
|
|
9
|
-
* backend last said - VERBATIM. A budget lapse returns the real `pending` answer; this helper never
|
|
10
|
-
* invents a status, and never blocks forever.
|
|
11
|
-
*
|
|
12
|
-
* Pure and injectable (clock + sleep) so its behaviour is testable without timers or a network.
|
|
13
|
-
*/
|
|
14
7
|
export declare function awaitTerminalWith(get: (opId: string) => Promise<Record<string, unknown>>, opId: string, budgetMs: number, now: () => number, sleep: (ms: number) => Promise<void>): Promise<Record<string, unknown>>;
|
|
15
|
-
/** Default API origin. The shared runtime reads no environment variables; its host supplies overrides. */
|
|
16
8
|
export declare const DEFAULT_API_BASE_URL = "https://api.app.botanary.xyz";
|
|
17
|
-
/** Per-instance agent identity and sessions. The signer owns all private-key storage. */
|
|
18
9
|
export declare class AgentRuntime {
|
|
19
10
|
#private;
|
|
20
11
|
constructor(signer: AgentSigner, options?: {
|
|
@@ -25,6 +16,7 @@ export declare class AgentRuntime {
|
|
|
25
16
|
client?: string;
|
|
26
17
|
profile?: string;
|
|
27
18
|
};
|
|
19
|
+
maxGasCostWei?: string;
|
|
28
20
|
});
|
|
29
21
|
get apiBaseUrl(): string;
|
|
30
22
|
protected get identityMaterialized(): boolean;
|
|
@@ -33,91 +25,32 @@ export declare class AgentRuntime {
|
|
|
33
25
|
profile?: string;
|
|
34
26
|
}): void;
|
|
35
27
|
protected replaceSigner(signer: AgentSigner): void;
|
|
36
|
-
/** The agent's public identity, creating it on first call if none exists yet. Cached for the life of
|
|
37
|
-
* this runtime (the address/fingerprint cannot change without a forget(), which calls reset()). */
|
|
38
28
|
identity(): Promise<AgentIdentity>;
|
|
39
29
|
pairingCode(): Promise<PairingCode>;
|
|
40
30
|
regeneratePairingCode(): Promise<PairingCode>;
|
|
41
31
|
pair(): Promise<PairingCode>;
|
|
42
|
-
/** Mint a FRESH session unconditionally (bypasses the cache - this is what re-minting after expiry or
|
|
43
|
-
* a 401 calls). Also (re)populates the cache, so an ordinary tool call right after this one reuses it
|
|
44
|
-
* via `ensureSession()` instead of minting again. */
|
|
45
32
|
mintSession(): Promise<string>;
|
|
46
|
-
/** The token every read/build/spend call below actually uses: the cached session if it is still safe
|
|
47
|
-
* to reuse, otherwise a freshly minted one. This is what makes "every tool call does not re-mint" true
|
|
48
|
-
* without any caller having to think about session lifetime. */
|
|
49
33
|
ensureSession(): Promise<string>;
|
|
50
|
-
/** `GET /agents/me` - this agent's own identity, its bound account, and its live grant if any (or an
|
|
51
|
-
* honest `grant: null`). Re-mints the session once and retries on a 401 (a token that expired between
|
|
52
|
-
* `ensureSession()`'s check and the request landing, or one the backend otherwise no longer honors). */
|
|
53
34
|
me(): Promise<AgentSelf>;
|
|
54
|
-
/** `GET /balance` - the account address and its token/holdings breakdown, exactly as the backend
|
|
55
|
-
* reports it. */
|
|
56
35
|
getBalance(): Promise<Record<string, unknown>>;
|
|
57
|
-
/** `GET /agents/requests` - every approval request this agent has filed, with the owner's verdict
|
|
58
|
-
* (`status`, `declineReason`) and deadline. The read half of `request_approval`: without it an agent
|
|
59
|
-
* files a request it can never learn the outcome of. */
|
|
60
36
|
listRequests(): Promise<unknown>;
|
|
61
|
-
/** `GET /chains` - every chain this build serves, each with the `chainTier` that decides what it can
|
|
62
|
-
* do (`watch` read-only, `basic` no AgentGuard, `botanary` full authority). */
|
|
63
37
|
listChains(): Promise<unknown>;
|
|
64
|
-
/** `GET /gas/methods` - only the gas methods actually AVAILABLE on the given chain (the backend
|
|
65
|
-
* filters unavailable/sponsored ones out itself). Every parameter is optional and passed through
|
|
66
|
-
* untouched; `key` is the Stellar/Solana key-keyed lane, `chainId` the EVM numeric one. */
|
|
67
38
|
getGasMethods(params: {
|
|
68
39
|
chainId?: number;
|
|
69
40
|
accountId?: string;
|
|
70
41
|
key?: string;
|
|
71
42
|
}): Promise<unknown>;
|
|
72
|
-
/** `GET /account` - SINGULAR: the one account this agent's session resolves to, optionally for a
|
|
73
|
-
* specific chain. Carries `address` and `deploymentStatus`. */
|
|
74
43
|
getAccount(params: {
|
|
75
44
|
chainId?: number;
|
|
76
45
|
}): Promise<unknown>;
|
|
77
|
-
/** Build and verify a bound action. Submission is explicit and attempted at most once per handle. */
|
|
78
46
|
prepareExactAction(input: ExactAgentAction, binding: AgentActionBinding | AgentSwapBinding): Promise<PreparedAgentAction>;
|
|
79
|
-
|
|
80
|
-
* `POST /delegations/{delegationId}/actions` - an UNSIGNED delegated-action op, built in the
|
|
81
|
-
* delegation's OWN Smart Sessions nonce lane with fixed native gas (the session validator cannot
|
|
82
|
-
* gas-estimate a stub signature). This is the ONLY build lane a session-key signature can validate:
|
|
83
|
-
* `POST /money/send/build` (this package's earlier, WRONG choice) builds in the Kernel account's ROOT
|
|
84
|
-
* nonce lane for the OWNER's key - an op built there, then signed with this agent's session key and
|
|
85
|
-
* wrapped in `spendUnderGrant`'s USE envelope, would route validation to the root ECDSA validator,
|
|
86
|
-
* which cannot parse a `(bytes1, bytes32, bytes)` envelope as a 65-byte ECDSA signature. `delegationId`
|
|
87
|
-
* is this agent's OWN grant id (`GET /agents/me`'s `grant.id` - never invented, never another agent's:
|
|
88
|
-
* the backend refuses that with a named 403, see the workspace's delegation.controller.ts). `amount` is
|
|
89
|
-
* DISPLAY units (e.g. `12.5` for 12.5 USDC), matching `DelegatedActionInput.amount` - never wei.
|
|
90
|
-
* `token`, when given, disambiguates which of the delegation's budgeted tokens to move - a contract
|
|
91
|
-
* address or CAIP-19 asset ref (Task A11), required whenever the grant budgets more than one
|
|
92
|
-
* stablecoin. Omitted, the backend defaults to it ONLY when exactly one token is budgeted; a
|
|
93
|
-
* multi-budget grant given neither refuses rather than silently picking the first (`propose_payment`
|
|
94
|
-
* always resolves and passes one - see `agent-actions.ts`).
|
|
95
|
-
*/
|
|
47
|
+
prepareAction(input: MandateTransferInput): Promise<PreparedAgentAction | AgentPolicyRefusal>;
|
|
96
48
|
buildDelegatedAction(params: {
|
|
97
49
|
delegationId: string;
|
|
98
50
|
recipient: string;
|
|
99
51
|
amount: number;
|
|
100
52
|
token?: string;
|
|
101
53
|
}): Promise<UserOpBuildResult>;
|
|
102
|
-
/**
|
|
103
|
-
* `POST /delegations/{delegationId}/actions` with `action: 'swap'` - the SAME endpoint, the same session
|
|
104
|
-
* nonce lane and the same fixed gas as `buildDelegatedAction` above; only the body's shape differs. The
|
|
105
|
-
* backend discriminates on `action` explicitly and NEVER infers it from the presence of `tokenIn`, so a
|
|
106
|
-
* transfer body with a typo stays a 422 on the wrong field rather than silently becoming a swap.
|
|
107
|
-
*
|
|
108
|
-
* Symbols, not addresses: unlike `buildDelegatedAction`'s `token` (Task A11), this shape was NOT widened
|
|
109
|
-
* to accept an address or asset ref - the backend re-resolves both legs from ITS OWN per-chain manifest,
|
|
110
|
-
* which is the same resolution `buildGrant` used when it compiled the venue's `EQ` rule, so the two
|
|
111
|
-
* cannot disagree. `propose_swap` (`agent-actions.ts`) still takes an address/asset ref from ITS OWN
|
|
112
|
-
* caller (`assetIn`/`assetOut`) and resolves each to a verified symbol before calling this - so the
|
|
113
|
-
* package-external argument names moved even though this wire shape did not. `amountIn` is DISPLAY
|
|
114
|
-
* units (e.g. `25` for 25 USDC), matching `amount` on the transfer shape.
|
|
115
|
-
*
|
|
116
|
-
* The op this produces is ONE call into `GrantExecutor.executeUnderGrantWithAllowance` - approve, route,
|
|
117
|
-
* zero, assert no residual - which the grant's session authorises only when the grant named a
|
|
118
|
-
* `swapVenue`. A grant without one has no such action at all and the backend declines
|
|
119
|
-
* `grant_swap_not_authorised` rather than handing back an op Smart Sessions would refuse in validation.
|
|
120
|
-
*/
|
|
121
54
|
buildDelegatedSwap(params: {
|
|
122
55
|
delegationId: string;
|
|
123
56
|
tokenIn: string;
|
|
@@ -125,79 +58,21 @@ export declare class AgentRuntime {
|
|
|
125
58
|
amountIn: number;
|
|
126
59
|
maxSlippageBps?: number;
|
|
127
60
|
}): Promise<UserOpBuildResult>;
|
|
128
|
-
/** `POST /agents/requests` - the "ask" half of the design (Flow 7d step 5): raise a request naming the
|
|
129
|
-
* calls that were declined and why, returning which bound was crossed and the deadline exactly as the
|
|
130
|
-
* backend computed them. */
|
|
131
61
|
raiseRequest(calls: UnsignedCallView[], reason: string): Promise<AgentRequestView>;
|
|
132
|
-
/**
|
|
133
|
-
* Sign a built op as the grant's session key and relay it. The USE envelope is EXACTLY the three lines
|
|
134
|
-
* `botanary-fe/src/lib/wallet/signing.ts:49` already uses - `SmartSessionMode.USE` is `0x00`, and the
|
|
135
|
-
* packing is `(bytes1, bytes32, bytes)`. Reproduced rather than re-derived: a second encoding of the same
|
|
136
|
-
* envelope is a second thing to get byte-exact, and only one of them would be tested.
|
|
137
|
-
*
|
|
138
|
-
* `intentType` is the SAME value the build response itself reported (`UserOpBuildResult.intentType`,
|
|
139
|
-
* `'delegated_action'` for `buildDelegatedAction`'s builds) - never assumed or hardcoded here, so the
|
|
140
|
-
* relay always describes what was actually built, which is what `OrchestratorService.submit` uses to
|
|
141
|
-
* label the audit trail entry.
|
|
142
|
-
*
|
|
143
|
-
* Returns the backend's OWN relay response (status/txHash/error, whatever `POST /userops` actually
|
|
144
|
-
* said) rather than nothing - a caller (`propose_payment`) reporting success has to report what the
|
|
145
|
-
* backend reported, never a string this package made up.
|
|
146
|
-
*/
|
|
147
62
|
spendUnderGrant(userOp: UnsignedUserOp, userOpHash: Hex, permissionId: Hex, token: string, intentType: string): Promise<Record<string, unknown>>;
|
|
148
|
-
/** `GET /userops/{opId}` - the receipt for an op THIS agent relayed. Reachable only because that route
|
|
149
|
-
* now carries `@AgentAllowed()`; before that it 403'd an `ags_` token before the handler ran. */
|
|
150
63
|
getUserOp(opId: string): Promise<Record<string, unknown>>;
|
|
151
|
-
/** Read the original agent submission without building or signing another operation. */
|
|
152
64
|
getUserOpByHash(chainId: number, hash: Hex): Promise<Record<string, unknown>>;
|
|
153
|
-
/** Follow an op to a terminal status, bounded. See `awaitTerminalWith`. */
|
|
154
65
|
awaitTerminal(opId: string, budgetMs: number): Promise<Record<string, unknown>>;
|
|
155
|
-
/** `GET /apis/providers` - the ranked, searchable catalog of API providers on a chain, with each
|
|
156
|
-
* provider's endpoint count, verified count, minimum and maximum price in atomic units (nullable).
|
|
157
|
-
* Does NOT call an endpoint or spend anything. Returns
|
|
158
|
-
* `{ providers, total, hidden, reasons, reasonsTruncated }`.
|
|
159
|
-
*
|
|
160
|
-
* The route is `/apis/providers`, not the `/apis/list` this file used to call: the backend's
|
|
161
|
-
* api-catalog controller serves `providers` and `providers/:providerId` and has no `list` route at
|
|
162
|
-
* all, so the old path 404s. botanary-mcp@0.6.1 was published with this corrected route but the
|
|
163
|
-
* change was never committed, which is how the repository came to describe a dead endpoint while
|
|
164
|
-
* the published package worked. */
|
|
165
66
|
listApis(chainId: number): Promise<unknown>;
|
|
166
|
-
/** `GET /apis/providers/{providerId}` - one provider with a page of its endpoints, each with its
|
|
167
|
-
* live price as measured or declared (nullable), and whether it is payable on this chain. Returns
|
|
168
|
-
* the `ApiProviderDetail` shape, with an `endpoints` array. */
|
|
169
67
|
getApiProvider(providerId: string, chainId?: number): Promise<unknown>;
|
|
170
|
-
/**
|
|
171
|
-
* Call a paid third-party API endpoint and pay for it from the owner's wallet, within the budget the
|
|
172
|
-
* owner committed on chain. Build -> sign -> relay, exactly like every other spending lane here.
|
|
173
|
-
*
|
|
174
|
-
* This used to `POST /v1/apis/calls`, a route that has never existed - the contract has
|
|
175
|
-
* `/apis/calls/requirements` and `/apis/calls/relay`, and there is no composite. There could not be
|
|
176
|
-
* one: a single endpoint would have to sign, and the backend holds no key. So the two halves are both
|
|
177
|
-
* real calls, with the signature produced HERE, from this agent's own key.
|
|
178
|
-
*
|
|
179
|
-
* `payload` is a 32-byte EIP-712 digest over an EIP-3009 `TransferWithAuthorization`. Signing it
|
|
180
|
-
* authorises exactly one transfer, of a value and to a recipient the digest already fixes; USDC
|
|
181
|
-
* verifies the result via ERC-1271 against the owner's account, which routes to
|
|
182
|
-
* `X402PaymentValidator` and is refused unless this agent key is inside a live budget.
|
|
183
|
-
*/
|
|
184
68
|
callApi(params: {
|
|
185
69
|
chainId: number;
|
|
186
70
|
providerId: string;
|
|
187
71
|
endpointId: string;
|
|
188
72
|
url: string;
|
|
189
|
-
/** Raw POST body, forwarded byte for byte. The price is quoted for THIS body and the paid request
|
|
190
|
-
* replays exactly it, so a caller cannot get a cheap quote and then send something expensive. */
|
|
191
73
|
body?: string;
|
|
192
74
|
}): Promise<Record<string, unknown>>;
|
|
193
|
-
/** Read durable submission status first. A submitted payment is never signed or forwarded again. */
|
|
194
75
|
resumeApi(requirementId: string, budgetMs?: number): Promise<Record<string, unknown>>;
|
|
195
|
-
/** `GET /apis/budget` - remaining authorizations, per-call maximum, expiry and epoch for this agent
|
|
196
|
-
* on a chain. Does NOT tell you which endpoints this agent may reach. */
|
|
197
76
|
getApiBudget(chainId: number): Promise<unknown>;
|
|
198
|
-
/** Drops cached identity/pairing/session state. Call after `store.forget()` so the next call re-derives
|
|
199
|
-
* from storage (and, in the ordinary case, creates a brand new identity) instead of continuing to serve
|
|
200
|
-
* an in-memory identity - or a session minted for it - whose key is now gone. */
|
|
201
77
|
reset(): void;
|
|
202
78
|
}
|
|
203
|
-
//# sourceMappingURL=runtime.d.ts.map
|
package/dist/signer.d.ts
CHANGED
|
@@ -1,22 +1,16 @@
|
|
|
1
1
|
import type { Hex } from 'viem';
|
|
2
|
-
/** Public metadata only. The runtime never accepts or exports a private key. */
|
|
3
2
|
export interface AgentIdentity {
|
|
4
3
|
address: Hex;
|
|
5
4
|
publicKey: Hex;
|
|
6
5
|
fingerprint: string;
|
|
7
6
|
createdAt: string;
|
|
8
|
-
/** A non-secret description of the injected signer, such as an HSM or desktop keychain. */
|
|
9
7
|
backend: string;
|
|
10
8
|
}
|
|
11
|
-
/** A server, HSM or desktop adapter supplies signing without exposing key material. */
|
|
12
9
|
export interface AgentSigner {
|
|
13
10
|
ensure(): Promise<AgentIdentity>;
|
|
14
|
-
/** EIP-191 personal message signing, used for app registration proofs. */
|
|
15
11
|
sign(message: string): Promise<Hex>;
|
|
16
|
-
/** Raw secp256k1 digest signing, used by existing agent sessions and grant execution. */
|
|
17
12
|
signHash(hash: Hex): Promise<Hex>;
|
|
18
13
|
}
|
|
19
|
-
/** Adapts an already-owned viem-compatible account. Key loading remains the caller's responsibility. */
|
|
20
14
|
export declare function createViemAgentSigner(account: {
|
|
21
15
|
address: Hex;
|
|
22
16
|
publicKey: Hex;
|
|
@@ -30,4 +24,3 @@ export declare function createViemAgentSigner(account: {
|
|
|
30
24
|
backend?: string;
|
|
31
25
|
createdAt?: string;
|
|
32
26
|
}): AgentSigner;
|
|
33
|
-
//# sourceMappingURL=signer.d.ts.map
|
package/dist/transport.d.ts
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
/** Injection seam for an existing host transport. It receives only public payloads and agent tokens. */
|
|
2
1
|
export interface AgentTransport {
|
|
3
2
|
get<T>(path: string, token?: string): Promise<T>;
|
|
4
3
|
post<T>(path: string, body: unknown, token?: string): Promise<T>;
|
|
5
4
|
}
|
|
6
|
-
/** No mutation retries. A failed relay must be reconciled using its existing operation/hash. */
|
|
7
5
|
export declare class AgentApiClient implements AgentTransport {
|
|
8
6
|
#private;
|
|
9
7
|
constructor(baseUrl: string, fetchImpl?: typeof fetch);
|
|
10
8
|
get<T>(path: string, token?: string): Promise<T>;
|
|
11
9
|
post<T>(path: string, body: unknown, token?: string): Promise<T>;
|
|
12
10
|
}
|
|
13
|
-
//# sourceMappingURL=transport.d.ts.map
|
package/dist/validation.d.ts
CHANGED
|
@@ -5,11 +5,12 @@ export declare function invalidResponse(): never;
|
|
|
5
5
|
export declare function record(value: unknown): Record<string, unknown>;
|
|
6
6
|
export declare function hex(value: unknown, bytes?: number): asserts value is Hex;
|
|
7
7
|
export declare function resourceId(value: unknown): asserts value is string;
|
|
8
|
+
export declare function rfc3339(value: unknown): value is string;
|
|
8
9
|
export declare function publicIdentity(value: unknown): AgentIdentity;
|
|
9
|
-
|
|
10
|
+
export declare function userOpBuild(value: unknown): import('./views.js').UserOpBuildResult;
|
|
11
|
+
export declare function agentRequest(value: unknown): import('./views.js').AgentRequestView;
|
|
12
|
+
export declare function agentSelf(value: unknown): import('./views.js').AgentSelf;
|
|
10
13
|
export declare function userOpQuantity(value: unknown, bits?: number): bigint;
|
|
11
14
|
export declare function unsignedUserOp(value: unknown): UnsignedUserOp;
|
|
12
15
|
export declare function readyRequirement(value: unknown): Pick<ApiCallRequirementsReady, 'payload' | 'authorization' | 'index' | 'validator'>;
|
|
13
|
-
/** Bind a recovery response to the requested handle; never treat provider success as payment proof. */
|
|
14
16
|
export declare function apiCallStatus(value: unknown, requirementId: string): Record<string, unknown>;
|
|
15
|
-
//# sourceMappingURL=validation.d.ts.map
|