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.
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
| Field | Meaning |
|---|---|
appId | Stable 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. |
displayName | What a wallet UI shows next to the signature prompt. Also accepted as the signed app: value. |
status | pending → active → suspended. Only active apps identify requests. |
origins | Canonical browser origins (https://trade.example.com). Requests from these origins are attributed to the app and pass CORS. |
embedAllowed | Reserved for the embeddable trade widget. |
feeShareBps / payoutAccount | Reserved for the fee-share program; recorded now, applied when the fee-split engine change ships. |
Three channels, one identity
| Channel | How the app is recognized | Typical user |
|---|---|---|
| Browser | Request Origin ∈ registered origins | Broker frontend where the user's own wallet signs |
| Server | x-sentico-app-key: <keyId>.<secret> header | Broker backend relaying signed actions, scripts, SDKs |
| Signed | app:<appId> line inside every wallet-signed control-plane message | Agent 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):
- Send your intended
appId, display name and browser origins. - The operator registers the app (
pending), issues a server key if you run a backend, and activates it. - 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.