@instadapp/interop-x 0.0.0-dev.59f2858 → 0.0.0-dev.59f84ce

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. package/bin/interop-x +1 -1
  2. package/dist/package.json +73 -0
  3. package/dist/{abi → src/abi}/erc20.json +0 -0
  4. package/dist/{abi → src/abi}/gnosisSafe.json +0 -0
  5. package/dist/{abi → src/abi}/index.js +2 -4
  6. package/dist/src/abi/interopXContract.json +391 -0
  7. package/dist/src/alias.js +10 -0
  8. package/dist/{api → src/api}/index.js +6 -3
  9. package/dist/{config → src/config}/index.js +11 -1
  10. package/dist/{constants → src/constants}/addresses.js +3 -11
  11. package/dist/{constants → src/constants}/index.js +0 -0
  12. package/dist/{constants → src/constants}/tokens.js +0 -0
  13. package/dist/{db → src/db}/index.js +0 -0
  14. package/dist/{db → src/db}/models/index.js +0 -0
  15. package/dist/{db → src/db}/models/transaction.js +27 -7
  16. package/dist/{db → src/db}/sequelize.js +0 -0
  17. package/dist/src/gnosis/actions/index.js +9 -0
  18. package/dist/src/gnosis/actions/withdraw/index.js +41 -0
  19. package/dist/src/gnosis/index.js +20 -0
  20. package/dist/src/index.js +117 -0
  21. package/dist/{logger → src/logger}/index.js +0 -0
  22. package/dist/{net → src/net}/index.js +0 -0
  23. package/dist/{net → src/net}/peer/index.js +8 -3
  24. package/dist/{net → src/net}/pool/index.js +32 -9
  25. package/dist/{net → src/net}/protocol/dial/BaseDialProtocol.js +0 -0
  26. package/dist/{net → src/net}/protocol/dial/SignatureDialProtocol.js +17 -12
  27. package/dist/src/net/protocol/dial/TransactionStatusDialProtocol.js +30 -0
  28. package/dist/{net → src/net}/protocol/index.js +51 -1
  29. package/dist/src/tasks/AutoUpdateTask.js +70 -0
  30. package/dist/{tasks → src/tasks}/BaseTask.js +12 -4
  31. package/dist/src/tasks/InteropXContract/ProcessBridgeRequestEvents.js +146 -0
  32. package/dist/src/tasks/InteropXContract/SyncBridgeRequestEvents.js +78 -0
  33. package/dist/src/tasks/Transactions/SyncTransactionStatusTask.js +55 -0
  34. package/dist/src/tasks/index.js +33 -0
  35. package/dist/{typechain → src/typechain}/Erc20.js +0 -0
  36. package/dist/{typechain → src/typechain}/GnosisSafe.js +0 -0
  37. package/dist/{typechain/InteropBridgeToken.js → src/typechain/InteropXContract.js} +0 -0
  38. package/dist/{typechain → src/typechain}/common.js +0 -0
  39. package/dist/{typechain → src/typechain}/factories/Erc20__factory.js +0 -0
  40. package/dist/{typechain → src/typechain}/factories/GnosisSafe__factory.js +0 -0
  41. package/dist/src/typechain/factories/InteropXContract__factory.js +526 -0
  42. package/dist/src/typechain/factories/index.js +12 -0
  43. package/dist/{typechain → src/typechain}/index.js +3 -5
  44. package/dist/{types.js → src/types.js} +0 -0
  45. package/dist/src/utils/index.js +168 -0
  46. package/package.json +10 -6
  47. package/patches/@ethersproject+properties+5.6.0.patch +13 -0
  48. package/src/abi/index.ts +2 -4
  49. package/src/abi/interopXContract.json +391 -0
  50. package/src/alias.ts +6 -0
  51. package/src/api/index.ts +5 -2
  52. package/src/config/index.ts +11 -1
  53. package/src/constants/addresses.ts +3 -11
  54. package/src/db/models/transaction.ts +61 -19
  55. package/src/gnosis/actions/index.ts +5 -0
  56. package/src/gnosis/actions/withdraw/index.ts +56 -0
  57. package/src/gnosis/index.ts +19 -0
  58. package/src/index.ts +95 -24
  59. package/src/net/peer/index.ts +9 -7
  60. package/src/net/pool/index.ts +41 -11
  61. package/src/net/protocol/dial/SignatureDialProtocol.ts +19 -13
  62. package/src/net/protocol/dial/TransactionStatusDialProtocol.ts +33 -0
  63. package/src/net/protocol/index.ts +67 -1
  64. package/src/tasks/AutoUpdateTask.ts +82 -0
  65. package/src/tasks/BaseTask.ts +14 -4
  66. package/src/tasks/InteropXContract/ProcessBridgeRequestEvents.ts +208 -0
  67. package/src/tasks/InteropXContract/SyncBridgeRequestEvents.ts +116 -0
  68. package/src/tasks/Transactions/SyncTransactionStatusTask.ts +67 -0
  69. package/src/tasks/index.ts +16 -4
  70. package/src/typechain/InteropXContract.ts +524 -0
  71. package/src/typechain/factories/InteropXContract__factory.ts +533 -0
  72. package/src/typechain/factories/index.ts +1 -2
  73. package/src/typechain/index.ts +2 -4
  74. package/src/utils/index.ts +118 -7
  75. package/tsconfig.json +7 -2
  76. package/dist/abi/interopBridgeToken.json +0 -286
  77. package/dist/abi/interopXGateway.json +0 -184
  78. package/dist/index.js +0 -66
  79. package/dist/tasks/InteropXGateway/SyncDepositEvents.js +0 -66
  80. package/dist/tasks/index.js +0 -27
  81. package/dist/typechain/InteropXGateway.js +0 -2
  82. package/dist/typechain/factories/InteropBridgeToken__factory.js +0 -459
  83. package/dist/typechain/factories/InteropXGateway__factory.js +0 -265
  84. package/dist/typechain/factories/index.js +0 -14
  85. package/dist/utils/index.js +0 -101
  86. package/src/abi/interopBridgeToken.json +0 -286
  87. package/src/abi/interopXGateway.json +0 -184
  88. package/src/tasks/InteropXGateway/SyncDepositEvents.ts +0 -111
  89. package/src/typechain/InteropBridgeToken.ts +0 -686
  90. package/src/typechain/InteropXGateway.ts +0 -407
  91. package/src/typechain/factories/InteropBridgeToken__factory.ts +0 -466
  92. package/src/typechain/factories/InteropXGateway__factory.ts +0 -272
