Quick Start
Set up the Mobile SDK and run your first MPC operations. You will create a working MPC three-party setup, where the first party, a React Native mobile application, interacts with the two Trio nodes as the second and third parties. We are providing a demo server endpoint for your convenience.
For quick testing, use our hosted demo server. No deployment is needed.
- Cloud Node Endpoint:
trio-server.demo.silencelaboratories.com - Cloud Verifying Key:
019c4c79e942bbc3ff1d6ace7256404d701498056978cc4638c35832acdf821b1e
As a shared demo server, it offers no rate-limit or uptime guarantees, and keyshares stored on it may be purged without notice. It is intended for evaluation and testing, not for production use.
Prerequisites
- Node.js (LTS) and a package manager (npm or Yarn).
- An NPM token from Silence Laboratories to install the SDK from our private registry. Don't have one? Email [email protected].
- A running iOS Simulator (Xcode) or Android emulator (Android Studio) to launch the app on.
Setup the Mobile SDK (React Native)
Create a new React Native project
npx create-expo-app@latest SilentMPC --template blank-typescript
Configure Your Package Manager
Configure your package manager with a private token provided by us to access the private registry.
If you don't have NPM token, please contact us at [email protected].
Use a consistent install workflow throughout (either npm install or yarn add). Note that .npmrc configuration applies to both npm and Yarn v1, while Yarn v2+ uses .yarnrc.yml.
- yarn v2
- yarn v1 / npm
- Create a
.yarnrc.ymlfile in the root of your project and add the following line:
npmScopes:
"silencelaboratories":
npmAlwaysAuth: true
npmRegistryServer: "https://registry.npmjs.org"
npmAuthToken: ${NPM_TOKEN}
- Create a
.npmrcfile in the root of your project and add the following line:
//registry.npmjs.org/:_authToken=${NPM_TOKEN}
- Add the npm token as an environment variable, e.g., in a terminal session run:
export NPM_TOKEN=your-npm-token
Install the core library
- npm
- yarn
npm install @silencelaboratories/silent-shard-sdk
yarn add @silencelaboratories/silent-shard-sdk
Install the native SDK(s) for your wallet types
You only need the native SDKs for the wallet families your app actually supports — installing extras only adds bundle size.
| Wallet family | Algorithm | Native package |
|---|---|---|
| EVM, Bitcoin, etc. | ECDSA | @silencelaboratories/dkls-sdk |
| Solana, etc. | EdDSA | @silencelaboratories/schnorr-sdk |
- ECDSA
- EdDSA
- npm
- yarn
npm install @silencelaboratories/dkls-sdk
yarn add @silencelaboratories/dkls-sdk
- npm
- yarn
npm install @silencelaboratories/schnorr-sdk
yarn add @silencelaboratories/schnorr-sdk
Project setup
Run the following command to generate the native code for your project:
npx expo prebuild
Session Creation
The Session object is the main entry point to interact with the Silent Shard SDK. It manages the lifecycle of the MPC operations.
import { CloudWebSocketClient } from "@silencelaboratories/silent-shard-sdk";
import { createEcdsaTrioSession } from "@silencelaboratories/silent-shard-sdk/ecdsa";
// Create a session
const cloudClient = new CloudWebSocketClient(
"trio-server.demo.silencelaboratories.com",
true // Use true for secure connection, otherwise use false for local server
);
const session = await createEcdsaTrioSession({
cloudVerifyingKey: "019c4c79e942bbc3ff1d6ace7256404d701498056978cc4638c35832acdf821b1e",
client: cloudClient,
});
Run the MPC operations
After creating the session, you can perform MPC operations.
Key Generation
Generate MPC keyshares and return the client keyshare with keygen method.
const clientKeyshare = await session.keygen();
console.log("Client Public Key:", clientKeyshare.publicKeyHex);
Signature Generation
Sign a message using the sign method.
const signature = await session.sign({
keyshare: clientKeyshare,
// Keccak256 Hash("Trusted Third Parties are Security Holes")
messageHash:
"53c48e76b32d4fb862249a81f0fc95da2d3b16bf53771cc03fd512ef5d4e6ed9",
derivationPath: "m",
});
console.log("Generated signature: ", signature);
Complete Code Example
Add the following code to your App.tsx.
import * as React from 'react';
import { CloudWebSocketClient } from '@silencelaboratories/silent-shard-sdk';
import { createEcdsaTrioSession } from '@silencelaboratories/silent-shard-sdk/ecdsa';
export default function App() {
React.useEffect(() => {
// We will MPC functions here
const mpcTest = async () => {
try {
// Create a session.
// 1st arg: the Cloud Node Endpoint (Trio Servers host). The single demo host
// fronts both Trio servers. 2nd arg: secure flag — true => wss:// (TLS), false => ws://.
const cloudClient = new CloudWebSocketClient('trio-server.demo.silencelaboratories.com', true);
const session = await createEcdsaTrioSession({
// The servers' public signing key, used to verify messages from the server parties.
cloudVerifyingKey: '019c4c79e942bbc3ff1d6ace7256404d701498056978cc4638c35832acdf821b1e',
client: cloudClient,
});
// Key generation
const clientKeyshare = await session.keygen();
// Get public key of newly generated wallet
console.log('Client Public Key:', clientKeyshare.publicKeyHex);
// Signature generation
const signature = await session.sign({
keyshare: clientKeyshare,
// Keccak256 Hash("Trusted Third Parties are Security Holes")
messageHash: '53c48e76b32d4fb862249a81f0fc95da2d3b16bf53771cc03fd512ef5d4e6ed9',
derivationPath: 'm',
});
console.log('Generated signature: ', signature);
} catch (err) {
console.error('MPC test failed:', err);
}
};
mpcTest();
}, []);
return null;
}
Run your application!
Run your application in a classic way.
Expo Go support is coming soon too!
- npm
- yarn
npm run android
or
npm run ios
yarn android
or
yarn ios
Once the application is running, check your console log to see the key generation and signing process updates in real-time.
Happy signing!
The steps above run against our hosted demo server, so you can generate a keyshare and sign without deploying anything. To run your own Trio nodes in production, see Trio Server.
Set up the Mobile SDK and run your first MPC operations.
You will create a working MPC three-party setup, where the first party, a Flutter mobile application, interacts with the two Trio nodes as the second and third parties. We are providing a demo server endpoint for your convenience.
For quick testing, use our hosted demo server. No deployment is needed.
- Cloud Node Endpoint:
trio-server.demo.silencelaboratories.com - Cloud Verifying Key:
019c4c79e942bbc3ff1d6ace7256404d701498056978cc4638c35832acdf821b1e
As a shared demo server, it offers no rate-limit or uptime guarantees, and keyshares stored on it may be purged without notice. It is intended for evaluation and testing, not for production use.
Prerequisites
- The Flutter SDK (with Dart) and a working Flutter toolchain, follow the Flutter installation guide.
- A Dart pub token from Silence Laboratories for our private registry (
dart-pkg.silencelaboratories.com). Don't have one? Email [email protected]. - A running iOS Simulator (Xcode) or Android emulator (Android Studio) to launch the app on.
Setup the Mobile SDK (Flutter)
Create a new Flutter project
flutter create silent_mpc
Configure your dart pub client
-
Obtain a Pub token from Silence Laboratories team.
-
Add token to dart pub client using the command:
dart pub token add https://dart-pkg.silencelaboratories.com
Enter secret token: <silence-dart-token>
Dependency Installation
- Add
silent_shard_sdkfrom thehttps://dart-pkg.silencelaboratories.comregistry. In terminal from root of the flutter project, run
dart pub add 'silent_shard_sdk:{"hosted":"https://dart-pkg.silencelaboratories.com"}'
Session Creation
The Session object is the main entry point to interact with the Silent Shard SDK. It manages the lifecycle of the MPC operations.
- ECDSA
- EdDSA
- Taproot
import 'dart:io';
import 'package:silent_shard_sdk/silent_shard_sdk.dart' as sdk;
Future<sdk.EcdsaSession> setup(
[String cloudVerifyingKeyHex = 'SERVER_PUBLIC_KEY_HEX']) async {
/// The port number is the port number of the cloud node.
const port = 8080;
/// The nodeUri is the URI of the cloud node. It is the IP address of the cloud node.
/// Localhost url used for Android and iOS is shown below.
/// 10.0.2.2 is the IP address of the Android emulator.
/// 0.0.0.0 is the IP address of the iOS simulator.
final nodeUri = Platform.isAndroid ? '10.0.2.2:$port' : '0.0.0.0:$port';
final cloudClient = sdk.CloudClient(
baseUri: nodeUri,
isSecure: false,
);
final session = sdk.createTrioEcdsaSession(
cloudClient: cloudClient,
cloudVerifyingKeyHex: cloudVerifyingKeyHex,
storageClient: sdk.SimpleStorageClient(),);
return session;
}
import 'dart:io';
import 'package:silent_shard_sdk/silent_shard_sdk.dart' as sdk;
Future<sdk.EddsaSession> setup(
[String cloudVerifyingKeyHex = 'SERVER_PUBLIC_KEY_HEX']) async {
/// The port number is the port number of the cloud node.
const port = 8080;
/// The nodeUri is the URI of the cloud node. It is the IP address of the cloud node.
/// Localhost url used for Android and iOS is shown below.
/// 10.0.2.2 is the IP address of the Android emulator.
/// 0.0.0.0 is the IP address of the iOS simulator.
final nodeUri = Platform.isAndroid ? '10.0.2.2:$port' : '0.0.0.0:$port';
final cloudClient = sdk.CloudClient(
baseUri: nodeUri,
isSecure: false,
);
final session = await sdk.createTrioEddsaSession(
cloudClient: cloudClient,
cloudVerifyingKeyHex: cloudVerifyingKeyHex,
storageClient: sdk.SimpleStorageClient(),
);
return session;
}
import 'dart:io';
import 'package:silent_shard_sdk/silent_shard_sdk.dart' as sdk;
Future<sdk.TaprootSession> setup([String cloudVerifyingKeyHex = 'SERVER_PUBLIC_KEY_HEX']) async {
/// The port number is the port number of the cloud node.
const port = 8080;
/// The nodeUri is the URI of the cloud node. It is the IP address of the cloud node.
/// Localhost url used for Android and iOS is shown below.
/// 10.0.2.2 is the IP address of the Android emulator.
/// 0.0.0.0 is the IP address of the iOS simulator.
final nodeUri = Platform.isAndroid ? '10.0.2.2:$port' : '0.0.0.0:$port';
final cloudClient = sdk.CloudClient(
baseUri: nodeUri,
isSecure: false,
);
final session = await sdk.createTrioTaprootSession(
cloudClient: cloudClient,
cloudVerifyingKeyHex: cloudVerifyingKeyHex,
storageClient: sdk.SimpleStorageClient(),
);
return session;
}
Run the MPC operations
After creating the session, you can perform MPC operations.
Key Generation
Generate MPC keyshares and return the client keyshare with keygen method.
- ECDSA
- EdDSA
- Taproot
import 'package:silent_shard_sdk/silent_shard_sdk.dart' as sdk;
Future<void> keygen(sdk.EcdsaSession session) async {
final keyshare = await session.keygen();
print('Keyshare created, public key: ${keyshare.publicKeyHex}');
}
import 'package:silent_shard_sdk/silent_shard_sdk.dart' as sdk;
Future<void> keygen(sdk.EddsaSession session) async {
final sdk.SchnorrKeyshare keyshare = await session.keygen();
print('Keyshare generated ${await keyshare.publicKeyHex}');
}
import 'package:silent_shard_sdk/silent_shard_sdk.dart' as sdk;
Future<void> keygen(sdk.TaprootSession session) async {
final keyshare = await session.keygen();
print('Keyshare created, public key: ${keyshare.publicKeyHex}');
}
Signature Generation
Sign a message using the sign method.
- ECDSA
- EdDSA
- Taproot
import 'package:silent_shard_sdk/silent_shard_sdk.dart' as sdk;
const messageHash =
'e2a159d17b7bb714aed7675d7c7d394dec8d2e4337842848104694bf89c71c03';
Future<void> signGen(sdk.EcdsaSession session) async {
// Creating a new keyshare for demo purpose. In real application, you can use an existing keyshare.
final keyshare = await session.keygen();
final signature = await session.sign(
keyId: keyshare.keyId,
messageHash: messageHash,
);
print('Signature: $signature');
}
import 'package:silent_shard_sdk/silent_shard_sdk.dart' as sdk;
const messageHash =
'e2a159d17b7bb714aed7675d7c7d394dec8d2e4337842848104694bf89c71c03';
Future<void> signGen(sdk.EddsaSession session) async {
// Creating a new keyshare for demo purpose. In real application, you can use an existing keyshare.
final keyshare = await session.keygen();
final signature = await session.sign(
keyId: await keyshare.keyId,
messageHash: messageHash,
);
print('Signature: $signature');
}
import 'package:silent_shard_sdk/silent_shard_sdk.dart' as sdk;
const messageHash =
'5ae9337fe6b54559bf2c16aea4472f8f8cfab3cfa6844547801fb8c752151552';
Future<void> signGen(sdk.TaprootSession session) async {
// Creating a new keyshare for demo purpose. In real application, you can use an existing keyshare.
final keyshare = await session.keygen();
final signature = await session.sign(
keyId: keyshare.keyId,
messageHash: messageHash,
);
print('Signature: $signature');
}
Complete Code Example
import 'package:flutter/material.dart';
import 'package:silent_shard_sdk/silent_shard_sdk.dart' as sdk;
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
Future<void> _testMpcOperations() async {
final cloudClient = sdk.CloudClient(baseUri: 'trio-server.demo.silencelaboratories.com', isSecure: true);
final session = await sdk.createTrioEcdsaSession(
cloudClient: cloudClient,
cloudVerifyingKeyHex: '019c4c79e942bbc3ff1d6ace7256404d701498056978cc4638c35832acdf821b1e',
storageClient: sdk.SimpleStorageClient(),
);
final keyshare = await session.keygen();
print('Client Public Key: ${keyshare.publicKeyHex}');
final signature = await session.sign(
keyId: keyshare.keyId,
// Keccak256 Hash("Trusted Third Parties are Security Holes")
messageHash: "53c48e76b32d4fb862249a81f0fc95da2d3b16bf53771cc03fd512ef5d4e6ed9",
derivationPath: 'm',
);
print('Generated signature: $signature');
}
// This widget is the root of your application.
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Silent MPC Demo')),
body: Center(
child: ElevatedButton(
onPressed: () async {
await _testMpcOperations();
},
child: Text('Test MPC operations'),
),
),
),
);
}
}
Run the flutter project
flutter run
Once the app launches, check your console log to see the key generation and signing process updates in real-time.
The steps above run against our hosted demo server (endpoint and verifying key in Prerequisites), so you can generate a keyshare and sign without deploying anything. To run your own Trio nodes in production, see Trio Server.
If you don't have have access to the docker image or don't have access to the android sdk repository, please contact us at [email protected].
Here is how you can setup the Mobile SDK and perform MPC operations in less than a minute.
You will create a working MPC two-party setup, where the first party, an Android application interacts with Trio Servers as a second party, and third party.
What you'll build
The example-hub reference wallet is a complete Android app that creates a 3-party, 2-of-3 MPC wallet and signs real Ethereum (Base Sepolia) and Solana (Devnet) transactions. This guide walks through its core MPC code — session setup, keygen, and signing. Clone the app to run the whole thing: wallet UI, funding, and on-chain transactions.




