Metadata-Version: 2.4
Name: hypnex-forge
Version: 0.2.1
Summary: Python SDK for Forge — the paid tool registry on Morpheus AI (MRC 60). Phase 1 listing rail + Phase 3 pre-paid escrow with relayer-attested per-call settlement on Arbitrum + Base.
Project-URL: Homepage, https://hypnex.xyz
Project-URL: Documentation, https://docs.hypnex.xyz/forge
Project-URL: Repository, https://github.com/hypnex-labs/hypnex
Project-URL: Issues, https://github.com/hypnex-labs/hypnex/issues
Author: Hypnex Labs
License: MIT
License-File: LICENSE
Keywords: agents,forge,hypnex,marketplace,mcp,mor,morpheus,mrc-60,tools,web3
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Requires-Python: >=3.10
Requires-Dist: eth-account>=0.10.0
Requires-Dist: web3<8.0,>=6.15.0
Provides-Extra: dev
Requires-Dist: pytest>=9.0.3; extra == 'dev'
Requires-Dist: ruff>=0.5; extra == 'dev'
Description-Content-Type: text/markdown

# hypnex-forge (Python)

Python SDK for **Forge** — the paid tool registry on Morpheus AI. Implements **MRC 60** Phase 1 (paid listings) and Phase 3 (on-chain per-call settlement via pre-paid escrow).

```bash
pip install hypnex-forge
```

## Affiliation & monetization

This SDK is published by **Hypnex Labs**. Hypnex is not affiliated with the Morpheus AI Foundation.

- `register()` costs **1 MOR** (configurable on-chain by claim-admin), forwarded directly to the Hypnex Labs treasury at `0x22B5C0075372E743042b2d62b3D254425Eb957D8` inside the same tx. The SDK auto-approves the MOR allowance on first use.
- `pricePerCallWei` is what end users pay YOU per call. With Phase 3 escrow, on-chain settlement debits the agent's escrow at this rate, with **90% routed to the tool owner and 10% to the Hypnex treasury** as a protocol fee. The fee is hard-capped at 20% in the contract; admin cannot rug.

## Quickstart — Phase 1 (listings)

### Read-only

```python
from hypnex_forge import Forge

f = Forge(chain="arbitrum")
print(f.total_tools())
print(f.list_tools(0, 100))
print(f.get_listing_fee_wei())  # 10**18 = 1 MOR
```

### Register a tool (with signer)

```python
import os
from hypnex_forge import Forge

f = Forge(
    chain="arbitrum",
    rpc_url=os.environ["ETH_RPC_URL"],
    private_key=os.environ["PRIVATE_KEY"],
)

tx = f.register(
    namespace="myorg",
    name="websearch",
    mcp_uri="https://mcp.example.com/v1",
    categories=["search", "data"],
    price_per_call_wei=int(0.001 * 10**18),
)
print("tool registered:", tx)
```

## Quickstart — Phase 3 (escrow + per-call settlement)

Three actors: the **agent** (who consumes the tool), the **tool owner** (who runs it), and the **Hypnex relayer** (which batches receipts and submits `settle()` on a 4-hourly cron).

### 1. Tool owner: register a signer key

```python
from hypnex_forge import Escrow, tool_id

esc = Escrow(chain="arbitrum", private_key=os.environ["TOOL_OWNER_PK"])
tid = tool_id("myorg", "websearch")

esc.set_signer(tid, "0xYourSessionKeyOrEoa")
```

### 2. Agent: pre-fund per-tool escrow

```python
from hypnex_forge import Escrow, tool_id

esc = Escrow(chain="arbitrum", private_key=os.environ["AGENT_PK"])
tid = tool_id("myorg", "websearch")

# Auto-approves MOR allowance on first call.
esc.deposit(tid, 10 * 10**18)  # 10 MOR runway
print("escrow balance:", esc.balance(tid))
```

### 3. Tool server: sign + post receipts

After every N calls, the tool's signer key signs a receipt and posts it
to `relayer.hypnex.xyz`:

```python
esc = Escrow(chain="arbitrum", private_key=os.environ["TOOL_OWNER_PK"])
esc.call_with_receipt(
    tool_id=tid,
    agent="0xAgentAddress",
    call_count=100,           # cumulative for this period
    period_id=42,             # strictly increasing per (toolId, agent)
)
# The relayer batches and submits settle() on the next cron tick.
```

### 4. Tool owner: withdraw accrued revenue

```python
print("accrued:", esc.tool_revenue(tid) / 1e18, "MOR")
esc.withdraw_tool(tid, "0xYourColdWallet")
```

### 5. Agent: 24h-delayed self-custody exit

If a tool owner misbehaves, agents can pull remaining escrow back:

```python
esc.agent_request_withdraw(tid)        # opens a 24h window
# ... 24 hours later ...
esc.agent_execute_withdraw(tid, "0xAgentAddress")
```

The relayer has the full 24h to flush pending settlements before the
exit becomes executable.

