Skip to main content

Hooks API

API reference for all React Hooks provided by GIWA SDK.

All Parameters Are Optional

Most hooks can be used without any parameters. They automatically use the connected wallet address.

// Use without parameters (recommended)
const { balance } = useBalance();
const { wallet, createWallet } = useGiwaWallet();
const { sendTransaction } = useTransaction();

// Specify options when needed
const { balance } = useBalance('0x...'); // Query specific address
await createWallet({ requireBiometric: true }); // Require biometric auth

useGiwaWallet​

Wallet management Hook

import { useGiwaWallet } from 'giwa-react-native-wallet';

const {
wallet, // GiwaWallet | null
isLoading, // boolean
isInitializing, // boolean - Whether SDK is initializing
hasWallet, // boolean - wallet !== null (convenience property)
error, // Error | null
createWallet, // (options?: SecureStorageOptions) => Promise<WalletCreationResult>
recoverWallet, // (mnemonic: string, options?: SecureStorageOptions) => Promise<GiwaWallet>
importFromPrivateKey, // (privateKey: Hex, options?: SecureStorageOptions) => Promise<GiwaWallet>
loadWallet, // (options?: SecureStorageOptions) => Promise<GiwaWallet | null>
deleteWallet, // () => Promise<void>
exportMnemonic, // (options?: SecureStorageOptions) => Promise<string | null>
exportPrivateKey, // (options?: SecureStorageOptions) => Promise<Hex | null>
} = useGiwaWallet();
Checking Initialization State

isInitializing is true while the SDK is initializing. Check this value before performing wallet operations.

if (isInitializing) {
return <LoadingSpinner />;
}

Types​

interface GiwaWallet {
address: `0x${string}`;
}

interface WalletCreationResult {
wallet: GiwaWallet;
mnemonic: string;
}

interface SecureStorageOptions {
requireBiometric?: boolean;
}

Returns​

PropertyTypeDescription
walletGiwaWallet | nullConnected wallet or null
isLoadingbooleanLoading state for wallet operations
isInitializingbooleanWhether SDK is initializing
hasWalletbooleanConvenience property: wallet !== null
errorError | nullError if operation failed
createWallet(options?) => Promise<WalletCreationResult>Create new wallet
recoverWallet(mnemonic, options?) => Promise<GiwaWallet>Recover from mnemonic
importFromPrivateKey(privateKey, options?) => Promise<GiwaWallet>Import from private key
loadWallet(options?) => Promise<GiwaWallet | null>Load saved wallet
deleteWallet() => Promise<void>Delete wallet from storage
exportMnemonic(options?) => Promise<string | null>Export recovery phrase
exportPrivateKey(options?) => Promise<Hex | null>Export private key

Security Notes​

  • exportMnemonic and exportPrivateKey have Rate Limiting applied (3 times per minute, 5-minute cooldown when exceeded)
  • Sensitive data is automatically cleared from memory after 5 minutes of inactivity

useBalance​

ETH balance query Hook

import { useBalance } from 'giwa-react-native-wallet';

const {
balance, // bigint (default 0n)
formattedBalance, // string (default '0')
isLoading, // boolean
error, // Error | null
refetch, // () => Promise<void>
} = useBalance(address?: string);
Type Change

balance is always of type bigint (previously: bigint | null). The initial value is 0n, and null checks are not required.

Parameters​

NameTypeRequiredDefaultDescription
addressstringNowallet.addressAddress to query balance for

Returns​

PropertyTypeDescription
balancebigintBalance in wei (default: 0n)
formattedBalancestringBalance in ETH (default: '0')
isLoadingbooleanLoading state
errorError | nullError if query failed
refetch() => Promise<void>Manually refresh balance

useTransaction​

Transaction sending Hook

import { useTransaction } from 'giwa-react-native-wallet';

const {
sendTransaction, // (tx: TransactionRequest) => Promise<string>
waitForReceipt, // (hash: string, options?: WaitOptions) => Promise<Receipt>
estimateGas, // (tx: TransactionRequest) => Promise<GasEstimate>
getTransaction, // (hash: string) => Promise<Transaction | null>
isLoading, // boolean
error, // GiwaError | null
} = useTransaction();

Types​

interface TransactionRequest {
to: string;
value?: string; // ETH units
data?: string; // Contract call data
gasLimit?: bigint;
gasPrice?: bigint;
nonce?: number;
}

