Skip to main content

Institutional Conformance Kit

Use this checklist before giving a bot production credentials. It is designed to catch the integration failures that are expensive in live market making: wrong account id, wrong credential type, nonce replay, stale risk state, mis-derived order ids, and over-trusting fast acknowledgements.

Required gates

GateRequired evidenceCommand or source
SDK build and vectorsTypeScript SDK compiles and action/HMAC/FIXP vectors passcd sdks/typescript && npm ci && npm run verify
Funded bundle manifestJSON bundle has owner wallet, 32-byte accountIdHex, 20-byte engine account, institutional_agent, HMAC credential, funding minimum, known-good quote, and signed batch pathnode scripts/e2e/institutional-conformance-kit.cjs --bundle-file tmp/institutional-beta-bundle.json
Known-good batch generationBundle knownGoodQuote is signed into orderEntry.signedBatchFile with the live action-signing domainnode sdks/typescript/dist/examples/institutional-known-good-batch.js --bundle-file tmp/institutional-beta-bundle.json
External conformance harnessHMAC vector, live BSL connectivity, fresh bootstrap, optional known-good submitnode scripts/e2e/institutional-conformance-kit.cjs
Python bundle preflightPython SDK reproduces HMAC V2, authenticates, reads connectivity, and verifies fresh bootstrap funding without submitting orderscd sdks/python && python examples/institutional_bundle_preflight.py --bundle-file ../../tmp/institutional-beta-bundle.json
Python signed-batch submitPython SDK sends orderEntry.signedBatchFile bytes over /api/order-entry/binary after funding passescd sdks/python && python examples/institutional_bundle_preflight.py --bundle-file ../../tmp/institutional-beta-bundle.json --submit-signed-batch
Rust bundle preflightRust SDK reproduces HMAC V2, authenticates, reads connectivity, and verifies fresh bootstrap funding without submitting orderscd sdks/rust && cargo run --example institutional_bundle_preflight -- --bundle-file ../../tmp/institutional-beta-bundle.json
Rust signed-batch submitRust SDK sends orderEntry.signedBatchFile bytes over /api/order-entry/binary after funding passescd sdks/rust && cargo run --example institutional_bundle_preflight -- --bundle-file ../../tmp/institutional-beta-bundle.json --submit-signed-batch
Internal docs contract auditLive beta metadata, protected-read boundary, BSL submit, and cleanup are checked by Sentico opsnode scripts/e2e/mm-docs-contract-audit.cjs
OpenAPI institutional contractAccount model, bootstrap, BSL submit, direct order-entry, receipts, and per-action results are typedcargo test -p senticore-sequencing-core openapi_contract --tests
HMAC vectorIndependent client reproduces the documented HMAC signaturesdks/typescript/tests/auth.test.ts
Action hash vectorsIndependent signer reproduces canonical JSON, v1/v2 hashes, and derived order idssdks/typescript/tests/signing.test.ts
Nonce replayDuplicate action nonce is rejected and client re-signs with a fresh in-window noncelocal test or beta account
IdempotencySame key plus same body returns/replays safely; same key plus different body conflictslocal test or beta account
Account mappingClient stores accountIdHex and engineAccountHex separatelylive trading-account list
Funding preflightFresh bootstrap shows funded balances.freeUsdcMicro and matching-engine source when presentGET /api/v1/accounts/:engineAccount/bootstrap?fresh=true
QuoteReplaceOne known-good QuoteReplace produces a derived order id and ackPOST /api/order-entry/binary or BSL compact facade
ReconciliationDerived order id is found in orders/drop-copy/fills or terminal stream eventprivate read/stream/FIX drop-copy
Lane-key compatibilityClient uses X-Senticore-Order-Entry-Key; legacy headers tested only for migrationHTTP order-entry tests

External-safe runner

The customer-facing harness is:

node scripts/e2e/institutional-conformance-kit.cjs --offline

Offline mode verifies the documented HMAC vector and writes a redacted report to tmp/institutional-conformance-last.json. It does not load local secrets, does not SSH to Sentico infrastructure, and does not submit orders.

For live credential preflight:

node scripts/e2e/institutional-conformance-kit.cjs \
--bundle-file tmp/institutional-beta-bundle.json

This checks:

  • HMAC signing string and signature vector
  • funded bundle manifest shape
  • authenticated GET /api/v1/bsl/connectivity
  • testedBetaSubmitPath === "/api/order-entry/binary"
  • fresh GET /api/v1/accounts/:engineAccount/bootstrap?fresh=true
  • freeUsdcMicro against expectedFunding.freeUsdcMicroAtLeast from the bundle

Live submit is opt-in because it requires a known-good signed batch:

