@kalp_studio/tresori-sdk-js
v1.2.1
Published
The TreSori SDK provides a unified, high-level API for blockchain wallet operations. It supports three distinct wallet types to accommodate various security models and use cases:
Downloads
406
Readme
TreSori SDK
Overview
The TreSori SDK provides a unified, high-level API for blockchain wallet operations. It supports three distinct wallet types to accommodate various security models and use cases:
- Self-Custodial: Full user control with local key management
- Custodial: Service-managed wallets linked to user accounts
- MPC: Enhanced security through distributed key shards with verification flows
Table of Contents
Features
Self-Custodial Wallets
| Feature | Description | | -------------------------- | ---------------------------------------------------------------- | | Mnemonic Generation | Generate BIP39-compliant mnemonic phrases (12/15/18/21/24 words) | | Wallet Creation | Create wallets from mnemonic with blockchain registration | | Mnemonic Import | Restore wallets from existing mnemonic phrases | | Private Key Import | Import wallets directly from private keys | | Token Transfers | Transfer native tokens (ETH, MATIC, etc.) | | Smart Contract Interaction | Sign and send contract transactions |
Custodial Wallets
| Feature | Description | | --------------------------- | ------------------------------------------------ | | Managed Wallet Creation | Create server-managed wallets linked to user IDs | | Token Transfers | Transfer native and ERC-20 tokens | | Smart Contract Transactions | Execute contract write operations |
MPC Wallets
| Feature | Description |
| -------------------------- | ------------------------------------------------------------------------------------------------------------- |
| Email / phone verification | OTP flows; after verify you receive session data for MPC signing |
| Native & ERC-20 transfers | Sign and broadcast via chain RPC using clientShare, sessionId, rpcUrl |
| Gasless ERC-20 (optional) | When the project has gasless enabled, transferMpcTokens with a token address uses permit + relay (EIP-2612) |
| Smart contract writes | Encode locally, MPC sign-simple, broadcast raw tx on your rpcUrl |
Multi-Chain Support
- Dynamic chain configuration loaded at runtime
- Support for multiple EVM-compatible networks
- Chain-specific parameters (chain ID, explorer URL, currency)
Installation
Published package name (see package.json):
npm install @kalp_studio/tresori-sdk-jsOr with yarn:
yarn add @kalp_studio/tresori-sdk-jsThe package is ESM-only ("type": "module"). Use in Node.js (14+) or in bundlers (Vite, webpack, Metro, etc.).
The SDK lists @noble/hashes, @noble/ciphers, and related @noble/* packages for MPC DKG (ECDH, SHA-256, AES-256-GCM in pure JS, so React Native does not need crypto.subtle for that path).
The example and example-rn apps in this repo depend on the local package as tresori-sdk-js (file:..); their imports use that name. Published apps should import @kalp_studio/tresori-sdk-js as shown above.
React Native
The SDK works in React Native (iOS and Android). The library does not use DOM-only APIs in its published code.
MPC email flow (new vs returning user)
For sendEmailVerificationRequest and verifyEmail, the SDK calls POST /auth/is-mpc-exist with blockchain, network (mapped from your selected chain), and walletIdentifier (email is trimmed and lowercased before server calls). It sets the internal new-user flag to !isMPCExists, then sends/verifies the OTP with the correct backend shape. You do not pass isNewUser on these methods. If the wallet already exists, verify follows the returning-user path (no DKG). If DKG runs for a new user and fails (e.g. missing crypto.getRandomValues on React Native), the SDK returns the raw verify body and logs a console.warn with the error.
Cryptography (MPC DKG on React Native)
MPC DKG: ECDH and SHA-256 use @noble/curves / @noble/hashes. AES-256-GCM uses @noble/ciphers inside the SDK (pure JavaScript) — you do not need react-native-webcrypto or crypto.subtle. UTF-8 for MPC payloads uses ethers’s toUtf8Bytes / toUtf8String so you do not need global TextDecoder / TextEncoder (Hermes often omits TextDecoder, which previously broke dkg-init after email verify).
Secure random: AES-GCM IVs use crypto.getRandomValues. On React Native you must load react-native-get-random-values once at app entry (Android and iOS). That is the standard, maintained polyfill used across the ecosystem (including with ethers).
Dependencies in your React Native app
npm install react-native-get-random-valuesPolyfills at app entry (before any other imports)
In your very first entry file (e.g. index.js), run:
import 'react-native-get-random-values';This repo’s example-rn does this in polyfills.ts, imported first from index.js.
(Optional) Register ethers secure random
If you use react-native-quick-crypto for performance, you can register it with ethers so mnemonic/key generation uses native bytes (unrelated to MPC AES, which stays in @noble/ciphers):
import crypto from 'react-native-quick-crypto';
import { randomBytes } from 'ethers';
randomBytes.register((length) => new Uint8Array(crypto.randomBytes(length)));Use the SDK as on web
import { TreSoriImpl, ChainListInstance } from '@kalp_studio/tresori-sdk-js';
await TreSoriImpl.instance.initialize(API_KEY);
// Chains are loaded by initialize()
const chain = ChainListInstance.all[0];
// Self-custodial, custodial, MPC APIs are unchanged.React Native summary
- Load
react-native-get-random-valuesat entry on Android and iOS socrypto.getRandomValuesexists. - No
react-native-webcryptois required for TreSori MPC DKG. - Phone MPC still requires an explicit
isNewUserflag (nois-mpc-existwiring in the SDK for phone yet).
Quick Start
import { TreSori, ChainListInstance } from '@kalp_studio/tresori-sdk-js';
async function main() {
// 1. Initialize the SDK with your API key
await TreSori().initialize('YOUR_API_KEY');
// 2. Generate a mnemonic phrase
const mnemonic = TreSori().generateMnemonic();
console.log('Mnemonic:', mnemonic);
// 3. Get a chain (after initialize, chains are loaded)
const selectedChain = ChainListInstance.all[0];
// 4. Create a wallet
const wallet = await TreSori().createWallet({
chain: selectedChain,
mnemonic,
userId: 'user_123',
});
console.log('Address:', wallet.address);
console.log('Private Key:', wallet.privateKey);
}
main().catch(console.error);API Reference
Initialization
initialize(apiKey: string): Promise<void>
Initializes the SDK with your API key. Must be called before any other operations. Loads supported chains from the backend.
await TreSori().initialize('YOUR_API_KEY');| Parameter | Type | Required | Description | | --------- | ------ | -------- | -------------------- | | apiKey | string | ✅ | Your TreSori API key |
Throws: Error if the API key is empty.
get mpcGaslessEnabled(): boolean
Read-only flag: true when the backend enabled-chains response includes gasless for the project (cached when initialize runs, and refreshed via Config when available). Use it to show or hide gasless ERC-20 UI. Actual gasless transfers still require an EIP-2612–compatible token and the arguments described under transferMpcTokens below.
await TreSori().initialize('YOUR_API_KEY');
if (TreSori().mpcGaslessEnabled) {
// Offer gasless ERC-20 path (see transferMpcTokens)
}Self-Custodial Wallet
generateMnemonic(opts?: { wordCount?: number }): string
Generates a BIP39-compliant mnemonic phrase.
// Generate 12-word mnemonic (default)
const mnemonic12 = TreSori().generateMnemonic();
// Generate 24-word mnemonic
const mnemonic24 = TreSori().generateMnemonic({ wordCount: 24 });| Parameter | Type | Default | Description | | -------------- | ------ | ------- | --------------------------------------- | | opts.wordCount | number | 12 | Number of words (12, 15, 18, 21, or 24) |
Returns: string — Space-separated mnemonic phrase
createWallet(args: { chain, mnemonic, userId }): Promise<object>
Creates a new wallet and registers it with the backend.
const result = await TreSori().createWallet({
chain: selectedChain,
mnemonic: 'word1 word2 word3 ... word12',
userId: 'unique_user_id',
});
console.log('Address:', result.address);
console.log('Private Key:', result.privateKey);
console.log('Mnemonic:', result.mnemonic);| Parameter | Type | Required | Description | | --------- | ------ | -------- | ------------------------- | | chain | Chain | ✅ | Target blockchain network | | mnemonic | string | ✅ | BIP39 mnemonic phrase | | userId | string | ✅ | Unique user identifier |
Returns: Promise<object>
{
mnemonic: string,
privateKey: string,
address: string,
userId: string,
}importWalletFromMnemonic(mnemonic: string): object
Imports an existing wallet from a mnemonic phrase.
const result = TreSori().importWalletFromMnemonic(
'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about',
);
console.log('Address:', result.address);
console.log('Private Key:', result.privateKey);| Parameter | Type | Required | Description | | --------- | ------ | -------- | --------------------------- | | mnemonic | string | ✅ | Valid BIP39 mnemonic phrase |
Returns: object
{
privateKey: string,
address: string,
}importWalletFromPrivateKey(privateKey: string): object
Imports a wallet from a private key.
const result = TreSori().importWalletFromPrivateKey(
'0x4c0883a69102937d6231471b5dbb6204fe5129617082792ae468d01a3f362318',
);
console.log('Address:', result.address);| Parameter | Type | Required | Description | | ---------- | ------ | -------- | --------------------------------------------------- | | privateKey | string | ✅ | Hex-encoded private key (with or without 0x prefix) |
Returns: object
{
privateKey: string,
address: string,
}transferTokens(args): Promise<string>
Transfers native tokens (ETH, MATIC, etc.) to a recipient address.
const txHash = await TreSori().transferTokens({
chain: selectedChain,
privateKey: '0x...',
toAddress: '0xRecipientAddress',
amount: '1', // in ether (e.g. 1 ETH); uses ethers parseEther
rpcUrl: 'https://rpc.example.com',
});
console.log('Transaction Hash:', txHash);| Parameter | Type | Required | Description | | ---------- | ------ | -------- | ------------------------------------ | | chain | Chain | ✅ | Target blockchain network | | privateKey | string | ✅ | Sender's private key | | toAddress | string | ✅ | Recipient's wallet address | | amount | string | ✅ | Amount in ether (e.g. "1" for 1 ETH) | | rpcUrl | string | ✅ | RPC endpoint URL |
Returns: Promise<string> — Transaction hash
signContractTransaction(args): Promise<string>
Signs and sends a smart contract transaction.
const txHash = await TreSori().signContractTransaction({
chain: selectedChain,
privateKey: '0x...',
contractAddress: '0xContractAddress',
contractAbi: [...],
functionName: 'transfer',
parameters: ['0xRecipient', 1000],
transaction: { value: 0n, maxGas: 100000n, ... },
rpcUrl: 'https://rpc.example.com',
});| Parameter | Type | Required | Description |
| --------------- | ------------------------ | -------- | --------------------------------------------------------------------------------- |
| chain | Chain | ✅ | Target blockchain network |
| privateKey | string | ✅ | Sender's private key |
| contractAddress | string | ✅ | Deployed contract address |
| contractAbi | ContractInterface | any | ✅ | Contract ABI (ethers-compatible) |
| functionName | string | ✅ | Contract function to call |
| parameters | any[] | No | Function parameters |
| transaction | object | ✅ | Ethers TransactionRequest fields; use {} to let the wallet fill gas and nonce |
| rpcUrl | string | ✅ | RPC endpoint URL |
Returns: Promise<string> — Transaction hash
Custodial Wallet
createCustodialWallet(args: { chain, userId }): Promise<object>
Creates a service-managed custodial wallet.
const result = await TreSori().createCustodialWallet({
chain: selectedChain,
userId: 'unique_user_id',
});
console.log('Custodial Address:', result.address);| Parameter | Type | Required | Description | | --------- | ------ | -------- | ------------------------- | | chain | Chain | ✅ | Target blockchain network | | userId | string | ✅ | Unique user identifier |
Returns: Promise<object> — Wallet details including address
transferCustodialTokens(args): Promise<object>
Transfers tokens from a custodial wallet.
const result = await TreSori().transferCustodialTokens({
fromAddress: '0xCustodialWalletAddress',
toAddress: '0xRecipientAddress',
amount: '1000000000000000000', // 1 token in wei
chain: selectedChain,
tokenAddress: '0xTokenContractAddress', // Optional: for ERC-20 tokens
});| Parameter | Type | Required | Description | | ------------ | ------ | -------- | ----------------------------------------------- | | fromAddress | string | ✅ | Custodial wallet address | | toAddress | string | ✅ | Recipient address | | amount | string | ✅ | Amount in wei (as string) | | chain | Chain | ✅ | Target blockchain network | | tokenAddress | string | No | ERC-20 token contract address (omit for native) |
Returns: Promise<object> — Transaction response
writeCustodialSmartContractTransaction(args): Promise<object>
Executes a smart contract write operation from a custodial wallet.
const result = await TreSori().writeCustodialSmartContractTransaction({
contractAddress: '0xContractAddress',
functionName: 'transfer',
parameters: ['0xRecipient', 1000],
contractAbi: [...],
fromAddress: '0xCustodialWalletAddress',
chain: selectedChain,
});| Parameter | Type | Required | Description | | --------------- | ------ | -------- | ------------------------- | | contractAddress | string | ✅ | Deployed contract address | | functionName | string | ✅ | Contract function to call | | parameters | any[] | ✅ | Function parameters | | contractAbi | any[] | ✅ | Contract ABI as array | | fromAddress | string | ✅ | Custodial wallet address | | chain | Chain | ✅ | Target blockchain network |
Returns: Promise<object> — Transaction response
MPC Wallet
isMpcExist(args): Promise<object>
Checks whether an MPC wallet already exists for a chain + identifier (typically the same email you use for OTP).
const { isMPCExists, mpcExistRequest } = await TreSori().isMpcExist({
chain: selectedChain,
walletIdentifier: '[email protected]',
});| Parameter | Type | Required | Description |
| ---------------- | ------ | -------- | ---------------------------------------------------------- |
| chain | Chain | ✅ | Target chain (blockchain / network mapped for the API) |
| walletIdentifier | string | ✅ | e.g. email address |
Returns: isMPCExists (boolean) and mpcExistRequest — the { blockchain, network, walletIdentifier } body sent to /auth/is-mpc-exist (useful for logging).
Email Verification
sendEmailVerificationRequest(args): Promise<object>
Calls isMpcExist with walletIdentifier = trimmed email, then sends the OTP with the correct new-user vs returning-user payload. chain selects blockchain / network for that check and for DKG when applicable.
const result = await TreSori().sendEmailVerificationRequest({
chain: selectedChain,
email: '[email protected]',
userId: 'unique_user_id',
});| Parameter | Type | Required | Description | | --------- | ------ | -------- | ------------------------- | | chain | Chain | ✅ | Target blockchain network | | email | string | ✅ | User's email address | | userId | string | ✅ | Unique user identifier |
Returns: Promise<object> — Backend OTP response. On a normal JSON object response, the SDK also merges isMPCExists and mpcExistRequest for client logging.
verifyEmail(args): Promise<object>
Calls isMpcExist again (same rules as send), then verifies the OTP with the matching new-user vs returning-user behavior.
const result = await TreSori().verifyEmail({
chain: selectedChain,
email: '[email protected]',
userId: 'unique_user_id',
otp: '123456',
});| Parameter | Type | Required | Description | | --------- | ------ | -------- | ------------------------- | | chain | Chain | ✅ | Target blockchain network | | email | string | ✅ | User's email address | | userId | string | ✅ | Unique user identifier | | otp | string | ✅ | OTP code from email |
Returns: Promise<object> — Returning users (MPC already exists for that email/chain): response often includes walletAddress, sessionId, and clientShare without DKG. New users: the SDK runs initDKG (dkg-init then dkg-contribute) and returns those fields on success; on failure it returns the raw email-verify payload (see the React Native section). Merged fields isMPCExists and mpcExistRequest are included when the payload is a plain object.
Phone Verification
sendPhoneVerificationCode(args): Promise<object>
Sends an OTP verification code via SMS.
const result = await TreSori().sendPhoneVerificationCode({
chain: selectedChain,
countryCode: '+1',
phone: '5551234567',
userId: 'unique_user_id',
isNewUser: true,
});| Parameter | Type | Required | Description | | ----------- | ------- | -------- | --------------------------------------- | | chain | Chain | ✅ | Target blockchain network | | countryCode | string | ✅ | Country code (e.g. '+1', '+44') | | phone | string | ✅ | Phone number without country code | | userId | string | ✅ | Unique user identifier | | isNewUser | boolean | ✅ | Whether this is a new user registration |
Returns: Promise<object> — Response indicating OTP was sent
verifyPhone(args): Promise<object>
Verifies the phone number using the OTP received.
const result = await TreSori().verifyPhone({
chain: selectedChain,
countryCode: '+1',
phone: '5551234567',
userId: 'unique_user_id',
otp: '123456',
isNewUser: true,
});| Parameter | Type | Required | Description | | ----------- | ------- | -------- | --------------------------------------- | | chain | Chain | ✅ | Target blockchain network | | countryCode | string | ✅ | Country code | | phone | string | ✅ | Phone number | | userId | string | ✅ | Unique user identifier | | otp | string | ✅ | OTP code from SMS | | isNewUser | boolean | ✅ | Whether this is a new user registration |
Returns: Promise<object> — Verification result with wallet details
MPC token transfers
transferMpcTokens(args): Promise<Record<string, any>>
Single entry point for native, ERC-20 (user pays gas), and gasless ERC-20 MPC transfers. You must complete email (or phone) verification first and persist clientShare, sessionId, and the MPC wallet fromAddress. All paths need a working rpcUrl to the same chain as chain.
Modes
- Native (chain currency) — Omit
tokenAddressor pass an empty string. Amount is parsed withdecimals(default 18), e.g."1"for one ETH-style unit. The wallet pays gas. - ERC-20 (user pays gas) — Set
tokenAddressto the token contract. Setdecimalsif not 18. Amount is a human-readable token string in those decimals (e.g."1.5"). - Gasless ERC-20 — When
mpcGaslessEnabledistrueandtokenAddressis non-empty, the implementation routes to the gasless pipeline (permit + relayer). UseplatformFeefor the fee in token units (same decimals); defaults apply per backend/facilitator rules. Token must support EIP-2612 permits.
When gasless is used via this method, TreSoriImpl supplies built-in sponsor and relayer addresses for the relay flow. To use your own relayer/sponsor, call gaslessTransferTokens instead.
// Native (default 18 decimals → "1" = 1 ETH-style unit)
const native = await TreSori().transferMpcTokens({
fromAddress: mpcAddress,
toAddress: '0xRecipient',
amount: '1',
chain: selectedChain,
clientShare,
sessionId,
userIdentity: 'email',
rpcUrl: 'https://sepolia.drpc.org',
});
// ERC-20 (payer pays gas)
const erc20 = await TreSori().transferMpcTokens({
fromAddress: mpcAddress,
toAddress: '0xRecipient',
amount: '10',
chain: selectedChain,
clientShare,
sessionId,
userIdentity: 'email',
rpcUrl: 'https://sepolia.drpc.org',
tokenAddress: '0xToken',
decimals: 18,
});
// Gasless ERC-20 (only when mpcGaslessEnabled && tokenAddress set)
const gasless = await TreSori().transferMpcTokens({
fromAddress: mpcAddress,
toAddress: '0xRecipient',
amount: '10',
chain: selectedChain,
clientShare,
sessionId,
userIdentity: 'email',
rpcUrl: 'https://sepolia.drpc.org',
tokenAddress: '0xEip2612Token',
decimals: 18,
platformFee: '1',
});| Parameter | Type | Required | Description |
| ------------ | ------ | -------- | ---------------------------------------------------------------------------- |
| fromAddress | string | ✅ | MPC wallet address |
| toAddress | string | ✅ | Recipient address |
| amount | string | ✅ | Human amount; decimals applies (default 18) for both native and ERC-20 |
| chain | Chain | ✅ | Target chain |
| clientShare | string | ✅ | Client share from verify / DKG |
| sessionId | string | ✅ | MPC session id |
| userIdentity | string | ✅ | Identity channel, e.g. 'email' |
| rpcUrl | string | ✅ | Chain JSON-RPC URL |
| tokenAddress | string | No | Omit or empty for native; required for ERC-20 and gasless |
| decimals | number | No | Token decimals (default 18) when tokenAddress is set |
| platformFee | string | No | Gasless: fee in token units (default '1' when gasless path is used) |
Returns: Promise<Record<string, any>> — Backend/RPC payload; often includes txHash / transactionHash (shape may vary by path).
gaslessTransferTokens(args): Promise<Record<string, any>>
Lower-level gasless transfer with explicit relayerAddress and sponsorAddress. The userShards argument is the same secret material as clientShare in other MPC APIs (naming follows the abstract API).
await TreSori().gaslessTransferTokens({
fromAddress: mpcAddress,
toAddress: '0xRecipient',
amount: '10',
chain: selectedChain,
userShards: clientShare,
userIdentity: 'email',
rpcUrl: 'https://...',
sessionId,
tokenAddress: '0xToken',
relayerAddress: '0x...',
sponsorAddress: '0x...',
decimals: 18,
platformFee: '1',
});| Parameter | Type | Required | Description |
| -------------- | ------ | -------- | ---------------------------------------------- |
| fromAddress | string | ✅ | MPC wallet address |
| toAddress | string | ✅ | Recipient |
| amount | string | ✅ | Human amount (token decimals) |
| chain | Chain | ✅ | Target chain |
| userShards | string | ✅ | Client share (same as clientShare elsewhere) |
| userIdentity | string | ✅ | e.g. 'email' |
| rpcUrl | string | ✅ | Chain RPC |
| sessionId | string | ✅ | MPC session |
| tokenAddress | string | ✅ | EIP-2612 token |
| relayerAddress | string | ✅ | Relayer contract / service address |
| sponsorAddress | string | ✅ | Sponsor address |
| decimals | number | No | Default 18 |
| platformFee | string | No | Fee in token units |
writeMpcSmartContractTransaction(args): Promise<object>
Encodes the call locally, signs with MPC (/v2/wallet/mpc/sign-simple), and broadcasts via your chain RPC (no relayer write-transaction).
const result = await TreSori().writeMpcSmartContractTransaction({
contractAddress: '0xContractAddress',
functionName: 'transfer',
params: ['0xRecipient', '1000000000000000000'],
abi: ['function transfer(address to, uint256 amount) returns (bool)'],
fromAddress: '0xMpcWalletAddress',
chain: selectedChain,
clientShare: '...', // from verify / DKG
sessionId: '...',
rpcUrl: 'https://...',
value: '0', // optional: wei sent with call (payable)
});| Parameter | Type | Required | Description |
| --------------- | -------- | -------- | ------------------------------------------------------------------------------------------------------------- |
| contractAddress | string | ✅ | Contract address |
| functionName | string | ✅ | Function to call |
| params | any[] | ✅ | Function arguments (ethers-compatible) |
| abi | string[] | ✅ | Human-readable ethers fragments only (e.g. 'function foo(uint256) external') — not { type, name, … } JSON |
| fromAddress | string | ✅ | MPC wallet address |
| chain | Chain | ✅ | Target blockchain network |
| clientShare | string | ✅ | Client share from verify / DKG |
| sessionId | string | ✅ | MPC session id |
| rpcUrl | string | ✅ | Chain JSON-RPC URL |
| value | string | No | Wei sent with tx (payable functions) |
Returns: Promise<object> — e.g. { txHash } from eth_sendRawTransaction
Wallet Balance
getWalletBalance(args: { address, chain }): Promise<object>
Retrieves the balance of a wallet.
const result = await TreSori().getWalletBalance({
address: '0xWalletAddress',
chain: selectedChain,
});
console.log('Balance:', result.balance);| Parameter | Type | Required | Description | | --------- | ------ | -------- | ------------------------- | | address | string | ✅ | Wallet address to query | | chain | Chain | ✅ | Target blockchain network |
Returns: Promise<object> — Balance information
Chain Management
After initialize() is called, supported chains are loaded from the backend. Use ChainListInstance or the chain proxy to obtain a Chain for API calls.
import { TreSori, ChainListInstance, chain } from '@kalp_studio/tresori-sdk-js';
await TreSori().initialize('YOUR_API_KEY');
// All available chains
const allChains = ChainListInstance.all;
for (const c of ChainListInstance.all) {
console.log(`${c.blockchain} - ${c.network}`);
console.log(' Chain ID:', c.chainId);
console.log(' Currency:', c.currency);
console.log(' Explorer:', c.explorerUrl);
}
// Get chain by blockchain and network (e.g. Ethereum Mainnet)
const ethereumMainnet = chain.ethereum.mainnet;
// Get chain by chainId
const chainById = ChainListInstance.ofChainId('1');Chain shape
Chains are plain objects with the following fields:
| Property | Type | Description | | ----------- | ------ | -------------------------- | | id | number | Internal ID | | blockchain | string | e.g. "Ethereum", "Polygon" | | network | string | e.g. "Mainnet", "Amoy" | | chainId | string | e.g. "1", "80002" | | explorerUrl | string | Block explorer URL | | currency | string | e.g. "ETH", "MATIC" | | logo | string | Logo URL | | createdAt | string | Creation timestamp |
Error Handling
The SDK throws errors for invalid or failed operations. Wrap calls in try/catch (or handle promise rejections).
try {
await TreSori().initialize('YOUR_API_KEY');
const wallet = await TreSori().createWallet({
chain: selectedChain,
mnemonic,
userId,
});
} catch (err) {
console.error('Error:', err.message);
}Common errors
| Error | Cause |
| --------------------------------------------------------------------- | --------------------------------------------------------------------- |
| Wallet not initialized. Call initialize() first. | SDK methods called before initialize() |
| API key is required. Call initialize() first. | Empty API key passed to initialize() |
| ChainList not loaded. Call "await ChainList.instance.load()" first. | Chains accessed before initialize() (load runs inside initialize) |
| Network/HTTP errors | API connectivity or backend failures |
Response Formats
Successful wallet creation
{
mnemonic: 'word1 word2 ... word12',
privateKey: '4c0883a69102937d6231471b5dbb6204fe5129617082792ae468d01a3f362318',
address: '0x742d35Cc6634C0532925a3b844Bc9e7595f8fE56',
userId: 'user_123',
}Wallet import (mnemonic / private key)
{
privateKey: '4c0883a69102937d6231471b5dbb6204fe5129617082792ae468d01a3f362318',
address: '0x742d35Cc6634C0532925a3b844Bc9e7595f8fE56',
}Example apps
Web (/example)
React + Vite demo: initialization, self-custodial and custodial flows, MPC email/phone verification, native and ERC-20 MPC transfers (including gasless when enabled), MPC contract writes with fragment ABI, and chain selection.
cd example
npm install
npm run devReact Native (/example-rn)
Expo-based (SDK 55, React Native with New Architecture) Android/iOS demo with the same TreSori APIs. The checked-in app targets Android in app.json. Entry index.js loads ./polyfills first so react-native-get-random-values runs before other imports (Android and iOS). MPC DKG uses @noble/ciphers in the SDK, not react-native-webcrypto. Use npm run android:dev / expo run:android or expo run:ios when you need a full native project; after major Expo upgrades run npm run prebuild:android (or npx expo prebuild --platform android) so android/ stays in sync. See React Native above and example-rn/MPC_FLOW_RN.md. On the MPC tab, new vs returning email flow is determined by /auth/is-mpc-exist; the demo logs MPC: New user or MPC: User exists after Send OTP / Verify.
# from repo root
npm run build
cd example-rn
npm install
npm run android:dev
# iOS: npm run iosBuild the SDK from the repo root first when using a local file:.. dependency:
npm run build
cd example && npm install && npm run devExports
The package exports:
TreSori— Function that returns the singleton SDK instance:TreSori().initialize(),TreSori().createWallet(), etc.TreSoriImpl— Concrete class withTreSoriImpl.instance(same singleton; useful in RN when you prefer a static entry point).ChainListInstance— Chain list:load(),all,get,ofChainId,isLoaded, and related helpers.chain— Proxy:chain.<blockchain>.<network>(e.g.chain.ethereum.mainnet).parseMpcAbiFragments/parseMpcAbiFragmentsFromText— Normalize MPC contractabitostring[]fragments (human-readable ethers fragments only; rejects JSON ABI objects). The text helper accepts one fragment per line, strict JSONstring[], or bracketed lists (including common single-quote paste formats).- Abstract
TreSoritype and re-exports from./corewhere applicable for advanced integration.
License
See LICENSE for details.
Support
For issues, feature requests, or questions, please contact the TreSori team.
