Skip to main content

Aleo Bridge SDK

Bring assets from Ethereum or Solana to Aleo for payments and applications, or withdraw them back to their source chain. Hyperlane carries ETH, WBTC, USDT, and SOL; Circle xReserve connects Ethereum USDC with Aleo USDCx.

Review the cost before sending, monitor whether the recipient received the funds, and recover an interrupted transfer without making another deposit. For USDC, choose between public delivery, a private balance, and a private balance that also conceals the Aleo recipient in the Ethereum deposit.

See the runnable examples for step-by-step tutorials on bridging to and from Aleo, shielding assets, and recovering interrupted transfers.

Install

The bridge package includes the clients needed for Ethereum, Solana, and Aleo, along with delegated proving for Aleo transactions. Install it in a Python 3.10 or later environment before following the examples:

python -m pip install aleo-bridge-sdk

Import the package as aleo_bridge.

Examples

The installed package includes runnable examples for quotes, transfers, shielding, and recovery. Start with a script's command-line help:

python -m aleo_bridge.examples.quote_transfer --help

Use any script name from the examples guide after aleo_bridge.examples., without the .py extension. No checkout is needed.

Supported pairs

The bridge supports transfers to and from Aleo, connecting assets on Ethereum and Solana with their corresponding assets on Aleo. Funds can be brought to Aleo for use in payments and applications, then bridged back to the supported external chain.

The table below shows the supported mainnet pairs in both directions, including the asset sent, the asset received, and the provider handling the transfer. Choose the source chain and asset first, then find the corresponding destination:

Source chain Source asset Destination chain Destination asset Provider
Aleo ETH Ethereum ETH Hyperlane
Aleo WBTC Ethereum WBTC Hyperlane
Aleo USDT Ethereum USDT Hyperlane
Aleo SOL Solana SOL Hyperlane
Aleo USDCx Ethereum USDC Circle xReserve
Ethereum ETH Aleo ETH Hyperlane
Ethereum WBTC Aleo WBTC Hyperlane
Ethereum USDT Aleo USDT Hyperlane
Ethereum USDC Aleo USDCx Circle xReserve
Solana SOL Aleo SOL Hyperlane

Setup

To bridge assets to and from Aleo, create a Bridge client with the accounts and network connections needed for the transfer. The client uses those connections to check balances, quote costs, submit transactions, and monitor whether the recipient has received the funds.

A bridge transfer can still be in progress when the application closes or loses its connection. A journal is a local record of the transfer's details and submitted transaction IDs, saved as checkpoints while the transfer advances. After a restart, these checkpoints let the application identify the original transfer, check what completed, and continue unfinished steps without starting another transfer.

To retain this recovery information between sessions, attach a FileCheckpointStore when creating the Bridge client, as shown below.

The setup below creates an Aleo account connection, adds Ethereum, and attaches a journal. Solana can be added afterward for transfers involving SOL.

Run connected examples in the same Python session. Unless marked as observed, output comments are illustrative; addresses, transaction IDs, and fees vary by transfer.

import os
from aleo import Aleo, HTTPProvider
from aleo_bridge import Bridge, Ethereum, FileCheckpointStore

aleo = Aleo(HTTPProvider("https://edge.provable.com/api", network="mainnet"))
aleo.default_account = aleo.account.from_private_key(os.environ["ALEO_PRIVATE_KEY"])
ethereum = Ethereum(
    "https://ethereum-rpc.publicnode.com",
    private_key=os.environ["EVM_PRIVATE_KEY"],
)
store = FileCheckpointStore("~/.aleo-bridge/checkpoints")
bridge = Bridge(aleo, ethereum=ethereum, checkpoints=store)
recipient = bridge.aleo_address()  # The configured account's aleo1… address.

To send or receive SOL through the bridge, include the Solana connection:

from aleo_bridge import Solana

solana = Solana(
    os.environ["SOLANA_RPC_URL"],
    private_key=os.environ["SOLANA_PRIVATE_KEY"],
)
bridge = Bridge(aleo, ethereum=ethereum, solana=solana, checkpoints=store)

Bridge assets

The following walkthrough sends 0.001 WBTC from Ethereum to the Aleo recipient configured in Setup. It covers the full transfer: reviewing the cost, submitting the deposit, and monitoring delivery.

