Skip to main content

Library for trading on Tristero

Project description

Tristero

PyPI version Python Support

This repository is home to Tristero's trading library.

Installation

pip install tristero

Quick Start

Execute a cross-chain swap in just a few lines:

import os
from tristero.client import TokenSpec, execute_swap
from eth_account import Account
from web3 import AsyncWeb3
from tristero.api import ChainID

private_key = os.getenv("EVM_PRIVATE_KEY")
account = Account.from_key(private_key)
w3 = AsyncWeb3(AsyncWeb3.AsyncHTTPProvider("https://arbitrum-one-rpc.publicnode.com"))

result = await execute_swap(
    w3=w3,
    account=account,
    src_t=TokenSpec(chain_id=ChainID.arbitrum, token_address="0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9"),  # USDT
    dst_t=TokenSpec(chain_id=ChainID.base, token_address="0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"),  # USDC
    raw_amount=10000000  # Raw token amount (multiply by 10^decimals)
)

Usage Examples

Permit2 Swap (EVM-to-EVM)

Permit2 swaps enable seamless EVM-to-EVM cross-chain token transfers with gasless approvals and EIP-712 signed orders.

import os
from tristero.client import TokenSpec, execute_permit2_swap
from eth_account import Account
from web3 import AsyncWeb3
from tristero.api import ChainID

private_key = os.getenv("EVM_PRIVATE_KEY")
account = Account.from_key(private_key)
w3 = AsyncWeb3(AsyncWeb3.AsyncHTTPProvider("https://mainnet.base.org"))

# Example: USDC on Base → USDT on Avalanche
result = await execute_permit2_swap(
    w3=w3,
    account=account,
    src_t=TokenSpec(chain_id=ChainID.base, token_address="0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"),  # USDC on Base
    dst_t=TokenSpec(chain_id=ChainID.avalanche, token_address="0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7"),  # USDT on Avalanche
    raw_amount=10 * 10**6  # 10 USDC (6 decimals)
)

print(f"Swap completed: {result}")

Feather Swap (UTXO-to-UTXO)

Feather swaps facilitate cross-chain transfers between UTXO-based chains like Bitcoin and Monero, providing a deposit address for manual fund transfers.

import asyncio
from tristero.client import TokenSpec, start_feather_swap, wait_for_feather_completion
from tristero.api import ChainID

# Example: Bitcoin → Monero
async def btc_to_xmr_swap():
    # Start the swap to get a deposit address
    swap_result = await start_feather_swap(
        src_t=TokenSpec(chain_id=ChainID.bitcoin, token_address="native"),  # BTC
        dst_t=TokenSpec(chain_id=ChainID.monero, token_address="native"),   # XMR
        dst_addr="YOUR_XMR_RECEIVING_ADDRESS",  # Your Monero destination address
        raw_amount=100000  # Amount in satoshis (0.001 BTC)
    )
    
    print(f"Send {swap_result.data['amount']} satoshis to: {swap_result.deposit_address}")
    
    # Wait for swap completion after sending funds
    result = await wait_for_feather_completion(swap_result.data['id'])
    print(f"Swap completed: {result}")

# Run the swap
asyncio.run(btc_to_xmr_swap())

Two-Step Permit2 Swap

For more control, you can separate the swap initiation from monitoring:

from tristero.client import TokenSpec, start_permit2_swap, wait_for_completion_with_retry
from eth_account import Account
from web3 import AsyncWeb3
from tristero.api import ChainID

# Step 1: Start the swap
account = Account.from_key(os.getenv("EVM_PRIVATE_KEY"))
w3 = AsyncWeb3(AsyncWeb3.AsyncHTTPProvider("https://arbitrum-one-rpc.publicnode.com"))

order_id = await start_permit2_swap(
    w3=w3,
    account=account,
    src_t=TokenSpec(chain_id=ChainID.arbitrum, token_address="0xaf88d065e77c8cC2239327C5EDb3A432268e5831"),  # USDC
    dst_t=TokenSpec(chain_id=ChainID.polygon, token_address="0xc2132D05D31c914a87C6611C10748AEb04B58e8F"),  # USDT
    raw_amount=50 * 10**6  # 50 USDC
)

print(f"Swap initiated with order ID: {order_id}")

# Step 2: Wait for completion with retry logic
result = await wait_for_completion_with_retry(order_id, feather=False)
print(f"Swap completed successfully!")

How it works

Tristero supports two primary swap mechanisms:

Permit2 Swaps (EVM-to-EVM)

  • Quote & Approve - Request a quote and approve tokens via Permit2 (gasless approval)
  • Sign & Submit - Sign an EIP-712 order and submit for execution
  • Monitor - Track swap progress via WebSocket updates

Feather Swaps (UTXO-based)

  • Quote & Deposit - Request a quote to receive a deposit address
  • Manual Transfer - Send funds to the provided deposit address
  • Monitor - Track swap completion via WebSocket updates

This library provides both high-level convenience functions and lower-level components for precise control.

API Reference

Execute Full Swap

execute_swap handles the entire workflow automatically: quoting, signing, submitting, and monitoring.

