MPC Sessions & Key Generation
The Silent Shard SDK works through two session types:
- ECDSA session — used for EVM chains (Ethereum, Base, etc.)
- EdDSA session — used for Solana
Each session represents the device-side half of the MPC key pair. The cloud-side half lives on duo-server. Neither side ever has the full key.
Session initialization
Sessions are initialized once on app startup in libs/silent-shard.ts:
// libs/silent-shard.ts
async initSessions(
cloudNodeUrl: string,
cloudVerifyingKey: string,
messageSigner: MessageSigner,
) {
const url = new URL(cloudNodeUrl);
const isSecure = url.protocol === 'https:';
const stripeHttp = `${url.hostname}:${url.port}`;
const cloudClient = new CloudWebSocketClient(stripeHttp, isSecure);
const sessionConfig = {
client: cloudClient, // WebSocket connection to duo-server
cloudVerifyingKey, // Verifies responses are from the genuine cloud node
storage: storageProvider, // Persists keyshares via expo-secure-store
messageSigner, // Signs SDK transport messages using the device TEE key
};
this._ecdsaSession = await createEcdsaDuoSession(sessionConfig);
this._eddsaSession = await createEddsaDuoSession(sessionConfig);
}
export const silentShardSDK = new SilentShardSDK();
The messageSigner comes from libs/secure-key.ts — it wraps the device's TEE key and signs every message sent to the cloud node, preventing tampering in transit.
Session initialization flow
Keyshare storage
Keyshares are persisted automatically via libs/storage-provider.ts, which wraps expo-secure-store. This means sessions survive app restarts — on the next launch, the SDK reloads the keyshares from secure storage and the sessions are ready to sign without needing keygen again.
Key generation
Key generation (keygen) runs once to create the wallet. It is triggered from the Create Wallet screen via api/useKeygen.ts:
// api/useKeygen.ts
const ecdsaKeyshare = await silentShardSDK.ecdsaSession.keygen();
const eddsaKeyshare = await silentShardSDK.eddsaSession.keygen();
// Store the keyshare IDs and derive wallet addresses
setEcdsaMpcShare(ecdsaKeyshare);
setEddsaMpcShare(eddsaKeyshare);
Each keygen() call triggers the MPC protocol between the device and duo-server. duo-server checks auth-svc via hook before proceeding. On completion, each party stores their share — the device in expo-secure-store, duo-server on its own storage.
The resulting keyshare object contains publicKeyHex, which is used to derive the wallet address (see Multi-Chain Signing).
Keygen is a one-time operation per device. The keyshare ID is persisted to walletStore (MMKV). If the app is uninstalled or the device keystore is cleared without a backup, the wallet cannot be recovered.