Wallet

Unreal Wallet

Wallet creation, address lookup, signing, sending, and receipt waiting.

Prerequisites

  • Signed in with SignIn(...) or SignInWithCreateAsync(...)
  • EVM chain routing requires a ChainId (recommended: eip155:<number>)
  • Confirmation UI enabled via EnableSignConfirmation(AppName)

Address and wallet APIs

// Setup wallet with UI (PIN and wallet found modals handled internally)
Sdk->SetupWalletWithUIAsync(Sub,
    FCROSSxCreateWalletDelegate::CreateLambda([](const FCROSSxCreateWalletResult& R)
    {
        UE_LOG(LogTemp, Log, TEXT("Wallet: %s"), *R.Address);
    })
);

// Create wallet with migration control
Sdk->CreateWalletWithMigrateAsync(true,
    FCROSSxCreateWalletDelegate::CreateLambda([](const FCROSSxCreateWalletResult& R) { /* ... */ })
);

// Synchronous address APIs
FCROSSxGetAddressResponse Primary = Sdk->GetAddress();
FCROSSxGetAddressResponse ByIndex = Sdk->GetAddress(0);
FCROSSxGetAddressesResponse All = Sdk->GetAddresses();

// Check wallet state
Sdk->CheckWalletAsync(
    FCROSSxCheckWalletDelegate::CreateLambda([](const FCROSSxCheckWalletResponse& R) { /* ... */ })
);

// Wallet selection with UI
Sdk->SelectWalletWithUIAsync(TEXT(""),
    FCROSSxWalletSelectionDelegate::CreateLambda([](const FCROSSxWalletSelectionResult& R) { /* ... */ })
);

Wallet password and biometrics

The SDK may show password entry and confirmation UI before signing and sending. After verification once, the password is reused for later operations.

bool bCan = Sdk->CanUseBiometric();
bool bEnabled = Sdk->IsBiometricEnabled();
Sdk->SetBiometricEnabled(true);

Message and typed data signing

Confirmation UI is shown automatically for UI Flow APIs.

FString ChainId = TEXT("eip155:612044");

// Sign message with UI
Sdk->SignMessageWithUIAsync(TEXT("Hello CROSSx"), ChainId, From,
    FCROSSxSignMessageDelegate::CreateLambda([](const FCROSSxSignMessageResponse& R)
    {
        UE_LOG(LogTemp, Log, TEXT("Signature: %s"), *R.Signature);
    })
);

// Sign typed data with UI
Sdk->SignTypedDataWithUIAsync(From, TypedDataJson, ChainId,
    FCROSSxSignTypedDataDelegate::CreateLambda([](const FCROSSxSignTypedDataResponse& R)
    {
        UE_LOG(LogTemp, Log, TEXT("Signature: %s"), *R.Signature);
    })
);

// Off-chain typed data (no chainId required)
Sdk->SignTypedDataOffchainWithUIAsync(From, TypedDataJson,
    FCROSSxSignTypedDataDelegate::CreateLambda([](const FCROSSxSignTypedDataResponse& R) { /* ... */ })
);

Transaction signing

FCROSSxUnsignedTx Tx;
Tx.ChainId = TEXT("eip155:612044");
Tx.From = TEXT("0xYourAddress");
Tx.To = TEXT("0xRecipient");
Tx.Value = TEXT("0xde0b6b3a7640000");
Tx.Data = TEXT("0x");

// Sign transaction with UI
Sdk->SignTransactionWithUIAsync(Tx, Tx.ChainId,
    FCROSSxSignTxDelegate::CreateLambda([](const FCROSSxSignTxResponse& R)
    {
        UE_LOG(LogTemp, Log, TEXT("SignedTx: %s"), *R.SignedTx);
    })
);

You can also use FCROSSxWalletUnsignedTransaction for SDK-level models:

FCROSSxWalletUnsignedTransaction WalletTx;
WalletTx.ChainId = TEXT("eip155:612044");
WalletTx.From = TEXT("0xYourAddress");
WalletTx.To = TEXT("0xRecipient");
WalletTx.Value = TEXT("0xde0b6b3a7640000");
WalletTx.Data = TEXT("0x");

FCROSSxUnsignedTx RawTx = WalletTx.ToUnsignedTx();

Sending transactions

// Send with UI
Sdk->SendTransactionWithUIAsync(Tx, Tx.ChainId,
    FCROSSxSendTxDelegate::CreateLambda([](const FCROSSxSendTxResponse& R)
    {
        UE_LOG(LogTemp, Log, TEXT("TxHash: %s"), *R.TxHash);
    })
);

Send and wait for receipt with UI

Sdk->SendTransactionWithWaitForReceiptWithUIAsync(Tx, Tx.ChainId,
    FCROSSxTxReceiptDelegate::CreateLambda([](const FCROSSxTxReceiptResponse& R)
    {
        UE_LOG(LogTemp, Log, TEXT("TxHash: %s, Status: %s"), *R.TransactionHash, *R.Status);
    }),
    TEXT(""), TEXT(""), TEXT(""),
    30000, 1000
);

Manual receipt polling

// Synchronous
FCROSSxTxReceiptResponse Receipt = Sdk->WaitForTxReceipt(
    TEXT("0x..."), TEXT("eip155:612044"), 30000, 1000
);

// Asynchronous
Sdk->WaitForTxReceiptAsync(TEXT("0x..."), TEXT("eip155:612044"), 30000, 1000,
    FCROSSxTxReceiptDelegate::CreateLambda([](const FCROSSxTxReceiptResponse& R)
    {
        UE_LOG(LogTemp, Log, TEXT("Status: %s"), *R.Status);
    })
);

RPC helpers

// JSON-RPC
FCROSSxJsonRpcRequest RpcReq;
RpcReq.Method = TEXT("eth_call");
RpcReq.Params = TEXT("[]");

FCROSSxJsonRpcResponse RpcResp = Sdk->WalletRpc(RpcReq, TEXT("eip155:612044"));

// Balance and nonce
FString Balance = Sdk->GetBalance(TEXT("0xYourAddress"), TEXT("eip155:612044"));
FString Nonce = Sdk->GetNonce(TEXT("0xYourAddress"), TEXT("eip155:612044"), TEXT("pending"));

WalletRpc is intended for contract read/call only (e.g. eth_call). Sending/signing transaction methods are not supported through this RPC API.

Confirmation UI

The SDK provides built-in Slate modals for transaction confirmation. Enable them after initialization:

Sdk->EnableSignConfirmation(TEXT("My Game"), ECROSSxThemeMode::Dark);

Modal types managed by the SDK:

  • SignConfirmationModal — sign/send confirmation
  • WalletFoundModal — existing wallet recovery prompt (managed internally)
  • PinInputModal — password entry (managed internally)
  • SessionExpiredModal — session expiry handling
  • WalletCompleteModal — wallet creation success notification
  • TransactionCompleteModal — transaction completion status

© 2025 NEXUS Co., Ltd. All Rights Reserved.