@instadapp/interop-x 0.0.0-dev.ee3d74b → 0.0.0-dev.ef7acff

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. package/dist/package.json +3 -1
  2. package/dist/src/abi/index.js +2 -0
  3. package/dist/src/abi/instList.json +232 -0
  4. package/dist/src/api/index.js +7 -0
  5. package/dist/src/constants/addresses.js +4 -2
  6. package/dist/src/db/models/transaction.js +15 -7
  7. package/dist/src/errors/index.js +17 -0
  8. package/dist/src/gnosis/actions/aaveV2/source.js +15 -4
  9. package/dist/src/gnosis/actions/aaveV2/target.js +78 -0
  10. package/dist/src/index.js +1 -1
  11. package/dist/src/tasks/InteropX/{ProcessSubmitSubmitEvents.js → ProcessSubmitEvents.js} +29 -5
  12. package/dist/src/tasks/InteropX/ProcessValidateEvents.js +184 -0
  13. package/dist/src/tasks/InteropX/SyncLogExecuteEvents.js +112 -0
  14. package/dist/src/tasks/InteropX/SyncLogSubmitEvents.js +1 -0
  15. package/dist/src/tasks/InteropX/SyncLogValidateEvents.js +105 -0
  16. package/dist/src/tasks/index.js +13 -5
  17. package/dist/src/typechain/InstList.js +2 -0
  18. package/dist/src/typechain/factories/InstList__factory.js +249 -0
  19. package/dist/src/typechain/factories/index.js +3 -1
  20. package/dist/src/typechain/index.js +3 -1
  21. package/dist/src/utils/async.js +18 -0
  22. package/dist/src/utils/dsa.js +24 -0
  23. package/dist/src/utils/formatting.js +17 -0
  24. package/dist/src/utils/gnosis.js +62 -0
  25. package/dist/src/utils/http.js +10 -0
  26. package/dist/src/utils/index.js +21 -219
  27. package/dist/src/utils/interop.js +16 -0
  28. package/dist/src/utils/validate.js +23 -0
  29. package/dist/src/utils/web3.js +92 -0
  30. package/package.json +3 -1
  31. package/src/abi/index.ts +2 -0
  32. package/src/abi/instList.json +232 -0
  33. package/src/api/index.ts +8 -0
  34. package/src/constants/addresses.ts +5 -3
  35. package/src/db/models/transaction.ts +134 -80
  36. package/src/errors/index.ts +13 -0
  37. package/src/gnosis/actions/aaveV2/source.ts +19 -5
  38. package/src/gnosis/actions/aaveV2/target.ts +130 -2
  39. package/src/tasks/InteropX/{ProcessSubmitSubmitEvents.ts → ProcessSubmitEvents.ts} +35 -7
  40. package/src/tasks/InteropX/ProcessValidateEvents.ts +272 -0
  41. package/src/tasks/InteropX/SyncLogExecuteEvents.ts +160 -0
  42. package/src/tasks/InteropX/SyncLogSubmitEvents.ts +3 -4
  43. package/src/tasks/InteropX/SyncLogValidateEvents.ts +150 -0
  44. package/src/tasks/index.ts +16 -5
  45. package/src/typechain/InstList.ts +402 -0
  46. package/src/typechain/factories/InstList__factory.ts +253 -0
  47. package/src/typechain/factories/index.ts +1 -0
  48. package/src/typechain/index.ts +2 -0
  49. package/src/utils/async.ts +22 -0
  50. package/src/utils/dsa.ts +30 -0
  51. package/src/utils/formatting.ts +15 -0
  52. package/src/utils/gnosis.ts +123 -0
  53. package/src/utils/http.ts +6 -0
  54. package/src/utils/index.ts +8 -365
  55. package/src/utils/interop.ts +28 -0
  56. package/src/utils/validate.ts +24 -0
  57. package/src/utils/web3.ts +131 -0
