Keyring Controller

All the wallet management & Chain Interactions executing on the client side is managed by this class.

Create an instance

const keyring = new KeyringController({ 
    baseUrl: 'http://localhost:8000',
    walletType: {
        embedded: true, // for external wallet it should be false
        supportAa: true, // false if dapp only wants EOA wallets
    },
    sentryDns, // string
    environment, // ENV
    sessionSignatures, //[OPTIONAL] SESSION SIG FROM litController.initSession
    currentAccount, //[OPTIONAL] fetch PKPs FROM litController.fetchPKPs
    customAuthMethod,
    accessToken,
    aa,
    selectedWallet,
} as TriaArgs);

export type TriaArgs = {
  baseUrl: string;
  sentryDns?: string;
  walletType?: WalletType;
  selectedChainName?: ChainName;
  environment?: ENV;
  currentAccount?: IRelayPKP;
  sessionSignatures?: string;
  customAuthMethod?: LitCustomAuthMethod;
  accessToken?: string;
  aa?: AaDetails;
  selectedWallet?: "EOA" | "AA";
};

export type ENV = 'testnet' | 'mainnet-staging' | 'mainnet';

To maintain the integrity of the keyring object that stores decrypted vaults in memory, it is crucial to preserve its context. This implies that the keyring object should not be recreated, but rather instantiated only once.

Recreating the keyring object would lead to the loss of critical in-memory data, consequently preventing the user from performing any transaction signing. Therefore, it is imperative to avoid the recreation of this object at all costs.

Functions

Reconstruction of Vault

The ideal moment to invoke this method is immediately after a successful user login. This timing ensures that we have access to the user's password and pin, which are essential for decrypting and reconstructing the vault.

To ensure smooth functioning and optimal performance of the KeyringController, it is essential to call the following method as the first step before invoking any other methods. This method initializes the persist storage and in-memory data, laying the foundation for subsequent operations.

Additionally, it should be called only once during the application startup process. Repeated invocations of this method may result in unnecessary overhead, affecting efficiency.

reconstruct(password: string, pin: string): Promise<ReconstructResponse>;
// Example
const password = 'password';
const pin = '444444';
const data = await keyring.reconstruct(password, pin);
console.log(data);
interface ReconstructResponse {
  success: boolean
}

Social Login [v2]

async socialogin({
    triaName,
    password,
    platform,
    userId,
    isPasswordLess,
  }: {
    triaName: string;
    password: string;
    platform: string;
    userId: string;
    isPasswordLess: boolean;
  }): Promise<SocialLoginResponse>
interface SocialLoginResponse {
  success: boolean;
  data: any;
}

Create Account [v2]

async createAccount({ triaName, password }: { triaName: string; password: string }) 

Get Vault [v2]

async getVault({ triaName, password, userId,}: { triaName?: string; password: string; userId?: string; })

Add Wallet

 addWallet(username: string, password: string, pin: string, chainName: string): Promise<AddWalletResponse>;
// Example
await keyring.addWallet({username: "alex@tria", password:"password", pin:"444444", chainName:"ETH"});
export interface AddWalletResponse {
  list: UpdatedWalletInfoList
  success: boolean
}

interface UpdatedWalletInfoList extends Array<WalletInfo> { }
interface WalletInfo {
  creationMethod: CreationMethod;
  addresses: AddressList;
}
interface AddressList extends Array<Address> { }
interface Address {
  subname: Nullable<string>;
  address: string;
  isDeleted: Nullable<boolean>;
  chain: string;
}
enum CreationMethod {
  Onboarding = 1, // start from 1 not from zero, because it is falsy
  ManualCreation = 2,
  ManualImport = 3
}
type Nullable<T> = T | undefined | null;

Export Mnemonic

async exportMnemonic(password: string, pin: string): Promise<exportMnemonicResponse>
interface exportMnemonicResponse {
    success: boolean,
    mnemonic: string | null;
}

Export Private Key

async exportPrivateKey(triaName: string, password: string, pin: string, chainName: string): Promise<ExportPrivateKeyResponse>
interface ExportPrivateKeyResponse {
    success: boolean,
    privateKey: string | null;
}

Update SubName

async updateSubName({ newSubName, oldSubName, password, pin }: UpdateSubNameArgs) : Promise<UpdateSubNameResponse> 
interface UpdateSubNameArgs {
    password: string,
    pin: string,
    oldSubName: string,
    newSubName: string
}
interface UpdateSubNameResponse {
    message: string,
    success: boolean,
    vault: UpdatedPublicVault | null
}

Remove Address

async removeAddress({ subname, password, pin }: RemoveAddressArgs) : Promise<RemoveAddressResponse>
export interface RemoveAddressArgs {
    subname: string,
    password: string,
    pin: string
}
interface RemoveAddressResponse {
    message: string,
    success: boolean,
    vault: UpdatedPublicVault | null
}
  • For Choose Asset or Assets display

  • filter - chainNames - makes sense only when sending to a subName i.e. only available on one chain

  • triaName- for fetching userDoc (vault with public keys) from db

  • Available now for -

    [
      'ETH',
      'POLYGON',
      'AVALANCHE',
      'ARBITRUM',
      'BINANCE',
      'OPTIMISM',
      'FANTOM',
      'MOONBEAM',
      'BITCOIN'
    ];

Detect Logged in Account

detectLoggedInAccount();
Example implementation

Add this in auth.tria.so/detect and open this as a invisible iframe in the onboarding SDK to send events to the SDK, and read events with const {account} = useDetectAccount();

import { KeyringController } from '@tria-sdk/web';
import React, { useEffect } from 'react';
// import { baseUrl, embeddedWalletType } from '../utils/constants';
import { eventTypes, Account } from '@tria-sdk/connect';

const baseUrl = 'https://staging.tria.so';
const walletType = { embedded: true };

const Detect = () => {
  const detectAccount = async () => {
    const keyring = new KeyringController({
      baseUrl,
      walletType,
    });
    await keyring.init({});
    keyring.detectLoggedInAccount();
  };
  useEffect(() => {
    detectAccount();
  }, []);
  return <div>Detect</div>;
};

export default Detect;

Last updated