API Reference
Unity SDK API Reference
This page documents the public API surface of CROSSxSDK for Unity.
Configuration Types
SDKConfig
SDKConfigclass SDKConfig
{
string ProjectId { get; set; } // default: "unity-sample"
string AppId { get; set; } // default: Application.identifier
string AppName { get; set; } // default: "App"
SDKLoginProvider LoginProvider { get; set; } // default: All
string DefaultChainId { get; set; } // default: "eip155:612055"
string Locale { get; set; } // default: "en"
ThemeMode Theme { get; set; } // default: Dark
ThemeTokens ThemeTokens { get; set; }
string OAuthServerUrl { get; set; }
string AuthApiUrl { get; set; }
string EmbeddedWalletGatewayUrl { get; set; }
bool Debug { get; set; } // default: false
string CustomUriScheme => $"crossx-{ProjectId}" // read-only
string WebkitCustomUriScheme => $"webkit-{ProjectId}" // read-only
}Gateway whitelist headers are added automatically on authenticated wallet/RPC calls:
X-Project-Id:ProjectIdX-App-Id:AppId(defaults toApplication.identifier)X-App-Type:android/ios/windows(per build target)
enum SDKLoginProvider { All, Google, Apple }
Allshows the login provider selector modal.Applego directly to that provider. Default isAll.
Theme
enum ThemeMode { Light, Dark, System }
class ThemeTokens
{
ThemeColorOverrides Light { get; set; }
ThemeColorOverrides Dark { get; set; }
}ThemeColorOverrides
ThemeColorOverridesclass ThemeColorOverrides
{
Color? Primary
Color? Secondary
Color? OnPrimary
Color? BorderDefault
Color? BorderSubtle
Color? TextIconPrimary
Color? TextIconSecondary
Color? TextIconTertiary
Color? SurfaceDefault
Color? SurfaceSubtle
Color? Bg
}Color format: Unity
Colorstruct.
Factory
static class CROSSxSDKFactory
{
static CROSSxSDK Create(SDKConfig config)
}Creates and returns a CROSSxSDK instance. This is the only way to instantiate the SDK — do not call new CROSSxSDK() directly.
Core API
IsInitialized
IsInitializedbool IsInitialized { get; }true after InitializeAsync() has completed successfully. Methods that require initialization will throw InvalidOperationException if called before this.
InitializeAsync()
InitializeAsync()Task<AuthResult> InitializeAsync()Returns: AuthResult if a prior session is restored, null if no session exists.
Restores an existing session at app startup. Must be called once before any other SDK method. If a stored session is found, refreshes the token if expired and returns the auth state. Sets IsInitialized to true.
EnableSignConfirmation(uiRoot, theme?, appName?)
EnableSignConfirmation(uiRoot, theme?, appName?)void EnableSignConfirmation(
VisualElement uiRoot,
ThemeMode? theme = null,
string appName = null)| Parameter | Type | Required | Description |
|---|---|---|---|
uiRoot | VisualElement | Yes | UI Toolkit root element to attach modals to |
theme | ThemeMode? | No | Override theme. Falls back to SDKConfig.Theme. |
appName | string | No | Override app name displayed in confirmation modals. Falls back to SDKConfig.AppName. |
Enables the sign confirmation modal system. Must be called before any signing or sending methods. Attaches all modal UI to the provided VisualElement and applies the CJK font fallback for Korean/Chinese/Japanese text rendering on Unity 2022.3 and earlier.
ApplyTheme(themeMode?, themeTokens?)
ApplyTheme(themeMode?, themeTokens?)void ApplyTheme(ThemeMode? themeMode = null, ThemeTokens themeTokens = null)| Parameter | Type | Required | Description |
|---|---|---|---|
themeMode | ThemeMode? | No | Theme mode to apply |
themeTokens | ThemeTokens | No | Color token overrides for light/dark modes |
Changes the confirmation modal theme at runtime. Takes effect on the next modal open.
SetLocale(locale)
SetLocale(locale)void SetLocale(string locale)| Parameter | Type | Required | Description |
|---|---|---|---|
locale | string | Yes | Locale code (e.g. "en", "ko") |
Changes the modal UI language at runtime. Takes effect on the next modal open.
GetLocale()
GetLocale()string GetLocale()Returns: Current locale string (e.g. "en" or "ko").
Returns the currently active locale used for modal UI text.
SignInAsync(provider?)
SignInAsync(provider?)Task<AuthResult> SignInAsync(SDKLoginProvider? provider = null)| Parameter | Type | Required | Description |
|---|---|---|---|
provider | SDKLoginProvider? | No | Login provider. If null or All and UI is enabled, the login selector modal is shown. |
Returns: AuthResult
Opens the OAuth sign-in flow. If provider is null or All and EnableSignConfirmation() has been called, the login provider selector modal is shown. Otherwise falls back to SDKConfig.LoginProvider. Throws OperationCanceledException if the user cancels.
SignInAsync(providerOrUrl)
SignInAsync(providerOrUrl)Task<AuthResult> SignInAsync(string providerOrUrl)| Parameter | Type | Required | Description |
|---|---|---|---|
providerOrUrl | string | Yes | Provider path (e.g. "google", "apple") or a full OAuth URL |
Returns: AuthResult
Signs in using a provider path string or a full OAuth URL. Useful for bypassing the modal and passing a provider programmatically.
SignInAgainAsync()
SignInAgainAsync()Task<AuthResult> SignInAgainAsync()Returns: AuthResult
Re-authenticates with the existing account after a session expiry. Uses the stored login provider from the previous session without prompting for provider selection. Equivalent to the Android SDK's signInAgain(). Falls back to SignInAsync() if no stored provider is found.
SignInWithCreateAsync(provider?)
SignInWithCreateAsync(provider?)Task<AuthResult> SignInWithCreateAsync(SDKLoginProvider? provider = null)| Parameter | Type | Required | Description |
|---|---|---|---|
provider | SDKLoginProvider? | No | Login provider. If null or All and UI is enabled, the login selector modal is shown. |
Returns: AuthResult (includes wallet address after wallet setup)
Convenience method that calls SignInAsync() and then SetupWalletAsync() sequentially. Handles wallet creation or migration automatically after sign-in. Equivalent to the Android SDK's signInWithCreate().
SignOutAsync()
SignOutAsync()Task SignOutAsync()Signs out the current user. Clears the session from persistent storage and clears any cached PIN from memory. Token revocation is not performed server-side; the local token is discarded.
IsLoggedIn()
IsLoggedIn()bool IsLoggedIn()Returns: true if a session exists in storage, false otherwise.
Synchronous check based on stored session data. Does not verify token validity — use EnsureLoggedInAsync() to also validate and refresh the token.
EnsureLoggedInAsync()
EnsureLoggedInAsync()Task<bool> EnsureLoggedInAsync()Returns: true if the session is valid (refreshing the token if expired), false if no session exists or the refresh failed.
Checks whether the login session is valid and automatically refreshes the access token if it has expired. Use before performing operations that require authentication.
RefreshTokenAsync()
RefreshTokenAsync()Task<string> RefreshTokenAsync()Returns: The refreshed access token string.
Manually refreshes the access token. In most cases the SDK refreshes tokens automatically — this method is only needed for explicit token management. Only available in FirebaseBackend auth mode.
GetUserInfoAsync()
GetUserInfoAsync()Task<SDKUserInfo> GetUserInfoAsync()Returns: SDKUserInfo, or null if not logged in.
Retrieves the authenticated user's profile including ID, email, login type, and wallet addresses. Reads the session from storage and fetches the current address list from the server.
Wallet Password and Biometrics
Wallet passwords (PINs) are stored securely in memory after confirmation UI and reused for subsequent signing and sending operations within the session.
CanUseBiometric()
CanUseBiometric()bool CanUseBiometric()Returns: true if biometric authentication is hardware-available on the device.
Checks whether the device has biometric authentication capability. Currently returns false on all Unity platforms (stub for future support).
IsBiometricEnabled()
IsBiometricEnabled()bool IsBiometricEnabled()Returns: true if biometric authentication is enabled for this user.
Checks whether biometric authentication is enabled. Currently returns false on all Unity platforms (stub for future support).
SetBiometricEnabledAsync(enabled)
SetBiometricEnabledAsync(enabled)Task SetBiometricEnabledAsync(bool enabled)| Parameter | Type | Required | Description |
|---|---|---|---|
enabled | bool | Yes | true to enable biometric, false to disable |
Enables or disables biometric authentication. Currently a no-op on all Unity platforms (stub for future support).
Address / Wallet
CheckWalletAsync()
CheckWalletAsync()Task<CheckWalletResponse> CheckWalletAsync()Returns: CheckWalletResponse with one of Exists, MigrationRequired, or NotFound set to true.
Checks the wallet status for the currently logged-in user. Equivalent to the Android SDK's checkWallet(). Use before deciding whether to call SetupWalletAsync() or CreateWalletAsync().
SetupWalletAsync(sub?)
SetupWalletAsync(sub?)Task<SetupWalletResult> SetupWalletAsync(string sub = null)| Parameter | Type | Required | Description |
|---|---|---|---|
sub | string | No | Optional user subject identifier for migration flows |
Returns: SetupWalletResult
Checks the wallet status and automatically enters the appropriate flow: verify an existing wallet (PIN prompt), migrate a legacy CROSSx wallet, or create a new wallet (PIN creation). All PIN/password UI is managed internally by the SDK. Equivalent to calling CreateWalletAsync(migrateAutomatically: true).
CreateWalletAsync(migrateAutomatically?)
CreateWalletAsync(migrateAutomatically?)Task<SetupWalletResult> CreateWalletAsync(bool migrateAutomatically = true)| Parameter | Type | Required | Description |
|---|---|---|---|
migrateAutomatically | bool | No | If false, throws CROSSxException(MigrationRequired) when migration is needed instead of running the migration flow. Default: true. |
Returns: SetupWalletResult
Equivalent to the Android SDK's createWallet(migrateAutomatically). Checks wallet state and handles exists / migration_required / not_found accordingly. When migrateAutomatically is false and migration is required, throws CROSSxException with CROSSxErrorType.MigrationRequired.
GetAddressAsync(index?)
GetAddressAsync(index?)Task<GetAddressResponse> GetAddressAsync(int index = 0)| Parameter | Type | Required | Description |
|---|---|---|---|
index | int | No | Wallet derivation index. Default: 0. |
Returns: GetAddressResponse containing address and index.
Retrieves the wallet address for a specific derivation index. Prompts the user for PIN if not already cached in memory. Throws OperationCanceledException if the user cancels PIN input.
GetAddressesAsync()
GetAddressesAsync()Task<GetAddressesResponse> GetAddressesAsync()Returns: GetAddressesResponse containing addresses[] — all cached wallet addresses.
Retrieves the list of all cached wallet addresses for the current user without requiring PIN input.
SelectWalletAsync(selectedAddress?)
SelectWalletAsync(selectedAddress?)Task<WalletSelectionResult> SelectWalletAsync(string selectedAddress = null)| Parameter | Type | Required | Description |
|---|---|---|---|
selectedAddress | string | No | Address to mark as "currently selected" in the wallet selector modal |
Returns: WalletSelectionResult with Address and Index, or null if the user cancels.
Opens the wallet selection modal, allowing the user to switch between multiple HD wallets or add a new one. If selectedAddress is provided, the matching wallet entry is highlighted. Requires EnableSignConfirmation() to have been called.
Signing / Sending
All sign/send methods display the SDK confirmation modal before executing. chainId must be in CAIP-2 eip155:<number> format (e.g. eip155:612044). From must be non-empty for transaction sign/send flows.
SignMessageAsync(...)
SignMessageAsync(...)Task<SignMessageResponse> SignMessageAsync(
string message,
string chainId = null,
string from = null,
string dappName = null,
string accountName = "Account")| Parameter | Type | Required | Description |
|---|---|---|---|
message | string | Yes | Plain-text message to sign |
chainId | string | No | CAIP-2 chain ID. Defaults to SDKConfig.DefaultChainId. |
from | string | No | Signer address displayed in the confirmation modal |
dappName | string | No | DApp name displayed in the confirmation modal |
accountName | string | No | Account label in the confirmation modal (default: "Account") |
Returns: SignMessageResponse containing signature.
Signs a UTF-8 message using EIP-191 personal sign. Displays a confirmation modal with the message and signer address before proceeding.
SignTypedDataAsync(...)
SignTypedDataAsync(...)// object overload
Task<SignTypedDataResponse> SignTypedDataAsync(
object typedData,
string chainId,
string from = null,
string dappName = null,
string accountName = "Account")
// Eip712TypedData overload
Task<SignTypedDataResponse> SignTypedDataAsync(
Eip712TypedData typedData,
string chainId,
string from = null,
string dappName = null,
string accountName = "Account")| Parameter | Type | Required | Description |
|---|---|---|---|
typedData | object / Eip712TypedData | Yes | EIP-712 typed data. domain.chainId must be present and match chainId. |
chainId | string | Yes | CAIP-2 chain ID. Must match typedData.domain.chainId. |
from | string | No | Signer address displayed in the confirmation modal |
dappName | string | No | DApp name displayed in the confirmation modal |
accountName | string | No | Account label in the confirmation modal (default: "Account") |
Returns: SignTypedDataResponse containing signature.
Signs EIP-712 typed structured data for on-chain use. Throws ArgumentException if typedData.domain.chainId is missing or does not match chainId. Use when typedData.domain.chainId is present (on-chain typed data).
SignTypedDataOffchainAsync(...)
SignTypedDataOffchainAsync(...)// object overload
Task<SignTypedDataResponse> SignTypedDataOffchainAsync(
object typedData,
string from = null,
string dappName = null,
string accountName = "Account")
// Eip712TypedData overload
Task<SignTypedDataResponse> SignTypedDataOffchainAsync(
Eip712TypedData typedData,
string from = null,
string dappName = null,
string accountName = "Account")| Parameter | Type | Required | Description |
|---|---|---|---|
typedData | object / Eip712TypedData | Yes | EIP-712 typed data without domain.chainId (or with chainId: 0) |
from | string | No | Signer address displayed in the confirmation modal |
dappName | string | No | DApp name displayed in the confirmation modal |
accountName | string | No | Account label in the confirmation modal (default: "Account") |
Returns: SignTypedDataResponse containing signature.
Signs EIP-712 typed data for off-chain use cases (e.g. permit signatures, order books). Use when typedData.domain.chainId is absent or zero. Throws ArgumentException if typedData.domain.chainId is present and non-zero.
SignTransactionAsync(...)
SignTransactionAsync(...)// WalletUnsignedTransaction overload (Recommended)
Task<SignTxResponse> SignTransactionAsync(
WalletUnsignedTransaction walletTx,
string dappName = null,
string networkName = null,
string estimatedFee = null,
string amount = null)
// UnsignedTx overload
Task<SignTxResponse> SignTransactionAsync(
UnsignedTx unsignedTx,
string chainId = null,
string dappName = null,
string networkName = null,
string estimatedFee = null,
string amount = null)| Parameter | Type | Required | Description |
|---|---|---|---|
walletTx | WalletUnsignedTransaction | Yes (recommended overload) | Transaction with chainId embedded in the object |
unsignedTx | UnsignedTx | Yes (raw overload) | Low-level gateway payload |
chainId | string | No | CAIP-2 chain ID. Overrides unsignedTx.chainId. Defaults to SDKConfig.DefaultChainId. |
dappName | string | No | DApp name displayed in the confirmation modal |
networkName | string | No | Network name displayed in the confirmation modal |
estimatedFee | string | No | Fee string displayed in the modal (e.g. "0.001 CROSS") |
amount | string | No | Transfer amount displayed in the modal (e.g. "1.0 CROSS") |
Returns: SignTxResponse containing signedTx and optional txHash.
Signs a transaction without broadcasting. Displays the sign confirmation modal before proceeding. Gas fields are resolved automatically if not provided. Use WalletUnsignedTransaction by default; use UnsignedTx only when you need low-level gateway payload control.
SendTransactionAsync(...)
SendTransactionAsync(...)// WalletUnsignedTransaction overload (Recommended)
Task<SendTxResponse> SendTransactionAsync(
WalletUnsignedTransaction walletTx,
string dappName = null,
string networkName = null,
string estimatedFee = null,
string amount = null,
long receiptTimeoutMs = 30000,
long receiptPollIntervalMs = 1000)
// UnsignedTx overload
Task<SendTxResponse> SendTransactionAsync(
UnsignedTx unsignedTx,
string chainId = null,
string dappName = null,
string networkName = null,
string estimatedFee = null,
string amount = null,
long receiptTimeoutMs = 30000,
long receiptPollIntervalMs = 1000)| Parameter | Type | Required | Description |
|---|---|---|---|
walletTx | WalletUnsignedTransaction | Yes (recommended overload) | Transaction with chainId embedded |
unsignedTx | UnsignedTx | Yes (raw overload) | Low-level gateway payload |
chainId | string | No | CAIP-2 chain ID. Overrides unsignedTx.chainId. Defaults to SDKConfig.DefaultChainId. |
dappName | string | No | DApp name displayed in the confirmation modal |
networkName | string | No | Network name displayed in the confirmation modal |
estimatedFee | string | No | Fee string displayed in the modal |
amount | string | No | Transfer amount displayed in the modal |
receiptTimeoutMs | long | No | Receipt polling timeout in ms (default: 30000) |
receiptPollIntervalMs | long | No | Receipt polling interval in ms (default: 1000) |
Returns: SendTxResponse containing txHash.
Signs and broadcasts a transaction. Displays a send confirmation modal followed by a transaction progress modal showing pending and mined states. Gas fields are auto-resolved if not provided.
SendTransactionWithWaitForReceiptAsync(...)
SendTransactionWithWaitForReceiptAsync(...)// WalletUnsignedTransaction overload (Recommended)
Task<JObject> SendTransactionWithWaitForReceiptAsync(
WalletUnsignedTransaction walletTx,
string dappName = null,
string networkName = null,
string estimatedFee = null,
string amount = null,
long timeoutMs = 30000,
long pollIntervalMs = 1000)
// UnsignedTx overload
Task<JObject> SendTransactionWithWaitForReceiptAsync(
UnsignedTx unsignedTx,
string chainId = null,
string dappName = null,
string networkName = null,
string estimatedFee = null,
string amount = null,
long timeoutMs = 30000,
long pollIntervalMs = 1000)| Parameter | Type | Required | Description |
|---|---|---|---|
walletTx | WalletUnsignedTransaction | Yes (recommended overload) | Transaction with chainId embedded |
unsignedTx | UnsignedTx | Yes (raw overload) | Low-level gateway payload |
chainId | string | No | CAIP-2 chain ID |
dappName | string | No | DApp name displayed in the confirmation modal |
networkName | string | No | Network name displayed in the confirmation modal |
estimatedFee | string | No | Fee string displayed in the modal |
amount | string | No | Transfer amount displayed in the modal |
timeoutMs | long | No | Receipt polling timeout in ms (default: 30000) |
pollIntervalMs | long | No | Receipt polling interval in ms (default: 1000) |
Returns: JObject — the raw receipt JSON (access fields with receipt["transactionHash"], receipt["status"], etc.)
Signs, broadcasts, and waits for the transaction receipt. Internally calls SendTransactionAsync() and then fetches the receipt. The send confirmation modal and transaction progress modal are shown as part of SendTransactionAsync().
RPC / Helpers
WalletRpcAsync(request, chainId)
WalletRpcAsync(request, chainId)Task<JsonRpcResponse> WalletRpcAsync(JsonRpcRequest request, string chainId)| Parameter | Type | Required | Description |
|---|---|---|---|
request | JsonRpcRequest | Yes | JSON-RPC 2.0 request object |
chainId | string | Yes | CAIP-2 chain ID (e.g. "eip155:612044") |
Returns: JsonRpcResponse with id, jsonrpc, result, and optional error (all camelCase fields).
Sends a JSON-RPC read-only request to the specified chain's RPC endpoint. Equivalent to the Android SDK's walletRpc(). Use for contract read calls (eth_call, etc.). Do not use for transaction signing or sending — use SignTransactionAsync() / SendTransactionAsync() instead.
chainIdis mandatory and must be in CAIP-2eip155:<number>format.
GetBalanceAsync(address, chainId, blockTag?)
GetBalanceAsync(address, chainId, blockTag?)Task<string> GetBalanceAsync(string address, string chainId, string blockTag = "latest")| Parameter | Type | Required | Description |
|---|---|---|---|
address | string | Yes | Wallet address to query |
chainId | string | Yes | CAIP-2 chain ID |
blockTag | string | No | Block tag (default: "latest") |
Returns: Hex-encoded balance in Wei (e.g. "0xde0b6b3a7640000").
Queries the native token balance for the given address via eth_getBalance.
GetNonceAsync(address, chainId, blockTag?)
GetNonceAsync(address, chainId, blockTag?)Task<string> GetNonceAsync(string address, string chainId, string blockTag = "pending")| Parameter | Type | Required | Description |
|---|---|---|---|
address | string | Yes | Wallet address to query |
chainId | string | Yes | CAIP-2 chain ID |
blockTag | string | No | Block tag (default: "pending") |
Returns: Hex-encoded nonce (e.g. "0x5").
Returns the transaction count (nonce) for the given address via eth_getTransactionCount. Defaults to "pending" block to include mempool transactions.
WaitForTxAndGetReceiptAsync(txHash, chainId, timeoutMs?, pollIntervalMs?)
WaitForTxAndGetReceiptAsync(txHash, chainId, timeoutMs?, pollIntervalMs?)Task<JObject> WaitForTxAndGetReceiptAsync(
string txHash,
string chainId,
long timeoutMs = 30000,
long pollIntervalMs = 1000)| Parameter | Type | Required | Description |
|---|---|---|---|
txHash | string | Yes | Transaction hash to poll |
chainId | string | Yes | CAIP-2 chain ID |
timeoutMs | long | No | Polling timeout in ms (default: 30000) |
pollIntervalMs | long | No | Polling interval in ms (default: 1000) |
Returns: JObject — the raw receipt JSON (access fields with receipt["transactionHash"], receipt["status"], etc.)
Polls for a transaction receipt until it is mined or the timeout is reached. Throws TimeoutException if the timeout expires before the receipt is available. Throws if the transaction reverts (status 0x0).
Key Object Details
UnsignedTx
chainId: string?from: string(required for transaction sign/send flows)to: string?value: string?data: string?nonce: string?gasLimit: string?gasPrice: string?maxFeePerGas: string?maxPriorityFeePerGas: string?
WalletUnsignedTransaction
Abstract base. Use the nested class directly:
var walletTx = new WalletUnsignedTransaction.EvmEip155("eip155:612044")
{
From = "0xYourAddress",
To = "0xRecipient",
Value = "0xde0b6b3a7640000",
Data = "0x"
};EvmEip155(string chainId): EVM EIP-155 transactionChainId: string(required, set via constructor)From: string(required for sign/send flows)To,Value,Data,Nonce,GasLimit,GasPrice,MaxFeePerGas,MaxPriorityFeePerGas
Tron(string raw, string chainId = null): placeholder, not yet supported
Eip712TypedData
Types: Dictionary<string, List<Eip712Field>>PrimaryType: stringDomain: objectMessage: object
Eip712Field
Name: stringType: string
TransactionReceipt
TransactionHash: stringBlockHash: stringBlockNumber: stringFrom: stringTo: stringGasUsed: stringEffectiveGasPrice: stringStatus: stringTransactionIndex: stringType: stringLogs: objectRawJson: string
CheckWalletResponse
result: string— raw value:"exists"|"migration_required"|"not_found"Exists: boolMigrationRequired: boolNotFound: bool
SetupWalletResult
Status: WalletSetupStatus—Verified|Created|Migrated|SkippedAddress: string?IsReady: bool—truewhenStatusisVerified,Created, orMigrated
WalletSelectionResult
Address: stringIndex: int
AuthResult
Success: boolWalletAddress: string?User: UserInfo?NeedsMigration: bool?
SDKUserInfo
Id: stringEmail: string?LoginType: string?Addresses: List<string>
SignRequestType (confirmation modal type)
PersonalSignTypedDataTransactionSendTransaction
JsonRpcRequest
id: stringjsonrpc: stringmethod: string@params: object[](JSON array — usenew object[] { ... })
Errors
CROSSxException
CROSSxExceptionclass CROSSxException : Exception
{
CROSSxErrorType ErrorType { get; }
int? ErrorCode { get; }
PinLockInfo LockInfo { get; }
}CROSSxErrorType
CROSSxErrorTypeCommon error variants (matching Android CROSSxError):
- Auth:
NotAuthenticated,AuthFailed,TokenExpired,SessionExpired,OAuthFailed,AccountMismatch - User cancel:
UserRejected - Wallet:
MigrationRequired,WalletPasswordRequired,WalletPasswordChanged,WalletInconsistentState,MigrationPinFailed,WalletPinFailed,InvalidPassword,PasswordLocked - Sign / send:
SignFailed,TransactionFailed,Timeout - Other:
NetworkError,InvalidConfig,Unknown
Notes:
SessionExpired— access token is unusable and refresh failed (e.g. refresh token expired). Requires sign-out or re-authentication viaSignInAgainAsync().AccountMismatch— user signed in with a different account than expected.InvalidPassword— wrong wallet password entered.PasswordLocked— too many wrong password attempts; checkCROSSxException.LockInfofor lockout details.MigrationRequired— thrown whenCreateWalletAsync(migrateAutomatically: false)encounters a migration-required wallet.
SessionExpiredException
SessionExpiredExceptionThrown when both access and refresh tokens are expired. The SDK shows a session expired modal allowing the user to sign in again or sign out.
GatewayException
GatewayExceptionThrown for wallet gateway API errors with ErrorCode and ErrorData.
Wallet gateway integrations may also surface:
-10040— HMAC validation failed (for example a missingX-HMAC-Signature)-10041— HMAC validation failed (for example an invalidX-HMAC-Signature)
WebView
OpenWebViewAsync(url)
OpenWebViewAsync(url)Task<WebkitResult> OpenWebViewAsync(string url)| Parameter | Type | Required | Description |
|---|---|---|---|
url | string | Yes | URL to open in the WebView |
Returns: WebkitResult with Success and optional ErrorMessage.
Opens the specified URL using the bundled CROSSx Webkit SDK. Requires InitializeAsync() to have been called.
CROSS Pay
Architecture note: Checkout creation and payment status polling are game-server responsibilities. The server holds the Merchant API Key, creates the checkout, and returns
checkoutUrl+checkoutIdto the client. The SDK handles only the in-app WebView and deep-link callback flow.
For full CROSS Pay integration details, see the CROSS Pay documentation.
OpenCrossPayAndWaitResultAsync(checkoutUrl, checkoutId, timeoutMs?)
OpenCrossPayAndWaitResultAsync(checkoutUrl, checkoutId, timeoutMs?)Task<CrossPayCallbackResult> OpenCrossPayAndWaitResultAsync(
string checkoutUrl,
string checkoutId,
long timeoutMs = 300000)| Parameter | Type | Required | Description |
|---|---|---|---|
checkoutUrl | string | Yes | Checkout URL to open in WebView |
checkoutId | string | Yes | Checkout session identifier for callback matching |
timeoutMs | long | No | Timeout in ms waiting for the deep-link callback (default: 300000) |
Returns: CrossPayCallbackResult — decoded deep-link callback envelope.
Opens the checkout URL in WebView and waits for the deep-link callback. Throws TimeoutException if the callback does not arrive within timeoutMs.
Types
CrossPayCallbackResult — decoded deep-link callback envelope
Status: string— envelope-level status:"success"|"cancel"|"failed"(from wallet web) or raw PG status (e.g."PAID")State: string?— echoed CSRF stateData: JObject?— payment data from PG (fields vary by provider)Error: string?— error message whenIsFailedRawParams: IReadOnlyDictionary<string, string>?— all raw query/fragment params from the callback URL (e.g.checkout_id,payment_id,tx_hash)IsSuccess: bool—truewhenStatus == "success"IsCancel: bool—truewhenStatus == "cancel"IsFailed: bool—truewhenStatus == "failed"
Port Interfaces
The SDK follows hexagonal architecture. All external dependencies are abstracted through ports:
| Port | Responsibility |
|---|---|
ITransportPort | HTTP requests, authorization headers, project headers |
IOAuthPort | Build login URL, open browser, parse callback |
IDeepLinkPort | Wait for deep link callback, simulate deep link |
IStoragePort | Save, load, delete persistent data |
IAuthBackendPort | Exchange OAuth token for backend tokens |
IEmbeddedWalletPort | Gateway API (create, migrate, sign, send, RPC) |