The sender needs WBTC for the transfer and ETH for Ethereum transaction fees. Complete the steps in order, retaining the quote and progress returned along the way.

  1. Get a quote with quote and review fees and the expected amount received.
  2. Accept the quote by submitting its plan with execute.
  3. Monitor delivery with wait.
  4. If another action is requested, use resume for unfinished source work or complete for a private USDCx claim.

1. Get a bridge quote

A bridge quote shows the expected cost and amount received so the sender can decide whether to proceed. Requesting one reads current network information without signing or sending funds.

For this transfer, specify WBTC on both chains, the amount to send, and the Aleo recipient. Then inspect the fees and expected output. Amounts use display units: "0.001" means 0.001 WBTC.

quote = bridge.quote(
    source_chain="ethereum",
    source_asset="wbtc",
    destination_chain="aleo",
    destination_asset="wbtc",
    amount="0.001",  # 0.001 WBTC, not atomic units.
    recipient=recipient,  # Aleo address receiving the WBTC.
)

for fee in quote.fees:
    print(fee.kind, fee.amount, fee.asset_id, "estimated" if fee.estimated else "")
    # Example: network 0.0001 ethereum/eth estimated (illustrative fee).
print(quote.amount_out)  # "0.001" WBTC for this Hyperlane quote.

Use bridge_protocol="hyperlane" or "xreserve" if more than one provider matches the transfer. A route selected from bridge.routes(...) can also be passed as route=. The API can infer a destination asset when only one route fits; naming both assets keeps the intended transfer clear.

Keep quote.plan unchanged when accepting the quote so the submitted transfer uses the reviewed asset, amount, and recipient. Request a new quote to change those details.

2. Submit a bridge transaction from the source chain

The source transaction deposits the sender's funds into the bridge so they can be delivered on the destination chain. This is the step that commits funds and pays source-chain transaction fees.

After accepting the quote, submit its plan. A token transfer may first require an approval, so one bridge transfer can involve several transactions. USDT may also need an existing allowance reset before approval.

Call execute once and retain the returned progress to monitor the transfer. The journal saves checkpoints as submission advances, allowing the application to recover if it closes between approval and deposit.

def show_checkpoint(checkpoint):
    print("Checkpoint ID:", checkpoint.id)  # Copy this ID for store.load(...).

progress = bridge.execute(quote.plan, on_checkpoint=show_checkpoint)
print(progress.receipt.source_tx_id)  # Ethereum transaction hash: 0x… (64 hex digits).

Once a source transaction has been submitted, do not call execute again for the same transfer. Use the returned progress while the process stays alive, or recover from the latest checkpoint after an interruption.

3. Monitor bridge progress

After submission, the bridge still needs to confirm the deposit and deliver the funds. Monitoring establishes whether the recipient can use them or needs to take another action, such as claiming private USDCx.

Pass the progress returned by submission to wait, then inspect the next action. Monitoring does not sign or send another transaction.

progress = bridge.wait(progress)
print(progress.next)  # "done" when delivered; otherwise inspect the next action.

Read progress.next to decide whether the recipient can use the funds or another action is needed:

progress.next Caller action
done Show completion. No further action is required.
failed Show progress.error. Do not repeat a transaction that already succeeded.
wait Call wait again; polling stopped at an application-selected status.
resume Submit the remaining source operation with resume.
complete Authorize the private USDCx mint with complete.

A monitoring timeout leaves delivery unresolved; it does not cancel the deposit. Keep checking the existing transfer instead of sending again. wait allows 20 minutes by default and raises PollingTimeoutError with the latest progress when that time expires.

Use this in place of the wait call above to keep that progress for another check:

from aleo_bridge import PollingTimeoutError

try:
    progress = bridge.wait(progress, timeout_seconds=1200)
except PollingTimeoutError as exc:
    if exc.progress is None:
        raise
    progress = exc.progress

print(progress.next, progress.receipt.source_tx_id)  # Example while pending: wait 0x…

If an approval succeeded but the deposit remains unfinished, continue the transfer with resume when requested. It can submit the missing transaction without repeating confirmed work. After deciding to continue:

if progress.next == "resume":
    progress = bridge.resume(progress)
    progress = bridge.wait(progress)

A Private Bridge USDCx deposit needs the recipient to claim the funds with their Aleo account and original secret nonce. The USDC Bridging Guide explains that choice and the complete call used to claim.

Recover Funds

