Skip to Content
API Reference@embarkai/core

@embarkai/core API

API reference for the core SDK package (@embarkai/core 0.4.15).

The @embarkai/core package provides authentication, ERC-4337 bundler operations, contract encoding utilities, encrypted vault backup, and server-side wallet management. Signatures below are copied from the package’s type declarations.

import { loginWithEmail, sendUserOperationWithRetry, encodeERC20Transfer } from '@embarkai/core' import { getChainConfig } from '@embarkai/core/read' import { EmbarkAIAuthService } from '@embarkai/core/auth/node' import { FileKeyshareStorage } from '@embarkai/core/clients/node'
Entry pointContents
@embarkai/coreEverything below except the Node-only and read-layer modules
@embarkai/core/authAuth functions and JwtTokenManager
@embarkai/core/auth/nodeEmbarkAIAuthService for backend token verification
@embarkai/core/bundlerBundler, gas and fee helpers
@embarkai/core/clientsServerWalletClient, Blockscout client
@embarkai/core/clients/nodeFileKeyshareStorage
@embarkai/core/readChain configs, viem chains and the public read client
@embarkai/core/utilsContract encoding and environment helpers

Auth

Functions for user authentication and JWT token management. All helpers that take an optional manager operate on the singleton jwtTokenManager by default.

Configuration

declare function configureJwtModule(config: { tssUrl?: string; projectId?: string }): void

Login Methods

import type { LoginResponse } from '@embarkai/core' declare function loginWithUserId(userId: string, options?: { skipTokenSave?: boolean }): Promise<LoginResponse> declare function loginWithEmail(email: string, code: string, options?: { skipTokenSave?: boolean }): Promise<LoginResponse> declare function loginWithTelegram( telegramData: { id: number first_name: string last_name?: string username?: string photo_url?: string auth_date: number hash: string }, options?: { skipTokenSave?: boolean }, ): Promise<LoginResponse>

Each login method returns a LoginResponse and, unless skipTokenSave is set, stores the tokens in the singleton manager.

Token Management

import type { JwtTokenManager, JwtTokens, RefreshOutcome, VerifyResponse } from '@embarkai/core' declare function verifyToken(manager?: JwtTokenManager): Promise<VerifyResponse | null> declare function ensureFreshSession(manager?: JwtTokenManager): Promise<'valid' | RefreshOutcome> declare function ensureValidToken(manager?: JwtTokenManager): Promise<boolean> declare function getValidTokens(manager?: JwtTokenManager): Promise<JwtTokens | null> declare function syncKeyshareStatus(manager?: JwtTokenManager): Promise<boolean> declare function logout(manager?: JwtTokenManager): Promise<void>
  • verifyToken — asks the TSS service to validate the stored access token; null when there is no token or the request failed.
  • ensureFreshSession — refreshes if needed and returns 'valid' | 'refreshed' | 'session_dead' | 'unavailable'.
  • ensureValidToken — boolean wrapper over ensureFreshSession.
  • getValidTokens — current tokens, refreshed if expired; null when refresh failed.
  • syncKeyshareStatus — re-checks whether the server holds a keyshare and returns the fresh value.

Authenticated Requests

import type { JwtTokenManager } from '@embarkai/core' declare function authenticatedFetch(url: string, options?: RequestInit, manager?: JwtTokenManager): Promise<Response>

A drop-in replacement for fetch that attaches the bearer token and refreshes it when expired.

JWT Token Manager

import type { JwtTokens, LoginResponse, RefreshOutcome, TokenStorage } from '@embarkai/core' declare class JwtTokenManager { constructor(storage?: TokenStorage) setTokens(response: LoginResponse): Promise<void> getAccessToken(): string | null getRefreshToken(): string | null getUserId(): string | null getHasKeyshare(): boolean | null getAvatar(): string | null getDisplayName(): string | null getProviders(): string[] getTokens(): JwtTokens | null updateKeyshareStatus(hasKeyshare: boolean): Promise<void> updateDisplayName(displayName: string | null): Promise<void> isTokenExpired(): boolean isAuthenticated(): boolean clearTokens(): Promise<void> refreshAccessToken(): Promise<boolean> refreshTokens(): Promise<RefreshOutcome> getAuthHeader(): string | null } declare const jwtTokenManager: JwtTokenManager declare function createJwtTokenManager(storage: TokenStorage): JwtTokenManager

