Helpers Module

Device key management and signer helpers

Helpers Module

The helpers module provides comprehensive functionality for device key management and signer operations, simplifying working with email/phone signers and providing automatic device key resolution, validation, and caching.

Import

import { 
  // Storage Adapters (use createIndexedDBAdapter in browser for email/phone signers)
  createIndexedDBAdapter,
  createLocalStorageAdapter,
  createFileSystemAdapter,
  createMemoryAdapter,
  getDefaultStorageAdapter,
  
  // Validation
  isValidEmail,
  isValidPhone,
  
  // Email Signer Helpers
  createEmailSignerHelper,
  getEmailSignerKeypair,
  signWithEmailSigner,
  getEmailSignerByEmail,
  
  // Phone Signer Helpers
  createPhoneSignerHelper,
  getPhoneSignerKeypair,
  signWithPhoneSigner,
  getPhoneSignerByPhone,
  
  // Passkey
  createPasskeySigner,
  signWithPasskeySigner,
  
  // Generic / external
  signWithSigner,
  
  // Device Key Management
  getDevicePublicKey,
  generateDeviceKeyPair,
  rotateDeviceKey,
  clearDeviceKeyCache,
  findDeviceKeyByPublicKey,
  listAllDeviceKeys,
  
  // Device Identity Management
  addDeviceIdentityToSigner,
  replaceDeviceIdentity,
  addNewDeviceToSigner,
  canAddDeviceToSigner,
  
  // Validation & Resolution
  getSignerDeviceKeys,
  validateDeviceKey,
  resolveDeviceKey,
  getBestDeviceIdentity
} from 'cilantro-sdk/helpers';
import { createExternalWalletSigner } from 'cilantro-sdk/wallet';

In the browser, use createIndexedDBAdapter() for email/phone signers (recommended over localStorage). Create it once and pass the same instance to CilantroProvider and to helpers when creating signers. For external wallet signers, use createExternalWalletSigner from cilantro-sdk/wallet. Validate email/phone with isValidEmail and isValidPhone before creating signers.

Quick Example

import { 
  createEmailSignerHelper,
  getEmailSignerKeypair,
  createIndexedDBAdapter 
} from 'cilantro-sdk/helpers';

// Create storage for device keys (browser: use IndexedDB)
const deviceKeyManager = createIndexedDBAdapter();

// Create email signer (device key generated automatically)
const result = await createEmailSignerHelper(walletId, {
  email: 'user@example.com',
  deviceKeyManager,
});
// result: { signerId, walletId, ... }

// Get keypair - SDK automatically:
// 1. Fetches signer from API
// 2. Extracts devicePublicKey and deviceId
// 3. Resolves device key from storage
// 4. Validates device key matches API
const keypair = await getEmailSignerKeypair(
  walletId,
  result.signerId,
  { deviceKeyManager }
);

Passkey: use createPasskeySigner, registerPasskey, authenticateWithPasskey, signWithPasskeySigner (browser only). External wallet signer: use createExternalWalletSigner(walletId, { address }) from cilantro-sdk/wallet.

Transaction helpers (non-custodial)

Option 1 — One step (recommended): use sendSOLWithSigner and sendSPLWithSigner from cilantro-sdk/helpers so device key resolution and signing are handled for you:

import { sendSOLWithSigner, sendSPLWithSigner } from 'cilantro-sdk/helpers';
import { createIndexedDBAdapter } from 'cilantro-sdk/helpers';

const storage = createIndexedDBAdapter();

const result = await sendSOLWithSigner(
  walletId,
  signerId,
  'email',  // or 'phone', 'passkey', 'external'
  '7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU',
  100000000,
  { emailSignerOptions: { deviceKeyManager: storage } }
);

Option 2 — Manual prepare / sign / submit: use prepareTransaction and submitTransaction from cilantro-sdk/wallet, and signTransactionWithEmailSigner from cilantro-sdk/helpers:

import { prepareTransaction, submitTransaction } from 'cilantro-sdk/wallet';
import { signTransactionWithEmailSigner } from 'cilantro-sdk/helpers';

const { data: { unsignedTransaction, blockhash } } = await prepareTransaction(walletId, {
  type: 'send_sol',
  signerPubkey: signerPublicKeyBase58,
  sendSolParams: { recipient: recipientAddress, amount: amountLamports },
});

const signedTransaction = await signTransactionWithEmailSigner(
  walletId,
  signerId,
  unsignedTransaction,
  { deviceKeyManager: storage }
);

const { data } = await submitTransaction(walletId, { signedTransaction });

Device Key Management

getDevicePublicKey(options)

Get or create device key with caching.

const deviceKey = await getDevicePublicKey({
  deviceKeyManager: storage
});

generateDeviceKeyPair(options)

Generate new device key pair.

const keyPair = await generateDeviceKeyPair({
  deviceKeyManager: storage
});

rotateDeviceKey(deviceId, options)

Rotate device keys.

await rotateDeviceKey('old-device-id', {
  deviceKeyManager: storage
});

clearDeviceKeyCache()

Clear cache.

clearDeviceKeyCache();