cd sdks/typescript
npm install
npm run build
SENTICORE_ACTION_PRIVATE_KEY=0x... \
node dist/examples/institutional-known-good-batch.js \
--bundle-file ../../tmp/institutional-beta-bundle.json
cd ../..
SENTICORE_CONFORMANCE_SUBMIT=1 \
node scripts/e2e/institutional-conformance-kit.cjs \
--bundle-file tmp/institutional-beta-bundle.json

The bundle's orderEntry.signedBatchFile must already contain a fully signed action batch. The harness posts the bytes, verifies HTTP 200, ok: true, and fails when actionResults[] contains a reject. Use the SDK examples on Place Your First Institutional BSL Quote to generate the signed batch for a funded beta account.

To turn on live idempotency and nonce-replay gates, use the same signed batch:

SENTICORE_CONFORMANCE_SUBMIT=1 \
SENTICORE_CONFORMANCE_IDEMPOTENCY=1 \
SENTICORE_CONFORMANCE_REPLAY=1 \
SENTICORE_REPLAY_IDEMPOTENCY_KEY=quote-7-yes-bid-0-replay \
node scripts/e2e/institutional-conformance-kit.cjs \
--bundle-file tmp/institutional-beta-bundle.json

Expected:

  • signed-batch-submit returns HTTP 200, top-level ok: true, and no rejected actionResults[].
  • idempotency-replay-same-key submits identical bytes with the same Idempotency-Key; it should replay or return the same accepted response.
  • nonce-replay-different-key submits identical signed bytes with a different Idempotency-Key; it must reject as a nonce replay/conflict. If this accepts, the client or venue is not enforcing signed action nonce replay protection.

The JSON report records the bundle summary, batch SHA-256, redacted credential metadata, request ids, response status, top-level errors, and per-action reject counts.

Run the language-specific preflights against the same funded bundle before handing credentials to a production strategy:

cd sdks/python
python3 -m pip install -e .
python examples/institutional_bundle_preflight.py \
--bundle-file ../../tmp/institutional-beta-bundle.json
cd ../..
cd sdks/rust
cargo run --example institutional_bundle_preflight -- \
--bundle-file ../../tmp/institutional-beta-bundle.json
cd ../..

Both preflights are read-only. They fail when expectedFunding.freeUsdcMicroAtLeast is not met, because an unfunded account would turn a signing test into a risk-layer failure.

After sdks/typescript/dist/examples/institutional-known-good-batch.js writes orderEntry.signedBatchFile, Python and Rust can submit the same bytes:

cd sdks/python
python examples/institutional_bundle_preflight.py \
--bundle-file ../../tmp/institutional-beta-bundle.json \
--submit-signed-batch
cd ../..
cd sdks/rust
cargo run --example institutional_bundle_preflight -- \
--bundle-file ../../tmp/institutional-beta-bundle.json \
--submit-signed-batch
cd ../..

The submit report includes the batch SHA-256, request id, ok, seqs, derivedOrderIds, acceptedActions, ackMode, and rejectCount.

Action signing vectors

The TypeScript SDK pins the same vectors as the backend. If your client cannot match these, do not send live orders.

SpotPlaceOrder

Canonical JSON:

{"account":"0x1111111111111111111111111111111111111111","nonce":4810,"nonce_reservation_id":null,"ts":1765500000000,"action":{"SpotPlaceOrder":{"market":7,"side":"Bid","price":998400,"qty":1000,"stp_mode":null,"time_in_force":"post_only","is_market":false,"reduce_only":false,"expires_at":null}}}
OutputValue
v1 hash0xc8d02209196c492de5b39c90d7efd356548784ddd464603913b59afab911b42f
v2 hash, chain 8453, contract 0xcccccccccccccccccccccccccccccccccccccccc0x26d8533a5150e7a8bf6537824715562eddb55a0c019a0b23635533a1d4e7e084
derived order id0x52401b1d6de155089120a39ccd8ca52e3b5daaf090f090c5a0705b53b914d57e

QuoteReplace

Canonical JSON:

{"account":"0x1111111111111111111111111111111111111111","nonce":4812,"nonce_reservation_id":"res-1","ts":1765500000002,"action":{"SpotQuoteReplace":{"market":7,"legs":[{"cancel_order_id":"0x2222222222222222222222222222222222222222222222222222222222222222","side":"Bid","price":998500,"qty":1189,"stp_mode":null,"time_in_force":"post_only","is_market":false,"reduce_only":false,"expires_at":null}]}}}
OutputValue
v1 hash0x0b635be460cf6d9ae3a9fe11c1b5d5176c942e9b6139f88dac142baa1818584c
derived child order id, leg 00xfeac5884704773dd3150bef258b3f5a139dafaba0bba2190fc9d520b8a505e22

For production signatures, fetch the live v2 chain binding from:

GET /api/v1/bsl/connectivity

Then sign with actionSigning.chainId and actionSigning.verifyingContract.

