All files / src/parsers opensea.seaport.parser.ts

100% Statements 40/40
100% Branches 19/19
100% Functions 12/12
100% Lines 34/34

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 621x     1x 1x   1x 1x   1x   1x         47x 47x 45x 47x 43x       92x 1671x   18x   21x 14x   3x 3x     15x 6x 6x     9x 9x     9x   9x 2x   11x   7x 7x 4x   7x 7x   1671x    
import { AbiCoder, Log, TransactionResponse, ethers } from "ethers";
import { LogParser } from "./parser.definition";
import { config } from "../config";
import openseaSeaportABI from '../abi/seaportABI.json';
import { createLogger } from "../logging.utils";
 
const seaportInterface = new ethers.Interface(openseaSeaportABI)
const logger = createLogger('openseaseaport.parser')
 
export class OpenSeaSeaportParser implements LogParser {
    
    platform: string = 'opensea';
    
    parseLogs(transaction:TransactionResponse, logs: Log[], tokenId: string): number {
        
 
        let result = this.decode(transaction, logs, tokenId, false)
        if (result.length === 0)
          result = this.decode(transaction, logs, tokenId, true)
        if (result.length) return parseFloat(result.reduce((previous,current) => previous + current, BigInt(0)).toString())/1000;
        return undefined
    }
 
    decode(transaction:TransactionResponse, logs: Log[], tokenId: string, allowUnknownOfferer:boolean) {
      return logs.map((log: any) => {
        if (log.topics[0].toLowerCase() === '0x9d9af8e38d66c62e2c12f0225249fd9d721c54b83f48d9352c97c6cacdcb6f31') {
 
          const logDescription = seaportInterface.parseLog(log);
          
          if (logDescription.args.offer.filter( o => o.identifier.toString() !== '0').length && 
              logDescription.args.consideration.filter( o => o.identifier.toString() !== '0').length) {
            // complex opensea trade detected, ignore
            logger.info(`complex opensea trade detected for ${transaction.hash} log ${log.index}, ignoring...`)
            return
          }
 
          if (!allowUnknownOfferer && transaction.from !== logDescription.args.offerer) {
            logger.info(`offerer is not the transaction emitter, ${transaction.hash} log ${log.index}, ignoring...`)
            return
          }
                      
          const matchingOffers = logDescription.args.offer.filter(
            o => o.identifier.toString() === tokenId || 
            o.identifier.toString() === '0');
          
          const tokenCount = logDescription.args.offer.length;
          
          if (matchingOffers.length === 0) {
            return
          }
          let amounts = logDescription.args.consideration.map(c => BigInt(c.amount))
          // add weth
          const wethOffers = matchingOffers.map(o => o.token === '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2' && o.amount > 0 ? BigInt(o.amount) : BigInt(0));
          if (wethOffers.length > 0 && wethOffers[0] != BigInt(0)) {
            amounts = wethOffers
          }
          const amount = amounts.reduce((previous,current) => previous + current, BigInt(0))
          return amount / BigInt('1000000000000000') / BigInt(tokenCount)
        }
      }).filter(n => n !== undefined)        
    }
}