2020-08-01 07:05:58 -07:00
|
|
|
import {
|
|
|
|
HumanizeDuration,
|
|
|
|
HumanizeDurationLanguage,
|
|
|
|
} from "humanize-duration-ts";
|
2021-10-16 19:14:50 -07:00
|
|
|
import { PublicKey } from "@solana/web3.js";
|
2020-08-08 06:06:24 -07:00
|
|
|
|
|
|
|
// Switch to web3 constant when web3 updates superstruct
|
2022-05-21 10:24:25 -07:00
|
|
|
export const LAMPORTS_PER_SOL = 1_000_000_000;
|
|
|
|
export const MICRO_LAMPORTS_PER_LAMPORT = 1_000_000;
|
2020-08-01 07:05:58 -07:00
|
|
|
|
|
|
|
export const NUM_TICKS_PER_SECOND = 160;
|
|
|
|
export const DEFAULT_TICKS_PER_SLOT = 64;
|
|
|
|
export const NUM_SLOTS_PER_SECOND =
|
|
|
|
NUM_TICKS_PER_SECOND / DEFAULT_TICKS_PER_SLOT;
|
|
|
|
export const MS_PER_SLOT = 1000 / NUM_SLOTS_PER_SECOND;
|
2020-04-29 05:48:38 -07:00
|
|
|
|
2020-04-09 02:49:47 -07:00
|
|
|
export function assertUnreachable(x: never): never {
|
|
|
|
throw new Error("Unreachable!");
|
|
|
|
}
|
2020-04-29 05:48:38 -07:00
|
|
|
|
2020-08-29 05:50:45 -07:00
|
|
|
export function normalizeTokenAmount(
|
|
|
|
raw: string | number,
|
|
|
|
decimals: number
|
|
|
|
): number {
|
|
|
|
let rawTokens: number;
|
|
|
|
if (typeof raw === "string") rawTokens = parseInt(raw);
|
|
|
|
else rawTokens = raw;
|
|
|
|
return rawTokens / Math.pow(10, decimals);
|
|
|
|
}
|
|
|
|
|
2022-05-21 10:24:25 -07:00
|
|
|
export function microLamportsToLamports(
|
|
|
|
microLamports: number | bigint
|
|
|
|
): number {
|
|
|
|
if (typeof microLamports === "number") {
|
|
|
|
return microLamports / MICRO_LAMPORTS_PER_LAMPORT;
|
|
|
|
}
|
|
|
|
|
|
|
|
const microLamportsString = microLamports.toString().padStart(7, "0");
|
|
|
|
const splitIndex = microLamportsString.length - 6;
|
|
|
|
const lamportString =
|
|
|
|
microLamportsString.slice(0, splitIndex) +
|
|
|
|
"." +
|
|
|
|
microLamportsString.slice(splitIndex);
|
|
|
|
return parseFloat(lamportString);
|
|
|
|
}
|
|
|
|
|
|
|
|
export function microLamportsToLamportsString(
|
|
|
|
microLamports: number | bigint,
|
|
|
|
maximumFractionDigits: number = 6
|
|
|
|
): string {
|
|
|
|
const lamports = microLamportsToLamports(microLamports);
|
|
|
|
return new Intl.NumberFormat("en-US", { maximumFractionDigits }).format(
|
|
|
|
lamports
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-09-23 22:05:41 -07:00
|
|
|
export function lamportsToSol(lamports: number | bigint): number {
|
2020-08-08 06:06:24 -07:00
|
|
|
if (typeof lamports === "number") {
|
2022-09-23 22:05:41 -07:00
|
|
|
return lamports / LAMPORTS_PER_SOL;
|
2020-08-08 06:06:24 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
let signMultiplier = 1;
|
2022-09-23 22:05:41 -07:00
|
|
|
if (lamports < 0) {
|
2020-08-08 06:06:24 -07:00
|
|
|
signMultiplier = -1;
|
|
|
|
}
|
|
|
|
|
2022-09-23 22:05:41 -07:00
|
|
|
const absLamports = lamports < 0 ? -lamports : lamports;
|
2020-08-08 06:06:24 -07:00
|
|
|
const lamportsString = absLamports.toString(10).padStart(10, "0");
|
|
|
|
const splitIndex = lamportsString.length - 9;
|
|
|
|
const solString =
|
|
|
|
lamportsString.slice(0, splitIndex) +
|
|
|
|
"." +
|
|
|
|
lamportsString.slice(splitIndex);
|
|
|
|
return signMultiplier * parseFloat(solString);
|
|
|
|
}
|
|
|
|
|
2020-05-22 12:09:28 -07:00
|
|
|
export function lamportsToSolString(
|
2022-09-23 22:05:41 -07:00
|
|
|
lamports: number | bigint,
|
2020-05-22 12:09:28 -07:00
|
|
|
maximumFractionDigits: number = 9
|
2021-06-21 16:53:06 -07:00
|
|
|
): string {
|
2020-08-08 06:06:24 -07:00
|
|
|
const sol = lamportsToSol(lamports);
|
2021-06-21 16:53:06 -07:00
|
|
|
return new Intl.NumberFormat("en-US", { maximumFractionDigits }).format(sol);
|
|
|
|
}
|
|
|
|
|
2022-04-13 12:38:59 -07:00
|
|
|
export function numberWithSeparator(s: string) {
|
|
|
|
return s.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
|
|
}
|
|
|
|
|
2020-08-01 07:05:58 -07:00
|
|
|
const HUMANIZER = new HumanizeDuration(new HumanizeDurationLanguage());
|
|
|
|
HUMANIZER.setOptions({
|
|
|
|
language: "short",
|
|
|
|
spacer: "",
|
|
|
|
delimiter: " ",
|
|
|
|
round: true,
|
|
|
|
units: ["d", "h", "m", "s"],
|
|
|
|
largest: 3,
|
|
|
|
});
|
|
|
|
HUMANIZER.addLanguage("short", {
|
|
|
|
y: () => "y",
|
|
|
|
mo: () => "mo",
|
|
|
|
w: () => "w",
|
|
|
|
d: () => "d",
|
|
|
|
h: () => "h",
|
|
|
|
m: () => "m",
|
|
|
|
s: () => "s",
|
|
|
|
ms: () => "ms",
|
|
|
|
decimal: ".",
|
|
|
|
});
|
|
|
|
|
2020-08-04 07:18:09 -07:00
|
|
|
export function slotsToHumanString(
|
|
|
|
slots: number,
|
|
|
|
slotTime = MS_PER_SLOT
|
|
|
|
): string {
|
|
|
|
return HUMANIZER.humanize(slots * slotTime);
|
2020-08-01 07:05:58 -07:00
|
|
|
}
|
2020-10-28 21:08:24 -07:00
|
|
|
|
|
|
|
export function wrap(input: string, length: number): string {
|
|
|
|
var result = [];
|
|
|
|
while (input.length) {
|
|
|
|
result.push(input.substr(0, length));
|
|
|
|
input = input.substr(length);
|
|
|
|
}
|
|
|
|
return result.join("\n");
|
|
|
|
}
|
2021-02-23 14:53:22 -08:00
|
|
|
|
|
|
|
export function localStorageIsAvailable() {
|
|
|
|
const test = "test";
|
|
|
|
try {
|
|
|
|
localStorage.setItem(test, test);
|
|
|
|
localStorage.removeItem(test);
|
|
|
|
return true;
|
|
|
|
} catch (e) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2021-02-26 15:50:37 -08:00
|
|
|
|
|
|
|
export function camelToTitleCase(str: string): string {
|
|
|
|
const result = str.replace(/([A-Z])/g, " $1");
|
|
|
|
return result.charAt(0).toUpperCase() + result.slice(1);
|
|
|
|
}
|
2021-07-20 09:43:17 -07:00
|
|
|
|
2022-04-13 12:38:59 -07:00
|
|
|
export function snakeToTitleCase(str: string): string {
|
|
|
|
const result = str.replace(/([-_]\w)/g, (g) => ` ${g[1].toUpperCase()}`);
|
|
|
|
return result.charAt(0).toUpperCase() + result.slice(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
export function snakeToPascal(string: string) {
|
|
|
|
return string
|
|
|
|
.split("/")
|
|
|
|
.map((snake) =>
|
|
|
|
snake
|
|
|
|
.split("_")
|
|
|
|
.map((substr) => substr.charAt(0).toUpperCase() + substr.slice(1))
|
|
|
|
.join("")
|
|
|
|
)
|
|
|
|
.join("/");
|
|
|
|
}
|
|
|
|
|
|
|
|
export function capitalizeFirstLetter(input: string) {
|
|
|
|
return input.charAt(0).toUpperCase() + input.slice(1);
|
|
|
|
}
|
|
|
|
|
2021-07-20 09:43:17 -07:00
|
|
|
export function abbreviatedNumber(value: number, fixed = 1) {
|
|
|
|
if (value < 1e3) return value;
|
|
|
|
if (value >= 1e3 && value < 1e6) return +(value / 1e3).toFixed(fixed) + "K";
|
|
|
|
if (value >= 1e6 && value < 1e9) return +(value / 1e6).toFixed(fixed) + "M";
|
|
|
|
if (value >= 1e9 && value < 1e12) return +(value / 1e9).toFixed(fixed) + "B";
|
|
|
|
if (value >= 1e12) return +(value / 1e12).toFixed(fixed) + "T";
|
|
|
|
}
|
2021-10-16 19:14:50 -07:00
|
|
|
|
|
|
|
export const pubkeyToString = (key: PublicKey | string = "") => {
|
|
|
|
return typeof key === "string" ? key : key?.toBase58() || "";
|
|
|
|
};
|
|
|
|
|
|
|
|
export const getLast = (arr: string[]) => {
|
|
|
|
if (arr.length <= 0) {
|
|
|
|
return undefined;
|
|
|
|
}
|
|
|
|
|
|
|
|
return arr[arr.length - 1];
|
|
|
|
};
|