An application can lose its connection or close while a bridge transfer is still in progress. Recovery finds that existing transfer, checks whether the funds arrived, and identifies any remaining action. It does not refund or repeat the deposit.

Start with the saved journal if one is available. The examples below show how to recover a known checkpoint, find a transfer in the journal, or reconstruct a supported transfer from chain history when no files remain.

A bridge journal saves checkpoints—records identifying the transfer and its submitted transactions—so monitoring can continue after a restart. If no files remain, some transfers can be recovered using their on-chain history.

Recover with a bridge journal

A saved checkpoint identifies the transfer and the work already submitted, allowing monitoring to continue after a restart. This path loads that record and asks the network for the transfer's current progress.

Reopen the journal with the same network and connections. Select the latest checkpoint ID from the submission callback or journal listing. New transfers use a stable, readable filename such as 2026-09-25_001_ethereum-wbtc_to_aleo-wbtc_0.001.json. The date is UTC; the counter distinguishes transfers started that day, even if their details match. The name is reserved before submission and stays unchanged through recovery. Pass the filename without .json to store.load(...).

The journal retains its counter in hidden metadata, so deleting a completed checkpoint does not reuse its number. Keep .journal-counter and .journal.lock with the journal. Failed attempts can leave gaps; counters are local to this journal, not globally unique.

For a concrete example, the repository includes a checkpoint from a confirmed Solana-to-Aleo transfer. It was reconstructed from the original transaction and checked against mainnet. Its filename records when the example journal entry was created, not when the original transaction was submitted. The Solana signature remains inside the JSON. Run this example from the bridge-sdk directory; it reads the saved file and network without sending funds:

from aleo import Aleo, HTTPProvider
from aleo_bridge import Bridge, FileCheckpointStore, Solana

example_store = FileCheckpointStore("examples/checkpoints")
example_bridge = Bridge(Aleo(HTTPProvider()), solana=Solana())
checkpoint_id = (
    "2026-09-25_001_solana-sol_to_aleo-sol_676.2"
)
checkpoint = example_store.load(checkpoint_id)
if checkpoint is None:
    raise ValueError(f"No saved checkpoint for {checkpoint_id}")

progress = example_bridge.recover(checkpoint)
print(progress.next, progress.error)  # Observed on 2026-09-25: wait None.

This checkpoint belongs to an existing transfer, not the account configured in Setup. Recovery reported a confirmed source transaction with delivery still pending when checked. To recover an application's own transfer, use its checkpoint store and the ID returned by that checkpoint. Older checkpoints remain loadable by their original transaction or message IDs. checkpoint.id is the journal key; checkpoint.receipt_id identifies the receipt and can change as approval, submission, and delivery advance.

Recovery reports whether to keep waiting, finish a submission, or claim the funds. It does not authorize those actions. Follow progress.next:

progress.next Action
wait Call bridge.wait(progress) to continue monitoring.
resume Call bridge.resume(progress) to submit the unfinished source operation.
complete Call bridge.complete(progress, secret_nonce=secret_nonce) to mint private USDCx on Aleo.
done Delivery is complete; no further action is needed.
failed Inspect progress.error before deciding what to do.

resume and complete can submit transactions. A private USDCx mint requires the original secret nonce, which must be stored separately from the journal. Do not call execute again after an ambiguous submission. A timeout or lost RPC response does not establish that the original transaction failed.

Find saved bridge transactions

The journal can contain several transfers, and the checkpoint ID may not be at hand. Listing the saved entries helps identify the intended transfer from its asset, amount, and recipient.

Load the entries, inspect their details, and select one for recovery. This step reads local files without contacting a network:

result = store.load_checkpoints()

for checkpoint in result.checkpoints:
    print(checkpoint.id)  # Example: 2026-09-25_001_ethereum-wbtc_to_aleo-wbtc_0.001.
    print(checkpoint.intent["source"])  # {"chain": "ethereum", "asset": "wbtc"}
    print(checkpoint.intent["amount"])  # "0.001" for the WBTC example.

for error in result.errors:
    print(error.path, error.error)  # Identifies an unreadable file and the reason.

Select the intended transfer from result.checkpoints and pass it to recover to check its current status. Entries are ordered by file modification time, oldest first. An entry in result.errors means a file could not be loaded; it does not mean the associated transfer failed.

Recover without saved files