HMAC vector

Signing string:

SENTICORE-HMAC-V2
sc-key:spk_test
sc-nonce:7
sc-timestamp:123456
method:POST
path:/api/v1/private/account
query:a=1&b=2
body-sha256:08220911bbc1dfd55d93796c4d425a9582f94221975933bb2d98d269ab3c7b95

With secret sps_secret:

0x54ddc2c6f1eef6b75c317de7908c2e5c16a4e38561d75a147085cee9b0e6fb00

Rules:

  • method is uppercase
  • path excludes query string
  • query is split on &, empty parts are dropped, then sorted and rejoined
  • body hash is lowercase SHA-256 hex of the raw request body, or SHA-256 of empty bytes for GET
  • SC-Nonce is decimal and single-use for that credential
  • SC-Timestamp is Unix milliseconds with a 30 second skew tolerance

Nonce replay tests

Run these against a funded beta account with tiny post-only quantities.

TestExpected
Submit action nonce N onceaccepted or valid strategy/risk reject
Submit exact same signed body again with same idempotency keyidempotency replay or same stored response
Submit exact same signed body with different idempotency keynonce_replayed or equivalent nonce conflict
Submit nonce below nonceFloorcode: nonce_below_floor, nonceFloor present
Submit nonce above nonceFloor + nonceWindowcode: nonce_outside_window, client must not blind retry
Submit nonce 0 on a fresh funded accountaccepted when no earlier nonce was used

Retry rule: if the nonce must change, rebuild and re-sign the action payload. Changing only Idempotency-Key cannot fix an action nonce failure.

Idempotency tests

For BSL compact submit:

  1. Build one encoded batch and compute its SHA-256 locally.
  2. Submit with Idempotency-Key: idem-1.
  3. Repeat the exact same bytes with idem-1.
  4. Submit different bytes with idem-1.

Expected:

  • step 2 returns accepted or a deterministic reject
  • step 3 returns the same stored response where idempotency is enabled
  • step 4 returns conflict

The client should persist idempotencyKey, request hash, action nonces, and derived order ids together.

Risk and funding fixture

Every beta bundle should include a known-good order and minimum funding.

{
"engineAccount": "0x2222222222222222222222222222222222222222",
"minimumFreeUsdcMicro": "100000000",
"quote": {
"kind": "QuoteReplace",
"market": 7,
"book": "YES",
"side": "Bid",
"price": 100000,
"qty": 100000,
"timeInForce": "post_only"
}
}

Before submitting, calculate:

requiredUsdcMicro = floor(priceMicro * qtyMicro / 1_000_000)

For price=100000 and qty=100000, required notional is 10000 micro USDC. The bundle's minimumFreeUsdcMicro should exceed this by enough margin for fees, open-order holds, and any account risk config.

QuoteReplace fixture rules

For outcome markets use QuoteReplace; for spot markets use SpotQuoteReplace.

{
"QuoteReplace": {
"market": 7,
"legs": [
{
"cancel_order_id": null,
"book": "YES",
"side": "Bid",
"price": 100000,
"qty": 100000,
"stp_mode": "skip_self",
"time_in_force": "post_only",
"is_market": false,
"reduce_only": false,
"expires_at": null
},
{
"cancel_order_id": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"book": "YES",
"side": "Bid",
"price": 0,
"qty": 0,
"stp_mode": null,
"time_in_force": "post_only",
"is_market": false,
"reduce_only": false,
"expires_at": null
}
]
}
}

The first leg places a deterministic child order. The second leg is cancel-only because qty is 0. Conformance should assert local derived child ids match the response derivedOrderIds[].

Live beta audit

From the repository root:

node scripts/e2e/mm-docs-contract-audit.cjs

For BSL compact facade verification:

MM_DOCS_SUBMIT_ROUTE=/api/v1/bsl/orders/compact \
MM_DOCS_RESULT_MODE=ack \
MM_DOCS_RESPONSE_MODE=detailed \
node scripts/e2e/mm-docs-contract-audit.cjs

The audit should produce a redacted JSON artifact under tmp/ and should never print HMAC secrets or private keys.

Ship/no-ship criteria

Ship the integration only when all are true:

  • Account mapping is explicit: owner wallet, accountIdHex, and engine account are separately stored and logged.
  • HMAC and action-signing vectors pass in the client language.
  • Fresh bootstrap reports a funded account.
  • One QuoteReplace is accepted and reconciled to an order/drop-copy/fill state.
  • Nonce replay and idempotency behavior are tested.
  • Strategy code treats ack as admission, not terminal truth.
  • Per-action rejects in actionResults[] and receipt/drop-copy rejects are handled as real terminal state, not ignored because HTTP was 200.
  • Risk rejects are logged with account, market, book, asset, free, locked, required, nonce, and idempotency key.