UNPKG

@lyncworld/fuel-marketplace

Version:

Marketplace NPM SDK on Fuel blockchain. Powered by LYNC, it allows anyone to create their own decentralized marketplace which includes listing and buying of Non-fungible tokens (NFTs) and Semi-fungible tokens (SFTs) in a few lines of code.

169 lines (144 loc) 5.6 kB
import axios from 'axios'; import { Account, Address, getMintedAssetId, isB256, Provider } from 'fuels'; import { MarketplaceErrorCodes, Networks } from '@/enums'; import { ContractBalancesQueryResponse, MarketplaceError, SubgraphErrorResponse, TokensInCollection, } from '@/interfaces'; import { publicRpcs } from '@/configs'; import { NonFungibleCreator } from '@/contracts/non-fungible'; import { SemiFungibleCreator } from '@/contracts/semi-fungible'; import { checkArguments } from './helpers'; import { parseError } from './parse-error'; export const getContractBalances = async (network: Networks, contractAddress: `0x${string}`) => { const CONTRACT_BALANCES_QUERY = ` { contractBalances ( filter: { contract: "${contractAddress}" } first: 1000 ) { nodes { amount assetId } } } `; try { const { status, data } = await axios.post<SubgraphErrorResponse | ContractBalancesQueryResponse>( publicRpcs[network], { query: CONTRACT_BALANCES_QUERY }, { headers: { 'Content-Type': 'application/json' } } ); if (status !== 200 || 'errors' in data) throw new MarketplaceError( 'Network Request Error: Error fetching data from fuel network', MarketplaceErrorCodes.NetworkRequestError, (data as SubgraphErrorResponse).errors ); return { success: true, data: data.data.contractBalances.nodes }; } catch (error: unknown) { console.error('Error Log: Error fetching data from fuel network: ', error); return { success: false, error }; } }; export const fetchAllNftOfContract = async ( network: Networks, contractAddress: `0x${string}`, nftStandard: 'NFT' | 'SEMI_FT', assetIds: string[] ) => { let SUB_ID = '0x0000000000000000000000000000000000000000000000000000000000000000'; const provider = await Provider.create(publicRpcs[network]); const allNftsOfContract: TokensInCollection[] = []; const CreatorContract = nftStandard === 'NFT' ? NonFungibleCreator : SemiFungibleCreator; const contract = new CreatorContract(contractAddress, provider); for (const assetId of assetIds) { const metaData = await contract.functions.metadata({ bits: assetId }, 'URI').get(); const name = await contract.functions.name({ bits: assetId }).get(); const symbol = await contract.functions.symbol({ bits: assetId }).get(); try { const subId = await contract.functions.getSubId({ bits: assetId }).get(); SUB_ID = subId.value.toString(); } catch (error: unknown) { console.error('Error Log: Error fetching subId: ', error); } const tokenDetails: TokensInCollection = { tokenName: '', tokenImage: '', tokenAssetMedia: '', description: '', contractAddress: contractAddress, assetId: assetId as `0x${string}`, tokenStandard: nftStandard, contractName: name.value?.toString() ?? '', contractSymbol: symbol.value?.toString() ?? '', tokenId: SUB_ID as `0x${string}`, }; try { if (!metaData.value?.String) { throw new MarketplaceError( 'Server Error: Unable to get metadata URL from contract.', MarketplaceErrorCodes.ServerError ); } const { status, data } = await axios.get(metaData.value?.String); if (status !== 200) throw new MarketplaceError( 'Network Request Error: Failed to fetch NFT metadata.', MarketplaceErrorCodes.NetworkRequestError ); tokenDetails.tokenName = data.name; tokenDetails.tokenImage = data.image; tokenDetails.tokenAssetMedia = data.assetMedia; tokenDetails.description = data.description; } catch (error: unknown) { console.error('Error Log: Error fetching NFT metadata: ', error); } allNftsOfContract.push(tokenDetails); } return allNftsOfContract; }; export const checkNftOwnership = async ( wallet: Account, contractAddress: `0x${string}`, subId: `0x${string}`, nftStandard: 'NFT' | 'SEMI_FT' ) => { checkArguments([wallet, contractAddress, subId, nftStandard], 'arguments'); const errors: string[] = []; try { const isAddress = Address.fromB256(contractAddress.toString()); if (!isAddress) { errors.push('Validation error: Invalid contract address'); } const isSubId = isB256(subId); if (!isSubId) { errors.push('Validation error: Invalid Sub Id'); } if (errors.length) { return { success: false, errors }; } const assetId = getMintedAssetId(contractAddress, subId); const balance = await wallet.getBalance(assetId); const CreatorContract = nftStandard === 'NFT' ? NonFungibleCreator : SemiFungibleCreator; const contract = new CreatorContract(contractAddress, wallet); const decimals = await contract.functions.decimals({ bits: assetId }).get(); if (decimals.value?.toString() !== '0') { errors.push(`Validation error: Invalid ${nftStandard} contract address`); return { success: false, errors }; } const quantityValidation = nftStandard === 'NFT' ? Number(balance.toString()) === 1 : Number(balance.toString()) >= 1; if (!quantityValidation) { errors.push(`Validation error: Not a valid ${nftStandard} type`); return { success: false, errors }; } return { success: true, data: { contractAddress, subId, nftStandard } }; } catch (error: unknown) { console.error('Error Log: Error fetching owned token details: ', error); return { success: false, errors: [parseError(error)] }; } };