Losing the journal does not remove a submitted transfer from the chain. For supported routes, the original transaction and its transfer details can be used to restore monitoring without any saved files.

First locate the bridge deposit or dispatch in the source wallet's history or a block explorer. Check its status, asset, amount, sender, and destination recipient. A token approval alone does not identify a completed deposit.

For a confirmed Ethereum-to-Aleo Hyperlane transfer, those details are enough to reconstruct the recovery data in memory. The example below recovers a WBTC transfer on mainnet. Enter the original transfer's details from the explorer; the amount is in WBTC, not its smallest units.

Use the Aleo and Ethereum connections from Setup, but construct the bridge without a checkpoint store. This example reads the network and does not load or write a journal, sign a transaction, or send funds:

bridge = Bridge(aleo, ethereum=ethereum)
source_tx_id = input("Confirmed Ethereum bridge transaction hash: ").strip()  # 0x + 64 hex digits.
sender = input("Original Ethereum sender address: ").strip()  # 0x + 40 hex digits.
recipient = input("Original Aleo recipient address: ").strip()  # aleo1… address from the deposit.
amount = input("Original amount in WBTC: ").strip()  # Example: "0.001".

route = bridge.routes(
    source_chain="ethereum",
    source_asset="wbtc",
    destination_chain="aleo",
    bridge_protocol="hyperlane",
)[0]

recovery_data = {
    "version": 1,
    "intent": {
        "source": {"chain": "ethereum", "asset": "wbtc"},
        "destination": {"chain": "aleo", "asset": "wbtc"},
        "bridgeProtocol": "hyperlane",
        "amount": amount,
        "sender": sender,
        "recipient": recipient,
    },
    "route": {"id": route.id, "registryVersion": bridge.registry.version},
    "source": {"transactionId": source_tx_id},
}
progress = bridge.recover(recovery_data)
print(progress.next, progress.error)  # Example: wait None; done None after delivery.

This restores monitoring from the original transaction without a saved file. Use bridge.wait(progress) to check delivery on Aleo; no new deposit is needed. The installed SDK must still support the original route. The recovery data above supplies the same transfer details that a journal would have retained.

Other routes may need additional information:

  • Private USDCx deposits: recover the original commitment data from the Ethereum deposit and retain the original secret nonce for the claim. A lost nonce cannot be reconstructed from public chain data; the recipient cannot complete the claim through this flow without it.
  • Aleo-origin transfers: recovery can track source confirmation, but some delivery checks depend on the destination balance recorded before submission. Without that information, confirm receipt on the destination chain; the SDK may continue reporting delivery as pending.
  • Transactions never broadcast: an unsubmitted proof cannot be recovered from the chain. First establish that no source transfer was submitted before starting another one.

The SDK does not yet reconstruct every route from a transaction hash alone. The example above applies specifically to confirmed Ethereum-to-Aleo Hyperlane transfers; do not reuse its recovery data for a different route.

Keep any private-mint nonce separately: restoring a checkpoint cannot replace that claim secret. Checkpoints exclude private keys and private record plaintext, but can include an authorized Aleo transaction awaiting broadcast. Protect the journal accordingly. Applications with existing storage can save checkpoints from on_checkpoint using checkpoint.to_json().

USDC Bridging Guide

USDC sent from Ethereum arrives on Aleo as USDCx, where it can be used in payments and applications. The bridge offers three delivery options with different visibility and claim requirements.

First choose whether the recipient needs a public or private balance and whether the deposit may reveal their Aleo address. The examples then show private delivery with and without a separate recipient claim.

Choose how the recipient will use the funds

The choice affects both how the funds can be used on Aleo and what the Ethereum deposit reveals. Compare the options below before requesting a quote; the table maps each choice to its mint_mode setting.

Public Bridge delivers a public balance for payments and applications that use publicly visible balances. Anyone can read the recipient's public USDCx balance. Delivery requires no further action from the recipient.

Public Bridge to Private Balance delivers a private record for payments and applications that accept private funds. Its contents are encrypted rather than stored in a public balance. The bridge can deliver this record without requiring the recipient to return and claim it. However, the Ethereum deposit still reveals the recipient's Aleo address: receiving funds privately does not, by itself, hide who received the deposit.

Private Bridge suits transfers where the Ethereum deposit should not reveal the recipient's Aleo address. The recipient must return to claim the funds and keep a secret needed for that claim. Choose this option only when the recipient can complete that extra step.