@@ -0,0 +1,30 @@
1
+ import Web3EthAbi from "web3-eth-abi";
2
+ import { connectors } from "@/abi/connectors";
3
+
4
+ export const encodeConnectorMethod = (params: {
5
+ connector: string;
6
+ method: string;
7
+ args: string[];
8
+ }) => {
9
+ const connectorInterface = getInterface(
10
+ connectors.versions[2][params.connector],
11
+ params.method
12
+ );
13
+
14
+ if (!connectorInterface)
15
+ throw new Error(`ConnectorInterface '${params.method}' not found`);
16
+
17
+ //@ts-ignore
18
+ return Web3EthAbi.encodeFunctionCall(connectorInterface, params.args);
19
+ };
20
+
21
+ const getInterface = (abiItems: any[], method: string) => {
22
+ const abiItem = abiItems.find((abiItem) => abiItem.name === method);
23
+
24
+ if (!abiItem) {
25
+ console.error(`${method} is an invalid method.`);
26
+ return;
27
+ }
28
+
29
+ return abiItem;
30
+ };
@@ -0,0 +1,15 @@
1
+ export function shortenHash(hash: string, length: number = 4) {
2
+ if (!hash) return;
3
+
4
+ if (hash.length < 12) return hash;
5
+
6
+ const beginningChars = hash.startsWith("0x") ? length + 2 : length;
7
+
8
+ const shortened = hash.substr(0, beginningChars) + "…" + hash.substr(-length);
9
+
10
+ return shortened;
11
+ }
12
+
13
+ export function short(buffer: Buffer): string {
14
+ return buffer.toString("hex").slice(0, 8) + "...";
15
+ }
@@ -0,0 +1,123 @@
1
+ import { addresses } from "@/constants";
2
+ import { GnosisSafe } from "@/typechain";
3
+ import { ChainId } from "@/types";
4
+ import { ethers, Wallet } from "ethers";
5
+
6
+ export interface Signature {
7
+ signer: string;
8
+ hash?: string;
9
+ data: string;
10
+ }
11
+
12
+ export const buildSignatureBytes = (signatures: Signature[]): string => {
13
+ signatures.sort((left, right) =>
14
+ left.signer.toLowerCase().localeCompare(right.signer.toLowerCase())
15
+ );
16
+ let signatureBytes = "0x";
17
+ for (const sig of signatures) {
18
+ signatureBytes += sig.data.slice(2);
19
+ }
20
+ return signatureBytes;
21
+ };
22
+
23
+ export const signGnosisSafeTx = async (
24
+ {
25
+ to,
26
+ data = null as any,
27
+ value = "0",
28
+ operation = "1",
29
+ baseGas = "0",
30
+ gasPrice = "0",
31
+ gasToken = "0x0000000000000000000000000000000000000000",
32
+ refundReceiver = "0x0000000000000000000000000000000000000000",
33
+ safeTxGas = "79668" as string | number,
34
+ nonce = "0",
35
+ chainId = 137 as ChainId,
36
+ },
37
+ { signer }: { signer: Wallet }
38
+ ) => {
39
+ const gnosisSafe = addresses[chainId].gnosisSafe;
40
+
41
+ const domain = {
42
+ verifyingContract: gnosisSafe,
43
+ chainId,
44
+ };
45
+
46
+ const types = {
47
+ SafeTx: [
48
+ { type: "address", name: "to" },
49
+ { type: "uint256", name: "value" },
50
+ { type: "bytes", name: "data" },
51
+ { type: "uint8", name: "operation" },
52
+ { type: "uint256", name: "safeTxGas" },
53
+ { type: "uint256", name: "baseGas" },
54
+ { type: "uint256", name: "gasPrice" },
55
+ { type: "address", name: "gasToken" },
56
+ { type: "address", name: "refundReceiver" },
57
+ { type: "uint256", name: "nonce" },
58
+ ],
59
+ };
60
+
61
+ const message = {
62
+ baseGas,
63
+ data,
64
+ gasPrice,
65
+ gasToken,
66
+ nonce: Number(nonce),
67
+ operation,
68
+ refundReceiver,
69
+ safeAddress: gnosisSafe,
70
+ safeTxGas: String(safeTxGas),
71
+ to,
72
+ value,
73
+ };
74
+
75
+ return await signer._signTypedData(domain, types, message);
76
+ };
77
+
78
+ export const generateGnosisTransaction = async (
79
+ transactionData: any,
80
+ safeContract: GnosisSafe
81
+ ) => {
82
+ console.log(transactionData);
83
+
84
+ let isExecuted = await safeContract.dataHashes(
85
+ await safeContract.getTransactionHash(
86
+ transactionData.to,
87
+ transactionData.value,
88
+ transactionData.data,
89
+ transactionData.operation,
90
+ transactionData.safeTxGas,
91
+ transactionData.baseGas,
92
+ transactionData.gasPrice,
93
+ transactionData.gasToken,
94
+ transactionData.refundReceiver,
95
+ transactionData.nonce
96
+ )
97
+ );
98
+
99
+ while (isExecuted == 1) {
100
+ transactionData.safeTxGas = ethers.BigNumber.from(
101
+ String(transactionData.safeTxGas)
102
+ )
103
+ .add(1)
104
+ .toString();
105
+
106
+ isExecuted = await safeContract.dataHashes(
107
+ await safeContract.getTransactionHash(
108
+ transactionData.to,
109
+ transactionData.value,
110
+ transactionData.data,
111
+ transactionData.operation,
112
+ transactionData.safeTxGas,
113
+ transactionData.baseGas,
114
+ transactionData.gasPrice,
115
+ transactionData.gasToken,
116
+ transactionData.refundReceiver,
117
+ transactionData.nonce
118
+ )
119
+ );
120
+ }
121
+
122
+ return transactionData;
123
+ };
@@ -0,0 +1,6 @@
1
+ import axios from "axios";
2
+ import axiosRetry from "axios-retry";
3
+
4
+ export const http = axios.create();
5
+
6
+ axiosRetry(http, { retries: 3, retryDelay: axiosRetry.exponentialDelay });
@@ -1,365 +1,8 @@
1
- /**
2
- * @module util
3
- */
4
- import axios from "axios";
5
- import axiosRetry from "axios-retry";
6
- import { addresses } from "@/constants";
7
- import { ChainId } from "@/types";
8
- import { ethers } from "ethers";
9
- import { GnosisSafe } from "@/typechain";
10
- import retry from "async-retry";
11
- import { connectors } from "@/abi/connectors";
12
-
13
- export const http = axios.create();
14
-
15
- axiosRetry(http, { retries: 3, retryDelay: axiosRetry.exponentialDelay });
16
-
17
- export function shortenHash(hash: string, length: number = 4) {
18
- if (!hash) return;
19
-
20
- if (hash.length < 12) return hash;
21
-
22
- const beginningChars = hash.startsWith("0x") ? length + 2 : length;
23
-
24
- const shortened = hash.substr(0, beginningChars) + "…" + hash.substr(-length);
25
-
26
- return shortened;
27
- }
28
-
29
- export function short(buffer: Buffer): string {
30
- return buffer.toString("hex").slice(0, 8) + "...";
31
- }
32
-
33
- export const signGnosisSafeTx = async (
34
- {
35
- to,
36
- data = null as any,
37
- value = "0",
38
- operation = "1",
39
- baseGas = "0",
40
- gasPrice = "0",
41
- gasToken = "0x0000000000000000000000000000000000000000",
42
- refundReceiver = "0x0000000000000000000000000000000000000000",
43
- safeTxGas = "79668" as string | number,
44
- nonce = "0",
45
- chainId = 137 as ChainId,
46
- },
47
- { signer }
48
- ) => {
49
- const gnosisSafe = addresses[chainId].gnosisSafe;
50
-
51
- const domain = {
52
- verifyingContract: gnosisSafe,
53
- chainId,
54
- };
55
-
56
- const types = {
57
- SafeTx: [
58
- { type: "address", name: "to" },
59
- { type: "uint256", name: "value" },
60
- { type: "bytes", name: "data" },
61
- { type: "uint8", name: "operation" },
62
- { type: "uint256", name: "safeTxGas" },
63
- { type: "uint256", name: "baseGas" },
64
- { type: "uint256", name: "gasPrice" },
65
- { type: "address", name: "gasToken" },
66
- { type: "address", name: "refundReceiver" },
67
- { type: "uint256", name: "nonce" },
68
- ],
69
- };
70
-
71
- const message = {
72
- baseGas,
73
- data,
74
- gasPrice,
75
- gasToken,
76
- nonce: Number(nonce),
77
- operation,
78
- refundReceiver,
79
- safeAddress: gnosisSafe,
80
- safeTxGas: String(safeTxGas),
81
- to,
82
- value,
83
- };
84
-
85
- return await signer._signTypedData(domain, types, message);
86
- };
87
-
88
- export const getRpcProviderUrl = (chainId: ChainId) => {
89
- switch (chainId) {
90
- case 1:
91
- return "https://rpc.ankr.com/eth";
92
- case 137:
93
- return "https://rpc.ankr.com/polygon";
94
- case 43114:
95
- return "https://rpc.ankr.com/avalanche";
96
- default:
97
- throw new Error(`Unknown chainId: ${chainId}`);
98
- }
99
- };
100
-
101
- export interface Signature {
102
- signer: string;
103
- hash?: string;
104
- data: string;
105
- }
106
-
107
- export const buildSignatureBytes = (signatures: Signature[]): string => {
108
- signatures.sort((left, right) =>
109
- left.signer.toLowerCase().localeCompare(right.signer.toLowerCase())
110
- );
111
- let signatureBytes = "0x";
112
- for (const sig of signatures) {
113
- signatureBytes += sig.data.slice(2);
114
- }
115
- return signatureBytes;
116
- };
117
-
118
- /**
119
- * Call an async function with a maximum time limit (in milliseconds) for the timeout
120
- * Resolved promise for async function call, or an error if time limit reached
121
- */
122
- export const asyncCallWithTimeout = async <T>(
123
- asyncPromise: Promise<T>,
124
- timeout: number
125
- ) => {
126
- let timeoutHandle;
127
-
128
- const timeoutPromise = new Promise((_resolve, reject) => {
129
- timeoutHandle = setTimeout(
130
- () => reject(new Error("Async call timeout limit reached")),
131
- timeout
132
- );
133
- });
134
-
135
- return Promise.race([asyncPromise, timeoutPromise]).then((result) => {
136
- clearTimeout(timeoutHandle);
137
- return result;
138
- }) as Promise<T>;
139
- };
140
-
141
- type GenerateInteropTransactionHashParam = {
142
- actionId: string;
143
- vnonce: string;
144
- sourceSender: string;
145
- sourceChainId: string | number;
146
- sourceDsaId: string;
147
- targetChainId: string | number;
148
- targetDsaId: string;
149
- };
150
-
151
- export const generateInteropTransactionHash = (
152
- data: GenerateInteropTransactionHashParam
153
- ) => {
154
- return ethers.utils.solidityKeccak256(
155
- Array.from({ length: 7 }, () => "string"),
156
- [
157
- String(data.actionId),
158
- String(data.vnonce),
159
- String(data.sourceSender),
160
- String(data.sourceChainId),
161
- String(data.sourceDsaId),
162
- String(data.targetChainId),
163
- String(data.targetDsaId),
164
- ]
165
- );
166
- };
167
-
168
- export class ContractError extends Error {
169
- method: string;
170
- address: string;
171
- args: any[];
172
- }
173
-
174
- export function getContract<TContract extends ethers.Contract>(
175
- address: string,
176
- contractInterface: ethers.ContractInterface | any,
177
- signerOrProvider?: ethers.Signer | ethers.providers.Provider
178
- ) {
179
- if (
180
- !ethers.utils.getAddress(address) ||
181
- address === ethers.constants.AddressZero
182
- ) {
183
- throw Error(`Invalid 'address' parameter '${address}'.`);
184
- }
185
-
186
- const contract = new ethers.Contract(
187
- address,
188
- contractInterface,
189
- signerOrProvider
190
- ) as TContract;
191
-
192
- // Make sure the contract properties is writable
193
- const desc = Object.getOwnPropertyDescriptor(contract, "functions");
194
-
195
- if (!desc || desc.writable !== true) {
196
- return contract;
197
- }
198
-
199
- return new Proxy(contract, {
200
- get(target, prop, receiver) {
201
- const value = Reflect.get(target, prop, receiver);
202
-
203
- if (
204
- typeof value === "function" &&
205
- (contract.functions.hasOwnProperty(prop) ||
206
- ["queryFilter"].includes(String(prop)))
207
- ) {
208
- let isConstant = false;
209
-
210
- try {
211
- isConstant = contract.interface.getFunction(String(prop)).constant;
212
- } catch (error) {}
213
-
214
- return async (...args: any[]) => {
215
- try {
216
- return await retry(
217
- async () => await value.bind(contract)(...args),
218
- { retries: isConstant ? 1 : 3 }
219
- );
220
- } catch (error) {
221
- const err = new ContractError(
222
- `Error calling "${String(prop)}" on "${address}": ${
223
- error.reason || error.message
224
- }`
225
- );
226
-
227
- err.method = String(prop);
228
- err.address = address;
229
- err.args = [...args];
230
-
231
- throw err;
232
- }
233
- };
234
- }
235
-
236
- if (
237
- typeof value === "object" &&
238
- [
239
- "populateTransaction",
240
- "estimateGas",
241
- "functions",
242
- "callStatic",
243
- ].includes(String(prop))
244
- ) {
245
- const parentProp = String(prop);
246
-
247
- return new Proxy(value, {
248
- get(target, prop, receiver) {
249
- const value = Reflect.get(target, prop, receiver);
250
-
251
- if (typeof value === "function") {
252
- return async (...args: any[]) => {
253
- try {
254
- return await retry(
255
- async () => await value.bind(contract)(...args),
256
- { retries: parentProp === "callStatic" ? 3 : 1 }
257
- );
258
- } catch (error) {
259
- const err = new ContractError(
260
- `Error calling "${String(
261
- prop
262
- )}" using "${parentProp}" on "${address}": ${
263
- error.reason || error.message
264
- }`
265
- );
266
-
267
- err.method = String(prop);
268
- err.address = address;
269
- err.args = [...args];
270
-
271
- throw err;
272
- }
273
- };
274
- }
275
- },
276
- });
277
- }
278
-
279
- return value;
280
- },
281
- });
282
- }
283
-
284
- export const generateGnosisTransaction = async (
285
- transactionData: any,
286
- safeContract: GnosisSafe
287
- ) => {
288
- console.log(transactionData);
289
-
290
- let isExecuted = await safeContract.dataHashes(
291
- await safeContract.getTransactionHash(
292
- transactionData.to,
293
- transactionData.value,
294
- transactionData.data,
295
- transactionData.operation,
296
- transactionData.safeTxGas,
297
- transactionData.baseGas,
298
- transactionData.gasPrice,
299
- transactionData.gasToken,
300
- transactionData.refundReceiver,
301
- transactionData.nonce
302
- )
303
- );
304
-
305
- while (isExecuted == 1) {
306
- transactionData.safeTxGas = ethers.BigNumber.from(
307
- String(transactionData.safeTxGas)
308
- )
309
- .add(1)
310
- .toString();
311
-
312
- isExecuted = await safeContract.dataHashes(
313
- await safeContract.getTransactionHash(
314
- transactionData.to,
315
- transactionData.value,
316
- transactionData.data,
317
- transactionData.operation,
318
- transactionData.safeTxGas,
319
- transactionData.baseGas,
320
- transactionData.gasPrice,
321
- transactionData.gasToken,
322
- transactionData.refundReceiver,
323
- transactionData.nonce
324
- )
325
- );
326
- }
327
-
328
- return transactionData;
329
- };
330
-
331
- export class LiquidityError extends Error {
332
- constructor(message?: string) {
333
- super(message || "Not enough liquidity");
334
- Object.setPrototypeOf(this, new.target.prototype);
335
- }
336
- }
337
-
338
- export const encodeConnectorMethod = (params: {
339
- connector: string;
340
- method: string;
341
- args: string[];
342
- }) => {
343
- const connectorInterface = getInterface(
344
- connectors.versions[2][params.connector],
345
- params.method
346
- );
347
-
348
- if (!connectorInterface)
349
- throw new Error(`ConnectorInterface '${params.method}' not found`);
350
-
351
- const iface = new ethers.utils.Interface(connectorInterface);
352
-
353
- return iface.encodeFunctionData(params.method, params.args);
354
- };
355
-
356
- const getInterface = (abiItems: any[], method: string) => {
357
- const abiItem = abiItems.find((abiItem) => abiItem.name === method);
358
-
359
- if (!abiItem) {
360
- console.error(`${method} is an invalid method.`);
361
- return;
362
- }
363
-
364
- return abiItem;
365
- };
1
+ export * from './async';
2
+ export * from './dsa';
3
+ export * from './formatting';
4
+ export * from './gnosis';
5
+ export * from './http';
6
+ export * from './interop';
7
+ export * from './web3';
8
+ export * from './validate';
@@ -0,0 +1,28 @@
1
+ import { ethers } from "ethers";
2
+
3
+ type GenerateInteropTransactionHashParam = {
4
+ actionId: string;
5
+ vnonce: string;
6
+ sourceSender: string;
7
+ sourceChainId: string | number;
8
+ sourceDsaId: string;
9
+ targetChainId: string | number;
10
+ targetDsaId: string;
11
+ };
12
+
13
+ export const generateInteropTransactionHash = (
14
+ data: GenerateInteropTransactionHashParam
15
+ ) => {
16
+ return ethers.utils.solidityKeccak256(
17
+ Array.from({ length: 7 }, () => "string"),
18
+ [
19
+ String(data.actionId),
20
+ String(data.vnonce),
21
+ String(data.sourceSender),
22
+ String(data.sourceChainId),
23
+ String(data.sourceDsaId),
24
+ String(data.targetChainId),
25
+ String(data.targetDsaId),
26
+ ]
27
+ );
28
+ };
@@ -0,0 +1,24 @@
1
+ import { addresses } from "@/constants";
2
+ import { InvalidChaindIdError } from "@/errors";
3
+
4
+ export const validateChains = ({ sourceChainId, targetChainId }) => {
5
+ if (!sourceChainId) {
6
+ throw new InvalidChaindIdError("Source chain id is required");
7
+ }
8
+
9
+ if (!targetChainId) {
10
+ throw new InvalidChaindIdError("Target chain id is required");
11
+ }
12
+
13
+ if (sourceChainId == targetChainId) {
14
+ throw new InvalidChaindIdError("Source and target chain cannot be the same");
15
+ }
16
+
17
+ if (!addresses[sourceChainId]) {
18
+ throw new InvalidChaindIdError("Invalid source chain id");
19
+ }
20
+
21
+ if (!addresses[targetChainId]) {
22
+ throw new InvalidChaindIdError("Invalid target chain id");
23
+ }
24
+ };