findDeviceKeyByPublicKey(publicKey, options)

Find device key by public key.

const deviceKey = await findDeviceKeyByPublicKey(
  'device-public-key',
  { deviceKeyManager: storage }
);

listAllDeviceKeys(options)

List all device keys with metadata.

const deviceKeys = await listAllDeviceKeys({
  deviceKeyManager: storage
});

Email Signer Helpers

createEmailSignerHelper(walletId, options)

Create email signer with automatic device key generation.

emailstringrequired

Email address for the signer

deviceKeyManagerDeviceKeyStoragerequired

Storage adapter for device keys

const signer = await createEmailSignerHelper('wallet-id', {
  email: 'user@example.com',
  deviceKeyManager: storage
});

getEmailSignerKeypair(walletId, signerId, options)

Get keypair with automatic device key resolution.

const keypair = await getEmailSignerKeypair(
  'wallet-id',
  'signer-id',
  { 
    deviceKeyManager: storage
  }
);

signWithEmailSigner(walletId, signerId, message, options)

Sign messages with email signer.

const signature = await signWithEmailSigner(
  'wallet-id',
  'signer-id',
  message,
  { deviceKeyManager: storage }
);

getEmailSignerByEmail(walletId, email)

Find email signer by email address.

const signer = await getEmailSignerByEmail('wallet-id', 'user@example.com');

Phone Signer Helpers

createPhoneSignerHelper(walletId, options)

Create phone signer with automatic device key generation.

const signer = await createPhoneSignerHelper('wallet-id', {
  phone: '+1234567890',
  deviceKeyManager: storage
});

getPhoneSignerKeypair(walletId, signerId, options)

Get keypair with automatic device key resolution.

const keypair = await getPhoneSignerKeypair(
  'wallet-id',
  'signer-id',
  { deviceKeyManager: storage }
);

signWithPhoneSigner(walletId, signerId, message, options)

Sign messages with phone signer.

const signature = await signWithPhoneSigner(
  'wallet-id',
  'signer-id',
  message,
  { deviceKeyManager: storage }
);

getPhoneSignerByPhone(walletId, phone)

Find phone signer by phone number. Validate phone with isValidPhone before creating a signer.

import { isValidPhone } from 'cilantro-sdk/helpers';
if (!isValidPhone(phone)) throw new Error('Invalid phone');
const signer = await createPhoneSignerHelper(walletId, { phone, deviceKeyManager });

Similarly use isValidEmail before createEmailSignerHelper.

Storage Adapters

createIndexedDBAdapter()

Browser IndexedDB adapter. Recommended for email/phone signers in the browser. Create once (e.g. in useMemo in React) and pass to CilantroProvider and to signer helpers.

const storage = createIndexedDBAdapter();

createLocalStorageAdapter()

Browser localStorage adapter.

const storage = createLocalStorageAdapter();

createFileSystemAdapter(options?)

Node.js filesystem adapter.

const storage = createFileSystemAdapter({
  basePath: './device-keys'
});

createMemoryAdapter()

In-memory adapter (for testing).

const storage = createMemoryAdapter();

getDefaultStorageAdapter()

Get platform-appropriate adapter.

const storage = getDefaultStorageAdapter();

Device Identity Management

addDeviceIdentityToSigner(walletId, signerId, identity)

Add new device to existing signer.

await addDeviceIdentityToSigner(
  'wallet-id',
  'signer-id',
  {
    devicePublicKey: 'new-device-public-key',
    deviceId: 'new-device-id'
  }
);

replaceDeviceIdentity(walletId, signerId, oldDeviceId, newIdentity)

Replace existing device identity.

await replaceDeviceIdentity(
  'wallet-id',
  'signer-id',
  'old-device-id',
  {
    devicePublicKey: 'new-device-public-key',
    deviceId: 'new-device-id'
  }
);

addNewDeviceToSigner(walletId, signerId, options)

Convenience function for adding new device.

await addNewDeviceToSigner('wallet-id', 'signer-id', {
  deviceKeyManager: storage
});

canAddDeviceToSigner(walletId, signerId)

Check if device can be added.

const canAdd = await canAddDeviceToSigner('wallet-id', 'signer-id');

Validation & Resolution

getSignerDeviceKeys(walletId, signerId)

Get all device keys for a signer from API.

const deviceKeys = await getSignerDeviceKeys('wallet-id', 'signer-id');

validateDeviceKey(walletId, signerId, devicePublicKey, options)

Validate device key matches API.

const isValid = await validateDeviceKey(
  'wallet-id',
  'signer-id',
  'device-public-key',
  { deviceKeyManager: storage }
);

resolveDeviceKey(walletId, signerId, options)

Automatically find matching device key.

const deviceKey = await resolveDeviceKey(
  'wallet-id',
  'signer-id',
  { deviceKeyManager: storage }
);

getBestDeviceIdentity(walletId, signerId, options)

Get most recently used device identity.

const deviceIdentity = await getBestDeviceIdentity(
  'wallet-id',
  'signer-id',
  { deviceKeyManager: storage }
);
Helpers Module | Cilantro Smart Wallet Docs | Cilantro Smart Wallet