- Coin: Zano → Lethean, ticker: ZAN/ZANO → LTHN - Ports: 11211 → 36941 (mainnet RPC), 46941 (testnet RPC) - Wallet: 11212 → 36944/46944 - Address prefix: iTHN - URLs: zano.org → lethean.io - Explorer links: explorer.lthn.io Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
205 lines
5.9 KiB
TypeScript
205 lines
5.9 KiB
TypeScript
import WalletCredentials from '@/interfaces/common/WalletCredentials';
|
|
import Decimal from 'decimal.js';
|
|
import whitelistedTokens from '@/constants/tokens.json';
|
|
|
|
export const intToStrFixedLen = (int: number, fixed = 2) => {
|
|
let str = int.toString();
|
|
while (str.length < fixed) {
|
|
str = `0${str}`;
|
|
}
|
|
|
|
return str;
|
|
};
|
|
|
|
export const shortenAddress = (address: string, startAmount = 6, endAmount = 4) =>
|
|
`${(address || '').slice(0, startAmount)}...${(address || '').slice(-endAmount)}`;
|
|
|
|
export const cutAddress = (address = '', maxAmount = 6) => {
|
|
if (maxAmount >= address.length) {
|
|
return address || '';
|
|
}
|
|
|
|
return `${(address || '').slice(0, maxAmount)}...`;
|
|
};
|
|
|
|
export const toStandardDateString = (date: Date) =>
|
|
`${date.getFullYear()}-${intToStrFixedLen(date.getMonth() + 1, 2)}-${intToStrFixedLen(date.getDate(), 2)}`;
|
|
|
|
export const separateArray = <T>(arr: T[], func: (_item: T) => boolean) => {
|
|
const trueArr: T[] = [];
|
|
const falseArr: T[] = [];
|
|
arr.forEach((item) => {
|
|
if (func(item)) {
|
|
trueArr.push(item);
|
|
} else {
|
|
falseArr.push(item);
|
|
}
|
|
});
|
|
return [...trueArr, ...falseArr];
|
|
};
|
|
|
|
export const formatDollarValue = (value: string) => {
|
|
const numValue = parseFloat(value);
|
|
|
|
const withFullDecimals = numValue >= 1 ? numValue.toFixed(2) : numValue.toFixed(6);
|
|
|
|
return parseFloat(withFullDecimals).toString();
|
|
};
|
|
|
|
export const canvasResize = (inputCanvas: HTMLCanvasElement) => {
|
|
const canvas = inputCanvas;
|
|
const ctx = canvas.getContext('2d') as CanvasRenderingContext2D;
|
|
|
|
const screenRatio = (() => {
|
|
const devicePixelRatio = window.devicePixelRatio || 1;
|
|
|
|
const backingStorePixel =
|
|
(ctx as unknown as { webkitBackingStorePixelRatio?: number })
|
|
?.webkitBackingStorePixelRatio ||
|
|
(ctx as unknown as { mozBackingStorePixelRatio?: number })?.mozBackingStorePixelRatio ||
|
|
(ctx as unknown as { msBackingStorePixelRatio?: number })?.msBackingStorePixelRatio ||
|
|
(ctx as unknown as { oBackingStorePixelRatio?: number })?.oBackingStorePixelRatio ||
|
|
(ctx as unknown as { backingStorePixelRatio?: number })?.backingStorePixelRatio ||
|
|
1;
|
|
|
|
return devicePixelRatio / backingStorePixel;
|
|
})();
|
|
|
|
const selectedWidth = canvas.getBoundingClientRect().width;
|
|
const selectedHeight = canvas.getBoundingClientRect().height;
|
|
|
|
canvas.width = selectedWidth * screenRatio;
|
|
canvas.height = selectedHeight * screenRatio;
|
|
|
|
ctx?.setTransform?.(screenRatio, 0, 0, screenRatio, 0, 0);
|
|
};
|
|
|
|
export const roundTo = (x: number | string, digits = 7) => {
|
|
if (x === undefined || x === null) {
|
|
return NaN;
|
|
}
|
|
const decimalValue = new Decimal(x);
|
|
|
|
const fixedValue = decimalValue.toFixed(digits);
|
|
|
|
// Remove trailing zeros
|
|
return fixedValue.replace(/(\.\d*?[1-9])0+$/g, '$1').replace(/\.0+$/, '');
|
|
};
|
|
|
|
export const notationToString = (notation: number | string, fixed?: number) => {
|
|
const decimalValue = new Decimal(notation || '0');
|
|
|
|
if (fixed !== undefined) {
|
|
return decimalValue.toFixed(fixed).replace(/\.?0+$/, '');
|
|
}
|
|
|
|
return decimalValue.toFixed();
|
|
};
|
|
|
|
export const localeTimeLeft = (now: number | null, timestamp: number) => {
|
|
if (!now) return '00:00:00';
|
|
const timeLeft = timestamp - now;
|
|
|
|
if (timeLeft < 0) {
|
|
return '00:00:00';
|
|
}
|
|
|
|
const hours = Math.floor(timeLeft / 3600000);
|
|
const minutes = Math.floor((timeLeft - hours * 3600000) / 60000);
|
|
const seconds = Math.floor((timeLeft - hours * 3600000 - minutes * 60000) / 1000);
|
|
|
|
return `${intToStrFixedLen(hours)}:${intToStrFixedLen(minutes)}:${intToStrFixedLen(seconds)}`;
|
|
};
|
|
|
|
export function setWalletCredentials(credentials: WalletCredentials | undefined) {
|
|
if (credentials) {
|
|
localStorage.setItem('wallet', JSON.stringify(credentials));
|
|
} else {
|
|
localStorage.removeItem('wallet');
|
|
}
|
|
}
|
|
|
|
export function isPositiveFloatStr(input: string) {
|
|
const regExp = /^\d+(\.\d*)?$/;
|
|
return regExp.test(input);
|
|
}
|
|
|
|
export function formatTime(ts: string | number) {
|
|
let num = Number(ts);
|
|
|
|
if (num < 1e12) num *= 1000;
|
|
const date = new Date(num);
|
|
|
|
if (Number.isNaN(date.getTime())) return '-';
|
|
|
|
return date.toLocaleTimeString('ru-RU', { hour12: false });
|
|
}
|
|
|
|
export function formatTimestamp(ms: number | string) {
|
|
if (Number.isNaN(Number(ms))) {
|
|
return 0;
|
|
}
|
|
|
|
const date = new Date(Number(ms));
|
|
const YYYY = date.getFullYear();
|
|
const MM = String(date.getMonth() + 1).padStart(2, '0');
|
|
const DD = String(date.getDate()).padStart(2, '0');
|
|
const hh = String(date.getHours()).padStart(2, '0');
|
|
const mm = String(date.getMinutes()).padStart(2, '0');
|
|
const ss = String(date.getSeconds()).padStart(2, '0');
|
|
return `${hh}:${mm}:${ss} ${DD}-${MM}-${YYYY}`;
|
|
}
|
|
|
|
export function classes(...classes: (string | boolean | undefined)[]): string {
|
|
// boolean for constructions like [predicate] && [className]
|
|
return classes.filter((className) => className).join(' ');
|
|
}
|
|
|
|
export const getAssetIcon = (assetId: string): string => {
|
|
const findAsset = whitelistedTokens.find((s) => s === assetId);
|
|
|
|
if (findAsset) {
|
|
return `/tokens/${assetId}.png`;
|
|
}
|
|
return '/tokens/token.png';
|
|
};
|
|
|
|
type Getters<T> = {
|
|
getSide: (_item: T) => 'buy' | 'sell';
|
|
getPrice: (_item: T) => string | number | Decimal;
|
|
};
|
|
|
|
export function createOrderSorter<T>({ getSide, getPrice }: Getters<T>) {
|
|
return (a: T, b: T) => {
|
|
const aSide = getSide(a);
|
|
const bSide = getSide(b);
|
|
|
|
if (aSide !== bSide) {
|
|
return aSide === 'sell' ? -1 : 1;
|
|
}
|
|
|
|
const ap = new Decimal(getPrice(a));
|
|
const bp = new Decimal(getPrice(b));
|
|
|
|
return bp.comparedTo(ap);
|
|
};
|
|
}
|
|
|
|
export function countByKeyRecord<T>(
|
|
array: T[],
|
|
keySelector: (_item: T) => string | number,
|
|
): Record<string, number> {
|
|
return array.reduce<Record<string, number>>((acc, item) => {
|
|
const key = String(keySelector(item));
|
|
acc[key] = (acc[key] ?? 0) + 1;
|
|
return acc;
|
|
}, {});
|
|
}
|
|
|
|
export const LTHN_ASSET_ID = 'd6329b5b1f7c0805b5c345f4957554002a2f557845f64d7645dae0e051a6498a';
|
|
|
|
const knownCurrencies = ['lethean', 'xmr', 'btc', 'firo', 'usd', 'eur', 'cad', 'jpy'];
|
|
|
|
const tradingKnownCurrencies = ['lethean', 'weth', 'wbtc'];
|
|
|
|
export { tradingKnownCurrencies, knownCurrencies };
|