Token Storage Adapters

interface TokenStorage { getItem(key: string): Promise<string | null> | string | null setItem(key: string, value: string): Promise<void> | void removeItem(key: string): Promise<void> | void } declare class LocalStorageAdapter implements TokenStorage { getItem(key: string): string | null setItem(key: string, value: string): void removeItem(key: string): void } declare class MemoryStorage implements TokenStorage { getItem(key: string): string | null setItem(key: string, value: string): void removeItem(key: string): void }

Encoding Helpers

declare function arrayBufferToBase64url(buffer: ArrayBuffer): string declare function base64urlToUint8Array(base64url: string): Uint8Array declare function arrayBufferToBase64(buffer: ArrayBuffer): string

Backend Token Verification

@embarkai/core/auth/node verifies embarkAI access tokens on your own server against the public JWKS.

interface EmbarkAITokenPayload { sub: string userId: string sessionId?: string providers?: string[] scope?: string exp?: number iat?: number jti?: string iss?: string aud?: string token_type?: string } interface EmbarkAITokenVerificationResult { valid: boolean user?: EmbarkAITokenPayload error?: 'expired' | 'invalid_signature' | 'not_yet_valid' | 'missing_userid' | 'unknown' errorMessage?: string } declare class EmbarkAIAuthService { constructor(options?: { jwksUri?: string; logger?: Record<string, (params: Record<string, any>) => void> }) verifyToken(accessToken: string): Promise<EmbarkAITokenVerificationResult> }

See Backend Auth for a middleware example.


Bundler

ERC-4337 v0.7 bundler client for submitting and tracking UserOperations. Chain-specific helpers take { chainId } and resolve the bundler URL and EntryPoint from the built-in chain config; fee helpers take a FeeChainContext.

Sending Operations

import type { UserOperationV07 } from '@embarkai/core' declare function sendUserOperationRaw(userOp: UserOperationV07, options: { chainId: number }): Promise<`0x${string}`> declare function sendUserOperationWithRetry( userOp: UserOperationV07, resigner: (nonce: `0x${string}`) => Promise<UserOperationV07>, options: { chainId: number; maxRetries: number }, ): Promise<`0x${string}`> declare function getUserOperationReceipt(userOpHash: `0x${string}`, bundlerUrl: string): Promise<any> declare function isNetworkError(errorMsg: string): boolean
  • sendUserOperationWithRetry — retries transient failures; resigner must return a freshly signed operation for the given nonce.
  • getUserOperationReceipt — raw eth_getUserOperationReceipt result; ServerWallet wraps it with typed polling.

Gas Estimation

import type { FeeChainContext, GasEstimationResult, UserOperationV07 } from '@embarkai/core' interface UserOperationParams { sender: `0x${string}` nonce: `0x${string}` callData: `0x${string}` includeFactory?: boolean factoryAddress?: `0x${string}` factoryData?: `0x${string}` feeType?: 'economy' | 'standard' | 'fast' } declare function estimateUserOperationGas( userOp: UserOperationV07, options: { chainId: number; retryWithoutFactory: boolean }, ): Promise<GasEstimationResult> declare function estimateUserOperationGasWithSignature( userOp: UserOperationV07, getSignature: (opHash: `0x${string}`) => Promise<`0x${string}` | null>, getUserOpHash: (packedOp: any) => Promise<`0x${string}`>, options: { chainId: number; retryWithoutFactory: boolean }, ): Promise<GasEstimationResult> declare function estimateUserOperationGasWithDynamicFees( params: UserOperationParams, context: FeeChainContext, retryWithoutFactory?: boolean, ): Promise<GasEstimationResult & { calculatedFees?: any }>

Simulation & Validation

Both use a Lumia-specific bundler extension and are marked @experimental.

import type { SimulationResult, UserOperationV07 } from '@embarkai/core' declare function simulateUserOperation(userOp: UserOperationV07, options: { chainId: number }): Promise<SimulationResult> declare function validateUserOperation( userOp: UserOperationV07, options: { chainId: number }, ): Promise<{ valid: boolean; error?: string }>