## Public API

### `Forge` (Phase 1 — listings)

```
Forge(address=None, chain="arbitrum", w3=None, rpc_url=None,
      account=None, private_key=None)

# read
.total_tools() -> int
.list_tools(offset=0, limit=100) -> list[bytes32]
.tools_of(owner) -> list[bytes32]
.tools_in_category(label_or_bytes32) -> list[bytes32]
.get_tool(tool_id) -> Tool
.is_registered(tool_id) -> bool
.tool_id_of(namespace, name) -> bytes32
.get_listing_fee_wei() -> int
.get_claim_admin() -> str
.get_mor_balance(address=None) -> int
.get_mor_allowance(owner=None) -> int

# write (signer required)
.register(namespace, name, mcp_uri, categories, price_per_call_wei=0) -> tx
.update_tool(tool_id, mcp_uri, price_per_call_wei) -> tx
.set_categories(tool_id, categories) -> tx
.deactivate(tool_id) -> tx
.reactivate(tool_id) -> tx
.transfer_ownership(tool_id, new_owner) -> tx
```

### `Escrow` (Phase 3 — per-call settlement)

```
Escrow(address=None, chain="arbitrum", w3=None, rpc_url=None,
       account=None, private_key=None, relayer_url=None)

# read
.balance(tool_id, agent=None) -> int
.tool_revenue(tool_id) -> int
.treasury_revenue() -> int
.signer_of(tool_id) -> str
.last_period_id(tool_id, agent) -> int
.withdraw_unlock_at(tool_id, agent) -> int
.protocol_fee_bps() -> int
.relayer_address() -> str
.claim_admin() -> str
.quote_settle(tool_id, call_count) -> (total, tool_payout, protocol_fee)

# agent-side write
.deposit(tool_id, amount, auto_approve=True) -> tx
.agent_request_withdraw(tool_id) -> tx
.agent_execute_withdraw(tool_id, to=None) -> tx

# tool-owner-side write
.set_signer(tool_id, new_signer) -> tx
.withdraw_tool(tool_id, to) -> tx
.sign_receipt(tool_id, agent, call_count, period_id) -> bytes
.post_receipt(tool_id, agent, call_count, period_id, signature, ...) -> dict
.call_with_receipt(tool_id, agent, call_count, period_id, ...) -> dict

# relayer / claim-admin write
.settle(tool_id, agent, call_count, period_id, signature) -> tx
.withdraw_treasury(to) -> tx
.set_relayer(new_relayer) -> tx
.set_protocol_fee_bps(new_bps) -> tx
```

Plus a pure helper:

```
receipt_struct_hash(*, chain_id, escrow_address, tool_id,
                    agent, call_count, period_id) -> bytes
```

The bytes returned match the on-chain Solidity recovery exactly:

```
keccak256(abi.encode(chainid, escrow, toolId, agent, callCount, periodId))
```

wrapped with the EIP-191 `\x19Ethereum Signed Message:\n32` prefix when
signed.

## Environment variables

| Variable | Purpose |
|---|---|
| `HYPNEX_FORGE_CHAIN` | Default chain (`arbitrum` or `base`) |
| `HYPNEX_FORGE_RPC_URL` | Override RPC URL |
| `HYPNEX_FORGE_ADDRESS` | Override `ForgeToolRegistry` address |
| `HYPNEX_FORGE_ESCROW_ADDRESS` | Override `ForgeEscrow` address |
| `HYPNEX_FORGE_RELAYER_URL` | Override relayer endpoint (default `https://relayer.hypnex.xyz`) |
| `PRIVATE_KEY` | Required for write methods |

## Status

- **Phase 1** — paid listings on Arbitrum One + Base mainnet (live since 2026-05-09).
- **Phase 2** — discovery UI at `forge.hypnex.xyz` (live).
- **Phase 3** — pre-paid escrow + per-call settlement (`ForgeEscrow`). Live since 2026-05-09:
  - Arbitrum One: [`0x88E32F332A5140Af16c6273d8131bC84BC089Da5`](https://arbiscan.io/address/0x88E32F332A5140Af16c6273d8131bC84BC089Da5#code)
  - Base mainnet: [`0xCC258a7BBF361fd824e87D4b3C0D394De6Fd454F`](https://basescan.org/address/0xCC258a7BBF361fd824e87D4b3C0D394De6Fd454F#code)

  SDK 0.2.1+ resolves these automatically when you pass `chain="arbitrum"` or `chain="base"`. The Cloudflare Worker relayer at `relayer.hypnex.xyz` is the last operational piece; until it's live, receipts can be submitted directly to `Escrow.settle()` by the configured relayer EOA.

## License

MIT (Copyright (c) 2026 Hypnex Labs). The MIT-licensed source includes hard-coded fee routers to the Hypnex Labs treasury for both the listing fee and the Phase-3 protocol fee — see "Affiliation & monetization" above.
