hypnex-forge
v0.2.2
Published
TypeScript 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.
Maintainers
Readme
hypnex-forge (TypeScript)
TypeScript 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).
npm install hypnex-forge
# or pnpm add hypnex-forgeAffiliation & 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 at0x22B5C0075372E743042b2d62b3D254425Eb957D8inside the same tx. The SDK auto-approves the MOR allowance on first use.pricePerCallWeiis 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
import { Forge } from "hypnex-forge";
const f = await Forge.fromFallbacks({ chain: "arbitrum" });
console.log(await f.totalTools());
console.log(await f.getListingFeeWei()); // 10n**18n = 1 MOR
console.log(await f.listTools(0n, 100n));Register a tool
import { Forge } from "hypnex-forge";
const f = Forge.withPrivateKey(
process.env.PRIVATE_KEY as `0x${string}`,
{ rpcUrl: process.env.ETH_RPC_URL, chain: "arbitrum" },
);
const txHash = await f.register({
namespace: "myorg",
name: "websearch",
mcpURI: "https://mcp.example.com/v1",
categories: ["search", "data"],
pricePerCallWei: 10n ** 15n, // 0.001 MOR per call
});Quickstart — Phase 3 (escrow + per-call settlement)
Three actors: the agent, the tool owner, and the Hypnex relayer (which batches receipts and submits settle() on a 4-hourly cron).
1. Tool owner: register a signer key
import { Escrow, toolId } from "hypnex-forge";
const esc = Escrow.withPrivateKey(process.env.TOOL_OWNER_PK as `0x${string}`, { chain: "arbitrum" });
const tid = toolId("myorg", "websearch");
await esc.setSigner(tid, "0xYourSessionKeyOrEoa");2. Agent: pre-fund per-tool escrow
import { Escrow, toolId } from "hypnex-forge";
const esc = Escrow.withPrivateKey(process.env.AGENT_PK as `0x${string}`, { chain: "arbitrum" });
const tid = toolId("myorg", "websearch");
await esc.deposit({ toolId: tid, amount: 10n ** 19n }); // 10 MOR runway
console.log("balance:", await 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:
const esc = Escrow.withPrivateKey(process.env.TOOL_OWNER_PK as `0x${string}`, { chain: "arbitrum" });
await esc.callWithReceipt({
toolId: tid,
agent: "0xAgentAddress",
callCount: 100n, // cumulative for this period
periodId: 42n, // strictly increasing per (toolId, agent)
});4. Tool owner: withdraw accrued revenue
console.log("accrued:", await esc.toolRevenue(tid), "wei");
await esc.withdrawTool(tid, "0xYourColdWallet");5. Agent: 24h-delayed self-custody exit
await esc.agentRequestWithdraw(tid); // opens a 24h window
// ... 24 hours later ...
await esc.agentExecuteWithdraw(tid);The relayer has the full 24h to flush pending settlements before the exit becomes executable.
Public API
Forge (Phase 1 — listings)
new Forge({ publicClient?, walletClient?, rpcUrl?, chain?, address? })
// Static factories
Forge.fromFallbacks(opts?)
Forge.withPrivateKey(pk, opts?)
Forge.fromEnv(opts?)
// Read methods
.totalTools() -> bigint
.listTools(offset?, limit?) -> bytes32[]
.toolsOf(owner) -> bytes32[]
.toolsInCategory(label_or_bytes32) -> bytes32[]
.getTool(toolId) -> Tool
.isRegistered(toolId) -> boolean
.toolIdOf(namespace, name) -> bytes32
.getListingFeeWei() -> bigint
.getClaimAdmin() -> Address
.getMorBalance(address?) -> bigint
.getMorAllowance(owner?) -> bigint
// Write methods (require walletClient)
.register({ namespace, name, mcpURI, categories, pricePerCallWei? })
.updateTool({ toolId, mcpURI, pricePerCallWei })
.setCategories(toolId, categories)
.deactivate(toolId)
.reactivate(toolId)
.transferOwnership(toolId, newOwner)Escrow (Phase 3 — per-call settlement)
new Escrow({ publicClient?, walletClient?, rpcUrl?, chain?, address?, relayerUrl? })
// Static factories
Escrow.withPrivateKey(pk, opts?)
Escrow.fromEnv(opts?)
// Read methods
.balance(toolId, agent?) -> bigint
.toolRevenue(toolId) -> bigint
.treasuryRevenue() -> bigint
.signerOf(toolId) -> Address
.lastPeriodId(toolId, agent) -> bigint
.withdrawUnlockAt(toolId, agent) -> bigint
.protocolFeeBps() -> bigint
.relayerAddress() -> Address
.claimAdmin() -> Address
.quoteSettle(toolId, callCount) -> { totalCost, toolPayout, protocolFee }
// Agent-side write
.deposit({ toolId, amount, autoApprove? })
.agentRequestWithdraw(toolId)
.agentExecuteWithdraw(toolId, to?)
// Tool-owner-side write
.setSigner(toolId, newSigner)
.withdrawTool(toolId, to)
.signReceipt({ toolId, agent, callCount, periodId }) -> Hex (sig)
.postReceipt({ ..., signature, relayerUrl?, timeoutMs? }) -> unknown
.callWithReceipt({ toolId, agent, callCount, periodId, ... }) -> unknown
// Relayer / admin write
.settle({ toolId, agent, callCount, periodId, signature })
.withdrawTreasury(to)
.setRelayer(newRelayer)
.setProtocolFeeBps(newBps)Plus a pure helper exported from the package root:
receiptStructHash({ chainId, escrow, toolId, agent, callCount, periodId }) -> HexThe 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 - Base mainnet:
0xCC258a7BBF361fd824e87D4b3C0D394De6Fd454F
SDK 0.2.1+ resolves these automatically when you pass
chain: "arbitrum"orchain: "base". The Cloudflare Worker relayer atrelayer.hypnex.xyzis the last operational piece.- Arbitrum One:
License
MIT (Copyright (c) 2026 Hypnex Labs).