Fee Context

Fee and dynamic-gas helpers take a FeeChainContext. Build one from a chain ID:

import type { PublicClient } from 'viem' import type { FeeChainContext } from '@embarkai/core' interface FeeChainContextOptions { client?: PublicClient bundlerUrl?: string } declare function createFeeChainContext(chainId: number, options?: FeeChainContextOptions): FeeChainContext

Throws ChainNotSupportedError for unknown chain IDs; client defaults to createPublicClientForChain(chainId), bundlerUrl to the chain config.

Fee Calculation

import type { CalculatedFees, ChainContext, FeeChainContext, FeeConfig } from '@embarkai/core' declare function calculateDynamicFees(config: FeeConfig | undefined, context: FeeChainContext): Promise<CalculatedFees> declare function calculateFastFees(context: FeeChainContext): Promise<CalculatedFees> declare function calculateEconomyFees(context: FeeChainContext): Promise<CalculatedFees> declare function calculateLegacyFees(bufferPercent: number, context: ChainContext): Promise<CalculatedFees> declare function getFeeEstimates( context: FeeChainContext, ): Promise<{ economy: CalculatedFees; standard: CalculatedFees; fast: CalculatedFees }> declare function getCurrentBaseFee(context: ChainContext): Promise<bigint> declare function getCurrentPriorityFee(bundlerUrl: string, context: ChainContext): Promise<bigint>

Operation Helpers

import type { FeeChainContext, PackedUserOperationV07, UserOperationV07 } from '@embarkai/core' interface UserOperationParams { sender: `0x${string}` nonce: `0x${string}` callData: `0x${string}` includeFactory?: boolean factoryAddress?: `0x${string}` factoryData?: `0x${string}` feeType?: 'economy' | 'standard' | 'fast' } declare function packUserOperationV07( userOp: UserOperationV07, includeFactory: boolean, factoryAddress?: `0x${string}`, factoryData?: `0x${string}`, ): PackedUserOperationV07 declare function createDummyUserOperation( sender: `0x${string}`, nonce: `0x${string}`, callData: `0x${string}`, includeFactory?: boolean, factoryAddress?: `0x${string}`, factoryData?: `0x${string}`, customMaxFeePerGas?: `0x${string}`, customMaxPriorityFeePerGas?: `0x${string}`, ): UserOperationV07 declare function createUserOperationWithDynamicFees( params: UserOperationParams, context: FeeChainContext, ): Promise<UserOperationV07>

Public Client

declare function setPublicClient(client: any): void declare function getPublicClient(): any declare function hasPublicClient(): boolean

Constants

import type { FeeConfig } from '@embarkai/core' declare const ENTRYPOINT_V07: '0x0000000071727De22E5E9d8BAf0edAc6f37da032' declare const ENTRYPOINT: '0x0000000071727De22E5E9d8BAf0edAc6f37da032' // alias for ENTRYPOINT_V07 declare const DUMMY_SIGNATURE: `0x${string}` declare const DEFAULT_FEE_CONFIG: FeeConfig // baseFeeBuffer 0.5, priorityFeeBuffer 0.05 declare const CONSERVATIVE_FEE_CONFIG: FeeConfig // baseFeeBuffer 1, priorityFeeBuffer 0.25

Contract Encoding (Utils)

Pre-built calldata encoders for common token standards. All encoders are asynchronous.

ERC-20

declare function encodeERC20Transfer(to: `0x${string}`, amount: bigint): Promise<`0x${string}`> declare function encodeERC20Approve(spender: `0x${string}`, amount: bigint): Promise<`0x${string}`> declare function encodeERC20TransferFrom(from: `0x${string}`, to: `0x${string}`, amount: bigint): Promise<`0x${string}`>

ERC-721

declare function encodeERC721TransferFrom(from: `0x${string}`, to: `0x${string}`, tokenId: bigint): Promise<`0x${string}`> declare function encodeERC721SafeTransferFrom( from: `0x${string}`, to: `0x${string}`, tokenId: bigint, data?: `0x${string}`, ): Promise<`0x${string}`> declare function encodeERC721Approve(to: `0x${string}`, tokenId: bigint): Promise<`0x${string}`> declare function encodeERC721SetApprovalForAll(operator: `0x${string}`, approved: boolean): Promise<`0x${string}`>

