Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,6 @@ jobs:
uv run --isolated --python=3.13 pytest
uv run --isolated --python=3.14 pytest
env:
TEST_API_KEY: ${{ secrets.TEST_API_KEY }}
TEST_API_SECRET: ${{ secrets.TEST_API_SECRET }}
TEST_API_PASSPHRASE: ${{ secrets.TEST_API_PASSPHRASE }}
TESTNET4_API_KEY: ${{ secrets.TESTNET4_API_KEY }}
TESTNET4_API_KEY_SECRET: ${{ secrets.TESTNET4_API_KEY_SECRET }}
TESTNET4_API_KEY_PASSPHRASE: ${{ secrets.TESTNET4_API_KEY_PASSPHRASE }}
31 changes: 31 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.0.20] - 2026-05-13

### Added

- `stream/v1` WebSocket client (`stream_v1` package, models, auth, public, subscription).
- `account.read_notifications()` method — maps to `PUT /account/notifications` (mark all as read).
- `examples/stream_v1.py` demonstrating WebSocket usage.

### Changed

- Package layout: `lnmarkets_sdk.rest_v3` → `lnmarkets_sdk.rest.v3`.
- Renamed `examples/basic.py` → `examples/rest_v3.py`.
- `examples/rest_v3.py`: take-profit update now opens a real isolated market trade and uses its ID instead of hardcoded UUID.

### Removed

- `AccountClient.withdraw_internal` (endpoint not present in api-rest-v3).
- `AccountClient.get_internal_deposits` (endpoint not present in api-rest-v3).
- `AccountClient.get_internal_withdrawals` (endpoint not present in api-rest-v3).
- Associated models: `WithdrawInternalParams`, `WithdrawInternalResponse`, `InternalDeposit`, `InternalWithdrawal`, `GetInternalDepositsParams`, `GetInternalWithdrawalsParams`.

### Fixed

- `examples/rest_v3.py`: `update_takeprofit` no longer hits hardcoded trade ID that returned `400 You do not own this trade`.
134 changes: 120 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
# LN Markets SDK v3
# LN Markets SDK

