The client library for Silent Network Wallet Provider Service.
npm i @silencelaboratories/walletprovider-sdk
We provide simple demo-page what showcases the features of this SDK. Check the demo for a quick start guide.
For description of classes, interfaces, types, please refer to documentation.
Requests to the network can be authenticated by the User, using Externally Owned Account (EOA), by Passkeys, some of the requests, by session keys (also known as ephemeral keys).
The authentication can be required, or not, depending on the version of Silent Network backend.
In no-authentication case It's backend responsibility to authenticate the User, and then forward the request to the Silent Network nodes.
For more information, please read Types of architectures in our high-level documentation.
This SDK supports both versions of Silent Network, no-authentication, and where User authentication is required.
The core object to use is the NetworkSigner. It allows to send requests to the Silent Network.
The request goes to the backend, without any sort of User authentication.
Use the NoAuthWalletProviderServiceClient with the Network Signer.
During keygen provide number of parties n, the threshold t and types of the keys you want to generate.
const wpClient = new NoAuthWalletProviderServiceClient(selectedWpProvider);
const sdk = new NetworkSigner(wpClient);
const response = await sdk.generateKey(
config.threshold,
config.parties,
keySignAlgs,
);
The message to be signed can be of different types. The example usage of different types is shown here.
const wpClient = new NoAuthWalletProviderServiceClient(selectedWpProvider);
const sdk = new NetworkSigner(wpClient);
let sample_message = ...;
const response = await sdk.signMessage(
config.threshold,
config.keyId,
config.signAlg,
sample_message,
);
The full working example is in the demo.
In order to create your keys, you need two other components. The WalletProviderServiceClient that connects to the Backend part of the SDK, and the authenticator module.
We provide EOA authentication via EOAAuth module. Let's create the NetworkSigner with associated EOAAuth object.
// Create Client to the network
const wpClient = createWalletProviderService(clusterConfig);
// Authenticate using EOA
const eoaAuth = new EOAAuth(accountsFromBrowserWallet[0], new BrowserWallet());
// Create a new signer instance
const sdk = new NetworkSigner(wpClient, eoaAuth);
// Generate new eph key
const selectedEphSignAlg = 'secp256k1'; // Signing algorithm of ephemeral key
const sk = generateEphPrivateKey(selectedEphSignAlg);
const ephPK = getEphPublicKey(sk, selectedEphSignAlg);
const ephId = uuidv4();
const ephClaim = new EphKeyClaim(ephId, ephPK, selectedEphSignAlg, expireAt(60 * 60));
Now you can generate a key, using the generateKey method. The method accepts optional permissions. No permissions means allow all operations.
const permissions = {
permissions: [
{
type: 'erc20',
method: 'approve',
to: '0x1234567890123456789012345678901234567890',
args: {
spender: '0x1234567890123456789012345678901234567890',
value: 10000,
eq: '<',
},
},
],
};
let signAlgs = ['secp256k1', 'ed25519'];
// Generate keys for secp256k1, ed25519, and include ephemeral key, permissions in the request
let resp: KeygenResponse[] = await sdk.generateKey(+threshold, +partiesNumber, signAlgs, ephClaim, permissions);
Calling this method will cause to the Digital Wallet window to pop up, requesting the User to sign the request.
The returned response KeygenResponse[] is a list of DKG results, each contains keyId, publicKey and signAlg. The publicKey is the public part of the key generated by Silent Network. The signAlg is the sign algorithm of the MPC key. Use the keyId in subsequent calls to sign.
The ephemeral sk key can be later used in subsequent signgen requests for authenticating.
First, we need to register user passkey to the network.
const wpClient = createWalletProviderService(clusterConfig);
const rpConfig: RelyingPartyConfig = {
rpId: clusterConfig.rpConfig.rpId,
rpName: clusterConfig.rpConfig.rpName,
};
userId = newUser();
const passkeyUser = {
id: userId,
displayName: 'Alice',
name: 'alice@gmail.com ' + userId, // For development purposes
};
const passkeyAuth = new PasskeyRegister(rpConfig, passkeyUser);
// Create a new signer instance
const sdk = new NetworkSigner(wpClient, passkeyAuth);
// Generate a new key
let resp: RegisterPasskeyResponse = await sdk.registerPasskey();
We provide Passkey login authentication via PasskeyAuth module. Let's create the NetworkSigner with associated PasskeyAuth object.
// Create a new signer instance
const sdk = new NetworkSigner(wpClient, passkeyAuth);
const credentialId = getPasskeyCredentialId();
if (!credentialId) {
throw new Error('Must register passkey first');
}
const passkeyAuth = new PasskeyAuth(
rpConfig,
credentialId,
);
// Create a new signer instance
const sdk = new NetworkSigner(wpClient, passkeyAuth);
// Generate a new key
const sk = generateEphPrivateKey(selectedEphSignAlg);
const ephPK = getEphPublicKey(sk, selectedEphSignAlg);
const ephId = uuidv4();
const ephClaim = new EphKeyClaim(ephId, ephPK, selectedEphSignAlg, expireAt(60 * 60));
let resp: KeygenResponse[] = await sdk.generateKey(+threshold, +partiesNumber, signAlgs, ephClaim, permissions);
Now you can generate a key like in the EOA example by calling the generateKey method.
Calling this method will prompt the device to request Passkey User Verification. Once user verification is done, the KeygenResponse is returned.
The sk key can be later used in subsequent signgen requests.
The full signing example is here.
The workflow is similar to the keygen process. The core objects to use are the NetworkSigner, WalletProviderServiceClient, and the ephemeral authenticator module.
const authModule = new EphAuth(selectedEphId, ephSK, selectedEphSignAlg);
// Create a new signer instance
const sdk = new NetworkSigner(wpClient, authModule);
Use the SignRequestBuilder builder to generate the sign message payload. Then call the signMessage method to run the signing process.
const signMessage = new SignRequestBuilder()
.setRequest(
uuidv4(),
JSON.stringify({
userOperation: {
sender: '0x8d4cb2540d993fe34c646299f1ab4af3012ff34c',
nonce: '0x7',
initCode: '0x',
callData: '0000...',
callGasLimit: '0x18473',
verificationGasLimit: '0x18473',
preVerificationGas: '66768',
maxFeePerGas: '',
maxPriorityFeePerGas: '',
paymasterAndData: '0x',
},
entryPointVersion: 'v0.6.0',
entryPointAddress: '0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789',
chainId: 80002,
}),
'accountAbstractionTx',
)
.setRequest(
uuidv4(),
'4549502d313931206d657373616765',
'rawBytes',
)
.build();
let resp = await sdk.signMessage( threshold, selectedKeyId, signMessage);
The SignResponse contains the signature sign, the recovery ID recid and the transaction ID transactionId.
The full key refresh example is here.
The workflow is similar to the keygen process.
const algSign = 'secp256k1'; // Signing algorithms of ephemeral key
// Create EOA authenticator
const eoaAuth = new EOAAuth(
accountsFromBrowserWallet[0],
new BrowserWallet(),
);
// Create a client that connects to the backend service
const wpClient = await createWalletProviderService(clusterConfig);
// Create a new signer instance
const sdk = new NetworkSigner(wpClient, eoaAuth);
Now you can refresh the key (before doing this, make sure you've already generated the key), using the refreshKey method.
// Refresh the key
let resp: KeyRefreshResponse = await sdk.refreshKey(+threshold, selectedKeyId, mpcKeySignAlg);
The returned response KeyRefreshResponse contains keyId, publicKey and signAlg of the refreshed MPC key.
npm i
npm run build
The output will be in the dist folder.
Please refer to README.md for instructions how to execute them.
npm run docs
./local_ci.sh