Skip to content

Commit

Permalink
Merge pull request #37 from Crypto-Phunks/feature/nftx_mevbot
Browse files Browse the repository at this point in the history
implemented proper mevbot transaction support, including mevbot swapp…
  • Loading branch information
tat2bu authored Aug 26, 2023
2 parents 7dee070 + 0d74258 commit e1d785e
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 22 deletions.
3 changes: 2 additions & 1 deletion src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ import { PhunksAuctionHouseService } from './extensions/phunks.auction.house.ext
export class AppModule {

constructor(private saleService:Erc721SalesService) {
if (!global.doNotStartAutomatically)
if (!global.doNotStartAutomatically) {
this.saleService.startProvider()
}
}
}
45 changes: 45 additions & 0 deletions src/erc721sales.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,50 @@ describe('Erc721SalesService', () => {
expect(service).toBeDefined()
});

it('0x5464119779617b8b270bd0defa3cc4aa69661afb71d9360b82ae7247d56aa231 - NFTX sale to vault', async () => {
await delay(COOLDOWN_BETWEEN_TESTS)
const provider = service.getWeb3Provider()
config.contract_address = '0xf07468eAd8cf26c752C676E43C814FEe9c8CF402'
const tokenContract = new ethers.Contract('0xf07468eAd8cf26c752C676E43C814FEe9c8CF402', erc721abi, provider);
let filter = tokenContract.filters.Transfer();
const startingBlock = 17994239
const events = await tokenContract.queryFilter(filter,
startingBlock,
startingBlock+1)
const results = (await Promise.all(events.map(async (e) => await service.getTransactionDetails(e)))).filter(r => r !== undefined)

let logs = ''
results.forEach(r => {
logs += `${r.tokenId} sold for ${r.alternateValue} to ${r.to}\n`
expect(r.alternateValue).toBe(0.265)
})
expect(results.length).toBe(1)

console.log(logs)
})

it('0xa13c09a4b0dc88f5e1914aca92675a2f19498d173d0ea2ada5df4652467b9e5b - nftx transaction involving swap', async () => {
await delay(COOLDOWN_BETWEEN_TESTS)
const provider = service.getWeb3Provider()
config.contract_address = '0xf07468eAd8cf26c752C676E43C814FEe9c8CF402'
const tokenContract = new ethers.Contract('0xf07468eAd8cf26c752C676E43C814FEe9c8CF402', erc721abi, provider);
let filter = tokenContract.filters.Transfer();
const startingBlock = 17994239
const events = await tokenContract.queryFilter(filter,
startingBlock,
startingBlock+1)
const results = await Promise.all(events.map(async (e) => await service.getTransactionDetails(e)))
//expect(results[0].alternateValue).toBe(0.31)
let logs = ''
results.filter(r => r !== undefined).forEach(r => {
console.log(r)
logs += `${r.tokenId} sold for ${r.alternateValue}\n`
expect(r.alternateValue).toBe(0.3205)
})

console.log(logs)
})

