nadfun-sdk


Namenadfun-sdk JSON
Version 0.1.3 PyPI version JSON
download
home_pageNone
SummaryPython SDK for Nad.fun contracts
upload_time2025-08-31 12:16:17
maintainerNone
docs_urlNone
authorNone
requires_python>=3.11
licenseMIT
keywords blockchain ethereum defi trading bonding-curve
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Nad.fun Python SDK

A comprehensive Python SDK for interacting with Nad.fun ecosystem contracts on Monad blockchain, including bonding curves, DEX trading, and real-time event monitoring.

## Features

- 🚀 **Trading**: Execute buy/sell operations on bonding curves with slippage protection
- 💰 **Token Operations**: ERC-20 token interactions (balance, approve, transfer)
- 📊 **Bonding Curves**: Query curve parameters and check listing status
- 🔄 **Real-time Streaming**: Monitor bonding curve and DEX events via WebSocket with token filtering
- 📚 **Historical Indexing**: Fetch and analyze past events with CurveIndexer and DexIndexer
- ⚡ **Async/Await**: Fully asynchronous design for high performance
- 🔐 **Type Safety**: Full type hints for better IDE support

## Installation

```bash
pip install nadfun-sdk
```

Or install from source:

```bash
git clone https://github.com/naddotfun/nadfun-sdk-python.git
cd nadfun-sdk-python
pip install -e .
```

## Quick Start

```python
import asyncio
from nadfun_sdk import Trade, BuyParams, calculate_slippage, parseMon

async def main():
    # Initialize trade client
    trade = Trade(rpc_url="https://monad-testnet.rpc.url", private_key="your_private_key")

    # Get quote for buying tokens
    token = "0x1957d1BED06c69f479f564E9Dc163e3Cf4E3eF03"
    amount_in = parseMon(1)  # 1 MON
    quote = await trade.get_amount_out(token, amount_in, is_buy=True)

    # Execute buy with slippage protection
    params = BuyParams(
        token=token,
        to=trade.address,
        amount_in=amount_in,
        amount_out_min=calculate_slippage(quote.amount, 5)  # 5% slippage tolerance
    )
    tx_hash = await trade.buy(params, quote.router)
    print(f"Transaction: {tx_hash}")

asyncio.run(main())
```

## Core Modules

### 🚀 Trading

Execute trades on bonding curves with automatic routing:

```python
from nadfun_sdk import Trade, BuyParams, SellParams, calculate_slippage

trade = Trade(rpc_url, private_key)

# Get quotes
buy_quote = await trade.get_amount_out(token, mon_amount, is_buy=True)
sell_quote = await trade.get_amount_out(token, token_amount, is_buy=False)

# Buy tokens
buy_params = BuyParams(
    token=token,
    to=wallet_address,
    amount_in=mon_amount,
    amount_out_min=calculate_slippage(buy_quote.amount, 5),
    deadline=None  # Auto-sets to now + 120 seconds
)
tx = await trade.buy(buy_params, buy_quote.router)

# Sell tokens
sell_params = SellParams(
    token=token,
    to=wallet_address,
    amount_in=token_amount,
    amount_out_min=calculate_slippage(sell_quote.amount, 5),
    deadline=None
)
tx = await trade.sell(sell_params, sell_quote.router)

# Wait for transaction
receipt = await trade.wait_for_transaction(tx, timeout=60)
```

### 💰 Token Operations

Interact with ERC-20 tokens:

```python
from nadfun_sdk import Token

token = Token(rpc_url, private_key)

# Get token metadata
metadata = await token.get_metadata(token_address)
print(f"Token: {metadata['name']} ({metadata['symbol']})")
print(f"Decimals: {metadata['decimals']}")
print(f"Total Supply: {metadata['totalSupply']}")

# Check balances
balance = await token.get_balance(token_address)
balance = await token.get_balance(token_address, owner_address)  # Check other address

# Check allowance
allowance = await token.get_allowance(token_address, spender_address)

# Approve tokens
tx = await token.approve(token_address, spender_address, amount)

# Transfer tokens
tx = await token.transfer(token_address, recipient_address, amount)

# Smart approval (only approves if needed)
tx = await token.check_and_approve(token_address, spender_address, required_amount)
```

### 📊 Bonding Curve Data

Query bonding curve information:

```python
# Check if token is listed on curve
is_listed = await trade.is_listed(token_address)

# Get curve reserves
curve_data = await trade.get_curves(token_address)
print(f"Reserve MON: {curve_data.reserve_mon}")
print(f"Reserve Token: {curve_data.reserve_token}")

# Get amount needed for specific output
quote = await trade.get_amount_in(token_address, desired_output, is_buy=True)
```

### 🔄 Real-time Event Streaming

Monitor events in real-time using WebSocket connections:

#### Curve Events Stream