The Ethereum sender and deposited USDC amount remain public in all three cases. Concealing the Aleo address does not conceal the Ethereum transaction.

Recipient's needs Delivery choice Quote setting
A public balance, with no claim step Public Bridge mint_mode="public" (default)
Funds for private use, with no claim step; the deposit may reveal the Aleo address Public Bridge to Private Balance mint_mode="record"
Funds for private use without publishing the Aleo address in the deposit; the recipient can claim them later Private Bridge mint_mode="private"

Bridge Privately: Hide the balance

Public Bridge to Private Balance delivers an encrypted USDCx record ready for private payments. The recipient does not need to return for a separate claim, but the Ethereum deposit still identifies their Aleo address.

This example requests a quote for that delivery option, submits the deposit, and monitors it until the funds arrive.

The sender needs USDC for the transfer and ETH for transaction fees. Review the cost and expected amount received before submitting the deposit.

Using the client from Setup, request a private record with mint_mode="record". Change it to "public" to receive a public balance instead:

usdc_quote = bridge.quote(
    source_chain="ethereum",
    source_asset="usdc",
    destination_chain="aleo",
    destination_asset="usdcx",
    amount="2",  # 2 USDC, not 2 atomic units.
    recipient=bridge.aleo_address(),
    mint_mode="record",  # Use "public" to receive a public balance.
)
print(usdc_quote.fees)  # Fee entries include asset_id, amount, and estimated.
print(usdc_quote.amount_out)  # Expected USDCx amount in display units.

Submit the deposit after accepting the quote, then monitor it until delivery finishes. The recipient does not need to take part in this step:

usdc_progress = bridge.execute(usdc_quote.plan)
usdc_progress = bridge.wait(usdc_progress)
print(usdc_progress.next, usdc_progress.error)  # done None when delivery completes.

Bridge Privately: Hide the balance and recipient

Private Bridge conceals the recipient's Aleo address in the Ethereum deposit and delivers funds as a private balance. Unlike automatic delivery, it requires the recipient to claim the funds before spending them.

The flow has three stages: retain a secret nonce, submit the deposit using that nonce, and claim the USDCx when it is ready. The nonce is a random value used to conceal the address; the claim requires both the original nonce and the recipient's Aleo account.

Save the nonce before sending funds and retain it until the claim completes. Losing it prevents the recipient from completing the claim through this flow. The bridge journal does not save it, so restoring the journal alone is not enough. The default 0scalar provides no secrecy; use a securely generated nonce for this option.

This is an alternative to the automatic delivery example above. Store the nonce as an Aleo scalar literal in BRIDGE_MINT_SECRET_NONCE. The example uses the configured Aleo account as the recipient, so that account can claim the funds later. Request a quote with mint_mode="private":

secret_nonce = os.environ["BRIDGE_MINT_SECRET_NONCE"]  # Aleo scalar: decimal digits + "scalar".
private_quote = bridge.quote(
    source_chain="ethereum",
    source_asset="usdc",
    destination_chain="aleo",
    destination_asset="usdcx",
    amount="2",  # 2 USDC, not 2 atomic units.
    recipient=bridge.aleo_address(),
    mint_mode="private",
    secret_nonce=secret_nonce,
)
print(private_quote.fees)  # Review Ethereum fees before submitting.
print(private_quote.amount_out)  # Expected USDCx amount in display units.

After the deposit is confirmed and Circle has attested it, the recipient can claim the USDCx. progress.next == "complete" indicates that the claim is ready. Claiming requires the recipient to authorize an Aleo transaction and can incur an Aleo fee:

private_progress = bridge.execute(private_quote.plan, secret_nonce=secret_nonce)
private_progress = bridge.wait(private_progress)

if private_progress.next == "complete":  # The deposit is ready for the recipient to claim.
    private_progress = bridge.complete(private_progress, secret_nonce=secret_nonce)
    private_progress = bridge.wait(private_progress)

print(private_progress.next, private_progress.error)  # done None after the claim confirms.

If the application closes or monitoring times out, the deposit may still be in progress. Recover the existing transfer rather than sending USDC again. Keep the same nonce for any remaining deposit or claim step; see Recover Funds.

Shielding Assets

Assets already held on Aleo can be moved between a public balance and an encrypted private record. Shielding prepares funds for private payments; unshielding makes them public when a bridge withdrawal requires it. Earlier public deposits remain visible.

