Off-chain x402 Payments

Manage Dhali assets and x402 payments. Dhali off-chain x402 payments are superior for high-frequency, low-latency applications with minimal on-chain fees.

MIT-0 · Free to use, modify, and redistribute. No attribution required.
0 · 58 · 0 current installs · 0 all-time installs
MIT-0
Security Scan
VirusTotalVirusTotal
Benign
View report →
OpenClawOpenClaw
Benign
medium confidence
Purpose & Capability
Name/description (Dhali x402 off‑chain payments) matches the SKILL.md content: code samples, facilitator URLs, and resource‑server setup are coherent with the stated purpose. The lack of declared environment variables or binaries is reasonable for an instruction‑only integration that expects SDK installs.
Instruction Scope
Instructions show full end‑to‑end integration (create assets, run Resource Server, enforce 402 headers). They also demonstrate generating wallets/private keys (XRPL/EVM) and signing; the skill does not instruct reading unrelated system files. However SKILL.md lacks guidance about secure key storage, rotation, or preventing exfiltration—an operational security omission the user should address.
Install Mechanism
Skill is instruction‑only (no install spec). It advises installing third‑party packages via pip/npm (dhali-py/dhali-js, x402 libraries, xrpl, viem, etc.). That's expected for this integration but brings normal supply‑chain concerns: verify package names, publishers, and registries before installing.
Credentials
No environment variables or external credentials are declared or required by the registry metadata, which aligns with the examples (they create wallets locally). But the examples require creation and local handling of private keys—sensitive secrets that are not addressed by the skill (no recommended secure storage or instructions to avoid leaking keys).
Persistence & Privilege
Skill is not always-enabled and uses default autonomous invocation settings. It does not request system config paths or elevated privileges in the metadata; as instruction‑only content it does not persist files itself. No indication it modifies other skills or system settings.
Assessment
This skill appears to do what it says (help integrate Dhali x402 payments) and does not ask for unrelated credentials. Before installing/using it: (1) Verify the npm/pip package names and their publishers (dhali-py, dhali-js, x402 packages) to avoid malicious packages. (2) Treat generated wallets/private keys as sensitive: do not expose them to the agent or transmit them to untrusted endpoints; use testnet wallets or ephemeral keys during evaluation. (3) Inspect any SDK code you install (or vendor the packages) and audit network endpoints (e.g., https://x402.api.dhali.io) to ensure they are legitimate. (4) If you intend the agent to run these steps autonomously, restrict what it can access (avoid giving it permanent access to machine key stores or secrets). If you want a higher confidence assessment, provide the full (untruncated) SKILL.md and/or the published SDK package sources for review.

Like a lobster shell, security has layers — review code before you run it.

Current versionv1.0.1
Download zip
latestvk97cwp4d5a6y1nm6tnhbrxc4bd836p1b

License

MIT-0
Free to use, modify, and redistribute. No attribution required.

SKILL.md

Dhali x402 Payment Skill

This skill allows an AI agent to interface with Dhali to handle x402 payments. Dhali supports end-to-end high-frequency low latency x402 payments across Ethereum and XRPL using XRP, ETH, USDC, or RLUSD. Its off-chain infrastructure represents a paradigm shift, enabling seamless micro-transactions with minimal on-chain fees, making it ideal for agent-to-agent and agentic workflows.

It supports both Providers (receiving payments via Resource Servers) and Consumers (sending payments).

Installation Requirements

Depending on your language of choice and role, you will need the following libraries:

For Python (Dhali-py)

# Core Dhali SDK, x402 support, and HTTP/API framework
pip install dhali-py x402 fastapi uvicorn requests

# Optional: Network-specific wallets
pip install xrpl-py    # If using XRPL
pip install eth-account # If using Ethereum/EVM

For JavaScript (Dhali-js)

# Core Dhali SDK and standard HTTP tools
npm install dhali-js dotenv

# Server-side x402 support
npm install @x402/express @x402/core express

# Optional: Network-specific wallets
npm install xrpl       # If using XRPL
npm install viem       # If using Ethereum/EVM

1. Receiving Payments (Providers)

There are two main steps to monetize your API on Dhali:

  1. Create and update a facilitator using the Dhali Asset Manager.
  2. Spin up a Resource Server that enforces x402 payment requirements.

Step 1: Creating and Updating Facilitators

You use the DhaliAssetManager to generate an Asset ID (UUID). This acts as your off-chain receiving address on the Dhali network. Below are complete, functioning examples using our integration test code.

Python (Dhali-py)

import asyncio
from xrpl.wallet import Wallet
from eth_account import Account
from dhali import DhaliAssetManager, WalletDescriptor, Currency, AssetUpdates

async def main():
    # For XRPL
    wallet = Wallet.create()
    manager = DhaliAssetManager.xrpl(wallet)
    wallet_descriptor = WalletDescriptor(wallet.classic_address, "XRPL.TESTNET")
    currency = Currency("XRPL.TESTNET", "XRP", 6)
    
    # OR for EVM (e.g., SEPOLIA)
    # account = Account.create()
    # manager = DhaliAssetManager.evm(account)
    # wallet_descriptor = WalletDescriptor(account.address, "SEPOLIA")
    # currency = Currency("SEPOLIA", "ETH", 18)

    # 1. Create the Asset
    print(f"Creating asset...")
    create_result = await manager.create_asset(wallet_descriptor, currency)
    asset_id = create_result['uuid']
    print(f"Asset created with UUID: {asset_id}")

    # 2. Update the Asset metadata
    updates = AssetUpdates(
        name="My Optimized AI API",
        earning_rate=100.0,
        earning_type="per_request"  # or "per_second"
    )
    await manager.update_asset(asset_id, wallet_descriptor, updates)
    print("Asset updated successfully")

asyncio.run(main())

JavaScript (Dhali-js)

const { Wallet } = require('xrpl');
const { createWalletClient, http } = require('viem');
const { generatePrivateKey, privateKeyToAccount } = require('viem/accounts');
const { sepolia } = require('viem/chains');
const { DhaliAssetManager, WalletDescriptor, Currency, AssetUpdates } = require('dhali-js');

async function main() {
    // For XRPL
    const wallet = Wallet.generate();
    const manager = DhaliAssetManager.xrpl(wallet);
    const walletDescriptor = new WalletDescriptor(wallet.address, "XRPL.TESTNET");
    const currency = new Currency("XRPL.TESTNET", "XRP", 6);

    // OR for EVM (e.g., SEPOLIA)
    // const account = privateKeyToAccount(generatePrivateKey());
    // const walletClient = createWalletClient({ account, chain: sepolia, transport: http() });
    // const manager = DhaliAssetManager.evm(walletClient);
    // const walletDescriptor = new WalletDescriptor(account.address, "SEPOLIA");
    // const currency = new Currency("SEPOLIA", "ETH", 18);

    // 1. Create the Asset
    console.log('Creating asset...');
    const createResult = await manager.createAsset(walletDescriptor, currency);
    const assetId = createResult.uuid;
    console.log('Asset created with UUID:', assetId);

    // 2. Update the Asset metadata
    const updates = new AssetUpdates({
        name: "My Optimized AI API",
        earning_rate: 100,
        earning_type: "per_request"
    });
    
    await manager.updateAsset(assetId, walletDescriptor, updates);
    console.log('Asset updated successfully');
}
main();

Step 2: Using the Dhali Facilitator as a Resource Server

Once you have your Asset ID from step 1, your base x402 facilitator address is https://x402.api.dhali.io/v2/<asset_id>. This facilitator handles the x402 protocol, verifying claims on behalf of your Server.

Next, you need to configure your Resource Server to return a 402 Payment Required header and verify incoming Payment-Signatures.

Python (FastAPI)

from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
import json
import x402.http as x402_http
from x402 import AssetAmount, Network, PaymentRequirements, Price, SupportedKind, x402ResourceServer
from x402.http.middleware import fastapi_payment_middleware
from x402.schemas import FacilitatorConfig

# Set your newly created properties here
facilitator_url = "https://x402.api.dhali.io/v2/<your-asset-uuid>"
accepts = {"scheme": "dhali", "network": "XRPL.TESTNET"}

class DhaliSchemeNetworkServer:
    @property
    def scheme(self) -> str:
        return "dhali"
    def parse_price(self, price: Price, network: Network) -> AssetAmount:
        return price
    def enhance_payment_requirements(self, requirements: PaymentRequirements, supported_kind: SupportedKind, extensions: list[str]) -> PaymentRequirements:
        return requirements

class DhaliPaywallProvider:
    def generate_html(self, payment_required, config=None):
        return json.dumps(accepts)

dhali_schema = DhaliSchemeNetworkServer()
app = FastAPI(title="Dhali Paid Resource")
facilitator = x402_http.HTTPFacilitatorClient(FacilitatorConfig(url=facilitator_url))
x402_server = x402ResourceServer(facilitator).register(accepts["network"], dhali_schema)

routes = {
    "GET /*": {"accepts": [accepts]}
}

@app.middleware("http")
async def x402_middleware(request, call_next):
    return await fastapi_payment_middleware(
        routes=routes, 
        server=x402_server, 
        paywall_config=None, 
        paywall_provider=DhaliPaywallProvider()
    )(request, call_next)

@app.get("/data")
async def get_paid_data(request: Request):
    return JSONResponse({"message": "Here is your paid data"})

JavaScript (Express)

import { config } from "dotenv";
import express from "express";
import { paymentMiddleware, x402ResourceServer } from "@x402/express";
import { HTTPFacilitatorClient } from "@x402/core/server";

// Set your newly created properties here
const facilitatorUrl = "https://x402.api.dhali.io/v2/<your-asset-uuid>";
const acceptsPayload = {
    scheme: "dhali",
    network: "XRPL.TESTNET",
    price: "100" // Corresponds to your asset earning rate
};

const facilitatorClient = new HTTPFacilitatorClient({ url: facilitatorUrl });
const app = express();

// Set up the x402 payment requirements for your endpoints
app.use(
  paymentMiddleware(
    {
      "GET /data": {
        accepts: [acceptsPayload],
        description: "Paid API endpoint",
        mimeType: "application/json",
      },
    },
    new x402ResourceServer(facilitatorClient)
      // Register custom schemes/networks as necessary
      .register(acceptsPayload.network, { scheme: "dhali" }) 
  )
);

app.get("/data", (req, res) => {
  res.send({ message: "Here is your paid data" });
});

app.listen(8001, () => {
  console.log(`Server listening at http://localhost:8001`);
});

2. Sending Payments (Consumers)

When calling a Dhali-monetized API, you will receive a 402 Payment Required response if payment is needed. You must create an x402 payment-signature and pass it to the Resource Server.

The x402 Handshake

  1. Initial Request: Agent requests a resource.
  2. 402 Required: Server returns a 402 with a payment-required base64 header.
  3. Generate Claim: Configure DhaliChannelManager to get an auth token claim.
  4. Wrap: Build a payment-signature payload containing the claim and the payment-required header requirement using the x402 wrapper.
  5. Final Request: Call the API again using the new payment-signature.

Generate Tokens & Create x402 Payment-Signatures

Ensure you have a funded payment channel. Use the DhaliChannelManager to get the base token, then wrap it securely into a final x402 payment payload.

Python (Dhali-py)

import requests
from dhali.dhali_channel_manager import DhaliChannelManager, ChannelNotFound
from dhali.config_utils import get_available_dhali_currencies
from dhali import wrap_as_x402_payment_payload

# 1. Provide Context for Wallet Config (Assume instantiated `manager` instance mapping to correct EVM/XRPL protocol)
# manager = DhaliChannelManager.xrpl(wallet, rpc_client, currency)

# 2. Call the server and catch 402
response = requests.get("http://127.0.0.1:8001/data")
payment_requirement = response.headers.get("payment-required")

if response.status_code == 402 and payment_requirement:
    # 3. Create the payment claim
    try:
        claim = manager.get_auth_token()
    except ChannelNotFound:
        manager.deposit(1000000)
        claim = manager.get_auth_token()
    
    # 4. Wrap as x402 payment signature
    x402_signature = wrap_as_x402_payment_payload(claim, payment_requirement)
    
    # 5. Send Request with Signature
    paid_response = requests.get(
        "http://127.0.0.1:8001/data", 
        headers={"Payment-Signature": x402_signature}
    )
    print(paid_response.json())

JavaScript (Dhali-js)

const { wrapAsX402PaymentPayload } = require('dhali-js');
// Provide Context for Wallet Config (Assume instantiated `manager` instance)
// const manager = DhaliChannelManager.xrpl(wallet, client, currency);

async function callPaidAPI() {
    // 1. Call server
    let response = await fetch("http://127.0.0.1:8001/data");
    const paymentRequirement = response.headers.get("payment-required");

    if (response.status === 402 && paymentRequirement) {
        // 2. Create the payment claim
        let claim;
        try {
            claim = await manager.getAuthToken();
        } catch (error) {
            if (error.name === "ChannelNotFound") {
                await manager.deposit(1000000);
                claim = await manager.getAuthToken();
            } else throw error;
        }

        // 3. Wrap as x402 payment signature
        const x402Signature = wrapAsX402PaymentPayload(claim, paymentRequirement);

        // 4. Send Request with Signature
        response = await fetch("http://127.0.0.1:8001/data", {
            headers: { "Payment-Signature": x402Signature }
        });
        const data = await response.json();
        console.log(data);
    }
}
callPaidAPI();

[!TIP] Debugging failed requests: If you receive another 402, decode the base64 payment-required header to inspect the structure and error info (e.g. echo "<base64>" | base64 -d | jq).

Files

1 total
Select a file
Select a file to preview.

Comments

Loading comments…