interface GasEstimate {
gasLimit: bigint;
gasPrice: bigint;
estimatedFee: string; // ETH units
}

interface WaitOptions {
confirmations?: number;
timeout?: number;
}

Returns​

PropertyTypeDescription
sendTransaction(tx: TransactionRequest) => Promise<string>Send transaction, returns tx hash
waitForReceipt(hash, options?) => Promise<Receipt>Wait for confirmation
estimateGas(tx: TransactionRequest) => Promise<GasEstimate>Estimate gas for transaction
getTransaction(hash: string) => Promise<Transaction | null>Get transaction details
isLoadingbooleanLoading state
errorGiwaError | nullError if operation failed

useTokens​

ERC-20 token management Hook

import { useTokens } from 'giwa-react-native-wallet';

const {
getBalance, // (tokenAddress: string) => Promise<TokenBalance>
transfer, // (tokenAddress: string, to: string, amount: string) => Promise<string>
approve, // (tokenAddress: string, spender: string, amount: string) => Promise<string>
allowance, // (tokenAddress: string, spender: string) => Promise<AllowanceResult>
getTokenInfo, // (tokenAddress: string) => Promise<TokenInfo>
isLoading, // boolean
} = useTokens();

Types​

interface TokenBalance {
token: TokenInfo;
balance: bigint;
formattedBalance: string;
}

interface TokenInfo {
address: string;
name: string;
symbol: string;
decimals: number;
totalSupply?: bigint;
}

interface AllowanceResult {
amount: bigint;
formattedAmount: string;
}

Returns​

PropertyTypeDescription
getBalance(tokenAddress) => Promise<TokenBalance>Get token balance
transfer(tokenAddress, to, amount) => Promise<string>Transfer tokens
approve(tokenAddress, spender, amount) => Promise<string>Approve spender
allowance(tokenAddress, spender) => Promise<AllowanceResult>Check allowance
getTokenInfo(tokenAddress) => Promise<TokenInfo>Get token metadata
isLoadingbooleanLoading state

useBridge​

L1↔L2 Bridge Hook — deposits, withdrawals, and the withdrawal prove/finalize flow

L1 Configuration Required

Deposits (depositETH/depositToken) and every withdrawal step past initiation (getWithdrawalStatus, getTimeToProve, getTimeToFinalize, proveWithdrawal, finalizeWithdrawal) require endpoints.l1RpcUrl to be configured on GiwaProvider/GiwaConfig — the SDK ships no default. withdrawETH/withdrawToken work without it. See the Bridge guide for setup and the full withdrawal lifecycle.

import { useBridge } from 'giwa-react-native-wallet';

const {
depositETH, // (amount: string, to?: Address) => Promise<Hash>
depositToken, // (l1TokenAddress: Address, l2TokenAddress: Address, amount: bigint, to?: Address) => Promise<Hash>
withdrawETH, // (amount: string, to?: Address) => Promise<Hash>
withdrawToken, // (l2TokenAddress: Address, amount: bigint, to?: Address) => Promise<Hash>
getWithdrawalStatus, // (l2TxHash: Hash) => Promise<WithdrawalStatus>
getTimeToProve, // (l2TxHash: Hash) => Promise<GetTimeToProveReturnType>
getTimeToFinalize, // (l2TxHash: Hash) => Promise<GetTimeToFinalizeReturnType>
proveWithdrawal, // (l2TxHash: Hash) => Promise<Hash>
finalizeWithdrawal, // (l2TxHash: Hash) => Promise<Hash>
getPendingTransactions, // () => BridgeTransaction[]
getTransaction, // (hash: Hash) => BridgeTransaction | undefined
getEstimatedWithdrawalTime, // () => number (seconds)
isL1Configured, // boolean - whether endpoints.l1RpcUrl is set
isLoading, // boolean
isInitializing, // boolean
error, // Error | null
} = useBridge();

Types​

type Hash = `0x${string}`;

type WithdrawalStatus =
| 'waiting-to-prove'
| 'ready-to-prove'
| 'waiting-to-finalize'
| 'ready-to-finalize'
| 'finalized';

interface BridgeTransaction {
direction: 'deposit' | 'withdraw';
amount: bigint;
token?: Address;
l1TxHash?: Hash;
l2TxHash?: Hash;
status: 'pending' | 'confirmed' | 'proved' | 'finalized' | 'failed';
}

