forked from Dshield-xyz/Dshield
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathkyc.ts
More file actions
88 lines (80 loc) · 2.5 KB
/
Copy pathkyc.ts
File metadata and controls
88 lines (80 loc) · 2.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
const KYC_KEY = "dshield_kyc";
const KYC_LOCK_KEY = "dshield_kyc_lock";
const LOCK_TIMEOUT_MS = 5000;
export interface KycRecord {
preimage: string;
hash: string;
registeredOnChain: boolean;
createdAt: number;
}
/**
* Acquire a simple advisory lock to serialize cross-tab writes.
* Prevents concurrent KYC updates from different tabs/windows.
*/
async function acquireLock(): Promise<() => void> {
const lockId = Date.now().toString() + Math.random().toString(36);
const deadline = Date.now() + LOCK_TIMEOUT_MS;
while (Date.now() < deadline) {
const currentLock = localStorage.getItem(KYC_LOCK_KEY);
if (!currentLock) {
const lockData = JSON.stringify({ id: lockId, timestamp: Date.now() });
localStorage.setItem(KYC_LOCK_KEY, lockData);
const verifyLock = localStorage.getItem(KYC_LOCK_KEY);
if (verifyLock) {
try {
const parsed = JSON.parse(verifyLock);
if (parsed.id === lockId) {
return () => {
const currentData = localStorage.getItem(KYC_LOCK_KEY);
if (currentData) {
try {
const current = JSON.parse(currentData);
if (current.id === lockId) {
localStorage.removeItem(KYC_LOCK_KEY);
}
} catch {
localStorage.removeItem(KYC_LOCK_KEY);
}
}
};
}
} catch {
// Invalid JSON, try again
}
}
} else {
try {
const lockData = JSON.parse(currentLock);
if (lockData.timestamp && Date.now() - lockData.timestamp > LOCK_TIMEOUT_MS) {
localStorage.removeItem(KYC_LOCK_KEY);
}
} catch {
// Invalid lock data without timestamp, don't clear immediately
}
}
await new Promise((resolve) => setTimeout(resolve, 10));
}
throw new Error("Failed to acquire KYC storage lock after timeout");
}
async function withLock<T>(fn: () => T): Promise<T> {
const release = await acquireLock();
try {
return fn();
} finally {
release();
}
}
export async function saveKyc(record: KycRecord): Promise<void> {
return withLock(() => {
localStorage.setItem(KYC_KEY, JSON.stringify(record));
});
}
export function getKyc(): KycRecord | null {
if (typeof window === "undefined") return null;
const raw = localStorage.getItem(KYC_KEY);
if (!raw) return null;
return JSON.parse(raw);
}
export function clearKyc(): void {
localStorage.removeItem(KYC_KEY);
}