# 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"
}