bridge_ui: nft supply check
Change-Id: Ib74c0add8a093ccfef571fc345951f6a818cb75c
This commit is contained in:
parent
8dd29f2b88
commit
302368d704
|
@ -30,6 +30,7 @@ import { NFTParsedTokenAccount } from "../store/nftSlice";
|
|||
import { hexToNativeString, uint8ArrayToHex } from "../utils/array";
|
||||
import {
|
||||
CHAINS,
|
||||
CHAINS_BY_ID,
|
||||
ETH_NFT_BRIDGE_ADDRESS,
|
||||
SOLANA_HOST,
|
||||
SOL_NFT_BRIDGE_ADDRESS,
|
||||
|
@ -294,6 +295,9 @@ export default function NFTOriginVerifier() {
|
|||
>
|
||||
Origin Info
|
||||
</Typography>
|
||||
<Typography variant="body2" gutterBottom>
|
||||
Chain: {CHAINS_BY_ID[originInfo.chainId].name}
|
||||
</Typography>
|
||||
<Typography variant="body2" gutterBottom>
|
||||
Address: {readableAddress}
|
||||
</Typography>
|
||||
|
|
|
@ -236,7 +236,7 @@ export default function NFTViewer({
|
|||
})}
|
||||
>
|
||||
{hasVideo ? (
|
||||
<video autoPlay controls style={{ maxWidth: "100%" }}>
|
||||
<video autoPlay controls loop style={{ maxWidth: "100%" }}>
|
||||
<source src={safeIPFS(metadata.animation_url || "")} />
|
||||
{image}
|
||||
</video>
|
||||
|
|
|
@ -13,7 +13,7 @@ import {
|
|||
MIGRATION_ASSET_MAP,
|
||||
WORMHOLE_V1_MINT_AUTHORITY,
|
||||
} from "../../utils/consts";
|
||||
import { shortenAddress } from "../../utils/solana";
|
||||
import { ExtractedMintInfo, shortenAddress } from "../../utils/solana";
|
||||
import NFTViewer from "./NFTViewer";
|
||||
import RefreshButtonWrapper from "./RefreshButtonWrapper";
|
||||
|
||||
|
@ -37,7 +37,9 @@ type SolanaSourceTokenSelectorProps = {
|
|||
onChange: (newValue: ParsedTokenAccount | null) => void;
|
||||
accounts: ParsedTokenAccount[];
|
||||
disabled: boolean;
|
||||
mintAccounts: DataWrapper<Map<string, string | null>> | undefined;
|
||||
mintAccounts:
|
||||
| DataWrapper<Map<string, ExtractedMintInfo | null> | undefined>
|
||||
| undefined;
|
||||
resetAccounts: (() => void) | undefined;
|
||||
nft?: boolean;
|
||||
};
|
||||
|
@ -135,13 +137,13 @@ export default function SolanaSourceTokenSelector(
|
|||
if (!props.mintAccounts?.data) {
|
||||
return true; //These should never be null by this point
|
||||
}
|
||||
const mintInfo = props.mintAccounts.data.get(address);
|
||||
const mintAuthority = props.mintAccounts.data.get(address)?.mintAuthority;
|
||||
|
||||
if (!mintInfo) {
|
||||
if (!mintAuthority) {
|
||||
return true; //We should never fail to pull the mint of an account.
|
||||
}
|
||||
|
||||
if (mintInfo === WORMHOLE_V1_MINT_AUTHORITY) {
|
||||
if (mintAuthority === WORMHOLE_V1_MINT_AUTHORITY) {
|
||||
return true; //This means the mint was created by the wormhole v1 contract, and we want to disallow its transfer.
|
||||
}
|
||||
|
||||
|
@ -233,16 +235,17 @@ export default function SolanaSourceTokenSelector(
|
|||
//difficult to do before this point.
|
||||
const filteredOptions = useMemo(() => {
|
||||
return props.accounts.filter((x) => {
|
||||
//TODO, do a better check which likely involves supply or checking masterEdition.
|
||||
const zeroBalance = x.amount === "0";
|
||||
if (zeroBalance) {
|
||||
return false;
|
||||
}
|
||||
const isNFT =
|
||||
x.decimals === 0 && metaplex.data?.get(x.mintKey)?.data?.uri;
|
||||
x.decimals === 0 &&
|
||||
metaplex.data?.get(x.mintKey)?.data?.uri &&
|
||||
mintAccounts?.data?.get(x.mintKey)?.supply === "1";
|
||||
return nft ? isNFT : !isNFT;
|
||||
});
|
||||
}, [metaplex.data, nft, props.accounts]);
|
||||
}, [mintAccounts?.data, metaplex.data, nft, props.accounts]);
|
||||
|
||||
const isOptionDisabled = useMemo(() => {
|
||||
return (value: ParsedTokenAccount) => {
|
||||
|
|
|
@ -55,7 +55,8 @@ import {
|
|||
WETH_DECIMALS,
|
||||
} from "../utils/consts";
|
||||
import {
|
||||
extractMintAuthorityInfo,
|
||||
ExtractedMintInfo,
|
||||
extractMintInfo,
|
||||
getMultipleAccountsRPC,
|
||||
} from "../utils/solana";
|
||||
|
||||
|
@ -336,7 +337,9 @@ function useGetAvailableTokens(nft: boolean = false) {
|
|||
string | undefined
|
||||
>(undefined);
|
||||
|
||||
const [solanaMintAccounts, setSolanaMintAccounts] = useState<any>(undefined);
|
||||
const [solanaMintAccounts, setSolanaMintAccounts] = useState<
|
||||
Map<string, ExtractedMintInfo | null> | undefined
|
||||
>(undefined);
|
||||
const [solanaMintAccountsLoading, setSolanaMintAccountsLoading] =
|
||||
useState(false);
|
||||
const [solanaMintAccountsError, setSolanaMintAccountsError] = useState<
|
||||
|
@ -425,6 +428,10 @@ function useGetAvailableTokens(nft: boolean = false) {
|
|||
// mintAddresses.push("4QixXecTZ4zdZGa39KH8gVND5NZ2xcaB12wiBhE4S7rn");
|
||||
//SOLT devnet token
|
||||
// mintAddresses.push("2WDq7wSs9zYrpx2kbHDA4RUTRch2CCTP6ZWaH4GNfnQQ");
|
||||
// bad monkey "NFT"
|
||||
// mintAddresses.push("5FJeEJR8576YxXFdGRAu4NBBFcyfmtjsZrXHSsnzNPdS");
|
||||
// degenerate monkey NFT
|
||||
// mintAddresses.push("EzYsbigNNGbNuANRJ3mnnyJYU2Bk7mBYVsxuonUwAX7r");
|
||||
|
||||
const connection = new Connection(SOLANA_HOST, "confirmed");
|
||||
getMultipleAccountsRPC(
|
||||
|
@ -433,12 +440,12 @@ function useGetAvailableTokens(nft: boolean = false) {
|
|||
).then(
|
||||
(results) => {
|
||||
if (!cancelled) {
|
||||
const output = new Map<String, string | null>();
|
||||
const output = new Map<string, ExtractedMintInfo | null>();
|
||||
|
||||
results.forEach((result, index) =>
|
||||
output.set(
|
||||
mintAddresses[index],
|
||||
(result && extractMintAuthorityInfo(result)) || null
|
||||
(result && extractMintInfo(result)) || null
|
||||
)
|
||||
);
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { BigNumber } from "@ethersproject/bignumber";
|
||||
import { MintLayout } from "@solana/spl-token";
|
||||
import { WalletContextState } from "@solana/wallet-adapter-react";
|
||||
import {
|
||||
|
@ -21,17 +22,26 @@ export async function signSendAndConfirm(
|
|||
return txid;
|
||||
}
|
||||
|
||||
export function extractMintAuthorityInfo(
|
||||
export interface ExtractedMintInfo {
|
||||
mintAuthority?: string;
|
||||
supply?: string;
|
||||
}
|
||||
|
||||
export function extractMintInfo(
|
||||
account: AccountInfo<Buffer>
|
||||
): string | null {
|
||||
): ExtractedMintInfo {
|
||||
const data = Buffer.from(account.data);
|
||||
const mintInfo = MintLayout.decode(data);
|
||||
|
||||
const uintArray = mintInfo?.mintAuthority;
|
||||
const pubkey = new PublicKey(uintArray);
|
||||
const output = pubkey?.toString();
|
||||
const supply = BigNumber.from(mintInfo?.supply.reverse()).toString();
|
||||
const output = {
|
||||
mintAuthority: pubkey?.toString(),
|
||||
supply: supply.toString(),
|
||||
};
|
||||
|
||||
return output || null;
|
||||
return output;
|
||||
}
|
||||
|
||||
export async function getMultipleAccountsRPC(
|
||||
|
|
Loading…
Reference in New Issue