Skip to content
embark-aiPublic

About

EmbarkAI — Smart account SDK for Web3 apps

Resources

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

5 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 

Repository files navigation

@embarkai/core

Framework-agnostic core SDK for embarkAI smart accounts — Account Abstraction (ERC-4337) with MPC (TSS) wallet infrastructure.

npm license

📖 Full documentation: docs.embarkai.io/core-sdk

Features

  • Zero React dependencies — works in Node.js, browsers and edge runtimes
  • Server wallets — create and operate backend MPC wallets with a project API key
  • Account Abstraction — ERC-4337 (EntryPoint v0.7) UserOperations, batches, parallel nonces, sponsored gas
  • Policy-checked signing — TSS recomputes what is signed and enforces the wallet policies set in the Dashboard
  • Keyshare backup — encrypted backup to and restore from the embarkAI Share Vault
  • Auth — JWT session management for clients, JWKS token validation for backends
  • Blockchain read layer — cached viem public client with RPC fallback, multicall batching and log pagination
  • Contract encoding helpers — ERC20, ERC721, ERC1155 and arbitrary ABI calls
  • Multi-chain — chain parameters are resolved from chainId for every supported network

Installation

npm install @embarkai/core viem
# server wallets (DKG and signing) also need the TSS WASM module
npm install dkls23-wasm

viem ≥ 2.10 is a peer dependency. dkls23-wasm is an optional peer dependency: it is loaded on first use, and server wallet calls throw if it is not installed.

Quick Start

Get a project API key from the embarkAI Dashboard.

import { createServerWalletManager, MemoryKeyshareStorage } from '@embarkai/core'

const manager = createServerWalletManager({
  apiKey: process.env.EMBARK_API_KEY!,
  storage: new MemoryKeyshareStorage(), // dev only — use FileKeyshareStorage or your own storage in production
  chainId: 2030232745 // Lumia Beam Testnet
})

// Create a wallet (runs DKG with TSS)
const wallet = await manager.createWallet('treasury_main')
console.log('Owner (EOA):', wallet.ownerAddress)
console.log('Smart Account:', wallet.smartAccountAddress)

// Send a UserOperation
const userOpHash = await wallet.sendUserOperation(
  '0x742d35Cc6634C0532925a3b844Bc454e4438f44e', // to
  '1000000000000000000', // value in wei
  '0x', // calldata
  'standard' // 'economy' | 'standard' | 'fast'
)

const receipt = await wallet.waitForUserOperationReceipt(userOpHash)
console.log('Tx hash:', receipt.transactionHash, receipt.success)

Bundler, RPC, factory, EntryPoint and paymaster are resolved from chainId. Pass bundlerUrl, rpcUrl, factoryAddress, entryPointAddress, paymasterAddress or tssUrl to override them.

→ Server Wallets

Server Wallets

Manager method Description
createWallet(id) / getWallet(id) / listWallets() Create (DKG) or load wallets
walletExists(id) / hasKeyshare(id) Check the wallet on TSS and the keyshare in local storage
checkBackupExists(id) / backupToVault(id, password) / restoreFromVault(id, password) Share Vault backup and restore
waitForUserOperationReceipt(hash, { pollIntervalMs, maxPollTimeMs }) Poll for a receipt
ServerWallet method Description
sendUserOperation(to, value, data?, feeType?, nonceKey?) Sign and submit a single call; pass a nonceKey to send in parallel
sendBatchUserOperation([{ to, value, data }], feeType?) Atomic multi-call UserOperation
signMessage(message) EIP-191 signature by the owner key
signTypedData({ domain, types, primaryType, message }) EIP-712 signature by the owner key
signUserOperation({ userOp, userOpHash }) Sign a UserOperation without submitting it
getUserOperationReceipt(hash) / waitForUserOperationReceipt(hash, opts?) Receipt lookup and polling

signMessage and signTypedData produce an owner-key signature; a contract accepts it only if it verifies smart-account signatures (ERC-1271). signDigest with a bare hash is deprecated: TSS accepts it only during the migration and only for wallets without policies.

Storage

Storage Use
MemoryKeyshareStorage Development only — keyshares are lost on restart
FileKeyshareStorage from @embarkai/core/clients/node AES-encrypted files, Node.js only
Your own ServerKeyshareStorage set, get, has, list (sync or async) over KMS, Vault, a database…
import { FileKeyshareStorage } from '@embarkai/core/clients/node'

const storage = new FileKeyshareStorage({
  storageDir: './data/keyshares',
  encryptionPassword: process.env.EMBARK_KEYSHARE_ENCRYPTION_PASSWORD!
})
await storage.init()

A lost keyshare cannot be recovered without a backup. Never delete keyshares, and back them up with backupToVault. → Vault & Key Backup

