Tokens & Compliance
Who it's for: Issuers deploying a new tokenised asset and compliance officers who need to control which countries and investor types can hold it. Why it matters: Every RWA token comes with built-in compliance rules that automatically block ineligible investors, so issuers stay within regulatory boundaries without manual oversight.
POST /rwa/create — Deploy RWA Token
Auth: x-admin-secret header required.
{
"ownerAddress": "0xabc...",
"name": "Accra Commercial Property",
"symbol": "ACP",
"decimals": 18,
"assetType": 0,
"assetId": "PROP-GH-001",
"jurisdiction": "GH",
"priceSource": {
"baseUrl": "https://api.pricedata.com",
"httpMethod": "GET",
"pathTemplate": "/property/{assetId}/price",
"priceRegex": "\"price\":(\\d+\\.?\\d*)",
"priceDecimals": 8,
"credentialsKey": "PRICE_API_KEY"
}
}The service automatically:
- Checks if
ownerAddresshas an SSI identity — creates one if not - Deploys the RWA Diamond via
GenericRWAFactory.createRWA() - Wires compliance modules based on
assetType - Grants
RouterHookandP2POfferBookAGENT_ROLE - Stores
priceSourcecredentials encrypted in D1
Response: { "id": "uuid", "status": "pending" } (202)
POST /rwa/:address/mint — Mint to Investor
{
"investorAddress": "0xdef...",
"amount": "1000000000000000000"
}amount in token base units (typically 18 decimals for RWA).
POST /rwa/:address/burn
{ "from": "0xdef...", "amount": "500000000000000000" }POST /rwa/:address/freeze — Freeze Investor
{ "investorAddress": "0xdef...", "freeze": true }POST /rwa/:address/forced-transfer
Compliance-driven transfer between holders.
{ "from": "0xdef...", "to": "0xghi...", "amount": "100000000000000000" }GET /rwa/list — All Active RWAs
{
"tokens": [
{
"address": "0x...",
"name": "Accra Commercial Property",
"symbol": "ACP",
"assetType": 0,
"jurisdiction": "GH",
"totalSupply": "100000000000000000000"
}
]
}GET /rwa/:address — Full Token State
{
"address": "0x...",
"name": "Accra Commercial Property",
"symbol": "ACP",
"totalSupply": "100000000000000000000",
"paused": false,
"complianceAddress": "0x...",
"identityRegistry": "0xC44357...",
"onchainID": "0x...",
"assetConfig": { "assetType": 0, "jurisdiction": "GH" },
"db": { "status": "active", "assetId": "PROP-GH-001" }
}Compliance Modules
POST /rwa/compliance/:address/add-country-restrict
{ "allowedCountries": ["GH", "NG", "KE"] }POST /rwa/compliance/:address/add-max-balance
{ "maxBalance": "10000000000000000000" }AI Compliance Chat
core-rwa embeds an AI assistant for managing compliance configuration conversationally. It uses Server-Sent Events (SSE) streaming.
POST /rwa/compliance/chat/start
Start a new compliance chat session for a Diamond.
Request{ "diamondAddress": "0xrwa..." }{
"sessionId": "chat-uuid",
"greeting": "Hi! I can see ACP has CountryRestrict and MaxBalance modules active...",
"currentModules": ["CountryRestrictModule", "MaxBalanceModule"]
}POST /rwa/compliance/chat/message (SSE)
Send a message and receive a streamed response.
Request{ "sessionId": "chat-uuid", "message": "Add Nigeria to the allowed countries" }Response — Content-Type: text/event-stream
data: {"type": "token", "content": "I'll add Nigeria"}
data: {"type": "token", "content": " to the CountryRestrictModule."}
data: {"type": "ready", "jobId": "job-uuid", "config": { ... }}
data: {"type": "done"}The AI proposes a change. When type: "ready" fires, the caller gets a jobId with the proposed config.
POST /rwa/compliance/apply
Execute the AI-proposed compliance change.
{ "jobId": "job-uuid" }GET /rwa/compliance/job/:jobId
Poll status of a pending compliance change.
{ "jobId": "job-uuid", "status": "pending", "config": { ... } }