@@ -1,5 +1,7 @@
1
1
  import { ethers, Wallet } from "ethers"
2
2
  import { EventBus, EventBusType } from "@/types"
3
+ import fs from 'fs-extra'
4
+ import expandHomeDir from "expand-home-dir";
3
5
 
4
6
  class Config {
5
7
  public readonly events: EventBusType
@@ -8,14 +10,18 @@ class Config {
8
10
  public readonly privateKey: string
9
11
  public readonly wallet: Wallet
10
12
  public readonly staging: boolean
13
+ public readonly autoUpdate: boolean
14
+ public readonly baseConfigPath: string
11
15
 
12
16
  constructor() {
13
17
  this.events = new EventBus() as EventBusType
14
- this.maxPeers = 10
18
+ this.maxPeers = 20
15
19
  this.privateKey = process.env.PRIVATE_KEY as string;
16
20
  this.staging = !! process.env.STAGING && process.env.STAGING === 'true';
21
+ this.autoUpdate = !! process.env.AUTO_UPDATE && process.env.AUTO_UPDATE === 'true';
17
22
  this.wallet = new Wallet(this.privateKey);
18
23
  this.leadNodeAddress = '0x910E413DBF3F6276Fe8213fF656726bDc142E08E'
24
+ this.baseConfigPath = expandHomeDir(`~/.interop-x`);
19
25
  }
20
26
 
21
27
  get publicAddress(){
@@ -25,6 +31,10 @@ class Config {
25
31
  isLeadNode() {
26
32
  return ethers.utils.getAddress(this.leadNodeAddress) === ethers.utils.getAddress(this.wallet.address)
27
33
  }
34
+
35
+ isMaintenanceMode(){
36
+ return fs.existsSync(this.baseConfigPath + '/maintenance')
37
+ }
28
38
  }
29
39
 
30
40
  export default new Config()
@@ -2,24 +2,16 @@ export const addresses = {
2
2
  1: {
3
3
  gnosisSafe: '0x811Bff6eF88dAAA0aD6438386B534A81cE3F160F',
4
4
  multisend: '0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761',
5
- interopXGateway: '',
6
- interopBridgeTokens: [],
5
+ interopXContract: '',
7
6
  },
8
7
  137: {
9
8
  gnosisSafe: '0x5635d2910e51da33d9DC0422c893CF4F28B69A25',
10
9
  multisend: '0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761',
11
- interopXGateway: '',
12
- interopBridgeTokens: [
13
- {
14
- address: '0x6c20F03598d5ABF729348E2868b0ff5e8A48aB1F',
15
- symbol : 'USDC',
16
- }
17
- ],
10
+ interopXContract: '0x2189741c8cAc1cf51570932817A7d6390646C80e',
18
11
  },
19
12
  43114: {
20
13
  gnosisSafe: '0x31d7a5194Fe60AC209Cf1Ce2d539C9A60662Ed6b',
21
14
  multisend: '0x998739BFdAAdde7C933B942a68053933098f9EDa',
22
- interopXGateway: '0x8D27758751BA488690974B6Ccfcda771D462945f',
23
- interopBridgeTokens: [],
15
+ interopXContract: '0x1867DF97Ec24bb0bbD4AD464F0Be9C6713422EAE',
24
16
  }
25
17
  }
@@ -1,38 +1,61 @@
1
1
  import { sequelize } from '@/db/sequelize'
2
2
  import { CreationOptional, InferAttributes, InferCreationAttributes, Model, DataTypes } from 'sequelize';
3
3
 
4
+ export interface IPositionTokenInfo{
5
+ amount: string;
6
+ sourceToken: string;
7
+ targetToken: string;
8
+ }
9
+
10
+ export interface IPosition {
11
+ supply: IPositionTokenInfo[];
12
+ withdraw: IPositionTokenInfo[];
13
+ }
14
+
4
15
  export class Transaction extends Model<InferAttributes<Transaction>, InferCreationAttributes<Transaction>> {
5
16
  declare id: CreationOptional<number>;
6
17
 
7
18
  declare transactionHash: string;
19
+
8
20
  declare action: string;
9
- declare from: string;
10
- declare to: string;
21
+ declare bridger: string;
22
+ declare requestTransactionHash: string;
11
23
 
24
+ declare requestBlockNumber: number;
12
25
 
13
26
  declare sourceChainId: number;
14
- declare sourceTransactionHash: string;
15
- declare sourceBlockNumber: number;
16
- declare sourceStatus: string;
27
+ declare sourceTransactionHash: CreationOptional<string>;
28
+ declare sourceBlockNumber: CreationOptional<number>;
29
+ declare sourceStatus: CreationOptional<string>;
17
30
  declare sourceErrors: CreationOptional<string[]>;
31
+ declare sourceLogs: CreationOptional<any[]>;
18
32
  declare sourceCreatedAt: CreationOptional<Date>;
19
33
  declare sourceDelayUntil: CreationOptional<Date>;
20
34
 
21
35
  declare targetChainId: number;
22
36
  declare targetTransactionHash: CreationOptional<string>;
23
37
  declare targetBlockNumber: CreationOptional<number>;
24
- declare targetStatus: string;
38
+ declare targetStatus: CreationOptional<string>;
25
39
  declare targetErrors: CreationOptional<string[]>;
40
+ declare targetLogs: CreationOptional<any[]>;
26
41
  declare targetCreatedAt: CreationOptional<Date>;
27
42
  declare targetDelayUntil: CreationOptional<Date>;
28
43
 
29
- declare submitEvent: any;
30
- declare sourceEvent: CreationOptional<any>;
31
- declare targetEvent: CreationOptional<any>;
32
-
44
+ declare requestEvent: {
45
+ bridger: string;
46
+ metadata: string;
47
+ position: IPosition;
48
+ sourceChainId: number;
49
+ targetChainId: number;
50
+ };
51
+ declare requestSendEvent: CreationOptional<any>;
52
+ declare committedEvent: CreationOptional<any>;
53
+ declare completedEvent: CreationOptional<any>;
54
+
55
+ declare position: any;
33
56
  declare metadata: CreationOptional<any>;
34
57
 
35
- declare status: string;
58
+ declare status: CreationOptional<string>;
36
59
 
37
60
  declare createdAt: CreationOptional<Date>;
38
61
  declare updatedAt: CreationOptional<Date>;
@@ -45,21 +68,28 @@ Transaction.init({
45
68
  primaryKey: true
46
69
  },
47
70
 
71
+ requestTransactionHash: DataTypes.NUMBER,
72
+ requestBlockNumber: DataTypes.NUMBER,
48
73
 
49
74
  transactionHash: DataTypes.STRING,
50
75
  action: DataTypes.STRING,
51
-
52
- from: DataTypes.STRING,
53
- to: DataTypes.STRING,
76
+ bridger: DataTypes.STRING,
54
77
 
55
78
  sourceChainId: DataTypes.NUMBER,
56
79
  sourceTransactionHash: DataTypes.STRING,
57
80
  sourceBlockNumber: DataTypes.NUMBER,
58
- sourceStatus: DataTypes.STRING,
81
+ sourceStatus: {
82
+ type: DataTypes.STRING,
83
+ defaultValue: 'uninitialised'
84
+ },
59
85
  sourceErrors: {
60
86
  type: DataTypes.JSON,
61
87
  // defaultValue: [],
62
88
  },
89
+ sourceLogs: {
90
+ type: DataTypes.JSON,
91
+ // defaultValue: [],
92
+ },
63
93
  sourceCreatedAt: {
64
94
  type: DataTypes.DATE,
65
95
  defaultValue: Date.now()
@@ -69,18 +99,30 @@ Transaction.init({
69
99
  targetChainId: DataTypes.NUMBER,
70
100
  targetTransactionHash: DataTypes.STRING,
71
101
  targetBlockNumber: DataTypes.NUMBER,
72
- targetStatus: DataTypes.STRING,
102
+ targetStatus: {
103
+ type: DataTypes.STRING,
104
+ defaultValue: 'uninitialised'
105
+ },
73
106
  targetErrors: {
74
107
  type: DataTypes.JSON,
75
108
  // defaultValue: [],
76
109
  },
110
+ targetLogs: {
111
+ type: DataTypes.JSON,
112
+ // defaultValue: [],
113
+ },
77
114
  targetCreatedAt: DataTypes.DATE,
78
115
  targetDelayUntil: DataTypes.DATE,
79
116
 
80
- submitEvent: DataTypes.JSON,
81
- sourceEvent: DataTypes.JSON,
82
- targetEvent: DataTypes.JSON,
117
+ requestEvent: {
118
+ type: DataTypes.JSON,
119
+ allowNull: false
120
+ },
121
+ requestSendEvent: DataTypes.JSON,
122
+ committedEvent: DataTypes.JSON,
123
+ completedEvent: DataTypes.JSON,
83
124
 
125
+ position: DataTypes.JSON,
84
126
  metadata: DataTypes.JSON,
85
127
 
86
128
  status: {
@@ -0,0 +1,5 @@
1
+ import withdraw from "./withdraw"
2
+
3
+ export default {
4
+ withdraw,
5
+ }
@@ -0,0 +1,56 @@
1
+ import abi from "@/abi";
2
+ import config from "@/config";
3
+ import { addresses, tokens } from "@/constants";
4
+ import { Transaction } from "@/db";
5
+ import { InteropXContract } from "@/typechain";
6
+ import { ChainId } from "@/types";
7
+ import { getContract, getRpcProviderUrl } from "@/utils";
8
+ import { ethers } from "ethers";
9
+ import { MetaTransaction, OperationType } from "ethers-multisend";
10
+
11
+ export default async function (transaction: Transaction, type: 'source' | 'target') {
12
+ const transactions: MetaTransaction[] = [];
13
+ const logs: any[] = [];
14
+
15
+ if (transaction.action !== 'withdraw') {
16
+ throw new Error(`Invalid action: ${transaction.action}`)
17
+ }
18
+
19
+ if (type !== 'source') {
20
+ throw new Error(`Type not supported: ${type}`)
21
+ }
22
+
23
+ if (transaction.action === 'withdraw' && transaction.sourceStatus === 'pending') {
24
+ throw Error('Cannot build data for pending withdraw transaction');
25
+ }
26
+
27
+ if (!transaction.requestEvent) {
28
+ throw Error('Cannot build data for transaction without requestEvent');
29
+ }
30
+
31
+ const { bridger, position, sourceChainId, targetChainId, metadata, } = transaction.requestEvent;
32
+
33
+ const sourceChainProvider = new ethers.providers.JsonRpcProvider(getRpcProviderUrl(targetChainId as ChainId));
34
+ const sourceWallet = new ethers.Wallet(config.privateKey, sourceChainProvider);
35
+ const contractAddress = addresses[sourceChainId].interopXContract;
36
+ const contract = getContract<InteropXContract>(contractAddress, abi.interopXContract, sourceWallet);
37
+
38
+ const { data } = await contract.populateTransaction.withdrawRequested(
39
+ bridger,
40
+ position.withdraw[0].sourceToken,
41
+ position.withdraw[0].targetToken,
42
+ position.withdraw[0].amount,
43
+ targetChainId,
44
+ transaction.requestTransactionHash,
45
+ metadata,
46
+ );
47
+
48
+ transactions.push({
49
+ to: contractAddress,
50
+ data: data!,
51
+ value: '0',
52
+ operation: OperationType.Call,
53
+ });
54
+
55
+ return { transactions, logs }
56
+ }
@@ -0,0 +1,19 @@
1
+ import { Transaction } from "@/db";
2
+ import { encodeMulti } from "ethers-multisend";
3
+ import actions from "./actions";
4
+
5
+ export const buildGnosisAction = async (transaction: Transaction, type?: 'source' | 'target') => {
6
+ type = type || transaction.sourceStatus === 'pending' ? 'source' : 'target';
7
+
8
+ if (actions.hasOwnProperty(transaction.action)) {
9
+
10
+ const { transactions, logs } = await actions[transaction.action](transaction, type);
11
+
12
+ return {
13
+ data: encodeMulti(transactions).data,
14
+ logs
15
+ };
16
+ }
17
+
18
+ throw new Error(`Unknown action: ${transaction.action}`);
19
+ }
package/src/index.ts CHANGED
@@ -1,49 +1,87 @@
1
- import moduleAlias from 'module-alias';
2
-
3
- moduleAlias.addAliases({
4
- "@/": __dirname + "/",
5
- "@/logger": __dirname + "/logger",
6
- "@/tasks": __dirname + "/tasks",
7
- "@/utils": __dirname + "/utils",
8
- "@/api": __dirname + "/api",
9
- "@/net": __dirname + "/net",
10
- "@/db": __dirname + "/db",
11
- "@/config": __dirname + "/config",
12
- "@/types": __dirname + "/types",
13
- "@/abi": __dirname + "/abi",
14
- "@/constants": __dirname + "/constants",
15
- "@/typechain": __dirname + "/typechain"
16
- })
1
+ import './alias'
2
+ import expandHomeDir from "expand-home-dir";
3
+ import fs from 'fs-extra'
17
4
 
18
- moduleAlias();
19
- import assert from "assert";
20
5
  import dotenv from "dotenv";
6
+ import chalk from 'chalk';
21
7
  import { ethers } from "ethers";
8
+ import packageJson from '../package.json'
22
9
  dotenv.config();
23
10
 
24
11
  import Logger from "@/logger";
25
12
  const logger = new Logger('Process')
26
13
 
14
+ const GIT_SHORT_HASH = '@GIT_SHORT_HASH@';
15
+
16
+ const printUsage = () => {
17
+ console.log()
18
+ console.log(`Interop X Node (v${packageJson.version} - rev.${GIT_SHORT_HASH})`)
19
+ console.log()
27
20
 
28
- if (process.argv.at(-1) === 'help') {
29
21
  console.log('Usage:')
30
- console.log(' PRIVATE_KEY=abcd1234 interop-x')
31
- console.log(' PRIVATE_KEY=abcd1234 STAGING=true interop-x')
22
+ console.log(' interop-x help Show this message')
23
+ console.log(' interop-x version Print out the installed version of Interop X')
24
+
25
+ console.log()
26
+
27
+ console.log(' interop-x down Put the node into maintenance mode')
28
+ console.log(' interop-x up Take the node out of maintenance mode')
29
+
30
+ console.log()
31
+
32
+ console.log(' PRIVATE_KEY=abcd1234 interop-x Start the node with the given private key')
33
+ console.log(' PRIVATE_KEY=abcd1234 STAGING=true interop-x Start the node in staging mode')
34
+ console.log(' PRIVATE_KEY=abcd1234 AUTO_UPDATE=true interop-x Start the node in auto update mode')
35
+ console.log(' PRIVATE_KEY=abcd1234 API_HOST=0.0.0.0 API_PORT=8080 interop-x Start the node with custom API host and port')
36
+ console.log()
37
+
38
+ }
39
+
40
+ if (process.argv.at(-1) === 'help') {
41
+ printUsage()
42
+ process.exit(0)
43
+ }
44
+
45
+ const basePath = expandHomeDir(`~/.interop-x`);
46
+
47
+ if (process.argv.at(-1) === 'down') {
48
+ fs.outputFileSync(basePath + '/maintenance', Date.now().toString())
49
+ console.log(chalk.red('Maintenance mode enabled'))
32
50
  process.exit(0)
33
51
  }
34
52
 
35
- assert(process.env.PRIVATE_KEY, "PRIVATE_KEY is not defined");
53
+ if (process.argv.at(-1) === 'up') {
54
+ fs.removeSync(basePath + '/maintenance')
55
+ console.log(chalk.green('Maintenance mode disabled'))
56
+ process.exit(0)
57
+ }
36
58
 
59
+
60
+ if (process.argv.at(-1) === 'version') {
61
+ console.log(`Interop X Node (v${packageJson.version} - rev.${GIT_SHORT_HASH})`)
62
+ process.exit(0)
63
+ }
64
+
65
+ if (!process.env.PRIVATE_KEY) {
66
+ console.error(chalk.bgRed.white.bold('Please provide a private key\n'))
67
+ printUsage()
68
+ process.exit(1)
69
+ }
37
70
  try {
38
71
  new ethers.Wallet(process.env.PRIVATE_KEY!)
39
72
  } catch (e) {
40
- logger.error('Invalid private key')
73
+ console.error(chalk.bgRed.white('Invalid private key\n'))
74
+ printUsage()
41
75
  process.exit(1)
42
76
  }
43
77
 
78
+ logger.debug(`Starting Interop X Node (v${packageJson.version} - rev.${GIT_SHORT_HASH})`)
79
+
44
80
  import { Tasks } from "@/tasks";
45
- import { startPeer } from "@/net";
81
+ import { startPeer, protocol, peerPool } from "@/net";
46
82
  import { startApiServer } from '@/api';
83
+ import { Transaction } from './db';
84
+ import { shortenHash } from './utils';
47
85
 
48
86
  async function main() {
49
87
 
@@ -54,6 +92,39 @@ async function main() {
54
92
  tasks.start();
55
93
 
56
94
  startApiServer()
95
+
96
+ protocol.on('TransactionStatus', async (payload) => {
97
+ if (!peerPool.isLeadNode(payload.peerId)) {
98
+ const peer = peerPool.getPeer(payload.peerId)
99
+
100
+ if (!peer) {
101
+ return;
102
+ }
103
+
104
+ logger.info(`ignored transaction status from ${payload.peerId} ${shortenHash(peer.publicAddress)} `)
105
+ return;
106
+ }
107
+
108
+ const transaction = await Transaction.findOne({ where: { transactionHash: payload.data.transactionHash } })
109
+
110
+ if (!transaction) {
111
+ return;
112
+ }
113
+
114
+ transaction.sourceStatus = payload.data.sourceStatus
115
+ transaction.sourceTransactionHash = payload.data.sourceTransactionHash
116
+ transaction.sourceErrors = payload.data.sourceErrors
117
+ transaction.sourceLogs = payload.data.sourceLogs
118
+
119
+ transaction.targetStatus = payload.data.targetStatus
120
+ transaction.targetTransactionHash = payload.data.targetTransactionHash
121
+ transaction.targetErrors = payload.data.targetErrors
122
+ transaction.targetLogs = payload.data.targetLogs
123
+
124
+ transaction.status = payload.data.status
125
+
126
+ await transaction.save()
127
+ })
57
128
  }
58
129
 
59
130
  main()
@@ -17,6 +17,7 @@ import KadDHT from "libp2p-kad-dht";
17
17
  import PubsubPeerDiscovery from "libp2p-pubsub-peer-discovery";
18
18
  import { protocol } from "@/net";
19
19
  import config from "@/config";
20
+ import chalk from "chalk";
20
21
 
21
22
  const logger = new Logger("Peer");
22
23
 
@@ -80,7 +81,7 @@ export const startPeer = async ({ }: IPeerOptions) => {
80
81
  },
81
82
  });
82
83
 
83
- logger.info("Peer ID:", node.peerId.toB58String());
84
+ logger.info("Peer ID:", chalk.bold(node.peerId.toB58String()));
84
85
 
85
86
  await node.start();
86
87
 
@@ -88,12 +89,13 @@ export const startPeer = async ({ }: IPeerOptions) => {
88
89
  libp2p: node
89
90
  })
90
91
 
91
- node.on("peer:discovery", (peer) =>
92
- logger.log(`Discovered peer ${peer}`)
93
- ); // peer disc.
94
- node.connectionManager.on("peer:connect", (connection) =>
95
- logger.log(`Connected to ${connection.remotePeer.toB58String()}`)
96
- );
92
+ node.on("peer:discovery", (peer) => {
93
+ // logger.log(`Discovered peer ${peer}`)
94
+ }); // peer disc.
95
+
96
+ node.connectionManager.on("peer:connect", (connection) => {
97
+ // logger.log(`Connected to ${connection.remotePeer.toB58String()}`)
98
+ });
97
99
 
98
100
  logger.log("Peer discovery started");
99
101
 
@@ -1,5 +1,12 @@
1
1
  import { Event } from "@/types";
2
2
  import config from "@/config";
3
+ import Logger from "@/logger";
4
+ import { getAddress } from "ethers/lib/utils";
5
+ import { shortenHash } from "@/utils";
6
+ import chalk from "chalk";
7
+
8
+
9
+ const logger = new Logger('PeerPool')
3
10
 
4
11
  export interface IPeerInfo {
5
12
  id: string;
@@ -75,10 +82,15 @@ export class PeerPool {
75
82
  * @emits {@link Event.POOL_PEER_ADDED}
76
83
  */
77
84
  add(peer?: IPeerInfo) {
78
- if (peer && peer.id && !this.pool.get(peer.id)) {
85
+ if (peer && peer.id) {
86
+ const newPeer = !this.pool.get(peer.id);
79
87
  this.pool.set(peer.id, peer)
80
88
  peer.pooled = true
81
- config.events.emit(Event.POOL_PEER_ADDED, peer)
89
+
90
+ if (newPeer) {
91
+ config.events.emit(Event.POOL_PEER_ADDED, peer)
92
+ logger.info(`Peer ${chalk.bold(shortenHash(peer.id, 16))} with address ${chalk.bold(shortenHash(peer.publicAddress))} added to pool`)
93
+ }
82
94
  }
83
95
  }
84
96
 
@@ -92,6 +104,7 @@ export class PeerPool {
92
104
  if (this.pool.delete(peer.id)) {
93
105
  peer.pooled = false
94
106
  config.events.emit(Event.POOL_PEER_REMOVED, peer)
107
+ logger.info(`Peer ${chalk.bold(shortenHash(peer.id, 16))} with address ${chalk.bold(shortenHash(peer.publicAddress))} removed from pool`)
95
108
  }
96
109
  }
97
110
  }
@@ -100,7 +113,7 @@ export class PeerPool {
100
113
  this.cleanup()
101
114
 
102
115
  return this.peers.filter((p) => {
103
- if(!p.pooled) return false;
116
+ if (!p.pooled) return false;
104
117
 
105
118
  const now = new Date()
106
119
 
@@ -112,16 +125,33 @@ export class PeerPool {
112
125
  return this.activePeers.map((p) => p.id)
113
126
  }
114
127
 
128
+ getPeer(id: string){
129
+ return this.pool.get(id);
130
+ }
115
131
 
116
- cleanup() {
117
- let compDate = Date.now() - this.PEERS_CLEANUP_TIME_LIMIT * 60
132
+ isLeadNode(id: string) {
133
+ const peer = this.pool.get(id);
118
134
 
119
- this.peers.forEach((peerInfo) => {
120
- if (peerInfo.updated.getTime() < compDate) {
121
- console.log(`Peer ${peerInfo.id} idle for ${this.PEERS_CLEANUP_TIME_LIMIT} minutes`)
122
- this.remove(peerInfo)
123
- }
124
- })
135
+ if (!peer) {
136
+ return false;
137
+ }
138
+
139
+ return getAddress(peer.publicAddress) === getAddress(config.leadNodeAddress)
140
+ }
141
+
142
+ getLeadPeer() {
143
+ return this.peers.find((p) => this.isLeadNode(p.id))
144
+ }
145
+
146
+ cleanup() {
147
+ // let compDate = Date.now() - this.PEERS_CLEANUP_TIME_LIMIT * 60
148
+
149
+ // this.peers.forEach((peerInfo) => {
150
+ // if (peerInfo.updated.getTime() < compDate) {
151
+ // console.log(`Peer ${peerInfo.id} idle for ${this.PEERS_CLEANUP_TIME_LIMIT} minutes`)
152
+ // this.remove(peerInfo)
153
+ // }
154
+ // })
125
155
  }
126
156
  }
127
157
 
@@ -2,9 +2,13 @@ import { BaseDialProtocol } from "./BaseDialProtocol";
2
2
  import wait from "waait";
3
3
  import config from "@/config";
4
4
  import { Transaction } from "@/db";
5
+ import { signGnosisSafeTx } from "@/utils";
6
+ import { addresses } from "@/constants";
7
+ import { ChainId } from "@/types";
8
+ import { buildGnosisAction } from "@/gnosis";
5
9
 
6
10
  export interface ISignatureRequest {
7
- type: string,
11
+ type: 'source' | 'target',
8
12
  transactionHash: string
9
13
  safeTxGas: string
10
14
  safeNonce: string
@@ -24,36 +28,38 @@ export class SignatureDialProtocol extends BaseDialProtocol<ISignatureRequest, I
24
28
  async response(data: ISignatureRequest): Promise<ISignatureResponse> {
25
29
  const signer = config.wallet;
26
30
 
27
- let event: Transaction | null;
31
+ let transaction: Transaction | null;
28
32
  let maxTimeout = 20000;
29
33
 
30
34
  do {
31
- event = await Transaction.findOne({ where: { transactionHash: data.transactionHash } })
35
+ transaction = await Transaction.findOne({ where: { transactionHash: data.transactionHash } })
32
36
 
33
- if (!event) {
37
+ if (!transaction) {
34
38
  await wait(1000);
35
39
  maxTimeout -= 1000;
36
40
  }
37
- } while (!event && maxTimeout > 0)
41
+ } while (!transaction && maxTimeout > 0)
38
42
 
39
- if (!event) {
43
+ if (!transaction) {
40
44
  return {
41
45
  signer: signer.address,
42
46
  data: null,
43
47
  error: 'Event not found'
44
48
  };
45
49
  }
50
+ const { data: gnosisData } = await buildGnosisAction(transaction, data.type);
46
51
 
47
- // const signedData = await signGnosisSafeTx({
48
- // to: addresses[event.chainId as ChainId].multisend,
49
- // data: 'TODO',
50
- // chainId: event.chainId as ChainId,
51
- // safeTxGas: data.safeTxGas,
52
- // }, { signer });
52
+ const signedData = await signGnosisSafeTx({
53
+ to: addresses[transaction.targetChainId].multisend,
54
+ data: gnosisData,
55
+ chainId: transaction.targetChainId as ChainId,
56
+ safeTxGas: data.safeTxGas,
57
+ nonce: data.safeNonce,
58
+ }, { signer });
53
59
 
54
60
  return {
55
61
  signer: signer.address,
56
- data: null, //signedData,
62
+ data: signedData
57
63
  }
58
64
  }
59
65
  }
@@ -0,0 +1,33 @@
1
+ import { BaseDialProtocol } from "./BaseDialProtocol";
2
+ import { Transaction } from "@/db";
3
+
4
+ export class TransactionStatusDialProtocol extends BaseDialProtocol<string, Pick<Transaction, 'transactionHash' | 'sourceStatus' | 'sourceTransactionHash' | 'sourceErrors' | 'sourceLogs' | 'targetStatus' | 'targetTransactionHash' | 'targetErrors' | 'targetLogs' | 'status'> | null> {
5
+ protected timeout = 30000;
6
+
7
+ constructor(libp2p) {
8
+ super(libp2p, '/interop-x/transaction-status')
9
+ }
10
+
11
+ async response(transactionHash: string){
12
+ const transaction = await Transaction.findOne({ where: { transactionHash } })
13
+
14
+ if(! transaction){
15
+ return null
16
+ }
17
+ return {
18
+ transactionHash: transaction.transactionHash,
19
+
20
+ sourceStatus: transaction.sourceStatus,
21
+ sourceTransactionHash: transaction.sourceTransactionHash,
22
+ sourceErrors: transaction.sourceErrors,
23
+ sourceLogs: transaction.sourceLogs,
24
+
25
+ targetStatus: transaction.targetStatus,
26
+ targetTransactionHash: transaction.targetTransactionHash,
27
+ targetErrors: transaction.targetErrors,
28
+ targetLogs: transaction.targetLogs,
29
+
30
+ status: transaction.status,
31
+ }
32
+ }
33
+ }