refactor: use @luxfi/chains, @luxfi/contracts, @luxfi/hooks shared packages

- Replace inline chain/contract/hook implementations with @luxfi/* imports
- All 6 lib/hook files now thin re-exports from shared packages
- Standalone market at github.com/luxfi/market (removed from exchange monorepo)
This commit is contained in:
2026-03-24 18:06:03 -07:00
parent 57b2a13d3d
commit a526be76e4
7 changed files with 53 additions and 773 deletions
+3
View File
@@ -12,6 +12,9 @@
"lint": "next lint"
},
"dependencies": {
"@luxfi/chains": "^1.0.0",
"@luxfi/contracts": "^1.0.0",
"@luxfi/hooks": "^1.0.0",
"@radix-ui/react-dialog": "^1.1.0",
"@radix-ui/react-dropdown-menu": "^2.1.0",
"@radix-ui/react-slot": "^1.1.0",
+1 -17
View File
@@ -1,17 +1 @@
'use client'
import { createContext, useContext } from 'react'
export interface ChainContextValue {
chainId: number
setChainId: (id: number) => void
}
export const ChainContext = createContext<ChainContextValue>({
chainId: 96369,
setChainId: () => {},
})
export function useChainContext() {
return useContext(ChainContext)
}
export { useChainContext, ChainContext, type ChainContextValue } from '@luxfi/hooks'
+10 -108
View File
@@ -1,108 +1,10 @@
'use client'
import { useQuery } from '@tanstack/react-query'
import {
getCollections,
getToken,
getTokenInstances,
getTokenInstance,
getTokenInstanceTransfers,
getTokenTransfers,
getAddressTokens,
searchTokens,
} from '@/lib/explorer'
// ---- Query key factory ----
const nftKeys = {
all: ['nft'] as const,
collections: (chainId: number) => [...nftKeys.all, 'collections', chainId] as const,
collection: (chainId: number, address: string) => [...nftKeys.all, 'collection', chainId, address] as const,
instances: (chainId: number, address: string) => [...nftKeys.all, 'instances', chainId, address] as const,
instance: (chainId: number, address: string, tokenId: string) =>
[...nftKeys.all, 'instance', chainId, address, tokenId] as const,
transfers: (chainId: number, address: string, tokenId: string) =>
[...nftKeys.all, 'transfers', chainId, address, tokenId] as const,
collectionTransfers: (chainId: number, address: string) =>
[...nftKeys.all, 'collection-transfers', chainId, address] as const,
portfolio: (chainId: number, wallet: string) => [...nftKeys.all, 'portfolio', chainId, wallet] as const,
search: (chainId: number, query: string) => [...nftKeys.all, 'search', chainId, query] as const,
}
/** Fetch NFT collections on a chain */
export function useCollections(chainId: number, search?: string) {
return useQuery({
queryKey: search ? nftKeys.search(chainId, search) : nftKeys.collections(chainId),
queryFn: () => getCollections(chainId, { q: search }),
staleTime: 60_000,
})
}
/** Fetch a single collection/token by address */
export function useCollection(chainId: number, address: string) {
return useQuery({
queryKey: nftKeys.collection(chainId, address),
queryFn: () => getToken(chainId, address),
enabled: !!address,
staleTime: 60_000,
})
}
/** Fetch NFT instances (items) in a collection */
export function useTokenInstances(chainId: number, address: string) {
return useQuery({
queryKey: nftKeys.instances(chainId, address),
queryFn: () => getTokenInstances(chainId, address),
enabled: !!address,
staleTime: 30_000,
})
}
/** Fetch a single NFT instance with full metadata */
export function useTokenInstance(chainId: number, address: string, tokenId: string) {
return useQuery({
queryKey: nftKeys.instance(chainId, address, tokenId),
queryFn: () => getTokenInstance(chainId, address, tokenId),
enabled: !!address && !!tokenId,
staleTime: 30_000,
})
}
/** Fetch transfer history for a specific NFT */
export function useTokenInstanceTransfers(chainId: number, address: string, tokenId: string) {
return useQuery({
queryKey: nftKeys.transfers(chainId, address, tokenId),
queryFn: () => getTokenInstanceTransfers(chainId, address, tokenId),
enabled: !!address && !!tokenId,
staleTime: 30_000,
})
}
/** Fetch all transfers for a collection */
export function useCollectionTransfers(chainId: number, address: string) {
return useQuery({
queryKey: nftKeys.collectionTransfers(chainId, address),
queryFn: () => getTokenTransfers(chainId, address),
enabled: !!address,
staleTime: 30_000,
})
}
/** Fetch NFTs owned by a wallet on a chain */
export function usePortfolioNFTs(chainId: number, walletAddress: string | undefined) {
return useQuery({
queryKey: nftKeys.portfolio(chainId, walletAddress ?? ''),
queryFn: () => getAddressTokens(chainId, walletAddress!),
enabled: !!walletAddress,
staleTime: 30_000,
})
}
/** Search for NFT collections */
export function useSearchCollections(chainId: number, query: string) {
return useQuery({
queryKey: nftKeys.search(chainId, query),
queryFn: () => searchTokens(chainId, query),
enabled: query.length >= 2,
staleTime: 15_000,
})
}
export {
useCollections,
useCollection,
useTokenInstances,
useTokenInstance,
useTokenInstanceTransfers,
useCollectionTransfers,
usePortfolioNFTs,
useSearchCollections,
} from '@luxfi/hooks'
+10 -81
View File
@@ -1,81 +1,10 @@
import { defineChain } from 'viem'
export const luxMainnet = defineChain({
id: 96369,
name: 'Lux',
nativeCurrency: { name: 'LUX', symbol: 'LUX', decimals: 18 },
rpcUrls: {
default: { http: ['https://api.lux.network/mainnet/ext/bc/C/rpc'] },
},
blockExplorers: {
default: { name: 'Lux Explorer', url: 'https://explore.lux.network' },
},
})
export const zooMainnet = defineChain({
id: 200200,
name: 'Zoo',
nativeCurrency: { name: 'ZOO', symbol: 'ZOO', decimals: 18 },
rpcUrls: {
default: { http: ['https://api.lux.network/mainnet/ext/bc/zoo/rpc'] },
},
blockExplorers: {
default: { name: 'Zoo Explorer', url: 'https://explore-zoo.lux.network' },
},
})
export const hanzoMainnet = defineChain({
id: 36963,
name: 'Hanzo',
nativeCurrency: { name: 'HANZO', symbol: 'HNZ', decimals: 18 },
rpcUrls: {
default: { http: ['https://api.lux.network/mainnet/ext/bc/hanzo/rpc'] },
},
blockExplorers: {
default: { name: 'Hanzo Explorer', url: 'https://explore-hanzo.lux.network' },
},
})
export const spcMainnet = defineChain({
id: 36911,
name: 'SPC',
nativeCurrency: { name: 'SPC', symbol: 'SPC', decimals: 18 },
rpcUrls: {
default: { http: ['https://api.lux.network/mainnet/ext/bc/spc/rpc'] },
},
blockExplorers: {
default: { name: 'SPC Explorer', url: 'https://explore-spc.lux.network' },
},
})
export const parsMainnet = defineChain({
id: 494949,
name: 'Pars',
nativeCurrency: { name: 'PARS', symbol: 'PARS', decimals: 18 },
rpcUrls: {
default: { http: ['https://api.lux.network/mainnet/ext/bc/pars/rpc'] },
},
blockExplorers: {
default: { name: 'Pars Explorer', url: 'https://explore-pars.lux.network' },
},
})
export const supportedChains = [luxMainnet, zooMainnet, hanzoMainnet, spcMainnet, parsMainnet] as const
/** Map chain ID to Explorer API base URL */
export const EXPLORER_API: Record<number, string> = {
96369: 'https://explore.lux.network/api/v2',
200200: 'https://explore-zoo.lux.network/api/v2',
36963: 'https://explore-hanzo.lux.network/api/v2',
36911: 'https://explore-spc.lux.network/api/v2',
494949: 'https://explore-pars.lux.network/api/v2',
}
/** Chain display info for UI */
export const CHAIN_INFO: Record<number, { name: string; symbol: string; color: string }> = {
96369: { name: 'Lux', symbol: 'LUX', color: '#E8E8E8' },
200200: { name: 'Zoo', symbol: 'ZOO', color: '#7C5CFC' },
36963: { name: 'Hanzo', symbol: 'HNZ', color: '#FF6B35' },
36911: { name: 'SPC', symbol: 'SPC', color: '#00C2FF' },
494949: { name: 'Pars', symbol: 'PARS', color: '#FFD700' },
}
export {
lux as luxMainnet,
zoo as zooMainnet,
hanzo as hanzoMainnet,
spc as spcMainnet,
pars as parsMainnet,
chains as supportedChains,
EXPLORER_API,
CHAIN_INFO,
} from '@luxfi/chains'
+7 -356
View File
@@ -1,356 +1,7 @@
import type { Address } from 'viem'
// Contract addresses per chain
export const CONTRACTS: Record<
number,
{
markets: Address
lssvmPairFactory: Address
linearCurve: Address
exponentialCurve: Address
}
> = {
// Lux Mainnet (C-Chain)
96369: {
markets: '0x308EBD39eB5E27980944630A0af6F8B0d19e31C6',
lssvmPairFactory: '0x29E3E018C3C19F7713B2dffa3A3c340fD2c7089E',
linearCurve: '0x360149cC47A3996522376E4131b4A6eB2A1Ca3D3',
exponentialCurve: '0x28EBC6764A1c7Ed47b38772E197761102b08f3bb',
},
// Zoo Mainnet
200200: {
markets: '0x49B76d9ca9BcA9e9eDef5e2EC4eD425b2e6b2445',
lssvmPairFactory: '0x28EBC6764A1c7Ed47b38772E197761102b08f3bb',
linearCurve: '0x2BaeF607871FB40515Fb42A299a1E0b03F0C681f',
exponentialCurve: '0x360149cC47A3996522376E4131b4A6eB2A1Ca3D3',
},
// Hanzo Mainnet
36963: {
markets: '0x6B7D3c38A3e030B95E101927Ee6ff9913ef626d4',
lssvmPairFactory: '0x60b2d8E6B5B0FEeE529DcC6c460C44eed7b2E82A',
linearCurve: '0x719685C371ce4C4720d3D7877CBf9bc867Ac39a6',
exponentialCurve: '0xB4e242f9417872A843B2D0b92FCf89055349ABb5',
},
// SPC Mainnet
36911: {
markets: '0x9BC44B0De1aBe2e436C8fA5Cd5cA519026b9D8fD',
lssvmPairFactory: '0x38E71f39f3f46907E03C48983F6578F9a8c2e72e',
linearCurve: '0x9607F59f2377Dff9A56D0A76F0313040070c08CD',
exponentialCurve: '0xdE5280a9306da7829A4Ba1fBf87B58e1bB4F4A53',
},
// Pars Mainnet
494949: {
markets: '0x3589fd09e7dfF3f7653fc4965B7CE1b8d8fdA9Bd',
lssvmPairFactory: '0xb43dB9AF0C5CACb99f783E30398Ee0AEe6744212',
linearCurve: '0xd13AB81F02449B1630ecd940Be5Fb9CD367225B4',
exponentialCurve: '0xBc92f4e290F8Ad03F5348F81a27fb2Af3B37ec47',
},
}
// Market.sol ABI (Seaport-based)
export const MARKET_ABI = [
{
name: 'list',
type: 'function',
stateMutability: 'nonpayable',
inputs: [
{ name: 'nftContract', type: 'address' },
{ name: 'tokenId', type: 'uint256' },
{ name: 'paymentToken', type: 'address' },
{ name: 'price', type: 'uint256' },
{ name: 'duration', type: 'uint256' },
],
outputs: [{ name: 'listingId', type: 'bytes32' }],
},
{
name: 'cancelListing',
type: 'function',
stateMutability: 'nonpayable',
inputs: [{ name: 'listingId', type: 'bytes32' }],
outputs: [],
},
{
name: 'buy',
type: 'function',
stateMutability: 'payable',
inputs: [{ name: 'listingId', type: 'bytes32' }],
outputs: [],
},
{
name: 'makeOffer',
type: 'function',
stateMutability: 'payable',
inputs: [
{ name: 'nftContract', type: 'address' },
{ name: 'tokenId', type: 'uint256' },
{ name: 'paymentToken', type: 'address' },
{ name: 'amount', type: 'uint256' },
{ name: 'duration', type: 'uint256' },
],
outputs: [{ name: 'offerId', type: 'bytes32' }],
},
{
name: 'cancelOffer',
type: 'function',
stateMutability: 'nonpayable',
inputs: [{ name: 'offerId', type: 'bytes32' }],
outputs: [],
},
{
name: 'acceptOffer',
type: 'function',
stateMutability: 'nonpayable',
inputs: [{ name: 'offerId', type: 'bytes32' }],
outputs: [],
},
{
name: 'getListing',
type: 'function',
stateMutability: 'view',
inputs: [{ name: 'listingId', type: 'bytes32' }],
outputs: [
{ name: 'seller', type: 'address' },
{ name: 'nftContract', type: 'address' },
{ name: 'tokenId', type: 'uint256' },
{ name: 'paymentToken', type: 'address' },
{ name: 'price', type: 'uint256' },
{ name: 'expiry', type: 'uint256' },
{ name: 'active', type: 'bool' },
],
},
{
name: 'Listing',
type: 'event',
inputs: [
{ name: 'listingId', type: 'bytes32', indexed: true },
{ name: 'seller', type: 'address', indexed: true },
{ name: 'nftContract', type: 'address', indexed: false },
{ name: 'tokenId', type: 'uint256', indexed: false },
{ name: 'price', type: 'uint256', indexed: false },
],
},
{
name: 'Sale',
type: 'event',
inputs: [
{ name: 'listingId', type: 'bytes32', indexed: true },
{ name: 'buyer', type: 'address', indexed: true },
{ name: 'price', type: 'uint256', indexed: false },
],
},
{
name: 'OfferMade',
type: 'event',
inputs: [
{ name: 'offerId', type: 'bytes32', indexed: true },
{ name: 'buyer', type: 'address', indexed: true },
{ name: 'nftContract', type: 'address', indexed: false },
{ name: 'tokenId', type: 'uint256', indexed: false },
{ name: 'amount', type: 'uint256', indexed: false },
],
},
] as const
// ERC721 ABI (minimal for NFT queries)
export const ERC721_ABI = [
{
name: 'name',
type: 'function',
stateMutability: 'view',
inputs: [],
outputs: [{ type: 'string' }],
},
{
name: 'symbol',
type: 'function',
stateMutability: 'view',
inputs: [],
outputs: [{ type: 'string' }],
},
{
name: 'tokenURI',
type: 'function',
stateMutability: 'view',
inputs: [{ name: 'tokenId', type: 'uint256' }],
outputs: [{ type: 'string' }],
},
{
name: 'ownerOf',
type: 'function',
stateMutability: 'view',
inputs: [{ name: 'tokenId', type: 'uint256' }],
outputs: [{ type: 'address' }],
},
{
name: 'balanceOf',
type: 'function',
stateMutability: 'view',
inputs: [{ name: 'owner', type: 'address' }],
outputs: [{ type: 'uint256' }],
},
{
name: 'approve',
type: 'function',
stateMutability: 'nonpayable',
inputs: [
{ name: 'to', type: 'address' },
{ name: 'tokenId', type: 'uint256' },
],
outputs: [],
},
{
name: 'setApprovalForAll',
type: 'function',
stateMutability: 'nonpayable',
inputs: [
{ name: 'operator', type: 'address' },
{ name: 'approved', type: 'bool' },
],
outputs: [],
},
{
name: 'isApprovedForAll',
type: 'function',
stateMutability: 'view',
inputs: [
{ name: 'owner', type: 'address' },
{ name: 'operator', type: 'address' },
],
outputs: [{ type: 'bool' }],
},
{
name: 'totalSupply',
type: 'function',
stateMutability: 'view',
inputs: [],
outputs: [{ type: 'uint256' }],
},
{
name: 'Transfer',
type: 'event',
inputs: [
{ name: 'from', type: 'address', indexed: true },
{ name: 'to', type: 'address', indexed: true },
{ name: 'tokenId', type: 'uint256', indexed: true },
],
},
] as const
// ERC1155 minimal ABI
export const ERC1155_ABI = [
{
name: 'balanceOf',
type: 'function',
stateMutability: 'view',
inputs: [
{ name: 'account', type: 'address' },
{ name: 'id', type: 'uint256' },
],
outputs: [{ type: 'uint256' }],
},
{
name: 'uri',
type: 'function',
stateMutability: 'view',
inputs: [{ name: 'id', type: 'uint256' }],
outputs: [{ type: 'string' }],
},
{
name: 'setApprovalForAll',
type: 'function',
stateMutability: 'nonpayable',
inputs: [
{ name: 'operator', type: 'address' },
{ name: 'approved', type: 'bool' },
],
outputs: [],
},
{
name: 'isApprovedForAll',
type: 'function',
stateMutability: 'view',
inputs: [
{ name: 'owner', type: 'address' },
{ name: 'operator', type: 'address' },
],
outputs: [{ type: 'bool' }],
},
] as const
// LSSVM Pair ABI (sudoswap AMM for NFTs)
export const LSSVM_PAIR_ABI = [
{
name: 'swapTokenForSpecificNFTs',
type: 'function',
stateMutability: 'payable',
inputs: [
{ name: 'nftIds', type: 'uint256[]' },
{ name: 'maxExpectedTokenInput', type: 'uint256' },
{ name: 'nftRecipient', type: 'address' },
{ name: 'isRouter', type: 'bool' },
{ name: 'routerCaller', type: 'address' },
],
outputs: [{ name: 'inputAmount', type: 'uint256' }],
},
{
name: 'swapNFTsForToken',
type: 'function',
stateMutability: 'nonpayable',
inputs: [
{ name: 'nftIds', type: 'uint256[]' },
{ name: 'minExpectedTokenOutput', type: 'uint256' },
{ name: 'tokenRecipient', type: 'address' },
{ name: 'isRouter', type: 'bool' },
{ name: 'routerCaller', type: 'address' },
],
outputs: [{ name: 'outputAmount', type: 'uint256' }],
},
{
name: 'getBuyNFTQuote',
type: 'function',
stateMutability: 'view',
inputs: [
{ name: 'assetId', type: 'uint256' },
{ name: 'numNFTs', type: 'uint256' },
],
outputs: [
{ name: 'error', type: 'uint8' },
{ name: 'newSpotPrice', type: 'uint256' },
{ name: 'newDelta', type: 'uint256' },
{ name: 'inputAmount', type: 'uint256' },
{ name: 'protocolFee', type: 'uint256' },
{ name: 'royaltyAmount', type: 'uint256' },
],
},
{
name: 'getSellNFTQuote',
type: 'function',
stateMutability: 'view',
inputs: [
{ name: 'assetId', type: 'uint256' },
{ name: 'numNFTs', type: 'uint256' },
],
outputs: [
{ name: 'error', type: 'uint8' },
{ name: 'newSpotPrice', type: 'uint256' },
{ name: 'newDelta', type: 'uint256' },
{ name: 'outputAmount', type: 'uint256' },
{ name: 'protocolFee', type: 'uint256' },
{ name: 'royaltyAmount', type: 'uint256' },
],
},
{
name: 'spotPrice',
type: 'function',
stateMutability: 'view',
inputs: [],
outputs: [{ type: 'uint128' }],
},
{
name: 'nft',
type: 'function',
stateMutability: 'view',
inputs: [],
outputs: [{ type: 'address' }],
},
] as const
export {
CONTRACTS,
MARKET_ABI,
ERC721_ABI,
ERC1155_ABI,
LSSVM_PAIR_ABI,
} from '@luxfi/contracts'
+21 -201
View File
@@ -1,201 +1,21 @@
/**
* Explorer API client for NFT data.
* Uses the /api/v2/ endpoints from our deployed Lux Explorer instances.
*/
import { EXPLORER_API } from './chains'
// ---- Types matching Explorer v2 API response shapes ----
export interface ExplorerToken {
address: string
name: string
symbol: string
total_supply: string
type: 'ERC-20' | 'ERC-721' | 'ERC-1155' | 'ERC-404'
holders: string
icon_url: string | null
exchange_rate: string | null
}
export interface ExplorerTokenInstance {
id: string
token: ExplorerToken
animation_url: string | null
external_app_url: string | null
image_url: string | null
is_unique: boolean
metadata: NFTMetadata | null
owner: { hash: string } | null
}
export interface NFTMetadata {
name?: string
description?: string
image?: string
image_data?: string
external_url?: string
animation_url?: string
background_color?: string
attributes?: NFTTrait[]
properties?: Record<string, unknown>
}
export interface NFTTrait {
trait_type: string
value: string | number
display_type?: string
max_value?: number
}
export interface ExplorerTransfer {
from: { hash: string }
to: { hash: string }
total: { token_id: string; value: string } | null
token: ExplorerToken
tx_hash: string
timestamp: string
method: string
block_number: number
}
export interface ExplorerAddress {
hash: string
is_contract: boolean
name: string | null
token_balances: unknown[]
}
export interface PaginatedResponse<T> {
items: T[]
next_page_params: Record<string, string> | null
}
// ---- API Client ----
function getApiBase(chainId: number): string {
return EXPLORER_API[chainId] ?? EXPLORER_API[96369]
}
async function fetchApi<T>(chainId: number, path: string, params?: Record<string, string>): Promise<T> {
const base = getApiBase(chainId)
const url = new URL(`${base}${path}`)
if (params) {
Object.entries(params).forEach(([k, v]) => url.searchParams.set(k, v))
}
const res = await fetch(url.toString(), {
headers: { Accept: 'application/json' },
next: { revalidate: 30 },
})
if (!res.ok) throw new Error(`Explorer API error: ${res.status} ${res.statusText}`)
return res.json()
}
/** List NFT collections (ERC-721 + ERC-1155 tokens) on a chain */
export async function getCollections(
chainId: number,
params?: { type?: string; q?: string }
): Promise<PaginatedResponse<ExplorerToken>> {
return fetchApi(chainId, '/tokens', {
type: params?.type ?? 'ERC-721,ERC-1155',
...(params?.q ? { q: params.q } : {}),
})
}
/** Get a specific token/collection by address */
export async function getToken(chainId: number, address: string): Promise<ExplorerToken> {
return fetchApi(chainId, `/tokens/${address}`)
}
/** List token instances (NFTs) within a collection */
export async function getTokenInstances(
chainId: number,
address: string,
params?: { holder_address_hash?: string }
): Promise<PaginatedResponse<ExplorerTokenInstance>> {
return fetchApi(chainId, `/tokens/${address}/instances`, params as Record<string, string>)
}
/** Get a single NFT instance */
export async function getTokenInstance(
chainId: number,
address: string,
tokenId: string
): Promise<ExplorerTokenInstance> {
return fetchApi(chainId, `/tokens/${address}/instances/${tokenId}`)
}
/** Get transfers for a specific NFT instance */
export async function getTokenInstanceTransfers(
chainId: number,
address: string,
tokenId: string
): Promise<PaginatedResponse<ExplorerTransfer>> {
return fetchApi(chainId, `/tokens/${address}/instances/${tokenId}/transfers`)
}
/** Get holders of a specific NFT instance */
export async function getTokenInstanceHolders(
chainId: number,
address: string,
tokenId: string
): Promise<PaginatedResponse<{ address: ExplorerAddress; value: string }>> {
return fetchApi(chainId, `/tokens/${address}/instances/${tokenId}/holders`)
}
/** Get all token transfers for a collection */
export async function getTokenTransfers(
chainId: number,
address: string
): Promise<PaginatedResponse<ExplorerTransfer>> {
return fetchApi(chainId, `/tokens/${address}/token-transfers`)
}
/** Get NFTs owned by an address across a specific collection */
export async function getAddressTokenInstances(
chainId: number,
walletAddress: string,
tokenAddress: string
): Promise<PaginatedResponse<ExplorerTokenInstance>> {
return fetchApi(chainId, `/tokens/${tokenAddress}/instances`, {
holder_address_hash: walletAddress,
})
}
/** Get all NFT tokens held by an address */
export async function getAddressTokens(
chainId: number,
address: string,
type: string = 'ERC-721'
): Promise<PaginatedResponse<{ token: ExplorerToken; value: string; token_id: string | null; token_instance: ExplorerTokenInstance | null }>> {
return fetchApi(chainId, `/addresses/${address}/tokens`, { type })
}
/** Search for tokens by name */
export async function searchTokens(
chainId: number,
query: string
): Promise<{ items: Array<{ address: string; name: string; symbol: string; type: string; icon_url: string | null }> }> {
return fetchApi(chainId, '/search', { q: query })
}
/** Resolve IPFS URLs to gateway URLs */
export function resolveMediaUrl(url: string | null | undefined): string | null {
if (!url) return null
if (url.startsWith('ipfs://')) {
return `https://ipfs.io/ipfs/${url.slice(7)}`
}
if (url.startsWith('ar://')) {
return `https://arweave.net/${url.slice(5)}`
}
return url
}
/** Get the best image URL for an NFT instance */
export function getNftImageUrl(instance: ExplorerTokenInstance): string | null {
return (
resolveMediaUrl(instance.image_url) ??
resolveMediaUrl(instance.metadata?.image) ??
resolveMediaUrl(instance.metadata?.image_data) ??
null
)
}
export {
type ExplorerToken,
type ExplorerTokenInstance,
type NFTMetadata,
type NFTTrait,
type ExplorerTransfer,
type ExplorerAddress,
type PaginatedResponse,
getCollections,
getToken,
getTokenInstances,
getTokenInstance,
getTokenInstanceTransfers,
getTokenInstanceHolders,
getTokenTransfers,
getAddressTokenInstances,
getAddressTokens,
searchTokens,
resolveMediaUrl,
getNftImageUrl,
} from '@luxfi/chains/explorer'
+1 -10
View File
@@ -1,10 +1 @@
import { createConfig, http } from 'wagmi'
import { injected } from 'wagmi/connectors'
import { supportedChains } from './chains'
export const config = createConfig({
chains: supportedChains,
connectors: [injected()],
transports: Object.fromEntries(supportedChains.map((c) => [c.id, http()])) as any,
ssr: true,
})
export { config } from '@luxfi/chains/wagmi'