ERC-1155

declare function encodeERC1155SafeTransferFrom( from: `0x${string}`, to: `0x${string}`, id: bigint, amount: bigint, data?: `0x${string}`, ): Promise<`0x${string}`> declare function encodeERC1155SafeBatchTransferFrom( from: `0x${string}`, to: `0x${string}`, ids: readonly bigint[], amounts: readonly bigint[], data?: `0x${string}`, ): Promise<`0x${string}`> declare function encodeERC1155SetApprovalForAll(operator: `0x${string}`, approved: boolean): Promise<`0x${string}`>

Generic Encoding

declare function encodeContractCall<TAbi extends readonly unknown[]>( abi: TAbi, functionName: string, args?: readonly unknown[], ): Promise<`0x${string}`> declare const ERC20_ABI: readonly unknown[] declare const ERC721_ABI: readonly unknown[] declare const ERC1155_ABI: readonly unknown[]

Vault

Encrypted keyshare backup and recovery via the embarkAI ShareVault. The functions take an API-key authenticated ServerWalletClient; ServerWalletManager exposes the same operations by wallet ID.

import type { KeyshareBackupData, ServerWalletClient } from '@embarkai/core' declare function configureVaultModule(config: { tssUrl?: string; shareVaultUrl?: string }): void declare function checkBackupExists( client: ServerWalletClient, userId: string, ): Promise<{ hasBackup: boolean; serviceAvailable: boolean }> declare function backupToVault(client: ServerWalletClient, data: KeyshareBackupData, password: string): Promise<void> declare function restoreFromVault(client: ServerWalletClient, userId: string, password: string): Promise<KeyshareBackupData>
interface KeyshareBackupData { userId: string sessionId: string keyshare: string ownerAddress: `0x${string}` createdAt: number version: string }

Server Wallets

Server-side MPC wallet management. See Server Wallets for a guide.

Manager

import type { ServerKeyshareStorage } from '@embarkai/core' interface ServerWalletManagerConfig { apiKey: string storage: ServerKeyshareStorage chainId: number tssUrl?: string bundlerUrl?: string rpcUrl?: string factoryAddress?: `0x${string}` entryPointAddress?: `0x${string}` paymasterAddress?: `0x${string}` dashboardApiUrl?: string domainLabel?: string maxCallGasLimit?: bigint maxVerificationGasLimit?: bigint debug?: boolean }
import type { BatchOperation, EcdsaSignature, ServerWallet, ServerWalletManagerConfig, UserOpReceiptResult, } from '@embarkai/core' declare class ServerWalletManager { constructor(config: ServerWalletManagerConfig) createWallet(userId: string): Promise<ServerWallet> getWallet(userId: string): Promise<ServerWallet> listWallets(): Promise<ServerWallet[]> walletExists(userId: string): Promise<boolean> hasKeyshare(userId: string): Promise<boolean> sendUserOperation( wallet: ServerWallet, to: `0x${string}`, value: string, data?: `0x${string}`, feeType?: 'economy' | 'standard' | 'fast', nonceKey?: bigint, ): Promise<`0x${string}`> sendBatchUserOperation( wallet: ServerWallet, operations: BatchOperation[], feeType?: 'economy' | 'standard' | 'fast', nonceKey?: bigint, ): Promise<`0x${string}`> getUserOperationReceipt(userOpHash: `0x${string}`): Promise<UserOpReceiptResult | null> waitForUserOperationReceipt( userOpHash: `0x${string}`, options?: { pollIntervalMs?: number; maxPollTimeMs?: number }, ): Promise<UserOpReceiptResult> signDigest(userId: string, digest32: string, chainPath?: string): Promise<EcdsaSignature> checkBackupExists(userId: string): Promise<{ hasBackup: boolean; serviceAvailable: boolean }> backupToVault(userId: string, password: string): Promise<void> restoreFromVault(userId: string, password: string): Promise<void> } declare function createServerWalletManager(config: ServerWalletManagerConfig): ServerWalletManager declare const MAX_NONCE_KEY: bigint

Wallet