Policy errors

Every signing request is checked in TSS against the wallet policies configured in the Dashboard. A rejected request throws a typed error before any signing round starts:

import { PolicyViolationError, PolicyUnavailableError, TssRequestError, WalletRevokedError } from '@embarkai/core'

try {
  await wallet.sendUserOperation(to, value, data, 'standard')
} catch (error) {
  if (error instanceof PolicyViolationError) {
    console.log('blocked by policy', error.policyId, error.rule, error.reason)
  } else if (error instanceof PolicyUnavailableError) {
    console.log('policies could not be read, retry later', error.retryable)
  } else if (error instanceof WalletRevokedError) {
    console.log('this wallet was revoked in the Dashboard')
  } else if (error instanceof TssRequestError) {
    console.log(error.status, error.tssCode, error.response?.url) // response snapshot, no request headers
  } else {
    throw error
  }
}

Other classes: DigestMismatchError, MissingOperationError; codes in TssErrorCodes.

Contract Encoding

All helpers are async and return calldata for sendUserOperation:

import { encodeERC20Transfer } from '@embarkai/core'

const data = await encodeERC20Transfer('0xRecipient...', 1000n * 10n ** 18n)
await wallet.sendUserOperation('0xTokenContract...', '0', data, 'standard')

encodeContractCall(abi, fn, args), encodeERC20Transfer / Approve / TransferFrom, encodeERC721TransferFrom / SafeTransferFrom / Approve / SetApprovalForAll, encodeERC1155SafeTransferFrom / SafeBatchTransferFrom / SetApprovalForAll, plus ERC20_ABI, ERC721_ABI, ERC1155_ABI.

→ Contract Encoding

Blockchain Read Layer

import { getPublicClient } from '@embarkai/core/read'
import { erc20Abi } from 'viem'

const client = getPublicClient({ chainId: 994873017 })
const balance = await client.readContract({
  address: '0xToken...',
  abi: erc20Abi,
  functionName: 'balanceOf',
  args: ['0xUser...']
})

LRU cache (12 s TTL), automatic RPC fallback, multicall batching, paginated getLogs, getTransactionReceipt and waitForTransactionReceipt. Chain helpers: getChainConfig, isChainSupported, getViemChain.

Bundler (Low-Level)

For services that build UserOperations themselves: sendUserOperationRaw(userOp, { chainId }), sendUserOperationWithRetry, getUserOperationReceipt(hash, bundlerUrl), estimateUserOperationGas, createFeeChainContext(chainId), fee helpers (getFeeEstimates, calculateDynamicFees, …) and packUserOperationV07.

→ Bundler & UserOperations

Authentication

Clients — jwtTokenManager keeps the session tokens; ensureFreshSession(), getValidTokens(), fetchWithSession(url, init) (refreshes before the request, retries once on 401), logout() and jwtTokenManager.subscribe(listener) (called when a session starts or ends). In React apps @embarkai/ui-kit configures this for you. → Client Authentication

Backends — validate access tokens against the embarkAI JWKS:

import { EmbarkAIAuthService } from '@embarkai/core/auth/node'

const auth = new EmbarkAIAuthService({ projectId: 'your-project-id' }) // projectId is optional
const result = await auth.verifyToken(token)
if (!result.valid) throw new Error(result.error) // 'expired' | 'wrong_project' | …
console.log(result.user?.userId)

With projectId, tokens issued for another project and anything but access tokens are rejected. → Backend Auth Tokens Validation

Import Paths

Path Contents
@embarkai/core Everything below except Node-only modules
@embarkai/core/read Public client, chain config helpers
@embarkai/core/bundler UserOperation submission, gas and fee helpers
@embarkai/core/clients ServerWalletManager, ServerWalletClient, TSS errors, Blockscout client
@embarkai/core/clients/node FileKeyshareStorage (Node.js)
@embarkai/core/auth JWT session management
@embarkai/core/auth/node EmbarkAIAuthService (Node.js)
@embarkai/core/utils Contract encoding, ABIs

Supported Networks

Network Chain ID Type
Lumia Prism 994873017 Mainnet (default)
BNB Smart Chain 56 Mainnet
Lumia Beam 2030232745 Testnet
Lumia Pulsar 1279885899 Testnet
Ethereum Sepolia 11155111 Testnet
BSC Testnet 97 Testnet
Arbitrum Sepolia 421614 Testnet
Base Sepolia 84532 Testnet

→ Supported Chains

Related Packages

Package Description
@embarkai/ui-kit React components and hooks
@embarkai/mcp MCP server for AI agents

Community

License

MIT

About

EmbarkAI — Smart account SDK for Web3 apps

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors