import { WalletType } from 'rnwalletman'; import AsyncStorage from '@react-native-async-storage/async-storage'; export interface WalletItem { id: string; walletType: string; upi?: string; phone?: string; status?: string; otpMode?: boolean; } const DEFAULT_DOMAIN = 'aa.pfgame.org'; const STORAGE_KEY = 'server_domain'; const HTTPS_KEY = 'server_https'; const TOKEN_AUTO_REBIND_KEY = 'token_auto_rebind_enabled'; const TOKEN_AUTO_REBIND_SCAN_MS_KEY = 'token_auto_rebind_scan_ms'; const TOKEN_AUTO_REBIND_COOLDOWN_MS_KEY = 'token_auto_rebind_cooldown_ms'; const TOKEN_AUTO_REBIND_FAIL_COOLDOWN_MS_KEY = 'token_auto_rebind_fail_cooldown_ms'; /** 扫 list 间隔 */ const DEFAULT_TOKEN_AUTO_REBIND_SCAN_MS = 1 * 60 * 1000; /** 重绑成功后冷却 */ const DEFAULT_TOKEN_AUTO_REBIND_COOLDOWN_MS = 1 * 60 * 1000; /** 重绑失败后冷却 */ const DEFAULT_TOKEN_AUTO_REBIND_FAIL_COOLDOWN_MS = 1 * 60 * 1000; let _tokenAutoRebindEnabled = false; let _tokenAutoRebindScanMs = DEFAULT_TOKEN_AUTO_REBIND_SCAN_MS; let _tokenAutoRebindCooldownMs = DEFAULT_TOKEN_AUTO_REBIND_COOLDOWN_MS; let _tokenAutoRebindFailCooldownMs = DEFAULT_TOKEN_AUTO_REBIND_FAIL_COOLDOWN_MS; let _domain = DEFAULT_DOMAIN; let _useHttps = true; export async function loadServerDomain(): Promise { const saved = await AsyncStorage.getItem(STORAGE_KEY); if (saved) _domain = saved; const https = await AsyncStorage.getItem(HTTPS_KEY); if (https !== null) _useHttps = https === 'true'; const autoRebind = await AsyncStorage.getItem(TOKEN_AUTO_REBIND_KEY); _tokenAutoRebindEnabled = autoRebind === 'true'; const scanMs = await AsyncStorage.getItem(TOKEN_AUTO_REBIND_SCAN_MS_KEY); const cooldownMs = await AsyncStorage.getItem(TOKEN_AUTO_REBIND_COOLDOWN_MS_KEY); if (scanMs) { const n = parseInt(scanMs, 10); if (Number.isFinite(n) && n > 0) _tokenAutoRebindScanMs = n; } if (cooldownMs) { const n = parseInt(cooldownMs, 10); if (Number.isFinite(n) && n > 0) _tokenAutoRebindCooldownMs = n; } const failCooldownMs = await AsyncStorage.getItem(TOKEN_AUTO_REBIND_FAIL_COOLDOWN_MS_KEY); if (failCooldownMs) { const n = parseInt(failCooldownMs, 10); if (Number.isFinite(n) && n > 0) _tokenAutoRebindFailCooldownMs = n; } console.log('loadServerDomain', _domain, 'https:', _useHttps); return _domain; } export function getTokenAutoRebindOptions(): { scanIntervalMs: number; cooldownMs: number; failCooldownMs: number; } { return { scanIntervalMs: _tokenAutoRebindScanMs, cooldownMs: _tokenAutoRebindCooldownMs, failCooldownMs: _tokenAutoRebindFailCooldownMs, }; } export async function saveTokenAutoRebindOptions( scanIntervalMs: number, cooldownMs: number, failCooldownMs: number = DEFAULT_TOKEN_AUTO_REBIND_FAIL_COOLDOWN_MS, ): Promise { _tokenAutoRebindScanMs = scanIntervalMs; _tokenAutoRebindCooldownMs = cooldownMs; _tokenAutoRebindFailCooldownMs = failCooldownMs; await AsyncStorage.setItem(TOKEN_AUTO_REBIND_SCAN_MS_KEY, String(scanIntervalMs)); await AsyncStorage.setItem(TOKEN_AUTO_REBIND_COOLDOWN_MS_KEY, String(cooldownMs)); await AsyncStorage.setItem(TOKEN_AUTO_REBIND_FAIL_COOLDOWN_MS_KEY, String(failCooldownMs)); } export function getTokenAutoRebindEnabled(): boolean { return _tokenAutoRebindEnabled; } export async function saveTokenAutoRebindEnabled(enabled: boolean): Promise { _tokenAutoRebindEnabled = enabled; await AsyncStorage.setItem(TOKEN_AUTO_REBIND_KEY, String(enabled)); } export async function saveServerDomain(domain: string, useHttps: boolean): Promise { _domain = domain; _useHttps = useHttps; await AsyncStorage.setItem(STORAGE_KEY, domain); await AsyncStorage.setItem(HTTPS_KEY, String(useHttps)); } export function getServerDomain(): string { return _domain; } export function getUseHttps(): boolean { return _useHttps; } class Api { public static get BASE_URL() { const domain = getServerDomain(); const scheme = getUseHttps() ? 'https' : 'http'; return `${scheme}://${domain}`; } public static get WS_URL() { const domain = getServerDomain(); const scheme = getUseHttps() ? 'wss' : 'ws'; return `${scheme}://${domain}/ws`; } private static _instance: Api | null = null; private userId: number = 0; private userToken: string = ''; private constructor() {} public setUserId(userId: number) { this.userId = userId; } public getUserId(): number { return this.userId; } public getUserToken(): string { return this.userToken; } public static get instance() { if (Api._instance === null) { Api._instance = new Api(); } return Api._instance; } private headers(): Record { const h: Record = { 'Content-Type': 'application/json' }; if (this.userId > 0) { h['X-User-ID'] = String(this.userId); } return h; } public async login(username: string, password: string): Promise { console.log('login', Api.BASE_URL); const res = await fetch(`${Api.BASE_URL}/login`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username, password }), }); const data = await res.json(); if (!data.success) throw new Error(data.message); this.userId = data.data.userId; this.userToken = data.data.userToken ?? String(data.data.userId); return this.userId; } public async register(walletType: WalletType, params: any) { const res = await fetch(`${Api.BASE_URL}/register`, { method: 'POST', headers: this.headers(), body: JSON.stringify({ walletType, params }), }); const data = await res.json(); if (!data.success) throw new Error(data.message); return data; } public async requestOTP(walletType: WalletType, mobile: string, params: any = {}) { const res = await fetch(`${Api.BASE_URL}/request-otp`, { method: 'POST', headers: this.headers(), body: JSON.stringify({ walletType, mobile, params }), }); const data = await res.json(); if (!data.success) throw new Error(data.message); return data; } public async verifyOTP(walletType: WalletType, mobile: string, otp: string, params: any = {}) { const res = await fetch(`${Api.BASE_URL}/verify-otp`, { method: 'POST', headers: this.headers(), body: JSON.stringify({ walletType, mobile, otp, params }), }); const data = await res.json(); if (!data.success) throw new Error(data.message); return data; } public async listWallets(): Promise { const res = await fetch(`${Api.BASE_URL}/wallets`, { headers: this.headers() }); const data = await res.json(); if (!data.success) throw new Error(data.message); return data.data?.wallets ?? []; } public async getWalletVpas(walletId: string): Promise { const res = await fetch(`${Api.BASE_URL}/wallet/vpas?walletId=${encodeURIComponent(walletId)}`, { headers: this.headers(), }); const data = await res.json(); if (!data.success) throw new Error(data.message); return data.data?.vpas ?? []; } public async setCurrentVpa(walletId: string, vpaIndex: number): Promise { const res = await fetch(`${Api.BASE_URL}/wallet/set-vpa`, { method: 'POST', headers: this.headers(), body: JSON.stringify({ walletId, vpaIndex }), }); const data = await res.json(); if (!data.success) throw new Error(data.message); return data.data?.vpa ?? ''; } public async setWalletStatus(walletId: string, active: boolean): Promise { const res = await fetch(`${Api.BASE_URL}/wallet/set-status`, { method: 'POST', headers: this.headers(), body: JSON.stringify({ walletId, active }), }); const data = await res.json(); if (!data.success) throw new Error(data.message); return data.data?.status ?? ''; } public async generateLink(walletId: string, amount: string): Promise<{ link: string; orderId: string }> { const res = await fetch(`${Api.BASE_URL}/generate-link`, { method: 'POST', headers: this.headers(), body: JSON.stringify({ walletId, amount }), }); const data = await res.json(); if (!data.success) throw new Error(data.message); return { link: data.data?.link, orderId: data.data?.orderId }; } } export default Api;