[![CI](https://github.com/ln-markets/sdk-python/actions/workflows/check.yml/badge.svg)](https://github.com/ln-markets/sdk-python/actions/workflows/check.yml)

This is the Python version of the LN Markets API SDK. It provides a client-based interface for interacting with the LN Markets API.
Python SDK for the LN Markets API. Ships two clients:

## Usage
- **REST v3** (`lnmarkets_sdk.rest.v3`) — request/response API.
- **Stream v1** (`lnmarkets_sdk.stream.v1`) — JSON-RPC WebSocket with subscriptions.

## REST v3

For public endpoints, you can just do this:

```python
from lnmarkets_sdk.v3.http.client import LNMClient
from lnmarkets_sdk.rest.v3.http.client import LNMClient
import asyncio

async with LNMClient() as client:
Expand All @@ -23,7 +26,7 @@ Remember to sleep between requests, as the rate limit is 1 requests per second f
For endpoints that need authentication, you need to create an instance of the `LNMClient` class and provide your API credentials:

```python
from lnmarkets_sdk.v3.http.client import APIAuthContext, APIClientConfig, LNMClient
from lnmarkets_sdk.rest.v3.http.client import APIAuthContext, APIClientConfig, LNMClient

config = APIClientConfig(
authentication=APIAuthContext(
Expand All @@ -39,12 +42,12 @@ async with LNMClient(config) as client:
account = await client.account.get_account()
```

For endpoints that requires input parameters, you can find the corresponding models in the `lnmarkets_sdk.models` module.
For endpoints that requires input parameters, you can find the corresponding models in the `lnmarkets_sdk.rest.v3.models` module.

```python

from lnmarkets_sdk.v3.http.client import APIAuthContext, APIClientConfig, LNMClient
from lnmarkets_sdk.v3.models.account import GetLightningDepositsParams
from lnmarkets_sdk.rest.v3.http.client import APIAuthContext, APIClientConfig, LNMClient
from lnmarkets_sdk.rest.v3.models.account import GetLightningDepositsParams

config = APIClientConfig(
authentication=APIAuthContext(
Expand All @@ -62,9 +65,9 @@ async with LNMClient(config) as client:
)
```

Check our [example](./examples/basic.py) for more details.
Check our [REST example](./examples/rest_v3.py) for more details.

## Available Methods
### Available Methods

🔒 = requires API credentials

Expand All @@ -78,14 +81,12 @@ client.account.get_bitcoin_address()
client.account.add_bitcoin_address()
client.account.deposit_lightning()
client.account.withdraw_lightning()
client.account.withdraw_internal()
client.account.withdraw_on_chain()
client.account.get_lightning_deposits()
client.account.get_lightning_withdrawals()
client.account.get_internal_deposits()
client.account.get_internal_withdrawals()
client.account.get_on_chain_deposits()
client.account.get_on_chain_withdrawals()
client.account.read_notifications()

# Futures
client.futures.get_ticker()
Expand Down Expand Up @@ -131,9 +132,114 @@ client.synthetic_usd.get_swaps() # 🔒
client.synthetic_usd.new_swap() # 🔒
```

## Stream v1

WebSocket JSON-RPC client. Connect, subscribe to topics, register event listeners.

Public stream:

```python
import asyncio
from lnmarkets_sdk.stream.v1 import StreamClientConfig, create_stream_client
from lnmarkets_sdk.stream.v1.models import SubscribeParams

async def main():
config = StreamClientConfig(network="mainnet")
client = create_stream_client(config)

client.on(
"futures/inverse/btc_usd/ticker",
lambda data: print(data["lastPrice"]),
)

await client.connect()
await client.subscription.subscribe(
SubscribeParams(topics=["futures/inverse/btc_usd/ticker"]),
)
await asyncio.sleep(30)
await client.close()

asyncio.run(main())
```

Authenticated stream (private topics: trades, orders, position, wallet):

```python
from lnmarkets_sdk.stream.v1 import StreamClientConfig, create_stream_client
from lnmarkets_sdk.stream.v1.models import AuthenticateParams, SubscribeParams

config = StreamClientConfig(
network="mainnet",
reconnect_enabled=True,
reconnect_interval=5.0,
max_reconnect_attempts=5,
)
client = create_stream_client(config)

await client.connect()
await client.auth.authenticate(
AuthenticateParams(key=your_key, secret=your_secret, passphrase=your_passphrase),
)
await client.subscription.subscribe(
SubscribeParams(topics=[
"futures/inverse/btc_usd/isolated/trades",
"wallet/deposit",
"wallet/withdrawal",
]),
)
```

Server rate-limits to 10 messages/sec per socket — pace RPC calls accordingly.

Check our [Stream example](./examples/stream_v1.py) for full RPC + topic coverage.

### Available RPCs and Topics

🔒 = requires authentication

```python
# Public RPCs
client.public.hello()
client.public.ping()
client.public.time()

# Auth RPCs 🔒
client.auth.authenticate()
client.auth.whoami()

# Subscription RPCs
client.subscription.subscribe()
client.subscription.unsubscribe()
client.subscription.unsubscribe_all()

# Lifecycle events
client.on("open", ...)
client.on("close", ...)
client.on("error", ...)
client.on("reconnected", ...)

# Public topics
"announcements"
"futures/inverse/btc_usd/ticker"
"futures/inverse/btc_usd/lastPrice"
"futures/inverse/btc_usd/index"
"futures/inverse/btc_usd/buckets"
"futures/inverse/btc_usd/funding"
"futures/inverse/btc_usd/ohlc/1m"
"futures/inverse/btc_usd/ohlc/5m"

# Private topics 🔒
"futures/inverse/btc_usd/isolated/trades"
"futures/inverse/btc_usd/cross/orders"
"futures/inverse/btc_usd/cross/position"
"wallet/deposit"
"wallet/withdrawal"
```

## API Reference

For full API documentation, see: [LNM API v3 Documentation](https://api.lnmarkets.com/v3/)
- [REST](https://docs.lnmarkets.com/en/api)
- [STREAM](https://docs.lnmarkets.com/en/stream)

## Contributing

Expand Down
Loading
Loading