from tristero.client import execute_swap, TokenSpec
from web3 import AsyncWeb3
from eth_account.signers.local import LocalAccount

w3 = AsyncWeb3(...)  # Your Web3 provider
account: LocalAccount = ...  # Your account

result = await execute_swap(
    w3=w3,
    account=account,
    src_t=TokenSpec(chain_id=ChainID.ethereum, token_address="0xA0b8..."),
    dst_t=TokenSpec(chain_id=ChainID.arbitrum, token_address="0xaf88..."),
    raw_amount=10*(10**18),
    retry=True,
    timeout=300.0  # 5 minutes
)

Execute Permit2 Swap

execute_permit2_swap handles EVM-to-EVM swaps with Permit2 integration.

from tristero.client import execute_permit2_swap, TokenSpec
from web3 import AsyncWeb3
from eth_account.signers.local import LocalAccount

w3 = AsyncWeb3(...)  # Your Web3 provider
account: LocalAccount = ...  # Your account

result = await execute_permit2_swap(
    w3=w3,
    account=account,
    src_t=TokenSpec(chain_id=ChainID.base, token_address="0x833589f..."),  # USDC
    dst_t=TokenSpec(chain_id=ChainID.avalanche, token_address="0x9702230..."),  # USDT
    raw_amount=10*(10**6),  # 10 USDC (6 decimals)
    retry=True,
    timeout=300.0  # 5 minutes
)

Start Feather Swap

start_feather_swap initiates UTXO-based swaps and returns deposit information.

from tristero.client import start_feather_swap, TokenSpec

swap_result = await start_feather_swap(
    src_t=TokenSpec(chain_id=ChainID.bitcoin, token_address="native"),
    dst_t=TokenSpec(chain_id=ChainID.monero, token_address="native"),
    dst_addr="YOUR_DESTINATION_ADDRESS",
    raw_amount=100000  # Amount in smallest unit
)

deposit_address = swap_result.deposit_address
order_id = swap_result.data['id']

Requesting a quote

get_quote requests a quote for a particular swap, letting you see output amounts and gas fees.

from tristero.api import get_quote, ChainID

quote = await get_quote(
    from_wallet="0x1234...",           # Source wallet address
    to_wallet="0x5678...",             # Destination wallet address
    from_chain_id=ChainID.ethereum,    # Source chain
    from_address="0xA0b8...",          # Source token address (or "native")
    to_chain_id=ChainID.arbitrum,      # Destination chain
    to_address="0xaf88...",            # Destination token address (or "native")
    amount=10*(10**18),                # Amount in smallest unit (wei)
)

Creating a signed order

create_order creates and signs an order without submitting to be filled.

from tristero.api import get_quote, ChainID

w3 = AsyncWeb3(...)  # Your Web3 provider
account: LocalAccount = ...  # Your account

data, sig = await create_order(
    w3,
    account,
    from_chain_id=ChainID.ethereum,
    from_address="0xA0b8...",
    to_chain_id=ChainID.arbitrum,
    to_address="0xaf88...",
    raw_amount=10*(10**18),
)

Submit order

fill_order submits a signed order for execution.

from tristero.api import fill_order

data, sig = ... # from earlier

response = await fill_order(
    signature=str(sig.signature.to_0x_hex()),
    domain=data.domain.model_dump(by_alias=True, mode="json"),
    message=data.message.model_dump(by_alias=True, mode="json"),
)

order_id = response['id']

Monitoring with Built-in Functions

For convenience, use the built-in monitoring functions:

from tristero.client import wait_for_completion_with_retry

# Monitor Permit2 swap with retry logic
result = await wait_for_completion_with_retry(order_id, feather=False)

# Monitor Feather swap with retry logic
result = await wait_for_completion_with_retry(order_id, feather=True)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tristero-0.2.1.tar.gz (31.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tristero-0.2.1-py3-none-any.whl (34.0 kB view details)

Uploaded Python 3

File details

Details for the file tristero-0.2.1.tar.gz.

File metadata

  • Download URL: tristero-0.2.1.tar.gz
  • Upload date:
  • Size: 31.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.9.29 {"installer":{"name":"uv","version":"0.9.29","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for tristero-0.2.1.tar.gz
Algorithm Hash digest
SHA256 8c49ac92a1017555549e06ff9fce9e658e277451b8757d30bb5eaece5dd178c9
MD5 abc56b79cc50a03b0861f54c48f84aef
BLAKE2b-256 2314e730f138854b0e44b938946dd9a583d6aab482d3a290c81b66318732dd05

See more details on using hashes here.

File details

Details for the file tristero-0.2.1-py3-none-any.whl.

File metadata

  • Download URL: tristero-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 34.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.9.29 {"installer":{"name":"uv","version":"0.9.29","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for tristero-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 83faea3c32b8f8c32d21f990d7845f23995b742cae61c433cef360fd456a0cc4
MD5 729f220517f0c8bf328b391faca89830
BLAKE2b-256 3e9452a2f841e683257c449d6a993106868f06c5e8bc2201e57d608fc151ba11

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page