Whether either step is needed depends on the bridge provider. Check the requirements below, then shield or unshield only the amount needed.

  • Hyperlane delivers assets to public balances and requires public funds for withdrawals. Shield after delivery for private use on Aleo; unshield before bridging back to Ethereum or Solana.
  • xReserve can deliver USDCx as a public balance or a private record. Private delivery needs no additional shielding. A private USDCx withdrawal spends the record directly, so it needs no unshielding. Use mode="public" when withdrawing from a public balance.

Shield a public balance

Shielding lets the account use publicly held tokens in private payments and applications. The funds must already be available in its public Aleo balance.

After bridge delivery confirms, select the amount to shield and submit the conversion. This example shields 0.01 bridged SOL:

receipt = bridge.shield("aleo/sol", amount="0.01").delegate()  # Shield 0.01 SOL on Aleo.
print(receipt.transaction_id)  # Aleo transaction ID, beginning with at1.

Unshield for a Hyperlane withdrawal

Hyperlane withdrawals spend public balances, so funds held in a private record must be unshielded first. This step makes the withdrawal amount public on Aleo; it does not yet send funds to another chain.

First select an unspent record with record=, or use the hosted scanner to find one. Then unshield the required amount and wait for confirmation before starting the bridge withdrawal.

Scanner registration shares the account's view key with the service, which can then decrypt the account's records. Supply the record explicitly to avoid that disclosure. If hosted discovery is acceptable, register the account:

registration = bridge.aleo.records.register(bridge.aleo.default_account)
if not registration.get("ok"):
    raise RuntimeError(f"Scanner registration failed: {registration}")

Once the scanner has indexed a sufficient unspent record, unshield the amount needed for the withdrawal:

receipt = bridge.unshield("aleo/sol", amount="0.01").delegate()  # Return 0.01 SOL to a public balance.
print(receipt.transaction_id)  # Aleo transaction ID, beginning with at1.

Wait for the unshielding transaction to confirm before bridging those funds. The same record-discovery requirement applies to private xReserve withdrawals; supplying record= avoids the hosted scanner.

Shielding and unshielding each submit a separate Aleo transaction with a fee. A failed conversion does not reverse or repeat the bridge transfer.

Understand transfer costs

A bridge transfer can incur transaction fees, relay costs, and provider fees in addition to the amount sent. Some fees require a different asset—for example, sending WBTC from Ethereum still requires ETH for gas.

Before accepting a quote, check each fee's currency, keep enough to cover it, and review the expected amount the recipient will receive. The list below explains the costs associated with each chain and provider.

quote.fees names each fee's asset, chain, amount, and whether it is estimated. quote.amount_out gives the expected destination amount when available. Estimated costs and received amounts can change before the transfer completes.

  • Ethereum transfers need ETH for gas in addition to the asset being sent. An approval can add a transaction. Ethereum applies a minimum EIP-1559 priority fee of 0.1 gwei by default; min_priority_fee_wei changes it.
  • Aleo-origin Hyperlane transfers pay the relayer in credits as well as paying an Aleo transaction fee. Execution refreshes the relayer payment before proving unless gas_payment_microcredits is supplied explicitly. That override is in microcredits: 1,000,000 microcredits equal one credit.
  • Solana transfers need SOL for transaction fees, relay costs, and creation of Hyperlane message accounts, in addition to the amount being transferred.
  • xReserve withdrawal quotes use the registry's configured fee of 2 USDCx and mark it as estimated. The burn must exceed that amount. The actual delivery depends on the provider's fee.

Use a reliable Ethereum RPC endpoint and serialize transfers from the same Ethereum account so concurrent submissions do not compete for a nonce.

Agents and MCP

An agent can help a caller find a route, review its costs, and monitor a transfer. An application can limit the agent to those read operations or also allow it to submit transactions after explicit confirmation.

Agents can use the installed examples as reference flows without cloning the repository. Run python -m aleo_bridge.examples.quote_transfer --help, or choose another script from Examples. The packaged scripts show argument handling, submission, monitoring, and recovery.

The example below exposes the bridge tools and requests a USDC quote. It does not submit a deposit. Afterward, choose whether the application should expose submission tools or connect through MCP.

from aleo_bridge import bridge_tools, dispatch_tool

