-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathwallet-sync.js
More file actions
122 lines (108 loc) · 3.6 KB
/
wallet-sync.js
File metadata and controls
122 lines (108 loc) · 3.6 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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
(function () {
function ensureSyncPeers(wallet) {
if (!wallet || typeof wallet !== "object") return {};
const raw = wallet.syncPeers;
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
wallet.syncPeers = {};
}
return wallet.syncPeers;
}
function pickActivePeer(wallet) {
const peers = wallet && wallet.syncPeers ? wallet.syncPeers : null;
if (!peers || typeof peers !== "object") return null;
let bestKey = null;
let bestPeer = null;
let bestUpdatedAt = -1;
for (const [key, peer] of Object.entries(peers)) {
if (!peer || typeof peer !== "object") continue;
const updatedAt =
typeof peer.updatedAt === "number" && Number.isFinite(peer.updatedAt)
? Math.floor(peer.updatedAt)
: -1;
if (updatedAt > bestUpdatedAt) {
bestUpdatedAt = updatedAt;
bestKey = key;
bestPeer = peer;
}
}
if (!bestPeer || !bestKey || bestUpdatedAt <= 0) return null;
return { peerKey: bestKey, peer: bestPeer };
}
function computeAgeDays(peer) {
const updatedAt =
peer &&
typeof peer.updatedAt === "number" &&
Number.isFinite(peer.updatedAt)
? Math.floor(peer.updatedAt)
: 0;
if (updatedAt <= 0) return null;
const ageMs = Date.now() - updatedAt;
if (!Number.isFinite(ageMs) || ageMs < 0) return 0;
return Math.floor(ageMs / 86400000);
}
function computeTrafficLight(ageDays) {
if (typeof ageDays !== "number" || !Number.isFinite(ageDays)) {
return { level: "unknown", icon: "❔" };
}
if (ageDays <= 5) return { level: "green", icon: "✅" };
if (ageDays <= 10) return { level: "yellow", icon: "⚠️" };
return { level: "red", icon: "🛑" };
}
function clampInt(n) {
const v =
typeof n === "number" && Number.isFinite(n)
? Math.floor(n)
: parseInt(n, 10);
if (!Number.isFinite(v) || isNaN(v)) return 0;
return Math.max(0, v);
}
function normalizeSymbol(value, fallback) {
const raw = typeof value === "string" ? value.trim() : "";
if (raw.length === 1) {
const ch = raw;
if (ch !== "=" && ch !== "|" && ch !== "…" && ch !== " ") return ch;
}
return fallback;
}
function buildAsciiTimeline(wallet, peer, options) {
const maxLen =
options &&
typeof options.maxLen === "number" &&
Number.isFinite(options.maxLen)
? Math.max(10, Math.floor(options.maxLen))
: 30;
const localCount = Array.isArray(wallet && wallet.events)
? wallet.events.length
: 0;
const commonRaw = clampInt(peer && peer.commonEventCount);
const common = Math.min(commonRaw, localCount);
const localDelta = Math.max(0, localCount - common);
const localSymbol = normalizeSymbol(
options && typeof options.localSymbol === "string"
? options.localSymbol
: "",
"L",
);
// Compact timeline: fixed common marker, divergence only (local).
// "=" does not grow with commonEventCount; new events only increase divergence.
const marker = "===|";
const available = Math.max(0, maxLen - marker.length);
let deltaShown = localDelta;
let prefix = "";
if (localDelta > available) {
deltaShown = available;
// indicate truncation by replacing one "=" with "…": "…==|"
prefix = "…==|";
}
const timeline =
(prefix ? prefix : marker) + localSymbol.repeat(Math.max(0, deltaShown));
return "Sync: " + timeline;
}
window.dbWalletSync = {
ensureSyncPeers,
pickActivePeer,
computeAgeDays,
computeTrafficLight,
buildAsciiTimeline,
};
})();