Skip to content

Commit 85ab5ab

Browse files
authored
Merge pull request #318 from pedromcunha/master
Add Relay Bridge
2 parents 7347cd2 + 35affb8 commit 85ab5ab

File tree

5 files changed

+486
-1
lines changed

5 files changed

+486
-1
lines changed

src/adapters/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ import hyperlane from "./hyperlane";
7575
import wormhole from "./wormhole";
7676
import thresholdnetwork from "./threshold-network";
7777
import zircuit from "./zircuit";
78+
import relay from "./relay";
7879
import hyperliquid from "./hyperliquid";
7980
import flyover from "./rootstock-flyover";
8081

@@ -155,6 +156,7 @@ export default {
155156
wormhole,
156157
thresholdnetwork,
157158
zircuit,
159+
relay,
158160
hyperliquid,
159161
flyover
160162
} as {

src/adapters/relay/index.ts

+218
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
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

Comments
 (0)