Access TEE features from your JavaScript/TypeScript application running inside dstack. Derive deterministic keys, generate attestation quotes, create TLS certificates, and sign data—all backed by hardware security.
npm install @phala/dstack-sdkimport { DstackClient } from '@phala/dstack-sdk';
const client = new DstackClient();
// Derive a deterministic key for your wallet
const key = await client.getKey('wallet/eth');
console.log(key.key); // Same path always returns the same key
// Generate an attestation quote
const quote = await client.getQuote('my-app-state');
console.log(quote.quote);The client automatically connects to /var/run/dstack.sock. For local development with the simulator:
const client = new DstackClient('http://localhost:8090');getKey() derives deterministic keys bound to your application's identity (app_id). The same path always produces the same key for your app, but different apps get different keys even with the same path.
// Derive keys by path
const ethKey = await client.getKey('wallet/ethereum');
const btcKey = await client.getKey('wallet/bitcoin');
// Use path to separate keys
const mainnetKey = await client.getKey('wallet/eth/mainnet');
const testnetKey = await client.getKey('wallet/eth/testnet');Parameters:
path: Key derivation path (determines the key)purpose(optional): Included in signature chain message, does not affect the derived key
Returns: GetKeyResponse
key: Hex-encoded private keysignature_chain: Signatures proving the key was derived in a genuine TEE
getQuote() creates a TDX quote proving your code runs in a genuine TEE.
const quote = await client.getQuote('user:alice:nonce123');
// Replay RTMRs from the event log
const rtmrs = quote.replayRtmrs();
console.log(rtmrs);Parameters:
reportData: Exactly 64 bytes recommended. If shorter, pad with zeros. If longer, hash it first (e.g., SHA-256).
Returns: GetQuoteResponse
quote: Hex-encoded TDX quoteevent_log: JSON string of measured eventsreplayRtmrs(): Method to compute RTMR values from event log
const info = await client.info();
console.log(info.app_id);
console.log(info.instance_id);
console.log(info.tcb_info);Returns: InfoResponse
app_id: Application identifierinstance_id: Instance identifierapp_name: Application nametcb_info: TCB measurements (MRTD, RTMRs, event log)compose_hash: Hash of the app configurationapp_cert: Application certificate (PEM)
getTlsKey() creates fresh TLS certificates. Unlike getKey(), each call generates a new random key.
const tls = await client.getTlsKey({
subject: 'api.example.com',
altNames: ['localhost'],
usageRaTls: true // Embed attestation in certificate
});
console.log(tls.key); // PEM private key
console.log(tls.certificate_chain); // Certificate chainParameters:
subject(optional): Certificate common name (e.g., domain name)altNames(optional): List of subject alternative namesusageRaTls(optional): Embed TDX quote in certificate extensionusageServerAuth(optional): Enable for server authentication (default:true)usageClientAuth(optional): Enable for client authentication (default:false)
Returns: GetTlsKeyResponse
key: PEM-encoded private keycertificate_chain: List of PEM certificates
Sign data using TEE-derived keys (not yet released):
const result = await client.sign('ed25519', 'message to sign');
console.log(result.signature);
console.log(result.public_key);
// Verify the signature
const valid = await client.verify('ed25519', 'message to sign', result.signature, result.public_key);
console.log(valid.valid); // truesign() Parameters:
algorithm:'ed25519','secp256k1', or'secp256k1_prehashed'data: Data to sign (string, Buffer, or Uint8Array)
sign() Returns: SignResponse
signature: Hex-encoded signaturepublic_key: Hex-encoded public keysignature_chain: Signatures proving TEE origin
verify() Parameters:
algorithm: Algorithm used for signingdata: Original datasignature: Signature to verifypublic_key: Public key to verify against
verify() Returns: VerifyResponse
valid: Boolean indicating if signature is valid
Extend RTMR3 with custom measurements for your application's boot sequence (requires dstack OS 0.5.0+). These measurements are append-only and become part of the attestation record.
await client.emitEvent('config_loaded', 'production');
await client.emitEvent('plugin_initialized', 'auth-v2');Parameters:
event: Event name (string identifier)payload: Event value (string, Buffer, or Uint8Array)
import { toViemAccount } from '@phala/dstack-sdk/viem';
import { createWalletClient, http } from 'viem';
import { mainnet } from 'viem/chains';
const key = await client.getKey('wallet/ethereum');
const account = toViemAccount(key);
const wallet = createWalletClient({
account,
chain: mainnet,
transport: http()
});import { toKeypair } from '@phala/dstack-sdk/solana';
const key = await client.getKey('wallet/solana');
const keypair = toKeypair(key);
console.log(keypair.publicKey.toBase58());For local development without TDX hardware, use the simulator:
git clone https://github.com/Dstack-TEE/dstack.git
cd dstack/sdk/simulator
./build.sh
./dstack-simulatorThen set the endpoint:
export DSTACK_SIMULATOR_ENDPOINT=http://localhost:8090These utilities are for deployment scripts, not runtime SDK operations.
Encrypt secrets before deploying to dstack:
import { encryptEnvVars, verifyEnvEncryptPublicKey, verifyEnvEncryptPublicKeyLegacy, type EnvVar } from '@phala/dstack-sdk';
// Get and verify the KMS public key
// (obtain public_key, signature_v1, and timestamp from KMS API)
// Prefer signature_v1 with timestamp (prevents replay attacks)
const kmsIdentity = verifyEnvEncryptPublicKey(publicKeyBytes, signatureV1Bytes, appId, timestamp);
if (!kmsIdentity) {
// Fall back to legacy signature for backward compatibility with older KMS
const legacyIdentity = verifyEnvEncryptPublicKeyLegacy(publicKeyBytes, signatureBytes, appId);
if (!legacyIdentity) {
throw new Error('Invalid KMS key');
}
console.warn('Using legacy signature without timestamp protection');
}
// Encrypt variables
const envVars: EnvVar[] = [
{ key: 'DATABASE_URL', value: 'postgresql://...' },
{ key: 'API_KEY', value: 'secret' }
];
const encrypted = await encryptEnvVars(envVars, publicKey);new DstackClient(endpoint?: string)Parameters:
endpoint(optional): Connection endpoint- Unix socket path (production):
/var/run/dstack.sock - HTTP/HTTPS URL (development):
http://localhost:8090 - Environment variable:
DSTACK_SIMULATOR_ENDPOINT
- Unix socket path (production):
Production App Configuration:
The Docker Compose configuration is embedded in app-compose.json:
{
"manifest_version": 1,
"name": "production-app",
"runner": "docker-compose",
"docker_compose_file": "services:\n app:\n image: your-app\n volumes:\n - /var/run/dstack.sock:/var/run/dstack.sock\n environment:\n - NODE_ENV=production",
"public_tcbinfo": true
}Important: The docker_compose_file contains YAML content as a string, ensuring the volume binding for /var/run/dstack.sock is included.
Retrieves comprehensive information about the TEE instance.
Returns: InfoResponse
app_id: Unique application identifierinstance_id: Unique instance identifierapp_name: Application name from configurationdevice_id: TEE device identifiertcb_info: Trusted Computing Base informationmrtd: Measurement of TEE domainrtmr0-3: Runtime Measurement Registersevent_log: Boot and runtime eventsos_image_hash: Operating system measurementcompose_hash: Application configuration hash
app_cert: Application certificate in PEM formatkey_provider_info: Key management configuration
Derives a deterministic secp256k1/K256 private key for blockchain and Web3 applications. This is the primary method for obtaining cryptographic keys for wallets, signing, and other deterministic key scenarios.
Parameters:
path: Unique identifier for key derivation (e.g.,"wallet/ethereum","signing/solana")purpose(optional): Additional context for key usage (default:"")
Returns: GetKeyResponse
key: 32-byte secp256k1 private key asUint8Array(suitable for Ethereum, Bitcoin, Solana, etc.)signature_chain: Array of cryptographic signatures proving key authenticity
Key Characteristics:
- Deterministic: Same path + purpose always generates identical key
- Isolated: Different paths produce cryptographically independent keys
- Blockchain-Ready: Compatible with secp256k1 curve (Ethereum, Bitcoin, Solana)
- Verifiable: Signature chain proves key was derived inside genuine TEE
Use Cases:
- Cryptocurrency wallets
- Transaction signing
- DeFi protocol interactions
- NFT operations
- Any scenario requiring consistent, reproducible keys
// Examples of deterministic key derivation
const ethWallet = await client.getKey('wallet/ethereum', 'mainnet');
const btcWallet = await client.getKey('wallet/bitcoin', 'mainnet');
const solWallet = await client.getKey('wallet/solana', 'mainnet');
// Same path always returns same key
const key1 = await client.getKey('my-app/signing');
const key2 = await client.getKey('my-app/signing');
// key1.key === key2.key (guaranteed identical)
// Different paths return different keys
const userA = await client.getKey('user/alice/wallet');
const userB = await client.getKey('user/bob/wallet');
// userA.key !== userB.key (guaranteed different)Generates a TDX attestation quote containing the provided report data.
Parameters:
reportData: Data to include in quote (max 64 bytes)
Returns: GetQuoteResponse
quote: TDX quote as hex stringevent_log: JSON string of system eventsreplayRtmrs(): Function returning computed RTMR values
Use Cases:
- Remote attestation of application state
- Cryptographic proof of execution environment
- Audit trail generation
Generates a versioned attestation containing the provided report data.
Parameters:
reportData: Data to include in attestation (max 64 bytes)
Returns: AttestResponse
attestation: Hex-encoded attestation payload
Use Cases:
- Remote attestation across multiple platform types
- Verifier APIs that accept versioned attestations
Generates a fresh, random TLS key pair with X.509 certificate for TLS/SSL connections. Important: This method generates different keys on each call - use getKey() for deterministic keys.
Parameters: TlsKeyOptions
subject(optional): Certificate subject (Common Name) - typically the domain name (default:"")altNames(optional): Subject Alternative Names - additional domains/IPs for the certificate (default:[])usageRaTls(optional): Include TDX attestation quote in certificate extension for remote verification (default:false)usageServerAuth(optional): Enable server authentication - allows certificate to authenticate servers (default:true)usageClientAuth(optional): Enable client authentication - allows certificate to authenticate clients (default:false)
Returns: GetTlsKeyResponse
key: Private key in PEM format (X.509/PKCS#8)certificate_chain: Certificate chain array
Key Characteristics:
- Random Generation: Each call produces a completely different key
- TLS-Optimized: Keys and certificates designed for TLS/SSL scenarios
- RA-TLS Support: Optional remote attestation extension in certificates
- TEE-Signed: Certificates signed by TEE-resident Certificate Authority
Certificate Usage Scenarios:
-
Standard HTTPS Server (
usageServerAuth: true,usageClientAuth: false)- Web servers, API endpoints
- Server authenticates to clients
- Most common TLS use case
-
Remote Attestation Server (
usageRaTls: true)- TEE-based services requiring proof of execution environment
- Clients can verify the server runs in genuine TEE
- Combines TLS with hardware attestation
-
mTLS Client Certificate (
usageServerAuth: false,usageClientAuth: true)- Client authentication in mutual TLS
- API clients, service-to-service communication
- Client proves identity to server
-
Dual-Purpose Certificate (
usageServerAuth: true,usageClientAuth: true)- Services that act as both client and server
- Microservices architectures
- Maximum flexibility for TLS roles
// Example 1: Standard HTTPS server certificate
const serverCert = await client.getTlsKey({
subject: 'api.example.com',
altNames: ['api.example.com', 'www.api.example.com', '10.0.0.1']
// usageServerAuth: true (default) - allows server authentication
// usageClientAuth: false (default) - no client authentication
});
// Example 2: Certificate with remote attestation (RA-TLS)
const attestedCert = await client.getTlsKey({
subject: 'secure-api.example.com',
usageRaTls: true // Include TDX quote for remote verification
// Clients can verify the TEE environment through the certificate
});
// Example 3: Mutual TLS (mTLS) certificate for client authentication
const clientCert = await client.getTlsKey({
subject: 'client.example.com',
usageServerAuth: false, // This certificate won't authenticate servers
usageClientAuth: true // Enable client authentication
});
// Example 4: Certificate for both server and client authentication
const dualUseCert = await client.getTlsKey({
subject: 'dual.example.com',
usageServerAuth: true, // Can authenticate as server
usageClientAuth: true // Can authenticate as client
});
// ⚠️ Each call generates different keys (unlike getKey)
const cert1 = await client.getTlsKey();
const cert2 = await client.getTlsKey();
// cert1.key !== cert2.key (always different)
// Use with Node.js HTTPS server
import https from 'https';
const server = https.createServer({
key: serverCert.key,
cert: serverCert.certificate_chain.join('\n')
}, app);Extends RTMR3 with a custom event for audit logging.
Parameters:
event: Event identifier stringpayload: Event data
Requirements:
- dstack OS version 0.5.0 or later
- Events are permanently recorded in TEE measurements
Tests connectivity to the dstack service.
Returns: boolean indicating service availability
import { getComposeHash } from '@phala/dstack-sdk';
const hash = getComposeHash(appComposeObject);Replace TappdClient with DstackClient:
// Before
import { TappdClient } from '@phala/dstack-sdk';
const client = new TappdClient();
// After
import { DstackClient } from '@phala/dstack-sdk';
const client = new DstackClient();Method changes:
deriveKey()→getTlsKey()for TLS certificatestdxQuote()→getQuote()(raw data only, no hash algorithms)- Socket path:
/var/run/tappd.sock→/var/run/dstack.sock
Apache License 2.0