diff --git a/app/api/domain-info/[domain]/route.ts b/app/api/domain-info/[domain]/route.ts new file mode 100644 index 00000000..a5d3759a --- /dev/null +++ b/app/api/domain-info/[domain]/route.ts @@ -0,0 +1,31 @@ +import { Connection } from "@solana/web3.js" +import { NextResponse } from "next/server" + +import { MAINNET_BETA_URL } from "@/app/utils/cluster" +import { getDomainInfo } from "@/app/utils/domain-info" + +type Params = { + params: { + domain: string + } +} + +export type FetchedDomainInfo = Awaited>; + +export async function GET( + _request: Request, + { params: { domain } }: Params +) { + // Intentionally using legacy web3js for compatibility with bonfida library + // This is an API route so won't affect client bundle + // We only fetch domains on mainnet + const connection = new Connection(MAINNET_BETA_URL); + const domainInfo = await getDomainInfo(domain, connection); + + return NextResponse.json(domainInfo, { + headers: { + // 24 hours + "Cache-Control": "max-age=86400" + } + }); +} diff --git a/app/components/SearchBar.tsx b/app/components/SearchBar.tsx index 58e52fdf..683baad8 100644 --- a/app/components/SearchBar.tsx +++ b/app/components/SearchBar.tsx @@ -3,16 +3,16 @@ import { useCluster } from '@providers/cluster'; import { useTokenRegistry } from '@providers/token-registry'; import { TokenInfoMap } from '@solana/spl-token-registry'; -import { Connection } from '@solana/web3.js'; import { Cluster } from '@utils/cluster'; -import { getDomainInfo, hasDomainSyntax } from '@utils/name-service'; -import { LOADER_IDS, LoaderName, PROGRAM_INFO_BY_ID, SPECIAL_IDS, SYSVAR_IDS } from '@utils/tx'; import bs58 from 'bs58'; import { useRouter, useSearchParams } from 'next/navigation'; import React, { useId } from 'react'; import { Search } from 'react-feather'; import Select, { ActionMeta, InputActionMeta, ValueType } from 'react-select'; +import { FetchedDomainInfo } from '../api/domain-info/[domain]/route'; +import { LOADER_IDS, LoaderName, PROGRAM_INFO_BY_ID, SPECIAL_IDS, SYSVAR_IDS } from '../utils/programs'; + interface SearchOptions { label: string; options: { @@ -22,6 +22,10 @@ interface SearchOptions { }[]; } +const hasDomainSyntax = (value: string) => { + return value.length > 4 && value.substring(value.length - 4) === '.sol'; +}; + export function SearchBar() { const [search, setSearch] = React.useState(''); const searchRef = React.useRef(''); @@ -31,7 +35,7 @@ export function SearchBar() { const selectRef = React.useRef | null>(null); const router = useRouter(); const { tokenRegistry } = useTokenRegistry(); - const { url, cluster, clusterInfo } = useCluster(); + const { cluster, clusterInfo } = useCluster(); const searchParams = useSearchParams(); const onChange = ({ pathname }: ValueType, meta: ActionMeta) => { if (meta.action === 'select-option') { @@ -58,7 +62,7 @@ export function SearchBar() { setSearchOptions(options); // checking for non local search output - if (hasDomainSyntax(search)) { + if (hasDomainSyntax(search) && cluster === Cluster.MainnetBeta) { // if search input is a potential domain we continue the loading state domainSearch(options); } else { @@ -72,9 +76,8 @@ export function SearchBar() { // appends domain lookup results to the local search state const domainSearch = async (options: SearchOptions[]) => { setLoadingSearchMessage('Looking up domain...'); - const connection = new Connection(url); const searchTerm = search; - const updatedOptions = await buildDomainOptions(connection, search, options); + const updatedOptions = await buildDomainOptions(search, options); if (searchRef.current === searchTerm) { setSearchOptions(updatedOptions); // after attempting to fetch the domain name we can conclude the loading state @@ -213,8 +216,9 @@ function buildTokenOptions(search: string, cluster: Cluster, tokenRegistry: Toke } } -async function buildDomainOptions(connection: Connection, search: string, options: SearchOptions[]) { - const domainInfo = await getDomainInfo(search, connection); +async function buildDomainOptions(search: string, options: SearchOptions[]) { + const domainInfoResponse = await fetch(`/api/domain-info/${search}`); + const domainInfo = await domainInfoResponse.json() as FetchedDomainInfo; const updatedOptions: SearchOptions[] = [...options]; if (domainInfo && domainInfo.owner && domainInfo.address) { updatedOptions.push({ diff --git a/app/components/account/DomainsCard.tsx b/app/components/account/DomainsCard.tsx index 5d738a40..141c1bab 100644 --- a/app/components/account/DomainsCard.tsx +++ b/app/components/account/DomainsCard.tsx @@ -3,9 +3,11 @@ import { Address } from '@components/common/Address'; import { ErrorCard } from '@components/common/ErrorCard'; import { LoadingCard } from '@components/common/LoadingCard'; -import { DomainInfo, useUserDomains } from '@utils/name-service'; +import { useUserDomains } from '@utils/name-service'; import React from 'react'; +import { DomainInfo } from '@/app/utils/domain-info'; + export function DomainsCard({ address }: { address: string }) { const [domains, domainsLoading] = useUserDomains(address); diff --git a/app/utils/domain-info.ts b/app/utils/domain-info.ts new file mode 100644 index 00000000..8b4394d9 --- /dev/null +++ b/app/utils/domain-info.ts @@ -0,0 +1,40 @@ +import { getHashedName, getNameAccountKey, getNameOwner } from "@bonfida/spl-name-service"; +import { Connection, PublicKey } from "@solana/web3.js"; + +// Address of the SOL TLD +export const SOL_TLD_AUTHORITY = new PublicKey('58PwtjSDuFHuUkYjH9BYnnQKHfwo9reZhC2zMJv9JPkx'); + +async function getDomainKey(name: string, nameClass?: PublicKey, nameParent?: PublicKey) { + const hashedDomainName = await getHashedName(name); + const nameKey = await getNameAccountKey(hashedDomainName, nameClass, nameParent); + return nameKey; +} + +export interface DomainInfo { + name: string; + address: PublicKey; +} + +export const hasDomainSyntax = (value: string) => { + return value.length > 4 && value.substring(value.length - 4) === '.sol'; +}; + +// returns non empty wallet string if a given .sol domain is owned by a wallet +export async function getDomainInfo(domain: string, connection: Connection) { + const domainKey = await getDomainKey( + domain.slice(0, -4), // remove .sol + undefined, + SOL_TLD_AUTHORITY + ); + try { + const registry = await getNameOwner(connection, domainKey); + return registry && registry.registry.owner + ? { + address: domainKey.toString(), + owner: registry.registry.owner.toString(), + } + : null; + } catch { + return null; + } +} diff --git a/app/utils/name-service.tsx b/app/utils/name-service.tsx index 81697c98..40fa3e1d 100644 --- a/app/utils/name-service.tsx +++ b/app/utils/name-service.tsx @@ -2,9 +2,6 @@ import { getFilteredProgramAccounts, - getHashedName, - getNameAccountKey, - getNameOwner, NAME_PROGRAM_ID, performReverseLookup, } from '@bonfida/spl-name-service'; @@ -13,42 +10,7 @@ import { Connection, PublicKey } from '@solana/web3.js'; import { Cluster } from '@utils/cluster'; import { useEffect, useState } from 'react'; -// Address of the SOL TLD -const SOL_TLD_AUTHORITY = new PublicKey('58PwtjSDuFHuUkYjH9BYnnQKHfwo9reZhC2zMJv9JPkx'); - -export interface DomainInfo { - name: string; - address: PublicKey; -} -export const hasDomainSyntax = (value: string) => { - return value.length > 4 && value.substring(value.length - 4) === '.sol'; -}; - -async function getDomainKey(name: string, nameClass?: PublicKey, nameParent?: PublicKey) { - const hashedDomainName = await getHashedName(name); - const nameKey = await getNameAccountKey(hashedDomainName, nameClass, nameParent); - return nameKey; -} - -// returns non empty wallet string if a given .sol domain is owned by a wallet -export async function getDomainInfo(domain: string, connection: Connection) { - const domainKey = await getDomainKey( - domain.slice(0, -4), // remove .sol - undefined, - SOL_TLD_AUTHORITY - ); - try { - const registry = await getNameOwner(connection, domainKey); - return registry && registry.registry.owner - ? { - address: domainKey.toString(), - owner: registry.registry.owner.toString(), - } - : null; - } catch { - return null; - } -} +import { DomainInfo, SOL_TLD_AUTHORITY } from './domain-info'; async function getUserDomainAddresses(connection: Connection, userAddress: string): Promise { const filters = [ diff --git a/app/utils/programs.ts b/app/utils/programs.ts new file mode 100644 index 00000000..a6c026ef --- /dev/null +++ b/app/utils/programs.ts @@ -0,0 +1,436 @@ +import { Cluster } from "./cluster"; + +export enum PROGRAM_NAMES { + // native built-ins + ADDRESS_LOOKUP_TABLE = 'Address Lookup Table Program', + COMPUTE_BUDGET = 'Compute Budget Program', + CONFIG = 'Config Program', + STAKE = 'Stake Program', + SYSTEM = 'System Program', + VOTE = 'Vote Program', + + // native precompiles + SECP256K1 = 'Secp256k1 SigVerify Precompile', + ED25519 = 'Ed25519 SigVerify Precompile', + + // spl + ASSOCIATED_TOKEN = 'Associated Token Program', + ACCOUNT_COMPRESSION = 'State Compression Program', + FEATURE_PROPOSAL = 'Feature Proposal Program', + LENDING = 'Lending Program', + MEMO = 'Memo Program', + MEMO_2 = 'Memo Program v2', + NAME = 'Name Service Program', + STAKE_POOL = 'Stake Pool Program', + SWAP = 'Swap Program', + TOKEN = 'Token Program', + TOKEN_METADATA = 'Token Metadata Program', + TOKEN_VAULT = 'Token Vault Program', + + // other + ACUMEN = 'Acumen Program', + BREAK_SOLANA = 'Break Solana Program', + CHAINLINK_ORACLE = 'Chainlink OCR2 Oracle Program', + CHAINLINK_STORE = 'Chainlink Store Program', + CLOCKWORK_1 = 'Clockwork Thread Program v1', + CLOCKWORK_2 = 'Clockwork Thread Program v2', + MANGO_GOVERNANCE = 'Mango Governance Program', + MANGO_ICO = 'Mango ICO Program', + MANGO_1 = 'Mango Program v1', + MANGO_2 = 'Mango Program v2', + MANGO_3 = 'Mango Program v3', + MARINADE = 'Marinade Staking Program', + MERCURIAL = 'Mercurial Stable Swap Program', + METAPLEX = 'Metaplex Program', + NFT_AUCTION = 'NFT Auction Program', + NFT_CANDY_MACHINE = 'NFT Candy Machine Program', + NFT_CANDY_MACHINE_V2 = 'NFT Candy Machine Program V2', + ORCA_SWAP_1 = 'Orca Swap Program v1', + ORCA_SWAP_2 = 'Orca Swap Program v2', + ORCA_AQUAFARM = 'Orca Aquafarm Program', + PORT = 'Port Finance Program', + PYTH_DEVNET = 'Pyth Oracle Program', + PYTH_TESTNET = 'Pyth Oracle Program', + PYTH_MAINNET = 'Pyth Oracle Program', + QUARRY_MERGE_MINE = 'Quarry Merge Mine', + QUARRY_MINE = 'Quarry Mine', + QUARRY_MINT_WRAPPER = 'Quarry Mint Wrapper', + QUARRY_REDEEMER = 'Quarry Redeemer', + QUARRY_REGISTRY = 'Quarry Registry', + RAYDIUM_AMM = 'Raydium AMM Program', + RAYDIUM_IDO = 'Raydium IDO Program', + RAYDIUM_LP_1 = 'Raydium Liquidity Pool Program v1', + RAYDIUM_LP_2 = 'Raydium Liquidity Pool Program v2', + RAYDIUM_STAKING = 'Raydium Staking Program', + SABER_ROUTER = 'Saber Router Program', + SABER_SWAP = 'Saber Stable Swap Program', + SERUM_1 = 'Serum Dex Program v1', + SERUM_2 = 'Serum Dex Program v2', + SERUM_3 = 'Serum Dex Program v3', + SERUM_SWAP = 'Serum Swap Program', + SERUM_POOL = 'Serum Pool', + SOLEND = 'Solend Program', + SOLIDO = 'Lido for Solana Program', + STEP_SWAP = 'Step Finance Swap Program', + SWIM_SWAP = 'Swim Swap Program', + SWITCHBOARD = 'Switchboard Oracle Program', + WORMHOLE = 'Wormhole', + WORMHOLE_CORE = 'Wormhole Core Bridge', + WORMHOLE_TOKEN = 'Wormhole Token Bridge', + WORMHOLE_NFT = 'Wormhole NFT Bridge', + SOLANART = 'Solanart', + SOLANART_GO = 'Solanart - Global offers', + STEPN_DEX = 'STEPN Dex', + OPENBOOK_DEX = 'OpenBook Dex', +} + +const ALL_CLUSTERS = [Cluster.Custom, Cluster.Devnet, Cluster.Testnet, Cluster.MainnetBeta]; + +const LIVE_CLUSTERS = [Cluster.Devnet, Cluster.Testnet, Cluster.MainnetBeta]; + +export const LOADER_IDS: { [key: string]: string } = { + BPFLoader1111111111111111111111111111111111: 'BPF Loader', + BPFLoader2111111111111111111111111111111111: 'BPF Loader 2', + BPFLoaderUpgradeab1e11111111111111111111111: 'BPF Upgradeable Loader', + MoveLdr111111111111111111111111111111111111: 'Move Loader', + NativeLoader1111111111111111111111111111111: 'Native Loader', +} as const; + +export type LoaderName = (typeof LOADER_IDS)[keyof typeof LOADER_IDS]; + +export type ProgramInfo = { + name: string; + deployments: Cluster[]; +}; + +export const PROGRAM_INFO_BY_ID: { [address: string]: ProgramInfo } = { + '11111111111111111111111111111111': { + deployments: ALL_CLUSTERS, + name: PROGRAM_NAMES.SYSTEM, + }, + '22Y43yTVxuUkoRKdm9thyRhQ3SdgQS7c7kB6UNCiaczD': { + deployments: [Cluster.MainnetBeta], + name: PROGRAM_NAMES.SERUM_SWAP, + }, + '27haf8L6oxUeXrHrgEgsexjSY5hbVUWEmvv9Nyxg8vQv': { + deployments: [Cluster.MainnetBeta], + name: PROGRAM_NAMES.RAYDIUM_LP_2, + }, + '2rHhojZ7hpu1zA91nvZmT8TqWWvMcKmmNBCr2mKTtMq4': { + deployments: [Cluster.Devnet], + name: PROGRAM_NAMES.WORMHOLE_NFT, + }, + '3XXuUFfweXBwFgFfYaejLvZE4cGZiHgKiGfMtdxNzYmv': { + deployments: [Cluster.MainnetBeta, Cluster.Devnet], + name: PROGRAM_NAMES.CLOCKWORK_1, + }, + '3u8hJUVTA4jH1wYAyUur7FFZVQ8H635K3tSHHF4ssjQ5': { + deployments: [Cluster.Devnet], + name: PROGRAM_NAMES.WORMHOLE_CORE, + }, + '5ZfZAwP2m93waazg8DkrrVmsupeiPEvaEHowiUP7UAbJ': { + deployments: [Cluster.MainnetBeta], + name: PROGRAM_NAMES.SOLANART_GO, + }, + '5fNfvyp5czQVX77yoACa3JJVEhdRaWjPuazuWgjhTqEH': { + deployments: [Cluster.MainnetBeta], + name: PROGRAM_NAMES.MANGO_2, + }, + '675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8': { + deployments: [Cluster.MainnetBeta], + name: PROGRAM_NAMES.RAYDIUM_AMM, + }, + '7sPptkymzvayoSbLXzBsXEF8TSf3typNnAWkrKrDizNb': { + deployments: [Cluster.MainnetBeta], + name: PROGRAM_NAMES.MANGO_ICO, + }, + '82yxjeMsvaURa4MbZZ7WZZHfobirZYkH1zF8fmeGtyaQ': { + deployments: [Cluster.MainnetBeta], + name: PROGRAM_NAMES.ORCA_AQUAFARM, + }, + '8tfDNiaEyrV6Q1U4DEXrEigs9DoDtkugzFbybENEbCDz': { + deployments: [Cluster.Testnet], + name: PROGRAM_NAMES.PYTH_TESTNET, + }, + '9HzJyW1qZsEiSfMUf6L2jo3CcTKAyBmSyKdwQeYisHrC': { + deployments: [Cluster.MainnetBeta], + name: PROGRAM_NAMES.RAYDIUM_IDO, + }, + '9W959DqEETiGZocYWCQPaJ6sBmUzgfxXfqGeTEdp3aQP': { + deployments: [Cluster.MainnetBeta], + name: PROGRAM_NAMES.ORCA_SWAP_2, + }, + '9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin': { + deployments: [Cluster.MainnetBeta], + name: PROGRAM_NAMES.SERUM_3, + }, + // spl + ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL: { + deployments: ALL_CLUSTERS, + name: PROGRAM_NAMES.ASSOCIATED_TOKEN, + }, + // native built-ins + AddressLookupTab1e1111111111111111111111111: { + deployments: ALL_CLUSTERS, + name: PROGRAM_NAMES.ADDRESS_LOOKUP_TABLE, + }, + BJ3jrUzddfuSrZHXSCxMUUQsjKEyLmuuyZebkcaFp2fg: { + deployments: [Cluster.MainnetBeta], + name: PROGRAM_NAMES.SERUM_1, + }, + BrEAK7zGZ6dM71zUDACDqJnekihmwF15noTddWTsknjC: { + deployments: LIVE_CLUSTERS, + name: PROGRAM_NAMES.BREAK_SOLANA, + }, + // other + C64kTdg1Hzv5KoQmZrQRcm2Qz7PkxtFBgw7EpFhvYn8W: { + deployments: [Cluster.MainnetBeta], + name: PROGRAM_NAMES.ACUMEN, + }, + CJsLwbP1iu5DuUikHEJnLfANgKy6stB2uFgvBBHoyxwz: { + deployments: [Cluster.MainnetBeta], + name: PROGRAM_NAMES.SOLANART, + }, + CLoCKyJ6DXBJqqu2VWx9RLbgnwwR6BMHHuyasVmfMzBh: { + deployments: [Cluster.MainnetBeta, Cluster.Devnet], + name: PROGRAM_NAMES.CLOCKWORK_2, + }, + ComputeBudget111111111111111111111111111111: { + deployments: ALL_CLUSTERS, + name: PROGRAM_NAMES.COMPUTE_BUDGET, + }, + Config1111111111111111111111111111111111111: { + deployments: ALL_CLUSTERS, + name: PROGRAM_NAMES.CONFIG, + }, + CrX7kMhLC3cSsXJdT7JDgqrRVWGnUpX3gfEfxxU2NVLi: { + deployments: [Cluster.MainnetBeta], + name: PROGRAM_NAMES.SOLIDO, + }, + Crt7UoUR6QgrFrN7j8rmSQpUTNWNSitSwWvsWGf1qZ5t: { + deployments: [Cluster.Devnet, Cluster.MainnetBeta], + name: PROGRAM_NAMES.SABER_ROUTER, + }, + DZnkkTmCiFWfYTfT41X3Rd1kDgozqzxWaHqsw6W4x2oe: { + deployments: [Cluster.Devnet], + name: PROGRAM_NAMES.WORMHOLE_TOKEN, + }, + DjVE6JNiYqPL2QXyCUUh8rNjHrbz9hXHNYt99MQ59qw1: { + deployments: [Cluster.MainnetBeta], + name: PROGRAM_NAMES.ORCA_SWAP_1, + }, + Dooar9JkhdZ7J3LHN3A7YCuoGRUggXhQaG4kijfLGU2j: { + deployments: [Cluster.MainnetBeta], + name: PROGRAM_NAMES.STEPN_DEX, + }, + DtmE9D2CSB4L5D6A15mraeEjrGMm6auWVzgaD8hK2tZM: { + deployments: [Cluster.MainnetBeta], + name: PROGRAM_NAMES.SWITCHBOARD, + }, + EUqojwWA2rd19FZrzeBncJsm38Jm1hEhE3zsmX3bRc2o: { + deployments: [Cluster.MainnetBeta], + name: PROGRAM_NAMES.SERUM_2, + }, + Ed25519SigVerify111111111111111111111111111: { + deployments: ALL_CLUSTERS, + name: PROGRAM_NAMES.ED25519, + }, + EhhTKczWMGQt46ynNeRX1WfeagwwJd7ufHvCDjRxjo5Q: { + deployments: [Cluster.MainnetBeta], + name: PROGRAM_NAMES.RAYDIUM_STAKING, + }, + Feat1YXHhH6t1juaWF74WLcfv4XoNocjXA6sPWHNgAse: { + deployments: ALL_CLUSTERS, + name: PROGRAM_NAMES.FEATURE_PROPOSAL, + }, + FsJ3A3u2vn5cTVofAjvy6y5kwABJAqYWpe4975bi2epH: { + deployments: [Cluster.MainnetBeta], + name: PROGRAM_NAMES.PYTH_MAINNET, + }, + GqTPL6qRf5aUuqscLh8Rg2HTxPUXfhhAXDptTLhp1t2J: { + deployments: [Cluster.MainnetBeta], + name: PROGRAM_NAMES.MANGO_GOVERNANCE, + }, + HEvSKofvBgfaexv23kMabbYqxasxU3mQ4ibBMEmJWHny: { + deployments: [Cluster.Devnet, Cluster.MainnetBeta], + name: PROGRAM_NAMES.CHAINLINK_STORE, + }, + JD3bq9hGdy38PuWQ4h2YJpELmHVGPPfFSuFkpzAd9zfu: { + deployments: [Cluster.MainnetBeta], + name: PROGRAM_NAMES.MANGO_1, + }, + KeccakSecp256k11111111111111111111111111111: { + deployments: ALL_CLUSTERS, + name: PROGRAM_NAMES.SECP256K1, + }, + LendZqTs7gn5CTSJU1jWKhKuVpjJGom45nnwPb2AMTi: { + deployments: LIVE_CLUSTERS, + name: PROGRAM_NAMES.LENDING, + }, + MERLuDFBMmsHnsBPZw2sDQZHvXFMwp8EdjudcU2HKky: { + deployments: [Cluster.Devnet, Cluster.MainnetBeta], + name: PROGRAM_NAMES.MERCURIAL, + }, + MarBmsSgKXdrN1egZf5sqe1TMai9K1rChYNDJgjq7aD: { + deployments: [Cluster.MainnetBeta], + name: PROGRAM_NAMES.MARINADE, + }, + Memo1UhkJRfHyvLMcVucJwxXeuD728EqVDDwQDxFMNo: { + deployments: ALL_CLUSTERS, + name: PROGRAM_NAMES.MEMO, + }, + MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr: { + deployments: ALL_CLUSTERS, + name: PROGRAM_NAMES.MEMO_2, + }, + Port7uDYB3wk6GJAw4KT1WpTeMtSu9bTcChBHkX2LfR: { + deployments: [Cluster.MainnetBeta], + name: PROGRAM_NAMES.PORT, + }, + QMMD16kjauP5knBwxNUJRZ1Z5o3deBuFrqVjBVmmqto: { + deployments: LIVE_CLUSTERS, + name: PROGRAM_NAMES.QUARRY_MERGE_MINE, + }, + QMNeHCGYnLVDn1icRAfQZpjPLBNkfGbSKRB83G5d8KB: { + deployments: LIVE_CLUSTERS, + name: PROGRAM_NAMES.QUARRY_MINE, + }, + QMWoBmAyJLAsA1Lh9ugMTw2gciTihncciphzdNzdZYV: { + deployments: LIVE_CLUSTERS, + name: PROGRAM_NAMES.QUARRY_MINT_WRAPPER, + }, + QRDxhMw1P2NEfiw5mYXG79bwfgHTdasY2xNP76XSea9: { + deployments: LIVE_CLUSTERS, + name: PROGRAM_NAMES.QUARRY_REDEEMER, + }, + QREGBnEj9Sa5uR91AV8u3FxThgP5ZCvdZUW2bHAkfNc: { + deployments: LIVE_CLUSTERS, + name: PROGRAM_NAMES.QUARRY_REGISTRY, + }, + RVKd61ztZW9GUwhRbbLoYVRE5Xf1B2tVscKqwZqXgEr: { + deployments: [Cluster.MainnetBeta], + name: PROGRAM_NAMES.RAYDIUM_LP_1, + }, + SPoo1Ku8WFXoNDMHPsrGSTSG1Y47rzgn41SLUNakuHy: { + deployments: LIVE_CLUSTERS, + name: PROGRAM_NAMES.STAKE_POOL, + }, + SSwpMgqNDsyV7mAgN9ady4bDVu5ySjmmXejXvy2vLt1: { + deployments: [Cluster.MainnetBeta], + name: PROGRAM_NAMES.STEP_SWAP, + }, + SSwpkEEcbUqx4vtoEByFjSkhKdCT862DNVb52nZg1UZ: { + deployments: [Cluster.Devnet, Cluster.MainnetBeta], + name: PROGRAM_NAMES.SABER_SWAP, + }, + SWiMDJYFUGj6cPrQ6QYYYWZtvXQdRChSVAygDZDsCHC: { + deployments: [Cluster.MainnetBeta], + name: PROGRAM_NAMES.SWIM_SWAP, + }, + So1endDq2YkqhipRh3WViPa8hdiSpxWy6z3Z6tMCpAo: { + deployments: [Cluster.MainnetBeta], + name: PROGRAM_NAMES.SOLEND, + }, + Stake11111111111111111111111111111111111111: { + deployments: ALL_CLUSTERS, + name: PROGRAM_NAMES.STAKE, + }, + SwaPpA9LAaLfeLi3a68M4DjnLqgtticKg6CnyNwgAC8: { + deployments: LIVE_CLUSTERS, + name: PROGRAM_NAMES.SWAP, + }, + TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA: { + deployments: ALL_CLUSTERS, + name: PROGRAM_NAMES.TOKEN, + }, + Vote111111111111111111111111111111111111111: { + deployments: ALL_CLUSTERS, + name: PROGRAM_NAMES.VOTE, + }, + WnFt12ZrnzZrFZkt2xsNsaNWoQribnuQ5B5FrDbwDhD: { + deployments: [Cluster.MainnetBeta], + name: PROGRAM_NAMES.WORMHOLE_NFT, + }, + WormT3McKhFJ2RkiGpdw9GKvNCrB2aB54gb2uV9MfQC: { + deployments: [Cluster.MainnetBeta], + name: PROGRAM_NAMES.WORMHOLE, + }, + WvmTNLpGMVbwJVYztYL4Hnsy82cJhQorxjnnXcRm3b6: { + deployments: [Cluster.MainnetBeta], + name: PROGRAM_NAMES.SERUM_POOL, + }, + auctxRXPeJoc4817jDhf4HbjnhEcr1cCXenosMhK5R8: { + deployments: LIVE_CLUSTERS, + name: PROGRAM_NAMES.NFT_AUCTION, + }, + cjg3oHmg9uuPsP8D6g29NWvhySJkdYdAo9D25PRbKXJ: { + deployments: [Cluster.Devnet, Cluster.MainnetBeta], + name: PROGRAM_NAMES.CHAINLINK_ORACLE, + }, + cmtDvXumGCrqC1Age74AVPhSRVXJMd8PJS91L8KbNCK: { + deployments: [Cluster.Devnet, Cluster.MainnetBeta], + name: PROGRAM_NAMES.ACCOUNT_COMPRESSION, + }, + cndy3Z4yapfJBmL3ShUp5exZKqR3z33thTzeNMm2gRZ: { + deployments: LIVE_CLUSTERS, + name: PROGRAM_NAMES.NFT_CANDY_MACHINE_V2, + }, + cndyAnrLdpjq1Ssp1z8xxDsB8dxe7u4HL5Nxi2K5WXZ: { + deployments: LIVE_CLUSTERS, + name: PROGRAM_NAMES.NFT_CANDY_MACHINE, + }, + gSbePebfvPy7tRqimPoVecS2UsBvYv46ynrzWocc92s: { + deployments: [Cluster.Devnet], + name: PROGRAM_NAMES.PYTH_DEVNET, + }, + metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s: { + deployments: LIVE_CLUSTERS, + name: PROGRAM_NAMES.TOKEN_METADATA, + }, + mv3ekLzLbnVPNxjSKvqBpU3ZeZXPQdEC3bp5MDEBG68: { + deployments: [Cluster.MainnetBeta], + name: PROGRAM_NAMES.MANGO_3, + }, + namesLPneVptA9Z5rqUDD9tMTWEJwofgaYwp8cawRkX: { + deployments: LIVE_CLUSTERS, + name: PROGRAM_NAMES.NAME, + }, + p1exdMJcjVao65QdewkaZRUnU6VPSXhus9n2GzWfh98: { + deployments: LIVE_CLUSTERS, + name: PROGRAM_NAMES.METAPLEX, + }, + srmqPvymJeFKQ4zGQed1GFppgkRHL9kaELCbyksJtPX: { + deployments: [Cluster.MainnetBeta], + name: PROGRAM_NAMES.OPENBOOK_DEX, + }, + vau1zxA2LbssAUEF7Gpw91zMM1LvXrvpzJtmZ58rPsn: { + deployments: LIVE_CLUSTERS, + name: PROGRAM_NAMES.TOKEN_VAULT, + }, + worm2ZoG2kUd4vFXhvjh93UUH596ayRfgQ2MgjNMTth: { + deployments: [Cluster.MainnetBeta], + name: PROGRAM_NAMES.WORMHOLE_CORE, + }, + wormDTUJ6AWPNvk59vGQbDvGJmqbDTdgWgAqcLBCgUb: { + deployments: [Cluster.MainnetBeta], + name: PROGRAM_NAMES.WORMHOLE_TOKEN, + }, +}; + +export const SPECIAL_IDS: { [key: string]: string } = { + '1nc1nerator11111111111111111111111111111111': 'Incinerator', + Sysvar1111111111111111111111111111111111111: 'SYSVAR', +}; + +export const SYSVAR_IDS: { [key: string]: string } = { + Sysvar1nstructions1111111111111111111111111: 'Sysvar: Instructions', + SysvarC1ock11111111111111111111111111111111: 'Sysvar: Clock', + SysvarEpochSchedu1e111111111111111111111111: 'Sysvar: Epoch Schedule', + SysvarFees111111111111111111111111111111111: 'Sysvar: Fees', + SysvarRecentB1ockHashes11111111111111111111: 'Sysvar: Recent Blockhashes', + SysvarRent111111111111111111111111111111111: 'Sysvar: Rent', + SysvarRewards111111111111111111111111111111: 'Sysvar: Rewards', + SysvarS1otHashes111111111111111111111111111: 'Sysvar: Slot Hashes', + SysvarS1otHistory11111111111111111111111111: 'Sysvar: Slot History', + SysvarStakeHistory1111111111111111111111111: 'Sysvar: Stake History', +}; diff --git a/app/utils/tx.ts b/app/utils/tx.ts index f4e19d7d..5c9deeba 100644 --- a/app/utils/tx.ts +++ b/app/utils/tx.ts @@ -1,479 +1,16 @@ -import { OPEN_BOOK_PROGRAM_ID } from '@components/instruction/serum/types'; import { TokenInfoMap } from '@solana/spl-token-registry'; import { - BPF_LOADER_DEPRECATED_PROGRAM_ID, - BPF_LOADER_PROGRAM_ID, - Ed25519Program, ParsedInstruction, ParsedTransaction, PartiallyDecodedInstruction, - Secp256k1Program, - StakeProgram, - SystemProgram, - SYSVAR_CLOCK_PUBKEY, - SYSVAR_RENT_PUBKEY, - SYSVAR_REWARDS_PUBKEY, - SYSVAR_STAKE_HISTORY_PUBKEY, Transaction, TransactionInstruction, - VOTE_PROGRAM_ID, } from '@solana/web3.js'; import { Cluster } from '@utils/cluster'; import { SerumMarketRegistry } from '@utils/serumMarketRegistry'; import bs58 from 'bs58'; -export enum PROGRAM_NAMES { - // native built-ins - ADDRESS_LOOKUP_TABLE = 'Address Lookup Table Program', - COMPUTE_BUDGET = 'Compute Budget Program', - CONFIG = 'Config Program', - STAKE = 'Stake Program', - SYSTEM = 'System Program', - VOTE = 'Vote Program', - - // native precompiles - SECP256K1 = 'Secp256k1 SigVerify Precompile', - ED25519 = 'Ed25519 SigVerify Precompile', - - // spl - ASSOCIATED_TOKEN = 'Associated Token Program', - ACCOUNT_COMPRESSION = 'State Compression Program', - FEATURE_PROPOSAL = 'Feature Proposal Program', - LENDING = 'Lending Program', - MEMO = 'Memo Program', - MEMO_2 = 'Memo Program v2', - NAME = 'Name Service Program', - STAKE_POOL = 'Stake Pool Program', - SWAP = 'Swap Program', - TOKEN = 'Token Program', - TOKEN_METADATA = 'Token Metadata Program', - TOKEN_VAULT = 'Token Vault Program', - - // other - ACUMEN = 'Acumen Program', - BREAK_SOLANA = 'Break Solana Program', - CHAINLINK_ORACLE = 'Chainlink OCR2 Oracle Program', - CHAINLINK_STORE = 'Chainlink Store Program', - CLOCKWORK_1 = 'Clockwork Thread Program v1', - CLOCKWORK_2 = 'Clockwork Thread Program v2', - MANGO_GOVERNANCE = 'Mango Governance Program', - MANGO_ICO = 'Mango ICO Program', - MANGO_1 = 'Mango Program v1', - MANGO_2 = 'Mango Program v2', - MANGO_3 = 'Mango Program v3', - MARINADE = 'Marinade Staking Program', - MERCURIAL = 'Mercurial Stable Swap Program', - METAPLEX = 'Metaplex Program', - NFT_AUCTION = 'NFT Auction Program', - NFT_CANDY_MACHINE = 'NFT Candy Machine Program', - NFT_CANDY_MACHINE_V2 = 'NFT Candy Machine Program V2', - ORCA_SWAP_1 = 'Orca Swap Program v1', - ORCA_SWAP_2 = 'Orca Swap Program v2', - ORCA_AQUAFARM = 'Orca Aquafarm Program', - PORT = 'Port Finance Program', - PYTH_DEVNET = 'Pyth Oracle Program', - PYTH_TESTNET = 'Pyth Oracle Program', - PYTH_MAINNET = 'Pyth Oracle Program', - QUARRY_MERGE_MINE = 'Quarry Merge Mine', - QUARRY_MINE = 'Quarry Mine', - QUARRY_MINT_WRAPPER = 'Quarry Mint Wrapper', - QUARRY_REDEEMER = 'Quarry Redeemer', - QUARRY_REGISTRY = 'Quarry Registry', - RAYDIUM_AMM = 'Raydium AMM Program', - RAYDIUM_IDO = 'Raydium IDO Program', - RAYDIUM_LP_1 = 'Raydium Liquidity Pool Program v1', - RAYDIUM_LP_2 = 'Raydium Liquidity Pool Program v2', - RAYDIUM_STAKING = 'Raydium Staking Program', - SABER_ROUTER = 'Saber Router Program', - SABER_SWAP = 'Saber Stable Swap Program', - SERUM_1 = 'Serum Dex Program v1', - SERUM_2 = 'Serum Dex Program v2', - SERUM_3 = 'Serum Dex Program v3', - SERUM_SWAP = 'Serum Swap Program', - SERUM_POOL = 'Serum Pool', - SOLEND = 'Solend Program', - SOLIDO = 'Lido for Solana Program', - STEP_SWAP = 'Step Finance Swap Program', - SWIM_SWAP = 'Swim Swap Program', - SWITCHBOARD = 'Switchboard Oracle Program', - WORMHOLE = 'Wormhole', - WORMHOLE_CORE = 'Wormhole Core Bridge', - WORMHOLE_TOKEN = 'Wormhole Token Bridge', - WORMHOLE_NFT = 'Wormhole NFT Bridge', - SOLANART = 'Solanart', - SOLANART_GO = 'Solanart - Global offers', - STEPN_DEX = 'STEPN Dex', - OPENBOOK_DEX = 'OpenBook Dex', -} - -const ALL_CLUSTERS = [Cluster.Custom, Cluster.Devnet, Cluster.Testnet, Cluster.MainnetBeta]; - -const LIVE_CLUSTERS = [Cluster.Devnet, Cluster.Testnet, Cluster.MainnetBeta]; - -export type ProgramInfo = { - name: string; - deployments: Cluster[]; -}; - -export const PROGRAM_INFO_BY_ID: { [address: string]: ProgramInfo } = { - '22Y43yTVxuUkoRKdm9thyRhQ3SdgQS7c7kB6UNCiaczD': { - deployments: [Cluster.MainnetBeta], - name: PROGRAM_NAMES.SERUM_SWAP, - }, - - '27haf8L6oxUeXrHrgEgsexjSY5hbVUWEmvv9Nyxg8vQv': { - deployments: [Cluster.MainnetBeta], - name: PROGRAM_NAMES.RAYDIUM_LP_2, - }, - - '2rHhojZ7hpu1zA91nvZmT8TqWWvMcKmmNBCr2mKTtMq4': { - deployments: [Cluster.Devnet], - name: PROGRAM_NAMES.WORMHOLE_NFT, - }, - [StakeProgram.programId.toBase58()]: { - deployments: ALL_CLUSTERS, - name: PROGRAM_NAMES.STAKE, - }, - [SystemProgram.programId.toBase58()]: { - deployments: ALL_CLUSTERS, - name: PROGRAM_NAMES.SYSTEM, - }, - [VOTE_PROGRAM_ID.toBase58()]: { - deployments: ALL_CLUSTERS, - name: PROGRAM_NAMES.VOTE, - }, - - // native precompiles - [Secp256k1Program.programId.toBase58()]: { - deployments: ALL_CLUSTERS, - name: PROGRAM_NAMES.SECP256K1, - }, - [Ed25519Program.programId.toBase58()]: { - deployments: ALL_CLUSTERS, - name: PROGRAM_NAMES.ED25519, - }, - - '3XXuUFfweXBwFgFfYaejLvZE4cGZiHgKiGfMtdxNzYmv': { - deployments: [Cluster.MainnetBeta, Cluster.Devnet], - name: PROGRAM_NAMES.CLOCKWORK_1, - }, - - '3u8hJUVTA4jH1wYAyUur7FFZVQ8H635K3tSHHF4ssjQ5': { - deployments: [Cluster.Devnet], - name: PROGRAM_NAMES.WORMHOLE_CORE, - }, - - '5ZfZAwP2m93waazg8DkrrVmsupeiPEvaEHowiUP7UAbJ': { - deployments: [Cluster.MainnetBeta], - name: PROGRAM_NAMES.SOLANART_GO, - }, - - '5fNfvyp5czQVX77yoACa3JJVEhdRaWjPuazuWgjhTqEH': { - deployments: [Cluster.MainnetBeta], - name: PROGRAM_NAMES.MANGO_2, - }, - - '675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8': { - deployments: [Cluster.MainnetBeta], - name: PROGRAM_NAMES.RAYDIUM_AMM, - }, - - '7sPptkymzvayoSbLXzBsXEF8TSf3typNnAWkrKrDizNb': { - deployments: [Cluster.MainnetBeta], - name: PROGRAM_NAMES.MANGO_ICO, - }, - - '82yxjeMsvaURa4MbZZ7WZZHfobirZYkH1zF8fmeGtyaQ': { - deployments: [Cluster.MainnetBeta], - name: PROGRAM_NAMES.ORCA_AQUAFARM, - }, - - '8tfDNiaEyrV6Q1U4DEXrEigs9DoDtkugzFbybENEbCDz': { - deployments: [Cluster.Testnet], - name: PROGRAM_NAMES.PYTH_TESTNET, - }, - - '9HzJyW1qZsEiSfMUf6L2jo3CcTKAyBmSyKdwQeYisHrC': { - deployments: [Cluster.MainnetBeta], - name: PROGRAM_NAMES.RAYDIUM_IDO, - }, - - '9W959DqEETiGZocYWCQPaJ6sBmUzgfxXfqGeTEdp3aQP': { - deployments: [Cluster.MainnetBeta], - name: PROGRAM_NAMES.ORCA_SWAP_2, - }, - - '9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin': { - deployments: [Cluster.MainnetBeta], - name: PROGRAM_NAMES.SERUM_3, - }, - - // spl - ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL: { - deployments: ALL_CLUSTERS, - name: PROGRAM_NAMES.ASSOCIATED_TOKEN, - }, - - // native built-ins - AddressLookupTab1e1111111111111111111111111: { - deployments: ALL_CLUSTERS, - name: PROGRAM_NAMES.ADDRESS_LOOKUP_TABLE, - }, - - BJ3jrUzddfuSrZHXSCxMUUQsjKEyLmuuyZebkcaFp2fg: { - deployments: [Cluster.MainnetBeta], - name: PROGRAM_NAMES.SERUM_1, - }, - - BrEAK7zGZ6dM71zUDACDqJnekihmwF15noTddWTsknjC: { - deployments: LIVE_CLUSTERS, - name: PROGRAM_NAMES.BREAK_SOLANA, - }, - // other - C64kTdg1Hzv5KoQmZrQRcm2Qz7PkxtFBgw7EpFhvYn8W: { - deployments: [Cluster.MainnetBeta], - name: PROGRAM_NAMES.ACUMEN, - }, - CJsLwbP1iu5DuUikHEJnLfANgKy6stB2uFgvBBHoyxwz: { - deployments: [Cluster.MainnetBeta], - name: PROGRAM_NAMES.SOLANART, - }, - CLoCKyJ6DXBJqqu2VWx9RLbgnwwR6BMHHuyasVmfMzBh: { - deployments: [Cluster.MainnetBeta, Cluster.Devnet], - name: PROGRAM_NAMES.CLOCKWORK_2, - }, - ComputeBudget111111111111111111111111111111: { - deployments: ALL_CLUSTERS, - name: PROGRAM_NAMES.COMPUTE_BUDGET, - }, - Config1111111111111111111111111111111111111: { - deployments: ALL_CLUSTERS, - name: PROGRAM_NAMES.CONFIG, - }, - CrX7kMhLC3cSsXJdT7JDgqrRVWGnUpX3gfEfxxU2NVLi: { - deployments: [Cluster.MainnetBeta], - name: PROGRAM_NAMES.SOLIDO, - }, - Crt7UoUR6QgrFrN7j8rmSQpUTNWNSitSwWvsWGf1qZ5t: { - deployments: [Cluster.Devnet, Cluster.MainnetBeta], - name: PROGRAM_NAMES.SABER_ROUTER, - }, - DZnkkTmCiFWfYTfT41X3Rd1kDgozqzxWaHqsw6W4x2oe: { - deployments: [Cluster.Devnet], - name: PROGRAM_NAMES.WORMHOLE_TOKEN, - }, - DjVE6JNiYqPL2QXyCUUh8rNjHrbz9hXHNYt99MQ59qw1: { - deployments: [Cluster.MainnetBeta], - name: PROGRAM_NAMES.ORCA_SWAP_1, - }, - Dooar9JkhdZ7J3LHN3A7YCuoGRUggXhQaG4kijfLGU2j: { - deployments: [Cluster.MainnetBeta], - name: PROGRAM_NAMES.STEPN_DEX, - }, - DtmE9D2CSB4L5D6A15mraeEjrGMm6auWVzgaD8hK2tZM: { - deployments: [Cluster.MainnetBeta], - name: PROGRAM_NAMES.SWITCHBOARD, - }, - EUqojwWA2rd19FZrzeBncJsm38Jm1hEhE3zsmX3bRc2o: { - deployments: [Cluster.MainnetBeta], - name: PROGRAM_NAMES.SERUM_2, - }, - EhhTKczWMGQt46ynNeRX1WfeagwwJd7ufHvCDjRxjo5Q: { - deployments: [Cluster.MainnetBeta], - name: PROGRAM_NAMES.RAYDIUM_STAKING, - }, - Feat1YXHhH6t1juaWF74WLcfv4XoNocjXA6sPWHNgAse: { - deployments: ALL_CLUSTERS, - name: PROGRAM_NAMES.FEATURE_PROPOSAL, - }, - FsJ3A3u2vn5cTVofAjvy6y5kwABJAqYWpe4975bi2epH: { - deployments: [Cluster.MainnetBeta], - name: PROGRAM_NAMES.PYTH_MAINNET, - }, - GqTPL6qRf5aUuqscLh8Rg2HTxPUXfhhAXDptTLhp1t2J: { - deployments: [Cluster.MainnetBeta], - name: PROGRAM_NAMES.MANGO_GOVERNANCE, - }, - HEvSKofvBgfaexv23kMabbYqxasxU3mQ4ibBMEmJWHny: { - deployments: [Cluster.Devnet, Cluster.MainnetBeta], - name: PROGRAM_NAMES.CHAINLINK_STORE, - }, - JD3bq9hGdy38PuWQ4h2YJpELmHVGPPfFSuFkpzAd9zfu: { - deployments: [Cluster.MainnetBeta], - name: PROGRAM_NAMES.MANGO_1, - }, - LendZqTs7gn5CTSJU1jWKhKuVpjJGom45nnwPb2AMTi: { - deployments: LIVE_CLUSTERS, - name: PROGRAM_NAMES.LENDING, - }, - MERLuDFBMmsHnsBPZw2sDQZHvXFMwp8EdjudcU2HKky: { - deployments: [Cluster.Devnet, Cluster.MainnetBeta], - name: PROGRAM_NAMES.MERCURIAL, - }, - MarBmsSgKXdrN1egZf5sqe1TMai9K1rChYNDJgjq7aD: { - deployments: [Cluster.MainnetBeta], - name: PROGRAM_NAMES.MARINADE, - }, - Memo1UhkJRfHyvLMcVucJwxXeuD728EqVDDwQDxFMNo: { - deployments: ALL_CLUSTERS, - name: PROGRAM_NAMES.MEMO, - }, - MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr: { - deployments: ALL_CLUSTERS, - name: PROGRAM_NAMES.MEMO_2, - }, - [OPEN_BOOK_PROGRAM_ID]: { - deployments: [Cluster.MainnetBeta], - name: PROGRAM_NAMES.OPENBOOK_DEX, - }, - Port7uDYB3wk6GJAw4KT1WpTeMtSu9bTcChBHkX2LfR: { - deployments: [Cluster.MainnetBeta], - name: PROGRAM_NAMES.PORT, - }, - QMMD16kjauP5knBwxNUJRZ1Z5o3deBuFrqVjBVmmqto: { - deployments: LIVE_CLUSTERS, - name: PROGRAM_NAMES.QUARRY_MERGE_MINE, - }, - QMNeHCGYnLVDn1icRAfQZpjPLBNkfGbSKRB83G5d8KB: { - deployments: LIVE_CLUSTERS, - name: PROGRAM_NAMES.QUARRY_MINE, - }, - QMWoBmAyJLAsA1Lh9ugMTw2gciTihncciphzdNzdZYV: { - deployments: LIVE_CLUSTERS, - name: PROGRAM_NAMES.QUARRY_MINT_WRAPPER, - }, - QRDxhMw1P2NEfiw5mYXG79bwfgHTdasY2xNP76XSea9: { - deployments: LIVE_CLUSTERS, - name: PROGRAM_NAMES.QUARRY_REDEEMER, - }, - QREGBnEj9Sa5uR91AV8u3FxThgP5ZCvdZUW2bHAkfNc: { - deployments: LIVE_CLUSTERS, - name: PROGRAM_NAMES.QUARRY_REGISTRY, - }, - RVKd61ztZW9GUwhRbbLoYVRE5Xf1B2tVscKqwZqXgEr: { - deployments: [Cluster.MainnetBeta], - name: PROGRAM_NAMES.RAYDIUM_LP_1, - }, - SPoo1Ku8WFXoNDMHPsrGSTSG1Y47rzgn41SLUNakuHy: { - deployments: LIVE_CLUSTERS, - name: PROGRAM_NAMES.STAKE_POOL, - }, - SSwpMgqNDsyV7mAgN9ady4bDVu5ySjmmXejXvy2vLt1: { - deployments: [Cluster.MainnetBeta], - name: PROGRAM_NAMES.STEP_SWAP, - }, - SSwpkEEcbUqx4vtoEByFjSkhKdCT862DNVb52nZg1UZ: { - deployments: [Cluster.Devnet, Cluster.MainnetBeta], - name: PROGRAM_NAMES.SABER_SWAP, - }, - SWiMDJYFUGj6cPrQ6QYYYWZtvXQdRChSVAygDZDsCHC: { - deployments: [Cluster.MainnetBeta], - name: PROGRAM_NAMES.SWIM_SWAP, - }, - So1endDq2YkqhipRh3WViPa8hdiSpxWy6z3Z6tMCpAo: { - deployments: [Cluster.MainnetBeta], - name: PROGRAM_NAMES.SOLEND, - }, - SwaPpA9LAaLfeLi3a68M4DjnLqgtticKg6CnyNwgAC8: { - deployments: LIVE_CLUSTERS, - name: PROGRAM_NAMES.SWAP, - }, - TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA: { - deployments: ALL_CLUSTERS, - name: PROGRAM_NAMES.TOKEN, - }, - WnFt12ZrnzZrFZkt2xsNsaNWoQribnuQ5B5FrDbwDhD: { - deployments: [Cluster.MainnetBeta], - name: PROGRAM_NAMES.WORMHOLE_NFT, - }, - WormT3McKhFJ2RkiGpdw9GKvNCrB2aB54gb2uV9MfQC: { - deployments: [Cluster.MainnetBeta], - name: PROGRAM_NAMES.WORMHOLE, - }, - WvmTNLpGMVbwJVYztYL4Hnsy82cJhQorxjnnXcRm3b6: { - deployments: [Cluster.MainnetBeta], - name: PROGRAM_NAMES.SERUM_POOL, - }, - auctxRXPeJoc4817jDhf4HbjnhEcr1cCXenosMhK5R8: { - deployments: LIVE_CLUSTERS, - name: PROGRAM_NAMES.NFT_AUCTION, - }, - cjg3oHmg9uuPsP8D6g29NWvhySJkdYdAo9D25PRbKXJ: { - deployments: [Cluster.Devnet, Cluster.MainnetBeta], - name: PROGRAM_NAMES.CHAINLINK_ORACLE, - }, - cmtDvXumGCrqC1Age74AVPhSRVXJMd8PJS91L8KbNCK: { - deployments: [Cluster.Devnet, Cluster.MainnetBeta], - name: PROGRAM_NAMES.ACCOUNT_COMPRESSION, - }, - cndy3Z4yapfJBmL3ShUp5exZKqR3z33thTzeNMm2gRZ: { - deployments: LIVE_CLUSTERS, - name: PROGRAM_NAMES.NFT_CANDY_MACHINE_V2, - }, - cndyAnrLdpjq1Ssp1z8xxDsB8dxe7u4HL5Nxi2K5WXZ: { - deployments: LIVE_CLUSTERS, - name: PROGRAM_NAMES.NFT_CANDY_MACHINE, - }, - gSbePebfvPy7tRqimPoVecS2UsBvYv46ynrzWocc92s: { - deployments: [Cluster.Devnet], - name: PROGRAM_NAMES.PYTH_DEVNET, - }, - metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s: { - deployments: LIVE_CLUSTERS, - name: PROGRAM_NAMES.TOKEN_METADATA, - }, - mv3ekLzLbnVPNxjSKvqBpU3ZeZXPQdEC3bp5MDEBG68: { - deployments: [Cluster.MainnetBeta], - name: PROGRAM_NAMES.MANGO_3, - }, - namesLPneVptA9Z5rqUDD9tMTWEJwofgaYwp8cawRkX: { - deployments: LIVE_CLUSTERS, - name: PROGRAM_NAMES.NAME, - }, - p1exdMJcjVao65QdewkaZRUnU6VPSXhus9n2GzWfh98: { - deployments: LIVE_CLUSTERS, - name: PROGRAM_NAMES.METAPLEX, - }, - vau1zxA2LbssAUEF7Gpw91zMM1LvXrvpzJtmZ58rPsn: { - deployments: LIVE_CLUSTERS, - name: PROGRAM_NAMES.TOKEN_VAULT, - }, - worm2ZoG2kUd4vFXhvjh93UUH596ayRfgQ2MgjNMTth: { - deployments: [Cluster.MainnetBeta], - name: PROGRAM_NAMES.WORMHOLE_CORE, - }, - wormDTUJ6AWPNvk59vGQbDvGJmqbDTdgWgAqcLBCgUb: { - deployments: [Cluster.MainnetBeta], - name: PROGRAM_NAMES.WORMHOLE_TOKEN, - }, -}; - -export type LoaderName = (typeof LOADER_IDS)[keyof typeof LOADER_IDS]; -export const LOADER_IDS = { - BPFLoaderUpgradeab1e11111111111111111111111: 'BPF Upgradeable Loader', - MoveLdr111111111111111111111111111111111111: 'Move Loader', - [BPF_LOADER_DEPRECATED_PROGRAM_ID.toBase58()]: 'BPF Loader', - [BPF_LOADER_PROGRAM_ID.toBase58()]: 'BPF Loader 2', - NativeLoader1111111111111111111111111111111: 'Native Loader', -} as const; - -export const SPECIAL_IDS: { [key: string]: string } = { - '1nc1nerator11111111111111111111111111111111': 'Incinerator', - Sysvar1111111111111111111111111111111111111: 'SYSVAR', -}; - -export const SYSVAR_IDS = { - [SYSVAR_CLOCK_PUBKEY.toBase58()]: 'Sysvar: Clock', - Sysvar1nstructions1111111111111111111111111: 'Sysvar: Instructions', - SysvarEpochSchedu1e111111111111111111111111: 'Sysvar: Epoch Schedule', - SysvarFees111111111111111111111111111111111: 'Sysvar: Fees', - [SYSVAR_RENT_PUBKEY.toBase58()]: 'Sysvar: Rent', - [SYSVAR_REWARDS_PUBKEY.toBase58()]: 'Sysvar: Rewards', - SysvarRecentB1ockHashes11111111111111111111: 'Sysvar: Recent Blockhashes', - SysvarS1otHashes111111111111111111111111111: 'Sysvar: Slot Hashes', - [SYSVAR_STAKE_HISTORY_PUBKEY.toBase58()]: 'Sysvar: Stake History', - SysvarS1otHistory11111111111111111111111111: 'Sysvar: Slot History', -}; +import { LOADER_IDS, PROGRAM_INFO_BY_ID, SPECIAL_IDS, SYSVAR_IDS } from './programs'; export function getProgramName(address: string, cluster: Cluster): string { const label = programLabel(address, cluster); @@ -487,7 +24,7 @@ export function programLabel(address: string, cluster: Cluster): string | undefi return programInfo.name; } - return LOADER_IDS[address]; + return LOADER_IDS[address] as string; } export function tokenLabel(address: string, tokenRegistry?: TokenInfoMap): string | undefined {