import type { BatchOperation, EcdsaSignature, UserOpReceiptResult } from '@embarkai/core' declare class ServerWallet { readonly userId: string readonly pubkey: string readonly ownerAddress: `0x${string}` readonly smartAccountAddress: `0x${string}` readonly createdAt: string readonly sessionId: string sendUserOperation( to: `0x${string}`, value: string, data?: `0x${string}`, feeType?: 'economy' | 'standard' | 'fast', nonceKey?: bigint, ): Promise<`0x${string}`> sendBatchUserOperation( operations: BatchOperation[], feeType?: 'economy' | 'standard' | 'fast', nonceKey?: bigint, ): Promise<`0x${string}`> signDigest(digest32: string, chainPath?: string): Promise<EcdsaSignature> hasKeyshare(): Promise<boolean> getUserOperationReceipt(userOpHash: `0x${string}`): Promise<UserOpReceiptResult | null> waitForUserOperationReceipt( userOpHash: `0x${string}`, options?: { pollIntervalMs?: number; maxPollTimeMs?: number }, ): Promise<UserOpReceiptResult> toJSON(): { userId: string pubkey: string ownerAddress: `0x${string}` smartAccountAddress: `0x${string}` createdAt: string sessionId: string } }

Keyshare Storage

ServerWalletManager needs a ServerKeyshareStorage (not the TokenStorage-style KeyshareStorage exported from the root for the auth module).

interface ServerKeyshareStorage { 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[] } declare class MemoryKeyshareStorage implements ServerKeyshareStorage { set(userId: string, keyshare: string): Promise<void> get(userId: string): Promise<string | null> has(userId: string): Promise<boolean> list(): Promise<string[]> }

FileKeyshareStorage from @embarkai/core/clients/node stores AES-encrypted keyshares on disk (used by the MCP server):

interface FileKeyshareStorageConfig { storageDir?: string encryptionPassword: string salt?: string } declare class FileKeyshareStorage { constructor(config: FileKeyshareStorageConfig) init(): Promise<void> set(userId: string, keyshare: string): Promise<void> get(userId: string): Promise<string | null> has(userId: string): Promise<boolean> list(): Promise<string[]> delete(userId: string): Promise<void> }

Server Wallet Client

Low-level API-key client used by the manager and the vault functions (@embarkai/core/clients).

import type { ServerWalletInfo, ServerWalletsListResponse } from '@embarkai/core' interface ServerWalletClientConfig { apiKey: string tssUrl?: string debug?: boolean } declare class ServerWalletClient { constructor(config: ServerWalletClientConfig) listWallets(): Promise<ServerWalletsListResponse> getWalletInfo(userId: string): Promise<ServerWalletInfo> } declare function createServerWalletClient(config: ServerWalletClientConfig): ServerWalletClient

Paymaster Resolution

interface ResolvedPaymaster { address: `0x${string}` | null source: 'dashboard' | 'override' | 'default' | 'none' chainId: number projectId?: string } interface ResolveProjectPaymasterParams { chainId: number projectId?: string apiKey?: string explicitPaymasterAddress?: `0x${string}` | null defaultPaymasterAddress?: `0x${string}` | null dashboardApiUrl?: string cacheTtlMs?: number fetchFn?: typeof fetch disableDashboardLookup?: boolean } declare function resolveProjectPaymaster(params: ResolveProjectPaymasterParams): Promise<ResolvedPaymaster> declare function clearResolvedPaymasterCache(): void declare const PAYMASTER_CACHE_TTL_MS: number

Chains & Read Layer

Chain configuration and viem helpers live under @embarkai/core/read.

import type { Chain, PublicClient } from 'viem' import type { ChainConfig } from '@embarkai/core/read' declare function getChainConfig(chainId: number): ChainConfig | undefined declare function isChainSupported(chainId: number): boolean declare function getViemChain(chainId: number): Chain | undefined declare function createChainFromConfig(chainConfig: ChainConfig): Chain declare function createPublicClientForChain(chainId: number): PublicClient declare const DEFAULT_CHAIN_ID: 994873017 declare const SUPPORTED_CHAINS: Map<number, ChainConfig> declare const SUPPORTED_MAINNETS: number[] declare const VIEM_CHAINS: Map<number, Chain> declare const MULTICALL3_ADDRESS: `0x${string}` // Per-chain constants, e.g. declare const LUMIA_MAINNET_CHAIN_ID: 994873017 declare const LUMIA_MAINNET: ChainConfig declare const lumiaMainnetChain: Chain