```python
from nadfun_sdk import CurveStream, EventType, CurveEvent

# Initialize stream
stream = CurveStream(ws_url)

# Subscribe to specific events
stream.subscribe([EventType.BUY])  # Only BUY events
stream.subscribe([EventType.SELL])  # Only SELL events
stream.subscribe([EventType.BUY, EventType.SELL])  # Both
stream.subscribe()  # All events (default)

# Filter by token addresses (optional)
stream.subscribe(
    [EventType.BUY, EventType.SELL],
    token_addresses=["0x1234...", "0x5678..."]  # Only events from these tokens
)

# Process events with typed async iterator
event: CurveEvent
async for event in stream.events():
    print(f"Event: {event['eventName']}")      # "BUY" or "SELL"
    print(f"Trader: {event['trader']}")        # Buyer/Seller address
    print(f"Token: {event['token']}")          # Token address
    print(f"Amount In: {event['amountIn']}")   # MON for buy, tokens for sell
    print(f"Amount Out: {event['amountOut']}") # Tokens for buy, MON for sell
    print(f"Block: {event['blockNumber']}")
    print(f"Tx: {event['transactionHash']}")
```

#### DEX Swap Events Stream

```python
from nadfun_sdk import DexStream, DexSwapEvent

# Initialize stream
stream = DexStream(ws_url)

# Subscribe to tokens (automatically finds pools)
stream.subscribe_tokens("0x1234...")  # Single token
stream.subscribe_tokens(["0x1234...", "0x5678..."])  # Multiple tokens

# Process swap events with typed iterator
event: DexSwapEvent
async for event in stream.events():
    print(f"Event: {event['eventName']}")
    print(f"BlockNumber: {event['blockNumber']}")
    print(f"Pool: {event['pool']}")
    print(f"Sender: {event['sender']}")
    print(f"Recipient: {event['recipient']}")
    print(f"Amount0: {event['amount0']}")
    print(f"Amount1: {event['amount1']}")
    print(f"Liquidity: {event['liquidity']}")
    print(f"Tick: {event['tick']}")
    print(f"Price (sqrt X96): {event['sqrtPriceX96']}")
    print(f"Tx: {event['transactionHash']}")
    print("-" * 50)
```

### 📚 Historical Event Indexing

Index historical blockchain events for analysis:

#### Curve Indexer

```python
from nadfun_sdk import CurveIndexer, EventType

# Initialize indexer
indexer = CurveIndexer(rpc_url)

# Get current block number
latest_block = await indexer.get_block_number()
from_block = latest_block - 1000  # Last 1000 blocks

# Fetch all events
all_events = await indexer.fetch_events(from_block, latest_block)

# Filter by event types
trade_events = await indexer.fetch_events(
    from_block,
    latest_block,
    event_types=[EventType.BUY, EventType.SELL]
)

# Filter by token
token_events = await indexer.fetch_events(
    from_block,
    latest_block,
    token_filter="0x1234..."
)
```

#### DEX Indexer

```python
from nadfun_sdk import DexIndexer

# Initialize indexer
indexer = DexIndexer(rpc_url)

# Get current block number
latest_block = await indexer.get_block_number()

# Fetch swap events by tokens (automatically finds pools)
swap_events = await indexer.fetch_events(
    from_block,
    latest_block,
    tokens=["0x1234...", "0x5678..."]
)

# Or fetch by specific pool addresses
pool_events = await indexer.fetch_events(
    from_block,
    latest_block,
    pools="0xabcd..."
)
```

## API Reference

### Trade Class

```python
trade = Trade(rpc_url: str, private_key: str)
```

#### Methods

- `async get_amount_out(token: str, amount_in: int, is_buy: bool) -> QuoteResult`

  - Get expected output amount for a trade
  - Returns `QuoteResult` with `router` address and `amount`

- `async get_amount_in(token: str, amount_out: int, is_buy: bool) -> QuoteResult`

  - Get required input amount for desired output
  - Returns `QuoteResult` with `router` address and `amount`

- `async buy(params: BuyParams, router: str, nonce: int = None, gas: int = None) -> str`

  - Execute buy transaction
  - Returns transaction hash

- `async sell(params: SellParams, router: str, nonce: int = None, gas: int = None) -> str`

  - Execute sell transaction
  - Returns transaction hash

- `async is_listed(token: str) -> bool`

  - Check if token is listed on bonding curve

- `async get_curves(token: str) -> CurveData`

  - Get bonding curve reserves
  - Returns `CurveData` with `reserve_mon` and `reserve_token`

- `async wait_for_transaction(tx_hash: str, timeout: int = 60) -> Dict`
  - Wait for transaction confirmation

### Token Class

```python
token = Token(rpc_url: str, private_key: str)
```

#### Methods

- `async get_balance(token: str, address: str = None) -> int`

  - Get token balance (defaults to own address)

- `async get_allowance(token: str, spender: str, owner: str = None) -> int`

  - Get approved amount (defaults to own address as owner)

- `async get_metadata(token: str) -> TokenMetadata`

  - Get token metadata (name, symbol, decimals, totalSupply)

- `async approve(token: str, spender: str, amount: int) -> str`

  - Approve tokens for spending

- `async transfer(token: str, to: str, amount: int) -> str`

  - Transfer tokens

- `async check_and_approve(token: str, spender: str, required: int, buffer_percent: float = 10) -> Optional[str]`
  - Smart approval - only approves if current allowance is insufficient

### Stream Classes

#### CurveStream

```python
stream = CurveStream(ws_url: str)
```

- `subscribe(event_types: List[EventType] = None)` - Set events to subscribe to
- `async events() -> AsyncIterator[Dict]` - Async iterator yielding parsed events

#### DexStream

```python
stream = DexStream(ws_url: str)
```

- `subscribe_tokens(token_addresses: Union[str, List[str]])` - Set tokens to monitor
- `async events() -> AsyncIterator[Dict]` - Async iterator yielding swap events

### Indexer Classes

#### CurveIndexer

Historical event indexer for bonding curve events:

```python
indexer = CurveIndexer(rpc_url: str)
```

- `async fetch_events(from_block: int, to_block: int, event_types: List[EventType] = None, token_filter: str = None) -> List[Dict]`
  - Fetch historical curve events in a block range
  - Optionally filter by event types (CREATE, BUY, SELL, SYNC, LOCK, LISTED)
  - Optionally filter by token address
- `async get_block_number() -> int`
  - Get current block number

#### DexIndexer

Historical event indexer for DEX swap events:

```python
indexer = DexIndexer(rpc_url: str)
```

- `async fetch_events(from_block: int, to_block: int, pools: Union[str, List[str]] = None, tokens: Union[str, List[str]] = None) -> List[Dict]`
  - Fetch historical swap events in a block range
  - Optionally filter by pool address(es) or token address(es)
  - When filtering by tokens, automatically finds pools from V3 factory
- `async get_block_number() -> int`
  - Get current block number

### Type Definitions

```python
class BuyParams:
    token: str          # Token address to buy
    to: str            # Recipient address
    amount_in: int     # MON amount to spend
    amount_out_min: int # Minimum tokens to receive
    deadline: Optional[int] = None  # Transaction deadline
    nonce: Optional[int] = None     # Transaction nonce
    gas: Optional[int] = None       # Gas limit
    gas_price: Optional[int] = None # Gas price

class SellParams:
    token: str          # Token address to sell
    to: str            # Recipient address
    amount_in: int     # Token amount to sell
    amount_out_min: int # Minimum MON to receive
    deadline: Optional[int] = None
    nonce: Optional[int] = None
    gas: Optional[int] = None
    gas_price: Optional[int] = None

class QuoteResult:
    router: str        # Router contract address
    amount: int        # Expected amount

class CurveData:
    reserve_mon: int   # MON reserves in curve
    reserve_token: int # Token reserves in curve

class TokenMetadata:
    name: str
    symbol: str
    decimals: int
    totalSupply: int

# Event Types (TypedDict for type hints)
class CurveEvent:
    eventName: str          # "BUY" or "SELL"
    blockNumber: int        # Block number
    transactionHash: str    # Transaction hash
    trader: str            # Buyer/Seller address
    token: str             # Token address
    amountIn: int          # Amount in
    amountOut: int         # Amount out

class DexSwapEvent:
    eventName: str          # "Swap"
    blockNumber: int        # Block number
    transactionHash: str    # Transaction hash
    pool: str              # Pool address
    sender: str            # Sender address
    recipient: str         # Recipient address
    amount0: int           # Token0 amount (can be negative)
    amount1: int           # Token1 amount (can be negative)
    sqrtPriceX96: int      # Square root price
    liquidity: int         # Liquidity
    tick: int              # Price tick
```

### Utilities

- `calculate_slippage(amount: int, percent: float) -> int`
  - Calculate minimum output amount with slippage tolerance
- `parseMon(amount: float | str) -> int`
  - Convert MON amount to wei (18 decimals)

## Configuration

Create a `.env` file in your project root. You can copy from `.env.example`:

```bash
cp .env.example .env
```

### Environment Variables

```bash
# Network endpoints
RPC_URL=                                   # HTTP RPC endpoint for Monad testnet
WS_URL=                                    # WebSocket endpoint for real-time event streaming

# Wallet configuration
PRIVATE_KEY=your_private_key_here         # Private key (without 0x prefix)

# Token addresses
TOKEN=0x...                                # Single token address for trading
TOKENS=0x...                               # Multiple token addresses for DEX monitoring (comma-separated)

# Trading parameters
AMOUNT=                                    # Amount in MON for trading (e.g., 0.1)
SLIPPAGE=                                  # Slippage tolerance percentage (e.g., 5)
```

### Network Information

- **Chain**: Monad Testnet
- **Chain ID**: 10143
- **Native Token**: MON
- **Block Explorer**: https://explorer.monad.net

## Examples

The SDK includes comprehensive examples in the `examples/` directory. First, set up your environment:

```bash
# Copy example environment file
cp .env.example .env

# Edit .env with your configuration
nano .env
```

### Trading Examples

#### Buy Tokens (`examples/trade/buy.py`)

```bash
python examples/trade/buy.py
```

Demonstrates buying tokens on the bonding curve with slippage protection.

#### Sell Tokens (`examples/trade/sell.py`)

```bash
python examples/trade/sell.py
```

Shows selling tokens back to the bonding curve.

### Token Operations (`examples/token_operations.py`)

```bash
python examples/token_operations.py
```

Examples of token interactions:

- Checking balances
- Approving spending
- Transferring tokens
- Getting token metadata

### Real-time Event Streaming

#### Curve Events (`examples/stream/curve_stream.py`)

```bash
python examples/stream/curve_stream.py
```

Stream real-time bonding curve Buy/Sell events with filtering options.

#### DEX Swaps (`examples/stream/dex_stream.py`)

```bash
python examples/stream/dex_stream.py
```

Monitor DEX swap events for specified tokens in real-time.

### Historical Event Indexing

#### Curve Indexer (`examples/stream/curve_indexer.py`)

```bash
python examples/stream/curve_indexer.py
```

Index historical bonding curve events:

- Fetch all event types or filter specific ones
- Filter by token address
- Analyze event patterns

#### DEX Indexer (`examples/stream/dex_indexer.py`)

```bash
python examples/stream/dex_indexer.py
```

Index historical DEX swap events:

- Fetch swap events from V3 pools
- Filter by pool addresses or token addresses
- Analyze swap patterns

## Contract Addresses

All contract addresses are defined in `src/nadfun_sdk/constants.py`:

- **Wrapper Contract**: `0x4F5A3518F082275edf59026f72B66AC2838c0414`
- **Curve Contract**: `0x52D34d8536350Cd997bCBD0b9E9d722452f341F5`
- **Lens Contract**: `0x4F5A3518F082275edf59026f72B66AC2838c0414`
- **V3 Factory**: `0x4f6F577e3bfB25dF11f635d93E5ff645d30CB474`
- **WMON Token**: `0x88CCF31322CEc314E36D0c993651cE14e4AE7B2d`

## Requirements

- Python 3.11+
- web3.py >= 7.0.0
- eth-account
- eth-abi
- python-dotenv

## Development

```bash
# Clone the repository
git clone https://github.com/naddotfun/nadfun-sdk-python.git
cd nadfun-sdk-python

# Install in development mode
pip install -e .

# Install development dependencies
pip install -r requirements-dev.txt

# Format code
black src/ examples/

# Type checking
mypy src/
```

## License

MIT License - see [LICENSE](LICENSE) for details.

## Support

