import { Address, AddressType, BufferUtils, CommonUtils, Networks } from "libnexa-ts"; import type { Balance } from "../types/wallet.types"; import bigDecimal from 'js-big-decimal'; export const MAIN_WALLET_ID = -1; export const MAX_INT64 = 9223372036854775807n; export const VAULT_FIRST_BLOCK = 274710; export const VAULT_SCRIPT_PREFIX = "0014461ad25081cb0119d034385ff154c8d3ad6bdd76"; export function isTestnet(): boolean { return Networks.defaultNetwork == Networks.testnet; } export function isGenesisHashValid(hash: string): boolean { if(isTestnet()) { return hash == "508c843a4b98fb25f57cf9ebafb245a5c16468f06519cdd467059a91e7b79d52"; } return hash == "edc7144fe1ba4edd0edf35d7eea90f6cb1dba42314aa85da8207e97c5339c801"; } export function isValidNexaAddress(address: string, type = AddressType.PayToScriptTemplate): boolean { return Address.isValid(address, Networks.defaultNetwork, type); } export function getExplorerUrl(): string { return `https://${(isTestnet() ? 'testnet-' : '')}explorer.nexa.org`; } export function currentTimestamp(): number { return Math.floor(Date.now() / 1000); } export function estimateDateByFutureBlock(current: number, future: number): string { const estimateMins = (future - current) * 2; const time = new Date(); time.setMinutes(time.getMinutes() + estimateMins); return time.toLocaleDateString(); } export function isNullOrEmpty(arg?: string | any[] | null): arg is undefined | [] | null | '' { return !arg || arg.length === 0; } export function truncateStringMiddle(str?: string, maxLength = 0): string { if (!str || str.length <= maxLength) { return str || ''; } const ellipsis = '...'; const halfLength = Math.floor((maxLength - ellipsis.length) / 2); const firstHalf = str.slice(0, halfLength); const secondHalf = str.slice(str.length - halfLength); return firstHalf + ellipsis + secondHalf; }; export function capitalizeFirstLetter(str: string): string { if (str.length === 0) { return ""; } return str.charAt(0).toUpperCase() + str.substring(1); } export function getAddressBuffer(address: string): Uint8Array { if (CommonUtils.isHexa(address)) { return BufferUtils.hexToBuffer(address) ; } return Address.fromString(address).data; } export function tokenIdToHex(token: string): string { if (CommonUtils.isHexa(token)) { return token; } return BufferUtils.bufferToHex(getAddressBuffer(token)); } export function tokenHexToAddr(token: string): string { if (!CommonUtils.isHexa(token)) { return token; } return new Address(getAddressBuffer(token), Networks.defaultNetwork, AddressType.GroupIdAddress).toString(); } export function tokenAmountToAssetAmount(amount?: string | number | bigint): string { if (amount == null || amount === "") { return ""; } if (BigInt(amount) <= 0n) { return "0"; } return amount.toString(); } export function sumBalance(balances: Balance[]): Balance { let confirmed = BigInt(0), unconfirmed = BigInt(0); balances.forEach(b => { confirmed += BigInt(b.confirmed); unconfirmed += BigInt(b.unconfirmed); }); return {confirmed: confirmed.toString(), unconfirmed: unconfirmed.toString()}; } export function sumTokensBalance(balances: Record[]): Record { const tokensBalance: Record = {}; balances.forEach(b => { for (const key in b) { if (tokensBalance[key]) { tokensBalance[key].confirmed = (BigInt(tokensBalance[key].confirmed) + BigInt(b[key].confirmed)).toString(); tokensBalance[key].unconfirmed = (BigInt(tokensBalance[key].unconfirmed) + BigInt(b[key].unconfirmed)).toString(); } else { tokensBalance[key] = { confirmed: BigInt(b[key].confirmed).toString(), unconfirmed: BigInt(b[key].unconfirmed).toString() }; } } }); return tokensBalance; } const FILE_EXTENSION_TO_TYPE = { // Images //'.svg': { media: 'image', mime: 'image/svg+xml' }, '.gif': { media: 'image', mime: 'image/gif' }, '.png': { media: 'image', mime: 'image/png' }, '.apng': { media: 'image', mime: 'image/apng' }, '.jpg': { media: 'image', mime: 'image/jpeg' }, '.jpeg': { media: 'image', mime: 'image/jpeg' }, '.avif': { media: 'image', mime: 'image/avif' }, '.webp': { media: 'image', mime: 'image/webp' }, '.bmp': { media: 'image', mime: 'image/bmp' }, // Videos '.mp4': { media: 'video', mime: 'video/mp4' }, '.mpeg': { media: 'video', mime: 'video/mpeg' }, '.mpg': { media: 'video', mime: 'video/mpeg' }, '.webm': { media: 'video', mime: 'video/webm' }, '.mov': { media: 'video', mime: 'video/quicktime' }, // Audio '.mp3': { media: 'audio', mime: 'audio/mpeg' }, '.ogg': { media: 'audio', mime: 'audio/ogg' }, '.wav': { media: 'audio', mime: 'audio/wav' }, '.m4a': { media: 'audio', mime: 'audio/mp4' }, } as const; export function getFileMediaType(filename: string): 'video' | 'audio' | 'image' | 'unknown' { const lastDotIndex = filename.lastIndexOf('.'); if (lastDotIndex === -1) return 'unknown'; const extension = filename.slice(lastDotIndex).toLowerCase(); return FILE_EXTENSION_TO_TYPE[extension as keyof typeof FILE_EXTENSION_TO_TYPE]?.media ?? 'unknown'; } export function getFileMimeType(filename: string): string { const lastDotIndex = filename.lastIndexOf('.'); if (lastDotIndex === -1) return 'application/octet-stream'; const extension = filename.slice(lastDotIndex).toLowerCase(); return FILE_EXTENSION_TO_TYPE[extension as keyof typeof FILE_EXTENSION_TO_TYPE]?.mime ?? 'application/octet-stream'; } export function sleep(ms: number): Promise { return new Promise(resolve => setTimeout(resolve, ms)); } export function prettifyAmount(amount: string | number): string { let val = bigDecimal.getPrettyValue(amount); if (val.match(/\./)) { val = val.replace(/\.?0+$/, ''); } return val; }