Cross-Chain Access SDK
The Cross-Chain Access SDK enables trading of tokenised Real World Assets (RWAs) — stocks like AAPL, TSLA, GOOGL — using USDC as collateral. Trades execute at real US stock exchange prices during market hours, with on-chain settlement.
Use this when you want: stock market pricing, high liquidity during market hours, regulated/KYC-compliant trading, or consistent centralised pricing.
Key features
- Real US stock exchange pricing (ask for buys, bid for sells)
- On-chain settlement via USDC transfer to escrow
- Cross-chain delivery: send USDC from one network, receive assets on any other
- Automatic market hours enforcement and account validation
- Built-in retry logic (3 attempts with exponential backoff)
- Email trade confirmations
Prerequisites
KYC is required. Before using this SDK, you must:
- Connect your wallet at https://dotc.eth.limo/
- Complete KYC verification (typically takes 1–2 business days)
- Use the same KYC-verified wallet address in the SDK
Without KYC approval, trades will be rejected.
You also need:
- Python 3.8+
- USDC tokens on a supported network
- Gas tokens (MATIC, ETH, BNB, etc.) for transaction fees
Market hours
The SDK enforces US stock market hours automatically.
| Open | 14:30 UTC (9:30 AM EST) |
| Close | 21:00 UTC (4:00 PM EST) |
| Days | Monday–Friday |
| Closed | Weekends and US market holidays |
The SDK raises MarketClosedException if you attempt to trade outside these hours, with a message like "Market is closed. Opens in 5h 30m".
Supported networks
All trades use USDC. The SDK auto-detects the correct USDC contract address for your network.
| Network | Chain ID | Gas token |
|---|---|---|
| Polygon | 137 | MATIC |
| Ethereum | 1 | ETH |
| BSC | 56 | BNB |
| Base | 8453 | ETH |
Cross-chain delivery
You can send USDC from any of the 4 networks above and receive assets on any network by passing target_chain_id. This includes networks not in the list above (e.g. Arbitrum, Optimism).
Initialising the client
from swarm.cross_chain_access_sdk.sdk import CrossChainAccessClient
from swarm.shared.models import Network
async with CrossChainAccessClient(
network=Network.POLYGON,
private_key="0x...", # your KYC-verified wallet
user_email="you@example.com" # for trade confirmations
) as client:
# Ready to trade
pass
Always use async with — it handles authentication and cleanup automatically.
Constructor parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
| network | Network | ✅ | Blockchain network |
| private_key | str | ✅ | KYC-verified wallet private key |
| user_email | str | ❌ | Email for trade confirmations |
| rpc_url | str | ❌ | Custom RPC endpoint |
| is_dev | bool | ❌ | Use development environment (default: False) |
Buying assets
from decimal import Decimal
async with CrossChainAccessClient(
network=Network.POLYGON,
private_key="0x...",
user_email="you@example.com"
) as client:
result = await client.buy(
rwa_token_address="0x1234...", # token contract address
rwa_symbol="AAPL",
rwa_amount=10, # buy 10 shares
user_email="you@example.com"
)
print(f"Bought: {result.buy_amount} AAPL")
print(f"Spent: {result.sell_amount} USDC")
print(f"TX Hash: {result.tx_hash}")
print(f"Order ID: {result.order_id}")
Specify shares or USDC amount — not both:
# Option 1: specify how many shares
result = await client.buy(rwa_amount=10, ...)
# Option 2: specify how much USDC to spend
result = await client.buy(usdc_amount=1000, ...)
# You'll receive as many shares as $1,000 can buy at the current price
What happens automatically:
- Market hours and account status validated
- Real-time price quote fetched
- Amounts calculated with 1% slippage protection
- Buying power checked
- USDC transferred to escrow on-chain
- Order submitted to Cross-Chain Access
- Email confirmation sent (if email provided)
Selling assets
result = await client.sell(
rwa_token_address="0x1234...",
rwa_symbol="AAPL",
rwa_amount=5, # sell 5 shares
user_email="you@example.com"
)
print(f"Sold: {result.sell_amount} AAPL")
print(f"Received: {result.buy_amount} USDC")
Specify shares or target USDC — not both:
# Option 1: specify how many shares to sell
result = await client.sell(rwa_amount=5, ...)
# Option 2: sell enough shares to receive a target USDC amount
result = await client.sell(usdc_amount=500, ...)
Cross-chain delivery
Send USDC from one network and receive the purchased asset on a different network:
async with CrossChainAccessClient(network=Network.POLYGON, ...) as client:
result = await client.buy(
rwa_token_address="0x1234...",
rwa_symbol="AAPL",
rwa_amount=10,
user_email="you@example.com",
target_chain_id=8453 # receive AAPL on Base
)
The target_chain_id can be any EVM network — not limited to the four source networks.
# More examples
target_chain_id=1 # Ethereum
target_chain_id=42161 # Arbitrum
target_chain_id=10 # Optimism
Getting a quote
Fetch the current market price before trading:
quote = await client.get_quote("AAPL")
print(f"Current price: ${quote.rate}")
The buy() and sell() methods fetch quotes automatically — you only need to call this manually if you want to display a price to the user before executing.
Checking market availability
Check hours and account status without initiating a trade:
is_available, message = await client.check_trading_availability()
if is_available:
print(f"Ready: {message}")
else:
print(f"Not available: {message}")
# e.g. "Market is closed. Opens in 8h 30m"
# e.g. "Trading not available: account blocked"
Checks performed:
- Market hours (14:30–21:00 UTC, weekdays)
- Account not blocked
- Trading not suspended
- Transfers not restricted
- Market status
The buy() and sell() methods run these checks automatically.
Error handling
from swarm.cross_chain_access_sdk.cross_chain_access.exceptions import (
MarketClosedException,
AccountBlockedException,
InsufficientFundsException,
QuoteUnavailableException,
InvalidSymbolException,
CrossChainAccessException,
)
try:
result = await client.buy(...)
except MarketClosedException as e:
print(f"Market closed: {e}")
# Try again during 14:30–21:00 UTC on weekdays
except InsufficientFundsException as e:
print(f"Insufficient funds: {e}")
# Add more USDC (for buys) or RWA tokens (for sells)
except AccountBlockedException as e:
print(f"Account restricted: {e}")
# Contact support
except InvalidSymbolException as e:
print(f"Invalid symbol: {e}")
# Check the stock symbol spelling
except QuoteUnavailableException as e:
print(f"Quote unavailable: {e}")
# Retry after a moment
except CrossChainAccessException as e:
print(f"Trading error: {e}")
| Exception | When it occurs |
|---|---|
| MarketClosedException | Trade attempted outside market hours |
| AccountBlockedException | Account is blocked or trading suspended |
| InsufficientFundsException | Insufficient USDC (buy) or RWA tokens (sell) |
| QuoteUnavailableException | Real-time price could not be fetched |
| InvalidSymbolException | Stock symbol is not recognised |
| OrderFailedException | Order submission to the API failed |
| CrossChainAccessException | Base class for all Cross-Chain Access errors |
| AuthenticationError | Wallet not KYC-verified |
Built-in retry logic
The SDK automatically retries failed API calls — no configuration needed.
- Retries: 3 attempts
- Backoff: exponential (1s, 2s, 4s)
- Retried: network timeouts, 5xx server errors, 429 rate limits
- Not retried: 4xx client errors (invalid parameters, auth failures)
Email notifications
When user_email is provided, you'll receive a confirmation email after each trade containing the symbol, amount, price, transaction hash, order ID, timestamp, and network.
Complete example
import asyncio
from swarm.cross_chain_access_sdk.sdk import CrossChainAccessClient
from swarm.shared.models import Network
from swarm.cross_chain_access_sdk.cross_chain_access.exceptions import (
MarketClosedException,
InsufficientFundsException,
CrossChainAccessException,
)
async def main():
async with CrossChainAccessClient(
network=Network.POLYGON,
private_key="0x...",
user_email="you@example.com"
) as client:
try:
# Check current price
quote = await client.get_quote("AAPL")
print(f"AAPL price: ${quote.rate}")
print(f"Estimated cost for 10 shares: ${10 * quote.rate:.2f}")
# Execute buy
result = await client.buy(
rwa_token_address="0x1234...",
rwa_symbol="AAPL",
rwa_amount=10,
user_email="you@example.com"
)
print(f"✅ Trade successful!")
print(f" Bought: {result.buy_amount} AAPL")
print(f" Spent: ${result.sell_amount} USDC")
print(f" Price: ${result.rate}/share")
print(f" TX: {result.tx_hash}")
print(f" Order ID: {result.order_id}")
except MarketClosedException as e:
print(f"Market closed: {e}")
except InsufficientFundsException as e:
print(f"Insufficient funds: {e}")
except CrossChainAccessException as e:
print(f"Error: {e}")
asyncio.run(main())
Quick reference
# Imports
from swarm.cross_chain_access_sdk.sdk import CrossChainAccessClient
from swarm.shared.models import Network
from swarm.cross_chain_access_sdk.cross_chain_access.exceptions import (
MarketClosedException, AccountBlockedException,
InsufficientFundsException, CrossChainAccessException,
)
# Initialise
async with CrossChainAccessClient(
network=Network.POLYGON,
private_key="0x...",
user_email="you@example.com"
) as client:
# Check availability
is_open, msg = await client.check_trading_availability()
# Get quote
quote = await client.get_quote("AAPL")
# Buy (by shares)
result = await client.buy(
rwa_token_address="0x...", rwa_symbol="AAPL",
rwa_amount=10, user_email="you@example.com"
)
# Buy (by USDC amount)
result = await client.buy(
rwa_token_address="0x...", rwa_symbol="AAPL",
usdc_amount=1000, user_email="you@example.com"
)
# Sell
result = await client.sell(
rwa_token_address="0x...", rwa_symbol="AAPL",
rwa_amount=5, user_email="you@example.com"
)
# Cross-chain delivery
result = await client.buy(
rwa_token_address="0x...", rwa_symbol="AAPL",
rwa_amount=10, user_email="you@example.com",
target_chain_id=8453 # receive on Base
)
.png)