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
| Gate | Required evidence | Command or source |
|---|---|---|
| SDK build and vectors | TypeScript SDK compiles and action/HMAC/FIXP vectors pass | cd sdks/typescript && npm ci && npm run verify |
| Funded bundle manifest | JSON bundle has owner wallet, 32-byte accountIdHex, 20-byte engine account, institutional_agent, HMAC credential, funding minimum, known-good quote, and signed batch path | node scripts/e2e/institutional-conformance-kit.cjs --bundle-file tmp/institutional-beta-bundle.json |
| Known-good batch generation | Bundle knownGoodQuote is signed into orderEntry.signedBatchFile with the live action-signing domain | node sdks/typescript/dist/examples/institutional-known-good-batch.js --bundle-file tmp/institutional-beta-bundle.json |
| External conformance harness | HMAC vector, live BSL connectivity, fresh bootstrap, optional known-good submit | node scripts/e2e/institutional-conformance-kit.cjs |
| Python bundle preflight | Python SDK reproduces HMAC V2, authenticates, reads connectivity, and verifies fresh bootstrap funding without submitting orders | cd sdks/python && python examples/institutional_bundle_preflight.py --bundle-file ../../tmp/institutional-beta-bundle.json |
| Python signed-batch submit | Python SDK sends orderEntry.signedBatchFile bytes over /api/order-entry/binary after funding passes | cd sdks/python && python examples/institutional_bundle_preflight.py --bundle-file ../../tmp/institutional-beta-bundle.json --submit-signed-batch |
| Rust bundle preflight | Rust SDK reproduces HMAC V2, authenticates, reads connectivity, and verifies fresh bootstrap funding without submitting orders | cd sdks/rust && cargo run --example institutional_bundle_preflight -- --bundle-file ../../tmp/institutional-beta-bundle.json |
| Rust signed-batch submit | Rust SDK sends orderEntry.signedBatchFile bytes over /api/order-entry/binary after funding passes | cd sdks/rust && cargo run --example institutional_bundle_preflight -- --bundle-file ../../tmp/institutional-beta-bundle.json --submit-signed-batch |
| Internal docs contract audit | Live beta metadata, protected-read boundary, BSL submit, and cleanup are checked by Sentico ops | node scripts/e2e/mm-docs-contract-audit.cjs |
| OpenAPI institutional contract | Account model, bootstrap, BSL submit, direct order-entry, receipts, and per-action results are typed | cargo test -p senticore-sequencing-core openapi_contract --tests |
| HMAC vector | Independent client reproduces the documented HMAC signature | sdks/typescript/tests/auth.test.ts |
| Action hash vectors | Independent signer reproduces canonical JSON, v1/v2 hashes, and derived order ids | sdks/typescript/tests/signing.test.ts |
| Nonce replay | Duplicate action nonce is rejected and client re-signs with a fresh in-window nonce | local test or beta account |
| Idempotency | Same key plus same body returns/replays safely; same key plus different body conflicts | local test or beta account |
| Account mapping | Client stores accountIdHex and engineAccountHex separately | live trading-account list |
| Funding preflight | Fresh bootstrap shows funded balances.freeUsdcMicro and matching-engine source when present | GET /api/v1/accounts/:engineAccount/bootstrap?fresh=true |
| QuoteReplace | One known-good QuoteReplace produces a derived order id and ack | POST /api/order-entry/binary or BSL compact facade |
| Reconciliation | Derived order id is found in orders/drop-copy/fills or terminal stream event | private read/stream/FIX drop-copy |
| Lane-key compatibility | Client uses X-Senticore-Order-Entry-Key; legacy headers tested only for migration | HTTP 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 freeUsdcMicroagainstexpectedFunding.freeUsdcMicroAtLeastfrom 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-submitreturns HTTP200, top-levelok: true, and no rejectedactionResults[].idempotency-replay-same-keysubmits identical bytes with the sameIdempotency-Key; it should replay or return the same accepted response.nonce-replay-different-keysubmits identical signed bytes with a differentIdempotency-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}}}
| Output | Value |
|---|---|
| v1 hash | 0xc8d02209196c492de5b39c90d7efd356548784ddd464603913b59afab911b42f |
v2 hash, chain 8453, contract 0xcccccccccccccccccccccccccccccccccccccccc | 0x26d8533a5150e7a8bf6537824715562eddb55a0c019a0b23635533a1d4e7e084 |
| derived order id | 0x52401b1d6de155089120a39ccd8ca52e3b5daaf090f090c5a0705b53b914d57e |
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}]}}}
| Output | Value |
|---|---|
| v1 hash | 0x0b635be460cf6d9ae3a9fe11c1b5d5176c942e9b6139f88dac142baa1818584c |
derived child order id, leg 0 | 0xfeac5884704773dd3150bef258b3f5a139dafaba0bba2190fc9d520b8a505e22 |
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-Nonceis decimal and single-use for that credentialSC-Timestampis Unix milliseconds with a 30 second skew tolerance
Nonce replay tests
Run these against a funded beta account with tiny post-only quantities.
| Test | Expected |
|---|---|
Submit action nonce N once | accepted or valid strategy/risk reject |
| Submit exact same signed body again with same idempotency key | idempotency replay or same stored response |
| Submit exact same signed body with different idempotency key | nonce_replayed or equivalent nonce conflict |
Submit nonce below nonceFloor | code: nonce_below_floor, nonceFloor present |
Submit nonce above nonceFloor + nonceWindow | code: nonce_outside_window, client must not blind retry |
Submit nonce 0 on a fresh funded account | accepted 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:
- Build one encoded batch and compute its SHA-256 locally.
- Submit with
Idempotency-Key: idem-1. - Repeat the exact same bytes with
idem-1. - 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
ackas 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.