From d69bdf601bfee2b51f57346020ffd8d96c51bd1e Mon Sep 17 00:00:00 2001 From: g1nt0ki <99907941+g1nt0ki@users.noreply.github.com> Date: Sat, 23 Nov 2024 16:52:49 +0100 Subject: [PATCH 1/4] fix opensea --- fees/opensea/index.ts | 25 +--------- fees/opensea/seaport.ts | 103 ++++++++-------------------------------- 2 files changed, 21 insertions(+), 107 deletions(-) diff --git a/fees/opensea/index.ts b/fees/opensea/index.ts index bbbc83703b..fc956895b1 100644 --- a/fees/opensea/index.ts +++ b/fees/opensea/index.ts @@ -1,31 +1,10 @@ -import * as sdk from "@defillama/sdk"; import { Adapter, DISABLED_ADAPTER_KEY } from "../../adapters/types"; -import type { ChainEndpoints } from "../../adapters/types" -import { Chain } from '@defillama/sdk/build/general'; -import { getTimestampAtStartOfDayUTC } from "../../utils/date"; import { CHAIN } from "../../helpers/chains"; import { fetch } from "./seaport"; import disabledAdapter from "../../helpers/disabledAdapter"; -const seaportEndpoints = { - [CHAIN.ETHEREUM]: sdk.graph.modifyEndpoint('kGCuz7xhxMuyRSk8QdnUgijUEqgvhGwkzAVHkbYedCk'), -} - -const graphs = (_: ChainEndpoints) => { - return (_: Chain) => { - return async (timestamp: number) => { - const todaysTimestamp = getTimestampAtStartOfDayUTC(timestamp); - const fees = await fetch(timestamp); - return { - ...fees, - timestamp: todaysTimestamp, - } - }; - }; -}; - const adapter: Adapter = { - version: 1, + version: 2, breakdown: { v1: { [DISABLED_ADAPTER_KEY]: disabledAdapter, @@ -37,7 +16,7 @@ const adapter: Adapter = { }, seaport: { [CHAIN.ETHEREUM]: { - fetch: graphs(seaportEndpoints)(CHAIN.ETHEREUM), + fetch: fetch, start: '2022-06-12', }, } diff --git a/fees/opensea/seaport.ts b/fees/opensea/seaport.ts index 06b24f2451..daa64d5566 100644 --- a/fees/opensea/seaport.ts +++ b/fees/opensea/seaport.ts @@ -1,99 +1,34 @@ -import ADDRESSES from '../../helpers/coreAssets.json' -import * as sdk from "@defillama/sdk"; -import { getBlock } from "../../helpers/getBlock"; -import { getPrices } from "../../utils/prices"; -import { CHAIN } from "../../helpers/chains"; -import { FetchResultFees } from "../../adapters/types"; +import { FetchOptions, } from "../../adapters/types"; -interface ILog { - address: string; - data: string; - transactionHash: string; - topics: string[]; -} - -interface IAmount { - creator_fee: number; - marketplace_fee: number; - isHaveMPFees: boolean; -} - -interface IConrtact { - adddress: string; - startBlcok: number; -} const contract_v1_4 = '0x00000000000001ad428e4906ae43d8f9852d0dd6'; const contract_v1_5 = '0x00000000000000adc04c56bf30ac9d3c0aaf14dc'; +const contract_v1_6 = '0x0000000000000068F116a894984e2DB1123eB395'; -const contracts: IConrtact[] = [ - { - adddress: contract_v1_4, - startBlcok: 16655960, - }, - { - adddress: contract_v1_5, - startBlcok: 17129405, - } -] -const topic0 = '0x9d9af8e38d66c62e2c12f0225249fd9d721c54b83f48d9352c97c6cacdcb6f31'; const event_order_fulfilled = "event OrderFulfilled(bytes32 orderHash, address indexed offerer, address indexed zone, address recipient, (uint8 itemType, address token, uint256 identifier, uint256 amount)[] offer, (uint8 itemType, address token, uint256 identifier, uint256 amount, address recipient)[] consideration)" -const fees_collector = '0x0000a26b00c1f0df003000390027140000faa719'; +const fees_collectors = new Set(['0x0000a26b00c1f0df003000390027140000faa719', '0x31314e41E743A638FD485d537F4a2B5F57D662bb', '0x1208e7F7AED9d39Ed25ef582B8933e4a1D0DA6af'].map(i => i.toLowerCase())); + +export const fetch = async ({ createBalances, getLogs, }: FetchOptions) => { + const dailyFees = createBalances() + const dailyRevenue = createBalances() -export const fetch = async (timestamp: number): Promise => { - const fromTimestamp = timestamp - 60 * 60 * 24 - const toTimestamp = timestamp - const fromBlock = (await getBlock(fromTimestamp, CHAIN.ETHEREUM, {})); - const toBlock = (await getBlock(toTimestamp, CHAIN.ETHEREUM, {})); - const logs: ILog[] = (await Promise.all(contracts.filter(e => e.startBlcok <= fromBlock).map((contract: IConrtact) => sdk.getEventLogs({ - target: contract.adddress, - toBlock: toBlock, - fromBlock: fromBlock, - chain: CHAIN.ETHEREUM, - topics: [topic0] - })))).flat() as ILog[]; + const logs = await getLogs({ targets: [contract_v1_4, contract_v1_5, contract_v1_6], eventAbi: event_order_fulfilled, }) - const fes_raw: IAmount[] = logs.filter(e => e.data.length === 1602) - .map((e: ILog) => { - const data = e.data.replace('0x', ''); - const fees_1 = Number('0x' + data.slice(18 * 64, (18 * 64) + 64)) / 10 ** 18; - const address_1 = data.slice((19 * 64), (19 * 64) + 64); - const contract_address_1 = '0x' + address_1.slice(24, address_1.length); + logs.forEach(log => { + if (log.consideration.length < 2) return; + const biggestValue = log.consideration.reduce((a: any, b: any) => a.amount > b.amount ? a : b).amount - const fees_2 = Number('0x' + data.slice(23 * 64, (23 * 64) + 64)) / 10 ** 18; - const address_2 = data.slice((24 * 64), (24 * 64) + 64); - const contract_address_2 = '0x' + address_2.slice(24, address_2.length); - const min = Math.min(fees_1, fees_2); - const max = Math.max(fees_1, fees_2); - const isHaveMPFees = [contract_address_1.toLowerCase(), contract_address_2.toLowerCase()].includes(fees_collector.toLowerCase()); - return { - creator_fee: max, - marketplace_fee: min, - isHaveMPFees + log.consideration.forEach((consideration: any) => { + if (consideration.amount >= biggestValue) return; // this is sent to the NFT owner, rest are fees + dailyFees.add(consideration.token, consideration.amount) + if (fees_collectors.has(consideration.recipient.toLowerCase())) { + dailyRevenue.add(consideration.token, consideration.amount) } }) + }) - const marketplace_fee = fes_raw - .filter(e => e.isHaveMPFees) - .map(e => e.marketplace_fee as number) - .filter((e) => !isNaN(e)) - .filter(e => e < 100) - .reduce((a: number, b: number) => a + b, 0) - - const creator_fee = fes_raw.map(e => e.creator_fee as number) - .filter((e) => !isNaN(e)) - .filter(e => e < 100) - .reduce((a: number, b: number) => a + b, 0) - - const fees = (marketplace_fee + creator_fee); - const rev = (marketplace_fee); - const ethAddress = "ethereum:" + ADDRESSES.null; - const ethPrice = (await getPrices([ethAddress], timestamp))[ethAddress].price; - const dailyFees = (fees * ethPrice) - const dailyRevenue = (rev * ethPrice) return { - dailyFees: `${dailyFees}`, - dailyRevenue: `${dailyRevenue}`, - timestamp + dailyFees, dailyRevenue, } + } From b4dc14e6bc15f08e6d2daf1a5241f30b8716fe47 Mon Sep 17 00:00:00 2001 From: g1nt0ki <99907941+g1nt0ki@users.noreply.github.com> Date: Sat, 23 Nov 2024 17:40:17 +0100 Subject: [PATCH 2/4] opensea track more chains --- fees/opensea/index.ts | 13 ++++++------- fees/opensea/seaport.ts | 26 +++++++++++++++++++++----- 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/fees/opensea/index.ts b/fees/opensea/index.ts index fc956895b1..99155acdc0 100644 --- a/fees/opensea/index.ts +++ b/fees/opensea/index.ts @@ -1,7 +1,8 @@ import { Adapter, DISABLED_ADAPTER_KEY } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import { fetch } from "./seaport"; +import { fetch, config } from "./seaport"; import disabledAdapter from "../../helpers/disabledAdapter"; +const seaportConfig = { fetch, start: '2022-06-12', } const adapter: Adapter = { version: 2, @@ -14,12 +15,10 @@ const adapter: Adapter = { [DISABLED_ADAPTER_KEY]: disabledAdapter, [CHAIN.ETHEREUM]: disabledAdapter }, - seaport: { - [CHAIN.ETHEREUM]: { - fetch: fetch, - start: '2022-06-12', - }, - } + seaport: Object.keys(config).reduce((acc, chain) => { + acc[chain] = seaportConfig + return acc + }, {}), } } diff --git a/fees/opensea/seaport.ts b/fees/opensea/seaport.ts index daa64d5566..e14698a875 100644 --- a/fees/opensea/seaport.ts +++ b/fees/opensea/seaport.ts @@ -1,18 +1,34 @@ import { FetchOptions, } from "../../adapters/types"; - const contract_v1_4 = '0x00000000000001ad428e4906ae43d8f9852d0dd6'; const contract_v1_5 = '0x00000000000000adc04c56bf30ac9d3c0aaf14dc'; const contract_v1_6 = '0x0000000000000068F116a894984e2DB1123eB395'; +const defaultSeaports = [contract_v1_4, contract_v1_5, contract_v1_6] +const defaltFeeCollectors = ['0x0000a26b00c1f0df003000390027140000faa719'] const event_order_fulfilled = "event OrderFulfilled(bytes32 orderHash, address indexed offerer, address indexed zone, address recipient, (uint8 itemType, address token, uint256 identifier, uint256 amount)[] offer, (uint8 itemType, address token, uint256 identifier, uint256 amount, address recipient)[] consideration)" -const fees_collectors = new Set(['0x0000a26b00c1f0df003000390027140000faa719', '0x31314e41E743A638FD485d537F4a2B5F57D662bb', '0x1208e7F7AED9d39Ed25ef582B8933e4a1D0DA6af'].map(i => i.toLowerCase())); -export const fetch = async ({ createBalances, getLogs, }: FetchOptions) => { +export const config = { + ethereum: { + fees_collectors: [...defaltFeeCollectors, '0x31314e41E743A638FD485d537F4a2B5F57D662bb', '0x1208e7F7AED9d39Ed25ef582B8933e4a1D0DA6af'] + }, + arbitrum: {}, + avax: {}, + base: {}, + blast: {}, + klaytn: {}, + optimism: {}, + polygon: {}, + zora: {}, +} + +export const fetch = async ({ createBalances, getLogs, chain, }: FetchOptions) => { const dailyFees = createBalances() const dailyRevenue = createBalances() + const { seaports = defaultSeaports, fees_collectors = defaltFeeCollectors } = config[chain] + const feeCollectorSet = new Set(fees_collectors.map(i => i.toLowerCase())); - const logs = await getLogs({ targets: [contract_v1_4, contract_v1_5, contract_v1_6], eventAbi: event_order_fulfilled, }) + const logs = await getLogs({ targets: seaports, eventAbi: event_order_fulfilled, }) logs.forEach(log => { if (log.consideration.length < 2) return; @@ -21,7 +37,7 @@ export const fetch = async ({ createBalances, getLogs, }: FetchOptions) => { log.consideration.forEach((consideration: any) => { if (consideration.amount >= biggestValue) return; // this is sent to the NFT owner, rest are fees dailyFees.add(consideration.token, consideration.amount) - if (fees_collectors.has(consideration.recipient.toLowerCase())) { + if (feeCollectorSet.has(consideration.recipient.toLowerCase())) { dailyRevenue.add(consideration.token, consideration.amount) } }) From ac5a24f407be9b6fc3c8122d582bd3967ad53b9a Mon Sep 17 00:00:00 2001 From: g1nt0ki <99907941+g1nt0ki@users.noreply.github.com> Date: Sat, 23 Nov 2024 17:55:08 +0100 Subject: [PATCH 3/4] opensea: update fee logic --- fees/opensea/seaport.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fees/opensea/seaport.ts b/fees/opensea/seaport.ts index e14698a875..99a0255282 100644 --- a/fees/opensea/seaport.ts +++ b/fees/opensea/seaport.ts @@ -32,10 +32,10 @@ export const fetch = async ({ createBalances, getLogs, chain, }: FetchOptions) = logs.forEach(log => { if (log.consideration.length < 2) return; - const biggestValue = log.consideration.reduce((a: any, b: any) => a.amount > b.amount ? a : b).amount + const biggestValue = log.consideration.reduce((a: any, b: any) => a.amount > b.amount ? a : b) log.consideration.forEach((consideration: any) => { - if (consideration.amount >= biggestValue) return; // this is sent to the NFT owner, rest are fees + if (consideration.recipient === biggestValue.recipient) return; // this is sent to the NFT owner, rest are fees dailyFees.add(consideration.token, consideration.amount) if (feeCollectorSet.has(consideration.recipient.toLowerCase())) { dailyRevenue.add(consideration.token, consideration.amount) From a108a2a45e3be4c103e282de39208111c75e5ce9 Mon Sep 17 00:00:00 2001 From: g1nt0ki <99907941+g1nt0ki@users.noreply.github.com> Date: Sat, 23 Nov 2024 18:11:18 +0100 Subject: [PATCH 4/4] fix opensea bug: exclude NFT --- fees/opensea/seaport.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/fees/opensea/seaport.ts b/fees/opensea/seaport.ts index 99a0255282..2fa7a0b71b 100644 --- a/fees/opensea/seaport.ts +++ b/fees/opensea/seaport.ts @@ -31,10 +31,11 @@ export const fetch = async ({ createBalances, getLogs, chain, }: FetchOptions) = const logs = await getLogs({ targets: seaports, eventAbi: event_order_fulfilled, }) logs.forEach(log => { - if (log.consideration.length < 2) return; - const biggestValue = log.consideration.reduce((a: any, b: any) => a.amount > b.amount ? a : b) + const recipients = log.consideration.filter((i: any) => +i.itemType.toString() < 2) // exclude NFTs (ERC721 and ERC1155) + if (recipients.length < 2) return; + const biggestValue = recipients.reduce((a: any, b: any) => a.amount > b.amount ? a : b) - log.consideration.forEach((consideration: any) => { + recipients.forEach((consideration: any) => { if (consideration.recipient === biggestValue.recipient) return; // this is sent to the NFT owner, rest are fees dailyFees.add(consideration.token, consideration.amount) if (feeCollectorSet.has(consideration.recipient.toLowerCase())) {