dhali-py 2.0.0
A Python package for interfacing with Dhali
License: BSD 3-Clause License

[![Package Tests](https://github.com/Dhali-org/Dhali-py/actions/workflows/package_test.yaml/badge.svg)](https://github.com/Dhali-org/Dhali-py/actions/workflows/package_test.yaml)
[![Release](https://github.com/Dhali-org/Dhali-py/actions/workflows/release.yaml/badge.svg)](https://github.com/Dhali-org/Dhali-py/actions/workflows/release.yaml)


# dhali-py

A Python library for managing payment channels (XRPL & Ethereum) and generating auth tokens (i.e., payment-claims) for use with [Dhali](https://dhali.io) APIs. 

Includes support for **Machine-to-Machine (M2M) payments** using seamless off-chain claims.

---

## Installation

```bash
pip install dhali-py
```

---

## Quick Start: Machine-to-Machine Payments

### 1. XRPL

All signing is performed locally using `xrpl-py`.

```python
from dhali.dhali_channel_manager import DhaliChannelManager, ChannelNotFound
from dhali.config_utils import get_available_dhali_currencies
from xrpl.wallet import Wallet
from xrpl.clients import JsonRpcClient

seed    = "sXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
wallet  = Wallet.from_secret(seed=seed)
rpc_client = JsonRpcClient("https://testnet.xrpl-labs.com/")

currencies = get_available_dhali_currencies()
xrpl_testnet = currencies["XRPL.TESTNET"]["XRP"]

# Use the Factory to get an XRPL Manager
manager = DhaliChannelManager.xrpl(
    wallet=wallet, 
    rpc_client=rpc_client, 
    protocol="XRPL.TESTNET", 
    currency=xrpl_testnet.currency
)

# Generate a claim (Base64 encoded)
try:
    claim = manager.get_auth_token()
except ChannelNotFound:
    manager.deposit(1_000_000)          # deposit 1 XRP
    claim = manager.get_auth_token()    # 🔑 regenerate after deposit
print("XRPL Claim:", claim)
```

### 2. Ethereum (EVM)

Supports Ethereum, Sepolia, Holesky, etc. Requires `eth-account` and `web3.py`.

```python
from dhali.dhali_channel_manager import DhaliChannelManager, ChannelNotFound
from dhali.config_utils import get_available_dhali_currencies
from eth_account import Account
from web3 import Web3

# 1. Setup Account & Provider
private_key = "0x..."
account = Account.from_key(private_key)
w3 = Web3(Web3.HTTPProvider("https://ethereum-sepolia.publicnode.com"))

# 2. Fetch Available Currencies
currencies = get_available_dhali_currencies()
sepolia_rlusd = currencies["SEPOLIA"]["RLUSD"] # or "USDC"

# 3. Instantiate Manager with Dynamic Config
manager = DhaliChannelManager.evm(
    account=account,
    w3=w3,
    protocol="SEPOLIA",
    currency=sepolia_rlusd.currency
)

# 4. Generate EIP-712 Signed Claim
# Note: For RLUSD (18 decimals), 1 unit = 10^18. For USDC (6 decimals), 1 unit = 10^6.
amount = int(0.1 * 10**sepolia_rlusd.currency.scale) # 0.01 RLUSD

try:
    claim = manager.get_auth_token() 
except ChannelNotFound:
    manager.deposit(amount)
    claim = manager.get_auth_token(amount=amount) 
print("EVM Claim:", claim)
```

---

## Usage in API Calls

Once you have the claim string, include it in your API request query parameters or headers as required by the Dhali Gateway.

```python
import requests

url = f"https://xrplcluster.dhali.io?payment-claim={claim}"
response = requests.post(url, json={"data": "..."})

if response.status_code == 402:
    print("Payment Required: Channel may need topping up.")
```

---

## Classes

### `DhaliChannelManager` (Factory)

* `xrpl(wallet, rpc_client, protocol, currency, client=None, public_config=None) -> DhaliXrplChannelManager`
* `evm(account, w3, protocol, currency, client=None, public_config=None) -> DhaliEthChannelManager`

### `get_available_dhali_currencies()`

Fetches current Dhali configuration and returns a dict:
```python
{
    "SEPOLIA": {
        "USDC": NetworkCurrencyConfig(currency=..., destination_address=...),
        ...
    },
    ...
}
```

Here’s a clean, minimal addition you can append near the end of the README (for example, just before the “Classes” section or after it):

---

## Async Workflows

Currently, `dhali-py` provides a synchronous interface for managing payment channels and generating claims.

If you would like to see **native async/await support** (e.g., `async` workflows using `asyncio`, async Web3 providers, or async XRPL clients), please drop us a message and let us know. Community feedback helps us prioritise features 🚀

---