Sugar SDK
Project description
Sugar SDK
Sugar makes Velodrome and Aerodrome devs life sweeter 🍭
Contents
- Using Sugar
- Base Quickstart
- OP Quickstart
- Pools
- Fees and Incentives
- Swaps
- Configuration
- Contributing to Sugar
- Useful Links
Using Sugar
pip install git+https://github.com/velodrome-finance/sugar-sdk.git@v0.3.1
You can take it for a spin on CodeSandbox
Base Quickstart
Getting started with Sugar on Base network:
from sugar.chains import BaseChain, AsyncBaseChain
# async version
async with AsyncBaseChain() as chain:
prices = await chain.get_prices(await chain.get_all_tokens())
for p in prices[:5]:
print(f"{p.token.symbol} price: {p.price}")
# sync version
with BaseChain() as chain:
for p in chain.get_prices(chain.get_all_tokens())[:5]:
print(f"{p.token.symbol} price: {p.price}")
OP Quickstart
Getting started with Sugar on OP network:
from sugar.chains import AsyncOPChain, OPChain
async with AsyncOPChain() as chain:
prices = await chain.get_prices(await chain.get_all_tokens())
for p in prices[:5]:
print(f"{p.token.symbol} price: {p.price}")
with OPChain() as chain:
for p in chain.get_prices(chain.get_all_tokens())[:5]:
print(f"{p.token.symbol} price: {p.price}")
Pools
Getting information about pools:
from sugar.chains import AsyncOPChain, OPChain
async with AsyncOPChain() as chain:
pools = await chain.get_pools()
usdc_velo = next(iter([p for p in pools if p.token0.token_address == OPChain.usdc.token_address and p.token1.token_address == OPChain.velo.token_address]), None)
print(f"{usdc_velo.symbol}")
print("-----------------------")
print(f"Volume: {usdc_velo.token0_volume} {usdc_velo.token0.symbol} | {usdc_velo.token1_volume} {usdc_velo.token1.symbol} | ${usdc_velo.volume}")
print(f"Fees: {usdc_velo.token0_fees.amount} {usdc_velo.token0.symbol} | {usdc_velo.token1_fees.amount} {usdc_velo.token1.symbol} | ${usdc_velo.total_fees}")
print(f"TVL: {usdc_velo.reserve0.amount} {usdc_velo.token0.symbol} | {usdc_velo.reserve1.amount} {usdc_velo.token1.symbol} | ${usdc_velo.tvl}")
print(f"APR: {usdc_velo.apr}%")
with OPChain() as chain:
pools = chain.get_pools()
usdc_velo = next(iter([p for p in pools if p.token0.token_address == OPChain.usdc.token_address and p.token1.token_address == OPChain.velo.token_address]), None)
print(f"{usdc_velo.symbol}")
print("-----------------------")
print(f"Volume: {usdc_velo.token0_volume} {usdc_velo.token0.symbol} | {usdc_velo.token1_volume} {usdc_velo.token1.symbol} | ${usdc_velo.volume}")
print(f"Fees: {usdc_velo.token0_fees.amount} {usdc_velo.token0.symbol} | {usdc_velo.token1_fees.amount} {usdc_velo.token1.symbol} | ${usdc_velo.total_fees}")
print(f"TVL: {usdc_velo.reserve0.amount} {usdc_velo.token0.symbol} | {usdc_velo.reserve1.amount} {usdc_velo.token1.symbol} | ${usdc_velo.tvl}")
print(f"APR: {usdc_velo.apr}%")
Fees and Incentives
To get information for the latest epochs across all the pools:
async with AsyncOPChain() as chain:
epochs = await chain.get_latest_pool_epochs()
ep = epochs[0]
print(f"{ep.pool.symbol}")
print(f"Epoch date: {ep.epoch_date}")
print(f"Fees: {' '.join([f'{fee.amount} {fee.token.symbol}' for fee in ep.fees])} {ep.total_fees}")
print(f"Incentives: {' '.join([f'{incentive.amount} {incentive.token.symbol}' for incentive in ep.incentives])} {ep.total_incentives}")
You can also get epochs for a specific pool using its address:
async with AsyncOPChain() as chain:
epochs = await chain.get_pool_epochs("0x7A7f1187c4710010DB17d0a9ad3fcE85e6ecD90a")
ep = epochs[0]
print(f"{ep.pool.symbol}")
print(f"Epoch date: {ep.epoch_date}")
print(f"Fees: {' '.join([f'{fee.amount} {fee.token.symbol}' for fee in ep.fees])} {ep.total_fees}")
print(f"Incentives: {' '.join([f'{incentive.amount} {incentive.token.symbol}' for incentive in ep.incentives])} {ep.total_incentives}")
Swaps
Get a quote and swap:
from sugar.chains import AsyncOPChain
async with AsyncOPChain() as op:
quote = await op.get_quote(from_token=AsyncOPChain.velo, to_token=AsyncOPChain.eth, amount=AsyncOPChain.velo.parse_units(10))
if not quote:
# no quote found
# check quote.amount_out
await op.swap_from_quote(quote)
“I am Feeling lucky” swap:
from sugar.chains import AsyncOPChain
async with AsyncOPChain() as op:
await op.swap(from_token=velo, to_token=eth, amount=velo.parse_units(10))
Superswaps
from sugar import OPChain, LiskChain, Superswap
superswap = Superswap()
quote = superswap.get_super_quote(from_token=OPChain.velo, to_token=LiskChain.lsk, amount=OPChain.velo.parse_units(100))
superswap.swap_from_quote(quote)
# feeling lucky Superswap
Superswap().swap(from_token=OPChain.velo, to_token=LiskChain.lsk, amount=OPChain.velo.parse_units(100))
As always, async version is also available
from sugar import OPChain, LiskChain, AsyncSuperswap
superswap = AsyncSuperswap()
quote = await superswap.get_super_quote(from_token=OPChain.velo, to_token=LiskChain.lsk, amount=OPChain.velo.parse_units(100))
await superswap.swap_from_quote(quote)
# feeling lucky Superswap
await AsyncSuperswap().swap(from_token=OPChain.velo, to_token=LiskChain.lsk, amount=OPChain.velo.parse_units(100))
Configuration
Full list of configuration parameters for Sugar. Chain IDs can be found
here. Sugar uses decimal versions: Base is
8453, OP is 10.
| config | env | default value |
|---|---|---|
| native_token_symbol | ETH | |
| native_token_decimals | 18 | |
| wrapped_native_token_addr | SUGAR_WRAPPED_NATIVE_TOKEN_ADDR_<CHAIN_ID> |
chain specific |
| rpc_uri | SUGAR_RPC_URI_<CHAIN_ID> |
chain specific |
| sugar_contract_addr | SUGAR_CONTRACT_ADDR_<CHAIN_ID> |
chain specific |
| slipstream_contract_addr | SUGAR_SLIPSTREAM_CONTRACT_ADDR_<CHAIN_ID> |
chain specific |
| nfpm_contract_addr | SUGAR_NFPM_CONTRACT_ADDR |
chain specific |
| price_oracle_contract_addr | SUGAR_PRICE_ORACLE_ADDR_<CHAIN_ID> |
chain specific |
| router_contract_addr | SUGAR_ROUTER_CONTRACT_ADDR_<CHAIN_ID> |
chain specific |
| swapper_contract_addr | SUGAR_ROUTER_SWAPPER_CONTRACT_ADDR_<CHAIN_ID> |
chain specific |
| swap_slippage | SUGAR_SWAP_SLIPPAGE_<CHAIN_ID> |
0.01 |
| token_addr | SUGAR_TOKEN_ADDR_<CHAIN_ID> |
chain specific |
| stable_token_addr | SUGAR_STABLE_TOKEN_ADDR_<CHAIN_ID> |
chain specific |
| connector_tokens_addrs | SUGAR_CONNECTOR_TOKENS_ADDRS_<CHAIN_ID> |
chain specific |
| excluded_tokens_addrs | SUGAR_EXCLUDED_TOKENS_ADDRS_<CHAIN_ID> |
chain specific |
| price_batch_size | SUGAR_PRICE_BATCH_SIZE |
40 |
| price_threshold_filter | SUGAR_PRICE_THRESHOLD_FILTER |
10 |
| interchain_router_contract_addr | SUGAR_INTERCHAIN_ROUTER_CONTRACT_ADDR_<CHAIN_ID> |
chain specific |
| bridge_contract_addr | SUGAR_BRIDGE_CONTRACT_ADDR_<CHAIN_ID> |
chain specific |
| bridge_token_addr | SUGAR_BRIDGE_TOKEN_ADDR_<CHAIN_ID> |
chain specific |
| message_module_contract_addr | SUGAR_MESSAGE_MODULE_CONTRACT_ADDR_<CHAIN_ID> |
chain specific |
| pool_page_size | SUGAR_POOL_PAGE_SIZE |
500 |
| pools_count_upper_bound | POOLS_COUNT_UPPER_BOUND_<CHAIN_ID> |
2500 |
| pagination_limit | SUGAR_PAGINATION_LIMIT |
2000 |
| pricing_cache_timeout_seconds | SUGAR_PRICING_CACHE_TIMEOUT_SECONDS_<CHAIN_ID> |
5 |
| threading_max_workers | SUGAR_THREADING_MAX_WORKERS_<CHAIN_ID> |
5 |
In order to write to Sugar contracts, you need to set your wallet
private key using env var SUGAR_PK
You can override specific settings in 2 ways:
- by setting corresponding env var:
SUGAR_RPC_URI_10=https://myrpc.com - in code:
from sugar.chains import OPChain
async with OPChain(rpc_uri="https://myrpc.com") as chain:
...
Contributing to Sugar
Set up and activate python virtual env
python3 -m venv env
source env/bin/activate
Install dependencies
pip install nbdev pre-commit
pip install -e '.[dev]'
Install pre-commit hooks for nbdev prep and cleanup
pre-commit install
Regenerate ABIs if needed
ABIs for contracts are stored inside sugar/abis dir. To regenerate
them, use abis.py script (make sure you have ETHERSCAN_API_KEY env
var set). We use Optimistic
Etherscan.
Useful Links
- keep an eye on the latest sugar contract deployment for your favorite chain here
- latest universal router contract (referred to as "swapper" in this sdk) deployment can be found here
Chores and random release related gymnastics
- getting one file diff for LLM ingestion (skipping notebooks and ABIs):
git diff main YOUR_NEW_BRANCH --output=YOUR_NEW_BRANCH.diff ':(exclude)src/*.ipynb' ':(exclude)sugar/_modidx.py' ':(exclude)sugar/abis/*.json'
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file sugar_sdk-0.3.1.tar.gz.
File metadata
- Download URL: sugar_sdk-0.3.1.tar.gz
- Upload date:
- Size: 54.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.6.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7022d7a1d3216102a3fe76594683bc1e27415e137a2842d092e4c394611f6962
|
|
| MD5 |
ce7341c102b72c60000556d7567db38b
|
|
| BLAKE2b-256 |
efa7fd344d739a311a2fcb5f729d8f5d1eeda7fd3abf9e6781bdb57bdf680076
|
File details
Details for the file sugar_sdk-0.3.1-py3-none-any.whl.
File metadata
- Download URL: sugar_sdk-0.3.1-py3-none-any.whl
- Upload date:
- Size: 57.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.6.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
39f4ce92b5a32f9da74e6ffb64de22f9f9cfe2cdbd610324e929eeb143217535
|
|
| MD5 |
d986cafe21b9654bc9976522acd92a63
|
|
| BLAKE2b-256 |
872edd1ef496339709ba8d2b618755bc503dab98605990707f6dbedbf808a9c5
|