Skip to content

Latest commit

 

History

History
231 lines (176 loc) · 5.51 KB

File metadata and controls

231 lines (176 loc) · 5.51 KB

Balancer Maths Python

Python implementation of mathematics for Balancer v3

Note: This is the Python implementation within the balancer-maths monorepo, which also contains TypeScript and Rust implementations.

Installation

From PyPI (recommended)

pip install balancer-maths

From source

git clone https://github.com/balancer/balancer-maths.git
cd balancer-maths/python
pip install -e .

Development Setup

  1. Create and activate a virtual environment:
python -m venv .venv
source .venv/bin/activate  # On Windows use: .venv\Scripts\activate
  1. Install development dependencies:
pip install -e ".[dev]"

Hooks Support

Hooks are supported on a case by case basis.

When a pool has a hook type included in the pool data relevant hook data must also be passed as an input to any Vault operation. See Remove Liquidity example below.

Currently supported hooks:

  • ExitFeeHook
    • This hook implements the ExitFeeHookExample found in mono-repo

Examples

Swap

from src.vault import Vault
from src.swap import SwapInput, SwapKind

pool = {
    "poolType": "WEIGHTED",
    "chainId": "11155111",
    "blockNumber": "5955145",
    "poolAddress": "0xb2456a6f51530053bc41b0ee700fe6a2c37282e8",
    "tokens": [
        "0x7b79995e5f793A07Bc00c21412e50Ecae098E7f9",
        "0xb19382073c7A0aDdbb56Ac6AF1808Fa49e377B75",
    ],
    "scalingFactors": [1000000000000000000, 1000000000000000000],
    "weights": [500000000000000000, 500000000000000000],
    "swapFee": 100000000000000000,
    "balancesLiveScaled18": [2000000000000000000, 2000000000000000000],
    "tokenRates": [1000000000000000000, 1000000000000000000],
    "totalSupply": 1000000000000000000,
    "aggregateSwapFee": 500000000000000000,
}


swap_input = SwapInput(
    amount_raw=100000000,
    swap_kind=SwapKind.GIVENIN,
    token_in=pool['tokens'][0],
    token_out=pool['tokens'][1],
)

vault = Vault()

calculated_result = vault.swap(
    swap_input,
    pool,
)

Add Liquidity

from src.vault import Vault
from src.add_liquidity import AddLiquidityInput, AddLiquidityKind

pool = {
    "poolType": "WEIGHTED",
    "chainId": "11155111",
    "blockNumber": "5955145",
    "poolAddress": "0xb2456a6f51530053bc41b0ee700fe6a2c37282e8",
    "tokens": [
        "0x7b79995e5f793A07Bc00c21412e50Ecae098E7f9",
        "0xb19382073c7A0aDdbb56Ac6AF1808Fa49e377B75",
    ],
    "scalingFactors": [1000000000000000000, 1000000000000000000],
    "weights": [500000000000000000, 500000000000000000],
    "swapFee": 100000000000000000,
    "balancesLiveScaled18": [2000000000000000000, 2000000000000000000],
    "tokenRates": [1000000000000000000, 1000000000000000000],
    "totalSupply": 1000000000000000000,
    "aggregateSwapFee": 500000000000000000,
}


add_liquidity_input = AddLiquidityInput(
    pool="0xb2456a6f51530053bc41b0ee700fe6a2c37282e8",
    max_amounts_in_raw=[200000000000000000, 100000000000000000],
    min_bpt_amount_out_raw=0,
    kind=AddLiquidityKind.UNBALANCED,
)

vault = Vault()

calculated_result = vault.add_liquidity(
    add_liquidity_input,
    pool,
)

Remove Liquidity

This example shows how to calculate the result of a remove liqudity operation when the pool is registered with the ExitFee hook.

from src.vault import Vault
from src.remove_liquidity import RemoveLiquidityInput, RemoveLiquidityKind

pool = {
    "poolType": "WEIGHTED",
    "hookType": "ExitFee",
    "chainId": "11155111",
    "blockNumber": "5955145",
    "poolAddress": "0x03722034317d8fb16845213bd3ce15439f9ce136",
    "tokens": [
        "0x7b79995e5f793A07Bc00c21412e50Ecae098E7f9",
        "0xb19382073c7A0aDdbb56Ac6AF1808Fa49e377B75",
    ],
    "scalingFactors": [1000000000000000000, 1000000000000000000],
    "weights": [500000000000000000, 500000000000000000],
    "swapFee": 100000000000000000,
    "balancesLiveScaled18": [5000000000000000, 5000000000000000000],
    "tokenRates": [1000000000000000000, 1000000000000000000],
    "totalSupply": 158113883008415798,
    "aggregateSwapFee": 0,
}

remove_liquidity_input = RemoveLiquidityInput(
    pool="0x03722034317d8fb16845213bd3ce15439f9ce136",
    min_amounts_out_raw=[1, 1],
    max_bpt_amount_in_raw=10000000000000,
    kind=RemoveLiquidityKind.PROPORTIONAL,
)

input_hook_state = {
    'removeLiquidityHookFeePercentage': 0,
    'tokens': pool['tokens'],
}

vault = Vault()

calculated_result = vault.remove_liquidity(
    remove_liquidity_input,
    pool,
    hook_state=input_hook_state
)

Building and Releasing

Local Development

To build the package locally for testing:

python build_and_release.py --all

This will:

  • Clean previous build artifacts
  • Install build dependencies
  • Build the package
  • Check the built package

Releasing to PyPI

  1. Test Release (recommended first):
python build_and_release.py --test-upload
  1. Production Release:
python build_and_release.py --upload

Note: You'll need to have your PyPI credentials configured. You can set them up using:

pip install twine
twine configure

Manual Build

If you prefer to build manually:

# Install build tools
pip install build twine

# Build the package
python -m build

# Check the package
twine check dist/*

# Upload to TestPyPI
twine upload --repository testpypi dist/*

# Upload to PyPI
twine upload dist/*