Skip to main content

Apps & Brokers

Senticore is the venue: matching, settlement, custody proofs. An app is any client surface that brings users to that venue — the first-party frontends as well as a third-party broker with its own UI. Every app has the same identity model and the same rules; the first-party frontends are simply the first registered apps.

Non-custodial by construction

A broker never holds user funds. Users deposit into the vault under their own wallet, every balance is a leaf in the committed exit tree, and forced withdrawals work without the broker. A broker earns on the flow it brings, not on custody.

The app record

FieldMeaning
appIdStable identity, lowercase [a-z0-9_-], max 32 bytes. This is the string users sign as app:<appId> and the value carried in attributed order payloads. Choose it once.
displayNameWhat a wallet UI shows next to the signature prompt. Also accepted as the signed app: value.
statuspendingactivesuspended. Only active apps identify requests.
originsCanonical browser origins (https://trade.example.com). Requests from these origins are attributed to the app and pass CORS.
embedAllowedReserved for the embeddable trade widget.
feeShareBps / payoutAccountReserved for the fee-share program; recorded now, applied when the fee-split engine change ships.

Three channels, one identity

ChannelHow the app is recognizedTypical user
BrowserRequest Origin ∈ registered originsBroker frontend where the user's own wallet signs
Serverx-sentico-app-key: <keyId>.<secret> headerBroker backend relaying signed actions, scripts, SDKs
Signedapp:<appId> line inside every wallet-signed control-plane messageAgent authorization, session keys, account management, launchpad submit

The channels must agree. A request whose origin belongs to app A but whose key belongs to app B is rejected (APP_CHANNEL_MISMATCH). A message a user signed for app A cannot be relayed through app B. The signed domain: must be one of the app's registered origin hosts (or a parent domain of one).

Attributed orders

Order payloads accept an optional appId:

{
"account": "0x…",
"nonce": 17,
"appId": "brokerx",
"ts": 1780000000000,
"action": { "SpotPlaceOrder": { "marketId": 7, "side": "Bid", "price": 998400, "qty": 1000 } }
}

appId is part of the signed canonical bytes: the user attests which app they traded through, and neither the relaying app nor the venue can rewrite it. It must name an active app and, when the request itself is identified, the same app. Payloads without appId are accepted and simply unattributed — every existing signing hash, order id and replay record is unchanged.

Agents created through an app

Agents (browser sessions, API agents, session keys) remember the appId they were authorized through. An operator can revoke every agent of an app at once — for example when a broker is suspended.

Onboarding

Registration is operator-managed today (self-service registration is planned):

  1. Send your intended appId, display name and browser origins.
  2. The operator registers the app (pending), issues a server key if you run a backend, and activates it.
  3. From that moment your origins pass CORS and your users sign app:<appId> — no venue restart involved.

Server keys are shown once at creation. Rotate by creating a new key and revoking the old one.

Migration note for first-party clients

Clients deployed before the registry signed the fixed name SentiPredict. That name stays accepted as an alias during the migration window (APP_REGISTRY_LEGACY_ALIAS=true) and is attributed to the app the request arrived through. New integrations must sign their own appId.