Prerequisites
For quick testing, the demo server is already deployed at trio-server.demo.silencelaboratories.com. We are using this server for the quickstart guide.
The Cloud Verifying Key for the demo server is 9c4c79e942bbc3ff1d6ace7256404d701498056978cc4638c35832acdf821b1e.
The Cloud Node Endpoint for the demo server is https://trio-server.demo.silencelaboratories.com.
Setup the Mobile SDK (Android)
The quickest way to get running is to clone the reference app and launch it:
git clone https://github.com/silence-laboratories/examples-hub.git
cd examples-hub/silent-shard-sdk/with-android/trio-initiator
Add your GitHub Packages credentials to local.properties (see Dependency Installation below for the read-only token), then open the project in Android Studio and run it on a device or emulator. It talks to the public demo server out of the box, so you can create a wallet and sign a transaction right away. The full file-by-file walkthrough (keygen, signing, export, key refresh, and more) is in Android & iOS reference apps.
Session Creation
A TrioSession is the handle for all MPC operations (keygen, sign, and so on). The reference app builds one session per algorithm inside its VaultSessionManager:
// HardwareMessageSigner is the app's own implementation of the SDK's MessageSigner
// interface, signing with a hardware-backed key (Android Keystore).
private val messageSigner = HardwareMessageSigner()
private val websocketConfig = WebsocketConfig(url = DEMO_SERVER_URL, port = DEMO_SERVER_PORT, isSecure = true)
// EncryptedStorageClient is the app's own implementation of the SDK's StorageClient
// interface. Since that interface carries a keyType, ECDSA and EdDSA keyshares are
// persisted through separate clients — one per algorithm.
private val ecdsaStorage = EncryptedStorageClient(store, KeyType.ECDSA)
private val eddsaStorage = EncryptedStorageClient(store, KeyType.EdDSA)
// One TrioSession per algorithm, each bound to the message signer, the cloud
// verifying key, the websocket config, and its storage client.
private val ecdsaSession: TrioSession =
SilentShard.ECDSA.trioInitiator(messageSigner, CLOUD_VERIFYING_KEY, websocketConfig, ecdsaStorage)
private val eddsaSession: TrioSession =
SilentShard.EdDSA.trioInitiator(messageSigner, CLOUD_VERIFYING_KEY, websocketConfig, eddsaStorage)
HardwareMessageSigner and EncryptedStorageClient are not SDK types — they are the reference app's own implementations of the SDK's MessageSigner and StorageClient interfaces (hardware-backed P-256 signing and encrypted keyshare storage). Supply your own implementations, or clone the example-hub app to use these as-is.
Run the MPC operations
After creating the session, you can perform MPC operations.
Key Generation
Generate MPC keyshares with the keygen method. It returns a keyId (a String); the SDK persists the keyshare to your StorageClient and every later operation is addressed by that keyId. Here is how the reference app does it:
suspend fun keygen(keyType: KeyType): KeyResult {
Log.i(TAG, "Keygen started for type: ${keyType.name}")
// sessionFor(...) is this app's own helper (not an SDK method) — it returns the TrioSession
// we created earlier for this algorithm (ECDSA or EdDSA).
val session: TrioSession = sessionFor(keyType)
// keygen() is the SDK call: runs the MPC protocol, persists the keyshare to your
// StorageClient, and returns the keyId that addresses it.
val keyId = session.keygen().getOrThrow()
val publicKey = extractPublicKey(keyId)
Log.i(TAG, "Keygen completed for keyId: $keyId")
return KeyResult(keyId, publicKey)
}
Signature Generation
Sign a message using the sign method, passing the keyId returned from keygen:
suspend fun sign(keyId: String, message: ByteArray, derivationPath: String): ByteArray {
val dao = readDao(keyId)
// sessionFor(...) is this app's own helper (not an SDK method) — it returns the TrioSession
// we created earlier for this key's algorithm (the stored record's keyType).
val session: TrioSession = sessionFor(dao.keyType)
// sign() is the SDK call: it produces the threshold signature for the key addressed by keyId.
val signature = session
.sign(keyId, message.toHex(), derivationPath)
.getOrThrow()
Log.i(TAG, "Sign completed (${signature.size} bytes, type=${dao.keyType.name})")
return signature
}
The HardwareMessageSigner, EncryptedStorageClient, and WebSocket client shown are the reference app's implementations — hence for reference only, not a recommendation. Provide your own for production.
Setup your own app
Prefer to wire the SDK into your own app instead of the reference project? Create a new Android Studio project by following the official guide (or use an existing one), then add the SilentShard dependency.
Dependency Installation
Step 1: Create access token for the repository
- Get access to the repository https://github.com/silence-laboratories/silent-shard-artifacts from the Silence Laboratories team.
- Create a personal access token at https://github.com/settings/tokens with the following scopes
checked[✓] to access the repository, and it's
associated GithubPackages
through gradle.
- Under
repo-> [✓]public_repo - Under
write:packages-> [✓]read:packages
We can leavewrite:packagesuntouched/unchecked as we only need read access - It will end up looking like this : Two items checked everything else unchecked. See below.

