@solana/spl-token#MintInfo TypeScript Examples
The following examples show how to use
@solana/spl-token#MintInfo.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: utils.ts From metaplex with Apache License 2.0 | 8 votes |
export function toLamports(
account?: TokenAccount | number,
mint?: MintInfo,
): number {
if (!account) {
return 0;
}
const amount =
typeof account === 'number' ? account : account.info.amount?.toNumber();
const precision = Math.pow(10, mint?.decimals || 0);
return Math.floor(amount * precision);
}
Example #2
Source File: utils.ts From metaplex with Apache License 2.0 | 7 votes |
export function convert(
account?: TokenAccount | number,
mint?: MintInfo,
rate: number = 1.0,
): number {
if (!account) {
return 0;
}
const amount =
typeof account === 'number' ? account : account.info.amount?.toNumber();
const precision = Math.pow(10, mint?.decimals || 0);
const result = (amount / precision) * rate;
return result;
}
Example #3
Source File: utils.ts From metaplex with Apache License 2.0 | 7 votes |
export function fromLamports(
account?: TokenAccount | number | BN,
mint?: MintInfo,
rate: number = 1.0,
): number {
if (!account) {
return 0;
}
const amount = Math.floor(
typeof account === 'number'
? account
: BN.isBN(account)
? account.toNumber()
: account.info.amount.toNumber(),
);
const precision = Math.pow(10, mint?.decimals || 9);
return (amount / precision) * rate;
}
Example #4
Source File: utils.ts From metaplex with Apache License 2.0 | 7 votes |
export function formatTokenAmount(
account?: TokenAccount | number | BN,
mint?: MintInfo,
rate: number = 1.0,
prefix = '',
suffix = '',
precision = 3,
abbr = false,
): string {
if (!account) {
return '';
}
return `${[prefix]}${formatAmount(
fromLamports(account, mint, rate),
precision,
abbr,
)}${suffix}`;
}
Example #5
Source File: instructions.ts From serum-ts with Apache License 2.0 | 6 votes |
deserializeMint = (data: Buffer): MintInfo => {
if (data.length !== MintLayout.span) {
throw new Error('Not a valid Mint');
}
const mintInfo = MintLayout.decode(data);
if (mintInfo.mintAuthorityOption === 0) {
mintInfo.mintAuthority = null;
} else {
mintInfo.mintAuthority = new PublicKey(mintInfo.mintAuthority);
}
mintInfo.supply = u64.fromBuffer(mintInfo.supply);
mintInfo.isInitialized = mintInfo.isInitialized !== 0;
if (mintInfo.freezeAuthorityOption === 0) {
mintInfo.freezeAuthority = null;
} else {
mintInfo.freezeAuthority = new PublicKey(mintInfo.freezeAuthority);
}
return mintInfo as MintInfo;
}
Example #6
Source File: index.ts From serum-ts with Apache License 2.0 | 6 votes |
export async function getMintInfo(
provider: Provider,
addr: PublicKey,
): Promise<MintInfo> {
let depositorAccInfo = await provider.connection.getAccountInfo(addr);
if (depositorAccInfo === null) {
throw new Error('Failed to find token account');
}
return parseMintAccount(depositorAccInfo.data);
}
Example #7
Source File: pools.ts From serum-ts with Apache License 2.0 | 6 votes |
async getCachedMintAccount(
connection: Connection,
pubkey: PublicKey | string,
cacheDurationMs = 0,
): Promise<MintInfo> {
return this.cached<MintInfo>(
() => getMintAccount(connection, pubkey),
this._mintAccountsCache,
typeof pubkey === 'string' ? pubkey : pubkey.toBase58(),
cacheDurationMs,
);
}
Example #8
Source File: pools.ts From serum-ts with Apache License 2.0 | 6 votes |
getMintAccount = async (
connection: Connection,
pubKey: PublicKey | string,
): Promise<MintInfo> => {
const address = typeof pubKey === 'string' ? new PublicKey(pubKey) : pubKey;
const info = await connection.getAccountInfo(address);
if (info === null) {
throw new Error('Failed to find mint account');
}
return deserializeMint(info.data);
}
Example #9
Source File: Token.tsx From swap-ui with Apache License 2.0 | 6 votes |
export function useMint(mint?: PublicKey): MintInfo | undefined | null {
const { provider } = useTokenContext();
// Lazy load the mint account if needeed.
const asyncMintInfo = useAsync(async () => {
if (!mint) {
return undefined;
}
if (_MINT_CACHE.get(mint.toString())) {
return _MINT_CACHE.get(mint.toString());
}
const mintClient = new Token(
provider.connection,
mint,
TOKEN_PROGRAM_ID,
new Account()
);
const mintInfo = mintClient.getMintInfo();
_MINT_CACHE.set(mint.toString(), mintInfo);
return mintInfo;
}, [provider.connection, mint]);
if (asyncMintInfo.result) {
return asyncMintInfo.result;
}
return undefined;
}
Example #10
Source File: accounts.ts From metaplex with Apache License 2.0 | 6 votes |
getMintInfo = async (
connection: Connection,
mint: string,
): Promise<{ key: PublicKey; info: MintInfo }> => {
let mintKey: PublicKey;
try {
mintKey = new PublicKey(mint);
} catch (err) {
throw new Error(`Invalid mint key ${err}`);
}
const mintAccount = await connection.getAccountInfo(mintKey);
if (mintAccount === null) {
throw new Error(`Could not fetch mint`);
}
if (!mintAccount.owner.equals(TOKEN_PROGRAM_ID)) {
const mintOwner = mintAccount.owner.toBase58();
throw new Error(`Invalid mint owner ${mintOwner}`);
}
if (mintAccount.data.length !== MintLayout.span) {
throw new Error(`Invalid mint size ${mintAccount.data.length}`);
}
const mintInfo = MintLayout.decode(Buffer.from(mintAccount.data));
return {
key: mintKey,
info: mintInfo,
};
}
Example #11
Source File: queryExtendedMetadata.ts From metaplex with Apache License 2.0 | 6 votes |
queryExtendedMetadata = async (
connection: Connection,
mintToMeta: Record<string, ParsedAccount<Metadata>>,
) => {
const mintToMetadata = { ...mintToMeta };
const mints = await getMultipleAccounts(
connection,
[...Object.keys(mintToMetadata)].filter(k => !cache.get(k)),
'single',
);
mints.keys.forEach((key, index) => {
const mintAccount = mints.array[index];
if (mintAccount) {
const mint = cache.add(
key,
mintAccount,
MintParser,
false,
) as ParsedAccount<MintInfo>;
if (!mint.info.supply.eqn(1) || mint.info.decimals !== 0) {
// naive not NFT check
delete mintToMetadata[key];
} else {
// const metadata = mintToMetadata[key];
}
}
});
// await Promise.all([...extendedMetadataFetch.values()]);
const metadata = [...Object.values(mintToMetadata)];
return {
metadata,
mintToMetadata,
};
}
Example #12
Source File: deserialize.ts From metaplex with Apache License 2.0 | 6 votes |
deserializeMint = (data: Buffer) => {
if (data.length !== MintLayout.span) {
throw new Error('Not a valid Mint');
}
const mintInfo = MintLayout.decode(data);
if (mintInfo.mintAuthorityOption === 0) {
mintInfo.mintAuthority = null;
} else {
mintInfo.mintAuthority = new PublicKey(mintInfo.mintAuthority);
}
mintInfo.supply = u64.fromBuffer(mintInfo.supply);
mintInfo.isInitialized = mintInfo.isInitialized !== 0;
if (mintInfo.freezeAuthorityOption === 0) {
mintInfo.freezeAuthority = null;
} else {
mintInfo.freezeAuthority = new PublicKey(mintInfo.freezeAuthority);
}
return mintInfo as MintInfo;
}
Example #13
Source File: index.ts From zo-client with Apache License 2.0 | 6 votes |
export async function getMintInfo(
provider: Provider,
pubkey: PublicKey,
): Promise<MintInfo> {
const data = (await provider.connection.getAccountInfo(pubkey))?.data;
if (!data) throw Error(`Couldn't load mint data for ${pubkey.toBase58()}`);
const m = MintLayout.decode(data);
return {
mintAuthority: new PublicKey(m.mintAuthority),
supply: u64.fromBuffer(m.supply),
decimals: m.decimals,
isInitialized: !!m.isInitialized,
freezeAuthority: new PublicKey(m.freezeAuthority),
};
}
Example #14
Source File: accounts.tsx From metaplex with Apache License 2.0 | 6 votes |
export function useMint(key?: string | PublicKey) {
const connection = useConnection();
const [mint, setMint] = useState<MintInfo>();
const id = typeof key === 'string' ? key : key?.toBase58();
useEffect(() => {
if (!id) {
return;
}
cache
.query(connection, id, MintParser)
.then(acc => setMint(acc.info as any))
.catch(err => console.log(err));
const dispose = cache.emitter.onCache(e => {
const event = e;
if (event.id === id) {
cache
.query(connection, id, MintParser)
.then(mint => setMint(mint.info as any));
}
});
return () => {
dispose();
};
}, [connection, id]);
return mint;
}
Example #15
Source File: Token.tsx From swap-ui with Apache License 2.0 | 5 votes |
export function setMintCache(pk: PublicKey, account: MintInfo) {
_MINT_CACHE.set(pk.toString(), new Promise((resolve) => resolve(account)));
}
Example #16
Source File: Token.tsx From swap-ui with Apache License 2.0 | 5 votes |
_MINT_CACHE = new Map<string, Promise<MintInfo>>([
[SOL_MINT.toString(), { decimals: 9 }],
])
Example #17
Source File: OpenOrdersDialog.tsx From swap-ui with Apache License 2.0 | 5 votes |
function toDisplay(mintInfo: MintInfo | undefined | null, value: BN): string {
if (!mintInfo) {
return value.toNumber().toString();
}
return (value.toNumber() / 10 ** mintInfo.decimals).toFixed(
mintInfo.decimals
);
}
Example #18
Source File: mint.ts From easy-spl with Apache License 2.0 | 5 votes |
async getInfo(): Promise<MintInfo> {
return mint.get.info(this.conn, this.key)
}
Example #19
Source File: pools.ts From serum-ts with Apache License 2.0 | 5 votes |
private _mintAccountsCache: {
[publickKey: string]: { value: MintInfo; ts: number };
};
Example #20
Source File: mint.ts From easy-spl with Apache License 2.0 | 5 votes |
getMintInfo = async (
conn: web3.Connection,
mint: web3.PublicKey
): Promise<MintInfo> => {
const token = new Token(conn, mint, TOKEN_PROGRAM_ID, {} as any)
return token.getMintInfo()
}
Example #21
Source File: index.ts From serum-ts with Apache License 2.0 | 5 votes |
export function parseMintAccount(data: Buffer): MintInfo {
const m = MintLayout.decode(data);
m.mintAuthority = new PublicKey(m.mintAuthority);
m.supply = u64.fromBuffer(m.supply);
m.isInitialized = m.state !== 0;
return m;
}
Example #22
Source File: cache.ts From metaplex with Apache License 2.0 | 5 votes |
pendingMintCalls = new Map<string, Promise<MintInfo>>()
Example #23
Source File: cache.ts From metaplex with Apache License 2.0 | 5 votes |
mintCache = new Map<string, MintInfo>()
Example #24
Source File: newOrder.ts From psyoptions with Apache License 2.0 | 4 votes |
describe("cpi_examples newOrder", () => {
const program = anchor.workspace.CpiExamples as Program<CpiExamples>;
const provider = program.provider;
const americanOptionsProgram = anchor.workspace
.PsyAmerican as Program<PsyAmerican>;
const payer = web3.Keypair.fromSecretKey(
Buffer.from(
JSON.parse(
require("fs").readFileSync(process.env.ANCHOR_WALLET, {
encoding: "utf-8",
})
)
)
);
const wallet = payer;
const mintAuthority = anchor.web3.Keypair.generate();
let underlyingToken: Token, usdcToken: Token, optionToken: Token;
// Global PsyOptions variables
let optionMarket: OptionMarketV2;
// Global DEX variables
let marketProxy: MarketProxy,
marketAuthority: anchor.web3.PublicKey,
marketAuthorityBump: number,
usdcMint: anchor.web3.PublicKey,
usdcMintInfo: MintInfo,
referral: anchor.web3.PublicKey,
openOrders: PublicKey,
openOrdersBump: number,
vault: anchor.web3.PublicKey,
vaultBumpSeed: number,
vaultAuthority: anchor.web3.PublicKey,
vaultAuthBump: number;
before(async () => {
// Setup - Create an OptionMarket
const {
optionMarket: newOptionMarket,
remainingAccounts,
instructions,
} = await initSetup(
provider,
wallet,
mintAuthority,
americanOptionsProgram
);
optionMarket = newOptionMarket;
await initOptionMarket(
americanOptionsProgram,
wallet,
optionMarket,
remainingAccounts,
instructions
);
[usdcMint] = await createMintAndVault(
provider,
new anchor.BN("1000000000000000000"),
undefined,
6
);
// Initialize a permissioned Serum Market
({ marketAuthority, marketAuthorityBump } = await getMarketAndAuthorityInfo(
americanOptionsProgram,
optionMarket,
DEX_PID,
usdcMint
));
// Setup - Create a Serum market for the OptionMarket's option tokens
({ marketA: marketProxy } = await initMarket(
provider,
americanOptionsProgram,
marketLoader(provider, program, optionMarket.key, marketAuthorityBump),
optionMarket,
usdcMint
));
// Set the token variables for use in later tests
underlyingToken = new Token(
provider.connection,
optionMarket.underlyingAssetMint,
TOKEN_PROGRAM_ID,
wallet
);
optionToken = new Token(
provider.connection,
optionMarket.optionMint,
TOKEN_PROGRAM_ID,
wallet
);
usdcToken = new Token(
provider.connection,
usdcMint,
TOKEN_PROGRAM_ID,
wallet
);
referral = await usdcToken.createAssociatedTokenAccount(FEE_OWNER_KEY);
});
describe("cpi_examples initNewOrderVault", () => {
it("should create a USDC vault owned by the program", async () => {
// Generate a PDA for the USDC vault
[vault, vaultBumpSeed] = await anchor.web3.PublicKey.findProgramAddress(
[usdcToken.publicKey.toBuffer(), textEncoder.encode("vault")],
program.programId
);
[vaultAuthority, vaultAuthBump] =
await anchor.web3.PublicKey.findProgramAddress(
[vault.toBuffer(), textEncoder.encode("vaultAuthority")],
program.programId
);
try {
await program.rpc.initNewOrderVault({
accounts: {
authority: wallet.publicKey,
usdcMint: usdcMint,
vault,
vaultAuthority,
tokenProgram: TOKEN_PROGRAM_ID,
rent: SYSVAR_RENT_PUBKEY,
systemProgram: SystemProgram.programId,
},
});
} catch (err) {
console.log((err as Error).toString());
throw err;
}
// validate that the vault was initialized and owned by the program
const vaultAcct = await usdcToken.getAccountInfo(vault);
assert.ok(vaultAcct.owner.equals(vaultAuthority));
});
});
describe("place newOrder", () => {
before(async () => {
// Vault is already initialized because these tests run sequentially
// transfer USDC to that vault so it can place an order
usdcMintInfo = await usdcToken.getMintInfo();
await usdcToken.mintTo(
vault,
wallet.publicKey,
[],
new u64(10_000_000 * usdcMintInfo.decimals)
);
// Get the open orders account that needs to be optionally created
[openOrders, openOrdersBump] = await PublicKey.findProgramAddress(
[
openOrdersSeed,
marketProxy.dexProgramId.toBuffer(),
marketProxy.market.address.toBuffer(),
// NOTE: For other developers, this should be changed to be the User or Vault that has the authority over the account.
vaultAuthority.toBuffer(),
],
americanOptionsProgram.programId
);
});
it("should create an open orders account and place an order on the Serum market", async () => {
// test the vault contains USDC
const vaultAcct = await usdcToken.getAccountInfo(vault);
assert.equal(
vaultAcct.amount.toString(),
new u64(10_000_000 * usdcMintInfo.decimals).toString()
);
// test the order book is blank
let bids = await marketProxy.market.loadBids(provider.connection);
let l2 = await bids.getL2(3);
assert.equal(l2.length, 0);
const price = 1;
const size = 22;
// Run placeOrder instruction for vault
try {
await program.rpc.placeOrder(
vaultAuthBump,
openOrdersBump,
marketAuthorityBump,
Side.Bid, // Side
marketProxy.market.priceNumberToLots(price), // liimit_price
marketProxy.market.baseSizeNumberToLots(size), // max_coin_qty
OrderType.PostOnly, // order_type
new anchor.BN(999), // client_order_id
SelfTradeBehavior.AbortTransaction, // self_trade_behavior
new anchor.BN(65535), // limit - no idea what this is
new anchor.BN(
// @ts-ignore: serum
marketProxy.market._decoded.quoteLotSize.toNumber()
).mul(
marketProxy.market
.baseSizeNumberToLots(size)
.mul(marketProxy.market.priceNumberToLots(price))
), // max_native_pc_qty_including_fees - no idea what exactly this is
{
accounts: {
userAuthority: wallet.publicKey,
psyAmericanProgram: americanOptionsProgram.programId,
dexProgram: DEX_PID,
openOrders,
market: marketProxy.market.address,
psyMarketAuthority: marketAuthority,
vault,
vaultAuthority,
// @ts-ignore: Dumb serum stuff
requestQueue: marketProxy.market._decoded.requestQueue,
// @ts-ignore: Dumb serum stuff
eventQueue: marketProxy.market._decoded.eventQueue,
marketBids: marketProxy.market.bidsAddress,
marketAsks: marketProxy.market.asksAddress,
// @ts-ignore: Dumb serum stuff
coinVault: marketProxy.market._decoded.baseVault,
// @ts-ignore: Dumb serum stuff
pcVault: marketProxy.market._decoded.quoteVault,
systemProgram: SystemProgram.programId,
tokenProgram: TOKEN_PROGRAM_ID,
rent: SYSVAR_RENT_PUBKEY,
},
}
);
} catch (err) {
console.log("*** error", (err as Error).toString());
throw err;
}
// Test that a new open orders account was created
const openOrdersAcct = await OpenOrders.load(
provider.connection,
openOrders,
DEX_PID
);
assert.ok(openOrdersAcct.owner.equals(openOrders));
// test that the order book contains the new order.
bids = await marketProxy.market.loadBids(provider.connection);
l2 = await bids.getL2(3);
assert.equal(l2.length, 1);
assert.equal(l2[0][0], price);
assert.equal(l2[0][1], size);
});
describe("Open orders account exists", () => {
it("should place the order without fail", async () => {
// Test that the open orders account already exists
const openOrdersAcct = await OpenOrders.load(
provider.connection,
openOrders,
DEX_PID
);
assert.ok(openOrdersAcct.owner.equals(openOrders));
// test that the order book contains the new order.
let bids = await marketProxy.market.loadBids(provider.connection);
let l2 = await bids.getL2(3);
assert.equal(l2.length, 1);
const price = 2;
const size = 1;
// Run placeOrder instruction for vault
try {
await program.rpc.placeOrder(
vaultAuthBump,
openOrdersBump,
marketAuthorityBump,
Side.Bid, // Side
marketProxy.market.priceNumberToLots(price), // liimit_price
marketProxy.market.baseSizeNumberToLots(size), // max_coin_qty
OrderType.PostOnly, // order_type
new anchor.BN(998), // client_order_id
SelfTradeBehavior.AbortTransaction, // self_trade_behavior
new anchor.BN(65535), // limit
new anchor.BN(
// @ts-ignore: serum
marketProxy.market._decoded.quoteLotSize.toNumber()
).mul(
marketProxy.market
.baseSizeNumberToLots(size)
.mul(marketProxy.market.priceNumberToLots(price))
), // max_native_pc_qty_including_fees
{
accounts: {
userAuthority: wallet.publicKey,
psyAmericanProgram: americanOptionsProgram.programId,
dexProgram: DEX_PID,
openOrders,
market: marketProxy.market.address,
psyMarketAuthority: marketAuthority,
vault,
vaultAuthority,
// @ts-ignore: Dumb serum stuff
requestQueue: marketProxy.market._decoded.requestQueue,
// @ts-ignore: Dumb serum stuff
eventQueue: marketProxy.market._decoded.eventQueue,
marketBids: marketProxy.market.bidsAddress,
marketAsks: marketProxy.market.asksAddress,
// @ts-ignore: Dumb serum stuff
coinVault: marketProxy.market._decoded.baseVault,
// @ts-ignore: Dumb serum stuff
pcVault: marketProxy.market._decoded.quoteVault,
systemProgram: SystemProgram.programId,
tokenProgram: TOKEN_PROGRAM_ID,
rent: SYSVAR_RENT_PUBKEY,
},
}
);
} catch (err) {
console.log("*** error", (err as Error).toString());
throw err;
}
bids = await marketProxy.market.loadBids(provider.connection);
l2 = await bids.getL2(3);
assert.equal(l2.length, 2);
});
});
});
});
Example #25
Source File: index.tsx From metaplex with Apache License 2.0 | 4 votes |
BidLine = (props: {
bid: any;
index: number;
mint?: MintInfo;
isCancelled?: boolean;
isActive?: boolean;
mintKey: string;
}) => {
const { bid, mint, isCancelled, mintKey } = props;
const { publicKey } = useWallet();
const bidder = bid.info.bidderPubkey;
const isme = publicKey?.toBase58() === bidder;
const tokenInfo = useTokenList().subscribedTokens.filter(
m => m.address == mintKey,
)[0];
// Get Twitter Handle from address
const connection = useConnection();
const [bidderTwitterHandle, setBidderTwitterHandle] = useState('');
useEffect(() => {
const getTwitterHandle = async (
connection: Connection,
bidder: StringPublicKey,
): Promise<string | undefined> => {
try {
const [twitterHandle] = await getHandleAndRegistryKey(
connection,
toPublicKey(bidder),
);
setBidderTwitterHandle(twitterHandle);
} catch (err) {
console.warn(`err`);
return undefined;
}
};
getTwitterHandle(connection, bidder);
}, [bidderTwitterHandle]);
const { width } = useWindowDimensions();
if (width < 768) {
return (
<Row className="mobile-bid-history">
<div className="bid-info-container">
<div className="bidder-info-container">
<Identicon
style={{
width: 24,
height: 24,
marginRight: 10,
marginTop: 2,
}}
address={bidder}
/>
{bidderTwitterHandle ? (
<a
target="_blank"
title={shortenAddress(bidder)}
href={`https://twitter.com/${bidderTwitterHandle}`}
rel="noreferrer"
>{`@${bidderTwitterHandle}`}</a>
) : (
shortenAddress(bidder)
)}
</div>
<div>
{!isCancelled && (
<div className={'flex '}>
{isme && (
<>
<CheckOutlined />
</>
)}
<AmountLabel
style={{ marginBottom: 0, fontSize: '16px' }}
containerStyle={{
flexDirection: 'row',
alignItems: 'center',
}}
displaySymbol={tokenInfo?.symbol || 'CUSTOM'}
iconSize={24}
amount={formatTokenAmount(bid.info.lastBid, mint)}
/>
</div>
)}
</div>
</div>
<div className="bid-info-container">
{format(bid.info.lastBidTimestamp.toNumber() * 1000)}
</div>
</Row>
);
} else {
return (
<Row className={'bid-history'}>
{isCancelled && (
<div
style={{
position: 'absolute',
left: 0,
width: '100%',
height: 1,
background: 'grey',
top: 'calc(50% - 1px)',
zIndex: 2,
}}
/>
)}
<Col span={8}>
{!isCancelled && (
<div className={'flex '}>
{isme && (
<>
<CheckOutlined />
</>
)}
<AmountLabel
style={{ marginBottom: 0, fontSize: '16px' }}
containerStyle={{
flexDirection: 'row',
alignItems: 'center',
}}
displaySymbol={tokenInfo?.symbol || 'CUSTOM'}
tokenInfo={tokenInfo}
iconSize={24}
amount={formatTokenAmount(bid.info.lastBid, mint)}
/>
</div>
)}
</Col>
<Col span={8} style={{ opacity: 0.7 }}>
{/* uses milliseconds */}
{format(bid.info.lastBidTimestamp.toNumber() * 1000)}
</Col>
<Col span={8}>
<div className={'flex-right'}>
<Identicon
style={{
width: 24,
height: 24,
marginRight: 10,
marginTop: 2,
}}
address={bidder}
/>{' '}
<span style={{ opacity: 0.7 }}>
{bidderTwitterHandle ? (
<Row className="pubkey-row">
<a
target="_blank"
title={shortenAddress(bidder)}
href={`https://twitter.com/${bidderTwitterHandle}`}
rel="noreferrer"
>{`@${bidderTwitterHandle}`}</a>
<ClickToCopy
className="copy-pubkey"
copyText={bidder as string}
/>
</Row>
) : (
<Row className="pubkey-row">
{shortenAddress(bidder)}
<ClickToCopy
className="copy-pubkey"
copyText={bidder as string}
/>
</Row>
)}
</span>
</div>
</Col>
</Row>
);
}
}
Example #26
Source File: billing.tsx From metaplex with Apache License 2.0 | 4 votes |
InnerBillingView = ({
auctionView,
wallet,
connection,
mint,
}: {
auctionView: AuctionView;
wallet: WalletSigner;
connection: Connection;
mint: MintInfo;
}) => {
const id = auctionView.thumbnail.metadata.pubkey;
const art = useArt(id);
const balance = useUserBalance(auctionView.auction.info.tokenMint);
const [escrowBalance, setEscrowBalance] = useState<number | undefined>();
const { whitelistedCreatorsByCreator, pullBillingPage } = useMeta();
useEffect(() => {
pullBillingPage(id);
}, []);
const [escrowBalanceRefreshCounter, setEscrowBalanceRefreshCounter] =
useState(0);
useEffect(() => {
connection
.getTokenAccountBalance(
toPublicKey(auctionView.auctionManager.acceptPayment),
)
.then(resp => {
if (resp.value.uiAmount !== undefined && resp.value.uiAmount !== null)
setEscrowBalance(resp.value.uiAmount);
});
}, [escrowBalanceRefreshCounter]);
const myPayingAccount = balance.accounts[0];
const { accountByMint } = useUserAccounts();
const {
bidsToClaim,
totalWinnerPayments,
payoutTickets,
participationPossibleTotal,
participationUnredeemedTotal,
hasParticipation,
} = useBillingInfo({
auctionView,
});
return (
<Content>
<Col>
<Row
style={{ margin: '0 30px', textAlign: 'left', fontSize: '1.4rem' }}
>
<Col span={12}>
<ArtContent
pubkey={id}
className="artwork-image"
allowMeshRender={true}
/>
</Col>
<Col span={12}>
<div style={{ fontWeight: 700 }}>{art.title}</div>
<br />
<div className="info-header">TOTAL AUCTION VALUE</div>
<div className="escrow">
{auctionView.auctionManager.acceptPayment ==
WRAPPED_SOL_MINT.toBase58()
? '◎'
: ''}
{fromLamports(
totalWinnerPayments + participationPossibleTotal,
mint,
)}
</div>
<br />
<div className="info-header">TOTAL AUCTION REDEEMED VALUE</div>
<div className="escrow">
{auctionView.auctionManager.acceptPayment ==
WRAPPED_SOL_MINT.toBase58()
? '◎'
: ''}
{fromLamports(
totalWinnerPayments +
participationPossibleTotal -
participationUnredeemedTotal,
mint,
)}
</div>
<br />
<div className="info-header">
TOTAL COLLECTED BY ARTISTS AND AUCTIONEER
</div>
<div className="escrow">
{auctionView.auctionManager.acceptPayment ==
WRAPPED_SOL_MINT.toBase58()
? '◎'
: ''}
{fromLamports(
Object.values(payoutTickets).reduce(
(acc, el) => (acc += el.sum),
0,
),
mint,
)}
</div>
<br />
<div className="info-header">TOTAL UNSETTLED</div>
<div className="escrow">
{auctionView.auctionManager.acceptPayment ==
WRAPPED_SOL_MINT.toBase58()
? '◎'
: ''}
{fromLamports(
bidsToClaim.reduce(
(acc, el) => (acc += el.metadata.info.lastBid.toNumber()),
0,
),
mint,
)}
</div>
<br />
<div className="info-header">TOTAL IN ESCROW</div>
<div className="escrow">
{escrowBalance !== undefined ? (
`${
auctionView.auction.info.tokenMint ==
WRAPPED_SOL_MINT.toBase58()
? '◎'
: ''
} ${escrowBalance}`
) : (
<Spin />
)}
</div>
<br />
{hasParticipation && (
<>
<div className="info-header">
TOTAL UNREDEEMED PARTICIPATION FEES OUTSTANDING
</div>
<div className="outstanding-open-editions">
{auctionView.auctionManager.acceptPayment ==
WRAPPED_SOL_MINT.toBase58()
? '◎'
: ''}
{fromLamports(participationUnredeemedTotal, mint)}
</div>
<br />
</>
)}
<br />
<Button
type="primary"
size="large"
className="action-btn"
onClick={async () => {
await settle(
connection,
wallet,
auctionView,
bidsToClaim.map(b => b.pot),
myPayingAccount.pubkey,
accountByMint,
);
setEscrowBalanceRefreshCounter(ctr => ctr + 1);
}}
>
SETTLE OUTSTANDING
</Button>
</Col>
</Row>
<Row>
<Table
style={{ width: '100%' }}
columns={[
{
title: 'Name',
dataIndex: 'name',
key: 'name',
},
{
title: 'Address',
dataIndex: 'address',
key: 'address',
},
{
title: 'Amount Paid',
dataIndex: 'amountPaid',
render: (val: number) => (
<span>◎{fromLamports(val, mint)}</span>
),
key: 'amountPaid',
},
]}
dataSource={Object.keys(payoutTickets).map(t => ({
key: t,
name: whitelistedCreatorsByCreator[t]?.info?.name || 'N/A',
address: t,
amountPaid: payoutTickets[t].sum,
}))}
/>
</Row>
</Col>
</Content>
);
}
Example #27
Source File: index.tsx From metaplex with Apache License 2.0 | 4 votes |
MemoizedBar = React.memo(function BarImpl(props: {
sortedSales: number[];
mint: MintInfo;
}) {
const histogrammedData: Record<number, number> = {
0: 0,
5: 0,
20: 0,
50: 0,
100: 0,
500: 0,
1000: 0,
10000: 0,
};
const asArray = [0, 5, 20, 50, 100, 500, 1000, 10000];
for (let i = 0; i < asArray.length; i++) {
const currRange = asArray[i];
if (i < asArray.length - 1) {
const nextRange = asArray[i + 1];
histogrammedData[currRange] = props.sortedSales.filter(
s =>
fromLamports(s, props.mint) >= currRange &&
fromLamports(s, props.mint) < nextRange,
).length;
} else {
histogrammedData[currRange] = props.sortedSales.filter(
s => fromLamports(s, props.mint) >= currRange,
).length;
}
}
const histoData = {
labels: [
'◎ [0 - 5)',
'◎ [5 - 20)',
'◎ [20 - 50)',
'◎ [50 - 100)',
'◎ [100 - 500)',
'◎ [500 - 1000)',
'◎ [1000 - 10000)',
'◎ [10000 -',
],
datasets: [
{
label: '# bids in these bins',
data: asArray.map(a => histogrammedData[a]),
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)',
'rgba(255, 139, 24, 0.2)',
'rgba(212, 39, 24, 0.2)',
],
borderColor: [
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)',
'rgba(255, 139, 24, 1)',
'rgba(212, 39, 24, 1)',
],
borderWidth: 1,
},
],
};
const histoOptions = {
scales: {
yAxes: [
{
ticks: {
beginAtZero: true,
},
},
],
},
};
// @ts-ignore
return <Bar data={histoData} options={histoOptions} />;
})
Example #28
Source File: index.tsx From metaplex with Apache License 2.0 | 4 votes |
function InnerAnalytics({ mint }: { mint: MintInfo }) {
const [usersWithMetadata, setUsersWithMetadata] = useState<
Record<string, boolean>
>({});
const [usersPublished, setUsersPublished] = useState<Record<string, boolean>>(
{},
);
const [usersBid, setUsersBid] = useState<Record<string, boolean>>({});
const [usersEngaged, setUsersEngaged] = useState<Record<string, boolean>>({});
const [byType, setByType] = useState<Record<AuctionType, number>>({
[AuctionType.Open]: 0,
[AuctionType.Limited]: 0,
[AuctionType.Tiered]: 0,
[AuctionType.OneOfKind]: 0,
});
const [averageBids, setAverageBids] = useState<number>(0);
const [averageSale, setAverageSale] = useState<number>(0);
const [highestSale, setHighestSale] = useState<number>(0);
const [sortedSales, setSortedSales] = useState<number[]>([]);
const {
metadata,
// stores,
auctionManagersByAuction,
bidderPotsByAuctionAndBidder,
auctionDataExtended,
} = useMeta();
const totalNFTs = metadata.length;
// const totalMarketplaces = Object.values(stores).length;
const auctionViews = useAuctions();
return (
<Content>
<Col style={{ marginTop: 10 }}>
<Button
type="primary"
size="large"
className="action-btn"
onClick={() =>
rerun({
auctionViews,
auctionManagersByAuction,
usersEngaged,
auctionDataExtended,
bidderPotsByAuctionAndBidder,
metadata,
setByType,
setAverageBids,
setUsersPublished,
setAverageSale,
setHighestSale,
setSortedSales,
setUsersWithMetadata,
setUsersBid,
setUsersEngaged,
})
}
>
RERUN CALCULATION
</Button>
<h1>Overview</h1>
<h3>
Total NFTs: {totalNFTs}
{/* Total Marketplaces: {totalMarketplaces} */}
</h3>
<h1>User Breakdown</h1>
<h3>Any Engagement: {Object.values(usersEngaged).length}</h3>
<h3>That bid: {Object.values(usersBid).length}</h3>
<h3>That sold items: {Object.values(usersPublished).length}</h3>
<h3>That minted NFTs: {Object.values(usersWithMetadata).length}</h3>
<h1>Sale Info</h1>
<h3>
Total Sales: ◎
{fromLamports(
sortedSales.reduce((acc, r) => (acc += r), 0),
mint,
)}
</h3>
<MemoizedBar sortedSales={sortedSales} mint={mint} />
<h3>Highest Sale: ◎ {fromLamports(highestSale, mint)}</h3>
<h3>Average Sale: ◎ {fromLamports(averageSale, mint)}</h3>
<h1>Auction Info</h1>
<h3>Average Bids per Auction: {averageBids}</h3>
<MemoizedPie byType={byType} />
</Col>
</Content>
);
}
Example #29
Source File: sendPlaceBid.ts From metaplex with Apache License 2.0 | 4 votes |
export async function setupPlaceBid(
connection: Connection,
wallet: WalletSigner,
bidderTokenAccount: string | undefined,
auctionView: AuctionView,
accountsByMint: Map<string, TokenAccount>,
// value entered by the user adjust to decimals of the mint
// If BN, then assume instant sale and decimals already adjusted.
amount: number | BN,
overallInstructions: TransactionInstruction[][],
overallSigners: Keypair[][],
): Promise<BN> {
if (!wallet.publicKey) throw new WalletNotConnectedError();
let signers: Keypair[] = [];
let instructions: TransactionInstruction[] = [];
const cleanupInstructions: TransactionInstruction[] = [];
const accountRentExempt = await connection.getMinimumBalanceForRentExemption(
AccountLayout.span,
);
const tokenAccount = bidderTokenAccount
? (cache.get(bidderTokenAccount) as TokenAccount)
: undefined;
const mint = cache.get(
tokenAccount ? tokenAccount.info.mint : QUOTE_MINT,
) as ParsedAccount<MintInfo>;
const lamports =
accountRentExempt +
(typeof amount === 'number'
? toLamports(amount, mint.info)
: amount.toNumber());
let bidderPotTokenAccount: string | undefined;
if (auctionView.myBidderPot) {
bidderPotTokenAccount = auctionView.myBidderPot?.info.bidderPot;
if (!auctionView.auction.info.ended()) {
const cancelSigners: Keypair[][] = [];
const cancelInstr: TransactionInstruction[][] = [];
await setupCancelBid(
auctionView,
accountsByMint,
accountRentExempt,
wallet,
cancelSigners,
cancelInstr,
connection,
);
signers = [...signers, ...cancelSigners[0]];
instructions = [...cancelInstr[0], ...instructions];
}
}
let receivingSolAccountOrAta = '';
if (auctionView.auction.info.tokenMint == WRAPPED_SOL_MINT.toBase58()) {
receivingSolAccountOrAta = ensureWrappedAccount(
instructions,
cleanupInstructions,
tokenAccount,
wallet.publicKey,
lamports + accountRentExempt * 2,
signers,
);
} else {
receivingSolAccountOrAta = await findAta(auctionView, wallet, connection);
}
const transferAuthority = approve(
instructions,
cleanupInstructions,
toPublicKey(receivingSolAccountOrAta),
wallet.publicKey,
lamports - accountRentExempt,
);
signers.push(transferAuthority);
const bid = new BN(lamports - accountRentExempt);
await placeBid(
wallet.publicKey.toBase58(),
pubkeyToString(receivingSolAccountOrAta),
bidderPotTokenAccount,
auctionView.auction.info.tokenMint,
transferAuthority.publicKey.toBase58(),
wallet.publicKey.toBase58(),
auctionView.auctionManager.vault,
bid,
instructions,
);
overallInstructions.push([...instructions, ...cleanupInstructions.reverse()]);
overallSigners.push(signers);
return bid;
}