Files
com.blitzwallet/app/components/admin/homeComponents/savings/utils.js
T

155 lines
3.8 KiB
JavaScript

import { DEFAULT_GOAL_EMOJI } from '../../../../constants';
export const toMicros = value => {
const numeric = Number(value || 0);
if (!Number.isFinite(numeric) || numeric <= 0) return 0;
return Math.round(numeric * 1_000_000);
};
export const fromMicros = value => {
const numeric = Number(value || 0);
if (!Number.isFinite(numeric)) return 0;
return (numeric / 1_000_000).toFixed(2);
};
export const formatTxDate = timestamp => {
const date = new Date(Number(timestamp || Date.now()));
return date.toLocaleDateString(undefined, {
month: 'short',
day: 'numeric',
year: 'numeric',
});
};
export async function fetchSavingsInterestPayouts(
pubKeyHex,
limit = 10,
offset = 0,
) {
try {
const res = await fetch(
`https://rewards.flashnet.xyz/v1/rewards/${pubKeyHex}/payouts?limit=${limit}&offset=${offset}`,
);
if (!res.ok) return [];
const data = await res.json();
if (Array.isArray(data)) return data;
if (Array.isArray(data.payouts)) return data.payouts;
return [];
} catch {
return [];
}
}
export function parseGoalMetadata(metadata) {
if (!metadata) return {};
try {
const parsed = JSON.parse(metadata);
return typeof parsed === 'object' && parsed ? parsed : {};
} catch {
return {};
}
}
export function serializeGoalMetadata(metadata) {
if (!metadata || typeof metadata !== 'object') return null;
try {
return JSON.stringify(metadata);
} catch {
return null;
}
}
function signedTransactionAmountMicros(transaction) {
const amount = Math.max(
0,
Math.round(Number(transaction?.amountMicros || 0)),
);
return transaction?.type === 'withdrawal' ? -amount : amount;
}
export function computeSavingsBalanceMicros(transactions) {
return transactions.reduce(
(sum, tx) => sum + signedTransactionAmountMicros(tx),
0,
);
}
export function computeGoalBalanceMicros(goalId, transactions) {
if (!goalId) return 0;
return transactions
.filter(tx => tx.goalId === goalId)
.reduce((sum, tx) => sum + signedTransactionAmountMicros(tx), 0);
}
export function toLegacyDisplayTransaction(transaction, goalName, t) {
const signedAmountMicros = signedTransactionAmountMicros(transaction);
const isWithdrawal = transaction.type === 'withdrawal';
const isBtcWithdrawl = transaction.type === 'bitcoinWithdrawal';
const key = isWithdrawal
? goalName
? 'savings.withdrawalWithGoal'
: 'savings.withdrawal'
: goalName
? 'savings.depositWithGoal'
: 'savings.deposit';
return {
txId: transaction.id,
goalId: transaction.goalId,
type: transaction.type,
amountMicros: signedAmountMicros,
createdAt: transaction.timestamp,
description: isBtcWithdrawl
? t('savings.rewardsWithdrawal')
: t(key, { goalName }),
};
}
export function normalizeGoalForUI(goal) {
if (!goal) return null;
const metadata = parseGoalMetadata(goal.metadata);
return {
...goal,
amountMicros: goal.targetAmountMicros,
emoji: metadata.emoji || DEFAULT_GOAL_EMOJI,
};
}
export function resolveGoalAndAmount(goalIdOrPayload, maybeAmount) {
if (
goalIdOrPayload &&
typeof goalIdOrPayload === 'object' &&
!Array.isArray(goalIdOrPayload)
) {
return {
goalId: goalIdOrPayload.goalId,
amount: goalIdOrPayload.amount,
};
}
return {
goalId: typeof goalIdOrPayload === 'string' ? goalIdOrPayload : undefined,
amount: maybeAmount,
};
}
export function mergeAndSortSavingsActivity(
contributions = [],
interestPayouts = [],
t,
) {
const normalised = interestPayouts.map(payout => ({
txId: payout.txId,
type: 'interest',
amountMicros: toMicros(payout.payoutSats),
createdAt: new Date(payout.createdAt).getTime(),
description: t('savings.rewardsPayout'),
}));
return [...contributions, ...normalised].sort(
(a, b) => b.createdAt - a.createdAt,
);
}