@provablehq/aleo-bridge-sdk 0.9.0-rc.1 → 0.11.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/README.md +327 -270
- package/dist/agent/index.d.ts +8 -7
- package/dist/agent/index.js +1 -1
- package/dist/chunk-NTWXJE7R.js +93 -0
- package/dist/chunk-NTWXJE7R.js.map +1 -0
- package/dist/chunk-OU6GVGG7.js +606 -0
- package/dist/chunk-OU6GVGG7.js.map +1 -0
- package/dist/createBridgeClient-DzmEyXfG.d.ts +1058 -0
- package/dist/index.d.ts +492 -201
- package/dist/index.js +3058 -867
- package/dist/index.js.map +1 -1
- package/dist/mcp/index.d.ts +8 -6
- package/dist/mcp/index.js +1 -1
- package/dist/mcp/index.js.map +1 -1
- package/dist/solana/index.d.ts +113 -0
- package/dist/solana/index.js +15 -0
- package/dist/solana/index.js.map +1 -0
- package/dist/solana-D5Qr6SLa.d.ts +725 -0
- package/package.json +20 -6
- package/dist/chunk-KG3LFIU5.js +0 -61
- package/dist/chunk-KG3LFIU5.js.map +0 -1
- package/dist/createBridgeClient-BwVZIJl1.d.ts +0 -816
package/README.md
CHANGED
|
@@ -1,334 +1,391 @@
|
|
|
1
1
|
# @provablehq/aleo-bridge-sdk
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
xReserve
|
|
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 versions in lockstep with the
|
|
11
|
+
> `@provablehq/veil-*` packages, but 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.
|
|
5
40
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
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.
|
|
10
81
|
|
|
11
|
-
|
|
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.
|
|
12
91
|
|
|
13
92
|
```ts
|
|
14
|
-
import {
|
|
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
|
+
```
|
|
15
132
|
|
|
16
|
-
|
|
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.
|
|
17
136
|
|
|
18
|
-
|
|
19
|
-
|
|
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,
|
|
20
150
|
sourceChainId: 'ethereum',
|
|
21
151
|
destinationChainId: 'aleo',
|
|
22
152
|
})
|
|
153
|
+
```
|
|
23
154
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
})
|
|
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.
|
|
29
159
|
|
|
30
|
-
|
|
31
|
-
// approve → deposit → wait-attestation → mint
|
|
32
|
-
```
|
|
160
|
+
## Move an asset across chains
|
|
33
161
|
|
|
34
|
-
|
|
35
|
-
and recipient format, then identifies every execution step and the first
|
|
36
|
-
irreversible operation. It does not query live fees, sign, submit, or move
|
|
37
|
-
funds.
|
|
162
|
+
Every transfer follows the same caller lifecycle:
|
|
38
163
|
|
|
39
|
-
|
|
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.
|
|
40
171
|
|
|
41
|
-
|
|
42
|
-
plan. Select `public`, `record`, or `private`; the deprecated
|
|
43
|
-
`privateRecipient: true` option remains an alias for `mintMode: 'private'`.
|
|
172
|
+
### 1. Quote the transfer
|
|
44
173
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
})
|
|
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.
|
|
51
179
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
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,
|
|
55
187
|
recipient: aleoAddress,
|
|
56
|
-
sender: connectedEthereumAccount,
|
|
57
|
-
mintMode: 'private',
|
|
58
|
-
privateMintSecretNonce: '7scalar', // Optional; defaults to 0scalar.
|
|
59
188
|
})
|
|
60
189
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
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)
|
|
67
196
|
```
|
|
68
197
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
`depositToRemote`. It then validates `DepositedToRemote`, derives Circle's
|
|
72
|
-
deposit nonce, builds the canonical 305-byte payload, and returns
|
|
73
|
-
`ATTESTATION_PENDING` with the message hash and resumable protocol state.
|
|
198
|
+
`quote.plan` identifies the exact route, amount, recipient, and reviewed
|
|
199
|
+
deployment that produced the quote. Keep this value unchanged for execution.
|
|
74
200
|
|
|
75
|
-
|
|
76
|
-
commits the intended recipient with BHP256 and directs the xReserve deposit to
|
|
77
|
-
`shielded_usdcx_wrapper.aleo`. Public and record modes do not load Aleo WASM.
|
|
78
|
-
Circle attestation HTTP access is injected so browser, Node, and React Native
|
|
79
|
-
applications can supply their own fetch-compatible transport.
|
|
201
|
+
### 2. Authorize the source transfer
|
|
80
202
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
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.
|
|
84
206
|
|
|
85
207
|
```ts
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
aleo: aleoWalletClient,
|
|
208
|
+
const execution = await bridge.execute({
|
|
209
|
+
plan: quote.plan,
|
|
210
|
+
onCheckpoint(checkpoint) {
|
|
211
|
+
saveCheckpoint(checkpoint)
|
|
91
212
|
},
|
|
92
|
-
xReserveHttpTransport: (url, init) => fetch(url, init),
|
|
93
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.
|
|
94
219
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
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
|
+
},
|
|
99
233
|
})
|
|
100
234
|
```
|
|
101
235
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
and intended Aleo recipient. The wrapper reproduces the recipient commitment, mints publicly to
|
|
105
|
-
its own program address, and transfers the amount to the recipient as a record.
|
|
236
|
+
The `next` field is the only value an application needs to select the next
|
|
237
|
+
lifecycle action:
|
|
106
238
|
|
|
107
|
-
|
|
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. |
|
|
108
246
|
|
|
109
|
-
|
|
110
|
-
|
|
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.
|
|
111
249
|
|
|
112
250
|
```ts
|
|
113
|
-
|
|
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
|
+
```
|
|
114
262
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
evm: injectedProvider as EvmBridgeExecutor,
|
|
119
|
-
},
|
|
120
|
-
})
|
|
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.
|
|
121
266
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
})
|
|
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
|
+
```
|
|
128
282
|
|
|
129
|
-
|
|
130
|
-
plan,
|
|
131
|
-
recipientBytes32: encodedAleoRecipient,
|
|
132
|
-
})
|
|
283
|
+
## Recover after an interruption
|
|
133
284
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
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
|
+
},
|
|
137
300
|
})
|
|
138
301
|
```
|
|
139
302
|
|
|
140
|
-
`
|
|
141
|
-
|
|
142
|
-
or submit a transaction.
|
|
303
|
+
After a restart, `recover` reconstructs the plan and checks existing network or
|
|
304
|
+
provider state. It never signs, submits, or repeats a transaction.
|
|
143
305
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
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
|
+
```
|
|
150
314
|
|
|
151
|
-
The
|
|
152
|
-
|
|
153
|
-
|
|
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.
|
|
154
318
|
|
|
155
|
-
|
|
156
|
-
submitted transaction identifiers. A timeout does not report the transaction as
|
|
157
|
-
failed. A confirmed dispatch returns `DELIVERY_PENDING` and includes the
|
|
158
|
-
Hyperlane message id when the Mailbox `DispatchId` event is present.
|
|
319
|
+
## Use private assets on Aleo
|
|
159
320
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
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.
|
|
163
324
|
|
|
164
|
-
|
|
325
|
+
### Unshield before bridging out through Hyperlane
|
|
165
326
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
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.
|
|
169
330
|
|
|
170
331
|
```ts
|
|
171
|
-
const
|
|
172
|
-
|
|
173
|
-
amount: '
|
|
174
|
-
recipient: ethereumRecipient,
|
|
332
|
+
const conversion = await bridge.unshield({
|
|
333
|
+
asset: { chain: 'aleo', asset: 'sol' },
|
|
334
|
+
amount: '0.01',
|
|
175
335
|
})
|
|
176
336
|
|
|
177
|
-
|
|
178
|
-
plan,
|
|
179
|
-
userRecord,
|
|
180
|
-
merkleProof,
|
|
181
|
-
// Default: private
|
|
182
|
-
})
|
|
337
|
+
console.log(conversion.transactionId)
|
|
183
338
|
```
|
|
184
339
|
|
|
185
|
-
|
|
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.
|
|
186
344
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
- `public` calls `burn_public` for public or program-owned balances.
|
|
190
|
-
- `public-as-signer` calls `burn_public_as_signer` when the public balance must
|
|
191
|
-
be proven to belong to the EOA signer.
|
|
345
|
+
Private USDCx can be burned directly by the xReserve private withdrawal flow.
|
|
346
|
+
It does not need to be unshielded first.
|
|
192
347
|
|
|
193
|
-
|
|
194
|
-
left-padded to `[u8; 32]`. ARC domain `26u32` is recorded in the registry but is
|
|
195
|
-
not selectable through the Ethereum route. Pause, freeze-list, and mutable
|
|
196
|
-
minimum/maximum burn checks execute atomically in the deployed Aleo program.
|
|
348
|
+
### Shield an asset for private use on Aleo
|
|
197
349
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
assets, and directional routes. Applications can pass a reviewed replacement:
|
|
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.
|
|
202
353
|
|
|
203
354
|
```ts
|
|
204
|
-
const
|
|
205
|
-
|
|
206
|
-
|
|
355
|
+
const conversion = await bridge.shield({
|
|
356
|
+
asset: { chain: 'aleo', asset: 'sol' },
|
|
357
|
+
amount: '0.01',
|
|
207
358
|
})
|
|
359
|
+
|
|
360
|
+
console.log(conversion.transactionId)
|
|
208
361
|
```
|
|
209
362
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
remains `metadata-required`, carries `aleoPlaceholderConfiguration: true`, and
|
|
240
|
-
`executeAleoHyperlaneTransferRemote` throws before calling the wallet. Use
|
|
241
|
-
`buildAleoHyperlaneTransferRemoteCall` only to inspect and integrate its ABI
|
|
242
|
-
until the configuration has been reviewed and replaced.
|
|
243
|
-
|
|
244
|
-
For USAD, the current dummy values are:
|
|
245
|
-
|
|
246
|
-
- `token_type`: `0u8`; `token_id`: `0field`
|
|
247
|
-
- `token_owner`, `ism`, `hook`, and all four allowance spenders: the same
|
|
248
|
-
development-only Aleo address
|
|
249
|
-
- remote-router recipient: 32 zero bytes; remote-router gas: `0u128`
|
|
250
|
-
- destination recipient limbs are derived from the Ethereum or Solana address
|
|
251
|
-
in the transfer plan
|
|
252
|
-
- all four credit allowance amounts: `0u64`
|
|
253
|
-
|
|
254
|
-
The WBTC route is partially populated from mainnet
|
|
255
|
-
[`hyp_warp_token_wbtc_v2.aleo`](https://explorer.provable.com/program/hyp_warp_token_wbtc_v2.aleo),
|
|
256
|
-
edition `0`. Its `app_metadata[true]` token type, owner, ISM, hook, token ID,
|
|
257
|
-
and `8u8` local/remote decimals are verified and are not placeholders. Its
|
|
258
|
-
first hook allowance amount is the live gas quote supplied at execution time.
|
|
259
|
-
|
|
260
|
-
The WBTC Ethereum remote router is also verified: domain `1u32`, recipient
|
|
261
|
-
`0x20CDC85778b732073F7EecEF3DF25c0d310f8772` left-padded to `[u8; 32]`, and
|
|
262
|
-
gas `68000u128`. `transfer_remote_as_signer` is selectable with
|
|
263
|
-
`mode: 'signer'`. Its allowance spender positions and three unused zero amounts
|
|
264
|
-
match the reviewed call shape. The first hook allowance amount remains dynamic;
|
|
265
|
-
the observed `9138947u64` applies only to the sample transaction and is not
|
|
266
|
-
stored as a route-wide cap.
|
|
267
|
-
|
|
268
|
-
The ETH route is populated from current mainnet app metadata and the reviewed
|
|
269
|
-
[`transfer_remote_as_signer` transaction](https://explorer.provable.com/transaction/at1vu0yckkms887zkl3qz7plnncd56jtf5zeal4uj2808upsjkusy8q7yp9v8).
|
|
270
|
-
Its Ethereum router is `0x38D447694f5c1f773ae3132cf93bF30B7Ec1Fa5A`,
|
|
271
|
-
left-padded to `[u8; 32]`, with domain `1u32` and gas `44000u128`. The
|
|
272
|
-
transaction's `8174147u64` first allowance is an observed dispatch quote and is
|
|
273
|
-
not stored as a route-wide cap. As with WBTC, the first hook allowance amount
|
|
274
|
-
is quoted live at execution time. Ethereum recipient limbs are derived from
|
|
275
|
-
`plan.recipient`.
|
|
276
|
-
|
|
277
|
-
The USDT route uses current edition `1` app metadata and the verified Ethereum
|
|
278
|
-
remote router at domain `1u32`: `0x3C2064D78e4578E8F936E3db42aEF044E33FBF31`
|
|
279
|
-
with gas `68000u128`. The reviewed signer transaction targets BSC domain `56`,
|
|
280
|
-
so it validates the shared allowance layout but is not used as the Ethereum
|
|
281
|
-
router source. Its `1994463u64` first allowance is transaction-specific. The
|
|
282
|
-
official Hyperlane route config records Aleo and Ethereum USDT as 6-decimal
|
|
283
|
-
assets with a `1000000000000` scale; the Aleo program's app metadata must still
|
|
284
|
-
be passed exactly as `local_decimals: 6u8, remote_decimals: 18u8`. The builder
|
|
285
|
-
therefore reads these contract metadata decimals instead of inferring both from
|
|
286
|
-
the endpoint assets.
|
|
287
|
-
|
|
288
|
-
The SOL route uses verified edition `0` app metadata with 9 local and remote
|
|
289
|
-
decimals. Its Solana destination is Hyperlane domain `1399811149u32`, router
|
|
290
|
-
`8YGT2pZwyZe94qBpGzWfY2TMEVcwaQ1bXAE7YAgpUaM7`, and gas `300000u128`. The
|
|
291
|
-
reviewed signer transition confirms the shared allowance layout; its
|
|
292
|
-
`7661056u64` first allowance is transaction-specific and is not stored as a
|
|
293
|
-
route-wide value. The Aleo SOL asset locator now points to the v2 warp program
|
|
294
|
-
and token identifier from the pinned Hyperlane route configuration.
|
|
295
|
-
|
|
296
|
-
All Aleo Warp Routes share the verified mainnet
|
|
297
|
-
[`hyp_mailbox.aleo`](https://explorer.provable.com/program/hyp_mailbox.aleo)
|
|
298
|
-
mailbox configuration, edition `0`. The `transfer_remote` input now uses its
|
|
299
|
-
`default_hook` and `required_hook`. The registry also records the local domain,
|
|
300
|
-
default ISM, dispatch proxy, owner, and the nonce/process count observed during
|
|
301
|
-
the 2026-08-17 review. The nonce and process count are mutable observations and
|
|
302
|
-
are not transaction inputs.
|
|
303
|
-
|
|
304
|
-
Before enabling USAD submission, replace and verify every field still reported
|
|
305
|
-
by `placeholderFields` for that route. Then remove
|
|
306
|
-
`aleoPlaceholderConfiguration` and change the route availability to `active` in
|
|
307
|
-
a reviewed registry snapshot, as the 2026-08-26 review did for ETH, WBTC, USDT,
|
|
308
|
-
and SOL.
|
|
309
|
-
|
|
310
|
-
## Exports
|
|
311
|
-
|
|
312
|
-
- `createBridgeClient`
|
|
313
|
-
- `getAssets` and `getRoutes`
|
|
314
|
-
- `prepareTransfer`
|
|
315
|
-
- `quoteEvmHyperlaneTransfer` and `executeEvmHyperlaneTransfer`
|
|
316
|
-
- `quoteEvmXReserveTransfer`, `executeEvmXReserveTransfer`, and `getXReserveAttestation`
|
|
317
|
-
- `executeXReservePrivateMint`
|
|
318
|
-
- `buildXReserveBurnCall` and `executeXReserveBurn`
|
|
319
|
-
- `buildAleoHyperlaneTransferRemoteCall` and `executeAleoHyperlaneTransferRemote`
|
|
320
|
-
- Aleo address, xReserve hook, nonce, payload, and message-hash utilities
|
|
321
|
-
- Ethereum and Solana Hyperlane recipient serialization for Aleo-origin transfers
|
|
322
|
-
- `DEFAULT_BRIDGE_REGISTRY` and `validateBridgeRegistry`
|
|
323
|
-
- Protocol-neutral asset, route, plan, fee, step, status, and receipt types
|
|
324
|
-
- `createBridgeAgentTools` from `/agent`
|
|
325
|
-
- `createBridgeMcpServer` from `/mcp`
|
|
326
|
-
|
|
327
|
-
The agent and MCP surfaces expose discovery and planning only. They do not expose
|
|
328
|
-
fund-moving wallet actions.
|
|
329
|
-
|
|
330
|
-
## Next implementation phases
|
|
331
|
-
|
|
332
|
-
1. Add protocol delivery tracking for relayer-driven xReserve and Hyperlane mints.
|
|
333
|
-
2. Replace and review the Aleo-origin USAD placeholders, then add destination confirmation for withdrawals.
|
|
334
|
-
3. Add injected Solana execution and gated protocol testnets.
|
|
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
|
+
| Aleo USDT → Ethereum USDT | [`usdt-to-ethereum.ts`](../../examples/bridge/usdt-to-ethereum.ts) |
|
|
385
|
+
| Solana SOL → Aleo SOL | [`sol-to-aleo.ts`](../../examples/bridge/sol-to-aleo.ts) |
|
|
386
|
+
| Aleo SOL → Solana SOL | [`sol-to-solana.ts`](../../examples/bridge/sol-to-solana.ts) |
|
|
387
|
+
| Ethereum USDC → Aleo USDCx | [`usdc-to-usdcx.ts`](../../examples/bridge/usdc-to-usdcx.ts) |
|
|
388
|
+
| Aleo USDCx → Ethereum USDC | [`usdcx-to-usdc.ts`](../../examples/bridge/usdcx-to-usdc.ts) |
|
|
389
|
+
|
|
390
|
+
Each script quotes mainnet state and exits without submitting by default. The
|
|
391
|
+
script prints the exact acknowledgement required to authorize real funds.
|