@instadapp/interop-x 0.0.0-dev.5953f3d → 0.0.0-dev.5a90c8d

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/dist/package.json +8 -1
  2. package/dist/src/abi/aaveV2Resolver.json +832 -0
  3. package/dist/src/abi/balanceResolver.json +211 -0
  4. package/dist/src/abi/index.js +6 -0
  5. package/dist/src/abi/instList.json +232 -0
  6. package/dist/src/api/index.js +7 -0
  7. package/dist/src/constants/addresses.js +8 -2
  8. package/dist/src/constants/capPerChain.js +8 -0
  9. package/dist/src/constants/index.js +2 -0
  10. package/dist/src/constants/tokens.js +44 -44
  11. package/dist/src/constants/wrappedNativeToken.js +8 -0
  12. package/dist/src/crons/index.js +3 -0
  13. package/dist/src/crons/prices.js +16 -0
  14. package/dist/src/db/models/transaction.js +15 -7
  15. package/dist/src/errors/index.js +30 -0
  16. package/dist/src/gnosis/actions/aaveV2/source.js +17 -5
  17. package/dist/src/gnosis/actions/aaveV2/target.js +79 -0
  18. package/dist/src/index.js +2 -1
  19. package/dist/src/providers/index.js +17 -0
  20. package/dist/src/providers/retry-provider.js +45 -0
  21. package/dist/src/services/Prices.js +74 -0
  22. package/dist/src/services/index.js +8 -0
  23. package/dist/src/tasks/InteropX/{ProcessSubmitSubmitEvents.js → ProcessSubmitEvents.js} +84 -7
  24. package/dist/src/tasks/InteropX/ProcessValidateEvents.js +185 -0
  25. package/dist/src/tasks/InteropX/SyncLogExecuteEvents.js +113 -0
  26. package/dist/src/tasks/InteropX/SyncLogSubmitEvents.js +3 -1
  27. package/dist/src/tasks/InteropX/SyncLogValidateEvents.js +106 -0
  28. package/dist/src/tasks/index.js +13 -5
  29. package/dist/src/typechain/AaveV2Resolver.js +2 -0
  30. package/dist/src/typechain/BalanceResolver.js +2 -0
  31. package/dist/src/typechain/InstList.js +2 -0
  32. package/dist/src/typechain/factories/AaveV2Resolver__factory.js +1191 -0
  33. package/dist/src/typechain/factories/BalanceResolver__factory.js +228 -0
  34. package/dist/src/typechain/factories/InstList__factory.js +249 -0
  35. package/dist/src/typechain/factories/index.js +7 -1
  36. package/dist/src/typechain/index.js +7 -1
  37. package/dist/src/utils/async.js +18 -0
  38. package/dist/src/utils/dsa.js +24 -0
  39. package/dist/src/utils/formatting.js +67 -0
  40. package/dist/src/utils/gnosis.js +62 -0
  41. package/dist/src/utils/http.js +10 -0
  42. package/dist/src/utils/index.js +22 -220
  43. package/dist/src/utils/interop.js +16 -0
  44. package/dist/src/utils/tokens.js +22 -0
  45. package/dist/src/utils/validate.js +111 -0
  46. package/dist/src/utils/web3.js +93 -0
  47. package/package.json +8 -1
  48. package/src/abi/aaveV2Resolver.json +832 -0
  49. package/src/abi/balanceResolver.json +211 -0
  50. package/src/abi/index.ts +6 -0
  51. package/src/abi/instList.json +232 -0
  52. package/src/api/index.ts +8 -0
  53. package/src/constants/addresses.ts +19 -3
  54. package/src/constants/capPerChain.ts +5 -0
  55. package/src/constants/index.ts +2 -0
  56. package/src/constants/tokens.ts +44 -44
  57. package/src/constants/wrappedNativeToken.ts +5 -0
  58. package/src/crons/index.ts +1 -0
  59. package/src/crons/prices.ts +12 -0
  60. package/src/db/models/transaction.ts +134 -80
  61. package/src/errors/index.ts +26 -0
  62. package/src/gnosis/actions/aaveV2/source.ts +21 -6
  63. package/src/gnosis/actions/aaveV2/target.ts +131 -2
  64. package/src/index.ts +1 -0
  65. package/src/providers/index.ts +1 -0
  66. package/src/providers/retry-provider.ts +51 -0
  67. package/src/services/Prices.ts +89 -0
  68. package/src/services/index.ts +1 -0
  69. package/src/tasks/InteropX/{ProcessSubmitSubmitEvents.ts → ProcessSubmitEvents.ts} +104 -11
  70. package/src/tasks/InteropX/ProcessValidateEvents.ts +272 -0
  71. package/src/tasks/InteropX/SyncLogExecuteEvents.ts +161 -0
  72. package/src/tasks/InteropX/SyncLogSubmitEvents.ts +6 -6
  73. package/src/tasks/InteropX/SyncLogValidateEvents.ts +151 -0
  74. package/src/tasks/index.ts +16 -5
  75. package/src/typechain/AaveV2Resolver.ts +1017 -0
  76. package/src/typechain/BalanceResolver.ts +266 -0
  77. package/src/typechain/InstList.ts +402 -0
  78. package/src/typechain/factories/AaveV2Resolver__factory.ts +1198 -0
  79. package/src/typechain/factories/BalanceResolver__factory.ts +235 -0
  80. package/src/typechain/factories/InstList__factory.ts +253 -0
  81. package/src/typechain/factories/index.ts +3 -0
  82. package/src/typechain/index.ts +6 -0
  83. package/src/utils/async.ts +22 -0
  84. package/src/utils/dsa.ts +30 -0
  85. package/src/utils/formatting.ts +68 -0
  86. package/src/utils/gnosis.ts +123 -0
  87. package/src/utils/http.ts +6 -0
  88. package/src/utils/index.ts +9 -365
  89. package/src/utils/interop.ts +28 -0
  90. package/src/utils/tokens.ts +21 -0
  91. package/src/utils/validate.ts +174 -0
  92. package/src/utils/web3.ts +132 -0