- Under
Step 2: Configure settings.gradle.kts
- Add the silentshard maven repo with the access credentials under the dependencyResolutionManagement -> repositories.
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
maven {
url =
uri("https://maven.pkg.github.com/silence-laboratories/silent-shard-artifacts")
credentials {
username = "github_username"
password = "token_we_just_created"
}
}
}
}
Step 3: Configure app level build.gradle.kts
Add the silentshard dependency in your dependencies block:
dependencies {
implementation("com.silencelaboratories.silentshard:trio:1.0.0")
}
Step 4: Gradle-Sync
- Sync gradle with project files.
Android Manifest
The SDK communicates with the cloud node over the network, so add the internet permission to your AndroidManifest.xml:
<uses-permission android:name="android.permission.INTERNET" />
With the dependency in place, wire it up the same way the reference app does — create a session, then run keygen and signing.
If you don't have have access to the docker image or don't have access to the iOS sdk repository, please contact us at [email protected].
Here is how you can setup the Mobile SDK and perform MPC operations in less than a minute.
You will create a working MPC three-party setup, where the first party, an iOS application interacts with Trio Server as a second party, and a third party.
What you'll build
The example-hub reference wallet is a complete iOS app that creates a 2-of-3 MPC wallet and signs real Ethereum (Base Sepolia) and Solana (Devnet) transactions. This guide walks through its core MPC code — session setup, keygen, and signing. Clone the app to run the whole thing: wallet UI, funding, and on-chain transactions.




