Skip to Content
Getting StartedQuick Start: Backend

Quick Start: Backend Integration

Create and manage server-side smart wallets from your Node.js backend using the @embarkai/core package.

Prerequisites

Installation

npm install @embarkai/core viem dkls23-wasm

Minimal Working Example

import { createServerWalletManager, MemoryKeyshareStorage } from '@embarkai/core' const manager = createServerWalletManager({ apiKey: process.env.EMBARK_API_KEY!, storage: new MemoryKeyshareStorage(), chainId: 2030232745, // Lumia Beam testnet }) // Create a wallet (runs TSS protocol automatically) const wallet = await manager.createWallet('treasury-main') console.log('Smart wallet address:', wallet.smartAccountAddress) // Send a transaction const userOpHash = await wallet.sendUserOperation( '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb', // recipient '1000000000000000000', // 1 LUMIA in wei '0x', // calldata (empty) 'standard', // fee type ) console.log('UserOperation hash:', userOpHash) // Wait for on-chain confirmation const receipt = await wallet.waitForUserOperationReceipt(userOpHash) console.log('Transaction hash:', receipt.transactionHash) console.log('Success:', receipt.success)

What Just Happened?

  1. API key authenticated — The createServerWalletManager uses your project API key to authenticate with EmbarkAI’s TSS service.
  2. MPC wallet createdcreateWallet() runs the DKLS23 distributed key generation protocol. Your backend holds one keyshare; EmbarkAI holds the other. No single party ever has the full private key.
  3. UserOperation built and signedsendUserOperation() constructs an ERC-4337 UserOperation, signs it using a two-party TSS signing round, and submits it to the bundler.
  4. Bundler executed on-chain — The bundler packages the UserOperation and submits it to the EntryPoint contract. The paymaster sponsors the gas so your wallet does not need native tokens for fees.

Storage Options

MemoryKeyshareStorage is fine for testing but loses keyshares on restart. For production, use encrypted file storage or a custom adapter:

File Storage (Node.js)

import { createServerWalletManager } from '@embarkai/core' import { FileKeyshareStorage } from '@embarkai/core/clients/node' const storage = new FileKeyshareStorage({ storageDir: './data/keyshares', encryptionPassword: process.env.EMBARK_KEYSHARE_PASSWORD!, }) await storage.init() const manager = createServerWalletManager({ apiKey: process.env.EMBARK_API_KEY!, storage, chainId: 2030232745, })

Custom Storage

Implement the KeyshareStorage interface for AWS KMS, HashiCorp Vault, or any other backend:

interface KeyshareStorage { set(userId: string, keyshare: string): Promise<void> | void get(userId: string): Promise<string | null> | string | null has(userId: string): Promise<boolean> | boolean list(): Promise<string[]> | string[] }

Warning: Keyshares are irreplaceable. If you lose a keyshare, the wallet and its funds are permanently inaccessible. Always use encrypted storage with redundant backups in production.

Smart Contract Interactions

The SDK provides encoding helpers for common contract calls:

import { createServerWalletManager, MemoryKeyshareStorage, encodeERC20Transfer, } from '@embarkai/core' const manager = createServerWalletManager({ apiKey: process.env.EMBARK_API_KEY!, storage: new MemoryKeyshareStorage(), chainId: 2030232745, }) const wallet = await manager.getWallet('treasury-main') // Encode an ERC20 transfer const callData = await encodeERC20Transfer( '0xRecipientAddress', 1000n * 10n ** 18n, // 1000 tokens ) // Send it as a UserOperation const userOpHash = await wallet.sendUserOperation( '0xTokenContractAddress', // to = token contract '0', // value = 0 (no native token) callData, // encoded transfer call 'standard', )

Available encoding helpers: encodeERC20Transfer, encodeERC20Approve, encodeERC721TransferFrom, encodeERC721SafeTransferFrom, encodeERC1155SafeTransferFrom, encodeContractCall (generic).

Next Steps

Last updated on