Here it is:
import {
Chain,
Token,
PoolExists,
Validateable,
Address,
FileType,
} from "./types";
import millify from "millify";
import Moralis from "moralis";
import BigNumber from "bignumber.js";
export const $openTab = (url: string) => {
if (!window) return;
window.open(url, "_blank");
};
export const $mask = (address: string) => {
if (!address) return address;
if (address.length < 6) return `Token ID: ${address}`;
let first4 = address.substring(0, 5);
let last5 = address.substring(address.length - 5);
let mask = "••••";
return (address = first4 + mask + last5);
};
export let APP_ENV = "process.env.APP_ENV";
export const ALLOWED_CHAINS: Chain[] =
APP_ENV == "mainnet"
? [
{
name: "Arbitrum",
networkId: "0xa4b1",
explorerUrl: "https://arbiscan.io/",
shortName: "ARB",
icon: {
url: "https://cdn.protoverse.ai/assets/ProtoVerse/arb2.svg",
},
content: "Choose this option if you want to mint on Arbitrum",
},
{
name: "Ethereum",
networkId: "0x1",
explorerUrl: "https://etherscan.io",
shortName: "ETH",
icon: {
url: "https://cdn.protoverse.ai/assets/theme/eth-icon.svg",
},
content: "Choose this option if you want to mint on Ethereum",
},
{
name: "Binance Smart Chain",
networkId: "0x38",
explorerUrl: "https://bscscan.com",
shortName: "BSC",
icon: {
url: "https://cdn.protoverse.ai/assets/theme/bsc-icon.svg",
},
content: "Choose this option if you want to mint on BSC",
},
{
name: "Polygon",
networkId: "0x89",
explorerUrl: "https://polygonscan.com",
shortName: "MATIC",
icon: {
url: "https://cdn.protoverse.ai/assets/theme/poly-icon.svg",
},
content: "Choose this option if you want to mint on Polygon",
},
{
name: "Proof Of Memes",
networkId: "0x46ef",
icon: { url: "https://cdn.protoverse.ai/assets/ProtoVerse/pom.svg" },
shortName: "POM",
explorerUrl: "https://explorer.memescan.io/",
content:
"Choose this option if you want to deploy the pool on Proof of memes.",
},
]
: [
{
name: "Polygon Testnet",
networkId: "0x13881",
explorerUrl: "https://mumbai.polygonscan.com",
shortName: "Matic",
icon: {
url: "https://cdn.protoverse.ai/assets/theme/poly-icon.svg",
},
content: "Choose this option if you want to mint on Polygon",
},
{
name: "Binance Testnet",
networkId: "0x61",
icon: {
url: "https://cdn.protoverse.ai/assets/theme/bsc-icon.svg",
},
shortName: "BNB",
explorerUrl: "https://testnet.bscscan.com",
content: "Choose this option if you want to mint on BSC",
},
{
name: "Ethereum Testnet",
networkId: "0x5",
icon: { url: "https://cdn.protoverse.ai/assets/theme/eth-icon.svg" },
shortName: "ETH",
explorerUrl: "https://goerli.etherscan.io/",
content: "Choose this option if you want to mint on Ethereum",
},
{
name: "Proof Of Memes Testnet",
networkId: "0xd649",
icon: { url: "https://cdn.protoverse.ai/assets/ProtoVerse/pom.svg" },
shortName: "POM",
explorerUrl: "https://testnet-explorer.memescan.io/",
content:
"Choose this option if you want to deploy the pool on Proof of memes.",
},
{
name: "Arbitrum Testnet",
networkId: "0x66eed",
icon: { url: "https://cdn.protoverse.ai/assets/ProtoVerse/arb2.svg" },
shortName: "ARBT",
explorerUrl: "https://goerli.arbiscan.io",
content:
"Choose this option if you want to deploy the pool on Arbitrum Testnet.",
},
];
export const ALLOWED_TOKENS: Token[] =
APP_ENV == "mainnet"
? [
// BSC
{
isNative: true,
name: "Binance",
symbol: "BNB",
decimals: 18,
address: "0x0000000000000000000000000000000000000000",
chainId: "0x38",
icon: {
url: "https://cdn.protoverse.ai/assets/theme/bsc-icon.svg",
},
},
{
name: "BUSD",
icon: {
url: "https://cdn.protoverse.ai/assets/theme/network-busd-icon.svg",
},
address: "0xe9e7cea3dedca5984780bafc599bd69add087d56",
symbol: "BUSD",
decimals: 18,
chainId: "0x38",
},
{
name: "DAI",
icon: {
url: "https://cdn.protoverse.ai/assets/theme/network-dai-icon.svg",
},
address: "0x1af3f329e8be154074d8769d1ffa4ee058b1dbc3",
symbol: "DAI",
decimals: 18,
chainId: "0x38",
},
{
name: "USDC",
icon: {
url: "https://cdn.protoverse.ai/assets/theme/network-usdc-icon.svg",
},
address: "0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d",
symbol: "USDC",
decimals: 18,
chainId: "0x38",
},
{
name: "USDT",
icon: {
url: "https://cdn.protoverse.ai/assets/theme/network-usdt-icon.svg",
},
address: "0x55d398326f99059ff775485246999027b3197955",
symbol: "USDT",
decimals: 18,
chainId: "0x38",
},
// Polygon
{
isNative: true,
name: "Matic",
symbol: "MATIC",
decimals: 18,
address: "0x0000000000000000000000000000000000000000",
chainId: "0x89",
icon: {
url: "https://cdn.protoverse.ai/assets/theme/poly-chain-black-bg.svg",
},
},
{
name: "BUSD",
icon: {
url: "https://cdn.protoverse.ai/assets/theme/network-busd-icon.svg",
},
address: "0xdab529f40e671a1d4bf91361c21bf9f0c9712ab7",
symbol: "BUSD",
decimals: 18,
chainId: "0x89",
},
{
name: "DAI",
icon: {
url: "https://cdn.protoverse.ai/assets/theme/network-dai-icon.svg",
},
address: "0x8f3cf7ad23cd3cadbd9735aff958023239c6a063",
symbol: "DAI",
decimals: 18,
chainId: "0x89",
},
{
name: "USDC",
icon: {
url: "https://cdn.protoverse.ai/assets/theme/network-usdc-icon.svg",
},
address: "0x2791bca1f2de4661ed88a30c99a7a9449aa84174",
symbol: "USDC",
decimals: 6,
chainId: "0x89",
},
{
name: "USDT",
icon: {
url: "https://cdn.protoverse.ai/assets/theme/network-usdt-icon.svg",
},
address: "0xc2132d05d31c914a87c6611c10748aeb04b58e8f",
symbol: "USDT",
decimals: 6,
chainId: "0x89",
},
// ETH
{
isNative: true,
name: "ETH",
symbol: "ETH",
decimals: 18,
address: "0x0000000000000000000000000000000000000000",
chainId: "0xa4b1",
icon: {
url: "https://cdn.protoverse.ai/assets/theme/eth-icon.svg",
},
},
{
isNative: true,
name: "ETH",
symbol: "ETH",
decimals: 18,
address: "0x0000000000000000000000000000000000000000",
chainId: "0x1",
icon: {
url: "https://cdn.protoverse.ai/assets/theme/eth-icon.svg",
},
},
// ETH
{
isNative: true,
name: "ETH",
symbol: "ETH",
decimals: 18,
address: "0x0000000000000000000000000000000000000000",
chainId: "0x1",
icon: {
url: "https://cdn.protoverse.ai/assets/theme/eth-icon.svg",
},
},
{
name: "BUSD",
icon: {
url: "https://cdn.protoverse.ai/assets/theme/network-busd-icon.svg",
},
address: "0x4Fabb145d64652a948d72533023f6E7A623C7C53",
symbol: "BUSD",
decimals: 18,
chainId: "0x1",
},
// {
// name: "USDT",
// icon: {
// url: "https://cdn.protoverse.ai/assets/theme/network-usdt-icon.svg",
// },
// address: "0xdAC17F958D2ee523a2206206994597C13D831ec7",
// symbol: "USDT",
// decimals: 6,
// chainId: "0x1",
// },
{
name: "USDC",
icon: {
url: "https://cdn.protoverse.ai/assets/theme/network-usdc-icon.svg",
},
address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
symbol: "USDC",
decimals: 6,
chainId: "0x1",
},
]
: [
{
isNative: true,
name: "Matic",
symbol: "MATIC",
decimals: 18,
address: "0x0000000000000000000000000000000000000000",
chainId: "0x13881",
icon: {
url: "https://cdn.protoverse.ai/assets/theme/poly-chain-black-bg.svg",
},
},
{
isNative: true,
name: "Binance",
symbol: "BNB",
decimals: 18,
address: "0x0000000000000000000000000000000000000000",
chainId: "0x61",
icon: {
url: "https://cdn.protoverse.ai/assets/theme/bsc-icon.svg",
},
},
{
isNative: true,
name: "Ethereum",
symbol: "ETH",
decimals: 18,
address: "0x0000000000000000000000000000000000000000",
chainId: "0x3",
icon: {
url: "https://cdn.protoverse.ai/assets/theme/eth-icon.svg",
},
},
{
name: "Staker Token",
symbol: "Staker",
decimals: 18,
address: "0xc55c1c75997d763660515ce31b003B77b5E914B3",
chainId: "0x13881",
icon: {
url: "https://cdn.protoverse.ai/assets/ProtoVerse/stake-icon.svg",
},
},
{
name: "Rewarder Token",
symbol: "Rewarder",
decimals: 18,
address: "0xFb2c09c9D172a2f18f8dd4de137b3A1b2A153dC1",
chainId: "0x13881",
icon: {
url: "https://cdn.protoverse.ai/assets/ProtoVerse/stake-icon.svg",
},
},
];
const dAppChainIds: any = {
ProtoStake: [
"0x89",
"0x13881",
"0x1",
"0x38",
"0x89",
"0x61",
"0x3",
"0x5",
"0x46ef",
"0xd649",
"0xa4b1",
"0x66eed",
],
ProtoMint: ["0x89", "0x13881", "0x1", "0x38", "0x89", "0x61", "0x3", "0x5", "0xa4b1", "0x66eed",],
ProtoRace: ["0x89", "0x13881", "0x1", "0x38", "0x89", "0x61", "0x3", "0x5", "0xa4b1", "0x66eed",],
Cryptopia: ["0x89", "0x13881", "0x1", "0x38", "0x89", "0x61", "0x3", "0x5", "0xa4b1", "0x66eed",],
Mint8: ["0x89", "0x13881", "0x1", "0x38", "0x89", "0x61", "0x3", "0x5", "0xa4b1", "0x66eed",],
Generic: [
"0x89",
"0x13881",
"0x1",
"0x38",
"0x89",
"0x61",
"0x3",
"0x5",
"0x46ef",
"0xd649",
"0xa4b1",
"0x66eed",
],
};
export const $chain = (chainId: string, dAppId: string) => {
return ALLOWED_CHAINS.find(
(chain) =>
dAppChainIds[dAppId].includes(chain.networkId) &&
chain.networkId == chainId
);
};
export const $token = (address: string, chainId: string, dAppId: string) => {
return ALLOWED_TOKENS.find(
(token) =>
dAppChainIds[dAppId].includes(token.chainId) &&
token.chainId == chainId &&
token.address.toLowerCase() === address?.toLowerCase()
);
};
export const $quickMillify = (value: any) => {
return millify(value, {
precision: 2,
decimalSeparator: ".",
});
};
export const $fromWei = (
weiAmount: any,
decimal?: number,
outDecimal?: number
) => {
return Number(Moralis.Units.FromWei(weiAmount, decimal || 18)).toFixed(
outDecimal || 4
);
};
export const $toWei = (tokenAmount: any, decimal?: number) => {
return Moralis.Units.Token(tokenAmount, decimal || 18);
};
export const $quickMillifyWei = (weiAmount: any, decimal: number) => {
return $quickMillify($fromWei(weiAmount, decimal || 18));
};
export const $sign = async ({
provider,
account,
message = "Hello, \nProtoStake uses a cryptographic signature to \nauthenticate your wallet address and will never \nrequest access to your funds. The signature request \nis a gas-free transaction.",
}: {
provider: any;
account: string | null;
message?: string;
}) => {
const timestamp = (new Date().getTime() / 1e3).toFixed(0);
let signature: string | null = null; // Initialize it to null
try {
const payload = [
`${message}\n\nTimestamp: ${timestamp}`,
account,
];
let result: any;
if (typeof provider.send === 'function') {
result = await provider.send("personal_sign", payload);
} else if (typeof provider.request === 'function') {
result = await provider.request({
method: "personal_sign",
params: payload
});
} else {
throw new Error('Provider does not support the send or request methods');
}
if (typeof result === 'string') {
signature = result;
} else if (result && typeof result === 'object' && 'result' in result) {
signature = result.result as string;
}
} catch (error) {
console.error('Error getting signature:', error);
}
if (!signature) throw Error("Unable to get a valid signature");
return { signature, timestamp };
};
export const $addHours = (date: any, h: any) => {
date.setTime(date.getTime() + h * 60 * 60 * 1000);
return date.getTime();
};
export const $apy = (
rewardSupplyWei: string,
totalActiveWei: string,
factor: string = "1"
) => {
if (new BigNumber(totalActiveWei).isZero()) return 0;
return Number(
Number(
new BigNumber(rewardSupplyWei)
.div(new BigNumber(totalActiveWei))
.times(100)
.times(factor)
.toString()
).toFixed(4)
);
};
export const $estimateEarnings = (
stakeWei: string,
earnedWei: string,
totalStakedWei: string,
poolExists: PoolExists,
currentBlockNumber?: number
) => {
const someZero = [stakeWei, totalStakedWei, currentBlockNumber || "0"].some(
(wei) => new BigNumber(wei).isZero()
);
if (!currentBlockNumber || someZero) return $fromWei(earnedWei);
const stakedPercent = new BigNumber(stakeWei)
.times(100)
.div(new BigNumber(totalStakedWei));
const totalBlocks = Number(poolExists.endsAt) - Number(poolExists.startsAt);
const remainingBlocks = Number(poolExists.endsAt) - currentBlockNumber;
const rewardRate = new BigNumber(poolExists.rewardSupply).div(totalBlocks);
const rewardsForRemainingBlocks = new BigNumber(rewardRate).times(
remainingBlocks
);
if (rewardsForRemainingBlocks.isZero() || stakedPercent.isZero())
return $fromWei(earnedWei);
const estimatedEarnings = new BigNumber(rewardsForRemainingBlocks)
.times(new BigNumber(stakedPercent))
.div(100);
return $fromWei(
estimatedEarnings.plus(new BigNumber(earnedWei)).toFixed(0) || "0"
);
};
export const defaultValidatableProps: Validateable<any> = {
onValid: () => {},
validate: (_: any) => true,
invalidate: () => {},
};
// Validations
// export const $isValidChainAddress = (address: string) => {
// return isAddress(address);
// };
export const $isValidPassword = (password: string) => {
return /^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{8,}$/.test(password);
};
export const isValidURL = (url: string) => {
var pattern = new RegExp(
"^(https?:\\/\\/)?" + // protocol
"((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|" + // domain name
"((\\d{1,3}\\.){3}\\d{1,3}))" + // OR ip (v4) address
"(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*" + // port and path
"(\\?[;&a-z\\d%_.~+=-]*)?" + // query string
"(\\#[-a-z\\d_]*)?$",
"i"
); // fragment locator
return pattern.test(url);
};
export const $fileType = (fileName: string) => {
const imageTypes = [
".jpg",
".jpeg",
".jfif",
".pjpeg",
".pjp",
".png",
".svg",
".webp",
".apng",
".avif",
];
const videoTypes = [
".mpg",
".mp2",
".mpeg",
".mpe",
".mpv",
".ogg",
".mp4",
".m4p",
".m4v",
".avi",
".wmv",
".mov",
".qt",
".flv",
".swf",
];
if (imageTypes.some((ext) => fileName.toLowerCase().endsWith(ext)))
return FileType.IMAGE;
if (videoTypes.some((ext) => fileName.toLowerCase().endsWith(ext)))
return FileType.VIDEO;
return FileType.OTHER;
};
export const findMintTx = (tx: any) => {
const isTransfer = tx.logs.find(
(log: any) =>
log.topic0 ==
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" &&
log.topic1
?.toLowerCase()
.includes(
"0x0000000000000000000000000000000000000000000000000000000000000000"
)
);
if (isTransfer)
return {
tokenId: new BigNumber(isTransfer.topic3).toString() as string,
address: isTransfer.address as Address,
};
const isTransferSingle = tx.logs.find(
(log: any) =>
log.topic0 ==
"0xc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62" &&
log.topic2
?.toLowerCase()
.includes(
"0x0000000000000000000000000000000000000000000000000000000000000000"
)
);
if (isTransferSingle) {
const [tokenId, amount] = Moralis.web3Library.utils.defaultAbiCoder.decode(
["uint256", "uint256"],
isTransferSingle.data
);
return {
tokenId: tokenId.toString() as string,
address: isTransferSingle.address as Address,
};
}
};
.........................................