- 📖 [Examples](examples/) - Comprehensive usage examples
- 🐛 [Issues](https://github.com/naddotfun/nadfun-sdk-python/issues) - Bug reports and feature requests

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "nadfun-sdk",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.11",
    "maintainer_email": null,
    "keywords": "blockchain, ethereum, defi, trading, bonding-curve",
    "author": null,
    "author_email": "Nadfun <dev@nad.fun>",
    "download_url": "https://files.pythonhosted.org/packages/15/a2/b56959512e917f69712e22aa49e1ea3692f55a5ba1eb856ff9cb2c3a417c/nadfun_sdk-0.1.3.tar.gz",
    "platform": null,
    "description": "# Nad.fun Python SDK\n\nA comprehensive Python SDK for interacting with Nad.fun ecosystem contracts on Monad blockchain, including bonding curves, DEX trading, and real-time event monitoring.\n\n## Features\n\n- \ud83d\ude80 **Trading**: Execute buy/sell operations on bonding curves with slippage protection\n- \ud83d\udcb0 **Token Operations**: ERC-20 token interactions (balance, approve, transfer)\n- \ud83d\udcca **Bonding Curves**: Query curve parameters and check listing status\n- \ud83d\udd04 **Real-time Streaming**: Monitor bonding curve and DEX events via WebSocket with token filtering\n- \ud83d\udcda **Historical Indexing**: Fetch and analyze past events with CurveIndexer and DexIndexer\n- \u26a1 **Async/Await**: Fully asynchronous design for high performance\n- \ud83d\udd10 **Type Safety**: Full type hints for better IDE support\n\n## Installation\n\n```bash\npip install nadfun-sdk\n```\n\nOr install from source:\n\n```bash\ngit clone https://github.com/naddotfun/nadfun-sdk-python.git\ncd nadfun-sdk-python\npip install -e .\n```\n\n## Quick Start\n\n```python\nimport asyncio\nfrom nadfun_sdk import Trade, BuyParams, calculate_slippage, parseMon\n\nasync def main():\n    # Initialize trade client\n    trade = Trade(rpc_url=\"https://monad-testnet.rpc.url\", private_key=\"your_private_key\")\n\n    # Get quote for buying tokens\n    token = \"0x1957d1BED06c69f479f564E9Dc163e3Cf4E3eF03\"\n    amount_in = parseMon(1)  # 1 MON\n    quote = await trade.get_amount_out(token, amount_in, is_buy=True)\n\n    # Execute buy with slippage protection\n    params = BuyParams(\n        token=token,\n        to=trade.address,\n        amount_in=amount_in,\n        amount_out_min=calculate_slippage(quote.amount, 5)  # 5% slippage tolerance\n    )\n    tx_hash = await trade.buy(params, quote.router)\n    print(f\"Transaction: {tx_hash}\")\n\nasyncio.run(main())\n```\n\n## Core Modules\n\n### \ud83d\ude80 Trading\n\nExecute trades on bonding curves with automatic routing:\n\n```python\nfrom nadfun_sdk import Trade, BuyParams, SellParams, calculate_slippage\n\ntrade = Trade(rpc_url, private_key)\n\n# Get quotes\nbuy_quote = await trade.get_amount_out(token, mon_amount, is_buy=True)\nsell_quote = await trade.get_amount_out(token, token_amount, is_buy=False)\n\n# Buy tokens\nbuy_params = BuyParams(\n    token=token,\n    to=wallet_address,\n    amount_in=mon_amount,\n    amount_out_min=calculate_slippage(buy_quote.amount, 5),\n    deadline=None  # Auto-sets to now + 120 seconds\n)\ntx = await trade.buy(buy_params, buy_quote.router)\n\n# Sell tokens\nsell_params = SellParams(\n    token=token,\n    to=wallet_address,\n    amount_in=token_amount,\n    amount_out_min=calculate_slippage(sell_quote.amount, 5),\n    deadline=None\n)\ntx = await trade.sell(sell_params, sell_quote.router)\n\n# Wait for transaction\nreceipt = await trade.wait_for_transaction(tx, timeout=60)\n```\n\n### \ud83d\udcb0 Token Operations\n\nInteract with ERC-20 tokens:\n\n```python\nfrom nadfun_sdk import Token\n\ntoken = Token(rpc_url, private_key)\n\n# Get token metadata\nmetadata = await token.get_metadata(token_address)\nprint(f\"Token: {metadata['name']} ({metadata['symbol']})\")\nprint(f\"Decimals: {metadata['decimals']}\")\nprint(f\"Total Supply: {metadata['totalSupply']}\")\n\n# Check balances\nbalance = await token.get_balance(token_address)\nbalance = await token.get_balance(token_address, owner_address)  # Check other address\n\n# Check allowance\nallowance = await token.get_allowance(token_address, spender_address)\n\n# Approve tokens\ntx = await token.approve(token_address, spender_address, amount)\n\n# Transfer tokens\ntx = await token.transfer(token_address, recipient_address, amount)\n\n# Smart approval (only approves if needed)\ntx = await token.check_and_approve(token_address, spender_address, required_amount)\n```\n\n### \ud83d\udcca Bonding Curve Data\n\nQuery bonding curve information:\n\n```python\n# Check if token is listed on curve\nis_listed = await trade.is_listed(token_address)\n\n# Get curve reserves\ncurve_data = await trade.get_curves(token_address)\nprint(f\"Reserve MON: {curve_data.reserve_mon}\")\nprint(f\"Reserve Token: {curve_data.reserve_token}\")\n\n# Get amount needed for specific output\nquote = await trade.get_amount_in(token_address, desired_output, is_buy=True)\n```\n\n### \ud83d\udd04 Real-time Event Streaming\n\nMonitor events in real-time using WebSocket connections:\n\n#### Curve Events Stream\n\n```python\nfrom nadfun_sdk import CurveStream, EventType, CurveEvent\n\n# Initialize stream\nstream = CurveStream(ws_url)\n\n# Subscribe to specific events\nstream.subscribe([EventType.BUY])  # Only BUY events\nstream.subscribe([EventType.SELL])  # Only SELL events\nstream.subscribe([EventType.BUY, EventType.SELL])  # Both\nstream.subscribe()  # All events (default)\n\n# Filter by token addresses (optional)\nstream.subscribe(\n    [EventType.BUY, EventType.SELL],\n    token_addresses=[\"0x1234...\", \"0x5678...\"]  # Only events from these tokens\n)\n\n# Process events with typed async iterator\nevent: CurveEvent\nasync for event in stream.events():\n    print(f\"Event: {event['eventName']}\")      # \"BUY\" or \"SELL\"\n    print(f\"Trader: {event['trader']}\")        # Buyer/Seller address\n    print(f\"Token: {event['token']}\")          # Token address\n    print(f\"Amount In: {event['amountIn']}\")   # MON for buy, tokens for sell\n    print(f\"Amount Out: {event['amountOut']}\") # Tokens for buy, MON for sell\n    print(f\"Block: {event['blockNumber']}\")\n    print(f\"Tx: {event['transactionHash']}\")\n```\n\n#### DEX Swap Events Stream\n\n```python\nfrom nadfun_sdk import DexStream, DexSwapEvent\n\n# Initialize stream\nstream = DexStream(ws_url)\n\n# Subscribe to tokens (automatically finds pools)\nstream.subscribe_tokens(\"0x1234...\")  # Single token\nstream.subscribe_tokens([\"0x1234...\", \"0x5678...\"])  # Multiple tokens\n\n# Process swap events with typed iterator\nevent: DexSwapEvent\nasync for event in stream.events():\n    print(f\"Event: {event['eventName']}\")\n    print(f\"BlockNumber: {event['blockNumber']}\")\n    print(f\"Pool: {event['pool']}\")\n    print(f\"Sender: {event['sender']}\")\n    print(f\"Recipient: {event['recipient']}\")\n    print(f\"Amount0: {event['amount0']}\")\n    print(f\"Amount1: {event['amount1']}\")\n    print(f\"Liquidity: {event['liquidity']}\")\n    print(f\"Tick: {event['tick']}\")\n    print(f\"Price (sqrt X96): {event['sqrtPriceX96']}\")\n    print(f\"Tx: {event['transactionHash']}\")\n    print(\"-\" * 50)\n```\n\n### \ud83d\udcda Historical Event Indexing\n\nIndex historical blockchain events for analysis:\n\n#### Curve Indexer\n\n```python\nfrom nadfun_sdk import CurveIndexer, EventType\n\n# Initialize indexer\nindexer = CurveIndexer(rpc_url)\n\n# Get current block number\nlatest_block = await indexer.get_block_number()\nfrom_block = latest_block - 1000  # Last 1000 blocks\n\n# Fetch all events\nall_events = await indexer.fetch_events(from_block, latest_block)\n\n# Filter by event types\ntrade_events = await indexer.fetch_events(\n    from_block,\n    latest_block,\n    event_types=[EventType.BUY, EventType.SELL]\n)\n\n# Filter by token\ntoken_events = await indexer.fetch_events(\n    from_block,\n    latest_block,\n    token_filter=\"0x1234...\"\n)\n```\n\n#### DEX Indexer\n\n```python\nfrom nadfun_sdk import DexIndexer\n\n# Initialize indexer\nindexer = DexIndexer(rpc_url)\n\n# Get current block number\nlatest_block = await indexer.get_block_number()\n\n# Fetch swap events by tokens (automatically finds pools)\nswap_events = await indexer.fetch_events(\n    from_block,\n    latest_block,\n    tokens=[\"0x1234...\", \"0x5678...\"]\n)\n\n# Or fetch by specific pool addresses\npool_events = await indexer.fetch_events(\n    from_block,\n    latest_block,\n    pools=\"0xabcd...\"\n)\n```\n\n## API Reference\n\n### Trade Class\n\n```python\ntrade = Trade(rpc_url: str, private_key: str)\n```\n\n#### Methods\n\n- `async get_amount_out(token: str, amount_in: int, is_buy: bool) -> QuoteResult`\n\n  - Get expected output amount for a trade\n  - Returns `QuoteResult` with `router` address and `amount`\n\n- `async get_amount_in(token: str, amount_out: int, is_buy: bool) -> QuoteResult`\n\n  - Get required input amount for desired output\n  - Returns `QuoteResult` with `router` address and `amount`\n\n- `async buy(params: BuyParams, router: str, nonce: int = None, gas: int = None) -> str`\n\n  - Execute buy transaction\n  - Returns transaction hash\n\n- `async sell(params: SellParams, router: str, nonce: int = None, gas: int = None) -> str`\n\n  - Execute sell transaction\n  - Returns transaction hash\n\n- `async is_listed(token: str) -> bool`\n\n  - Check if token is listed on bonding curve\n\n- `async get_curves(token: str) -> CurveData`\n\n  - Get bonding curve reserves\n  - Returns `CurveData` with `reserve_mon` and `reserve_token`\n\n- `async wait_for_transaction(tx_hash: str, timeout: int = 60) -> Dict`\n  - Wait for transaction confirmation\n\n### Token Class\n\n```python\ntoken = Token(rpc_url: str, private_key: str)\n```\n\n#### Methods\n\n- `async get_balance(token: str, address: str = None) -> int`\n\n  - Get token balance (defaults to own address)\n\n- `async get_allowance(token: str, spender: str, owner: str = None) -> int`\n\n  - Get approved amount (defaults to own address as owner)\n\n- `async get_metadata(token: str) -> TokenMetadata`\n\n  - Get token metadata (name, symbol, decimals, totalSupply)\n\n- `async approve(token: str, spender: str, amount: int) -> str`\n\n  - Approve tokens for spending\n\n- `async transfer(token: str, to: str, amount: int) -> str`\n\n  - Transfer tokens\n\n- `async check_and_approve(token: str, spender: str, required: int, buffer_percent: float = 10) -> Optional[str]`\n  - Smart approval - only approves if current allowance is insufficient\n\n### Stream Classes\n\n#### CurveStream\n\n```python\nstream = CurveStream(ws_url: str)\n```\n\n- `subscribe(event_types: List[EventType] = None)` - Set events to subscribe to\n- `async events() -> AsyncIterator[Dict]` - Async iterator yielding parsed events\n\n#### DexStream\n\n```python\nstream = DexStream(ws_url: str)\n```\n\n- `subscribe_tokens(token_addresses: Union[str, List[str]])` - Set tokens to monitor\n- `async events() -> AsyncIterator[Dict]` - Async iterator yielding swap events\n\n### Indexer Classes\n\n#### CurveIndexer\n\nHistorical event indexer for bonding curve events:\n\n```python\nindexer = CurveIndexer(rpc_url: str)\n```\n\n- `async fetch_events(from_block: int, to_block: int, event_types: List[EventType] = None, token_filter: str = None) -> List[Dict]`\n  - Fetch historical curve events in a block range\n  - Optionally filter by event types (CREATE, BUY, SELL, SYNC, LOCK, LISTED)\n  - Optionally filter by token address\n- `async get_block_number() -> int`\n  - Get current block number\n\n#### DexIndexer\n\nHistorical event indexer for DEX swap events:\n\n```python\nindexer = DexIndexer(rpc_url: str)\n```\n\n- `async fetch_events(from_block: int, to_block: int, pools: Union[str, List[str]] = None, tokens: Union[str, List[str]] = None) -> List[Dict]`\n  - Fetch historical swap events in a block range\n  - Optionally filter by pool address(es) or token address(es)\n  - When filtering by tokens, automatically finds pools from V3 factory\n- `async get_block_number() -> int`\n  - Get current block number\n\n### Type Definitions\n\n```python\nclass BuyParams:\n    token: str          # Token address to buy\n    to: str            # Recipient address\n    amount_in: int     # MON amount to spend\n    amount_out_min: int # Minimum tokens to receive\n    deadline: Optional[int] = None  # Transaction deadline\n    nonce: Optional[int] = None     # Transaction nonce\n    gas: Optional[int] = None       # Gas limit\n    gas_price: Optional[int] = None # Gas price\n\nclass SellParams:\n    token: str          # Token address to sell\n    to: str            # Recipient address\n    amount_in: int     # Token amount to sell\n    amount_out_min: int # Minimum MON to receive\n    deadline: Optional[int] = None\n    nonce: Optional[int] = None\n    gas: Optional[int] = None\n    gas_price: Optional[int] = None\n\nclass QuoteResult:\n    router: str        # Router contract address\n    amount: int        # Expected amount\n\nclass CurveData:\n    reserve_mon: int   # MON reserves in curve\n    reserve_token: int # Token reserves in curve\n\nclass TokenMetadata:\n    name: str\n    symbol: str\n    decimals: int\n    totalSupply: int\n\n# Event Types (TypedDict for type hints)\nclass CurveEvent:\n    eventName: str          # \"BUY\" or \"SELL\"\n    blockNumber: int        # Block number\n    transactionHash: str    # Transaction hash\n    trader: str            # Buyer/Seller address\n    token: str             # Token address\n    amountIn: int          # Amount in\n    amountOut: int         # Amount out\n\nclass DexSwapEvent:\n    eventName: str          # \"Swap\"\n    blockNumber: int        # Block number\n    transactionHash: str    # Transaction hash\n    pool: str              # Pool address\n    sender: str            # Sender address\n    recipient: str         # Recipient address\n    amount0: int           # Token0 amount (can be negative)\n    amount1: int           # Token1 amount (can be negative)\n    sqrtPriceX96: int      # Square root price\n    liquidity: int         # Liquidity\n    tick: int              # Price tick\n```\n\n### Utilities\n\n- `calculate_slippage(amount: int, percent: float) -> int`\n  - Calculate minimum output amount with slippage tolerance\n- `parseMon(amount: float | str) -> int`\n  - Convert MON amount to wei (18 decimals)\n\n## Configuration\n\nCreate a `.env` file in your project root. You can copy from `.env.example`:\n\n```bash\ncp .env.example .env\n```\n\n### Environment Variables\n\n```bash\n# Network endpoints\nRPC_URL=                                   # HTTP RPC endpoint for Monad testnet\nWS_URL=                                    # WebSocket endpoint for real-time event streaming\n\n# Wallet configuration\nPRIVATE_KEY=your_private_key_here         # Private key (without 0x prefix)\n\n# Token addresses\nTOKEN=0x...                                # Single token address for trading\nTOKENS=0x...                               # Multiple token addresses for DEX monitoring (comma-separated)\n\n# Trading parameters\nAMOUNT=                                    # Amount in MON for trading (e.g., 0.1)\nSLIPPAGE=                                  # Slippage tolerance percentage (e.g., 5)\n```\n\n### Network Information\n\n- **Chain**: Monad Testnet\n- **Chain ID**: 10143\n- **Native Token**: MON\n- **Block Explorer**: https://explorer.monad.net\n\n## Examples\n\nThe SDK includes comprehensive examples in the `examples/` directory. First, set up your environment:\n\n```bash\n# Copy example environment file\ncp .env.example .env\n\n# Edit .env with your configuration\nnano .env\n```\n\n### Trading Examples\n\n#### Buy Tokens (`examples/trade/buy.py`)\n\n```bash\npython examples/trade/buy.py\n```\n\nDemonstrates buying tokens on the bonding curve with slippage protection.\n\n#### Sell Tokens (`examples/trade/sell.py`)\n\n```bash\npython examples/trade/sell.py\n```\n\nShows selling tokens back to the bonding curve.\n\n### Token Operations (`examples/token_operations.py`)\n\n```bash\npython examples/token_operations.py\n```\n\nExamples of token interactions:\n\n- Checking balances\n- Approving spending\n- Transferring tokens\n- Getting token metadata\n\n### Real-time Event Streaming\n\n#### Curve Events (`examples/stream/curve_stream.py`)\n\n```bash\npython examples/stream/curve_stream.py\n```\n\nStream real-time bonding curve Buy/Sell events with filtering options.\n\n#### DEX Swaps (`examples/stream/dex_stream.py`)\n\n```bash\npython examples/stream/dex_stream.py\n```\n\nMonitor DEX swap events for specified tokens in real-time.\n\n### Historical Event Indexing\n\n#### Curve Indexer (`examples/stream/curve_indexer.py`)\n\n```bash\npython examples/stream/curve_indexer.py\n```\n\nIndex historical bonding curve events:\n\n- Fetch all event types or filter specific ones\n- Filter by token address\n- Analyze event patterns\n\n#### DEX Indexer (`examples/stream/dex_indexer.py`)\n\n```bash\npython examples/stream/dex_indexer.py\n```\n\nIndex historical DEX swap events:\n\n- Fetch swap events from V3 pools\n- Filter by pool addresses or token addresses\n- Analyze swap patterns\n\n## Contract Addresses\n\nAll contract addresses are defined in `src/nadfun_sdk/constants.py`:\n\n- **Wrapper Contract**: `0x4F5A3518F082275edf59026f72B66AC2838c0414`\n- **Curve Contract**: `0x52D34d8536350Cd997bCBD0b9E9d722452f341F5`\n- **Lens Contract**: `0x4F5A3518F082275edf59026f72B66AC2838c0414`\n- **V3 Factory**: `0x4f6F577e3bfB25dF11f635d93E5ff645d30CB474`\n- **WMON Token**: `0x88CCF31322CEc314E36D0c993651cE14e4AE7B2d`\n\n## Requirements\n\n- Python 3.11+\n- web3.py >= 7.0.0\n- eth-account\n- eth-abi\n- python-dotenv\n\n## Development\n\n```bash\n# Clone the repository\ngit clone https://github.com/naddotfun/nadfun-sdk-python.git\ncd nadfun-sdk-python\n\n# Install in development mode\npip install -e .\n\n# Install development dependencies\npip install -r requirements-dev.txt\n\n# Format code\nblack src/ examples/\n\n# Type checking\nmypy src/\n```\n\n## License\n\nMIT License - see [LICENSE](LICENSE) for details.\n\n## Support\n\n- \ud83d\udcd6 [Examples](examples/) - Comprehensive usage examples\n- \ud83d\udc1b [Issues](https://github.com/naddotfun/nadfun-sdk-python/issues) - Bug reports and feature requests\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Python SDK for Nad.fun contracts",
    "version": "0.1.3",
    "project_urls": {
        "Homepage": "https://github.com/naddotfun/nadfun-sdk",
        "Issues": "https://github.com/naddotfun/nadfun-sdk/issues",
        "Repository": "https://github.com/naddotfun/nadfun-sdk"
    },
    "split_keywords": [
        "blockchain",
        " ethereum",
        " defi",
        " trading",
        " bonding-curve"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "ffe22e17e516cedb13c0df7367417d3b410135ba31634daaf101ba0caf5990f6",
                "md5": "630483ea536dfb4933e830c7af4f898f",
                "sha256": "3fd4e1eb7b48cff798095326b8e7ef9b6df023f3cc836de59e31c24fd5cc036c"
            },
            "downloads": -1,
            "filename": "nadfun_sdk-0.1.3-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "630483ea536dfb4933e830c7af4f898f",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.11",
            "size": 29760,
            "upload_time": "2025-08-31T12:16:16",
            "upload_time_iso_8601": "2025-08-31T12:16:16.319755Z",
            "url": "https://files.pythonhosted.org/packages/ff/e2/2e17e516cedb13c0df7367417d3b410135ba31634daaf101ba0caf5990f6/nadfun_sdk-0.1.3-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "15a2b56959512e917f69712e22aa49e1ea3692f55a5ba1eb856ff9cb2c3a417c",
                "md5": "d7a6c96c87d32162eb401bfea745dcb5",
                "sha256": "9f8c8b76a6091e93dd2d80711d251e79f11e50668d4fb525b2dbc1a94e576ec0"
            },
            "downloads": -1,
            "filename": "nadfun_sdk-0.1.3.tar.gz",
            "has_sig": false,
            "md5_digest": "d7a6c96c87d32162eb401bfea745dcb5",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.11",
            "size": 26771,
            "upload_time": "2025-08-31T12:16:17",
            "upload_time_iso_8601": "2025-08-31T12:16:17.629161Z",
            "url": "https://files.pythonhosted.org/packages/15/a2/b56959512e917f69712e22aa49e1ea3692f55a5ba1eb856ff9cb2c3a417c/nadfun_sdk-0.1.3.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-08-31 12:16:17",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "naddotfun",
    "github_project": "nadfun-sdk",
    "github_not_found": true,
    "lcname": "nadfun-sdk"
}
        
Elapsed time: 0.45717s