Returns​

PropertyTypeDescription
depositETH(amount, to?) => Promise<Hash>Deposit ETH from L1 to L2. Returns the L1 tx hash
depositToken(l1TokenAddress, l2TokenAddress, amount, to?) => Promise<Hash>Deposit ERC-20 from L1 to L2 (auto-approves if needed). Returns the L1 tx hash
withdrawETH(amount, to?) => Promise<Hash>Initiate an ETH withdrawal to L1
withdrawToken(l2TokenAddress, amount, to?) => Promise<Hash>Initiate an ERC-20 withdrawal to L1
getWithdrawalStatus(l2TxHash) => Promise<WithdrawalStatus>Current status of a withdrawal
getTimeToProve(l2TxHash) => Promise<GetTimeToProveReturnType>Non-blocking: time until provable
getTimeToFinalize(l2TxHash) => Promise<GetTimeToFinalizeReturnType>Non-blocking: time until finalizable
proveWithdrawal(l2TxHash) => Promise<Hash>Prove a withdrawal on L1. Blocks until provable (can take hours)
finalizeWithdrawal(l2TxHash) => Promise<Hash>Finalize a proved withdrawal on L1, releasing funds
getPendingTransactions() => BridgeTransaction[]Get pending deposits/withdrawals
getTransaction(hash) => BridgeTransaction | undefinedGet transaction by hash
getEstimatedWithdrawalTime() => numberGet the challenge period estimate (seconds)
isL1ConfiguredbooleanWhether endpoints.l1RpcUrl is configured
isLoadingbooleanLoading state
isInitializingbooleanWhether bridge is initializing
errorError | nullError if operation failed

Usage Example​

// Deposit 0.1 ETH to L2 (requires endpoints.l1RpcUrl)
const depositHash = await depositETH('0.1');
console.log('L1 TX Hash:', depositHash);

// Withdraw 0.1 ETH to L1
const withdrawHash = await withdrawETH('0.1');
console.log('L2 TX Hash:', withdrawHash);

// Track transaction status
const tx = getTransaction(withdrawHash);
console.log('Status:', tx?.status);

// Poll status, then prove and finalize once ready (requires endpoints.l1RpcUrl)
const status = await getWithdrawalStatus(withdrawHash);
if (status === 'ready-to-prove') {
await proveWithdrawal(withdrawHash); // blocks until provable, can take hours
} else if (status === 'ready-to-finalize') {
await finalizeWithdrawal(withdrawHash);
}

// Estimated challenge period (~7 days for OP Stack)
const time = getEstimatedWithdrawalTime(); // 604800 seconds

useFlashblocks​

Flashblocks (fast confirmation) Hook

import { useFlashblocks } from 'giwa-react-native-wallet';

const {
sendTransaction, // (tx: FlashblocksTx) => Promise<FlashblocksResult>
getAverageLatency, // () => number
isAvailable, // boolean
isLoading, // boolean
} = useFlashblocks();

Types​

interface FlashblocksTx {
to: string;
value: bigint; // in wei
data?: string;
}

interface FlashblocksResult {
preconfirmation: Preconfirmation;
result: {
wait: () => Promise<TransactionReceipt>;
};
}

interface Preconfirmation {
txHash: string;
preconfirmedAt: number;
latencyMs: number;
sequencerSignature: string;
}

Returns​

PropertyTypeDescription
sendTransaction(tx: FlashblocksTx) => Promise<FlashblocksResult>Send with preconfirmation
getAverageLatency() => numberGet average latency (ms)
isAvailablebooleanWhether Flashblocks is available
isLoadingbooleanLoading state

useGiwaId​

GIWA ID (up.id, Upbit Web3 Names) Hook — read-only resolution via the on-chain UpnameRegistry

Registration

up.id names are minted through Upbit / the GIWA playground, not through this SDK. This hook only resolves names, reverse-resolves addresses, and checks availability — up.id has no ENS-style text record support.

See: GIWA ID Documentation

import { useGiwaId } from 'giwa-react-native-wallet';

const {
resolveAddress, // (name: string) => Promise<Address | null>
resolveName, // (address: Address) => Promise<string | null>
getGiwaId, // (name: string) => Promise<GiwaId | null>
isAvailable, // (name: string) => Promise<boolean>
isLoading, // boolean
isInitializing, // boolean
error, // Error | null
} = useGiwaId();