tools = bridge_tools()
result = dispatch_tool(bridge, "bridge_quote", {
    "source_chain": "ethereum", "source_asset": "usdc", "destination_chain": "aleo",
    "amount": "2", "recipient": bridge.aleo_address(),
})

For an agent that only advises or monitors, use bridge_tools(include_writes=False). Status, route, quote, and recovery tools can then inspect transfers without moving funds.

To permit a deposit, claim, resumed submission, shielding, or unshielding, the corresponding write tool requires confirm: true. Without confirmation, it returns the quote or recovered progress and how_to_confirm instructions instead of submitting a transaction.

Use python -m aleo_bridge to obtain the package's agent instructions. For an MCP client, install aleo-bridge-sdk[mcp] and configure python -m aleo_bridge.mcp as its stdio server.

Development

The development setup supports checking SDK changes without submitting live transactions. It includes the offline test suite and a check that the generated agent guide matches the SDK.

Create an environment, install the development dependencies, then run both checks:

cd bridge-sdk && python -m venv .venv && .venv/bin/pip install -e '.[dev]'
.venv/bin/python -m pytest -q -m "not live"          # hermetic suite
.venv/bin/python codegen/gen_context.py --check      # AGENTS.md is generated from docstrings

Asset discovery and client configuration

Find supported assets and routes

A route identifies an asset pair that can be bridged between two chains. Finding routes first helps an application offer transfers supported by the configured network.

The example below lists routes from Ethereum to Aleo. It reads the package's catalog without contacting a network or requesting a signature.

routes = bridge.routes(source_chain="ethereum", destination_chain="aleo")
for route in routes:
    print(route.id, route.protocol, route.availability)
    # Example: hyperlane:ethereum/wbtc->aleo/wbtc hyperlane active

Use the chain and asset names from these results when requesting a quote. For deployment inspection, include_unavailable=True also returns entries that cannot yet be used. Offer a transfer only when route.active is true.

Complete runnable scripts, including error handling and recovery, are in examples.

Solana key formats

Solana wallets and command-line tools export account keys in different formats. A wallet commonly exports a base58 string, while a Solana CLI keypair file contains a JSON array of 64 integers. Both represent signing keys; use the key for the account that holds the SOL needed for the transfer and fees, rather than its public address. The bridge accepts either format without manual conversion.

Reuse existing clients and signers

Applications already using Web3.py or solana-py can reuse their clients and signers through Ethereum(w3=..., signer=...) or Solana(client=..., signer=...). Omit the side-chain signer for an application that only reads balances, quotes, or status.

Delegated and local proving

Aleo transactions require a cryptographic proof before they can be submitted. The bridge uses Aleo's delegated proving by default: a proving service generates the proof, so the application does not need to perform that computation. The service receives the transaction contents, but the private key stays with the application.

Applications that need to keep transaction contents out of the proving service can configure local proving with proving="local" on execute, resume, or complete. The application's machine then generates the proof and may need to download proving parameters.

Release files for aleo-bridge-sdk 0.5.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for aleo-bridge-sdk 0.5.1
File Size Uploaded
aleo_bridge_sdk-0.5.1.tar.gz 367.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for aleo-bridge-sdk 0.5.1
File Interpreter ABI Platform
aleo_bridge_sdk-0.5.1-py3-none-any.whl Python 3 none any Details

Total release size: 564.0 kB

Release files / aleo_bridge_sdk-0.5.1.tar.gz

Download URL aleo_bridge_sdk-0.5.1.tar.gz
Size 367.6 kB
Tags Source
SHA-256 checksum
How to use checksums
035c36eec2be578ae09a2a9bc1b0c1f3d809e32ed38775a7bda6d2a176ab6d6f
BLAKE2b-256 checksum
How to use checksums
0a25dd4fce4c8b4b04ae2803bf68fe1c6aef8505e5f8b5fc96549a2abd835b50
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 28, 2026.

Transparency log

Release files / aleo_bridge_sdk-0.5.1-py3-none-any.whl

Download URL aleo_bridge_sdk-0.5.1-py3-none-any.whl
Size 196.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9e5e579b5a26bc678d19ac4760f9e81d62c317f31146149a22d876b6a1c0a0f1
BLAKE2b-256 checksum
How to use checksums
200fda6f93d14f8ae3674fbd390737723a2f9a1434bc6b3dcfdd007c518d9f6b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 28, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.5.1 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page