it('0xa13c09a4b0dc88f5e1914aca92675a2f19498d173d0ea2ada5df4652467b9e5b - nftx transaction involving swap', async () => {
await delay(COOLDOWN_BETWEEN_TESTS)
const provider = service.getWeb3Provider()
Expand All @@ -45,6 +89,7 @@ describe('Erc721SalesService', () => {
//expect(results[0].alternateValue).toBe(0.31)
let logs = ''
results.forEach(r => {
console.log(r)
logs += `${r.tokenId} sold for ${r.alternateValue}\n`
expect(r.alternateValue).toBe(0.3205)
})
Expand Down
21 changes: 13 additions & 8 deletions src/erc721sales.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ const blurBiddingContractAddress = '0x0000000000a39bb272e79075ade125fd351887ac';

const cargoTopicIdentifier = '0x5535fa724c02f50c6fb4300412f937dbcdf655b0ebd4ecaca9a0d377d0c0d9cc'
const raribleTopicIdentifier = '0x268820db288a211986b26a8fda86b1e0046281b21206936bb0e61c67b5c79ef4'
const botMevAddress = '0x00000000000A6D473a66abe3DBAab9E1388223Bd'
const nftxVaultBeaconProxyAddress = '0xB39185e33E8c28e0BB3DbBCe24DA5dEA6379Ae91'

const looksInterface = new ethers.Interface(looksRareABI);
const looksInterfaceV2 = new ethers.Interface(looksRareABIv2);
Expand Down Expand Up @@ -58,7 +60,7 @@ export class Erc721SalesService extends BaseService {

// Listen for Transfer event
this.provider.on({ address: config.contract_address, topics: [topics] }, (event) => {
this.getTransactionDetails(event).then((res) => {
this.getTransactionDetails(event, false, false, true).then((res) => {
if (!res) return
// Only tweet transfers with value (Ignore w2w transfers)
if (res?.ether || res?.alternateValue) this.dispatch(res);
Expand All @@ -69,7 +71,7 @@ export class Erc721SalesService extends BaseService {

}

async getTransactionDetails(tx: any, ignoreENS:boolean=false, ignoreNftxSwaps:boolean=true, ): Promise<any> {
async getTransactionDetails(tx: any, ignoreENS:boolean=false, ignoreNftxSwaps:boolean=true, ignoreContracts:boolean=true): Promise<any> {
// uncomment this to test a specific transaction
// if (tx.transactionHash !== '0xcee5c725e2234fd0704e1408cdf7f71d881e67f8bf5d6696a98fdd7c0bcf52f3') return;

Expand All @@ -93,15 +95,14 @@ export class Erc721SalesService extends BaseService {

// ignore internal transfers to contract, another transfer event will handle this
// transaction afterward (the one that'll go to the buyer wallet)
/*
const code = await this.provider.getCode(to)
we need this for stats
if (code !== '0x') {
// the ignoreContracts flag make the MEV bots like transaction ignored by the twitter
// bot, but not for statistics
if (to !== nftxVaultBeaconProxyAddress && code !== '0x' && ignoreContracts) {
logger.info(`contract detected for ${tx.transactionHash} event index ${tx.index}`)
return
}
*/


// not an erc721 transfer
if (!tx?.topics[3]) return

Expand Down Expand Up @@ -323,7 +324,11 @@ export class Erc721SalesService extends BaseService {
// count the number of tokens transfered
tokenCount = receipt.logs
.filter(l => l.address.toLowerCase() === config.contract_address.toLowerCase() &&
l.topics[0].toLowerCase() === '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef').length
l.topics[0].toLowerCase() === '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef')
.map(l => l.topics[3])
// take unique value
.filter((value, index, array) => array.indexOf(value) === index)
.length
}
alternateValue = parseFloat(NFTX[0].toString())/tokenCount/1000;
} else if (NLL.length) {
Expand Down
32 changes: 19 additions & 13 deletions src/extensions/statistics.extension.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,19 +153,22 @@ export class StatisticsService extends BaseService {
)

const guildIds = config.discord_guild_ids.split(',')
const commands = [
status.toJSON(),
userStats.toJSON(),
topTraders.toJSON(),
volumeStats.toJSON(),
graphStats.toJSON(),
checkTransaction.toJSON(),
indexTransaction.toJSON(),
ownedTokens.toJSON() ]
if (process.env.DEBUG_MODE === 'true') {
commands.push(sample.toJSON())
}
guildIds.forEach(async (guildId) => {
await rest.put(
Routes.applicationGuildCommands(config.discord_client_id, guildId),
{ body: [
// sample.toJSON(),
status.toJSON(),
userStats.toJSON(),
topTraders.toJSON(),
volumeStats.toJSON(),
graphStats.toJSON(),
checkTransaction.toJSON(),
indexTransaction.toJSON(),
ownedTokens.toJSON()] },
{ body: commands },
);
})

Expand Down Expand Up @@ -392,13 +395,16 @@ Amount: ${'Ξ'+(Math.floor(r.amount*100)/100).toFixed(2)}`)
}

getOwnedTokens(wallet:string) {
const sql = `select distinct token_id from
const sql = `select token_id,
ceil(JULIANDAY('now') -
JULIANDAY((select max(tx_date) from events e2 where e2.token_id = a.token_id))) owned_since
from (select distinct token_id from
(select distinct token_id,
last_value(to_wallet) over (
partition by token_id order by tx_date
RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) owner
from events) a
where lower(a.owner) = lower(@wallet)`
where lower(a.owner) = lower(@wallet)) a`
const result = this.db.prepare(sql).all({wallet})
return result
}
Expand Down Expand Up @@ -577,7 +583,7 @@ getOwnedTokens(wallet:string) {
await delay(500)
const results = await Promise.all(elements
.filter(e => e !== undefined)
.map(async (e) => this.erc721service.getTransactionDetails(e, true, false)))
.map(async (e) => this.erc721service.getTransactionDetails(e, true, false, false)))
for (let result of results) {
if (!result) continue
if (!result.alternateValue && result.ether)
Expand Down

0 comments on commit e1d785e

Please sign in to comment.