Merge pull request #43 from solana-labs/feature/fees

Feature/fees
This commit is contained in:
Bartosz Lipinski 2021-01-22 10:12:09 -06:00 committed by GitHub
commit 1694eadbad
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 106 additions and 40 deletions

View File

@ -2,6 +2,8 @@ import { PublicKey } from "@solana/web3.js";
import { useEffect, useMemo, useState } from "react"; import { useEffect, useMemo, useState } from "react";
import { LendingReserve, LendingReserveParser } from "../models/lending"; import { LendingReserve, LendingReserveParser } from "../models/lending";
import { cache, ParsedAccount } from "./../contexts/accounts"; import { cache, ParsedAccount } from "./../contexts/accounts";
import { useConnectionConfig } from "./../contexts/connection";
import { getTokenByName, KnownToken } from "../utils/utils";
export const getLendingReserves = () => { export const getLendingReserves = () => {
return cache return cache
@ -33,7 +35,27 @@ export function useLendingReserves() {
} }
export function useLendingReserve(address?: string | PublicKey) { export function useLendingReserve(address?: string | PublicKey) {
const id = useMemo(() => typeof address === "string" ? address : address?.toBase58(), [address]); const { tokenMap } = useConnectionConfig();
const { reserveAccounts } = useLendingReserves();
let addressName = address;
if (typeof address === "string") {
const token: KnownToken | null = getTokenByName(tokenMap, address);
if (token) {
const account = reserveAccounts.filter(
(acc) => acc.info.liquidityMint.toBase58() === token.mintAddress
)[0]
if (account) {
addressName = account.pubkey;
}
}
}
const id = useMemo(
() =>
typeof addressName === "string" ? addressName : addressName?.toBase58(),
[addressName]
);
const [reserveAccount, setReserveAccount] = useState< const [reserveAccount, setReserveAccount] = useState<
ParsedAccount<LendingReserve> ParsedAccount<LendingReserve>
>(cache.get(id || "") as ParsedAccount<LendingReserve>); >(cache.get(id || "") as ParsedAccount<LendingReserve>);

View File

@ -1,10 +1,10 @@
import { useCallback, useState } from 'react'; import { useCallback, useState } from "react";
import { MintInfo } from '@solana/spl-token'; import { MintInfo } from "@solana/spl-token";
import { PoolInfo, TokenAccount } from './../models'; import { PoolInfo, TokenAccount } from "./../models";
import { PublicKey } from '@solana/web3.js'; import { PublicKey } from "@solana/web3.js";
import BN from 'bn.js'; import BN from "bn.js";
import { WAD, ZERO } from '../constants'; import { WAD, ZERO } from "../constants";
export interface KnownToken { export interface KnownToken {
tokenSymbol: string; tokenSymbol: string;
@ -15,8 +15,8 @@ export interface KnownToken {
export type KnownTokenMap = Map<string, KnownToken>; export type KnownTokenMap = Map<string, KnownToken>;
export const formatPriceNumber = new Intl.NumberFormat('en-US', { export const formatPriceNumber = new Intl.NumberFormat("en-US", {
style: 'decimal', style: "decimal",
minimumFractionDigits: 2, minimumFractionDigits: 2,
maximumFractionDigits: 8, maximumFractionDigits: 8,
}); });
@ -55,11 +55,15 @@ export function shortenAddress(address: string, chars = 4): string {
return `${address.slice(0, chars)}...${address.slice(-chars)}`; return `${address.slice(0, chars)}...${address.slice(-chars)}`;
} }
export function getTokenName(map: KnownTokenMap, mint?: string | PublicKey, shorten = true): string { export function getTokenName(
const mintAddress = typeof mint === 'string' ? mint : mint?.toBase58(); map: KnownTokenMap,
mint?: string | PublicKey,
shorten = true
): string {
const mintAddress = typeof mint === "string" ? mint : mint?.toBase58();
if (!mintAddress) { if (!mintAddress) {
return 'N/A'; return "N/A";
} }
const knownSymbol = map.get(mintAddress)?.tokenSymbol; const knownSymbol = map.get(mintAddress)?.tokenSymbol;
@ -70,8 +74,23 @@ export function getTokenName(map: KnownTokenMap, mint?: string | PublicKey, shor
return shorten ? `${mintAddress.substring(0, 5)}...` : mintAddress; return shorten ? `${mintAddress.substring(0, 5)}...` : mintAddress;
} }
export function getTokenIcon(map: KnownTokenMap, mintAddress?: string | PublicKey): string | undefined { export function getTokenByName(tokenMap: KnownTokenMap, name: string) {
const address = typeof mintAddress === 'string' ? mintAddress : mintAddress?.toBase58(); let token: KnownToken | null = null;
for (const val of tokenMap.values()) {
if (val.tokenSymbol === name) {
token = val;
break;
}
}
return token;
}
export function getTokenIcon(
map: KnownTokenMap,
mintAddress?: string | PublicKey
): string | undefined {
const address =
typeof mintAddress === "string" ? mintAddress : mintAddress?.toBase58();
if (!address) { if (!address) {
return; return;
} }
@ -83,20 +102,25 @@ export function isKnownMint(map: KnownTokenMap, mintAddress: string) {
return !!map.get(mintAddress); return !!map.get(mintAddress);
} }
export const STABLE_COINS = new Set(['USDC', 'wUSDC', 'USDT']); export const STABLE_COINS = new Set(["USDC", "wUSDC", "USDT"]);
export function chunks<T>(array: T[], size: number): T[][] { export function chunks<T>(array: T[], size: number): T[][] {
return Array.apply<number, T[], T[][]>(0, new Array(Math.ceil(array.length / size))).map((_, index) => return Array.apply<number, T[], T[][]>(
array.slice(index * size, (index + 1) * size) 0,
); new Array(Math.ceil(array.length / size))
).map((_, index) => array.slice(index * size, (index + 1) * size));
} }
export function toLamports(account?: TokenAccount | number, mint?: MintInfo): number { export function toLamports(
account?: TokenAccount | number,
mint?: MintInfo
): number {
if (!account) { if (!account) {
return 0; return 0;
} }
const amount = typeof account === 'number' ? account : account.info.amount?.toNumber(); const amount =
typeof account === "number" ? account : account.info.amount?.toNumber();
const precision = Math.pow(10, mint?.decimals || 0); const precision = Math.pow(10, mint?.decimals || 0);
return Math.floor(amount * precision); return Math.floor(amount * precision);
@ -106,20 +130,28 @@ export function wadToLamports(amount?: BN): BN {
return amount?.div(WAD) || ZERO; return amount?.div(WAD) || ZERO;
} }
export function fromLamports(account?: TokenAccount | number | BN, mint?: MintInfo, rate: number = 1.0): number { export function fromLamports(
account?: TokenAccount | number | BN,
mint?: MintInfo,
rate: number = 1.0
): number {
if (!account) { if (!account) {
return 0; return 0;
} }
const amount = Math.floor( const amount = Math.floor(
typeof account === 'number' ? account : BN.isBN(account) ? account.toNumber() : account.info.amount.toNumber() typeof account === "number"
? account
: BN.isBN(account)
? account.toNumber()
: account.info.amount.toNumber()
); );
const precision = Math.pow(10, mint?.decimals || 0); const precision = Math.pow(10, mint?.decimals || 0);
return (amount / precision) * rate; return (amount / precision) * rate;
} }
var SI_SYMBOL = ['', 'k', 'M', 'G', 'T', 'P', 'E']; var SI_SYMBOL = ["", "k", "M", "G", "T", "P", "E"];
const abbreviateNumber = (number: number, precision: number) => { const abbreviateNumber = (number: number, precision: number) => {
let tier = (Math.log10(number) / 3) | 0; let tier = (Math.log10(number) / 3) | 0;
@ -133,20 +165,23 @@ const abbreviateNumber = (number: number, precision: number) => {
return scaled.toFixed(precision) + suffix; return scaled.toFixed(precision) + suffix;
}; };
export const formatAmount = (val: number, precision: number = 6, abbr: boolean = true) => export const formatAmount = (
abbr ? abbreviateNumber(val, precision) : val.toFixed(precision); val: number,
precision: number = 6,
abbr: boolean = true
) => (abbr ? abbreviateNumber(val, precision) : val.toFixed(precision));
export function formatTokenAmount( export function formatTokenAmount(
account?: TokenAccount, account?: TokenAccount,
mint?: MintInfo, mint?: MintInfo,
rate: number = 1.0, rate: number = 1.0,
prefix = '', prefix = "",
suffix = '', suffix = "",
precision = 6, precision = 6,
abbr = false abbr = false
): string { ): string {
if (!account) { if (!account) {
return ''; return "";
} }
return `${[prefix]}${formatAmount( return `${[prefix]}${formatAmount(
@ -156,13 +191,13 @@ export function formatTokenAmount(
)}${suffix}`; )}${suffix}`;
} }
export const formatUSD = new Intl.NumberFormat('en-US', { export const formatUSD = new Intl.NumberFormat("en-US", {
style: 'currency', style: "currency",
currency: 'USD', currency: "USD",
}); });
const numberFormater = new Intl.NumberFormat('en-US', { const numberFormater = new Intl.NumberFormat("en-US", {
style: 'decimal', style: "decimal",
minimumFractionDigits: 2, minimumFractionDigits: 2,
maximumFractionDigits: 2, maximumFractionDigits: 2,
}); });
@ -170,25 +205,30 @@ const numberFormater = new Intl.NumberFormat('en-US', {
export const formatNumber = { export const formatNumber = {
format: (val?: number) => { format: (val?: number) => {
if (!val) { if (!val) {
return '--'; return "--";
} }
return numberFormater.format(val); return numberFormater.format(val);
}, },
}; };
export const formatPct = new Intl.NumberFormat('en-US', { export const formatPct = new Intl.NumberFormat("en-US", {
style: 'percent', style: "percent",
minimumFractionDigits: 2, minimumFractionDigits: 2,
maximumFractionDigits: 2, maximumFractionDigits: 2,
}); });
export function convert(account?: TokenAccount | number, mint?: MintInfo, rate: number = 1.0): number { export function convert(
account?: TokenAccount | number,
mint?: MintInfo,
rate: number = 1.0
): number {
if (!account) { if (!account) {
return 0; return 0;
} }
const amount = typeof account === 'number' ? account : account.info.amount?.toNumber(); const amount =
typeof account === "number" ? account : account.info.amount?.toNumber();
const precision = Math.pow(10, mint?.decimals || 0); const precision = Math.pow(10, mint?.decimals || 0);
let result = (amount / precision) * rate; let result = (amount / precision) * rate;
@ -196,7 +236,11 @@ export function convert(account?: TokenAccount | number, mint?: MintInfo, rate:
return result; return result;
} }
export function getPoolName(map: KnownTokenMap, pool: PoolInfo, shorten = true) { export function getPoolName(
map: KnownTokenMap,
pool: PoolInfo,
shorten = true
) {
const sorted = pool.pubkeys.holdingMints.map((a) => a.toBase58()).sort(); const sorted = pool.pubkeys.holdingMints.map((a) => a.toBase58()).sort();
return sorted.map((item) => getTokenName(map, item, shorten)).join('/'); return sorted.map((item) => getTokenName(map, item, shorten)).join("/");
} }