@@ -5,12 +5,16 @@ import abi from "@/abi";
5
5
  import { Transaction } from "@/db";
6
6
  import {
7
7
  buildSignatureBytes,
8
+ chainIdToName,
8
9
  generateGnosisTransaction,
9
- generateInteropTransactionHash,
10
+ getChainIdNativeSymbol,
10
11
  getContract,
12
+ getExplorerUrl,
11
13
  getRpcProviderUrl,
12
- LiquidityError,
13
14
  Signature,
15
+ validateChains,
16
+ validateLiquidityCap,
17
+ validateSourceLiquidity,
14
18
  } from "@/utils";
15
19
  import { addresses, blockConfirmations } from "@/constants";
16
20
  import { ChainId } from "@/types";
@@ -22,9 +26,13 @@ import { buildGnosisAction } from "@/gnosis";
22
26
  import { peerPool, protocol } from "@/net";
23
27
  import { LogDescription } from "ethers/lib/utils";
24
28
  import wait from "waait";
29
+ import { LiquidityError, UnsupportedChaindIdError } from "@/errors";
30
+ import { BigNumber } from "bignumber.js";
31
+ import dedent from "dedent";
32
+ import { JsonRpcRetryProvider } from "@/providers";
25
33
 
26
- class ProcessSubmitSubmitEvents extends BaseTask {
27
- sourceProvider: ethers.providers.JsonRpcProvider;
34
+ export default class ProcessSubmitEvents extends BaseTask {
35
+ sourceProvider: JsonRpcRetryProvider;
28
36
  sourceGnosisContract: GnosisSafe;
29
37
  sourceWallet: Wallet;
30
38
  chainId: ChainId;
@@ -33,7 +41,7 @@ class ProcessSubmitSubmitEvents extends BaseTask {
33
41
 
34
42
  constructor({ chainId }: { chainId: ChainId }) {
35
43
  super({
36
- logger: new Logger("InteropX::ProcessSubmitSubmitEvents"),
44
+ logger: new Logger("InteropX::ProcessSubmitEvents"),
37
45
  });
38
46
  this.chainId = chainId;
39
47
  }
@@ -68,12 +76,86 @@ class ProcessSubmitSubmitEvents extends BaseTask {
68
76
  return;
69
77
  }
70
78
 
79
+ this.logger.debug(`Processing transaction ${transaction.transactionHash}`);
80
+
71
81
  transaction.sourceStatus = "proccessing";
72
82
  await transaction.save();
73
83
 
84
+ const { submitEvent: { position, sourceChainId, targetChainId } } = transaction;
85
+ try {
86
+ validateChains({ sourceChainId, targetChainId });
87
+ } catch (error) {
88
+ transaction.sourceErrors = [error.message];
89
+ transaction.sourceStatus = "failed";
90
+ transaction.targetStatus = "failed";
91
+ transaction.status = "failed";
92
+ await transaction.save();
93
+ return;
94
+ }
95
+
96
+ const walletBalance = (await this.sourceWallet.getBalance()).toString();
97
+ const currentGasPrice = (await this.sourceWallet.getGasPrice()).toString()
98
+
99
+ const minBalanceRequired = new BigNumber(currentGasPrice)
100
+ .multipliedBy(4_000_000)
101
+ .multipliedBy(2) // 2x balance
102
+
103
+ if (
104
+ new BigNumber(walletBalance).isLessThan(minBalanceRequired)
105
+ ) {
106
+ console.log(
107
+ dedent`Not enough balance in wallet ${getExplorerUrl(sourceChainId, '/address/' + this.sourceWallet.address)} on ${chainIdToName(sourceChainId)}
108
+ Balance: ${ethers.utils.parseEther(walletBalance)} ${getChainIdNativeSymbol(sourceChainId)}
109
+ Required Balance: ${ethers.utils.parseEther(minBalanceRequired.toString())}
110
+ Require more: ${ethers.utils.parseEther(minBalanceRequired.minus(walletBalance).toString())}`
111
+ );
112
+ transaction.sourceDelayUntil = moment().add({ minutes: 5 }).toDate();
113
+ transaction.sourceStatus = "pending";
114
+ await transaction.save();
115
+ return;
116
+ }
117
+
118
+ try {
119
+ await validateLiquidityCap(position, sourceChainId, targetChainId);
120
+ } catch (error) {
121
+ transaction.sourceErrors = [error.message];
122
+ transaction.sourceStatus = "failed";
123
+ transaction.targetStatus = "failed";
124
+ transaction.status = "failed";
125
+ await transaction.save();
126
+ return;
127
+ }
128
+
129
+ try {
130
+ await validateSourceLiquidity({
131
+ position,
132
+ sourceChainId,
133
+ sourceProvider: this.sourceProvider,
134
+ });
135
+ } catch (error) {
136
+ if (error instanceof UnsupportedChaindIdError) {
137
+ console.log(`Dropping transaction ${transaction.transactionHash}`);
138
+
139
+ transaction.sourceErrors = [error.message];
140
+ transaction.sourceStatus = "failed";
141
+ transaction.targetStatus = "failed";
142
+ transaction.status = "failed";
143
+ await transaction.save();
144
+ } else {
145
+ transaction.sourceStatus = "pending";
146
+ transaction.sourceDelayUntil = moment().add({ minutes: 5 }).toDate();
147
+ await transaction.save();
148
+
149
+ console.log("[validateSourceLiquidity][Warning]", error.message);
150
+ return;
151
+ }
152
+ }
153
+
74
154
  const ownersThreshold = await this.sourceGnosisContract.getThreshold();
75
155
  await wait(10000);
76
156
 
157
+ this.logger.debug(`Build gnosis action for ${transaction.transactionHash}`);
158
+
77
159
  let data,
78
160
  logs = [];
79
161
 
@@ -101,6 +183,10 @@ class ProcessSubmitSubmitEvents extends BaseTask {
101
183
  return;
102
184
  }
103
185
 
186
+ this.logger.debug(
187
+ `Generating gnosis tx for ${transaction.transactionHash}`
188
+ );
189
+
104
190
  let gnosisTx = await generateGnosisTransaction(
105
191
  {
106
192
  baseGas: "0",
@@ -186,10 +272,20 @@ class ProcessSubmitSubmitEvents extends BaseTask {
186
272
  buildSignatureBytes(validSignatures)
187
273
  );
188
274
 
275
+ const [gasPrice, gasLimit] = await Promise.all([
276
+ this.sourceProvider.getGasPrice(),
277
+ this.sourceProvider.estimateGas({
278
+ from: this.sourceWallet.address,
279
+ to: this.sourceGnosisContract.address,
280
+ data: txData,
281
+ }),
282
+ ]);
283
+
189
284
  const txSent = await this.sourceWallet.sendTransaction({
190
285
  from: this.sourceWallet.address,
191
- gasPrice: ethers.BigNumber.from(120 * 10 ** 9),
192
286
  to: this.sourceGnosisContract.address,
287
+ gasPrice: gasPrice.mul(120).div(100),
288
+ gasLimit: 5_000_000,//gasLimit.mul(120).div(100),
193
289
  data: txData,
194
290
  });
195
291
 
@@ -202,7 +298,7 @@ class ProcessSubmitSubmitEvents extends BaseTask {
202
298
  receipt.logs.forEach((log) => {
203
299
  try {
204
300
  parsedLogs.push(this.sourceGnosisContract.interface.parseLog(log));
205
- } catch (e) {}
301
+ } catch (e) { }
206
302
  });
207
303
 
208
304
  if (parsedLogs.find((e) => e.name === "ExecutionSuccess")) {
@@ -219,7 +315,6 @@ class ProcessSubmitSubmitEvents extends BaseTask {
219
315
  if (txSent.blockNumber)
220
316
  transaction.sourceBlockNumber = txSent.blockNumber;
221
317
  transaction.sourceTransactionHash = txSent.hash;
222
- transaction.sourceTransactionHash = txSent.hash;
223
318
  transaction.status = "failed";
224
319
  await transaction.save();
225
320
  }
@@ -230,7 +325,7 @@ class ProcessSubmitSubmitEvents extends BaseTask {
230
325
  async start(): Promise<void> {
231
326
  this.blockConfirmationsCount = blockConfirmations[this.chainId] + 1;
232
327
 
233
- this.sourceProvider = new ethers.providers.JsonRpcProvider(
328
+ this.sourceProvider = new JsonRpcRetryProvider(
234
329
  getRpcProviderUrl(this.chainId)
235
330
  );
236
331
 
@@ -248,5 +343,3 @@ class ProcessSubmitSubmitEvents extends BaseTask {
248
343
  await super.start();
249
344
  }
250
345
  }
251
-
252
- export default ProcessSubmitSubmitEvents;
@@ -0,0 +1,272 @@
1
+ import { BaseTask } from "../BaseTask";
2
+ import Logger from "@/logger";
3
+ import { ethers, Wallet } from "ethers";
4
+ import abi from "@/abi";
5
+ import { Transaction } from "@/db";
6
+ import {
7
+ buildSignatureBytes,
8
+ generateGnosisTransaction,
9
+ getContract,
10
+ getRpcProviderUrl,
11
+ Signature,
12
+ } from "@/utils";
13
+ import { addresses, blockConfirmations } from "@/constants";
14
+ import { ChainId } from "@/types";
15
+ import config from "@/config";
16
+ import { GnosisSafe, InteropX } from "@/typechain";
17
+ import moment from "moment";
18
+ import { Op } from "sequelize";
19
+ import { buildGnosisAction } from "@/gnosis";
20
+ import { peerPool, protocol } from "@/net";
21
+ import { LogDescription } from "ethers/lib/utils";
22
+ import wait from "waait";
23
+ import { LiquidityError } from "@/errors";
24
+ import { JsonRpcRetryProvider } from "@/providers";
25
+
26
+ export default class ProcessValidateEvents extends BaseTask {
27
+ sourceProvider: JsonRpcRetryProvider;
28
+ chainId: ChainId;
29
+ leadNodeOnly: boolean = true;
30
+ blockConfirmationsCount: number = 12;
31
+
32
+ constructor({ chainId }: { chainId: ChainId }) {
33
+ super({
34
+ logger: new Logger("InteropX::ProcessValidateEvents"),
35
+ });
36
+ this.chainId = chainId;
37
+ }
38
+
39
+ async pollHandler() {
40
+ const currentBlockNumber = await this.sourceProvider.getBlockNumber();
41
+
42
+ const transaction = await Transaction.findOne({
43
+ where: {
44
+ status: "pending",
45
+ sourceStatus: "success",
46
+ targetStatus: "pending",
47
+ sourceChainId: this.chainId,
48
+ sourceBlockNumber: {
49
+ [Op.lt]: currentBlockNumber - this.blockConfirmationsCount,
50
+ },
51
+ targetDelayUntil: {
52
+ [Op.or]: {
53
+ [Op.is]: null,
54
+ [Op.lt]: new Date(),
55
+ },
56
+ },
57
+
58
+ submitEvent: { $ne: null },
59
+ validateEvent: { $ne: null },
60
+
61
+ createdAt: {
62
+ [Op.gt]: moment().subtract({ hours: 12 }).toDate(),
63
+ },
64
+ },
65
+ });
66
+
67
+ if (!transaction) {
68
+ return;
69
+ }
70
+
71
+ this.logger.debug(`Processing transaction ${transaction.transactionHash}`);
72
+
73
+ transaction.targetStatus = "proccessing";
74
+ await transaction.save();
75
+
76
+ const { sourceChainId, targetChainId } = transaction.validateEvent
77
+
78
+ const targetProvider = new JsonRpcRetryProvider(
79
+ getRpcProviderUrl(targetChainId as ChainId)
80
+ );
81
+
82
+ const targetWallet = new ethers.Wallet(
83
+ config.privateKey!,
84
+ targetProvider
85
+ );
86
+
87
+ const targetGnosisContract = getContract<GnosisSafe>(
88
+ addresses[targetChainId].gnosisSafe,
89
+ abi.gnosisSafe,
90
+ targetWallet
91
+ );
92
+
93
+ const ownersThreshold = await targetGnosisContract.getThreshold();
94
+ await wait(10000);
95
+
96
+ this.logger.debug(`Build gnosis action for ${transaction.transactionHash}`);
97
+
98
+ let data,
99
+ logs = [];
100
+
101
+ try {
102
+ ({ data, logs } = await buildGnosisAction(transaction, "target"));
103
+ } catch (error) {
104
+ if (error instanceof LiquidityError) {
105
+ await transaction.save();
106
+ transaction.targetDelayUntil = new Date(Date.now() + 60 * 5 * 1000);
107
+ transaction.targetStatus = "pending";
108
+
109
+ await transaction.save();
110
+
111
+ throw error;
112
+ return;
113
+ }
114
+
115
+ transaction.targetStatus = "failed";
116
+ transaction.targetErrors = [error.message];
117
+ transaction.status = "failed";
118
+ await transaction.save();
119
+ protocol.sendTransaction(transaction);
120
+ return;
121
+ }
122
+
123
+ this.logger.debug(
124
+ `Generating gnosis tx for ${transaction.transactionHash}`
125
+ );
126
+
127
+ let gnosisTx = await generateGnosisTransaction(
128
+ {
129
+ baseGas: "0",
130
+ data,
131
+ gasPrice: "0",
132
+ gasToken: "0x0000000000000000000000000000000000000000",
133
+ nonce: "0",
134
+ operation: "1",
135
+ refundReceiver: "0x0000000000000000000000000000000000000000",
136
+ safeAddress: targetGnosisContract.address,
137
+ safeTxGas: "79668",
138
+ to: addresses[transaction.targetChainId].multisend,
139
+ value: "0",
140
+ },
141
+ targetGnosisContract
142
+ );
143
+
144
+ const owners = await targetGnosisContract
145
+ .getOwners()
146
+ .then((owners) => owners.map((owner) => owner.toLowerCase()));
147
+
148
+ const ownerPeerIds = peerPool.activePeers
149
+ .filter((peer) => owners.includes(peer.publicAddress.toLowerCase()))
150
+ .map((peer) => peer.id);
151
+
152
+ console.log(
153
+ `Collecting signatures for execution ${transaction.transactionHash}`
154
+ );
155
+
156
+ console.log(ownerPeerIds);
157
+
158
+ const signatures = await protocol.requestSignatures(
159
+ {
160
+ type: "target",
161
+ transactionHash: transaction.transactionHash,
162
+ safeTxGas: gnosisTx.safeTxGas,
163
+ safeNonce: gnosisTx.nonce,
164
+ chainId: targetChainId,
165
+ },
166
+ ownerPeerIds
167
+ );
168
+
169
+ const validSignatures = signatures.filter(
170
+ (s) => !!s.data && s.data !== "0x"
171
+ ) as Signature[];
172
+
173
+ console.log({
174
+ signatures,
175
+ validSignatures,
176
+ ownersThreshold: ownersThreshold.toString(),
177
+ });
178
+
179
+ if (
180
+ validSignatures.length === 0 ||
181
+ ownersThreshold.gt(validSignatures.length)
182
+ ) {
183
+ await transaction.save();
184
+ transaction.targetDelayUntil = new Date(Date.now() + 30 * 1000);
185
+ transaction.targetStatus = "pending";
186
+
187
+ await transaction.save();
188
+ const errorMessage = signatures.find((s) => !!s.error)?.error;
189
+ throw new Error(
190
+ `Not enough signatures` + (errorMessage ? `: ${errorMessage}` : "")
191
+ );
192
+ }
193
+
194
+ console.log(
195
+ `Executing transaction for execution ${transaction.transactionHash}`
196
+ );
197
+
198
+ const { data: txData } =
199
+ await targetGnosisContract.populateTransaction.execTransaction(
200
+ gnosisTx.to,
201
+ gnosisTx.value,
202
+ gnosisTx.data,
203
+ gnosisTx.operation,
204
+ gnosisTx.safeTxGas,
205
+ gnosisTx.baseGas,
206
+ gnosisTx.gasPrice,
207
+ gnosisTx.gasToken,
208
+ gnosisTx.refundReceiver,
209
+ buildSignatureBytes(validSignatures)
210
+ );
211
+
212
+ const [gasPrice, gasLimit] = await Promise.all([
213
+ targetProvider.getGasPrice(),
214
+ targetProvider.estimateGas({
215
+ from: targetWallet.address,
216
+ to: targetGnosisContract.address,
217
+ data: txData,
218
+ }),
219
+ ]);
220
+
221
+ const txSent = await targetWallet.sendTransaction({
222
+ from: targetWallet.address,
223
+ to: targetGnosisContract.address,
224
+ gasPrice: gasPrice.mul(120).div(100),
225
+ gasLimit: 5_000_000,//gasLimit.mul(120).div(100),
226
+ data: txData,
227
+ });
228
+
229
+ console.log(txSent);
230
+
231
+ const receipt = await txSent.wait();
232
+
233
+ const parsedLogs: LogDescription[] = [];
234
+
235
+ receipt.logs.forEach((log) => {
236
+ try {
237
+ parsedLogs.push(targetGnosisContract.interface.parseLog(log));
238
+ } catch (e) { }
239
+ });
240
+
241
+ if (parsedLogs.find((e) => e.name === "ExecutionSuccess")) {
242
+ console.log("ExecutionSuccess");
243
+ transaction.targetStatus = "success";
244
+ transaction.status = "success";
245
+ if (txSent.blockNumber)
246
+ transaction.targetBlockNumber = txSent.blockNumber;
247
+ transaction.targetTransactionHash = txSent.hash;
248
+ transaction.targetLogs = logs;
249
+ await transaction.save();
250
+ } else {
251
+ console.log("ExecutionFailure");
252
+ transaction.targetStatus = "failed";
253
+ if (txSent.blockNumber)
254
+ transaction.targetBlockNumber = txSent.blockNumber;
255
+ transaction.targetTransactionHash = txSent.hash;
256
+ transaction.status = "failed";
257
+ await transaction.save();
258
+ }
259
+
260
+ protocol.sendTransaction(transaction);
261
+ }
262
+
263
+ async start(): Promise<void> {
264
+ this.blockConfirmationsCount = blockConfirmations[this.chainId] + 1;
265
+
266
+ this.sourceProvider = new JsonRpcRetryProvider(
267
+ getRpcProviderUrl(this.chainId)
268
+ );
269
+
270
+ await super.start();
271
+ }
272
+ }
@@ -0,0 +1,161 @@
1
+ import { BaseTask } from "../BaseTask";
2
+ import Logger from "@/logger";
3
+ import { ethers } from "ethers";
4
+ import abi from "@/abi";
5
+ import { Transaction } from "@/db";
6
+ import {
7
+ generateInteropTransactionHash,
8
+ getContract,
9
+ getRpcProviderUrl,
10
+ } from "@/utils";
11
+ import { addresses } from "@/constants";
12
+ import { ChainId } from "@/types";
13
+ import config from "@/config";
14
+ import { InteropX } from "@/typechain";
15
+ import { Op } from "sequelize";
16
+ import { JsonRpcRetryProvider } from "@/providers";
17
+
18
+ export default class SyncLogExecuteEvents extends BaseTask {
19
+ contractAddress: string;
20
+ provider: JsonRpcRetryProvider;
21
+ contract: InteropX;
22
+ targetChainId: ChainId;
23
+
24
+ constructor({ targetChainId }: { targetChainId: ChainId }) {
25
+ super({
26
+ logger: new Logger("InteropX::SyncLogExecuteEvents"),
27
+ });
28
+ this.targetChainId = targetChainId;
29
+ }
30
+
31
+ async pollHandler() {
32
+ const currentBlock = await this.provider.getBlockNumber();
33
+
34
+ const events = await this.contract.queryFilter(
35
+ this.contract.filters.LogExecute(),
36
+ currentBlock - 2000,
37
+ currentBlock
38
+ );
39
+
40
+ let processedEvents = 0;
41
+
42
+ for (const event of events) {
43
+ try {
44
+ if (!event.args) {
45
+ continue;
46
+ }
47
+
48
+ const {
49
+ sourceSpells,
50
+ targetSpells,
51
+ position,
52
+ actionId,
53
+ actionIdHash,
54
+ sourceSender,
55
+ sourceDsaId,
56
+ targetDsaId,
57
+ sourceChainId,
58
+ targetChainId,
59
+ vnonce,
60
+ metadata,
61
+ } = event.args;
62
+
63
+ const uniqueIdentifier = {
64
+ actionId,
65
+ vnonce: vnonce.toString(),
66
+ sourceSender: sourceSender.toString(),
67
+ sourceChainId: sourceChainId.toNumber(),
68
+ targetChainId: targetChainId.toNumber(),
69
+ sourceDsaId: sourceDsaId.toString(),
70
+ targetDsaId: targetDsaId.toString(),
71
+ };
72
+
73
+ let transactionHash = generateInteropTransactionHash(uniqueIdentifier);
74
+
75
+ const transaction = await Transaction.findOne({
76
+ where: {
77
+ transactionHash,
78
+ executeEvent: { [Op.eq]: null },
79
+ },
80
+ });
81
+
82
+ if (!transaction) {
83
+ continue;
84
+ }
85
+
86
+ if (transaction.targetStatus != "success") {
87
+ transaction.targetStatus = "success";
88
+ }
89
+
90
+ if (transaction.status != "success") {
91
+ transaction.status = "success";
92
+ }
93
+
94
+ if (!transaction.targetCreatedAt) {
95
+ transaction.targetCreatedAt = new Date();
96
+ }
97
+
98
+ transaction.targetTransactionHash = event.transactionHash;
99
+ transaction.targetBlockNumber = event.blockNumber;
100
+ transaction.targetLogs = [];
101
+ transaction.executeEvent = {
102
+ actionId,
103
+ actionIdHashHash: actionIdHash,
104
+ actionIdHash,
105
+ vnonce: vnonce.toString(),
106
+ sourceSpells: sourceSpells.map(({ connector, data }) => ({
107
+ connector,
108
+ data,
109
+ })),
110
+ targetSpells: targetSpells.map(({ connector, data }) => ({
111
+ connector,
112
+ data,
113
+ })),
114
+ position: {
115
+ withdraw: position.withdraw.map((v) => ({
116
+ sourceToken: v.sourceToken,
117
+ targetToken: v.targetToken,
118
+ amount: v.amount.toString(),
119
+ })),
120
+ supply: position.supply.map((v) => ({
121
+ sourceToken: v.sourceToken,
122
+ targetToken: v.targetToken,
123
+ amount: v.amount.toString(),
124
+ })),
125
+ },
126
+ sourceChainId: sourceChainId.toNumber(),
127
+ targetChainId: targetChainId.toNumber(),
128
+ sourceSender,
129
+ sourceDsaId: sourceDsaId.toString(),
130
+ targetDsaId: targetDsaId.toString(),
131
+ metadata,
132
+ };
133
+
134
+ await transaction.save();
135
+
136
+ this.logger.info(`New InteropX tranaction: ${transactionHash} `);
137
+ } catch (error) {
138
+ this.logger.error(error);
139
+ }
140
+ }
141
+
142
+ if (processedEvents > 0)
143
+ this.logger.info(`${processedEvents} events processed`);
144
+ }
145
+
146
+ async start(): Promise<void> {
147
+ this.contractAddress = addresses[this.targetChainId].interopX;
148
+
149
+ this.provider = new JsonRpcRetryProvider(
150
+ getRpcProviderUrl(this.targetChainId)
151
+ );
152
+
153
+ this.contract = getContract<InteropX>(
154
+ this.contractAddress,
155
+ abi.interopX,
156
+ new ethers.Wallet(config.privateKey!, this.provider)
157
+ );
158
+
159
+ await super.start();
160
+ }
161
+ }
@@ -12,10 +12,11 @@ import { addresses } from "@/constants";
12
12
  import { ChainId } from "@/types";
13
13
  import config from "@/config";
14
14
  import { InteropX } from "@/typechain";
15
+ import { JsonRpcRetryProvider } from "@/providers";
15
16
 
16
- class SyncLogSubmitEvents extends BaseTask {
17
+ export default class SyncLogSubmitEvents extends BaseTask {
17
18
  contractAddress: string;
18
- provider: ethers.providers.JsonRpcProvider;
19
+ provider: JsonRpcRetryProvider;
19
20
  contract: InteropX;
20
21
  chainId: ChainId;
21
22
 
@@ -86,6 +87,7 @@ class SyncLogSubmitEvents extends BaseTask {
86
87
  submitEvent: {
87
88
  actionId,
88
89
  actionIdHashHash,
90
+ actionIdHash: actionIdHashHash,
89
91
  vnonce: vnonce.toString(),
90
92
  position: {
91
93
  withdraw: position.withdraw.map((v) => ({
@@ -121,7 +123,7 @@ class SyncLogSubmitEvents extends BaseTask {
121
123
  async start(): Promise<void> {
122
124
  this.contractAddress = addresses[this.chainId].interopX;
123
125
 
124
- this.provider = new ethers.providers.JsonRpcProvider(
126
+ this.provider = new JsonRpcRetryProvider(
125
127
  getRpcProviderUrl(this.chainId)
126
128
  );
127
129
 
@@ -133,6 +135,4 @@ class SyncLogSubmitEvents extends BaseTask {
133
135
 
134
136
  await super.start();
135
137
  }
136
- }
137
-
138
- export default SyncLogSubmitEvents;
138
+ }