@instadapp/interop-x 0.0.0-dev.a168c79 → 0.0.0-dev.adea608

Sign up to get free protection for your applications and to get access to all the features.
package/bin/interop-x CHANGED
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env node
2
- require('../dist/index')
2
+ require('../dist/src/index')
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@instadapp/interop-x",
3
- "version": "0.0.0-dev.a168c79",
3
+ "version": "0.0.0-dev.adea608",
4
4
  "license": "MIT",
5
5
  "main": "dist/index.js",
6
6
  "engines": {
@@ -12,7 +12,8 @@
12
12
  "build": "yarn generate-abi-types && export GIT_REF=$(git rev-parse --short HEAD) && rimraf ./dist && tsc -p tsconfig.json && replace-in-file '@GIT_SHORT_HASH@' $GIT_REF ./dist/**/*.js",
13
13
  "dev": "yarn generate-abi-types && NODE_ENV=development nodemon",
14
14
  "generate-abi-types": "typechain --target=ethers-v5 'src/abi/*.json' --out-dir 'src/typechain'",
15
- "prepublishOnly": "yarn build"
15
+ "prepublishOnly": "yarn build",
16
+ "postinstall": "patch-package"
16
17
  },
17
18
  "nodemonConfig": {
18
19
  "watch": [
@@ -45,7 +46,7 @@
45
46
  "libp2p-websockets": "^0.16.2",
46
47
  "luxon": "^2.3.2",
47
48
  "module-alias": "^2.2.2",
48
- "sequelize": "^6.19.0",
49
+ "sequelize": "6.18.0",
49
50
  "sqlite3": "^5.0.5",
50
51
  "waait": "^1.0.5"
51
52
  },
@@ -59,6 +60,8 @@
59
60
  "@types/fs-extra": "^9.0.13",
60
61
  "@types/node": "^17.0.17",
61
62
  "nodemon": "^2.0.15",
63
+ "patch-package": "^6.4.7",
64
+ "postinstall-postinstall": "^2.1.0",
62
65
  "replace-in-file": "^6.3.2",
63
66
  "rimraf": "^3.0.2",
64
67
  "ts-node": "^10.5.0",
@@ -5,7 +5,7 @@ exports.itokens = {
5
5
  1: [],
6
6
  137: [
7
7
  {
8
- address: '0x6c20F03598d5ABF729348E2868b0ff5e8A48aB1F',
8
+ address: '0xEab02fe1F016eE3e4106c1C6aad35FeEe657268E',
9
9
  symbol: 'USDC',
10
10
  }
11
11
  ],
package/dist/src/index.js CHANGED
@@ -40,15 +40,33 @@ catch (e) {
40
40
  logger.error('Invalid private key');
41
41
  process.exit(1);
42
42
  }
43
- logger.debug(`Starting Interop X Node (v${package_json_1.default.version} - rev.a168c79)`);
43
+ logger.debug(`Starting Interop X Node (v${package_json_1.default.version} - rev.adea608)`);
44
44
  const tasks_1 = require("@/tasks");
45
45
  const net_1 = require("@/net");
46
46
  const api_1 = require("@/api");
47
+ const db_1 = require("./db");
47
48
  async function main() {
48
49
  (0, net_1.startPeer)({});
49
50
  const tasks = new tasks_1.Tasks();
50
51
  tasks.start();
51
52
  (0, api_1.startApiServer)();
53
+ net_1.protocol.on('Transaction', async (payload) => {
54
+ if (!net_1.peerPool.isLeadNode(payload.peerId)) {
55
+ return;
56
+ }
57
+ const transaction = await db_1.Transaction.findOne({ where: { transactionHash: payload.data.transactionHash } });
58
+ if (!transaction) {
59
+ return;
60
+ }
61
+ transaction.sourceStatus = payload.data.sourceStatus;
62
+ transaction.sourceTransactionHash = payload.data.sourceTransactionHash;
63
+ transaction.sourceErrors = payload.data.sourceErrors;
64
+ transaction.targetStatus = payload.data.targetStatus;
65
+ transaction.targetTransactionHash = payload.data.targetTransactionHash;
66
+ transaction.targetErrors = payload.data.targetErrors;
67
+ transaction.status = payload.data.status;
68
+ await transaction.save();
69
+ });
52
70
  }
53
71
  main()
54
72
  .then(() => {
@@ -82,8 +82,12 @@ const startPeer = async ({}) => {
82
82
  net_1.protocol.start({
83
83
  libp2p: node
84
84
  });
85
- node.on("peer:discovery", (peer) => logger.log(`Discovered peer ${peer}`)); // peer disc.
86
- node.connectionManager.on("peer:connect", (connection) => logger.log(`Connected to ${connection.remotePeer.toB58String()}`));
85
+ node.on("peer:discovery", (peer) => {
86
+ // logger.log(`Discovered peer ${peer}`)
87
+ }); // peer disc.
88
+ node.connectionManager.on("peer:connect", (connection) => {
89
+ // logger.log(`Connected to ${connection.remotePeer.toB58String()}`)
90
+ });
87
91
  logger.log("Peer discovery started");
88
92
  await (0, waait_1.default)(1000);
89
93
  setInterval(() => net_1.protocol.sendPeerInfo({
@@ -6,6 +6,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.peerPool = exports.PeerPool = void 0;
7
7
  const types_1 = require("@/types");
8
8
  const config_1 = __importDefault(require("@/config"));
9
+ const logger_1 = __importDefault(require("@/logger"));
10
+ const utils_1 = require("ethers/lib/utils");
11
+ const logger = new logger_1.default('PeerPool');
9
12
  class PeerPool {
10
13
  constructor() {
11
14
  this.PEERS_CLEANUP_TIME_LIMIT = 1;
@@ -62,10 +65,14 @@ class PeerPool {
62
65
  * @emits {@link Event.POOL_PEER_ADDED}
63
66
  */
64
67
  add(peer) {
65
- if (peer && peer.id && !this.pool.get(peer.id)) {
68
+ if (peer && peer.id) {
69
+ const newPeer = !this.pool.get(peer.id);
66
70
  this.pool.set(peer.id, peer);
67
71
  peer.pooled = true;
68
- config_1.default.events.emit(types_1.Event.POOL_PEER_ADDED, peer);
72
+ if (newPeer) {
73
+ config_1.default.events.emit(types_1.Event.POOL_PEER_ADDED, peer);
74
+ logger.info(`Peer ${peer.id} with address ${peer.publicAddress} added to pool`);
75
+ }
69
76
  }
70
77
  }
71
78
  /**
@@ -78,6 +85,7 @@ class PeerPool {
78
85
  if (this.pool.delete(peer.id)) {
79
86
  peer.pooled = false;
80
87
  config_1.default.events.emit(types_1.Event.POOL_PEER_REMOVED, peer);
88
+ logger.info(`Peer ${peer.id} with address ${peer.publicAddress} removed from pool`);
81
89
  }
82
90
  }
83
91
  }
@@ -93,14 +101,21 @@ class PeerPool {
93
101
  get activePeerIds() {
94
102
  return this.activePeers.map((p) => p.id);
95
103
  }
104
+ isLeadNode(id) {
105
+ const peer = this.pool.get(id);
106
+ if (!peer) {
107
+ return false;
108
+ }
109
+ return (0, utils_1.getAddress)(peer.publicAddress) === (0, utils_1.getAddress)(config_1.default.leadNodeAddress);
110
+ }
96
111
  cleanup() {
97
- let compDate = Date.now() - this.PEERS_CLEANUP_TIME_LIMIT * 60;
98
- this.peers.forEach((peerInfo) => {
99
- if (peerInfo.updated.getTime() < compDate) {
100
- console.log(`Peer ${peerInfo.id} idle for ${this.PEERS_CLEANUP_TIME_LIMIT} minutes`);
101
- this.remove(peerInfo);
102
- }
103
- });
112
+ // let compDate = Date.now() - this.PEERS_CLEANUP_TIME_LIMIT * 60
113
+ // this.peers.forEach((peerInfo) => {
114
+ // if (peerInfo.updated.getTime() < compDate) {
115
+ // console.log(`Peer ${peerInfo.id} idle for ${this.PEERS_CLEANUP_TIME_LIMIT} minutes`)
116
+ // this.remove(peerInfo)
117
+ // }
118
+ // })
104
119
  }
105
120
  }
106
121
  exports.PeerPool = PeerPool;
@@ -33,12 +33,19 @@ class SignatureDialProtocol extends BaseDialProtocol_1.BaseDialProtocol {
33
33
  error: 'Event not found'
34
34
  };
35
35
  }
36
+ console.log("signing:", {
37
+ to: constants_1.addresses[transaction.targetChainId].multisend,
38
+ data: await (0, utils_1.buildDataForTransaction)(transaction, data.type),
39
+ chainId: transaction.targetChainId,
40
+ safeTxGas: data.safeTxGas,
41
+ nonce: data.safeNonce,
42
+ });
36
43
  const signedData = await (0, utils_1.signGnosisSafeTx)({
37
- //TODO: chain id depends on event type
38
- to: constants_1.addresses[transaction.sourceChainId].multisend,
39
- data: (0, utils_1.buildDataForTransaction)(transaction, data.type),
40
- chainId: transaction.sourceChainId,
44
+ to: constants_1.addresses[transaction.targetChainId].multisend,
45
+ data: await (0, utils_1.buildDataForTransaction)(transaction, data.type),
46
+ chainId: transaction.targetChainId,
41
47
  safeTxGas: data.safeTxGas,
48
+ nonce: data.safeNonce,
42
49
  }, { signer });
43
50
  return {
44
51
  signer: signer.address,
@@ -16,7 +16,7 @@ class Protocol extends stream_1.EventEmitter {
16
16
  this.protocolMessages = [
17
17
  {
18
18
  name: 'PeerInfo',
19
- code: 0x09,
19
+ code: 0x01,
20
20
  encode: (info) => [
21
21
  Buffer.from(info.publicAddress),
22
22
  ],
@@ -24,6 +24,30 @@ class Protocol extends stream_1.EventEmitter {
24
24
  publicAddress: publicAddress.toString(),
25
25
  }),
26
26
  },
27
+ {
28
+ name: 'Transaction',
29
+ code: 0x02,
30
+ encode: (transaction) => [
31
+ Buffer.from(transaction.transactionHash),
32
+ Buffer.from(transaction.sourceStatus),
33
+ Buffer.from(transaction.sourceTransactionHash),
34
+ transaction.sourceErrors.map((e) => Buffer.from(e)),
35
+ Buffer.from(transaction.targetStatus),
36
+ Buffer.from(transaction.targetTransactionHash),
37
+ transaction.targetErrors.map((e) => Buffer.from(e)),
38
+ Buffer.from(transaction.status),
39
+ ],
40
+ decode: ([transactionHash, sourceStatus, sourceTransactionHash, sourceErrors, targetStatus, targetTransactionHash, targetErrors, status]) => ({
41
+ transactionHash: transactionHash.toString(),
42
+ sourceStatus: sourceStatus.toString(),
43
+ sourceTransactionHash: sourceTransactionHash.toString(),
44
+ sourceErrors: sourceErrors.map((e) => e.toString()),
45
+ targetStatus: targetStatus.toString(),
46
+ targetTransactionHash: targetTransactionHash.toString(),
47
+ targetErrors: targetErrors.map((e) => e.toString()),
48
+ status: status.toString(),
49
+ }),
50
+ },
27
51
  ];
28
52
  }
29
53
  start({ libp2p, topic = null, }) {
@@ -75,6 +99,11 @@ class Protocol extends stream_1.EventEmitter {
75
99
  const encoded = ethereumjs_util_1.rlp.encode([message.code, message.encode(data)]);
76
100
  this.libp2p.pubsub.publish(this.topic, encoded);
77
101
  }
102
+ sendTransaction(transaction) {
103
+ const message = this.protocolMessages.find((m) => m.name === 'Transaction');
104
+ const encoded = ethereumjs_util_1.rlp.encode([message.code, message.encode(transaction)]);
105
+ this.libp2p.pubsub.publish(this.topic, encoded);
106
+ }
78
107
  async requestSignatures(data, peerIds) {
79
108
  try {
80
109
  peerIds = peerIds || __1.peerPool.activePeerIds;
@@ -28,7 +28,7 @@ class BaseTask extends events_1.default {
28
28
  }
29
29
  }
30
30
  catch (err) {
31
- this.logger.error(`poll check error: ${err.message}\ntrace: ${err.stack}`);
31
+ this.logger.error(`poll check error:\n${err.message}\ntrace: ${err.stack}`);
32
32
  }
33
33
  await this.postPollHandler();
34
34
  }
@@ -0,0 +1,147 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const BaseTask_1 = require("../BaseTask");
7
+ const logger_1 = __importDefault(require("@/logger"));
8
+ const ethers_1 = require("ethers");
9
+ const abi_1 = __importDefault(require("@/abi"));
10
+ const db_1 = require("@/db");
11
+ const utils_1 = require("@/utils");
12
+ const constants_1 = require("@/constants");
13
+ const config_1 = __importDefault(require("@/config"));
14
+ const sequelize_1 = require("sequelize");
15
+ const waait_1 = __importDefault(require("waait"));
16
+ const net_1 = require("@/net");
17
+ const generateGnosisTransaction = async (transactionData, safeContract) => {
18
+ console.log(transactionData);
19
+ let isExecuted = await safeContract.dataHashes(await safeContract.getTransactionHash(transactionData.to, transactionData.value, transactionData.data, transactionData.operation, transactionData.safeTxGas, transactionData.baseGas, transactionData.gasPrice, transactionData.gasToken, transactionData.refundReceiver, transactionData.nonce));
20
+ while (isExecuted == 1) {
21
+ transactionData.safeTxGas = ethers_1.BigNumber.from(String(transactionData.safeTxGas)).add(1).toString();
22
+ isExecuted = await safeContract.dataHashes(await safeContract.getTransactionHash(transactionData.to, transactionData.value, transactionData.data, transactionData.operation, transactionData.safeTxGas, transactionData.baseGas, transactionData.gasPrice, transactionData.gasToken, transactionData.refundReceiver, transactionData.nonce));
23
+ }
24
+ return transactionData;
25
+ };
26
+ class ProcessWithdrawEvents extends BaseTask_1.BaseTask {
27
+ constructor({ chainId }) {
28
+ super({
29
+ logger: new logger_1.default("InteropXGateway::ProcessWithdrawEvents"),
30
+ });
31
+ this.leadNodeOnly = true;
32
+ this.chainId = chainId;
33
+ }
34
+ async pollHandler() {
35
+ var _a;
36
+ const blockNumber = await this.provider.getBlockNumber();
37
+ const transaction = await db_1.Transaction.findOne({
38
+ where: {
39
+ status: 'pending',
40
+ sourceStatus: 'success',
41
+ targetStatus: 'uninitialised',
42
+ action: 'withdraw',
43
+ sourceCreatedAt: {
44
+ [sequelize_1.Op.gte]: new Date(Date.now() - 12 * 60 * 60 * 1000),
45
+ },
46
+ targetDelayUntil: {
47
+ [sequelize_1.Op.or]: {
48
+ [sequelize_1.Op.is]: null,
49
+ [sequelize_1.Op.lt]: new Date(),
50
+ }
51
+ },
52
+ sourceBlockNumber: {
53
+ [sequelize_1.Op.lt]: blockNumber - 12,
54
+ },
55
+ sourceChainId: this.chainId,
56
+ }
57
+ });
58
+ if (!transaction) {
59
+ return;
60
+ }
61
+ console.log(`Processing transaction ${transaction.transactionHash}`);
62
+ transaction.targetStatus = 'pending';
63
+ await transaction.save();
64
+ // refresh event data?
65
+ const targetChainProvider = new ethers_1.ethers.providers.JsonRpcProvider((0, utils_1.getRpcProviderUrl)(transaction.targetChainId));
66
+ const targetWallet = new ethers_1.ethers.Wallet(config_1.default.privateKey, targetChainProvider);
67
+ const safeAddress = constants_1.addresses[transaction.targetChainId].gnosisSafe;
68
+ const safeContract = (0, utils_1.getContract)(safeAddress, abi_1.default.gnosisSafe, targetWallet);
69
+ const ownersThreshold = await safeContract.getThreshold();
70
+ await (0, waait_1.default)(10000);
71
+ let gnosisTx = await generateGnosisTransaction({
72
+ baseGas: "0",
73
+ data: await (0, utils_1.buildDataForTransaction)(transaction),
74
+ gasPrice: "0",
75
+ gasToken: "0x0000000000000000000000000000000000000000",
76
+ nonce: '0',
77
+ operation: "1",
78
+ refundReceiver: "0x0000000000000000000000000000000000000000",
79
+ safeAddress: safeAddress,
80
+ safeTxGas: "79668",
81
+ to: constants_1.addresses[transaction.targetChainId].multisend,
82
+ value: "0",
83
+ }, safeContract);
84
+ const owners = await safeContract.getOwners().then(owners => owners.map(owner => owner.toLowerCase()));
85
+ const ownerPeerIds = net_1.peerPool.activePeers.filter(peer => owners.includes(peer.publicAddress.toLowerCase())).map(peer => peer.id);
86
+ console.log(`Collecting signatures for execution ${transaction.transactionHash}`);
87
+ console.log(ownerPeerIds);
88
+ const signatures = await net_1.protocol.requestSignatures({
89
+ type: 'source',
90
+ transactionHash: transaction.transactionHash,
91
+ safeTxGas: gnosisTx.safeTxGas,
92
+ safeNonce: gnosisTx.nonce
93
+ }, ownerPeerIds);
94
+ const validSignatures = signatures.filter(s => !!s.data && s.data !== '0x');
95
+ console.log({ signatures, validSignatures, ownersThreshold: ownersThreshold.toString() });
96
+ if (validSignatures.length === 0 || ownersThreshold.gt(validSignatures.length)) {
97
+ await transaction.save();
98
+ transaction.targetDelayUntil = new Date(Date.now() + 30 * 1000);
99
+ transaction.targetStatus = 'uninitialised';
100
+ await transaction.save();
101
+ const errorMessage = (_a = signatures.find(s => !!s.error)) === null || _a === void 0 ? void 0 : _a.error;
102
+ throw new Error(`Not enough signatures` + (errorMessage ? `: ${errorMessage}` : ''));
103
+ }
104
+ console.log(`Executing transaction for execution ${transaction.transactionHash}`);
105
+ const { data: txData } = await safeContract.populateTransaction.execTransaction(gnosisTx.to, gnosisTx.value, gnosisTx.data, gnosisTx.operation, gnosisTx.safeTxGas, gnosisTx.baseGas, gnosisTx.gasPrice, gnosisTx.gasToken, gnosisTx.refundReceiver, (0, utils_1.buildSignatureBytes)(validSignatures));
106
+ console.log({
107
+ from: targetWallet.address,
108
+ gasPrice: ethers_1.BigNumber.from(120 * 10 ** 9).toString(),
109
+ to: safeAddress,
110
+ data: txData,
111
+ });
112
+ const txSent = await targetWallet.sendTransaction({
113
+ from: targetWallet.address,
114
+ gasPrice: ethers_1.BigNumber.from(120 * 10 ** 9),
115
+ to: safeAddress,
116
+ data: txData,
117
+ });
118
+ const receipt = await txSent.wait();
119
+ const parsedLogs = [];
120
+ receipt.logs.forEach((log) => {
121
+ try {
122
+ parsedLogs.push(safeContract.interface.parseLog(log));
123
+ }
124
+ catch (e) { }
125
+ });
126
+ if (parsedLogs.find(e => e.name === 'ExecutionSuccess')) {
127
+ console.log('ExecutionSuccess');
128
+ transaction.targetStatus = 'success';
129
+ transaction.targetTransactionHash = txSent.hash;
130
+ transaction.status = 'success';
131
+ await transaction.save();
132
+ }
133
+ else {
134
+ console.log('ExecutionFailure');
135
+ transaction.targetStatus = 'failed';
136
+ transaction.targetTransactionHash = txSent.hash;
137
+ transaction.status = 'failed';
138
+ await transaction.save();
139
+ }
140
+ }
141
+ async start() {
142
+ this.logger.info(`Starting execution watcher on interop chain`);
143
+ this.provider = new ethers_1.ethers.providers.JsonRpcProvider((0, utils_1.getRpcProviderUrl)(this.chainId));
144
+ await super.start();
145
+ }
146
+ }
147
+ exports.default = ProcessWithdrawEvents;
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const BaseTask_1 = require("../BaseTask");
7
+ const logger_1 = __importDefault(require("@/logger"));
8
+ const ethers_1 = require("ethers");
9
+ const abi_1 = __importDefault(require("@/abi"));
10
+ const db_1 = require("@/db");
11
+ const utils_1 = require("@/utils");
12
+ const config_1 = __importDefault(require("@/config"));
13
+ class SyncWithdrawEvents extends BaseTask_1.BaseTask {
14
+ constructor({ chainId, itokenAddress }) {
15
+ super({
16
+ logger: new logger_1.default("InteropBridgeToken::SyncWithdrawEvents"),
17
+ });
18
+ this.chainId = chainId;
19
+ this.itokenAddress = itokenAddress;
20
+ }
21
+ async pollHandler() {
22
+ const currentBlock = await this.provider.getBlockNumber();
23
+ const events = await this.contract.queryFilter(this.contract.filters.Burn(), currentBlock - 2000, currentBlock);
24
+ let processedEvents = 0;
25
+ for (const event of events) {
26
+ try {
27
+ if (!event.args) {
28
+ continue;
29
+ }
30
+ const { to, amount, chainId } = event.args;
31
+ const uniqueIdentifier = {
32
+ action: 'withdraw',
33
+ submitTransactionHash: event.transactionHash,
34
+ sourceChainId: this.chainId,
35
+ targetChainId: chainId.toNumber(),
36
+ };
37
+ if (await db_1.Transaction.findOne({ where: uniqueIdentifier })) {
38
+ continue;
39
+ }
40
+ const tx = await event.getTransaction();
41
+ await db_1.Transaction.create(Object.assign(Object.assign({}, uniqueIdentifier), { transactionHash: (0, utils_1.generateInteropTransactionHash)(uniqueIdentifier), from: tx.from, to, submitTransactionHash: event.transactionHash, submitBlockNumber: event.blockNumber,
42
+ // submit & source are the same
43
+ sourceTransactionHash: event.transactionHash, sourceBlockNumber: event.blockNumber, sourceStatus: "success", targetStatus: "uninitialised", submitEvent: {
44
+ to,
45
+ amount: amount.toString(),
46
+ itoken: this.itokenAddress,
47
+ chainId: chainId.toString()
48
+ }, sourceEvent: {
49
+ to,
50
+ amount: amount.toString(),
51
+ itoken: this.itokenAddress,
52
+ chainId: chainId.toString(),
53
+ }, status: "pending" }));
54
+ this.logger.info(`Withdraw queued: ${event.transactionHash} ${event.blockNumber}`);
55
+ }
56
+ catch (error) {
57
+ this.logger.error(error);
58
+ }
59
+ }
60
+ if (processedEvents > 0)
61
+ this.logger.info(`${processedEvents} events processed`);
62
+ }
63
+ async start() {
64
+ this.logger.info(`Starting execution watcher on interop chain`);
65
+ this.provider = new ethers_1.ethers.providers.JsonRpcProvider((0, utils_1.getRpcProviderUrl)(this.chainId));
66
+ this.contract = (0, utils_1.getContract)(this.itokenAddress, abi_1.default.interopBridgeToken, new ethers_1.ethers.Wallet(config_1.default.privateKey, this.provider));
67
+ await super.start();
68
+ }
69
+ }
70
+ exports.default = SyncWithdrawEvents;
@@ -15,6 +15,7 @@ const sequelize_1 = require("sequelize");
15
15
  const waait_1 = __importDefault(require("waait"));
16
16
  const net_1 = require("@/net");
17
17
  const generateGnosisTransaction = async (transactionData, safeContract) => {
18
+ console.log(transactionData);
18
19
  let isExecuted = await safeContract.dataHashes(await safeContract.getTransactionHash(transactionData.to, transactionData.value, transactionData.data, transactionData.operation, transactionData.safeTxGas, transactionData.baseGas, transactionData.gasPrice, transactionData.gasToken, transactionData.refundReceiver, transactionData.nonce));
19
20
  while (isExecuted == 1) {
20
21
  transactionData.safeTxGas = ethers_1.BigNumber.from(String(transactionData.safeTxGas)).add(1).toString();
@@ -37,30 +38,39 @@ class ProcessDepositEvents extends BaseTask_1.BaseTask {
37
38
  where: {
38
39
  status: 'pending',
39
40
  sourceStatus: 'success',
41
+ targetStatus: 'uninitialised',
40
42
  action: 'deposit',
41
43
  sourceCreatedAt: {
42
44
  [sequelize_1.Op.gte]: new Date(Date.now() - 12 * 60 * 60 * 1000),
43
45
  },
46
+ targetDelayUntil: {
47
+ [sequelize_1.Op.or]: {
48
+ [sequelize_1.Op.is]: null,
49
+ [sequelize_1.Op.lt]: new Date(),
50
+ }
51
+ },
44
52
  sourceBlockNumber: {
45
53
  [sequelize_1.Op.lt]: blockNumber - 12,
46
- }
54
+ },
55
+ sourceChainId: this.chainId,
47
56
  }
48
57
  });
49
58
  if (!transaction) {
50
59
  return;
51
60
  }
52
- transaction.sourceStatus = 'pending';
61
+ console.log(`Processing transaction ${transaction.transactionHash}`);
62
+ transaction.targetStatus = 'pending';
53
63
  await transaction.save();
54
64
  // refresh event data?
55
65
  const targetChainProvider = new ethers_1.ethers.providers.JsonRpcProvider((0, utils_1.getRpcProviderUrl)(transaction.targetChainId));
56
66
  const targetWallet = new ethers_1.ethers.Wallet(config_1.default.privateKey, targetChainProvider);
57
67
  const safeAddress = constants_1.addresses[transaction.targetChainId].gnosisSafe;
58
- const safeContract = new ethers_1.ethers.Contract(safeAddress, abi_1.default.gnosisSafe, targetWallet);
68
+ const safeContract = (0, utils_1.getContract)(safeAddress, abi_1.default.gnosisSafe, targetWallet);
59
69
  const ownersThreshold = await safeContract.getThreshold();
60
70
  await (0, waait_1.default)(10000);
61
71
  let gnosisTx = await generateGnosisTransaction({
62
72
  baseGas: "0",
63
- data: (0, utils_1.buildDataForTransaction)(transaction),
73
+ data: await (0, utils_1.buildDataForTransaction)(transaction),
64
74
  gasPrice: "0",
65
75
  gasToken: "0x0000000000000000000000000000000000000000",
66
76
  nonce: '0',
@@ -74,6 +84,7 @@ class ProcessDepositEvents extends BaseTask_1.BaseTask {
74
84
  const owners = await safeContract.getOwners().then(owners => owners.map(owner => owner.toLowerCase()));
75
85
  const ownerPeerIds = net_1.peerPool.activePeers.filter(peer => owners.includes(peer.publicAddress.toLowerCase())).map(peer => peer.id);
76
86
  console.log(`Collecting signatures for execution ${transaction.transactionHash}`);
87
+ console.log(ownerPeerIds);
77
88
  const signatures = await net_1.protocol.requestSignatures({
78
89
  type: 'source',
79
90
  transactionHash: transaction.transactionHash,
@@ -84,33 +95,23 @@ class ProcessDepositEvents extends BaseTask_1.BaseTask {
84
95
  console.log({ signatures, validSignatures, ownersThreshold: ownersThreshold.toString() });
85
96
  if (validSignatures.length === 0 || ownersThreshold.gt(validSignatures.length)) {
86
97
  await transaction.save();
87
- transaction.sourceDelayUntil = new Date(Date.now() + 30 * 1000);
88
- transaction.sourceStatus = 'pending';
98
+ transaction.targetDelayUntil = new Date(Date.now() + 30 * 1000);
99
+ transaction.targetStatus = 'uninitialised';
89
100
  await transaction.save();
90
101
  const errorMessage = (_a = signatures.find(s => !!s.error)) === null || _a === void 0 ? void 0 : _a.error;
91
102
  throw new Error(`Not enough signatures` + (errorMessage ? `: ${errorMessage}` : ''));
92
103
  }
93
- const execTransactionParams = [
94
- gnosisTx.to,
95
- gnosisTx.value,
96
- gnosisTx.data,
97
- gnosisTx.operation,
98
- gnosisTx.safeTxGas,
99
- gnosisTx.baseGas,
100
- gnosisTx.gasPrice,
101
- gnosisTx.gasToken,
102
- gnosisTx.refundReceiver,
103
- (0, utils_1.buildSignatureBytes)(validSignatures),
104
- ];
105
104
  console.log(`Executing transaction for execution ${transaction.transactionHash}`);
105
+ const { data: txData } = await safeContract.populateTransaction.execTransaction(gnosisTx.to, gnosisTx.value, gnosisTx.data, gnosisTx.operation, gnosisTx.safeTxGas, gnosisTx.baseGas, gnosisTx.gasPrice, gnosisTx.gasToken, gnosisTx.refundReceiver, (0, utils_1.buildSignatureBytes)(validSignatures));
106
106
  console.log({
107
- execTransactionParams
107
+ from: targetWallet.address,
108
+ gasPrice: ethers_1.BigNumber.from(120 * 10 ** 9).toString(),
109
+ to: safeAddress,
110
+ data: txData,
108
111
  });
109
- const { data: txData } = await safeContract.populateTransaction.execTransaction(gnosisTx.to, gnosisTx.value, gnosisTx.data, gnosisTx.operation, gnosisTx.safeTxGas, gnosisTx.baseGas, gnosisTx.gasPrice, gnosisTx.gasToken, gnosisTx.refundReceiver, (0, utils_1.buildSignatureBytes)(validSignatures));
110
112
  const txSent = await targetWallet.sendTransaction({
111
113
  from: targetWallet.address,
112
114
  gasPrice: ethers_1.BigNumber.from(120 * 10 ** 9),
113
- gasLimit: ethers_1.BigNumber.from(6000000),
114
115
  to: safeAddress,
115
116
  data: txData,
116
117
  });
@@ -124,16 +125,25 @@ class ProcessDepositEvents extends BaseTask_1.BaseTask {
124
125
  });
125
126
  if (parsedLogs.find(e => e.name === 'ExecutionSuccess')) {
126
127
  console.log('ExecutionSuccess');
128
+ transaction.targetStatus = 'success';
129
+ transaction.targetTransactionHash = txSent.hash;
130
+ transaction.status = 'success';
131
+ await transaction.save();
127
132
  }
128
133
  else {
129
134
  console.log('ExecutionFailure');
135
+ transaction.targetStatus = 'failed';
136
+ transaction.targetTransactionHash = txSent.hash;
137
+ transaction.status = 'failed';
138
+ await transaction.save();
130
139
  }
140
+ net_1.protocol.sendTransaction(transaction);
131
141
  }
132
142
  async start() {
133
143
  this.logger.info(`Starting execution watcher on interop chain`);
134
144
  this.contractAddress = constants_1.addresses[this.chainId].interopXGateway;
135
145
  this.provider = new ethers_1.ethers.providers.JsonRpcProvider((0, utils_1.getRpcProviderUrl)(this.chainId));
136
- this.contract = new ethers_1.ethers.Contract(this.contractAddress, abi_1.default.interopXGateway, new ethers_1.ethers.Wallet(config_1.default.privateKey, this.provider));
146
+ this.contract = (0, utils_1.getContract)(this.contractAddress, abi_1.default.interopXGateway, new ethers_1.ethers.Wallet(config_1.default.privateKey, this.provider));
137
147
  await super.start();
138
148
  }
139
149
  }
@@ -45,17 +45,17 @@ class SyncDepositEvents extends BaseTask_1.BaseTask {
45
45
  sourceChainId: sourceChainId.toString(),
46
46
  targetChainId: targetChainId.toString(),
47
47
  token: token,
48
- ammout: amount.toString(),
48
+ amount: amount.toString(),
49
49
  vnonce: vnonce.toString(),
50
50
  }, sourceEvent: {
51
51
  user,
52
52
  sourceChainId: sourceChainId.toString(),
53
53
  targetChainId: targetChainId.toString(),
54
54
  token: token,
55
- ammout: amount.toString(),
55
+ amount: amount.toString(),
56
56
  vnonce: vnonce.toString(),
57
57
  }, status: "pending" }));
58
- this.logger.info(`Execution queued: ${event.transactionHash} ${event.blockNumber}`);
58
+ this.logger.info(`Deposit queued: ${event.transactionHash} ${event.blockNumber}`);
59
59
  }
60
60
  catch (error) {
61
61
  this.logger.error(error);
@@ -68,7 +68,7 @@ class SyncDepositEvents extends BaseTask_1.BaseTask {
68
68
  this.logger.info(`Starting execution watcher on interop chain`);
69
69
  this.contractAddress = constants_1.addresses[this.chainId].interopXGateway;
70
70
  this.provider = new ethers_1.ethers.providers.JsonRpcProvider((0, utils_1.getRpcProviderUrl)(this.chainId));
71
- this.contract = new ethers_1.ethers.Contract(this.contractAddress, abi_1.default.interopXGateway, new ethers_1.ethers.Wallet(config_1.default.privateKey, this.provider));
71
+ this.contract = (0, utils_1.getContract)(this.contractAddress, abi_1.default.interopXGateway, new ethers_1.ethers.Wallet(config_1.default.privateKey, this.provider));
72
72
  await super.start();
73
73
  }
74
74
  }
@@ -4,12 +4,25 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.Tasks = void 0;
7
+ const ProcessDepositEvents_1 = __importDefault(require("./InteropXGateway/ProcessDepositEvents"));
7
8
  const SyncDepositEvents_1 = __importDefault(require("./InteropXGateway/SyncDepositEvents"));
9
+ const SyncWithdrawEvents_1 = __importDefault(require("./InteropBridge/SyncWithdrawEvents"));
10
+ const ProcessWithdrawEvents_1 = __importDefault(require("./InteropBridge/ProcessWithdrawEvents"));
8
11
  class Tasks {
9
12
  constructor() {
10
13
  this.tasks = [
11
14
  new SyncDepositEvents_1.default({
12
15
  chainId: 43114
16
+ }),
17
+ new ProcessDepositEvents_1.default({
18
+ chainId: 43114
19
+ }),
20
+ new SyncWithdrawEvents_1.default({
21
+ chainId: 137,
22
+ itokenAddress: '0xEab02fe1F016eE3e4106c1C6aad35FeEe657268E',
23
+ }),
24
+ new ProcessWithdrawEvents_1.default({
25
+ chainId: 137,
13
26
  })
14
27
  ];
15
28
  }