Types​

interface GiwaId {
/** Full name, e.g. "alice.up.id" */
name: string;
address: Address;
/** ERC-721 token id in UpnameRegistry (= keccak256(label)) */
tokenId: bigint;
tokenUri?: string;
/** Best-effort image URL from token metadata */
avatar?: string;
}

Returns​

PropertyTypeDescription
resolveAddress(name) => Promise<Address | null>Resolve up.id name to address
resolveName(address) => Promise<string | null>Reverse-resolve address to up.id name
getGiwaId(name) => Promise<GiwaId | null>Get full GIWA ID info
isAvailable(name) => Promise<boolean>Check name availability (isClaimable)
isLoadingbooleanLoading state
isInitializingbooleanWhether service is initializing
errorError | nullError if operation failed

Usage Example​

// Resolve name to address
const address = await resolveAddress('alice'); // or 'alice.up.id'

// Reverse resolve address to name
const name = await resolveName('0x1234...');

// Get full info, including a best-effort avatar
const giwaId = await getGiwaId('alice');
console.log(giwaId?.avatar);

useDojang​

Dojang (EAS Attestation) Hook

Attestation Creation

Attestations can only be created by official issuers (e.g., Upbit Korea). This SDK provides read-only access for verifying attestations.

See: Dojang Documentation

import { useDojang } from 'giwa-react-native-wallet';

const {
getAttestation, // (uid: Hex) => Promise<Attestation | null>
isAttestationValid, // (uid: Hex) => Promise<boolean>
hasVerifiedAddress, // (address: Address, attesterId?: Hex) => Promise<boolean>
getVerifiedAddressAttestationUid, // (address: Address, attesterId?: Hex) => Promise<Hex | null>
getAttestationsForAddress, // (address: Address) => Promise<Attestation[]>
getVerifiedBalance, // (recipient: Address, coinType: bigint, snapshotAt: bigint, attesterId?: Hex) => Promise<bigint | null>
isVerifiedCode, // (codeHash: Hex, domain: string, attesterId?: Hex) => Promise<boolean>
decodeAttestationData, // (attestation: Pick<Attestation, 'attestationType' | 'data'>) => DojangAttestationData | null
isLoading, // boolean
isInitializing, // boolean
error, // Error | null
} = useDojang();
Attester defaults

hasVerifiedAddress and getVerifiedAddressAttestationUid default to checking every known attester for the current network when attesterId is omitted. getVerifiedBalance and isVerifiedCode instead default to a single attester, DEFAULT_DOJANG_ATTESTER_ID (Upbit). See the Dojang guide for the full breakdown and the schema/attester tables.

Attestation Types​

TypeDescription
verified_addressKYC-verified wallet address
balance_rootMerkle tree summary of balances
verified_balanceBalance attestation at specific time
verified_codeOn-chain verification of off-chain codes
unknownSchema UID that doesn't match any of the four schemas above

Types​

interface Attestation {
uid: Hex;
schema: Hex;
attester: Address;
recipient: Address;
attestationType: AttestationType;
data: Hex;
time: bigint;
expirationTime: bigint;
revocable: boolean;
revoked: boolean;
}

type AttestationType =
| 'verified_address'
| 'balance_root'
| 'verified_balance'
| 'verified_code'
| 'unknown';

// decodeAttestationData(attestation) return type - null for 'unknown' or on decode failure
type DojangAttestationData =
| { type: 'verified_address'; isVerified: boolean }
| {
type: 'balance_root';
coinType: bigint;
snapshotAt: bigint;
leafCount: bigint;
totalAmount: bigint;
root: Hex;
}
| { type: 'verified_balance'; balance: bigint; salt: Hex; proofs: readonly Hex[] }
| { type: 'verified_code'; codeHash: Hex; domain: string };

Returns​

PropertyTypeDescription
getAttestation(uid) => Promise<Attestation | null>Get attestation by UID
isAttestationValid(uid) => Promise<boolean>Check if attestation is valid
hasVerifiedAddress(address, attesterId?) => Promise<boolean>Check if any (or one) known attester verified the address
getVerifiedAddressAttestationUid(address, attesterId?) => Promise<Hex | null>Get the verified-address attestation UID
getAttestationsForAddress(address) => Promise<Attestation[]>Get every attestation across all known schemas/attesters
getVerifiedBalance(recipient, coinType, snapshotAt, attesterId?) => Promise<bigint | null>Get verified balance
isVerifiedCode(codeHash, domain, attesterId?) => Promise<boolean>Check off-chain code verification
decodeAttestationData(attestation) => DojangAttestationData | nullDecode raw attestation data bytes
isLoadingbooleanLoading state
isInitializingbooleanWhether service is initializing
errorError | nullError if operation failed

