API Reference
iOS SDK API Reference
Public CROSSxSDK API reference.
Configuration
SDKConfig
SDKConfigSDK initialization configuration object.
public struct SDKConfig: Sendable {
public init(
bundle: Bundle = .main,
projectId: String,
appName: String,
callbackScheme: String? = nil,
httpNetwork: HTTPNetworkConfig? = nil,
theme: SDKThemeMode = .system,
themeTokens: SDKThemeTokens? = nil,
debug: Bool = true,
locale: SDKLocale? = nil
)
public static func fromInfoPlist(
projectId: String,
appName: String,
bundle: Bundle = .main,
httpNetwork: HTTPNetworkConfig? = nil
) throws -> SDKConfig
public static func defaultScheme(for projectId: String) -> String
}| Parameter | Type | Default | Description |
|---|---|---|---|
bundle | Bundle | .main | App bundle; used to read Info.plist values |
projectId | String | — | CROSSx project identifier |
appName | String | — | Host app display name shown in SDK UI |
callbackScheme | String? | nil | OAuth deep-link scheme. Use SDKConfig.defaultScheme(for:) |
httpNetwork | HTTPNetworkConfig? | nil | Network timeout and retry settings |
theme | SDKThemeMode | .system | Initial theme mode |
themeTokens | SDKThemeTokens? | nil | Color token overrides per theme |
debug | Bool | true | Enables SDK debug logging |
locale | SDKLocale? | nil | UI language override; nil follows device system locale |
Example
let sdk = try CROSSxSDK(config: SDKConfig(
projectId: "your-project-id",
appName: "Your App Name",
locale: .ko // or .en
))SDKLocale
SDKLocaleControls the language used for all SDK-provided UI strings and error messages.
public enum SDKLocale: Sendable {
case en
case ko
}| Value | Behavior |
|---|---|
nil (default) | Follows the device system locale |
.en | Forces English regardless of system locale |
.ko | Forces Korean regardless of system locale |
Set at initialization via SDKConfig.locale, or change at runtime with updateLocale(_:).
SDKSignInProvider
SDKSignInProviderSelects the OAuth provider shown during signIn(provider:) / signInWithCreate(provider:).
public enum SDKSignInProvider: Equatable, Sendable {
case all // shows provider selection sheet
case google
case apple
}.all shows the provider selection sheet; .google / .apple skip directly to that provider.
Theme
SDKThemeMode / SDKThemeTokens
SDKThemeMode / SDKThemeTokenspublic enum SDKThemeMode: String, Sendable {
case light
case dark
case system
}
public struct SDKThemeTokens: Sendable {
public var light: SDKColorOverrides?
public var dark: SDKColorOverrides?
}Pass to SDKConfig or applyTheme(themeMode:themeTokens:) to control the visual appearance of SDK modals.
SDKColorOverrides
SDKColorOverridesPer-mode color overrides. All fields are optional; unset fields fall back to SDK defaults.
public struct SDKColorOverrides: Sendable {
public var primary: String?
public var secondary: String?
public var onPrimary: String?
public var borderDefault: String?
public var borderSubtle: String?
public var textPrimary: String?
public var textSecondary: String?
public var textTertiary: String?
public var surfaceDefault: String?
public var surfaceSubtle: String?
public var background: String?
}Color format: hex string (e.g.
"#FF5733","#12121280"for alpha).
HTTPNetworkConfig
HTTPNetworkConfigpublic struct HTTPNetworkConfig: Sendable {
public let timeout: TimeInterval // default 30
public let maxRetries: Int // default 3
}Core
version
versionstatic let version: StringCurrent SDK version string.
handleURL(_:)
handleURL(_:)@discardableResult
func handleURL(_ url: URL) -> BoolRoutes an incoming deep-link URL to the SDK's OAuth callback handler. Call this from your AppDelegate or SceneDelegate when the URL matches your callbackScheme.
Returns true if the URL was handled by the SDK, false otherwise.
initialize()
initialize()func initialize() async throws -> AuthResult?Attempts to restore a previously stored session. If a valid session is found, also checks cloud backup status and includes it in AuthResult.cloudBackupStatus.
- Returns
AuthResultif the session was successfully restored. - Returns
nilif no restorable session exists. - Call this on app start before checking
isLoggedIn().
Returns AuthResult? — restored session info including cloudBackupStatus, or nil.
applyTheme(themeMode:themeTokens:)
applyTheme(themeMode:themeTokens:)func applyTheme(themeMode: SDKThemeMode? = nil, themeTokens: SDKThemeTokens? = nil)Applies theme configuration to SDK modals. Takes effect from the next modal that is opened. Omitting a parameter keeps the current value.
| Parameter | Default | Description |
|---|---|---|
themeMode | current value | .light / .dark / .system |
themeTokens | current value | Color token overrides |
updateLocale(_:)
updateLocale(_:)func updateLocale(_ locale: SDKLocale?)Overrides the SDK UI language at runtime. Pass nil to revert to the system locale. Takes effect for the next SDK modal that is opened.
signIn(provider:)
signIn(provider:)func signIn(provider: SDKSignInProvider = .all) async throws -> AuthResultLaunches the OAuth sign-in flow. If provider is .all, shows the Apple/Google selection sheet first. After login, automatically checks cloud backup status and wallet state.
AuthResult.needsMigration == truemeanscreateWallet()will trigger the migration flow automatically.
| Parameter | Default | Description |
|---|---|---|
provider | .all | OAuth provider to use |
Returns AuthResult with cloudBackupStatus and needsMigration set.
signInAgain()
signInAgain()func signInAgain() async throws -> AuthResultRe-authenticates using the stored provider. If the obtained account differs from the stored session, throws CROSSxError.accountMismatch without overwriting the session.
Returns AuthResult after re-authentication.
Throws CROSSxError.accountMismatch if the re-authenticated account does not match the stored session.
signInWithCreate(provider:)
signInWithCreate(provider:)func signInWithCreate(provider: SDKSignInProvider = .all) async throws -> AuthResultCalls signIn(provider:) then createWallet() automatically in one step. If the wallet already exists, returns immediately without creating another. Returns with walletAddress set.
| Parameter | Default | Description |
|---|---|---|
provider | .all | OAuth provider to use |
Returns AuthResult with walletAddress set.
signInWithJWT(idToken:providerSub:provider:)
signInWithJWT(idToken:providerSub:provider:)func signInWithJWT(
idToken: String,
providerSub: String? = nil,
provider: String? = nil
) async throws -> AuthResultInjects an externally obtained Firebase ID token directly into the SDK session, bypassing the OAuth flow. The backend exchanges the token via /social/login. All fields are stored identically to a normal signIn(), so getUserInfo() returns complete data.
| Parameter | Default | Description |
|---|---|---|
idToken | — | Firebase ID token |
providerSub | nil | OAuth provider's unique user ID (Google/Apple sub). Extracted from idToken if omitted |
provider | nil | Provider identifier (e.g. "google", "apple"). Extracted from idToken if omitted |
Returns AuthResult with cloudBackupStatus and needsMigration set.
Throws CROSSxError.authFailed if backend token exchange or verification fails.
signOut()
signOut()func signOut() async throwsEnds the current session and clears all local data, including the cached wallet password.
refreshToken()
refreshToken()func refreshToken() async throws -> StringReturns a valid access token; refreshes via the stored refresh token if the current token is expired or close to expiry.
Returns a valid access token as a String.
Throws CROSSxError.sessionExpired if there is no token, refresh fails, or the session does not exist.
isLoggedIn()
isLoggedIn()func isLoggedIn() -> BoolReturns true if a stored access token exists and has not expired. This is a synchronous, local check — no network call is made.
ensureLoggedIn()
ensureLoggedIn()func ensureLoggedIn() async -> BoolEnsures the current session is usable. If the access token is already valid, returns true immediately. Otherwise attempts a token refresh.
Returns Boolean — true if a valid session is available, false if the session cannot be restored.
getUserInfo()
getUserInfo()func getUserInfo() async throws -> SDKUserInfoBuilds SDKUserInfo from the JWT payload, stored OAuth tokens, and wallet address list.
Returns SDKUserInfo with provider info, tokens, email, sub, and wallet addresses.
Wallet Password and Biometrics
The SDK may prompt for a PIN (wallet password) before signing and sending. The PIN is cached after first entry and reused.
canUseBiometric()
canUseBiometric()func canUseBiometric() -> BoolReturns true if biometric hardware (Face ID / Touch ID) is available and enrolled on the device.
isBiometricEnabled()
isBiometricEnabled()func isBiometricEnabled() -> BoolReturns true if the stored wallet PIN is currently protected by Face ID / Touch ID.
setBiometricEnabled(_:)
setBiometricEnabled(_:)func setBiometricEnabled(_ enabled: Bool) async throwsEnables or disables biometric protection for the cached wallet PIN. If no PIN is cached, shows the Enter PIN modal first.
| Parameter | Description |
|---|---|
enabled | true to enable Face ID / Touch ID protection, false to disable |
Throws CROSSxError.biometricFailed if biometric recognition fails.
Throws CROSSxError.userReject if the user cancels the biometric prompt or PIN modal.
Wallet Password Management
These methods accept the password directly — no PIN modal is shown. Collect the PIN from your own UI before calling.
verifyPassword(_:)
verifyPassword(_:)func verifyPassword(_ password: String) async throws -> BoolCalls POST /mnemonic/verify-password to verify the wallet password against the server. The password is not cached.
Returns true if the password is correct.
Throws on network error or authentication failure.
changePassword(password:newPassword:)
changePassword(password:newPassword:)func changePassword(password: String, newPassword: String) async throws -> ChangePasswordResponseVerifies the current password and replaces it with the new one via POST /mnemonic/change-password.
| Parameter | Description |
|---|---|
password | Current wallet password |
newPassword | New wallet password |
Throws CROSSxError.passwordWrong if the current password does not match.
exportMnemonic(password:)
exportMnemonic(password:)func exportMnemonic(password: String) async throws -> GetMnemonicResponseReturns the wallet mnemonic phrase via POST /mnemonic/mnemonic. No UI is shown — pass the password collected from your own UI.
Throws CROSSxError.passwordWrong if the password does not match.
exportPrivateKey(password:index:)
exportPrivateKey(password:index:)func exportPrivateKey(password: String, index: Int = 0) async throws -> GetPrivateKeyResponseReturns the private key for the given derivation index via POST /mnemonic/private-key. No UI is shown — pass the password collected from your own UI.
| Parameter | Default | Description |
|---|---|---|
password | — | Wallet password collected from your UI |
index | 0 | HD wallet derivation index |
Throws CROSSxError.passwordWrong if the password does not match.
Address / Wallet
checkWallet()
checkWallet()func checkWallet() async throws -> WalletCheckStatusQueries the server for the current wallet state without creating or modifying anything. Requires a valid access token but does not require authentication.
Returns WalletCheckStatus — .exists | .migrationRequired | .notFound.
createWallet(migrateAutomatically:)
createWallet(migrateAutomatically:)func createWallet(migrateAutomatically: Bool = true) async throws -> CreateWalletResponseCreates a new wallet or migrates an existing one, with UI for PIN/password entry.
| Parameter | Default | Description |
|---|---|---|
migrateAutomatically | true | When .migrationRequired: true shows migration UI, false throws CROSSxError.migrationRequired |
Branches:
.exists— prompts for the existing PIN if not cached; returns the current address..migrationRequired+migrateAutomatically = true— shows Wallet Found → PIN migration UI..migrationRequired+migrateAutomatically = false— throwsCROSSxError.migrationRequired..notFound— creates a new wallet and prompts for a new PIN.
Returns CreateWalletResponse with the resolved address.
getAddress(index:)
getAddress(index:)func getAddress(index: Int = 0) async throws -> GetAddressResponseReturns the wallet address at the given index. Prompts for PIN via Enter PIN modal if the password is not cached.
| Parameter | Default | Description |
|---|---|---|
index | 0 | HD wallet derivation index |
Returns GetAddressResponse — address and index.
getAddresses()
getAddresses()func getAddresses() async throws -> GetAddressesResponseReturns all cached wallet addresses. Returns an empty array if no addresses are cached. Each address includes the name label set by setAddressNames(_:).
Returns GetAddressesResponse — addresses: [WalletAddressInfo].
selectWallet(currentAddress:)
selectWallet(currentAddress:)func selectWallet(currentAddress: String? = nil) async throws -> WalletAddressInfo?Presents an HD wallet selector modal. Tapping "add a wallet" derives the next HD wallet index automatically.
| Parameter | Default | Description |
|---|---|---|
currentAddress | nil | Address to highlight with a "selected" badge |
Returns WalletAddressInfo? — the selected wallet, or nil if the user dismisses the modal.
Throws CROSSxError.sessionExpired if not logged in.
recoverWallet(shareC:)
recoverWallet(shareC:)func recoverWallet(shareC: String) async throws -> RecoverWalletResponseRecovers a wallet using a cloud backup share.
Returns RecoverWalletResponse — resolved address.
Chain Management
Chain management APIs do not require authentication. They only check the project whitelist.
getChains()
getChains()func getChains() async throws -> [ChainInfo]Returns all chains registered for the project, each with their chainId and rpcUrl.
Returns [ChainInfo].
getChain(chainId:)
getChain(chainId:)func getChain(chainId: String) async throws -> ChainInfoReturns the chain info for the given CAIP-2 chainId.
Returns ChainInfo — chainId and rpcUrl.
Throws CROSSxError.unsupportedChain if the chain is not registered for the project.
getRpcUrl(for:)
getRpcUrl(for:)func getRpcUrl(for chainId: String) async throws -> StringReturns the RPC URL for the given CAIP-2 chainId.
Returns String — the RPC URL.
Throws CROSSxError.unsupportedChain if the chain is not registered for the project.
Signing / Sending
All signing and sending methods require chainId. Use CAIP-2 eip155:<number> format (e.g. eip155:1, eip155:612044).
If dappName is nil, SDKConfig.appName is used.
Auto gas resolution for sendTransaction / sendTransactionAndWait
If nonce, gasLimit, or gas price fields are omitted from UnsignedTransaction, the SDK resolves them automatically via RPC before broadcasting:
nonce→eth_getTransactionCount(pending)gasLimit→eth_estimateGas- Gas price → EIP-1559 (
baseFeePerGas + 1 Gwei) if supported, otherwise legacy2 Gweifallback
signMessage(_:chainId:from:dappName:accountName:)
signMessage(_:chainId:from:dappName:accountName:)func signMessage(
_ message: String,
chainId: String,
from: String? = nil,
dappName: String? = nil,
accountName: String = "Account"
) async throws -> SignMessageResponseShows a confirmation dialog and signs a plain-text message (EIP-191) with the user's wallet.
| Parameter | Default | Description |
|---|---|---|
message | — | Plain text message to sign |
chainId | — | CAIP-2 chain identifier (e.g. eip155:1) |
from | nil | Signing address |
dappName | nil | DApp display name shown in the UI (falls back to SDKConfig.appName) |
accountName | "Account" | Account label shown in the UI |
Returns SignMessageResponse — signature: String?.
signTypedData(_:chainId:from:dappName:accountName:) — JSON string
signTypedData(_:chainId:from:dappName:accountName:) — JSON stringfunc signTypedData(
_ typedDataJson: String,
chainId: String,
from: String? = nil,
dappName: String? = nil,
accountName: String = "Account"
) async throws -> SignTypedDataResponseShows a confirmation dialog and signs EIP-712 typed data supplied as a JSON string. Routes to POST /mnemonic/sign-typed-data/:chainId.
For on-chain typed data, use chainId = "eip155:<number>" and ensure typedData.domain.chainId exists and matches the numeric part. Server mismatch errors return code -10026 (domain chainId mismatch).
Returns SignTypedDataResponse — signature: String?.
signTypedData(_:chainId:from:dappName:accountName:) — JSON Data
signTypedData(_:chainId:from:dappName:accountName:) — JSON Datafunc signTypedData(
_ typedDataJSON: Data,
chainId: String,
from: String? = nil,
dappName: String? = nil,
accountName: String = "Account"
) async throws -> SignTypedDataResponseSame as above, but accepts raw JSON Data instead of a String.
signTypedDataOffchain(_:from:dappName:accountName:)
signTypedDataOffchain(_:from:dappName:accountName:)// JSON string overload
func signTypedDataOffchain(
_ typedDataJson: String,
from: String? = nil,
dappName: String? = nil,
accountName: String = "Account"
) async throws -> SignTypedDataResponse
// JSON Data overload
func signTypedDataOffchain(
_ typedDataJSON: Data,
from: String? = nil,
dappName: String? = nil,
accountName: String = "Account"
) async throws -> SignTypedDataResponseSigns EIP-712 typed data for off-chain use cases where domain.chainId is absent. Internally sets chainId = "0". Use this instead of signTypedData(_:chainId:...) when the payload omits domain.chainId.
Returns SignTypedDataResponse — signature: String?.
signTransaction(_:chainId:dappName:networkName:estimatedFee:amount:)
signTransaction(_:chainId:dappName:networkName:estimatedFee:amount:)func signTransaction(
_ unsignedTx: UnsignedTransaction,
chainId: String,
dappName: String? = nil,
networkName: String? = nil,
estimatedFee: String? = nil,
amount: String? = nil
) async throws -> SignTransactionResponseShows a confirmation dialog and signs a transaction. The signed transaction is not broadcast — use sendTransaction to sign and broadcast in one step.
| Parameter | Default | Description |
|---|---|---|
networkName | nil | Human-readable network name shown in the confirmation UI |
estimatedFee | nil | Fee string shown in the confirmation UI |
amount | nil | Amount string shown in the confirmation UI |
Returns SignTransactionResponse — signedTx: String?, txHash: String?.
sendTransaction(_:chainId:dappName:networkName:estimatedFee:amount:)
sendTransaction(_:chainId:dappName:networkName:estimatedFee:amount:)func sendTransaction(
_ unsignedTx: UnsignedTransaction,
chainId: String,
dappName: String? = nil,
networkName: String? = nil,
estimatedFee: String? = nil,
amount: String? = nil
) async throws -> SendTransactionResponseShows a confirmation dialog, signs, and broadcasts the transaction to the network. Missing gas fields are resolved automatically via RPC.
Returns SendTransactionResponse — txHash: String?.
sendTransactionAndWait(_:chainId:dappName:networkName:estimatedFee:amount:options:)
sendTransactionAndWait(_:chainId:dappName:networkName:estimatedFee:amount:options:)func sendTransactionAndWait(
_ unsignedTx: UnsignedTransaction,
chainId: String,
dappName: String? = nil,
networkName: String? = nil,
estimatedFee: String? = nil,
amount: String? = nil,
options: PollingOptions = PollingOptions()
) async throws -> SendTransactionAndWaitResponseSame as sendTransaction but polls for the on-chain receipt before returning. Displays "Transaction complete" or "Transaction reverted" in the confirmation UI based on the receipt status.
| Parameter | Default | Description |
|---|---|---|
options | PollingOptions() | Polling interval and timeout (default: 2s interval, 60s timeout) |
Returns SendTransactionAndWaitResponse — txHash: String, receipt: TransactionReceipt.
sendTransactionWithWaitForReceipt(_:chainId:dappName:networkName:estimatedFee:amount:timeoutMs:pollIntervalMs:)
sendTransactionWithWaitForReceipt(_:chainId:dappName:networkName:estimatedFee:amount:timeoutMs:pollIntervalMs:)func sendTransactionWithWaitForReceipt(
_ unsignedTx: UnsignedTransaction,
chainId: String,
dappName: String? = nil,
networkName: String? = nil,
estimatedFee: String? = nil,
amount: String? = nil,
timeoutMs: Int = 30_000,
pollIntervalMs: Int = 1_000
) async throws -> TransactionReceiptAndroid-compatible overload of sendTransactionAndWait. Returns TransactionReceipt directly.
| Parameter | Default | Description |
|---|---|---|
timeoutMs | 30_000 | Maximum time to wait for receipt (ms) |
pollIntervalMs | 1_000 | Polling interval (ms) |
Returns TransactionReceipt.
RPC / Helpers
Direct RPC calls route through the chain's RPC URL (resolved via getChain). Use CAIP-2 eip155:<number> format for chainId.
walletRpc(request:chainId:)
walletRpc(request:chainId:)func walletRpc(request: JsonRpcRequest, chainId: String) async throws -> StringGeneric JSON-RPC request sent directly to the chain's RPC node. Use for reads and calls (e.g. eth_call). For signing and broadcasting, use the dedicated APIs.
Returns JSON-RPC result as a String (hex values, or JSON string for object results).
getBalance(address:chainId:blockTag:)
getBalance(address:chainId:blockTag:)func getBalance(address: String, chainId: String, blockTag: String = "latest") async throws -> StringCalls eth_getBalance(address, blockTag) against the chain's RPC URL.
| Parameter | Default | Description |
|---|---|---|
address | — | EVM wallet address |
chainId | — | CAIP-2 chain identifier |
blockTag | "latest" | Block tag ("latest", "pending", etc.) |
Returns hex string balance in wei, e.g. "0xde0b6b3a7640000".
getTokenBalance(contractAddress:ownerAddress:chainId:blockTag:)
getTokenBalance(contractAddress:ownerAddress:chainId:blockTag:)func getTokenBalance(
contractAddress: String,
ownerAddress: String,
chainId: String,
blockTag: String = "latest"
) async throws -> StringCalls eth_call with the ERC-20 balanceOf selector to retrieve an ERC-20 token balance.
| Parameter | Default | Description |
|---|---|---|
contractAddress | — | ERC-20 token contract address |
ownerAddress | — | Wallet address to query the balance for |
chainId | — | CAIP-2 chain identifier |
blockTag | "latest" | Block tag |
Returns hex string balance in the token's smallest unit.
getNonce(address:chainId:blockTag:)
getNonce(address:chainId:blockTag:)func getNonce(address: String, chainId: String, blockTag: String = "pending") async throws -> StringCalls eth_getTransactionCount(address, blockTag). Use "pending" (default) to include pending transactions — recommended before signing or sending.
| Parameter | Default | Description |
|---|---|---|
address | — | EVM wallet address |
chainId | — | CAIP-2 chain identifier |
blockTag | "pending" | Block tag ("pending" recommended for pre-sign nonce) |
Returns hex string nonce, e.g. "0x5".
getGasPrice(chainId:)
getGasPrice(chainId:)func getGasPrice(chainId: String) async throws -> StringCalls eth_gasPrice against the chain's RPC URL.
Returns hex string gas price in wei, e.g. "0x3B9ACA00".
getMaxPriorityFeePerGas(chainId:)
getMaxPriorityFeePerGas(chainId:)func getMaxPriorityFeePerGas(chainId: String) async throws -> StringCalls eth_maxPriorityFeePerGas against the chain's RPC URL.
Returns hex string priority fee in wei.
getBaseFeePerGas(chainId:)
getBaseFeePerGas(chainId:)func getBaseFeePerGas(chainId: String) async throws -> String?Fetches the latest block header and extracts baseFeePerGas. Returns nil for legacy chains that do not support EIP-1559.
Returns hex string base fee in wei, or nil for legacy chains.
estimateGas(_:chainId:)
estimateGas(_:chainId:)func estimateGas(_ unsignedTx: UnsignedTransaction, chainId: String) async throws -> StringCalls eth_estimateGas for the given transaction.
Returns hex string gas limit estimate, e.g. "0x5208".
getTransactionReceipt(txHash:chainId:)
getTransactionReceipt(txHash:chainId:)func getTransactionReceipt(txHash: String, chainId: String) async throws -> TransactionReceipt?Calls eth_getTransactionReceipt for the given transaction hash.
Returns TransactionReceipt? — nil if the transaction is still pending.
waitForTransaction(txHash:chainId:options:)
waitForTransaction(txHash:chainId:options:)func waitForTransaction(
txHash: String,
chainId: String,
options: PollingOptions = PollingOptions()
) async throws -> TransactionReceiptPolls for a transaction receipt until confirmed or timed out.
| Parameter | Default | Description |
|---|---|---|
txHash | — | Transaction hash to wait for |
chainId | — | CAIP-2 chain identifier |
options | PollingOptions() | Polling interval and timeout (default: 2s interval, 60s timeout) |
Returns TransactionReceipt.
waitForTxAndGetReceipt(txHash:chainId:timeoutMs:pollIntervalMs:)
waitForTxAndGetReceipt(txHash:chainId:timeoutMs:pollIntervalMs:)func waitForTxAndGetReceipt(
txHash: String,
chainId: String,
timeoutMs: Int = 30_000,
pollIntervalMs: Int = 1_000
) async throws -> TransactionReceiptAndroid-compatible overload of waitForTransaction.
| Parameter | Default | Description |
|---|---|---|
txHash | — | Transaction hash to wait for |
chainId | — | CAIP-2 chain identifier |
timeoutMs | 30_000 | Maximum wait time (ms) |
pollIntervalMs | 1_000 | Polling interval (ms) |
Returns TransactionReceipt.
Types
UnsignedTransaction
UnsignedTransaction| Field | Type | Description |
|---|---|---|
chainId | String? | CAIP-2 chain identifier |
from | String? | Sender address |
to | String? | Recipient address |
value | String? | ETH value (hex string) |
data | String? | Call data (hex string) |
nonce | String? | Transaction nonce (hex string); auto-resolved if omitted |
gasLimit | String? | Gas limit (hex string); auto-resolved if omitted |
gasPrice | String? | Gas price for legacy transactions (hex string) |
maxFeePerGas | String? | EIP-1559 max fee (hex string) |
maxPriorityFeePerGas | String? | EIP-1559 priority fee (hex string) |
PollingOptions
PollingOptions| Field | Default | Description |
|---|---|---|
intervalMs | 2000 | Polling interval in milliseconds |
timeoutMs | 60_000 | Maximum polling duration in milliseconds |
JsonRpcRequest
JsonRpcRequestpublic struct JsonRpcRequest: Codable, Sendable {
public let jsonrpc: String // always "2.0"
public let id: Int // default 1
public let method: String
public let params: [JsonRpcParam]
// Convenience init for simple string params
public init(id: Int = 1, method: String, params: [String] = [])
// Mixed params init (for eth_call etc.)
public init(id: Int = 1, method: String, params: [JsonRpcParam])
}
public enum JsonRpcParam: Sendable, Codable {
case string(String)
case bool(Bool)
case object([String: String])
}JsonRpcResponse
JsonRpcResponsepublic struct JsonRpcResponse: Sendable, Codable {
public let jsonrpc: String
public let id: Int
public let error: JsonRpcError?
public let resultData: Data? // raw JSON bytes of result field
public var result: String? // result as String (e.g. hex values)
public var isResultNull: Bool // true if result is null (pending receipt etc.)
public func decodeResult<T: Decodable>(_ type: T.Type) throws -> T?
}JsonRpcError
JsonRpcError| Field | Description |
|---|---|
code | JSON-RPC error code |
message | Error message |
TransactionReceipt
TransactionReceiptpublic struct TransactionReceipt: Sendable, Decodable {
public let transactionHash: String
public let blockHash: String
public let blockNumber: String
public let from: String
public let to: String? // nil for contract creation
public let gasUsed: String
public let effectiveGasPrice: String
public let status: String // "0x1" = success, "0x0" = reverted
public let transactionIndex: String
public let type: String
}AuthResult
AuthResultpublic struct AuthResult: Sendable {
public let success: Bool
public let walletAddress: String?
public let user: UserInfo?
public let cloudBackupStatus: CloudBackupStatus?
public let needsMigration: Bool?
}CloudBackupStatus
CloudBackupStatuspublic struct CloudBackupStatus: Sendable {
public let hasBackup: Bool // true if a legacy native app backup exists
public let primaryData: PrimaryStoreData?
public let nonce: Int?
}If
hasBackupistrue, the user has a legacy wallet backup recoverable via thecreateWallet()migration flow.
WalletCheckStatus
WalletCheckStatuspublic enum WalletCheckStatus: String, Codable, Sendable {
case exists = "exists"
case migrationRequired = "migration_required"
case notFound = "not_found"
}UserInfo
UserInfo| Field | Description |
|---|---|
id | Internal user ID |
email | User email |
SDKUserInfo
SDKUserInfopublic struct SDKUserInfo: Sendable {
public let status: String // "success"
public let data: SDKUserInfoData
public let loginType: String? // "google" or "apple"
public let addresses: [WalletAddressInfo]
// Convenience accessors (delegated from data)
public var id: String // data.sub
public var email: String? // data.email
public var provider: String? // data.provider
public var accessToken: String // data.accessToken
public var idToken: String? // data.idToken
public var sub: String // data.sub
public var providerSub: String? // data.providerSub
}SDKUserInfoData
SDKUserInfoDatapublic struct SDKUserInfoData: Sendable {
public let provider: String? // "google" or "apple"
public let accessToken: String
public let idToken: String?
public let email: String?
public let sub: String // JWT subject (user ID)
public let providerSub: String? // OAuth provider's original sub
}WalletAddressInfo
WalletAddressInfo| Field | Description |
|---|---|
address | Wallet address |
index | HD wallet derivation index |
ChainInfo
ChainInfopublic struct ChainInfo: Codable, Sendable, Equatable {
public let chainId: String // CAIP-2 format, e.g. "eip155:612044"
public let rpcUrl: String
}RecoverWalletResponse
RecoverWalletResponse| Field | Description |
|---|---|
address | Recovered wallet address |
SignMessageResponse
SignMessageResponse| Field | Description |
|---|---|
signature | Hex signature string |
SignTypedDataResponse
SignTypedDataResponse| Field | Description |
|---|---|
signature | Hex signature string |
SignTransactionResponse
SignTransactionResponse| Field | Description |
|---|---|
signedTx | Signed transaction hex string |
txHash | Transaction hash |
SendTransactionResponse
SendTransactionResponse| Field | Description |
|---|---|
txHash | Broadcast transaction hash |
SendTransactionAndWaitResponse
SendTransactionAndWaitResponse| Field | Description |
|---|---|
txHash | Transaction hash |
receipt | Confirmed TransactionReceipt |
Errors
All SDK errors are cases of CROSSxError.
Auth errors
| Error | Description |
|---|---|
notAuthenticated | No active session; user must sign in |
authFailed | Authentication failed (backend rejection or invalid token) |
tokenExpired | Access token is expired |
sessionExpired | Access token unusable and refresh failed. Requires sign-out |
accountMismatch | signInAgain() obtained a different account than the stored session |
User action
| Error | Description |
|---|---|
userRejected | User dismissed a confirmation or wallet modal |
userReject | User cancelled a biometric or PIN prompt |
Wallet errors
| Error | Description |
|---|---|
migrationRequired | Wallet requires migration and migrateAutomatically = false |
migrationPinLocked | Too many wrong migration PINs; check associated PinLockInfo |
walletInconsistentState | Internal wallet state is inconsistent |
passwordWrong | Wrong wallet password entered |
passwordLocked | Too many wrong password attempts; check associated PinLockInfo |
biometricFailed | Biometric recognition failed (iOS) |
Sign / send errors
| Error | Description |
|---|---|
signFailed | Signing operation failed |
transactionFailed | Transaction was rejected or reverted |
Chain errors
| Error | Description |
|---|---|
unsupportedChain | Chain is not registered for the project |
invalidChainId | Provided chainId is malformed |
Other errors
| Error | Description |
|---|---|
networkError | Network request failed |
invalidConfig | SDK configuration is invalid |
configurationMissing | Required Info.plist key is missing |
unknown | Unexpected error |
Message strings may vary with SDK resources and locale.
Wallet gateway error codes
| Code | Description |
|---|---|
-10026 | domain chainId mismatch — domain.chainId in the payload does not match the request chainId |