Prerequisites
For quick testing, the demo server is already deployed at trio-server.demo.silencelaboratories.com. We are using this server for the quickstart guide.
The Cloud Verifying Key for the demo server is 9c4c79e942bbc3ff1d6ace7256404d701498056978cc4638c35832acdf821b1e.
The Cloud Node Endpoint for the demo server is https://trio-server.demo.silencelaboratories.com.
Setup the Mobile SDK (iOS)
The quickest way to get running is to clone the reference app and launch it:
git clone https://github.com/silence-laboratories/examples-hub.git
cd examples-hub/silent-shard-sdk/with-ios/trio-initiator
Open SilentShardWalletTrio.xcodeproj in Xcode, let Swift Package Manager resolve the SDK dependency, and run it on a physical device (the Secure Enclave signer requires real hardware). iOS resolves the SDK package through your GitHub account — add it in Xcode → Settings → Accounts (see Dependency Installation below). It talks to the public demo server out of the box, so you can create a wallet and sign a transaction right away. The full file-by-file walkthrough (keygen, signing, export, key refresh, and more) is in Android & iOS reference apps.
Session Creation
A TrioSession is the handle for all MPC operations (keygen, sign, and so on). The reference app builds one session per algorithm inside its VaultSessionManager:
private let messageSigner: MessageSigner
private let store: EncryptedFileStorage
/// One storage client per algorithm. The MPC SDK's `StorageClient` API has
/// no concept of an algorithm tag, so each instance embeds its own ``KeyType``
/// in the serialized record. Reads from any instance see the same files, so
/// either client can resolve any keyId.
private let ecdsaStorage: EncryptedStorageClient
private let eddsaStorage: EncryptedStorageClient
private var ecdsaSession: TrioSession?
private var eddsaSession: TrioSession?
private static let demoServerUrl = "trio-server.demo.silencelaboratories.com"
private static let cloudVerifyingKey = "9c4c79e942bbc3ff1d6ace7256404d701498056978cc4638c35832acdf821b1e"
init() {
let fileStore = EncryptedFileStorage()
let signer: MessageSigner
do {
// SecureEnclaveMessageSigner is the app's own implementation of the SDK's MessageSigner
// interface, signing with a hardware-backed key (Secure Enclave).
signer = try SecureEnclaveMessageSigner()
} catch {
fatalError("Failed to initialize Secure Enclave: \(error). Use a physical device.")
}
self.messageSigner = signer
self.store = fileStore
// EncryptedStorageClient is the app's own implementation of the SDK's StorageClient
// interface, one per algorithm (ECDSA / EdDSA).
self.ecdsaStorage = EncryptedStorageClient(store: fileStore, algorithm: .ecdsa)
self.eddsaStorage = EncryptedStorageClient(store: fileStore, algorithm: .eddsa)
}
private func createWebsocketConfig() -> WebsocketConfig {
WebsocketConfig(url: Self.demoServerUrl, port: 443, isSecure: true)
}
// One TrioSession per algorithm, each bound to the message signer, the cloud
// verifying key, the websocket config, and its storage client.
private func getEcdsaSession() -> TrioSession {
if let session = ecdsaSession { return session }
let session = SilentShard.ECDSA.trioInitiator(
messageSigner: messageSigner,
cloudVerifyingKey: Self.cloudVerifyingKey,
websocketConfig: createWebsocketConfig(),
storageClient: ecdsaStorage
)
ecdsaSession = session
return session
}
private func getEddsaSession() -> TrioSession {
if let session = eddsaSession { return session }
let session = SilentShard.EdDSA.trioInitiator(
messageSigner: messageSigner,
cloudVerifyingKey: Self.cloudVerifyingKey,
websocketConfig: createWebsocketConfig(),
storageClient: eddsaStorage
)
eddsaSession = session
return session
}
SecureEnclaveMessageSigner and EncryptedStorageClient are not SDK types — they are the reference app's own implementations of the SDK's MessageSigner and StorageClient interfaces (Secure Enclave-backed P-256 signing and encrypted keyshare storage). Supply your own implementations, or clone the example-hub app to use these as-is.
Run the MPC operations
After creating the session, you can perform MPC operations.
Key Generation
Generate MPC keyshares with the keygen method. It returns a keyId (a String); the SDK persists the keyshare to your StorageClient and every later operation is addressed by that keyId. Here is how the reference app does it:
func keygen(type: KeyType) async throws -> KeygenResult {
log.info("Keygen started: \(type.rawValue)")
// sessionForKeyType(...) is this app's own helper (not an SDK method) — it returns the TrioSession
// we created earlier for this algorithm (ECDSA or EdDSA).
let session: TrioSession = sessionForKeyType(type)
// keygen() is the SDK call: runs the MPC protocol, persists the keyshare to your
// StorageClient, and returns the keyId that addresses it.
let keyId = try await session.keygen().get()
let publicKey = try await extractPublicKey(keyId: keyId)
log.info("Keygen completed: keyId=\(keyId), pubKey=\(publicKey.count) bytes")
return KeygenResult(keyId: keyId, publicKey: publicKey)
}
Signature Generation
Sign a message using the sign method, passing the keyId returned from keygen:
func sign(keyId: String, message: Data, derivationPath: String) async throws -> Data {
log.info("Sign started: keyId=\(keyId), msg=\(message.count) bytes")
let record = try loadRecord(keyId: keyId)
let messageHex = message.map { String(format: "%02x", $0) }.joined()
// sessionForKeyType(...) is this app's own helper (not an SDK method) — it returns the TrioSession
// we created earlier for this key's algorithm (the stored record's keyType).
let session: TrioSession = sessionForKeyType(record.keyType)
// sign() is the SDK call: it produces the threshold signature for the key addressed by keyId.
let sig = try await session.sign(keyId: keyId, message: messageHex, derivationPath: derivationPath).get()
log.info("Sign completed: \(sig.count) bytes")
return sig
}
The SecureEnclaveMessageSigner, EncryptedStorageClient, and WebSocket client shown are the reference app's implementations — hence for reference only, not a recommendation. Provide your own for production.
Setup your own app
Prefer to wire the SDK into your own app instead of the reference project? Create a new Xcode project by following the official guide (or use an existing one), then add the SilentShard dependency.
Dependency Installation
Step 1: Create Package URL
- Get access to the repository https://github.com/silence-laboratories/silent-shard-artifacts from the Silence Laboratories team.
- Get the package URL
- Add GitHub account : Skip this step if you already have added your GitHub account in Xcode. You can add your GitHub account by following the steps ( only until it adds your GitHub account).
- Final package URL: https://github.com/silence-laboratories/silent-shard-artifacts.
Step 2: Open Package(SPM) Collection Window
- In Xcode, open the Project Navigator.
- Select the project file (the root item in the navigator).
- In the Project Editor, select your project(Your Xcode Project title under
Projectsection). - Navigate to the Package Dependencies tab. See below

- Click the + icon (hint :Add Package Dependency) at the bottom of the Package Dependencies section.
- A dialog box will appear prompting you to enter a package URL.
Step 3: Add Package
- Copy the package URL (We get this from Step 2).
- Paste this URL into the
Search or Enter Package URLbox.
- Select the
silentshard-artifactson the left panel. - Click Add Package to proceed.
Step 4: Confirm and Add Package
- Xcode will fetch the package details.
- Add library
trioto your targets By clicking dropdown from the " Add to Target" items.
- Click Add Package to complete the installation.
With the SDK package added, wire it up the same way the reference app does — create a session, then run keygen and signing.