Usage Example​

// Check if attestation is valid
const isValid = await isAttestationValid('0x1234...');

// Get attestation details
const attestation = await getAttestation('0x1234...');
if (attestation && !attestation.revoked) {
console.log('Attester:', attestation.attester);
}

// Check if address has a verified-address attestation from any known attester
const hasVerified = await hasVerifiedAddress('0xabcd...');
console.log('Is verified:', hasVerified);

// Decode a schema-specific payload
const decoded = decodeAttestationData(attestation);

useFaucet​

Testnet Faucet Hook

Testnet Only

The faucet is only available on testnet. It opens the official GIWA faucet website in the browser.

See: GIWA Faucet

import { useFaucet } from 'giwa-react-native-wallet';

const {
requestFaucet, // (address?: Address) => Promise<void>
getFaucetUrl, // () => string
isInitializing, // boolean
isLoading, // boolean
error, // Error | null
} = useFaucet();

Returns​

PropertyTypeDescription
requestFaucet(address?) => Promise<void>Open faucet website
getFaucetUrl() => stringGet faucet URL
isInitializingbooleanWhether faucet is initializing
isLoadingbooleanLoading state
errorError | nullError if operation failed

Usage Example​

function FaucetButton() {
const { requestFaucet, isLoading } = useFaucet();

return (
<Button
title="Get Testnet ETH"
onPress={() => requestFaucet()}
disabled={isLoading}
/>
);
}
note

requestFaucet() opens the faucet website in the device's browser. The user must complete the faucet request on the website.


useNetworkInfo​

Network status and feature availability Hook

import { useNetworkInfo } from 'giwa-react-native-wallet';

const {
network, // 'testnet' | 'mainnet'
networkConfig, // GiwaNetwork
status, // NetworkStatus
isTestnet, // boolean
isReady, // boolean
hasWarnings, // boolean
warnings, // string[]
isFeatureAvailable, // (feature: FeatureName) => boolean
getFeatureInfo, // (feature: FeatureName) => FeatureAvailability | null
unavailableFeatures, // FeatureName[]
chainId, // number
rpcUrl, // string
flashblocksRpcUrl, // string - Flashblocks RPC endpoint
flashblocksWsUrl, // string - Flashblocks WebSocket endpoint
explorerUrl, // string
isInitializing, // boolean
} = useNetworkInfo();

Returns​

PropertyTypeDescription
network'testnet' | 'mainnet'Current network (mainnet: 🚧 Under Development)
networkConfigGiwaNetworkNetwork configuration
statusNetworkStatusFull network status
isTestnetbooleanWhether current network is testnet
isReadybooleanWhether network is ready for use
hasWarningsbooleanWhether there are warnings
warningsstring[]List of warning messages
isFeatureAvailable(feature) => booleanCheck feature availability
getFeatureInfo(feature) => FeatureAvailability | nullGet feature details (null while the SDK is still initializing)
unavailableFeaturesFeatureName[]List of unavailable features
chainIdnumberNetwork chain ID
rpcUrlstringRPC endpoint URL
flashblocksRpcUrlstringFlashblocks RPC URL
flashblocksWsUrlstringFlashblocks WebSocket URL
explorerUrlstringBlock explorer URL
isInitializingbooleanWhether the SDK is still initializing

Usage Example​

function NetworkStatus() {
const { network, isReady, hasWarnings, warnings, isFeatureAvailable } = useNetworkInfo();

return (
<View>
<Text>Network: {network}</Text>
<Text>Ready: {isReady ? 'Yes' : 'No'}</Text>

{hasWarnings && (
<View>
<Text>Warnings:</Text>
{warnings.map((w, i) => <Text key={i}>- {w}</Text>)}
</View>
)}

{!isFeatureAvailable('giwaId') && (
<Text>GIWA ID is not available</Text>
)}
</View>
);
}

Types​

type FeatureName = 'bridge' | 'giwaId' | 'dojang' | 'faucet' | 'flashblocks' | 'tokens';

