Skip to main content

Token Registry

The token registry service (ghost-token-registry, port 3009) tracks deployed GhostERC20 tokens on the Specter chain and provides token metadata to the webapp. It serves as the canonical directory of all privacy-wrapped tokens available in the Ghost Protocol ecosystem.

Purpose

When a new GhostERC20 token is deployed via the GhostERC20Factory, the on-chain contract records the token's address, name, symbol, and decimals. However, the on-chain data does not include rich metadata such as token icons, display categories, or ordering preferences. The token registry supplements on-chain data with this additional metadata, providing a complete picture for the webapp's token selection UI.

Data Model

Each token entry in the registry contains:

FieldSourceDescription
addressOn-chainThe GhostERC20 contract address on Specter
nameOn-chainToken name (e.g., "Ghost Wrapped USDC")
symbolOn-chainToken symbol (e.g., "gUSDC")
decimalsOn-chainToken decimal places (typically 18)
tokenIdDerivedThe Poseidon2-derived token identifier used in commitments
iconAdmin-uploadedURL or base64-encoded token icon image
categoryAdmin-managedClassification (e.g., "stablecoin", "governance", "native")
enabledAdmin-managedWhether the token is visible in the webapp
sortOrderAdmin-managedDisplay ordering in the token list
underlyingChainAdmin-managedThe source chain of the underlying asset (e.g., "Base", "Ethereum")

API

GET /tokens

Returns the full list of registered tokens.

Response:

{
"tokens": [
{
"address": "0x...",
"name": "Ghost Wrapped USDC",
"symbol": "gUSDC",
"decimals": 18,
"tokenId": "0x...",
"icon": "https://relayer.specterchain.com/icons/gusdc.png",
"category": "stablecoin",
"enabled": true,
"sortOrder": 1,
"underlyingChain": "Base"
}
]
}

GET /tokens/:address

Returns metadata for a single token by its contract address.

Response:

{
"address": "0x...",
"name": "Ghost Wrapped USDC",
"symbol": "gUSDC",
"decimals": 18,
"tokenId": "0x...",
"icon": "https://relayer.specterchain.com/icons/gusdc.png",
"category": "stablecoin",
"enabled": true,
"sortOrder": 1,
"underlyingChain": "Base"
}

POST /tokens (admin)

Adds or updates a token entry. Requires admin authentication.

Request:

{
"address": "0x...",
"icon": "<base64-encoded image or URL>",
"category": "stablecoin",
"enabled": true,
"sortOrder": 1,
"underlyingChain": "Base"
}

The service fetches name, symbol, and decimals directly from the on-chain contract, so the admin only needs to provide supplementary metadata.

POST /tokens/:address/icon (admin)

Uploads a token icon image. Accepts multipart/form-data with a single image file.

Response:

{
"iconUrl": "https://relayer.specterchain.com/icons/gusdc.png"
}

Icons are stored on the local filesystem and served statically by Caddy.

GET /health

{
"status": "healthy",
"tokenCount": 12,
"uptime": 864000
}

Admin Authentication

Admin endpoints are protected by an API key passed in the Authorization header:

Authorization: Bearer <ADMIN_API_KEY>

The admin API key is stored as an environment variable. Only the Specter team uses admin endpoints — the webapp only calls the public GET endpoints.

Token ID Derivation

The tokenId field is the Poseidon2-derived identifier used within the Ghost Protocol's ZK circuits to identify which token a commitment is associated with. The derivation follows this pattern:

tokenId = Poseidon2(tokenAddress, chainId) mod BN254_FIELD

The token registry computes this value when a token is added and includes it in API responses so that clients do not need to perform the Poseidon computation themselves.

Data Persistence

Token metadata is persisted to a JSON file on disk. The file is read at startup and written after any admin modification. The registry does not use a database — the token count is small enough (typically under 50 tokens) that a flat file is sufficient.

Configuration

ParameterDefaultDescription
PORT3009HTTP server port
RPC_URLSpecter chain RPC for on-chain token data
ADMIN_API_KEYAPI key for admin endpoints
ICONS_DIR./iconsDirectory for uploaded token icons
DATA_FILE./tokens.jsonPath to the persistent token data file