Using tKey JS SDK
Once you've installed all packages, and instantiated tKey instance in your constructor, you can use it to authenticate your users and generate their tKey shares. Further, you can use a variety of functions exposed by the tKey SDK and its modules to manage different aspects of your users' authentication needs.
We'll be talking in-depth about the following operations:
- Logging in the User
- Getting tKey Details
- Reconstructing User's Private Key
- Generating a new Share
- Deleting a Share
- Using Modules for Further Operations
- Making Blockchain Calls
TKey
Natively, the instance of tKey
, (ie. TKey
) returns many functions, however, we have documented a
few relevant ones here. You can check the table below for a list of all relevant functions, or the
class reference to checkout the full list of functions.
- Table
- Class Reference
Function | Description | Arguments | Return |
---|---|---|---|
initialize | Generates a Threshold Key corresponding to your login provider. | params?: TKeyInitArgs | KeyDetails |
reconstructKey | Reconstructs the user private key. Can only work if the minimum threshold of keys has reached | _reconstructKeyMiddleware?: boolean | ReconstructedKeyResult |
deleteShare | Delete a share details from metadata. The corresponding share won't be valid anymore. | shareIndex: BNString | DeleteShareResult |
getKeyDetails | Get the details of the keys present for the particular user. | void | KeyDetails |
generateNewShare | Generate a new share for the reconstructed private key. | void | GenerateNewShareResult |
inputShareStoreSafe | Input a share store into the tKey | shareStore: ShareStore, autoUpdateMetadata?: boolean | void |
outputShareStore | Output a share store from the tKey | shareIndex: BNString, polyID?: string | ShareStore |
addShareDescription | Add a description to a share | shareIndex: string, description: string, updateMetadata?: boolean | void |
deleteShareDescription | Delete a description from a share | shareIndex: string, description: string, updateMetadata?: boolean | void |
updateShareDescription | Update a description from a share | shareIndex: string, oldDescription: string, newDescription: string, updateMetadata?: boolean | void |
outputShare | Output a share | shareIndex: BNString, type?: string | unknown |
inputShare | Input a share | share: unknown, type?: string | void |
toJSON | Convert the tKey to JSON | void | StringifiedType |
declare class ThresholdKey implements ITKey {
modules: ModuleMap;
enableLogging: boolean;
serviceProvider: IServiceProvider;
storageLayer: IStorageLayer;
shares: ShareStorePolyIDShareIndexMap;
lastFetchedCloudMetadata: Metadata;
metadata: Metadata;
manualSync: boolean;
storeDeviceShare: (
deviceShareStore: ShareStore,
customDeviceInfo?: StringifiedType,
) => Promise<void>;
serverTimeOffset?: number;
private privKey;
private _ed25519Seed?;
constructor(args?: TKeyArgs);
get secp256k1Key(): BN | null;
get ed25519Key(): Buffer | null;
private set secp256k1Key(value);
private set ed25519Key(value);
static fromJSON(value: StringifiedType, args: TKeyArgs): Promise<ThresholdKey>;
getStorageLayer(): IStorageLayer;
getMetadata(): IMetadata;
initialize(params?: TKeyInitArgs): Promise<KeyDetails>;
/**
* catchupToLatestShare recursively loops fetches metadata of the provided share and checks if there is an encrypted share for it.
* @param shareStore - share to start of with
* @param polyID - if specified, polyID to refresh to if it exists
*/
catchupToLatestShare(params: {
shareStore: ShareStore;
polyID?: PolynomialID;
includeLocalMetadataTransitions?: boolean;
}): Promise<CatchupToLatestShareResult>;
reconstructKey(_reconstructKeyMiddleware?: boolean): Promise<ReconstructedKeyResult>;
reconstructLatestPoly(): Polynomial;
deleteShare(shareIndex: BNString): Promise<DeleteShareResult>;
generateNewShare(): Promise<GenerateNewShareResult>;
getEd25519PublicKey(): string | undefined;
retrieveEd25519Seed(): Promise<Buffer>;
addLocalMetadataTransitions(params: {
input: LocalTransitionData;
serviceProvider?: IServiceProvider;
privKey?: BN[];
acquireLock?: boolean;
}): Promise<void>;
syncLocalMetadataTransitions(): Promise<void>;
readMetadata<T>(privKey: BN): Promise<T>;
updateSDK(params?: { withShare?: ShareStore }): Promise<ThresholdKey>;
inputShareStore(shareStore: ShareStore): void;
inputShareStoreSafe(shareStore: ShareStore, autoUpdateMetadata?: boolean): Promise<void>;
outputShareStore(shareIndex: BNString, polyID?: string): ShareStore;
getCurrentShareIndexes(): string[];
getKeyDetails(): KeyDetails;
generateAuthMetadata(params: { input: Metadata[] }): AuthMetadata[];
setAuthMetadata(params: {
input: Metadata;
serviceProvider?: IServiceProvider;
privKey?: BN;
}): Promise<{
message: string;
}>;
setAuthMetadataBulk(params: {
input: Metadata[];
serviceProvider?: IServiceProvider;
privKey?: BN[];
}): Promise<void>;
getAuthMetadata(params: {
serviceProvider?: IServiceProvider;
privKey?: BN;
includeLocalMetadataTransitions?: boolean;
}): Promise<Metadata>;
getGenericMetadataWithTransitionStates(params: {
fromJSONConstructor: FromJSONConstructor;
serviceProvider?: IServiceProvider;
privKey?: BN;
includeLocalMetadataTransitions?: boolean;
_localMetadataTransitions?: LocalMetadataTransitions;
}): Promise<unknown>;
acquireWriteMetadataLock(): Promise<number>;
releaseWriteMetadataLock(): Promise<void>;
syncMultipleShareMetadata(
shares: BN[],
adjustScopedStore?: (ss: unknown) => unknown,
): Promise<void>;
addShareDescription(
shareIndex: string,
description: string,
updateMetadata?: boolean,
): Promise<void>;
deleteShareDescription(
shareIndex: string,
description: string,
updateMetadata?: boolean,
): Promise<void>;
updateShareDescription(
shareIndex: string,
oldDescription: string,
newDescription: string,
updateMetadata?: boolean,
): Promise<void>;
encrypt(data: Buffer): Promise<EncryptedMessage>;
decrypt(encryptedMessage: EncryptedMessage): Promise<Buffer>;
getTKeyStore(moduleName: string): Promise<TkeyStoreItemType[]>;
getTKeyStoreItem(moduleName: string, id: string): Promise<TkeyStoreItemType>;
outputShare(shareIndex: BNString, type?: string): Promise<unknown>;
inputShare(share: unknown, type?: string): Promise<void>;
toJSON(): StringifiedType;
getAllShareStoresForLatestPolynomial(): ShareStore[];
CRITICAL_deleteTkey(): Promise<void>;
}
Log In
The login with the tKey SDK is a 3-step process.
- Login using your desired login provider and get their OAuth Id Token
- Use the OAuth ID Token to connect to the Web3Auth Service Provider to generate the OAuth Key
- Once the OAuth Key is generated, initialize the tKey Instance
However, before starting this process, you need to set up Custom Authentication on your Web3Auth Dashboard. For this, you need to Create a Verifier within the Web3Auth Developer Dashboard with your desired configuration.
If you want to know more about setting up a verifier and how to use it, please refer to the Auth Provider Setup Documentation.
Login using OAuth
You can choose any OAuth Provider of your choice and login using their standard process. You can check out our examples where we have used the most common OAuth providers like Google, Auth0, Firebase etc. Additionally, you can checkout our documentation around OAuth Provider setup here.
If you prefer using an implicit login method with your OAuth Provider, you can do so by using the
TorusServiceProvider
. You can check out the
additional reading section for more information. This provider
doesn't work in a React Native environment.
Generating OAuth Key
This setup helps you generate a private key which will be needed by the tKey Instance to generate
the OAuth Share. This is done by calling the connect()
function within the tKey
instance's
serviceProvider
.
tKeyInstance.serviceProvider.connect(params: LoginParams): Promise<BN>;
LoginParams
- Table
- Type Declarations
Parameter | Description |
---|---|
verifier | Name of the verifier. It's a mandatory parameter as a string. |
verifierId | Verifier ID's value, sub or email value present in the idToken. It's a mandatory parameter as a string. |
idToken | A newly created JWT Token that has not already been sent to Web3Auth or a Duplicate Token error will be thrown. It's a mandatory parameter as a string. |
subVerifierInfoArray? | Sub verifier info. It's an optional parameter as a TorusSubVerifierInfo[]. |
serverTimeOffset? | Server time offset. It's an optional parameter as a number. |
export type LoginParams = {
verifier: string;
verifierId: string;
idToken: string;
subVerifierInfoArray?: TorusSubVerifierInfo[];
serverTimeOffset?: number;
};
Usage
const OAuthShareKey = await(tKeyInstance.serviceProvider as SfaServiceProvider).connect({
verifier,
verifierId,
idToken,
});
Initializing tKey
initialize(params?: TKeyInitArgs)
Once you have triggered the login process, you're ready to initialize the tKey. This will generate a Threshold Key corresponding to your login provider.
Parameters
The initialize
function accepts the following optional parameters:
- Table
- Type Declaration
Parameter | Description |
---|---|
withShare? | Initializes tKey with an existing share store. This allows you to directly initialize tKey without using the service provider login. |
importKey? | Imports a SEC1 key into tKey for initialization. |
importEd25519Seed? | Imports a Ed25519 seed into tKey for initialization. |
neverInitializeNewKey? | Never initialize using a new key if the shares are already formed |
transitionMetadata? | If transition metadata has been provided, it uses that as the current metadata instead of maintaining state before and after serialization. |
previouslyFetchedCloudMetadata? | Pass the previous cloud metadata |
previousLocalMetadataTransitions? | Pass the previous transition metadata |
delete1OutOf1? | If true, deletes the SFA and Custom Auth key, once it's imported into tKey. |
export type TKeyInitArgs = {
withShare?: ShareStore;
importKey?: BN;
importEd25519Seed?: Buffer;
neverInitializeNewKey?: boolean;
transitionMetadata?: IMetadata;
previouslyFetchedCloudMetadata?: IMetadata;
previousLocalMetadataTransitions?: LocalMetadataTransitions;
delete1OutOf1?: boolean;
};
Example
try {
// Login with Firebase
const loginRes = await signInWithGoogle();
// Get the id token from Firebase
const idToken = await loginRes.user.getIdToken(true);
const userInfo = parseToken(idToken);
await(tKey.serviceProvider as SfaServiceProvider).connect({
verifier,
verifierId: userInfo.sub,
idToken,
});
await tKey.initialize();
} catch (error) {
// Handle error
}
Get tKey Details
tKey.getKeyDetails()
The function getKeyDetails()
returns the details of the keys generated for the specific user. This
includes the public key X & Y of the user, alongside the shares details and the threshold.
Sample Key Details Return
{
"pubKey": {
"x": "a4f269df921cb49e120b4de6f2ecaf7fcfdded222f1f64578e953b9a7249e39c",
"y": "c2880cb79167feeea07a4665a5f0b27423008c42feb2879192f2449fbf1b0ac1"
},
"ed25519PublicKey": "0462c79c5d79186905909d65f0fcc370866349fd9734e52bebfd954816d186aad871e6f49ce879615a21088ec08338e5982e578181ffa914279206a39ce857e575",
"requiredShares": -1,
"threshold": 2,
"totalShares": 3,
"shareDescriptions": {
"c4dde5c2db59f3df601f1c76eadbdbfb93b5d02f81f6c95046b419934e8e9919": [
"{\"module\":\"webStorage\",\"userAgent\":\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36\",\"dateAdded\":1720176834113}"
],
"9c1466871b8a230039a0184b0bdcb1ff18440e294199bc841242b8660279bb96": [
"{\"module\":\"webStorage\",\"userAgent\":\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36\",\"dateAdded\":1720176838803}"
]
}
};
From here, you can know whether the user key can be reconstructed or not.
- If the
requiredShares
is greater than 0, then the key cannot be reconstructed, because this means that the user has not yet generated enough shares to meet the threshold. - Once the
requiredShares
is 0 or less than that, then the key can be reconstructed, and the user can use the shares to generate the private key and make further operations on the tKey and manipulate their keys.
const { requiredShares } = tKey.getKeyDetails();
if (requiredShares <= 0) {
console.log(
"All shares are present, you can reconstruct your private key and do operations on the tKey",
);
} else {
console.log("You need to generate more shares to reconstruct your private key");
}
Reconstruct Private Key
tKey.reconstructKey()
The function reconstructKey()
reconstructs the private key of the user from the shares generated.
This function returns the private key of the user once the threshold has been met.
reconstructKey(_reconstructKeyMiddleware?: boolean): Promise<ReconstructedKeyResult>;
export type ReconstructedKeyResult = {
secp256k1Key: BN;
ed25519Seed?: Buffer;
seedPhrase?: BN[];
allKeys?: BN[];
};;
const { requiredShares } = tKey.getKeyDetails();
if (requiredShares <= 0) {
const reconstructedKeyResult = await tKey.reconstructKey();
const privateKey = reconstructedKeyResult?.secp256k1Key.toString("hex");
console.log("Private Key: ", privateKey);
}
Generate a New Share
tKey.generateNewShare()
The function generateNewShare()
generates a new share on the same threshold set by the user. This
function returns the new share generated.
generateNewShare(): Promise<GenerateNewShareResult>;
export type GenerateNewShareResult = {
newShareStores: ShareStoreMap;
newShareIndex: BN;
};
const generateShareResult = await tKey.generateNewShare();
const share = await tKey.outputShareStore(generateShareResult.newShareIndex);
await(tKey.modules.webStorage as WebStorageModule).storeDeviceShare(share);
console.log("New Share Stored on the Browser Local Storage: ", share);
Delete a Share
tKey.deleteShare(shareIndex: BNString)
The function deleteShare()
deletes the user's given share. This function returns the updated
shareStore after the share has been deleted.
deleteShare(shareIndex: BNString): Promise<DeleteShareResult>;
export type DeleteShareResult = {
newShareStores: ShareStoreMap;
};
const shareStore = await tKey.deleteShare(previousShareIndex);
console.log("Share has been deleted", shareStore);
Using Modules
For making advanced operations on tKey and to manipulate the keys, you can use the modules provided by tKey. As mentioned in the initialisation section, you need to configure the modules beforehand to make it work with tKey. Once that is done, the instance of the respective module is available within your tKey instance and can be used for further operations.
Checkout the Modules section where we have listed all the available modules alongside the functions that can be used within them.
Making Blockchain Calls
Once you have generated the private key, you can use it to make blockchain calls. The key generated
by tKey is of type secp256k1
, which is compatible with EVM-based blockchains like Ethereum,
Polygon, and many others that use the same curve. From v13, tKey also generates a ed25519
key
which is compatible with blockchains like Solana, Aptos, and etc. However, you can also convert
secp256k1
key into other curves and utilize it.
In addition to that, we have dedicated provider packages for EVM, Solana and XRPL libraries. You can check out their respective documentation in the Providers Section.
You can checkout our Connect Blockchain documentation which has a detailed guide on how to connect to major blockchains out there.