type FeatureStatus = 'available' | 'unavailable' | 'partial';

interface FeatureAvailability {
name: FeatureName;
status: FeatureStatus;
reason?: string;
contractAddress?: string;
}

interface NetworkStatus {
network: 'testnet' | 'mainnet';
readiness: 'ready' | 'partial' | 'not_ready';
isTestnet: boolean;
hasWarnings: boolean;
warnings: NetworkWarning[];
features: Record<FeatureName, FeatureAvailability>;
}

useBiometricAuth​

Biometric authentication Hook

import { useBiometricAuth } from 'giwa-react-native-wallet';

const {
isAvailable, // boolean - Whether biometric hardware is available
isEnrolled, // boolean - Whether biometrics are enrolled
biometricType, // BiometricType - 'fingerprint' | 'face' | 'iris' | 'none'
capability, // BiometricCapability | null
isLoading, // boolean
error, // Error | null
authenticate, // (promptMessage?: string) => Promise<boolean>
refreshCapability, // () => Promise<void>
} = useBiometricAuth(options?: UseBiometricAuthOptions);

Parameters​

NameTypeRequiredDefaultDescription
optionsUseBiometricAuthOptionsNo{}Hook configuration
options.defaultPromptMessagestringNo'Authenticate'Default prompt message

Returns​

PropertyTypeDescription
isAvailablebooleanWhether biometric hardware is available
isEnrolledbooleanWhether biometrics are enrolled
biometricTypeBiometricTypeType: 'fingerprint' | 'face' | 'iris' | 'none'
capabilityBiometricCapability | nullFull capability info
isLoadingbooleanWhether capability check is in progress
errorError | nullError if check failed
authenticate(promptMessage?) => Promise<boolean>Authenticate user
refreshCapability() => Promise<void>Refresh capability info

Types​

type BiometricType = 'fingerprint' | 'face' | 'iris' | 'none';

interface BiometricCapability {
isAvailable: boolean;
biometricType: BiometricType;
isEnrolled: boolean;
}

Usage Example​

import { useBiometricAuth } from 'giwa-react-native-wallet';
import { Alert, Button, View, Text } from 'react-native';

function SecureActionScreen() {
const {
isAvailable,
isEnrolled,
biometricType,
authenticate,
isLoading,
} = useBiometricAuth({
defaultPromptMessage: 'Authenticate to continue',
});

const handleSecureAction = async () => {
if (!isAvailable) {
Alert.alert('Error', 'Biometric authentication not available');
return;
}

if (!isEnrolled) {
Alert.alert('Error', 'No biometrics enrolled on device');
return;
}

try {
const success = await authenticate('Confirm your identity');
if (success) {
Alert.alert('Success', 'Authentication successful!');
// Perform secure action
}
} catch (error) {
Alert.alert('Failed', 'Authentication failed');
}
};

if (isLoading) {
return <Text>Checking biometric capability...</Text>;
}

return (
<View>
<Text>Biometric Type: {biometricType}</Text>
<Text>Available: {isAvailable ? 'Yes' : 'No'}</Text>
<Text>Enrolled: {isEnrolled ? 'Yes' : 'No'}</Text>
<Button
title={`Authenticate with ${biometricType}`}
onPress={handleSecureAction}
disabled={!isAvailable || !isEnrolled}
/>
</View>
);
}

Biometric Types by Platform​

PlatformTypes
iOSFace ID, Touch ID
AndroidFingerprint, Face, Iris
Auto-authentication

The SDK automatically requests biometric authentication for sensitive operations like exportMnemonic and exportPrivateKey when requireBiometric: true is set.


Common Types​

GiwaError​

class GiwaError extends Error {
code: string;
details?: Record<string, any>;
}

// Error Codes
const ErrorCodes = {
INVALID_ADDRESS: 'INVALID_ADDRESS',
INVALID_MNEMONIC: 'INVALID_MNEMONIC',
INSUFFICIENT_FUNDS: 'INSUFFICIENT_FUNDS',
TRANSACTION_FAILED: 'TRANSACTION_FAILED',
NETWORK_ERROR: 'NETWORK_ERROR',
BIOMETRIC_FAILED: 'BIOMETRIC_FAILED',
SECURE_STORAGE_ERROR: 'SECURE_STORAGE_ERROR',
// ...
};