SDK
Leaders send signals from wherever their strategy runs. A trader can sign in the browser on the Lead page; an agent or a trading server uses the signal SDK from its own process. Either way the signal is signed with the strategy's signal key, sealed so that only the attested executor can read it, and admitted with a receipt signed by the executor.
Install
The packages are served from this site:
npm install https://unseen.markets/sdk/unseen-contract.tgz https://unseen.markets/sdk/unseen-signal-sdk.tgz
Both packages use Web Crypto, fetch and typed arrays only, so they run in Node 22+, Deno, Bun and browsers.
The deployment you trust
Pin these values in your own configuration. The SDK checks the executor against them before it signs anything, and never takes trust anchors from an API response.
API https://<api host>
Genesis hash <genesis hash>
Program <program id>
Executor key <executor public key>
Intel issuer <Intel Trust Authority issuer>
Intel JWKS <Intel Trust Authority JWKS URL>
TDX MRTD <TDX MRTD>
Policy IDs <workload policy IDs>
A signal key
The signal key is separate from the leader's wallet. Create it where it will be used and register its public key when you create the strategy, or rotate to it later from the strategy's card.
import { ed25519 } from '@noble/curves/ed25519'
import { randomBytes } from 'node:crypto'
const secret = randomBytes(32) // keep this secret where the agent runs
const signalPublicKey = ed25519.getPublicKey(secret) // register its base58 form as the strategy's signal key
The Lead page can also create a key file for you (Download a key file for an agent or server): a JSON array of 64 bytes, the first 32 being the secret.
Send a signal
import { createUnseenClient } from '@unseen/contract'
import { createSealedSignalClient } from '@unseen/signal-sdk'
import { ed25519 } from '@noble/curves/ed25519'
const api = createUnseenClient({ baseUrl: 'https://<api host>', accessToken: () => sessionToken })
const deployment = (await api.request('deployment')).data
const signals = createSealedSignalClient({
deployment,
trust: {
genesisHash: GENESIS_HASH,
programId: PROGRAM_ID,
executorPublicKey: EXECUTOR_PUBLIC_KEY,
issuer: ITA_ISSUER,
jwksUrl: ITA_JWKS_URL,
expectedMeasurement: TDX_MRTD,
expectedPolicyIds: POLICY_IDS,
},
signMessage: async (bytes) => ed25519.sign(bytes, secret),
submitEnvelope: (envelope) => api.request('sealedSignal', { body: envelope }),
})
const { meta } = await api.request('platform')
const signed = await signals.signSignal({
version: 2,
genesisHash: deployment.genesisHash,
programId: deployment.programs.unseen,
executorPublicKey: deployment.executor.publicKey,
strategyId: STRATEGY_ID,
signalKey: SIGNAL_PUBLIC_KEY,
sequence: '42',
targets: [{ market: 'SOL', side: 'long', weightBps: '15000' }],
validUntilSlot: (BigInt(meta.slot) + 150n).toString(),
maxOracleDeviationBps: '30',
})
const receipt = await signals.submitSigned(signed)
sessionToken is the leader wallet's API session (see Public API for sign-in). Keep signed until you have the receipt: after an uncertain response, call submitSigned(signed) again with the same object — the executor recognises the sequence and returns the original receipt.
What the SDK checks first
- The executor's attestation token is signed by Intel Trust Authority with a key from the pinned JWKS, from the pinned issuer, and fresh.
- The TDX measurement and the workload policies match your pins; debug mode is off; the TCB is up to date.
- The token's report data binds the deployment and both executor keys.
Only then does it sign the signal with your key and encrypt it (P-256 ECDH, HKDF-SHA256, AES-256-GCM) to the executor's attested key. The API relays the ciphertext; it can't read it. The executor's receipt is verified before submitSigned returns.
Read the console
const proof = await signals.signLeaderView({
strategyId: STRATEGY_ID,
wallet: LEADER_WALLET,
signMessage: (bytes) => leaderWallet.signMessage(bytes),
})
const view = (await api.request('leaderConsoleView', { params: { strategyId: STRATEGY_ID }, body: proof })).data
The proof is signed by the leader's wallet, not the signal key, lasts one minute, and works once. view holds positions, signals with their states, fills, fees and follower totals.
Public data without a key
Everything public — strategies, stats, epochs, unattributed executions, revealed trades and rebuilt NAV — needs no key and no session. See Public API and Verify a trade.