SDKs
Senticore maintains SDKs for TypeScript, Python, and Rust. The TypeScript SDK is published on npm; Python and Rust remain repository previews until their public registry releases are completed. Endpoint contracts can still change before public mainnet.
Live private-beta API base URL: https://api.sentico-labs.xyz.
The TypeScript SDK is public on npm as @sentico-labs/sdk.
Packages
| Language | Package name | Current source version | Registry status | Repo path |
|---|---|---|---|---|
| TypeScript | @sentico-labs/sdk | 0.1.4 | Public npm package | sdks/typescript |
| Python | senticore-sdk | 0.1.0rc1 | Repository preview | sdks/python |
| Rust | senticore-sdk | 0.1.0-rc.1 | Repository preview | sdks/rust |
Live Beta Configuration
export SENTICORE_PUBLIC_HTTP_URL="https://api.sentico-labs.xyz"
export SENTICORE_TRADING_HTTP_URL="https://api.sentico-labs.xyz"
export SENTICORE_PUBLIC_WS_URL="wss://api.sentico-labs.xyz/api/v1/ws/public"
export SENTICORE_PRIVATE_WS_URL="wss://api.sentico-labs.xyz/api/v1/ws/private/{account}"
export SENTICORE_ORDER_ENTRY_HTTP_URL="https://api.sentico-labs.xyz"
export SENTICORE_ORDER_ENTRY_BINARY_PATH="/api/order-entry/binary"
export SENTICORE_ORDER_ENTRY_API_KEY="..." # optional provisioned lane key
export SENTICORE_BEARER_TOKEN="..."
export SENTICORE_BSL_TCP_HOST="bsl.sentico-labs.xyz"
export SENTICORE_BSL_TCP_PORT="9001"
export SENTICORE_BSL_TCP_TLS_SNI="bsl.sentico-labs.xyz"
export SENTICORE_FIX_HOST="fix.sentico-labs.xyz"
export SENTICORE_FIX_PORT="9878"
export SENTICORE_FIX_TLS_SNI="fix.sentico-labs.xyz"
/api/order-entry/binary is the tested private-beta order-entry alias. The
direct compatibility route is /api/v1/mm/orders/batch.bin. The canonical BSL
route is /api/v1/bsl/orders/compact; use institutional_agent HMAC auth or a
provisioned lane key from the connectivity bundle.
TypeScript
npm install @sentico-labs/sdk
import { SenticoreClient } from "@sentico-labs/sdk";
const client = new SenticoreClient({
publicHttpBaseUrl: "https://api.sentico-labs.xyz",
tradingHttpBaseUrl: "https://api.sentico-labs.xyz",
publicWsUrl: "wss://api.sentico-labs.xyz/api/v1/ws/public",
privateWsUrl: "wss://api.sentico-labs.xyz/api/v1/ws/private/{account}",
orderEntryHttpBaseUrl: "https://api.sentico-labs.xyz",
orderEntryBinaryPath: "/api/order-entry/binary",
orderEntryApiKey: process.env.SENTICORE_ORDER_ENTRY_API_KEY,
bearerToken: process.env.SENTICORE_BEARER_TOKEN,
machineAuth: process.env.SENTICORE_API_KEY_ID
? {
apiKeyId: process.env.SENTICORE_API_KEY_ID,
apiSecret: process.env.SENTICORE_API_SECRET!,
apiPassphrase: process.env.SENTICORE_API_PASSPHRASE!
}
: undefined
});
const markets = await client.public.listMarkets();
const book = await client.public.getMarketOrderbook(1, { book: "YES", depth: 20 });
console.log(markets.data, book.requestId);
Create the client once per process or strategy shard and reuse it. The default
Node fetch keeps an internal connection pool; custom fetch implementations
should use a persistent agent or dispatcher. A quote loop must not build a new
SDK client or HTTP transport per order.
Capabilities
| Namespace | Use |
|---|---|
client.public | Anonymous market data reads. |
client.trading | Private reads and signed/delegated trading writes. |
client.orderEntry | BSL compact HTTP action-batch submission. |
client.mm | Deprecated alias for client.orderEntry. |
client.raw | Escape hatch for endpoints not promoted to stable helpers. |
client.ws | Public and private WebSocket helpers. |
The SDKs also expose BSL Direct TCP and FIX helper functions for institutional onboarding:
| Helper | Use |
|---|---|
encodeBslTcpHandshakeHello | Build the 48-byte Direct TCP HandshakeHello. |
decodeBslTcpHandshakeAck | Decode the 48-byte Direct TCP HandshakeAck. |
encodeBslOrderFromSignedAction | Build executable BSL Direct TCP order messages from a signed action and connectivity-bundle routing context. |
sessionKeyShadow option | Attach optional Phase-3 session-key shadow auth to wallet-signed Direct TCP orders without changing apply behavior. |
createSessionKey | Create a local Ed25519 session key for the BSL Direct TCP hot path. |
sessionDelegationTypedData | Build the EIP-712 one-time delegation for a session key. |
signSessionDelegationEip712 | Sign the EIP-712 session delegation with a local private key for agent/test flows. |
client.orderEntry.registerSessionKey | Register a wallet-authorized BSL session key. |
encodeBslSessionOrder | Build executable BSL Direct TCP messages using AuthSidecarV2 and Ed25519 session-key signing. |
encodeBslTcpCompactActionFrame | Add the 8-byte TCP message header around a 192-byte compact frame. |
client.orderEntry.getActionChainBinding | Fetch the production v2 action-signing domain once at startup. |
buildMachineAuthHeadersV2 | Build SC-* HMAC headers for custom transports. |
deriveFixSenderCompId | Build stable SenderCompID(49) from account, agent id, and scope. |
buildFixLogonFields | Build FIX 4.4 Logon fields with 553/554 HMAC credentials. |
encodeFixFrame | Add 8, 9, and 10 framing around ordered FIX fields. |
FixpSession | Build FIXP Negotiate/Establish/Sequence frames and classify inbound frames. |
client.orderEntry.getFixpSbeSchema | Fetch the published SBE XML schema. |
encodeFixpNewOrderSingle | Encode an SBE/SOFH NewOrderSingle for FIXP order entry. |
encodeFixpOrderCancelRequest | Encode FIXP cancel by OrderID or OrigClOrdID. |
encodeFixpOrderCancelReplaceRequest | Encode FIXP atomic cancel/replace. |
encodeFixpOrderMassCancelRequest | Encode FIXP account/market/side mass-cancel. |
encodeFixpOrderStatusRequest | Encode FIXP read-only order status requests. |
encodeFixpRetransmitRequest | Request replay for a missed FIXP server sequence range after gap or reconnect. |
decodeFixpFrame | Decode SOFH-framed FIXP/SBE control and execution-report messages. |
BSL Direct TCP
Read /api/v1/bsl/connectivity and use bslTcp. The native path is raw
TCP/TLS, not HTTPS:
cd sdks/typescript
npm ci
npm run build
SENTICORE_BSL_TCP_HOST=bsl.sentico-labs.xyz \
SENTICORE_BSL_TCP_PORT=9001 \
SENTICORE_BSL_TCP_TLS_SNI=bsl.sentico-labs.xyz \
node dist/examples/bsl-tcp-handshake.js
Use @sentico-labs/sdk@0.1.4 or newer for live order encoding. The supported
Direct TCP production shapes are single place actions and
QuoteReplace/SpotQuoteReplace atomic groups. Standalone Cancel and
AmendOrder are also supported when you pass routingMarket, the market id of
the referenced order. The signed action still only carries order_id; the
routing market is a Direct TCP shard-routing hint and is rejected if it conflicts
with known order state.
For the lowest local signing cost, use BSL session keys instead of wallet ECDSA per order:
Roll out in this order: first keep encodeBslOrderFromSignedAction as the
authoritative path and pass sessionKeyShadow while
BSL_SESSION_KEY_AUTH_SHADOW_ENABLED=true; after shadow logs are clean, switch
the account to encodeBslSessionOrder. Venues can temporarily set
BSL_SESSION_KEY_CANARY_ACCOUNTS during rollout, but general access uses an
empty canary list plus an active registered session key.
BSL session-key cancelOnDisconnect is supported for Direct TCP session keys.
The SDK policy flag enables a session-key scoped sweep: the gateway reports TCP
teardown to the sequencer, and the sequencer cancels only live order ids tracked
for that session key.
import {
bslCompactRoutingFromConnectivityBundle,
createSessionKey,
encodeBslSessionOrder,
sessionDelegationTypedData,
signSessionDelegationEip712,
SESSION_DELEGATION_SCHEME_EIP712_V2
} from "@sentico-labs/sdk";
const bundle = await client.orderEntry.getConnectivityBundle();
const routing = bslCompactRoutingFromConnectivityBundle(bundle.data);
const sessionKey = createSessionKey();
const policy = {
allowedMarkets: [7],
allowedActions: ["spot_place"],
maxOrderQtyLots: 1_000_000,
maxNotionalMicro: 250_000_000,
gatewayId: routing.gatewayId,
cancelOnDisconnect: false
};
const delegation = {
walletAuth,
chainBinding: routing.chainBinding,
accountIdHex: account,
sessionPublicKey: sessionKey.publicKey,
policy,
validFrom: Date.now() - 1000,
expiresAt: Date.now() + 60 * 60_000,
delegationNonce
};
const typedDelegation = sessionDelegationTypedData(delegation);
const delegationSignature =
walletClient
? await walletClient.signTypedData(typedDelegation)
: signSessionDelegationEip712(delegation, ownerPrivateKey);
const registered = await client.orderEntry.registerSessionKey({
...delegation,
algorithm: "ed25519",
delegationScheme: SESSION_DELEGATION_SCHEME_EIP712_V2,
delegationSignature
});
const encoded = encodeBslSessionOrder(payload, {
...routing,
accountIdx: routing.accountIdx!,
sessionId,
gatewaySeq,
sessionPrivateKey: sessionKey.privateKey,
sessionKeyId: sessionKey.sessionKeyId,
sessionSeq,
policyHash: (registered.data as any).policyHash
});
See BSL Session Keys for the exact policy fields, rollout flags, and revocation flow.
BSL Compact HTTP Order Entry
The SDK encodes:
{"version":1,"actions":[...],"idempotencyKey":"client-batch-1"}
and submits it as:
POST /api/order-entry/binary
Content-Type: application/x-senticore-order-entry-batch
X-BSL-Result-Mode: ack
X-Senticore-Response-Mode: detailed
X-Senticore-Order-Entry-Key: <optional provisioned lane key>
The order-entry key authorizes a dedicated lane and rate tier when assigned. It does not replace the signed action inside the batch.
After an ack response, use the SDK reconciliation helpers instead of a
bootstrap polling loop:
const receipts = await client.orderEntry.getActionReceipts(
account,
response.data.seqs,
{ waitMs: 250 }
);
const replay = await client.orderEntry.getAccountExecutions(account, {
fromSeq: response.data.lastSeq ?? response.data.seqs.at(-1)
});
console.log(receipts.data.receipts, replay.data);
FIX Logon Example
After creating an institutional_agent, read
GET /api/v1/bsl/connectivity and use the returned CompIDs. The TypeScript SDK
contains a runnable Logon example:
cd sdks/typescript
npm ci
npm run build
SENTICORE_ACCOUNT=0x... \
SENTICORE_AGENT_ID=agt_... \
SENTICORE_API_KEY_ID=spk_... \
SENTICORE_API_SECRET=... \
SENTICORE_API_PASSPHRASE=... \
node dist/examples/fix-logon.js
For code that only needs CompIDs and a Logon frame:
import {
buildFixLogonFields,
deriveFixSenderCompId,
encodeFixFrame
} from "@sentico-labs/sdk";
const senderCompId = deriveFixSenderCompId(account, agentId, "order_entry");
const frame = encodeFixFrame(buildFixLogonFields({
account,
apiKeyId,
apiSecret,
apiPassphrase,
senderCompId,
targetCompId: "SENTICORE",
targetSubId: "order_entry"
}));
FIXP / SBE
FIXP is the binary-FIX lane on the direct TCP/TLS host. Read
GET /api/v1/fixp/connectivity; the SBE XML is published at
GET /api/v1/fixp/schema and referenced as fixp.wire.schemaUrl.
import {
FixpSession,
FixpSide,
decodeFixpFrame,
encodeFixpNewOrderSingle
} from "@sentico-labs/sdk";
const session = new FixpSession({
apiKeyId,
apiSecret,
apiPassphrase,
account
});
socket.write(Buffer.concat(session.start()));
socket.write(encodeFixpNewOrderSingle({
clOrdId: "mm-1",
account,
marketId: 1,
price: 1_000_000,
orderQty: 1,
side: FixpSide.Bid
}));
const inbound = decodeFixpFrame(frameFromSocket);
For FIXP reconnect/recovery, create the next FixpSession with the same
sessionId and account credentials, complete Negotiate/Establish again, then
call session.encodeRetransmitRequest(fromSeqNo, count) for any missed server
sequence range. The server resumes only same-account retained sessions.
Python
git clone https://github.com/sentico-labs/senticore.git
cd senticore/sdks/python
python -m pip install -e .
from senticore import SenticoreClient, SenticoreConfig
client = SenticoreClient(
SenticoreConfig(
public_http_base_url="https://api.sentico-labs.xyz",
trading_http_base_url="https://api.sentico-labs.xyz",
public_ws_url="wss://api.sentico-labs.xyz/api/v1/ws/public",
private_ws_url="wss://api.sentico-labs.xyz/api/v1/ws/private/{account}",
order_entry_http_base_url="https://api.sentico-labs.xyz",
order_entry_binary_path="/api/order-entry/binary",
order_entry_api_key="...",
)
)
Rust
[dependencies]
senticore-sdk = { path = "sdks/rust" }
use senticore_sdk::{SenticoreClient, SenticoreConfig};
let client = SenticoreClient::new(
SenticoreConfig::new("https://api.sentico-labs.xyz", "https://api.sentico-labs.xyz")
.with_order_entry_api_key("optional-lane-key"),
)?;
Market Maker Verification
Use the repository audit script before handing SDK config to a market maker:
node scripts/e2e/mm-docs-contract-audit.cjs