@cleave-protocol/ai-sdk 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -100,6 +100,73 @@ Field-by-field answers are documented at
100
100
  the signed order to Cleave's relayer. That second call has
101
101
  `needsApproval` set, so the AI SDK asks for your approval before it runs.
102
102
 
103
+ ## Address checks
104
+
105
+ Before a `planSwap` plan or a `getGas` offer reaches the model, the package
106
+ checks it against per-chain contract addresses, rails and tokens pinned in
107
+ this package:
108
+
109
+ - `planSwap`: every call is on the planned chain and from the wallet. The
110
+ last call goes to a listed contract and function that fits the route,
111
+ sends to the planned chain and pays the requested recipient where its
112
+ calldata names one; refunds go to the wallet. Any call before it is an
113
+ approve of the sell token to that contract for exactly what the last
114
+ call pulls. For USDC and the chain's native or wrapped native coin, the
115
+ amount sold is the requested amount. The native value is what the
116
+ native amount sold and the Stargate native messaging fee need.
117
+ - `getGas`: the authorization is a USDC `ReceiveWithAuthorization` from
118
+ the wallet on the paying chain. The order carries the requested amount,
119
+ recipient and refund address, the pinned contracts, rail and fee
120
+ recipient, and the fee and amounts the offer shows. The order hash and
121
+ the payment address are recomputed and must match what is signed.
122
+
123
+ A plan or offer that fails a check is not passed on; the tool returns only
124
+ this:
125
+
126
+ ```json
127
+ {
128
+ "error": {
129
+ "code": "address_not_allowed",
130
+ "message": "P2: the main call's target is not on the allowlist",
131
+ "retryable": false
132
+ }
133
+ }
134
+ ```
135
+
136
+ A plan or offer that passes is returned with only its documented
137
+ top-level fields.
138
+
139
+ What these checks do not cover:
140
+
141
+ - The price, the route and the amount received.
142
+ - On routes that swap on arrival or pay a fee through the bridge message,
143
+ the funds go to the Across handler or Cleave's composer, and that
144
+ message decides who receives them. These checks do not read it, so a
145
+ compromised API could redirect those funds. Have a person check such a
146
+ plan before signing.
147
+ - When `sellToken` is a symbol other than USDC or the chain's native or
148
+ wrapped native coin, the API resolves it to an address. Check
149
+ `send.token` before signing.
150
+ - For any other sell token, given by symbol or by address, the package
151
+ does not know its decimals, so the amount in the approve and the
152
+ calldata is not checked against the request. Check the approve amount
153
+ and `pullsAtMost` before signing.
154
+ - The Stargate native messaging fee is the API's figure. The checks only
155
+ match it with the call's value; nothing bounds it.
156
+ - `next` and the notices are text from the API.
157
+
158
+ After Cleave redeploys a contract, plans that use it fail these checks
159
+ until a package update pins the new address.
160
+
161
+ Agents that call the API directly should pass each answer through
162
+ `screenPlanSwap(request, body)` or `screenGetGas(request, body)` and use
163
+ only what they return: the refusal, or the answer cut to its documented
164
+ fields. `checkPlanSwap` and `checkGetGas` return only a verdict; a pass
165
+ from them does not make the original answer safe to forward, since it
166
+ can carry fields the checks do not read.
167
+
168
+ Do not pair these tools with a wallet that signs without a human looking.
169
+
103
170
  ## Gas top-ups
104
171
 
105
172
  `getGas` takes two calls.
@@ -198,8 +265,9 @@ cleaveTools({
198
265
 
199
266
  ## Errors
200
267
 
201
- A refusal from the API comes back as the tool's result, unchanged, so the
202
- model can read it:
268
+ From `planSwap` and `getGas`, a refusal from the API comes back as the
269
+ tool's result with only its `apiVersion`, `requestId` and `error` fields,
270
+ so the model can read it. `trackSwap` and `findToken` return it unchanged:
203
271
 
204
272
  ```json
205
273
  {
@@ -222,7 +290,12 @@ when present, says when.
222
290
 
223
291
  - a network error, a timeout or an abort: `status` is `0` and `cause`
224
292
  holds the original error;
225
- - an answer that is not JSON: `status` is the HTTP status.
293
+ - a successful answer that is not a JSON object: `status` is the HTTP
294
+ status.
295
+
296
+ An error status whose body has no `error` object comes back as the tool's
297
+ result `{ "error": { "code": "http_error", "message": "HTTP 502", "retryable": true } }`,
298
+ with nothing else from the body; `retryable` is true for 5xx and 429.
226
299
 
227
300
  `requestId` carries the `x-request-id` header when the API sent one.
228
301