|
| 1 | +import { BridgeAdapter } from "../../helpers/bridgeAdapter.type"; |
| 2 | +import fetch from "node-fetch"; |
| 3 | +import { EventData } from "../../utils/types"; |
| 4 | +import { RelayRequestsResponse } from "./type"; |
| 5 | +const retry = require("async-retry"); |
| 6 | + |
| 7 | +/** |
| 8 | + * Relay is a cross-chain payments system that enables low cost instant bridging and cross-chain execution. |
| 9 | + * Contract addresses: https://docs.relay.link/resources/contract-addresses |
| 10 | + * |
| 11 | + * |
| 12 | + */ |
| 13 | + |
| 14 | +const startingBlocks: Record<string, number> = { |
| 15 | + 1: 18976112, |
| 16 | + 10: 114647896, |
| 17 | + 56: 39739873, |
| 18 | + 100: 33619680, |
| 19 | + 137: 55172593, |
| 20 | + 185: 3417903, |
| 21 | + 288: 2353048, |
| 22 | + 324: 25006838, |
| 23 | + 360: 2691201, |
| 24 | + 480: 3466510, |
| 25 | + 690: 254553, |
| 26 | + 1101: 12491343, |
| 27 | + 1135: 761002, |
| 28 | + 1329: 118912096, |
| 29 | + 2741: 4116, |
| 30 | + 2911: 2136055, |
| 31 | + 4321: 138647, |
| 32 | + 5000: 72911632, |
| 33 | + 5112: 1462668, |
| 34 | + 7560: 896262, |
| 35 | + 8333: 144055, |
| 36 | + 8453: 9046270, |
| 37 | + 17071: 58343, |
| 38 | + 33139: 636958, |
| 39 | + 33979: 238923, |
| 40 | + 34443: 7297896, |
| 41 | + 42161: 169028419, |
| 42 | + 42170: 38963884, |
| 43 | + 43114: 44583244, |
| 44 | + 55244: 30, |
| 45 | + 57073: 275058, |
| 46 | + 59144: 1814719, |
| 47 | + 60808: 275964, |
| 48 | + 70700: 19, |
| 49 | + 70701: 1543, |
| 50 | + 81457: 216675, |
| 51 | + 534352: 5560094, |
| 52 | + 543210: 1282, |
| 53 | + 660279: 4759873, |
| 54 | + 984122: 2655107, |
| 55 | + 7777777: 9094029, |
| 56 | + 8253038: 865885, |
| 57 | + 666666666: 1310814, |
| 58 | + 792703809: 279758248, |
| 59 | + 888888888: 1278785, |
| 60 | + 1380012617: 205727, |
| 61 | +}; |
| 62 | + |
| 63 | +const convertRequestToEvent = ( |
| 64 | + request: NonNullable<RelayRequestsResponse["requests"]>["0"] |
| 65 | +): { deposit?: EventData; withdraw?: EventData; depositChainId?: number; withdrawChainId?: number } => { |
| 66 | + const deposit = request.data?.metadata?.currencyIn; |
| 67 | + const withdraw = request.data?.metadata?.currencyOut; |
| 68 | + |
| 69 | + const depositTx = request.data?.inTxs?.[0]; |
| 70 | + const withdrawTx = request.data?.outTxs?.[0]; |
| 71 | + |
| 72 | + return { |
| 73 | + depositChainId: depositTx?.chainId, |
| 74 | + deposit: |
| 75 | + depositTx && depositTx.data && deposit |
| 76 | + ? { |
| 77 | + blockNumber: depositTx.block!, |
| 78 | + txHash: depositTx.hash as string, |
| 79 | + timestamp: depositTx.timestamp! * 1000, |
| 80 | + from: (depositTx.data as any).from |
| 81 | + ? (depositTx.data as any).from |
| 82 | + : depositTx.data |
| 83 | + ? (depositTx.data as any).signer |
| 84 | + : undefined, |
| 85 | + to: (depositTx.data as any).to |
| 86 | + ? (depositTx.data as any).to |
| 87 | + : withdrawTx?.data |
| 88 | + ? (withdrawTx.data as any).signer |
| 89 | + : undefined, |
| 90 | + token: deposit?.currency?.address!, |
| 91 | + amount: deposit?.amountUsd as any, |
| 92 | + isDeposit: true, |
| 93 | + isUSDVolume: true, |
| 94 | + } |
| 95 | + : undefined, |
| 96 | + withdrawChainId: withdrawTx?.chainId, |
| 97 | + withdraw: |
| 98 | + withdrawTx && withdrawTx.data && withdraw |
| 99 | + ? { |
| 100 | + blockNumber: withdrawTx.block!, |
| 101 | + txHash: withdrawTx.hash!, |
| 102 | + timestamp: withdrawTx.timestamp! * 1000, |
| 103 | + from: (withdrawTx.data as any).from |
| 104 | + ? (withdrawTx.data as any).from |
| 105 | + : withdrawTx.data |
| 106 | + ? (withdrawTx.data as any).signer |
| 107 | + : undefined, |
| 108 | + to: (withdrawTx.data as any).to ? (withdrawTx.data as any).to : request.data?.metadata?.recipient, |
| 109 | + token: withdraw?.currency?.address!, |
| 110 | + amount: withdraw?.amountUsd as any, |
| 111 | + isDeposit: false, |
| 112 | + isUSDVolume: true, |
| 113 | + } |
| 114 | + : undefined, |
| 115 | + }; |
| 116 | +}; |
| 117 | + |
| 118 | +const fetchRequests = async ( |
| 119 | + chainId: number, |
| 120 | + fromBlock: number, |
| 121 | + toBlock: number, |
| 122 | + continuation?: string |
| 123 | +): Promise<RelayRequestsResponse> => { |
| 124 | + let url = `https://api.relay.link/requests/v2?chainId=${chainId}&startBlock=${fromBlock}&endBlock=${toBlock}`; |
| 125 | + |
| 126 | + if (continuation) { |
| 127 | + url = `${url}&continuation=${continuation}`; |
| 128 | + } |
| 129 | + return retry(() => fetch(url).then((res) => res.json())); |
| 130 | +}; |
| 131 | + |
| 132 | +const fetchAllRequests = async ( |
| 133 | + chainId: number, |
| 134 | + fromBlock: number, |
| 135 | + toBlock: number |
| 136 | +): Promise<RelayRequestsResponse["requests"]> => { |
| 137 | + let allRequests: RelayRequestsResponse["requests"] = []; |
| 138 | + const response = await fetchRequests(chainId, fromBlock, toBlock); |
| 139 | + allRequests = [...(response.requests ?? [])]; |
| 140 | + let continuation = response.continuation; |
| 141 | + let maxRequests = 10000; |
| 142 | + let requestCount = 0; |
| 143 | + while (continuation !== undefined && requestCount < maxRequests) { |
| 144 | + const response = await fetchRequests(chainId, fromBlock, toBlock, continuation); |
| 145 | + continuation = response.continuation; |
| 146 | + allRequests = [...allRequests, ...(response.requests ?? [])]; |
| 147 | + } |
| 148 | + return allRequests; |
| 149 | +}; |
| 150 | + |
| 151 | +const constructParams = (chainId: number) => { |
| 152 | + return async (fromBlock: number, toBlock: number): Promise<EventData[]> => { |
| 153 | + //Performance optimization to limit empty requests |
| 154 | + const startingBlock = startingBlocks[chainId]; |
| 155 | + if (startingBlock !== undefined && toBlock < startingBlock) { |
| 156 | + return []; |
| 157 | + } |
| 158 | + const requests = await fetchAllRequests(chainId, fromBlock, toBlock); |
| 159 | + const events: EventData[] = []; |
| 160 | + requests?.forEach((request) => { |
| 161 | + const event = convertRequestToEvent(request); |
| 162 | + if (event.depositChainId === chainId && event.deposit) { |
| 163 | + events.push(event.deposit); |
| 164 | + } |
| 165 | + if (event.withdrawChainId === chainId && event.withdraw) { |
| 166 | + events.push(event.withdraw); |
| 167 | + } |
| 168 | + }); |
| 169 | + return events; |
| 170 | + }; |
| 171 | +}; |
| 172 | + |
| 173 | +const adapter: BridgeAdapter = { |
| 174 | + ethereum: constructParams(1), |
| 175 | + optimism: constructParams(10), |
| 176 | + bnb: constructParams(56), |
| 177 | + gnosis: constructParams(100), |
| 178 | + polygon: constructParams(137), |
| 179 | + mint: constructParams(185), |
| 180 | + boba: constructParams(288), |
| 181 | + zksync: constructParams(324), |
| 182 | + shape: constructParams(360), |
| 183 | + "world-chain": constructParams(480), |
| 184 | + redstone: constructParams(690), |
| 185 | + "polygon-zkevm": constructParams(1101), |
| 186 | + lisk: constructParams(1135), |
| 187 | + sei: constructParams(1329), |
| 188 | + hychain: constructParams(2911), |
| 189 | + mantle: constructParams(5000), |
| 190 | + ham: constructParams(5112), |
| 191 | + cyber: constructParams(7560), |
| 192 | + B3: constructParams(8333), |
| 193 | + base: constructParams(8453), |
| 194 | + arbitrum: constructParams(42161), |
| 195 | + "arbitrum-nova": constructParams(42170), |
| 196 | + avalanche: constructParams(43114), |
| 197 | + superposition: constructParams(55244), |
| 198 | + linea: constructParams(59144), |
| 199 | + bob: constructParams(60808), |
| 200 | + apex: constructParams(70700), |
| 201 | + boss: constructParams(70701), |
| 202 | + blast: constructParams(81457), |
| 203 | + scroll: constructParams(534352), |
| 204 | + "zero-network": constructParams(543210), |
| 205 | + xai: constructParams(660279), |
| 206 | + forma: constructParams(984122), |
| 207 | + solana: constructParams(792703809), |
| 208 | + ancient8: constructParams(888888888), |
| 209 | + rari: constructParams(1380012617), |
| 210 | + bitcoin: constructParams(8253038), |
| 211 | + degen: constructParams(666666666), |
| 212 | + funki: constructParams(33979), |
| 213 | + mode: constructParams(34443), |
| 214 | + "proof-of-play": constructParams(70700), |
| 215 | + "proof-of-play-boss": constructParams(70701), |
| 216 | +}; |
| 217 | + |
| 218 | +export default adapter; |
0 commit comments