From 6b0b7663ec1fd545943004396823f1a26dd00895 Mon Sep 17 00:00:00 2001 From: guanbinrui Date: Tue, 19 Jul 2022 22:47:53 +0800 Subject: [PATCH 1/3] refactor: align hub apis --- .../SNSAdaptor/components/ConsoleContent.tsx | 40 +- packages/plugins/EVM/src/state/Hub/hub.ts | 379 ++++++++++++------ packages/web3-providers/src/NFTScan/index.ts | 9 +- packages/web3-providers/src/opensea/index.ts | 68 ++-- packages/web3-providers/src/opensea/utils.ts | 4 +- packages/web3-providers/src/types.ts | 27 +- packages/web3-shared/base/src/specs/index.ts | 105 +++-- .../web3-shared/base/src/utils/function.ts | 6 +- 8 files changed, 421 insertions(+), 217 deletions(-) diff --git a/packages/plugins/Debugger/src/SNSAdaptor/components/ConsoleContent.tsx b/packages/plugins/Debugger/src/SNSAdaptor/components/ConsoleContent.tsx index 4d36ec5e805c..6ccb875c1c68 100644 --- a/packages/plugins/Debugger/src/SNSAdaptor/components/ConsoleContent.tsx +++ b/packages/plugins/Debugger/src/SNSAdaptor/components/ConsoleContent.tsx @@ -14,7 +14,7 @@ import { Web3Helper, } from '@masknet/plugin-infra/web3' import { makeStyles, useCustomSnackbar } from '@masknet/theme' -import { NetworkPluginID } from '@masknet/web3-shared-base' +import { NetworkPluginID, OrderSide, SourceType } from '@masknet/web3-shared-base' import { ChainId, ChainId as EVM_ChainId, @@ -468,19 +468,39 @@ export function ConsoleContent(props: ConsoleContentProps) { const formData = new FormData(ev.currentTarget) const address = formData.get('address') as string const tokenId = formData.get('tokenId') as string + const options = { + sourceType: SourceType.OpenSea, + } const allSettled = await Promise.allSettled([ - hub?.getFungibleTokenBalance?.(address), - hub?.getNonFungibleAsset?.(address, tokenId), + hub?.getNonFungibleTokenBalance?.(address, options), + hub?.getNonFungibleTokenContract?.(address, options), + hub?.getNonFungibleTokenEvents?.(address, tokenId, options), + hub?.getNonFungibleTokenOffers?.(address, tokenId, options), + hub?.getNonFungibleTokenListings?.(address, tokenId, options), + hub?.getNonFungibleTokenOrders?.(address, tokenId, OrderSide.Buy, options), + hub?.getNonFungibleTokenOrders?.(address, tokenId, OrderSide.Sell, options), + hub?.getNonFungibleAsset?.(address, tokenId, options), + hub?.getNonFungibleToken?.(address, tokenId, options), ]) - const getSettledValue = ( - result: PromiseSettledResult, - ): T | undefined => (result.status === 'fulfilled' ? result.value : undefined) + const keys = [ + 'getNonFungibleTokenBalance', + 'getNonFungibleTokenContract', + 'getNonFungibleTokenEvents', + 'getNonFungibleTokenOffers', + 'getNonFungibleTokenListings', + 'getNonFungibleTokenOrders Buy', + 'getNonFungibleTokenOrders Sell', + 'getNonFungibleAsset', + 'getNonFungibleToken', + ] console.log( - Object.fromEntries([ - ['getFungibleTokenBalance', getSettledValue(allSettled[0])], - ['getNonFungibleAsset', getSettledValue(allSettled[1])], - ]), + Object.fromEntries( + allSettled.map((settled, i) => [ + keys[i], + settled.status === 'fulfilled' ? settled.value : undefined, + ]), + ), ) }}> diff --git a/packages/plugins/EVM/src/state/Hub/hub.ts b/packages/plugins/EVM/src/state/Hub/hub.ts index c30ddba52f25..f930b9be382b 100644 --- a/packages/plugins/EVM/src/state/Hub/hub.ts +++ b/packages/plugins/EVM/src/state/Hub/hub.ts @@ -1,4 +1,4 @@ -import type { PartialRequired } from '@masknet/shared-base' +import { EMPTY_LIST, PartialRequired } from '@masknet/shared-base' import { Alchemy_EVM, CoinGecko, @@ -11,6 +11,8 @@ import { TokenList, Zerion, Rabby, + NonFungibleTokenAPI, + FungibleTokenAPI, } from '@masknet/web3-providers' import { FungibleToken, @@ -21,7 +23,6 @@ import { HubOptions, NonFungibleAsset, Pageable, - GasOptionType, createPageable, isSameAddress, currySameAddress, @@ -33,12 +34,16 @@ import { FungibleTokenSecurity, FungibleTokenSpenderAuthorization, NonFungibleContractSpenderAuthorization, + HubIndicator, + NonFungibleTokenEvent, + NonFungibleTokenOrder, + OrderSide, + NonFungibleTokenContract, } from '@masknet/web3-shared-base' import { ChainId, chainResolver, formatEthereumAddress, - GasOption, getCoinGeckoConstants, getTokenAssetBaseURLConstants, getTokenConstants, @@ -71,6 +76,76 @@ class Hub implements EVM_Hub { } } + private getProviders( + providers: Partial>, + defaultProviders: T[], + initial?: HubOptions, + ) { + const options = this.getOptions(initial) + const predicate = createPredicate(Object.keys(providers) as Array) + return predicate(options.sourceType) ? [providers[options.sourceType]!] : defaultProviders + } + + async getGasOptions(chainId: ChainId, initial?: HubOptions) { + const options = this.getOptions(initial, { + chainId, + }) + try { + const isEIP1559 = chainResolver.isSupport(options.chainId, 'EIP1559') + if (isEIP1559) return await MetaSwap.getGasOptions(options.chainId) + return await DeBank.getGasOptions(options.chainId) + } catch (error) { + return EthereumWeb3.getGasOptions(options.chainId) + } + } + + async getTransactions( + chainId: ChainId, + account: string, + initial?: HubOptions, + ): Promise>> { + const options = this.getOptions(initial, { + account, + chainId, + }) + return DeBank.getTransactions(options.account, options) + } + + async getNonFungibleTokensByCollection( + address: string, + initial?: HubOptions, + ): Promise>> { + throw new Error('Method not implemented.') + } + + async getNonFungibleAssetsByCollection( + address: string, + initial?: HubOptions, + ): Promise>> { + return NFTScan.getAssetsByCollection(address, initial) + } + + async getNonFungibleTokenContract( + address: string, + initial?: HubOptions | undefined, + ): Promise> { + throw new Error('Method not implemented.') + } + + async getFungibleTokenBalance( + address: string, + initial?: HubOptions | undefined, + ): Promise { + throw new Error('Method not implemented.') + } + + async getNonFungibleTokenBalance( + address: string, + initial?: HubOptions | undefined, + ): Promise { + throw new Error('Method not implemented.') + } + async getFungibleTokenSecurity( chainId: ChainId, address: string, @@ -79,11 +154,8 @@ class Hub implements EVM_Hub { const options = this.getOptions(initial, { chainId, }) - - console.log(options) throw new Error('Method not implemented.') } - async getNonFungibleTokenSecurity( chainId: ChainId, address: string, @@ -92,8 +164,6 @@ class Hub implements EVM_Hub { const options = this.getOptions(initial, { chainId, }) - - console.log(options) throw new Error('Method not implemented.') } @@ -104,7 +174,7 @@ class Hub implements EVM_Hub { const options = this.getOptions(initial, { chainId, }) - const { FUNGIBLE_TOKEN_LISTS = [] } = getTokenListConstants(options.chainId) + const { FUNGIBLE_TOKEN_LISTS = EMPTY_LIST } = getTokenListConstants(options.chainId) return TokenList.fetchFungibleTokensFromTokenLists(options.chainId, FUNGIBLE_TOKEN_LISTS) } async getNonFungibleTokensFromTokenList( @@ -113,42 +183,77 @@ class Hub implements EVM_Hub { ): Promise>> { throw new Error('Method not implemented.') } - async getGasOptions(chainId: ChainId, initial?: HubOptions): Promise> { + + async getFungibleTokenIconURLs( + chainId: ChainId, + address: string, + initial?: HubOptions, + ): Promise { const options = this.getOptions(initial, { chainId, }) - try { - const isEIP1559 = chainResolver.isSupport(options.chainId, 'EIP1559') - if (isEIP1559) return await MetaSwap.getGasOptions(options.chainId) - return await DeBank.getGasOptions(options.chainId) - } catch (error) { - return EthereumWeb3.getGasOptions(options.chainId) + const { TOKEN_ASSET_BASE_URI = EMPTY_LIST } = getTokenAssetBaseURLConstants(options.chainId) + const checkSummedAddress = formatEthereumAddress(address) + + if (isSameAddress(getTokenConstants(chainId).NATIVE_TOKEN_ADDRESS, checkSummedAddress)) { + return TOKEN_ASSET_BASE_URI.map((x) => `${x}/info/logo.png`) } + + const specialIcon = SPECIAL_ICON_LIST.find(currySameAddress(address)) + if (specialIcon) return [specialIcon.logo_url] + + // load from remote + return TOKEN_ASSET_BASE_URI.map((x) => `${x}/assets/${checkSummedAddress}/logo.png`) } - getFungibleAsset(address: string, initial?: HubOptions): Promise> { + async getNonFungibleTokenIconURLs( + chainId: ChainId, + address: string, + tokenId?: string | undefined, + initial?: HubOptions, + ): Promise { throw new Error('Method not implemented.') } - async getFungibleAssets( - account: string, - initial?: HubOptions, - ): Promise>> { + + async getFungibleTokenPrice(chainId: ChainId, address: string, initial?: HubOptions): Promise { const options = this.getOptions(initial, { - account, + chainId, }) + const { PLATFORM_ID = '', COIN_ID = '' } = getCoinGeckoConstants(options.chainId) - // only the first page is available - if ((options.indicator ?? 0) > 0) return createPageable([], createIndicator(options.indicator)) - - const providers = { - [SourceType.DeBank]: DeBank, - [SourceType.Zerion]: Zerion, + if (isNativeTokenAddress(address)) { + return CoinGecko.getTokenPriceByCoinId(COIN_ID, options.currencyType) } - const predicate = createPredicate(Object.keys(providers) as Array) - const filteredProviders = predicate(options.sourceType) ? [providers[options.sourceType]] : [DeBank, Zerion] - return attemptUntil( - filteredProviders.map((x) => () => x.getAssets(options.account, options)), - createPageable([], createIndicator(options.indicator)), - ) + return CoinGecko.getTokenPrice(PLATFORM_ID, address, options.currencyType) + } + async getNonFungibleTokenPrice( + chainId: ChainId, + address: string, + tokenId: string, + initial?: HubOptions, + ): Promise { + throw new Error('Method not implemented.') + } + + async getApprovedFungibleTokenSpenders( + chainId: ChainId, + account: string, + initial?: HubOptions, + ): Promise>> { + return Rabby.getApprovedFungibleTokenSpenders(chainId, account) + } + async getApprovedNonFungibleContracts( + chainId: ChainId, + account: string, + initial?: HubOptions, + ): Promise>> { + return Rabby.getApprovedNonFungibleContracts(chainId, account) + } + + async getFungibleAsset( + address: string, + initial?: HubOptions, + ): Promise> { + throw new Error('Method not implemented.') } async getNonFungibleAsset( address: string, @@ -156,130 +261,166 @@ class Hub implements EVM_Hub { initial?: HubOptions, ): Promise | undefined> { const options = this.getOptions(initial) - const providers = { - [SourceType.OpenSea]: OpenSea, - [SourceType.Rarible]: Rarible, - [SourceType.NFTScan]: NFTScan, - [SourceType.Alchemy_EVM]: Alchemy_EVM, - } - const predicate = createPredicate(Object.keys(providers) as Array) - const defaultProviders = - options.chainId === ChainId.Mainnet ? [OpenSea, Alchemy_EVM, Rarible] : [Alchemy_EVM, OpenSea, Rarible] - const filteredProviders = predicate(options.sourceType) ? [providers[options.sourceType]] : defaultProviders + const providers = this.getProviders>( + { + [SourceType.OpenSea]: OpenSea, + [SourceType.Rarible]: Rarible, + [SourceType.NFTScan]: NFTScan, + [SourceType.Alchemy_EVM]: Alchemy_EVM, + }, + options.chainId === ChainId.Mainnet ? [OpenSea, Alchemy_EVM, Rarible] : [Alchemy_EVM, OpenSea, Rarible], + initial, + ) return attemptUntil( - filteredProviders.map((x) => () => x.getAsset(address, tokenId, options)), + providers.map((x) => () => x.getAsset?.(address, tokenId, options)), undefined, ) } - async getNonFungibleTokens( + + async getFungibleAssets( account: string, initial?: HubOptions, - ): Promise>> { + ): Promise>> { const options = this.getOptions(initial, { account, }) - const providers = { - [SourceType.OpenSea]: OpenSea, - [SourceType.Rarible]: Rarible, - [SourceType.Alchemy_EVM]: Alchemy_EVM, - } - const predicate = createPredicate(Object.keys(providers) as Array) - const defaultProviders = - options.chainId === ChainId.Mainnet ? [OpenSea, Alchemy_EVM, Rarible] : [Alchemy_EVM, OpenSea, Rarible] - const filteredProviders = predicate(options.sourceType) ? [providers[options.sourceType]] : defaultProviders + + // only the first page is available + if ((options.indicator ?? 0) > 0) return createPageable(EMPTY_LIST, createIndicator(options.indicator)) + + const providers = this.getProviders>( + { + [SourceType.DeBank]: DeBank, + [SourceType.Zerion]: Zerion, + }, + [DeBank, Zerion], + initial, + ) return attemptUntil( - filteredProviders.map((x) => () => x.getAssets(options.account, options)), - createPageable([], createIndicator(options.indicator)), + providers.map((x) => () => x.getAssets(options.account, options)), + createPageable(EMPTY_LIST, createIndicator(options.indicator)), ) } - async getNonFungibleTokensByCollection( - address: string, - initial?: HubOptions, - ): Promise>> { - return NFTScan.getAssetsByCollection(address, initial) - } - getNonFungibleCollections( + async getNonFungibleAssets( account: string, initial?: HubOptions, - ): Promise>> { - const options = this.getOptions(initial, { - account, - }) - return OpenSea.getCollections(options.account, options) + ): Promise>> { + const options = this.getOptions(initial) + const providers = this.getProviders( + { + [SourceType.OpenSea]: OpenSea, + [SourceType.Rarible]: Rarible, + [SourceType.NFTScan]: NFTScan, + [SourceType.Alchemy_EVM]: Alchemy_EVM, + }, + options.chainId === ChainId.Mainnet ? [OpenSea, Alchemy_EVM, Rarible] : [Alchemy_EVM, OpenSea, Rarible], + initial, + ) + return attemptUntil( + providers.map((x) => () => x.getAssets(account, options)), + createPageable(EMPTY_LIST, createIndicator(options.indicator)), + ) } - getFungibleTokenPrice(chainId: ChainId, address: string, initial?: HubOptions): Promise { - const options = this.getOptions(initial, { - chainId, - }) - const { PLATFORM_ID = '', COIN_ID = '' } = getCoinGeckoConstants(options.chainId) - if (isNativeTokenAddress(address)) { - return CoinGecko.getTokenPriceByCoinId(COIN_ID, options.currencyType) - } - return CoinGecko.getTokenPrice(PLATFORM_ID, address, options.currencyType) + async getFungibleToken( + address: string, + initial?: HubOptions | undefined, + ): Promise | undefined> { + throw new Error('Method not implemented.') } - getNonFungibleTokenPrice( - chainId: ChainId, + async getNonFungibleToken( address: string, tokenId: string, initial?: HubOptions, - ): Promise { + ): Promise | undefined> { + const options = this.getOptions(initial) + const providers = this.getProviders>( + { + [SourceType.OpenSea]: OpenSea, + [SourceType.Rarible]: Rarible, + [SourceType.NFTScan]: NFTScan, + [SourceType.Alchemy_EVM]: Alchemy_EVM, + }, + options.chainId === ChainId.Mainnet ? [OpenSea, Alchemy_EVM, Rarible] : [Alchemy_EVM, OpenSea, Rarible], + initial, + ) + return attemptUntil( + providers.map((x) => () => x.getToken?.(address, tokenId, options)), + undefined, + ) + } + + async getFungibleTokens( + account: string, + initial?: HubOptions | undefined, + ): Promise>> { throw new Error('Method not implemented.') } - async getFungibleTokenIconURLs( - chainId: ChainId, - address: string, + async getNonFungibleTokens( + account: string, initial?: HubOptions, - ): Promise { + ): Promise>> { const options = this.getOptions(initial, { - chainId, + account, }) - const { TOKEN_ASSET_BASE_URI = [] } = getTokenAssetBaseURLConstants(options.chainId) - const checkSummedAddress = formatEthereumAddress(address) - - if (isSameAddress(getTokenConstants(chainId).NATIVE_TOKEN_ADDRESS, checkSummedAddress)) { - return TOKEN_ASSET_BASE_URI.map((x) => `${x}/info/logo.png`) - } + const providers = this.getProviders( + { + [SourceType.OpenSea]: OpenSea, + [SourceType.Rarible]: Rarible, + [SourceType.Alchemy_EVM]: Alchemy_EVM, + }, + options.chainId === ChainId.Mainnet ? [OpenSea, Alchemy_EVM, Rarible] : [Alchemy_EVM, OpenSea, Rarible], + initial, + ) - const specialIcon = SPECIAL_ICON_LIST.find(currySameAddress(address)) - if (specialIcon) return [specialIcon.logo_url] + return attemptUntil( + providers.map((x) => () => x.getAssets(options.account, options)), + createPageable(EMPTY_LIST, createIndicator(options.indicator)), + ) + } - // load from remote - return TOKEN_ASSET_BASE_URI.map((x) => `${x}/assets/${checkSummedAddress}/logo.png`) + async getNonFungibleTokenEvents( + address: string, + tokenId: string, + initial?: HubOptions | undefined, + ): Promise>> { + throw new Error('Method not implemented.') } - getNonFungibleTokenIconURLs( - chainId: ChainId, + + async getNonFungibleTokenListings( address: string, - tokenId?: string | undefined, - initial?: HubOptions, - ): Promise { + tokenId: string, + initial?: HubOptions | undefined, + ): Promise>> { throw new Error('Method not implemented.') } - getApprovedFungibleTokenSpenders( - chainId: ChainId, - account: string, - initial?: HubOptions, - ): Promise>> { - return Rabby.getApprovedFungibleTokenSpenders(chainId, account) + + async getNonFungibleTokenOffers( + address: string, + tokenId: string, + initial?: HubOptions | undefined, + ): Promise>> { + throw new Error('Method not implemented.') } - getApprovedNonFungibleContracts( - chainId: ChainId, - account: string, - initial?: HubOptions, - ): Promise>> { - return Rabby.getApprovedNonFungibleContracts(chainId, account) + + async getNonFungibleTokenOrders( + address: string, + tokenId: string, + side: OrderSide, + initial?: HubOptions | undefined, + ): Promise>> { + throw new Error('Method not implemented.') } - async getTransactions( - chainId: ChainId, + + async getNonFungibleCollections( account: string, initial?: HubOptions, - ): Promise>> { + ): Promise>> { const options = this.getOptions(initial, { account, - chainId, }) - return DeBank.getTransactions(options.account, options) + return OpenSea.getCollections(options.account, options) } } diff --git a/packages/web3-providers/src/NFTScan/index.ts b/packages/web3-providers/src/NFTScan/index.ts index 96c68def6c2a..367fee9a890e 100644 --- a/packages/web3-providers/src/NFTScan/index.ts +++ b/packages/web3-providers/src/NFTScan/index.ts @@ -1,4 +1,5 @@ import { DataProvider } from '@masknet/public-api' +import { EMPTY_LIST } from '@masknet/shared-base' import ERC721ABI from '@masknet/web3-contracts/abis/ERC721.json' import type { ERC721 } from '@masknet/web3-contracts/types/ERC721' import { @@ -174,7 +175,7 @@ export class NFTScanAPI implements NonFungibleTokenAPI.Provider 0 ? createNextIndicator(indicator) : undefined, ) @@ -246,7 +247,7 @@ export class NFTScanAPI implements NonFungibleTokenAPI.Provider { @@ -256,11 +257,11 @@ export class NFTScanAPI implements NonFungibleTokenAPI.Provider { - if (!keyword) return [] + if (!keyword) return EMPTY_LIST const nfts = await this.searchNftPlatformName(keyword) const coins = await Promise.all( diff --git a/packages/web3-providers/src/opensea/index.ts b/packages/web3-providers/src/opensea/index.ts index 6d89e08d5ba2..2239f8c2da5d 100644 --- a/packages/web3-providers/src/opensea/index.ts +++ b/packages/web3-providers/src/opensea/index.ts @@ -34,6 +34,7 @@ import type { } from './types' import { getOrderUSDPrice, toImage } from './utils' import { OPENSEA_ACCOUNT_URL, OPENSEA_API_URL } from './constants' +import { EMPTY_LIST } from '@masknet/shared-base' const cache = new LRU({ max: 50, @@ -66,10 +67,11 @@ function createTokenDetailed( decimals: number name: string symbol: string + image_url?: string }, ) { if (token.symbol === 'ETH') return createNativeToken(chainId) - return createERC20Token(chainId, token.address, token.name, token.symbol, token.decimals) + return createERC20Token(chainId, token.address, token.name, token.symbol, token.decimals, token.image_url) } function createAssetLink(account: OpenSeaCustomAccount | undefined) { @@ -129,7 +131,9 @@ function createNFTAsset(chainId: ChainId, asset: OpenSeaResponse): NonFungibleAs ), ) const orderTokens = uniqBy( - desktopOrder?.payment_token_contract ? [createTokenDetailed(chainId, desktopOrder.payment_token_contract)] : [], + desktopOrder?.payment_token_contract + ? [createTokenDetailed(chainId, desktopOrder.payment_token_contract)] + : EMPTY_LIST, (x) => x.address.toLowerCase(), ) const offerTokens = uniqBy( @@ -163,25 +167,29 @@ function createNFTAsset(chainId: ChainId, asset: OpenSeaResponse): NonFungibleAs type: x.trait_type, value: x.value, })), - price: { - [CurrencyType.USD]: getOrderUSDPrice( - asset.last_sale?.total_price, - asset.last_sale?.payment_token.usd_price, - asset.last_sale?.payment_token.decimals, - )?.toString(), - }, - priceInToken: { - token: createTokenDetailed(chainId, { - address: asset.last_sale?.payment_token.address ?? '', - decimals: Number(asset.last_sale?.payment_token.decimals ?? '0'), - name: '', - symbol: asset.last_sale?.payment_token.symbol ?? '', - }), - amount: formatBalance( - new BigNumber(asset.last_sale?.total_price ?? '0'), - asset.last_sale?.payment_token.decimals, - ), - }, + price: asset.last_sale + ? { + [CurrencyType.USD]: getOrderUSDPrice( + asset.last_sale.total_price, + asset.last_sale.payment_token.usd_price, + asset.last_sale.payment_token.decimals, + )?.toString(), + } + : undefined, + priceInToken: asset.last_sale + ? { + token: createTokenDetailed(chainId, { + address: asset.last_sale.payment_token.address ?? '', + decimals: Number(asset.last_sale.payment_token.decimals ?? '0'), + name: '', + symbol: asset.last_sale.payment_token.symbol ?? '', + }), + amount: formatBalance( + new BigNumber(asset.last_sale.total_price ?? '0'), + asset.last_sale.payment_token.decimals, + ), + } + : undefined, orders: asset.orders ?.sort((a, z) => new BigNumber(getOrderUSDPrice(z.current_price, z.payment_token_contract?.usd_price) ?? 0) @@ -325,19 +333,19 @@ export class OpenSeaAPI implements NonFungibleTokenAPI.Provider = {}) { - if (chainId !== ChainId.Mainnet) return createPageable([], createIndicator(indicator)) + async getAssets(account: string, { chainId = ChainId.Mainnet, indicator, size = 50 }: HubOptions = {}) { + if (chainId !== ChainId.Mainnet) return createPageable(EMPTY_LIST, createIndicator(indicator)) const response = await fetchFromOpenSea<{ assets?: OpenSeaResponse[] }>( urlcat('/api/v1/assets', { - owner: from, + owner: account, offset: (indicator?.index ?? 0) * size, limit: size, }), chainId, ) - const tokens = (response?.assets ?? []) + const tokens = (response?.assets ?? EMPTY_LIST) ?.filter( (x: OpenSeaResponse) => ['non-fungible', 'semi-fungible'].includes(x.asset_contract.asset_contract_type) || @@ -392,7 +400,7 @@ export class OpenSeaAPI implements NonFungibleTokenAPI.Provider createNFTHistory(chainId, x)) ?? [] + return response?.asset_events?.map((x) => createNFTHistory(chainId, x)) ?? EMPTY_LIST } async getOrders( @@ -413,14 +421,14 @@ export class OpenSeaAPI implements NonFungibleTokenAPI.Provider createAssetOrder(chainId, x)) ?? [] + return response?.orders?.map((x) => createAssetOrder(chainId, x)) ?? EMPTY_LIST } async getCollections( address: string, { chainId = ChainId.Mainnet, indicator, size = 50 }: HubOptions = {}, ) { - if (chainId !== ChainId.Mainnet) return createPageable([], createIndicator(indicator)) + if (chainId !== ChainId.Mainnet) return createPageable(EMPTY_LIST, createIndicator(indicator)) const response = await fetchFromOpenSea( urlcat('/api/v1/collections', { asset_owner: address, @@ -429,7 +437,7 @@ export class OpenSeaAPI implements NonFungibleTokenAPI.Provider> = response @@ -446,7 +454,7 @@ export class OpenSeaAPI implements NonFungibleTokenAPI.Provider x.address) ?? [] + .filter((x) => x.address) ?? EMPTY_LIST return createPageable( collections, diff --git a/packages/web3-providers/src/opensea/utils.ts b/packages/web3-providers/src/opensea/utils.ts index eaf199a52c9a..fe2a085eb615 100644 --- a/packages/web3-providers/src/opensea/utils.ts +++ b/packages/web3-providers/src/opensea/utils.ts @@ -1,5 +1,5 @@ import BigNumber from 'bignumber.js' -import { isOne, pow10 } from '@masknet/web3-shared-base' +import { isOne, pow10, ZERO } from '@masknet/web3-shared-base' import { resolveIPFSLink } from '@masknet/web3-shared-evm' export function getOrderUnitPrice(currentPrice?: string, decimals?: number, quantity?: string) { @@ -10,7 +10,7 @@ export function getOrderUnitPrice(currentPrice?: string, decimals?: number, quan } export function getOrderUSDPrice(currentPrice?: string, usdPrice?: string, decimals?: number) { - if (!currentPrice || !decimals) return + if (!currentPrice || !decimals) return ZERO const quantity = new BigNumber(currentPrice).div(pow10(decimals)) return new BigNumber(usdPrice ?? 0).multipliedBy(quantity).decimalPlaces(2, 2) } diff --git a/packages/web3-providers/src/types.ts b/packages/web3-providers/src/types.ts index 5dae79688282..b5a290ce106c 100644 --- a/packages/web3-providers/src/types.ts +++ b/packages/web3-providers/src/types.ts @@ -258,8 +258,8 @@ export namespace FungibleTokenAPI { export namespace NonFungibleTokenAPI { export interface Provider { - /** Get owned balance of a fungible token by given account. */ - getBalance?: (address: string, options?: HubOptions) => Promise + /** Get balance of a fungible token owned by the given account. */ + getBalance?: (account: string, options?: HubOptions) => Promise /** Get a non-fungible contract. */ getContract?: ( address: string, @@ -271,8 +271,13 @@ export namespace NonFungibleTokenAPI { tokenId: string, options?: HubOptions, ) => Promise | undefined> - /** Get non-fungible assets */ + /** Get non-fungible assets owned by the given account. */ getAssets?: ( + account: string, + options?: HubOptions, + ) => Promise>> + /** Get non-fungible assets of the given collection. */ + getAssetsByCollection?: ( address: string, options?: HubOptions, ) => Promise>> @@ -282,9 +287,14 @@ export namespace NonFungibleTokenAPI { tokenId: string, options?: HubOptions, ) => Promise | undefined> - /** Get non-fungible tokens. */ + /** Get non-fungible tokens owned by the given account. */ getTokens?: ( - from: string, + account: string, + options?: HubOptions, + ) => Promise, Indicator>> + /** Get non-fungible tokens of the given collection. */ + getTokensByCollection?: ( + account: string, options?: HubOptions, ) => Promise, Indicator>> /** Get events of a non-fungible token. */ @@ -299,7 +309,7 @@ export namespace NonFungibleTokenAPI { tokenId: string, options?: HubOptions, ) => Promise>> - /** Get offering orders of a non-fungible token. */ + /** Get offered orders of a non-fungible token. */ getOffers?: ( address: string, tokenId: string, @@ -312,11 +322,12 @@ export namespace NonFungibleTokenAPI { side: OrderSide, options?: HubOptions, ) => Promise>> - /** Get non-fungible collections of given account. */ + /** Get non-fungible collections owned by the given account. */ getCollections?: ( - address: string, + account: string, options?: HubOptions, ) => Promise, Indicator>> + /** Place a bid on a token. */ createBuyOrder?: (/** TODO: add parameters */) => Promise /** Listing a token for public sell. */ diff --git a/packages/web3-shared/base/src/specs/index.ts b/packages/web3-shared/base/src/specs/index.ts index 20e776a726e3..4a4ba8e56218 100644 --- a/packages/web3-shared/base/src/specs/index.ts +++ b/packages/web3-shared/base/src/specs/index.ts @@ -693,18 +693,18 @@ export interface Connection< ): Promise> /** Get native fungible token balance. */ getNativeTokenBalance(initial?: Web3ConnectionOptions): Promise - /** Get fungible token balance */ + /** Get fungible token balance. */ getFungibleTokenBalance(address: string, initial?: Web3ConnectionOptions): Promise - /** Get non-fungible token balance */ + /** Get non-fungible token balance. */ getNonFungibleTokenBalance( address: string, tokenId?: string, schema?: SchemaType, initial?: Web3ConnectionOptions, ): Promise - /** Get fungible token balance */ + /** Get fungible token balance. */ getFungibleTokensBalance(listOfAddress: string[], initial?: Web3ConnectionOptions): Promise> - /** Get non-fungible token balance */ + /** Get non-fungible token balance. */ getNonFungibleTokensBalance( listOfAddress: string[], initial?: Web3ConnectionOptions, @@ -835,26 +835,31 @@ export interface HubOptions { export interface Hub> { /** Get recommended gas options. */ getGasOptions?: (chainId: ChainId, initial?: Web3HubOptions) => Promise> - /** Get the most recent transactions of given account. */ + /** Get the most recent transactions of the given account. */ getTransactions: ( chainId: ChainId, account: string, initial?: Web3HubOptions, ) => Promise>> - /** Get non-fungible tokens in the same collection. */ + /** Get non-fungible tokens of the given collection. */ getNonFungibleTokensByCollection?: ( address: string, initial?: Web3HubOptions, ) => Promise>> - /** Get a non-fungible token contract. */ + /** Get non-fungible assets of the given collection. */ + getNonFungibleAssetsByCollection?: ( + address: string, + initial?: Web3HubOptions, + ) => Promise>> + /** Get a non-fungible contract. */ getNonFungibleTokenContract?: ( address: string, initial?: Web3HubOptions, ) => Promise> - /** Get owned balance of a fungible token by given account. */ - getFungibleTokenBalance?: (address: string, initial?: Web3HubOptions) => Promise - /** Get owned balance of a non-fungible token by given account. */ - getNonFungibleTokenBalance?: (address: string, initial?: Web3HubOptions) => Promise + /** Get balance of a fungible token owned by the given account. */ + getFungibleTokenBalance?: (address: string, initial?: Web3HubOptions) => Promise + /** Get balance of non-fungible tokens in a collection owned by the given account. */ + getNonFungibleTokenBalance?: (address: string, initial?: Web3HubOptions) => Promise /** Get security diagnosis about a fungible token. */ getFungibleTokenSecurity?: ( chainId: ChainId, @@ -877,13 +882,31 @@ export interface Hub Promise>> - /** Get approved spenders about a fungible token from given account. */ + /** Get price of a fungible token. */ + getFungibleTokenPrice?: (chainId: ChainId, address: string, initial?: Web3HubOptions) => Promise + /** Get price of a non-fungible token. */ + getNonFungibleTokenPrice?: ( + chainId: ChainId, + address: string, + tokenId: string, + initial?: Web3HubOptions, + ) => Promise + /** Get token icon URLs that point to a fungible token. */ + getFungibleTokenIconURLs?: (chainId: ChainId, address: string, initial?: Web3HubOptions) => Promise + /** Get token icon URLs that point to a non-fungible token. */ + getNonFungibleTokenIconURLs?: ( + chainId: ChainId, + address: string, + tokenId?: string, + initial?: Web3HubOptions, + ) => Promise + /** Get spenders of a fungible token approved by the given account. */ getApprovedFungibleTokenSpenders?: ( chainId: ChainId, account: string, initial?: Web3HubOptions, ) => Promise>> - /** Get approved contracts about a non-fungible token from given account. */ + /** Get contracts of a non-fungible token approved by the given account. */ getApprovedNonFungibleContracts?: ( chainId: ChainId, account: string, @@ -900,65 +923,63 @@ export interface Hub Promise | undefined> - /** Get fungible assets of given account. */ + /** Get fungible assets owned by the given account. */ getFungibleAssets?: ( account: string, initial?: Web3HubOptions, ) => Promise>> - /** Get non-fungible assets of given account. */ + /** Get non-fungible assets owned by the given account. */ getNonFungibleAssets?: ( account: string, initial?: Web3HubOptions, ) => Promise>> - /** Get fungible tokens of given account. */ + /** Get a fungible token. */ + getFungibleToken?: ( + address: string, + initial?: Web3HubOptions, + ) => Promise | undefined> + /** Get a non-fungible token. */ + getNonFungibleToken?: ( + address: string, + tokenId: string, + initial?: Web3HubOptions, + ) => Promise | undefined> + /** Get fungible tokens owned by the given account. */ getFungibleTokens?: ( account: string, initial?: Web3HubOptions, ) => Promise | Error>> - /** Get non-fungible tokens of given account. */ + /** Get non-fungible tokens owned by the given account. */ getNonFungibleTokens?: ( account: string, initial?: Web3HubOptions, ) => Promise>> - /** Get price of a fungible token */ - getFungibleTokenPrice?: (chainId: ChainId, address: string, initial?: Web3HubOptions) => Promise - /** Get price of a non-fungible token */ - getNonFungibleTokenPrice?: ( - chainId: ChainId, - address: string, - tokenId: string, - initial?: Web3HubOptions, - ) => Promise - /** Get token icon urls of a fungible token */ - getFungibleTokenIconURLs?: (chainId: ChainId, address: string, initial?: Web3HubOptions) => Promise - /** Get token icon urls of a non-fungible token */ - getNonFungibleTokenIconURLs?: ( - chainId: ChainId, - address: string, - tokenId?: string, - initial?: Web3HubOptions, - ) => Promise /** Get events of a non-fungible token. */ getNonFungibleTokenEvents?: ( - account: string, + address: string, + tokenId: string, initial?: Web3HubOptions, ) => Promise>> /** Get listed orders of a non-fungible token. */ getNonFungibleTokenListings?: ( - account: string, + address: string, + tokenId: string, initial?: Web3HubOptions, ) => Promise>> - /** Get offering orders of a non-fungible token. */ + /** Get offered orders of a non-fungible token. */ getNonFungibleTokenOffers?: ( - account: string, + address: string, + tokenId: string, initial?: Web3HubOptions, ) => Promise>> /** Get orders of a non-fungible token. */ getNonFungibleTokenOrders?: ( - account: string, + address: string, + tokenId: string, + side: OrderSide, initial?: Web3HubOptions, ) => Promise>> - /** Get non-fungible collections of given account. */ + /** Get non-fungible collections owned by the given account. */ getNonFungibleCollections?: ( account: string, initial?: Web3HubOptions, @@ -966,7 +987,7 @@ export interface Hub Promise - /** Listing a token for public sell. */ + /** List a token for public sell. */ createSellOrder?: (/** TODO: add parameters */) => Promise /** Fulfill an order. */ fulfillOrder?: (/** TODO: add parameters */) => Promise diff --git a/packages/web3-shared/base/src/utils/function.ts b/packages/web3-shared/base/src/utils/function.ts index 38c8a53dbe59..9982b370a020 100644 --- a/packages/web3-shared/base/src/utils/function.ts +++ b/packages/web3-shared/base/src/utils/function.ts @@ -2,10 +2,12 @@ export function createPredicate(candidates: T[]) { return (candidate?: unknown): candidate is P => !!candidate && candidates.includes(candidate as T) } -export async function attemptUntil(funcs: Array<() => Promise>, fallback: T) { +export async function attemptUntil(funcs: Array<() => Promise | undefined>, fallback: T) { for (const func of funcs) { try { - return await func() + const result = await func() + if (typeof result === 'undefined') continue + return result } catch { continue } From 29ed60bee1f24b9e30f6bdf777b9c9a33db27041 Mon Sep 17 00:00:00 2001 From: guanbinrui Date: Wed, 20 Jul 2022 01:02:21 +0800 Subject: [PATCH 2/3] refacotr: os and rarible --- packages/plugins/EVM/src/state/Hub/hub.ts | 64 ++++++++++++++++++-- packages/web3-providers/src/opensea/index.ts | 14 ++++- packages/web3-providers/src/rarible/index.ts | 64 +++++++++++--------- packages/web3-providers/src/types.ts | 8 +-- 4 files changed, 110 insertions(+), 40 deletions(-) diff --git a/packages/plugins/EVM/src/state/Hub/hub.ts b/packages/plugins/EVM/src/state/Hub/hub.ts index f930b9be382b..3d8df0ea9af7 100644 --- a/packages/plugins/EVM/src/state/Hub/hub.ts +++ b/packages/plugins/EVM/src/state/Hub/hub.ts @@ -385,7 +385,21 @@ class Hub implements EVM_Hub { tokenId: string, initial?: HubOptions | undefined, ): Promise>> { - throw new Error('Method not implemented.') + const options = this.getOptions(initial) + const providers = this.getProviders>( + { + [SourceType.OpenSea]: OpenSea, + [SourceType.Rarible]: Rarible, + [SourceType.Alchemy_EVM]: Alchemy_EVM, + }, + options.chainId === ChainId.Mainnet ? [OpenSea, Alchemy_EVM, Rarible] : [Alchemy_EVM, OpenSea, Rarible], + initial, + ) + + return attemptUntil( + providers.map((x) => () => x.getEvents?.(address, tokenId, options)), + createPageable(EMPTY_LIST, createIndicator(options.indicator)), + ) } async getNonFungibleTokenListings( @@ -393,7 +407,21 @@ class Hub implements EVM_Hub { tokenId: string, initial?: HubOptions | undefined, ): Promise>> { - throw new Error('Method not implemented.') + const options = this.getOptions(initial) + const providers = this.getProviders>( + { + [SourceType.OpenSea]: OpenSea, + [SourceType.Rarible]: Rarible, + [SourceType.Alchemy_EVM]: Alchemy_EVM, + }, + options.chainId === ChainId.Mainnet ? [OpenSea, Alchemy_EVM, Rarible] : [Alchemy_EVM, OpenSea, Rarible], + initial, + ) + + return attemptUntil( + providers.map((x) => () => x.getListings?.(address, tokenId, options)), + createPageable(EMPTY_LIST, createIndicator(options.indicator)), + ) } async getNonFungibleTokenOffers( @@ -401,7 +429,21 @@ class Hub implements EVM_Hub { tokenId: string, initial?: HubOptions | undefined, ): Promise>> { - throw new Error('Method not implemented.') + const options = this.getOptions(initial) + const providers = this.getProviders>( + { + [SourceType.OpenSea]: OpenSea, + [SourceType.Rarible]: Rarible, + [SourceType.Alchemy_EVM]: Alchemy_EVM, + }, + options.chainId === ChainId.Mainnet ? [OpenSea, Alchemy_EVM, Rarible] : [Alchemy_EVM, OpenSea, Rarible], + initial, + ) + + return attemptUntil( + providers.map((x) => () => x.getOffers?.(address, tokenId, options)), + createPageable(EMPTY_LIST, createIndicator(options.indicator)), + ) } async getNonFungibleTokenOrders( @@ -410,7 +452,21 @@ class Hub implements EVM_Hub { side: OrderSide, initial?: HubOptions | undefined, ): Promise>> { - throw new Error('Method not implemented.') + const options = this.getOptions(initial) + const providers = this.getProviders>( + { + [SourceType.OpenSea]: OpenSea, + [SourceType.Rarible]: Rarible, + [SourceType.Alchemy_EVM]: Alchemy_EVM, + }, + options.chainId === ChainId.Mainnet ? [OpenSea, Alchemy_EVM, Rarible] : [Alchemy_EVM, OpenSea, Rarible], + initial, + ) + + return attemptUntil( + providers.map((x) => () => x.getOrders?.(address, tokenId, side, options)), + createPageable(EMPTY_LIST, createIndicator(options.indicator)), + ) } async getNonFungibleCollections( diff --git a/packages/web3-providers/src/opensea/index.ts b/packages/web3-providers/src/opensea/index.ts index 2239f8c2da5d..49b4b74eb1db 100644 --- a/packages/web3-providers/src/opensea/index.ts +++ b/packages/web3-providers/src/opensea/index.ts @@ -400,7 +400,12 @@ export class OpenSeaAPI implements NonFungibleTokenAPI.Provider createNFTHistory(chainId, x)) ?? EMPTY_LIST + const events = response?.asset_events?.map((x) => createNFTHistory(chainId, x)) ?? EMPTY_LIST + return createPageable( + events, + createIndicator(indicator), + events.length === size ? createNextIndicator(indicator) : undefined, + ) } async getOrders( @@ -421,7 +426,12 @@ export class OpenSeaAPI implements NonFungibleTokenAPI.Provider createAssetOrder(chainId, x)) ?? EMPTY_LIST + const orders = response?.orders?.map((x) => createAssetOrder(chainId, x)) ?? EMPTY_LIST + return createPageable( + orders, + createIndicator(indicator), + orders.length === size ? createNextIndicator(indicator) : undefined, + ) } async getCollections( diff --git a/packages/web3-providers/src/rarible/index.ts b/packages/web3-providers/src/rarible/index.ts index 332db2d7a145..ed58bf88a32b 100644 --- a/packages/web3-providers/src/rarible/index.ts +++ b/packages/web3-providers/src/rarible/index.ts @@ -1,8 +1,8 @@ import urlcat from 'urlcat' import { compact, first } from 'lodash-unified' import getUnixTime from 'date-fns/getUnixTime' +import { EMPTY_LIST } from '@masknet/shared-base' import { - createLookupTableResolver, CurrencyType, HubOptions, FungibleToken, @@ -29,18 +29,10 @@ import { RaribleOfferResponse, RaribleProfileResponse, } from './types' -import { RaribleUserURL, RaribleRopstenUserURL, RaribleMainnetURL, RaribleChainURL, RaribleURL } from './constants' +import { RaribleMainnetURL, RaribleChainURL, RaribleURL } from './constants' import { isProxyENV } from '../helpers' import type { NonFungibleTokenAPI } from '../types' -const resolveRaribleUserNetwork = createLookupTableResolver( - { - [ChainId.Mainnet]: RaribleUserURL, - [ChainId.Ropsten]: RaribleRopstenUserURL, - }, - RaribleUserURL, -) - async function fetchFromRarible(url: string, path: string, init?: RequestInit) { const response = await fetch(urlcat(url, path), { ...(!isProxyENV() && { mode: 'cors' }), @@ -197,17 +189,15 @@ export class RaribleAPI implements NonFungibleTokenAPI.Provider = {}, - ): Promise>> { + { chainId = ChainId.Mainnet, indicator, size }: HubOptions = {}, + ) { const requestPath = urlcat('/items/:tokenAddress::tokenId/offers', { tokenAddress, tokenId }) const orders = await fetchFromRarible(RaribleMainnetURL, requestPath, { method: 'POST', - body: JSON.stringify({ size: 20 }), + body: JSON.stringify({ size }), headers: { 'content-type': 'application/json' }, }) - const profiles = await getProfilesFromRarible(orders.map((item) => item.maker)) - return orders.map((order): NonFungibleTokenOrder => { - const ownerInfo = profiles.find((owner) => owner.id === order.maker) + const offers = orders.map((order): NonFungibleTokenOrder => { return { id: order.tokenId, chainId: ChainId.Mainnet, @@ -231,22 +221,25 @@ export class RaribleAPI implements NonFungibleTokenAPI.Provider = {}, - ): Promise>> { + { chainId = ChainId.Mainnet, indicator, size }: HubOptions = {}, + ) { const requestPath = urlcat('/items/:tokenAddress::tokenId/ownerships', { tokenAddress, tokenId }) const assets = await fetchFromRarible(RaribleMainnetURL, requestPath) - const listings = assets.filter((x) => x.selling) - const profiles = await getProfilesFromRarible(listings.map((x) => x.owner)) - return listings.map((asset): NonFungibleTokenOrder => { - const ownerInfo = profiles.find((owner) => owner.id === asset.owner) + const orders = assets.filter((x) => x.selling) + const listings = orders.map((asset): NonFungibleTokenOrder => { return { id: asset.tokenId, - chainId: ChainId.Mainnet, + chainId, assetPermalink: '', createdAt: Number(asset.date ?? 0), price: { @@ -256,7 +249,7 @@ export class RaribleAPI implements NonFungibleTokenAPI.Provider, @@ -265,20 +258,25 @@ export class RaribleAPI implements NonFungibleTokenAPI.Provider = {}) { + async getOrders(tokenAddress: string, tokenId: string, side: OrderSide, options: HubOptions = {}) { switch (side) { case OrderSide.Buy: - return this.getOffers(tokenAddress, tokenId, opts) + return this.getOffers(tokenAddress, tokenId, options) case OrderSide.Sell: - return this.getListings(tokenAddress, tokenId, opts) + return this.getListings(tokenAddress, tokenId, options) default: - return [] + return createPageable(EMPTY_LIST, createIndicator(options.indicator)) } } - async getEvents(tokenAddress: string, tokenId: string): Promise>> { + async getEvents(tokenAddress: string, tokenId: string, { indicator, size }: HubOptions = {}) { const response = await fetchFromRarible(RaribleMainnetURL, '/activity', { method: 'POST', body: JSON.stringify({ @@ -304,7 +302,7 @@ export class RaribleAPI implements NonFungibleTokenAPI.Provider { + const events = histories.map((history) => { const ownerInfo = profiles.find((profile) => profile.id === history.owner) const fromInfo = profiles.find((profile) => profile.id === history.buyer || profile.id === history.from) return { @@ -329,5 +327,11 @@ export class RaribleAPI implements NonFungibleTokenAPI.Provider }) + + return createPageable( + events, + createIndicator(indicator), + events.length === size ? createNextIndicator(indicator) : undefined, + ) } } diff --git a/packages/web3-providers/src/types.ts b/packages/web3-providers/src/types.ts index b5a290ce106c..8af2774fb74f 100644 --- a/packages/web3-providers/src/types.ts +++ b/packages/web3-providers/src/types.ts @@ -302,26 +302,26 @@ export namespace NonFungibleTokenAPI { address: string, tokenId: string, options?: HubOptions, - ) => Promise>> + ) => Promise>> /** Get listed orders of a non-fungible token. */ getListings?: ( address: string, tokenId: string, options?: HubOptions, - ) => Promise>> + ) => Promise>> /** Get offered orders of a non-fungible token. */ getOffers?: ( address: string, tokenId: string, options?: HubOptions, - ) => Promise>> + ) => Promise>> /** Get orders of a non-fungible token. */ getOrders?: ( address: string, tokenId: string, side: OrderSide, options?: HubOptions, - ) => Promise>> + ) => Promise>> /** Get non-fungible collections owned by the given account. */ getCollections?: ( account: string, From 9f2342f801d3578338d8509078d2cb3347c2b133 Mon Sep 17 00:00:00 2001 From: guanbinrui Date: Wed, 20 Jul 2022 11:23:00 +0800 Subject: [PATCH 3/3] refactor: me --- packages/plugins/EVM/src/state/Hub/hub.ts | 20 ++++++++++++---- .../web3-providers/src/MagicEden/index.ts | 24 +++++++++++++------ 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/packages/plugins/EVM/src/state/Hub/hub.ts b/packages/plugins/EVM/src/state/Hub/hub.ts index 3d8df0ea9af7..0832d6c54c6c 100644 --- a/packages/plugins/EVM/src/state/Hub/hub.ts +++ b/packages/plugins/EVM/src/state/Hub/hub.ts @@ -195,7 +195,7 @@ class Hub implements EVM_Hub { const { TOKEN_ASSET_BASE_URI = EMPTY_LIST } = getTokenAssetBaseURLConstants(options.chainId) const checkSummedAddress = formatEthereumAddress(address) - if (isSameAddress(getTokenConstants(chainId).NATIVE_TOKEN_ADDRESS, checkSummedAddress)) { + if (isSameAddress(getTokenConstants(options.chainId).NATIVE_TOKEN_ADDRESS, checkSummedAddress)) { return TOKEN_ASSET_BASE_URI.map((x) => `${x}/info/logo.png`) } @@ -239,14 +239,22 @@ class Hub implements EVM_Hub { account: string, initial?: HubOptions, ): Promise>> { - return Rabby.getApprovedFungibleTokenSpenders(chainId, account) + const options = this.getOptions(initial, { + chainId, + account, + }) + return Rabby.getApprovedFungibleTokenSpenders(options.chainId, options.account) } async getApprovedNonFungibleContracts( chainId: ChainId, account: string, initial?: HubOptions, ): Promise>> { - return Rabby.getApprovedNonFungibleContracts(chainId, account) + const options = this.getOptions(initial, { + chainId, + account, + }) + return Rabby.getApprovedNonFungibleContracts(options.chainId, options.account) } async getFungibleAsset( @@ -306,7 +314,9 @@ class Hub implements EVM_Hub { account: string, initial?: HubOptions, ): Promise>> { - const options = this.getOptions(initial) + const options = this.getOptions(initial, { + account, + }) const providers = this.getProviders( { [SourceType.OpenSea]: OpenSea, @@ -318,7 +328,7 @@ class Hub implements EVM_Hub { initial, ) return attemptUntil( - providers.map((x) => () => x.getAssets(account, options)), + providers.map((x) => () => x.getAssets(options.account, options)), createPageable(EMPTY_LIST, createIndicator(options.indicator)), ) } diff --git a/packages/web3-providers/src/MagicEden/index.ts b/packages/web3-providers/src/MagicEden/index.ts index ff60a9b6a3b1..a2701a81b26c 100644 --- a/packages/web3-providers/src/MagicEden/index.ts +++ b/packages/web3-providers/src/MagicEden/index.ts @@ -223,12 +223,12 @@ export class MagicEdenAPI implements NonFungibleTokenAPI.Provider = {}) { const activities = await fetchFromMagicEden( urlcat('/v2/tokens/:mint_address/activities', { - mint_address: tokenId, + mint_address: address, offset: (indicator?.index ?? 0) * size, limit: size, }), ) - return (activities || []).map((activity) => { + const events = (activities || []).map((activity) => { return { id: activity.signature, chainId: ChainId.Mainnet, @@ -245,28 +245,38 @@ export class MagicEdenAPI implements NonFungibleTokenAPI.Provider = {}) { + async getOrders(address: string, tokenId: string, side: OrderSide, { indicator, size }: HubOptions = {}) { const limit = size || 20 - const offset = (indicator?.index ?? 0) * limit const offers = await fetchFromMagicEden( urlcat('/tokens/:mint_address/offer_received', { - mint_address: mintAddress, + mint_address: address, side, - offset, + offset: (indicator?.index ?? 0) * limit, limit, }), ) - return (offers || []).map((offer) => { + const orders = (offers || []).map((offer) => { return { id: offer.pdaAddress, chainId: ChainId.Mainnet, + side, quantity: '1', // TODO's assetPermalink: '', } }) + return createPageable( + orders, + createIndicator(indicator), + orders.length === size ? createNextIndicator(indicator) : undefined, + ) } async getCollections(symbol: string, { indicator, size }: HubOptions = {}) {