nory-x402 / app.py
MBMatt's picture
Upload folder using huggingface_hub
fabe31b verified
Raw
History Blame Contribute Delete
8.16 kB
"""
Nory x402 - Payment Infrastructure for AI Agents
Interactive demo showing how AI agents can pay for APIs using the x402 protocol.
"""
import gradio as gr
import requests
import json
# Nory API base URL
NORY_BASE = "https://noryx402.com"
def get_payment_requirements(endpoint: str, amount: str):
"""Get x402 payment requirements for an endpoint"""
try:
response = requests.get(
f"{NORY_BASE}/api/x402/requirements",
params={"resource": endpoint, "amount": amount}
)
if response.status_code == 200:
return json.dumps(response.json(), indent=2)
return f"Error: {response.status_code} - {response.text}"
except Exception as e:
return f"Error: {str(e)}"
def test_paid_api(api_choice: str, param_value: str):
"""Test a paid API (returns 402 without payment)"""
endpoints = {
"Crypto Prices": f"/api/paid/live-crypto?symbols={param_value or 'BTC,ETH,SOL'}",
"Weather": f"/api/paid/weather?city={param_value or 'London'}",
"QR Code": f"/api/paid/qr-code?data={param_value or 'https://noryx402.com'}&format=json",
"Web Summary": f"/api/paid/web-summary?url={param_value or 'https://example.com'}",
"Translate": f"/api/paid/translate?text={param_value or 'Hello world'}&to=es",
"Mock Data": f"/api/paid/mock-data?type=users&count={param_value or '3'}"
}
endpoint = endpoints.get(api_choice, endpoints["Crypto Prices"])
try:
response = requests.get(f"{NORY_BASE}{endpoint}")
if response.status_code == 402:
# Parse the x402 payment requirements
requirements = response.json()
return f"""## 402 Payment Required
The API returned HTTP 402 - payment is required to access this resource.
### Payment Requirements:
```json
{json.dumps(requirements, indent=2)}
```
### How an AI Agent Handles This:
1. **Parse requirements** - Extract amount, wallet address, and network
2. **Create payment** - Sign a USDC transfer transaction
3. **Retry request** - Include `X-PAYMENT` header with signed transaction
4. **Get data** - Server verifies payment, returns data
### With nory-x402-payer SDK:
```javascript
import {{ NoryPayer }} from 'nory-x402-payer';
const payer = new NoryPayer({{ privateKey: 'your-key' }});
const data = await payer.fetch('{NORY_BASE}{endpoint}');
// Payment handled automatically!
```
"""
elif response.status_code == 200:
return f"""## Success (200 OK)
```json
{json.dumps(response.json(), indent=2)}
```
"""
else:
return f"Error: {response.status_code}\n{response.text}"
except Exception as e:
return f"Error: {str(e)}"
def get_health():
"""Check Nory service health"""
try:
response = requests.get(f"{NORY_BASE}/api/x402/health")
return json.dumps(response.json(), indent=2)
except Exception as e:
return f"Error: {str(e)}"
def get_api_directory():
"""Get list of all paid APIs"""
try:
response = requests.get(f"{NORY_BASE}/api/paid")
if response.status_code == 200:
return json.dumps(response.json(), indent=2)
return f"Error: {response.status_code}"
except Exception as e:
return f"Error: {str(e)}"
# Create Gradio interface
with gr.Blocks(
title="Nory x402 - AI Agent Payments",
theme=gr.themes.Soft(primary_hue="emerald"),
css="""
.gradio-container { max-width: 1200px !important; }
.gr-button { min-height: 45px; }
"""
) as demo:
gr.Markdown("""
# Nory x402 - Payment Infrastructure for AI Agents
**Let AI agents pay for APIs autonomously using the x402 protocol (HTTP 402).**
- Sub-400ms settlement on Solana
- USDC stablecoin payments
- Works with any AI framework (CrewAI, AutoGPT, LangChain, etc.)
[Website](https://noryx402.com) | [Docs](https://noryx402.com/docs) | [npm](https://www.npmjs.com/package/nory-x402-payer)
""")
with gr.Tabs():
with gr.TabItem("Test Paid APIs"):
gr.Markdown("""
### Try a Paid API
Select an API and see the x402 payment flow in action. Without payment, you'll get a 402 response with payment requirements.
""")
with gr.Row():
api_dropdown = gr.Dropdown(
choices=["Crypto Prices", "Weather", "QR Code", "Web Summary", "Translate", "Mock Data"],
value="Crypto Prices",
label="Select API"
)
param_input = gr.Textbox(
label="Parameter (optional)",
placeholder="BTC,ETH,SOL | London | URL | etc."
)
test_btn = gr.Button("Test API (Get 402 Response)", variant="primary")
api_output = gr.Markdown(label="Response")
test_btn.click(
fn=test_paid_api,
inputs=[api_dropdown, param_input],
outputs=api_output
)
with gr.TabItem("Payment Requirements"):
gr.Markdown("""
### Get Payment Requirements
See exactly what payment is needed for any x402-protected resource.
""")
with gr.Row():
endpoint_input = gr.Textbox(
value="/api/paid/live-crypto",
label="Endpoint"
)
amount_input = gr.Textbox(
value="0.001",
label="Amount (USDC)"
)
req_btn = gr.Button("Get Requirements", variant="primary")
req_output = gr.Code(language="json", label="Payment Requirements")
req_btn.click(
fn=get_payment_requirements,
inputs=[endpoint_input, amount_input],
outputs=req_output
)
with gr.TabItem("API Directory"):
gr.Markdown("""
### Available Paid APIs
All x402-enabled endpoints you can pay for and access.
""")
dir_btn = gr.Button("Load API Directory", variant="primary")
dir_output = gr.Code(language="json", label="Paid APIs")
dir_btn.click(fn=get_api_directory, outputs=dir_output)
with gr.TabItem("Health Check"):
gr.Markdown("""
### Service Health
Check Nory's service status and supported networks.
""")
health_btn = gr.Button("Check Health", variant="primary")
health_output = gr.Code(language="json", label="Health Status")
health_btn.click(fn=get_health, outputs=health_output)
with gr.TabItem("Integration Code"):
gr.Markdown("""
### Integration Examples
#### For AI Agents (Payer SDK)
```javascript
import { NoryPayer } from 'nory-x402-payer';
const payer = new NoryPayer({
privateKey: process.env.SOLANA_PRIVATE_KEY,
network: 'solana-mainnet'
});
// Automatically handles 402 responses with payment
const { data, payment } = await payer.fetch('https://api.example.com/premium');
console.log('Data:', data);
console.log('Paid:', payment?.amount, 'USDC');
```
#### For API Providers (Middleware)
```javascript
import { x402Middleware } from 'nory-x402-middleware';
app.use('/api/premium', x402Middleware({
amount: '0.01', // $0.01 USDC
wallet: 'your-wallet',
network: 'solana-mainnet'
}));
```
#### MCP Server (for Claude)
```bash
npm install nory-mcp-server
```
Add to Claude Desktop config:
```json
{
"mcpServers": {
"nory": {
"command": "npx",
"args": ["nory-mcp-server"],
"env": {
"NORY_WALLET_KEY": "your-private-key"
}
}
}
}
```
""")
gr.Markdown("""
---
### Resources
- **npm packages**: [nory-x402-payer](https://npmjs.com/package/nory-x402-payer) | [nory-x402-middleware](https://npmjs.com/package/nory-x402-middleware) | [nory-mcp-server](https://npmjs.com/package/nory-mcp-server)
- **Documentation**: [noryx402.com/docs](https://noryx402.com/docs)
- **OpenAPI Spec**: [noryx402.com/openapi.yaml](https://noryx402.com/openapi.yaml)
- **x402 Protocol**: [github.com/coinbase/x402](https://github.com/coinbase/x402)
""")
if __name__ == "__main__":
demo.launch()