The same pattern (*_CHAIN_ID, * config, *Chain viem object) exists for LUMIA_TESTNET, SEPOLIA, BSC_TESTNET, ARBITRUM_SEPOLIA and BASE_SEPOLIA. See Supported Chains.


Types

Auth

interface JwtTokens { accessToken: string refreshToken: string userId: string expiresIn: number expiresAt: number hasKeyshare?: boolean isNewUser?: boolean avatar?: string | null displayName?: string | null providers?: string[] } interface LoginResponse { accessToken: string refreshToken: string userId: string expiresIn: number hasKeyshare: boolean isNewUser?: boolean avatar?: string | null displayName?: string | null providers?: string[] } interface RefreshResponse { accessToken: string refreshToken?: string expiresIn: number userId: string sessionId: string providers: string[] } interface VerifyResponse { valid: boolean userId?: string sessionId?: string exp?: number hasKeyshare?: boolean displayName?: string | null avatar?: string | null } type RefreshOutcome = 'refreshed' | 'session_dead' | 'unavailable'

UserOperations

interface UserOperationV07 { sender: `0x${string}` nonce: `0x${string}` callData: `0x${string}` callGasLimit: `0x${string}` verificationGasLimit: `0x${string}` preVerificationGas: `0x${string}` maxFeePerGas: `0x${string}` maxPriorityFeePerGas: `0x${string}` signature: `0x${string}` factory?: `0x${string}` factoryData?: `0x${string}` paymaster?: `0x${string}` paymasterData?: `0x${string}` paymasterVerificationGasLimit?: `0x${string}` paymasterPostOpGasLimit?: `0x${string}` } interface PackedUserOperationV07 { sender: `0x${string}` nonce: bigint initCode: `0x${string}` callData: `0x${string}` accountGasLimits: bigint preVerificationGas: bigint gasFees: bigint paymasterAndData: `0x${string}` signature: `0x${string}` } interface GasEstimationResult { callGasLimit: `0x${string}` verificationGasLimit: `0x${string}` preVerificationGas: `0x${string}` } interface BatchOperation { to: `0x${string}` value: string data: `0x${string}` } interface UserOpReceiptResult { success: boolean transactionHash: `0x${string}` blockNumber: string blockHash: string actualGasUsed: string actualGasCost: string logs: any[] } interface EcdsaSignature { r: string s: string v: number }

Simulation

import type { SimulationExecutionResult } from '@embarkai/core' interface AssetChange { assetType: 'NATIVE' | 'ERC20' | 'ERC721' | 'ERC1155' | 'SPECIAL_NFT' changeType: 'APPROVE' | 'TRANSFER' from: `0x${string}` to: `0x${string}` amount?: string rawAmount?: string symbol?: string decimals?: number contractAddress?: `0x${string}` name?: string logo?: string tokenId?: string } interface SimulationResult { changes: AssetChange[] executionResult?: SimulationExecutionResult error?: { message: string; code?: number } | null } interface BundlerRpcError { code: number message: string data?: { reason?: string; innerReason?: string; revertData?: `0x${string}` } }

Fees & Context

import type { PublicClient } from 'viem' import type { ChainConfig } from '@embarkai/core/read' interface ChainContext { client: PublicClient } interface FeeChainContext { client: PublicClient bundlerUrl: string chainConfig: ChainConfig } interface FeeConfig { baseFeeBuffer: number priorityFeeBuffer: number fallbackMaxFeePerGas?: bigint fallbackMaxPriorityFeePerGas?: bigint } interface CalculatedFees { maxFeePerGas: `0x${string}` maxPriorityFeePerGas: `0x${string}` baseFee?: bigint priorityFee?: bigint bufferedBaseFee?: bigint bufferedPriorityFee?: bigint }

Version

declare const VERSION: '0.1.0'

VERSION is not updated on releases and still reads "0.1.0" in 0.4.15. Use the installed package version instead.

Last updated on