Skip to content
This repository was archived by the owner on Feb 2, 2024. It is now read-only.

Hackaton/nodes and edges #531

Merged
merged 4 commits into from
Jun 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/api/tenderly/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './tenderlyApi'

export type { PublicTrade as Trade, Transfer, Account } from './types'
export * from './types'
4 changes: 2 additions & 2 deletions src/api/tenderly/tenderlyApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,10 @@ export async function getTransactionContracts(networkId: Network, txHash: string
export async function getTradesAndTransfers(networkId: Network, txHash: string): Promise<TxTradesAndTransfers> {
const trace = await _fetchTrace(networkId, txHash)

return traceToTransfersTrades(trace)
return traceToTransfersAndTrades(trace)
}

export function traceToTransfersTrades(trace: Trace): TxTradesAndTransfers {
export function traceToTransfersAndTrades(trace: Trace): TxTradesAndTransfers {
const transfers: Array<Transfer> = []
const trades: Array<Trade> = []

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import { Trade, Transfer } from 'api/tenderly'

const ADDRESSES_TO_IGNORE = new Set()
// CoW Protocol settlement contract
ADDRESSES_TO_IGNORE.add('0x9008d19f58aabd9ed0d60971565aa8510560ab41')
// ETH Flow contract
ADDRESSES_TO_IGNORE.add('0x40a50cf069e992aa4536211b23f286ef88752187')

export type ContractTrade = {
address: string
sellTokens: string[]
buyTokens: string[]
}

export function getContractTrades(trades: Trade[], transfers: Transfer[]): ContractTrade[] {
const userAddresses = new Set<string>()
const contractAddresses = new Set<string>()

// Build a list of addresses that are involved in trades
// Note: at this point we don't have the receivers - if different from owner
trades.forEach((trade) => userAddresses.add(trade.owner))

// Build list of contract addresses based on trades, which are not traders
// nor part of the ignored set (CoW Protocol itself, special contracts etc)
transfers.forEach((transfer) => {
;[transfer.from, transfer.to].forEach((address) => {
if (!userAddresses.has(address) && !ADDRESSES_TO_IGNORE.has(address)) {
contractAddresses.add(address)
}
})
})

// Get contract trades
return Array.from(contractAddresses).map((address) => {
const sellTokens: string[] = []
const buyTokens: string[] = []

transfers.forEach((transfer) => {
if (transfer.from === address) {
sellTokens.push(transfer.token)
} else if (transfer.to === address) {
buyTokens.push(transfer.token)
}
})

return { address, sellTokens, buyTokens }
})
}

// TODO: these types might overlap with existing ones, consider reusing them
export type Node = {
address: string
isHyperNode?: boolean
}

export type Edge = {
from: string
to: string
}

export type NodesAndEdges = {
nodes: Node[]
edges: Edge[]
}

export function getNotesAndEdges(userTrades: Trade[], contractTrades: ContractTrade[]): NodesAndEdges {
const nodes: Record<string, { address: string; isHyperNode?: boolean }> = {}
const edges: { from: string; to: string }[] = []

userTrades.forEach((trade) => {
nodes[trade.sellToken] = { address: trade.sellToken }
nodes[trade.sellToken] = { address: trade.buyToken }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just from pattern matching: nodes[trade.buyToken] in the second statement.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!


// one edge for each user trade
edges.push({ from: trade.sellToken, to: trade.buyToken })
})

contractTrades.forEach((trade) => {
// add all sellTokens from contract trades to nodes
trade.sellTokens.forEach((address) => (nodes[address] = { address }))
// add all buyTokens from contract trades to nodes
trade.buyTokens.forEach((address) => (nodes[address] = { address }))

if (trade.sellTokens.length === 1 && trade.buyTokens.length === 1) {
// no need to add a new node
// normal edge for normal contract interaction
edges.push({ from: trade.sellTokens[0], to: trade.buyTokens[0] })
} else if (trade.sellTokens.length > 1 || trade.buyTokens.length > 1) {
// if there are more than one sellToken or buyToken, the contract becomes a node
nodes[trade.address] = { address: trade.address, isHyperNode: true }

// one edge for each sellToken
trade.sellTokens.forEach((address) => edges.push({ from: address, to: trade.address }))
// one edge for each buyToken
trade.buyTokens.forEach((address) => edges.push({ from: trade.address, to: address }))
}
})

return {
nodes: Object.values(nodes),
edges,
}
}