@provablehq/aleo-bridge-sdk 0.1.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Provable Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,390 @@
1
+ # @provablehq/aleo-bridge-sdk
2
+
3
+ Moves assets between Aleo, Ethereum, and Solana through reviewed Hyperlane and
4
+ Circle xReserve deployments.
5
+
6
+ The package supports browser wallets and local keys. It does not choose a
7
+ wallet, store transfer progress, or submit a second transaction after an
8
+ interruption without caller authorization.
9
+
10
+ > This package is published as a preview. It is versioned separately from the
11
+ > `@provablehq/veil-*` packages, and its API is subject to breaking changes
12
+ > between minor releases.
13
+
14
+ ## Supported transfers
15
+
16
+ | Source | Destination | Asset received | Provider |
17
+ | --- | --- | --- | --- |
18
+ | Ethereum ETH | Aleo | ETH | Hyperlane |
19
+ | Aleo ETH | Ethereum | ETH | Hyperlane |
20
+ | Ethereum WBTC | Aleo | WBTC | Hyperlane |
21
+ | Aleo WBTC | Ethereum | WBTC | Hyperlane |
22
+ | Ethereum USDT | Aleo | USDT | Hyperlane |
23
+ | Aleo USDT | Ethereum | USDT | Hyperlane |
24
+ | Solana SOL | Aleo | SOL | Hyperlane |
25
+ | Aleo SOL | Solana | SOL | Hyperlane |
26
+ | Ethereum USDC | Aleo | USDCx | Circle xReserve |
27
+ | Aleo USDCx | Ethereum | USDC | Circle xReserve |
28
+
29
+ The registry also contains incomplete ALEO and USAD Hyperlane entries for
30
+ deployment discovery. Those entries are marked `metadata-required` and cannot
31
+ be quoted or executed. Solana routes currently support native SOL, not USDC or
32
+ other SPL tokens.
33
+
34
+ ## Create a browser client
35
+
36
+ A browser application supplies public network access and the wallet accounts
37
+ that may authorize transfers. Public clients read balances, fees, and
38
+ transaction status. Wallet clients request signatures only when a fund-moving
39
+ action runs.
40
+
41
+ ```ts
42
+ import {
43
+ createAleoClient,
44
+ createBridgeClient,
45
+ createEvmClient,
46
+ createSolanaClient,
47
+ evmHttp,
48
+ evmProvider,
49
+ solanaHttp,
50
+ solanaWallet,
51
+ } from '@provablehq/aleo-bridge-sdk'
52
+
53
+ const bridge = createBridgeClient({
54
+ environment: 'mainnet',
55
+ clients: {
56
+ ethereum: createEvmClient({
57
+ transport: evmHttp(ethereumRpcUrl),
58
+ account: evmProvider(window.ethereum),
59
+ }),
60
+ solana: createSolanaClient({
61
+ transport: solanaHttp(solanaRpcUrl),
62
+ account: solanaWallet({
63
+ wallet,
64
+ account: wallet.accounts[0],
65
+ chain: 'solana:mainnet',
66
+ }),
67
+ }),
68
+ aleo: createAleoClient({
69
+ publicClient: aleoPublicClient,
70
+ account: aleoWalletClient,
71
+ }),
72
+ },
73
+ })
74
+ ```
75
+
76
+ An EIP-1193 provider, such as `window.ethereum`, can supply both EVM reads and
77
+ wallet requests when `transport` is omitted. A separate transport keeps public
78
+ reads independent from the wallet provider. Solana always requires a public
79
+ transport because Wallet Standard accounts authorize transactions but do not
80
+ provide general RPC access.
81
+
82
+ An existing viem wallet client can be passed as
83
+ `createEvmClient({ walletClient })`. Add `publicClient` when reads and receipt
84
+ polling should use a different viem client.
85
+
86
+ ## Create a local-key client
87
+
88
+ A bot or server can use local EVM and Solana keys through the supplied account
89
+ adapters. An Aleo local account comes from `@provablehq/veil-aleo-sdk`, which
90
+ supports delegated or local proving.
91
+
92
+ ```ts
93
+ import {
94
+ createAleoClient,
95
+ createBridgeClient,
96
+ createEvmClient,
97
+ createSolanaClient,
98
+ evmHttp,
99
+ evmPrivateKey,
100
+ solanaHttp,
101
+ solanaKeyPair,
102
+ } from '@provablehq/aleo-bridge-sdk'
103
+ import { loadNetwork } from '@provablehq/veil-aleo-sdk'
104
+
105
+ const aleoNetwork = await loadNetwork('mainnet')
106
+ const {
107
+ publicClient: aleoPublicClient,
108
+ walletClient: aleoWalletClient,
109
+ } = aleoNetwork.createAleoClient({
110
+ privateKey: aleoPrivateKey,
111
+ provingMode: 'delegated',
112
+ })
113
+
114
+ const bridge = createBridgeClient({
115
+ environment: 'mainnet',
116
+ clients: {
117
+ ethereum: createEvmClient({
118
+ transport: evmHttp(ethereumRpcUrl),
119
+ account: evmPrivateKey(evmPrivateKey),
120
+ }),
121
+ solana: createSolanaClient({
122
+ transport: solanaHttp(solanaRpcUrl),
123
+ account: solanaKeyPair(solanaSecretKeyBytes),
124
+ }),
125
+ aleo: createAleoClient({
126
+ publicClient: aleoPublicClient,
127
+ account: aleoWalletClient,
128
+ }),
129
+ },
130
+ })
131
+ ```
132
+
133
+ Local EVM and Solana accounts sign inside the caller's process and broadcast
134
+ through their configured transports. The bridge client never receives the raw
135
+ key after the account adapter is created.
136
+
137
+ ## Find supported assets and routes
138
+
139
+ The registry is the reviewed catalog bundled with the package. Reading it does
140
+ not contact a network or request a wallet signature.
141
+
142
+ ```ts
143
+ const assets = bridge.registry.getAssets({
144
+ environment: bridge.environment,
145
+ chainId: 'aleo',
146
+ })
147
+
148
+ const routes = bridge.registry.getRoutes({
149
+ environment: bridge.environment,
150
+ sourceChainId: 'ethereum',
151
+ destinationChainId: 'aleo',
152
+ })
153
+ ```
154
+
155
+ Applications select assets by chain and asset names. They do not construct
156
+ encoded route strings or copy contract addresses into transfer requests.
157
+ `getRoutes` can also return `metadata-required` entries; check `availability`
158
+ before presenting a route as executable.
159
+
160
+ ## Move an asset across chains
161
+
162
+ Every transfer follows the same caller lifecycle:
163
+
164
+ 1. `quote` checks that the requested transfer is supported and reports current
165
+ costs that can be known before submission.
166
+ 2. `execute` asks the source wallet to authorize the required source-chain
167
+ transactions.
168
+ 3. `wait` follows the submitted transfer until it finishes, fails, or requires
169
+ another wallet authorization.
170
+ 4. `resume` or `complete` runs only when `progress.next` requests that action.
171
+
172
+ ### 1. Quote the transfer
173
+
174
+ The caller supplies the source asset, destination asset, amount, recipient, and
175
+ optional provider. The result reports route-specific fees, balance or approval
176
+ requirements where available, and the plan that must be passed to execution.
177
+ Quoting can read networks and providers, but it does not request a signature or
178
+ move funds.
179
+
180
+ ```ts
181
+ const quote = await bridge.quote({
182
+ source: { chain: 'ethereum', asset: 'wbtc' },
183
+ destination: { chain: 'aleo', asset: 'wbtc' },
184
+ bridgeProtocol: 'hyperlane',
185
+ amount: '0.001',
186
+ sender: ethereumAddress,
187
+ recipient: aleoAddress,
188
+ })
189
+
190
+ if (quote.kind !== 'evm-hyperlane') {
191
+ throw new Error(`Unexpected quote kind: ${quote.kind}`)
192
+ }
193
+
194
+ console.log(quote.amountAtomic)
195
+ console.log(quote.nativeFeeAtomic)
196
+ ```
197
+
198
+ `quote.plan` identifies the exact route, amount, recipient, and reviewed
199
+ deployment that produced the quote. Keep this value unchanged for execution.
200
+
201
+ ### 2. Authorize the source transfer
202
+
203
+ Execution may request more than one wallet transaction. An ERC-20 route can
204
+ require an approval before its bridge deposit. The result contains the latest
205
+ receipt and every transaction identifier already submitted.
206
+
207
+ ```ts
208
+ const execution = await bridge.execute({
209
+ plan: quote.plan,
210
+ onCheckpoint(checkpoint) {
211
+ saveCheckpoint(checkpoint)
212
+ },
213
+ })
214
+ ```
215
+
216
+ Once a source transaction has been submitted, do not call `execute` again for
217
+ the same transfer. Use the returned receipt while the application remains open,
218
+ or recover from the latest checkpoint after an interruption.
219
+
220
+ ### 3. Follow the transfer
221
+
222
+ `wait` reads source confirmation, provider processing, and destination delivery
223
+ where the route exposes verifiable evidence. It does not request another
224
+ signature or submit a transaction.
225
+
226
+ ```ts
227
+ let progress = await bridge.wait({
228
+ progress: {
229
+ next: 'wait',
230
+ plan: quote.plan,
231
+ receipt: execution.receipt,
232
+ },
233
+ })
234
+ ```
235
+
236
+ The `next` field is the only value an application needs to select the next
237
+ lifecycle action:
238
+
239
+ | `progress.next` | Caller action |
240
+ | --- | --- |
241
+ | `done` | Show completion. No further wallet action is required. |
242
+ | `failed` | Show the reported failure. Do not repeat a transaction that already succeeded. |
243
+ | `wait` | Call `wait` again when polling stopped at an application-selected status. |
244
+ | `resume` | Ask the source wallet to submit the remaining source operation. |
245
+ | `complete` | Ask the Aleo recipient to authorize a private USDCx mint. |
246
+
247
+ `resume` is used when work such as an ERC-20 approval succeeded but the source
248
+ deposit was not submitted. It does not repeat the confirmed approval.
249
+
250
+ ```ts
251
+ if (progress.next === 'resume') {
252
+ const resumed = await bridge.resume({ progress })
253
+ progress = await bridge.wait({
254
+ progress: {
255
+ next: 'wait',
256
+ plan: progress.plan,
257
+ receipt: resumed.receipt,
258
+ },
259
+ })
260
+ }
261
+ ```
262
+
263
+ `complete` applies only to an Ethereum USDC deposit that selected a private
264
+ USDCx mint. Circle first attests the deposit. The Aleo recipient then authorizes
265
+ one destination transaction that creates the private record.
266
+
267
+ ```ts
268
+ if (progress.next === 'complete') {
269
+ const destination = await bridge.complete({
270
+ progress,
271
+ privateMintSecretNonce,
272
+ })
273
+ progress = await bridge.wait({
274
+ progress: {
275
+ next: 'wait',
276
+ plan: progress.plan,
277
+ receipt: destination.receipt,
278
+ },
279
+ })
280
+ }
281
+ ```
282
+
283
+ ## Recover after an interruption
284
+
285
+ A checkpoint contains the public transfer intent and transaction identifiers
286
+ needed to find the transfer again. It excludes private keys, Aleo record
287
+ plaintext, proofs, and private-mint secret nonces.
288
+
289
+ The SDK calls `onCheckpoint` at supported submission boundaries. The callback
290
+ does not imply a storage system. A browser can use IndexedDB or local storage;
291
+ a server can use a database or file. Applications that stay open can keep the
292
+ receipt in memory and omit the callback.
293
+
294
+ ```ts
295
+ await bridge.execute({
296
+ plan: quote.plan,
297
+ onCheckpoint(checkpoint) {
298
+ localStorage.setItem('bridge-checkpoint', JSON.stringify(checkpoint))
299
+ },
300
+ })
301
+ ```
302
+
303
+ After a restart, `recover` reconstructs the plan and checks existing network or
304
+ provider state. It never signs, submits, or repeats a transaction.
305
+
306
+ ```ts
307
+ const checkpoint = JSON.parse(localStorage.getItem('bridge-checkpoint')!)
308
+ let progress = await bridge.recover({ checkpoint })
309
+
310
+ if (progress.next === 'wait') {
311
+ progress = await bridge.wait({ progress })
312
+ }
313
+ ```
314
+
315
+ The application then handles `progress.next` by the same table above. A private
316
+ mint nonce must be stored separately because it is intentionally absent from
317
+ the checkpoint.
318
+
319
+ ## Use private assets on Aleo
320
+
321
+ Hyperlane routes mint wrapped assets into public Aleo balances and spend public
322
+ balances when bridging out of Aleo. Shielding and unshielding let the same asset
323
+ move between that public balance and a private Aleo record.
324
+
325
+ ### Unshield before bridging out through Hyperlane
326
+
327
+ An outbound Hyperlane transfer cannot spend a private record directly. Convert
328
+ the amount into the account's public balance before quoting and executing the
329
+ bridge transfer.
330
+
331
+ ```ts
332
+ const conversion = await bridge.unshield({
333
+ asset: { chain: 'aleo', asset: 'sol' },
334
+ amount: '0.01',
335
+ })
336
+
337
+ console.log(conversion.transactionId)
338
+ ```
339
+
340
+ The Aleo wallet selects a sufficient record when it supports wallet-side record
341
+ requests. A local-key caller must supply the encoded record because a local
342
+ account cannot resolve a wallet-side record request. Wait for the Aleo
343
+ transaction to be accepted before spending the resulting public balance.
344
+
345
+ Private USDCx can be burned directly by the xReserve private withdrawal flow.
346
+ It does not need to be unshielded first.
347
+
348
+ ### Shield an asset for private use on Aleo
349
+
350
+ After a Hyperlane transfer arrives, its Aleo balance is public. Convert any
351
+ amount that should be held or spent privately into a record owned by the Aleo
352
+ account.
353
+
354
+ ```ts
355
+ const conversion = await bridge.shield({
356
+ asset: { chain: 'aleo', asset: 'sol' },
357
+ amount: '0.01',
358
+ })
359
+
360
+ console.log(conversion.transactionId)
361
+ ```
362
+
363
+ Shielding and unshielding each submit an Aleo transaction and incur an Aleo
364
+ transaction fee. They are separate from bridge delivery. A failed privacy
365
+ conversion does not repeat or reverse the completed cross-chain transfer.
366
+
367
+ The default registry supports these conversions for wrapped ETH, WBTC, USDT,
368
+ and SOL through their ARC-20 programs, and for USDCx through its ARC-22
369
+ transfers. The current USDCx default uses the empty freeze-list proof. Supply a
370
+ current proof after the deployed freeze-list tree is populated.
371
+
372
+ ## Complete examples
373
+
374
+ The [bridge tutorial](../../examples/bridge/README.md) explains configuration,
375
+ safe read-only runs, mainnet authorization, checkpoints, and each provider's
376
+ observable completion boundary.
377
+
378
+ | Transfer | Example |
379
+ | --- | --- |
380
+ | Ethereum ETH → Aleo ETH | [`eth-to-aleo.ts`](../../examples/bridge/eth-to-aleo.ts) |
381
+ | Ethereum WBTC → Aleo WBTC | [`wbtc-to-aleo.ts`](../../examples/bridge/wbtc-to-aleo.ts) |
382
+ | Aleo ETH → Ethereum ETH | [`eth-to-ethereum.ts`](../../examples/bridge/eth-to-ethereum.ts) |
383
+ | Aleo WBTC → Ethereum WBTC | [`wbtc-to-ethereum.ts`](../../examples/bridge/wbtc-to-ethereum.ts) |
384
+ | Solana SOL → Aleo SOL | [`sol-to-aleo.ts`](../../examples/bridge/sol-to-aleo.ts) |
385
+ | Aleo SOL → Solana SOL | [`sol-to-solana.ts`](../../examples/bridge/sol-to-solana.ts) |
386
+ | Ethereum USDC → Aleo USDCx | [`usdc-to-usdcx.ts`](../../examples/bridge/usdc-to-usdcx.ts) |
387
+ | Aleo USDCx → Ethereum USDC | [`usdcx-to-usdc.ts`](../../examples/bridge/usdcx-to-usdc.ts) |
388
+
389
+ Each script quotes mainnet state and exits without submitting by default. The
390
+ script prints the exact acknowledgement required to authorize real funds.
@@ -0,0 +1,23 @@
1
+ import { AgentTool } from '@provablehq/veil-core/agent';
2
+ export { AgentTool, AgentToolHandler, AgentToolSchema } from '@provablehq/veil-core/agent';
3
+ import { K as BridgeClient } from '../createBridgeClient-DzmEyXfG.js';
4
+ import '@provablehq/veil-core';
5
+ import '../solana-D5Qr6SLa.js';
6
+ import 'viem';
7
+
8
+ /**
9
+ * Creates tools an agent can use to discover and describe cross-chain transfers.
10
+ *
11
+ * The tools list supported assets and routes, validate an amount and recipient,
12
+ * and quote current costs when the selected route exposes them. They cannot
13
+ * request a signature, submit a transaction, or move funds.
14
+ *
15
+ * @param client Bridge client supplying the supported asset and route catalog.
16
+ * @returns Non-fund-moving agent tools for discovering and describing transfers.
17
+ *
18
+ * @example
19
+ * const tools = createBridgeAgentTools(createBridgeClient())
20
+ */
21
+ declare function createBridgeAgentTools(client: BridgeClient): AgentTool[];
22
+
23
+ export { createBridgeAgentTools };
@@ -0,0 +1,7 @@
1
+ import {
2
+ createBridgeAgentTools
3
+ } from "../chunk-NTWXJE7R.js";
4
+ export {
5
+ createBridgeAgentTools
6
+ };
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,93 @@
1
+ // src/agent/tools.ts
2
+ function createBridgeAgentTools(client) {
3
+ return [
4
+ {
5
+ schema: {
6
+ name: "bridge_list_assets",
7
+ description: "List assets available for cross-chain transfers. Returns each chain representation, symbol, decimal precision, and public token identifier without contacting a chain or wallet.",
8
+ inputSchema: {
9
+ type: "object",
10
+ properties: {
11
+ environment: { type: "string", enum: ["mainnet", "testnet"] },
12
+ chainId: { type: "string" },
13
+ symbol: { type: "string" }
14
+ }
15
+ }
16
+ },
17
+ handler: async (params) => {
18
+ const filters = params;
19
+ return client.registry.getAssets({
20
+ ...filters,
21
+ environment: filters.environment ?? client.environment
22
+ });
23
+ }
24
+ },
25
+ {
26
+ schema: {
27
+ name: "bridge_list_routes",
28
+ description: "List supported ways to move assets between chains and the provider responsible for each direction. A metadata-required route is recognized but cannot move funds until its deployed contracts or programs are reviewed.",
29
+ inputSchema: {
30
+ type: "object",
31
+ properties: {
32
+ environment: { type: "string", enum: ["mainnet", "testnet"] },
33
+ protocol: { type: "string", enum: ["xreserve", "hyperlane"] },
34
+ sourceChainId: { type: "string" },
35
+ destinationChainId: { type: "string" },
36
+ symbol: { type: "string" },
37
+ includeUnavailable: { type: "boolean" }
38
+ }
39
+ }
40
+ },
41
+ handler: async (params) => {
42
+ const filters = params;
43
+ return client.registry.getRoutes({
44
+ ...filters,
45
+ environment: filters.environment ?? client.environment
46
+ });
47
+ }
48
+ },
49
+ {
50
+ schema: {
51
+ name: "bridge_quote_transfer",
52
+ description: "Validate and price an intended transfer between two chains through xReserve or Hyperlane. This tool reads current chain or provider state where the selected route exposes live costs, but does not request a wallet signature or move funds.",
53
+ inputSchema: {
54
+ type: "object",
55
+ properties: {
56
+ source: {
57
+ type: "object",
58
+ properties: { chain: { type: "string" }, asset: { type: "string" } },
59
+ required: ["chain", "asset"]
60
+ },
61
+ destination: {
62
+ type: "object",
63
+ properties: { chain: { type: "string" }, asset: { type: "string" } },
64
+ required: ["chain", "asset"]
65
+ },
66
+ bridgeProtocol: { type: "string", enum: ["xreserve", "hyperlane"] },
67
+ amount: { type: "string", description: "Positive decimal amount in source-asset display units." },
68
+ recipient: { type: "string" },
69
+ sender: { type: "string" },
70
+ mintMode: { type: "string", enum: ["public", "record", "private"] }
71
+ },
72
+ required: ["source", "destination", "amount", "recipient"]
73
+ }
74
+ },
75
+ handler: async (params) => jsonSafe(await client.quote(params))
76
+ }
77
+ ];
78
+ }
79
+ function jsonSafe(value) {
80
+ if (typeof value === "bigint") return value.toString();
81
+ if (Array.isArray(value)) return value.map(jsonSafe);
82
+ if (value && typeof value === "object") {
83
+ return Object.fromEntries(
84
+ Object.entries(value).map(([key, entry]) => [key, jsonSafe(entry)])
85
+ );
86
+ }
87
+ return value;
88
+ }
89
+
90
+ export {
91
+ createBridgeAgentTools
92
+ };
93
+ //# sourceMappingURL=chunk-NTWXJE7R.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/agent/tools.ts"],"sourcesContent":["import type { AgentTool } from '@provablehq/veil-core/agent'\nimport type { BridgeClient } from '../clients/createBridgeClient.js'\nimport type { GetAssetsParameters, GetRoutesParameters } from '../types/protocol.js'\n\n/**\n * Creates tools an agent can use to discover and describe cross-chain transfers.\n *\n * The tools list supported assets and routes, validate an amount and recipient,\n * and quote current costs when the selected route exposes them. They cannot\n * request a signature, submit a transaction, or move funds.\n *\n * @param client Bridge client supplying the supported asset and route catalog.\n * @returns Non-fund-moving agent tools for discovering and describing transfers.\n *\n * @example\n * const tools = createBridgeAgentTools(createBridgeClient())\n */\nexport function createBridgeAgentTools(client: BridgeClient): AgentTool[] {\n return [\n {\n schema: {\n name: 'bridge_list_assets',\n description: 'List assets available for cross-chain transfers. Returns each chain representation, symbol, decimal precision, and public token identifier without contacting a chain or wallet.',\n inputSchema: {\n type: 'object',\n properties: {\n environment: { type: 'string', enum: ['mainnet', 'testnet'] },\n chainId: { type: 'string' },\n symbol: { type: 'string' },\n },\n },\n },\n handler: async (params) => {\n const filters = params as GetAssetsParameters\n return client.registry.getAssets({\n ...filters,\n environment: filters.environment ?? client.environment,\n })\n },\n },\n {\n schema: {\n name: 'bridge_list_routes',\n description: 'List supported ways to move assets between chains and the provider responsible for each direction. A metadata-required route is recognized but cannot move funds until its deployed contracts or programs are reviewed.',\n inputSchema: {\n type: 'object',\n properties: {\n environment: { type: 'string', enum: ['mainnet', 'testnet'] },\n protocol: { type: 'string', enum: ['xreserve', 'hyperlane'] },\n sourceChainId: { type: 'string' },\n destinationChainId: { type: 'string' },\n symbol: { type: 'string' },\n includeUnavailable: { type: 'boolean' },\n },\n },\n },\n handler: async (params) => {\n const filters = params as GetRoutesParameters\n return client.registry.getRoutes({\n ...filters,\n environment: filters.environment ?? client.environment,\n })\n },\n },\n {\n schema: {\n name: 'bridge_quote_transfer',\n description: 'Validate and price an intended transfer between two chains through xReserve or Hyperlane. This tool reads current chain or provider state where the selected route exposes live costs, but does not request a wallet signature or move funds.',\n inputSchema: {\n type: 'object',\n properties: {\n source: {\n type: 'object',\n properties: { chain: { type: 'string' }, asset: { type: 'string' } },\n required: ['chain', 'asset'],\n },\n destination: {\n type: 'object',\n properties: { chain: { type: 'string' }, asset: { type: 'string' } },\n required: ['chain', 'asset'],\n },\n bridgeProtocol: { type: 'string', enum: ['xreserve', 'hyperlane'] },\n amount: { type: 'string', description: 'Positive decimal amount in source-asset display units.' },\n recipient: { type: 'string' },\n sender: { type: 'string' },\n mintMode: { type: 'string', enum: ['public', 'record', 'private'] },\n },\n required: ['source', 'destination', 'amount', 'recipient'],\n },\n },\n handler: async (params) => jsonSafe(await client.quote(params as Parameters<BridgeClient['quote']>[0])),\n },\n ]\n}\n\n/** Converts atomic bigint amounts into decimal strings accepted by JSON-based agent transports. */\nfunction jsonSafe(value: unknown): unknown {\n if (typeof value === 'bigint') return value.toString()\n if (Array.isArray(value)) return value.map(jsonSafe)\n if (value && typeof value === 'object') {\n return Object.fromEntries(\n Object.entries(value).map(([key, entry]) => [key, jsonSafe(entry)]),\n )\n }\n return value\n}\n"],"mappings":";AAiBO,SAAS,uBAAuB,QAAmC;AACxE,SAAO;AAAA,IACL;AAAA,MACE,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,aAAa;AAAA,QACb,aAAa;AAAA,UACX,MAAM;AAAA,UACN,YAAY;AAAA,YACV,aAAa,EAAE,MAAM,UAAU,MAAM,CAAC,WAAW,SAAS,EAAE;AAAA,YAC5D,SAAS,EAAE,MAAM,SAAS;AAAA,YAC1B,QAAQ,EAAE,MAAM,SAAS;AAAA,UAC3B;AAAA,QACF;AAAA,MACF;AAAA,MACA,SAAS,OAAO,WAAW;AACzB,cAAM,UAAU;AAChB,eAAO,OAAO,SAAS,UAAU;AAAA,UAC/B,GAAG;AAAA,UACH,aAAa,QAAQ,eAAe,OAAO;AAAA,QAC7C,CAAC;AAAA,MACH;AAAA,IACF;AAAA,IACA;AAAA,MACE,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,aAAa;AAAA,QACb,aAAa;AAAA,UACX,MAAM;AAAA,UACN,YAAY;AAAA,YACV,aAAa,EAAE,MAAM,UAAU,MAAM,CAAC,WAAW,SAAS,EAAE;AAAA,YAC5D,UAAU,EAAE,MAAM,UAAU,MAAM,CAAC,YAAY,WAAW,EAAE;AAAA,YAC5D,eAAe,EAAE,MAAM,SAAS;AAAA,YAChC,oBAAoB,EAAE,MAAM,SAAS;AAAA,YACrC,QAAQ,EAAE,MAAM,SAAS;AAAA,YACzB,oBAAoB,EAAE,MAAM,UAAU;AAAA,UACxC;AAAA,QACF;AAAA,MACF;AAAA,MACA,SAAS,OAAO,WAAW;AACzB,cAAM,UAAU;AAChB,eAAO,OAAO,SAAS,UAAU;AAAA,UAC/B,GAAG;AAAA,UACH,aAAa,QAAQ,eAAe,OAAO;AAAA,QAC7C,CAAC;AAAA,MACH;AAAA,IACF;AAAA,IACA;AAAA,MACE,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,aAAa;AAAA,QACb,aAAa;AAAA,UACX,MAAM;AAAA,UACN,YAAY;AAAA,YACV,QAAQ;AAAA,cACN,MAAM;AAAA,cACN,YAAY,EAAE,OAAO,EAAE,MAAM,SAAS,GAAG,OAAO,EAAE,MAAM,SAAS,EAAE;AAAA,cACnE,UAAU,CAAC,SAAS,OAAO;AAAA,YAC7B;AAAA,YACA,aAAa;AAAA,cACX,MAAM;AAAA,cACN,YAAY,EAAE,OAAO,EAAE,MAAM,SAAS,GAAG,OAAO,EAAE,MAAM,SAAS,EAAE;AAAA,cACnE,UAAU,CAAC,SAAS,OAAO;AAAA,YAC7B;AAAA,YACA,gBAAgB,EAAE,MAAM,UAAU,MAAM,CAAC,YAAY,WAAW,EAAE;AAAA,YAClE,QAAQ,EAAE,MAAM,UAAU,aAAa,yDAAyD;AAAA,YAChG,WAAW,EAAE,MAAM,SAAS;AAAA,YAC5B,QAAQ,EAAE,MAAM,SAAS;AAAA,YACzB,UAAU,EAAE,MAAM,UAAU,MAAM,CAAC,UAAU,UAAU,SAAS,EAAE;AAAA,UACpE;AAAA,UACA,UAAU,CAAC,UAAU,eAAe,UAAU,WAAW;AAAA,QAC3D;AAAA,MACF;AAAA,MACA,SAAS,OAAO,WAAW,SAAS,MAAM,OAAO,MAAM,MAA8C,CAAC;AAAA,IACxG;AAAA,EACF;AACF;AAGA,SAAS,SAAS,OAAyB;AACzC,MAAI,OAAO,UAAU,SAAU,QAAO,MAAM,SAAS;AACrD,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO,MAAM,IAAI,QAAQ;AACnD,MAAI,SAAS,OAAO,UAAU,UAAU;AACtC,WAAO,OAAO;AAAA,MACZ,OAAO,QAAQ,KAAK,EAAE,IAAI,CAAC,CAAC,KAAK,KAAK,MAAM,CAAC,KAAK,SAAS,KAAK,CAAC,CAAC;AAAA,IACpE;AAAA,EACF;AACA,SAAO;AACT;","names":[]}