@instadapp/interop-x 0.0.0-dev.92afe89 → 0.0.0-dev.99c6cb0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (98) hide show
  1. package/.env.example +2 -1
  2. package/dist/package.json +74 -0
  3. package/dist/src/abi/erc20.json +350 -0
  4. package/dist/src/abi/gnosisSafe.json +747 -0
  5. package/dist/src/abi/index.js +13 -0
  6. package/dist/src/abi/interopXContract.json +454 -0
  7. package/dist/src/alias.js +10 -0
  8. package/dist/src/api/index.js +36 -0
  9. package/dist/src/config/index.js +31 -0
  10. package/dist/src/constants/addresses.js +20 -0
  11. package/dist/{constants → src/constants}/index.js +1 -0
  12. package/dist/src/constants/tokens.js +137 -0
  13. package/dist/{db → src/db}/index.js +0 -0
  14. package/dist/{db → src/db}/models/index.js +1 -1
  15. package/dist/src/db/models/transaction.js +70 -0
  16. package/dist/{db → src/db}/sequelize.js +2 -1
  17. package/dist/src/gnosis/actions/index.js +9 -0
  18. package/dist/src/gnosis/actions/withdraw/index.js +55 -0
  19. package/dist/src/gnosis/index.js +20 -0
  20. package/dist/src/index.js +119 -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 +13 -8
  24. package/dist/{net → src/net}/pool/index.js +34 -11
  25. package/dist/{net → src/net}/protocol/dial/BaseDialProtocol.js +1 -1
  26. package/dist/{net → src/net}/protocol/dial/SignatureDialProtocol.js +21 -14
  27. package/dist/src/net/protocol/dial/TransactionStatusDialProtocol.js +30 -0
  28. package/dist/{net → src/net}/protocol/index.js +54 -4
  29. package/dist/src/tasks/AutoUpdateTask.js +70 -0
  30. package/dist/{tasks → src/tasks}/BaseTask.js +14 -6
  31. package/dist/src/tasks/InteropXContract/ProcessBridgeRequestEvents.js +152 -0
  32. package/dist/src/tasks/InteropXContract/SyncBridgeRequestEvents.js +78 -0
  33. package/dist/src/tasks/InteropXContract/SyncBridgeRequestSentEvents.js +90 -0
  34. package/dist/src/tasks/Transactions/SyncTransactionStatusTask.js +55 -0
  35. package/dist/src/tasks/index.js +38 -0
  36. package/dist/src/typechain/Erc20.js +2 -0
  37. package/dist/src/typechain/GnosisSafe.js +2 -0
  38. package/dist/src/typechain/InteropXContract.js +2 -0
  39. package/dist/src/typechain/common.js +2 -0
  40. package/dist/src/typechain/factories/Erc20__factory.js +367 -0
  41. package/dist/src/typechain/factories/GnosisSafe__factory.js +1174 -0
  42. package/dist/src/typechain/factories/InteropXContract__factory.js +635 -0
  43. package/dist/src/typechain/factories/index.js +12 -0
  44. package/dist/src/typechain/index.js +33 -0
  45. package/dist/{types.js → src/types.js} +0 -0
  46. package/dist/src/utils/index.js +186 -0
  47. package/package.json +30 -15
  48. package/patches/@ethersproject+properties+5.6.0.patch +13 -0
  49. package/src/abi/erc20.json +350 -0
  50. package/src/abi/gnosisSafe.json +747 -0
  51. package/src/abi/index.ts +9 -0
  52. package/src/abi/interopXContract.json +454 -0
  53. package/src/alias.ts +6 -0
  54. package/src/api/index.ts +36 -0
  55. package/src/config/index.ts +18 -2
  56. package/src/constants/addresses.ts +10 -3
  57. package/src/constants/index.ts +1 -0
  58. package/src/constants/tokens.ts +134 -0
  59. package/src/db/index.ts +1 -1
  60. package/src/db/models/index.ts +1 -1
  61. package/src/db/models/transaction.ts +137 -0
  62. package/src/db/sequelize.ts +2 -1
  63. package/src/gnosis/actions/index.ts +5 -0
  64. package/src/gnosis/actions/withdraw/index.ts +77 -0
  65. package/src/gnosis/index.ts +19 -0
  66. package/src/index.ts +118 -7
  67. package/src/net/peer/index.ts +12 -10
  68. package/src/net/pool/index.ts +43 -13
  69. package/src/net/protocol/dial/BaseDialProtocol.ts +1 -1
  70. package/src/net/protocol/dial/SignatureDialProtocol.ts +24 -17
  71. package/src/net/protocol/dial/TransactionStatusDialProtocol.ts +33 -0
  72. package/src/net/protocol/index.ts +70 -4
  73. package/src/tasks/AutoUpdateTask.ts +82 -0
  74. package/src/tasks/BaseTask.ts +16 -7
  75. package/src/tasks/InteropXContract/ProcessBridgeRequestEvents.ts +216 -0
  76. package/src/tasks/InteropXContract/SyncBridgeRequestEvents.ts +115 -0
  77. package/src/tasks/InteropXContract/SyncBridgeRequestSentEvents.ts +121 -0
  78. package/src/tasks/Transactions/SyncTransactionStatusTask.ts +67 -0
  79. package/src/tasks/index.ts +24 -2
  80. package/src/typechain/Erc20.ts +491 -0
  81. package/src/typechain/GnosisSafe.ts +1728 -0
  82. package/src/typechain/InteropXContract.ts +680 -0
  83. package/src/typechain/common.ts +44 -0
  84. package/src/typechain/factories/Erc20__factory.ts +368 -0
  85. package/src/typechain/factories/GnosisSafe__factory.ts +1178 -0
  86. package/src/typechain/factories/InteropXContract__factory.ts +642 -0
  87. package/src/typechain/factories/index.ts +6 -0
  88. package/src/typechain/index.ts +10 -0
  89. package/src/types.ts +2 -2
  90. package/src/utils/index.ts +156 -4
  91. package/tsconfig.json +8 -0
  92. package/dist/config/index.js +0 -17
  93. package/dist/constants/addresses.js +0 -13
  94. package/dist/db/models/execution.js +0 -38
  95. package/dist/index.js +0 -34
  96. package/dist/tasks/index.js +0 -19
  97. package/dist/utils/index.js +0 -89
  98. package/src/db/models/execution.ts +0 -57
@@ -0,0 +1,134 @@
1
+ export const tokens = {
2
+ 1: [
3
+ {
4
+ aliases: ['eth'],
5
+ symbol: "ETH",
6
+ name: "Ethereum",
7
+ address: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
8
+ decimals: 18,
9
+ },
10
+ {
11
+ aliases: ['weth'],
12
+ symbol: "WETH",
13
+ name: "Wrapped Ethereum",
14
+ address: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
15
+ decimals: 18,
16
+ },
17
+ {
18
+ aliases: ['dai'],
19
+ symbol: "DAI",
20
+ name: "DAI Stable",
21
+ address: "0x6B175474E89094C44Da98b954EedeAC495271d0F",
22
+ decimals: 18,
23
+ },
24
+ {
25
+ aliases: ['usdc'],
26
+ symbol: "USDC",
27
+ name: "USD Coin",
28
+ address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
29
+ decimals: 6,
30
+ },
31
+ {
32
+ aliases: ['usdt'],
33
+ symbol: "USDT",
34
+ name: "Tether USD Coin",
35
+ address: "0xdAC17F958D2ee523a2206206994597C13D831ec7",
36
+ decimals: 6,
37
+ },
38
+ {
39
+ aliases: ['wbtc'],
40
+ symbol: "WBTC",
41
+ name: "Wrapped BTC",
42
+ address: "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599",
43
+ decimals: 8,
44
+ },
45
+ ],
46
+ 137: [
47
+ {
48
+ aliases: ['eth', 'weth'],
49
+ symbol: "ETH",
50
+ name: "Ethereum",
51
+ address: "0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619",
52
+ decimals: 18,
53
+ },
54
+ {
55
+ aliases: ['dai'],
56
+ symbol: "DAI",
57
+ name: "DAI Stable",
58
+ address: "0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063",
59
+ decimals: 18,
60
+ },
61
+ {
62
+ aliases: ['usdc'],
63
+ symbol: "USDC",
64
+ name: "USD Coin",
65
+ address: "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174",
66
+ decimals: 6,
67
+ },
68
+ {
69
+ aliases: ['usdt'],
70
+ symbol: "USDT",
71
+ name: "Tether USD Coin",
72
+ address: "0xc2132D05D31c914a87C6611C10748AEb04B58e8F",
73
+ decimals: 6,
74
+ },
75
+ {
76
+ aliases: ['wbtc'],
77
+ symbol: "WBTC",
78
+ name: "Wrapped BTC",
79
+ address: "0x1BFD67037B42Cf73acF2047067bd4F2C47D9BfD6",
80
+ decimals: 8,
81
+ },
82
+ {
83
+ aliases: ['avax'],
84
+ symbol: "AVAX",
85
+ name: "Avalanche Token",
86
+ address: "0x2C89bbc92BD86F8075d1DEcc58C7F4E0107f286b",
87
+ decimals: 18,
88
+ },
89
+ ],
90
+ 43114: [
91
+ {
92
+ aliases: ['eth', 'weth'],
93
+ symbol: "ETH",
94
+ name: "Ethereum",
95
+ address: "0x49D5c2BdFfac6CE2BFdB6640F4F80f226bc10bAB",
96
+ decimals: 18,
97
+ },
98
+ {
99
+ aliases: ['dai'],
100
+ symbol: "DAI",
101
+ name: "DAI Stable",
102
+ address: "0xd586E7F844cEa2F87f50152665BCbc2C279D8d70",
103
+ decimals: 18,
104
+ },
105
+ {
106
+ aliases: ['usdc'],
107
+ symbol: "USDC",
108
+ name: "USD Coin",
109
+ address: "0xA7D7079b0FEaD91F3e65f86E8915Cb59c1a4C664",
110
+ decimals: 6,
111
+ },
112
+ {
113
+ aliases: ['usdt'],
114
+ symbol: "USDt",
115
+ name: "Tether USD Coin",
116
+ address: "0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7",
117
+ decimals: 6,
118
+ },
119
+ {
120
+ aliases: ['usdt'],
121
+ symbol: "USDT.e",
122
+ name: "Tether USD",
123
+ address: "0xc7198437980c041c805A1EDcbA50c1Ce5db95118",
124
+ decimals: 6,
125
+ },
126
+ {
127
+ aliases: ["wbtc"],
128
+ symbol: "WBTC",
129
+ name: "Wrapped BTC",
130
+ address: "0x50b7545627a5162F82A992c33b87aDc75187B218",
131
+ decimals: 8,
132
+ },
133
+ ],
134
+ } as Record<number, { aliases: string[], symbol: string, name: string, address: string, decimals: number }[]>;
package/src/db/index.ts CHANGED
@@ -1 +1 @@
1
- export * from "./models"
1
+ export * from "./models"
@@ -1 +1 @@
1
- export * from './execution';
1
+ export * from './transaction';
@@ -0,0 +1,137 @@
1
+ import { sequelize } from '@/db/sequelize'
2
+ import { CreationOptional, InferAttributes, InferCreationAttributes, Model, DataTypes } from 'sequelize';
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
+
15
+ export class Transaction extends Model<InferAttributes<Transaction>, InferCreationAttributes<Transaction>> {
16
+ declare id: CreationOptional<number>;
17
+
18
+ declare transactionHash: string;
19
+
20
+ declare actionId: string;
21
+ declare bridger: string;
22
+ declare requestTransactionHash: string;
23
+
24
+ declare requestBlockNumber: number;
25
+
26
+ declare sourceChainId: number;
27
+ declare sourceTransactionHash: CreationOptional<string>;
28
+ declare sourceBlockNumber: CreationOptional<number>;
29
+ declare sourceStatus: CreationOptional<string>;
30
+ declare sourceErrors: CreationOptional<string[]>;
31
+ declare sourceLogs: CreationOptional<any[]>;
32
+ declare sourceCreatedAt: CreationOptional<Date>;
33
+ declare sourceDelayUntil: CreationOptional<Date>;
34
+
35
+ declare targetChainId: number;
36
+ declare targetTransactionHash: CreationOptional<string>;
37
+ declare targetBlockNumber: CreationOptional<number>;
38
+ declare targetStatus: CreationOptional<string>;
39
+ declare targetErrors: CreationOptional<string[]>;
40
+ declare targetLogs: CreationOptional<any[]>;
41
+ declare targetCreatedAt: CreationOptional<Date>;
42
+ declare targetDelayUntil: CreationOptional<Date>;
43
+
44
+ declare requestEvent: {
45
+ actionId: string;
46
+ bridger: string;
47
+ metadata: string;
48
+ position: IPosition;
49
+ sourceChainId: number;
50
+ targetChainId: number;
51
+ };
52
+ declare requestSentEvent: CreationOptional<{
53
+ actionId: string;
54
+ bridger: string;
55
+ metadata: string;
56
+ position: IPosition;
57
+ sourceChainId: number;
58
+ targetChainId: number;
59
+ requestTransactionHash: string;
60
+ }>;
61
+ declare committedEvent: CreationOptional<any>;
62
+ declare completedEvent: CreationOptional<any>;
63
+
64
+ declare status: CreationOptional<string>;
65
+
66
+ declare createdAt: CreationOptional<Date>;
67
+ declare updatedAt: CreationOptional<Date>;
68
+ }
69
+
70
+ Transaction.init({
71
+ id: {
72
+ type: DataTypes.INTEGER,
73
+ autoIncrement: true,
74
+ primaryKey: true
75
+ },
76
+
77
+ requestTransactionHash: DataTypes.NUMBER,
78
+ requestBlockNumber: DataTypes.NUMBER,
79
+
80
+ transactionHash: DataTypes.STRING,
81
+ actionId: DataTypes.STRING,
82
+ bridger: DataTypes.STRING,
83
+
84
+ sourceChainId: DataTypes.NUMBER,
85
+ sourceTransactionHash: DataTypes.STRING,
86
+ sourceBlockNumber: DataTypes.NUMBER,
87
+ sourceStatus: {
88
+ type: DataTypes.STRING,
89
+ defaultValue: 'uninitialised'
90
+ },
91
+ sourceErrors: {
92
+ type: DataTypes.JSON,
93
+ // defaultValue: [],
94
+ },
95
+ sourceLogs: {
96
+ type: DataTypes.JSON,
97
+ // defaultValue: [],
98
+ },
99
+ sourceCreatedAt: {
100
+ type: DataTypes.DATE,
101
+ defaultValue: Date.now()
102
+ },
103
+ sourceDelayUntil: DataTypes.STRING,
104
+
105
+ targetChainId: DataTypes.NUMBER,
106
+ targetTransactionHash: DataTypes.STRING,
107
+ targetBlockNumber: DataTypes.NUMBER,
108
+ targetStatus: {
109
+ type: DataTypes.STRING,
110
+ defaultValue: 'uninitialised'
111
+ },
112
+ targetErrors: {
113
+ type: DataTypes.JSON,
114
+ // defaultValue: [],
115
+ },
116
+ targetLogs: {
117
+ type: DataTypes.JSON,
118
+ // defaultValue: [],
119
+ },
120
+ targetCreatedAt: DataTypes.DATE,
121
+ targetDelayUntil: DataTypes.DATE,
122
+
123
+ requestEvent: {
124
+ type: DataTypes.JSON,
125
+ allowNull: false
126
+ },
127
+ requestSentEvent: DataTypes.JSON,
128
+ committedEvent: DataTypes.JSON,
129
+ completedEvent: DataTypes.JSON,
130
+
131
+ status: {
132
+ type: DataTypes.STRING,
133
+ defaultValue: 'pending'
134
+ },
135
+ createdAt: DataTypes.DATE,
136
+ updatedAt: DataTypes.DATE,
137
+ }, { sequelize, tableName: 'transactions' });
@@ -1,9 +1,10 @@
1
1
  //@ts-ignore
2
+ import config from "@/config";
2
3
  import expandHomeDir from "expand-home-dir";
3
4
 
4
5
  import { Sequelize } from 'sequelize';
5
6
 
6
- const basePath = expandHomeDir('~/.interop-x/data');
7
+ const basePath = expandHomeDir(`~/.interop-x/data/${config.publicAddress}/${config.staging ? 'staging' : ''}`);
7
8
 
8
9
  export const sequelize = new Sequelize({
9
10
  dialect: 'sqlite',
@@ -0,0 +1,5 @@
1
+ import withdraw from "./withdraw"
2
+
3
+ export default {
4
+ withdraw,
5
+ }
@@ -0,0 +1,77 @@
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.actionId !== 'withdraw') {
16
+ throw new Error(`Invalid action: ${transaction.actionId}`)
17
+ }
18
+
19
+ if (type !== 'source') {
20
+ throw new Error(`[WIP] Type not supported: ${type}`)
21
+ }
22
+
23
+ if (transaction.sourceStatus === 'pending') {
24
+ throw Error('Source transaction already processesing')
25
+ }
26
+
27
+ if (transaction.sourceStatus === 'pending') {
28
+ throw Error('Source transaction already processed')
29
+ }
30
+
31
+ if (!transaction.requestEvent) {
32
+ throw Error('Something went wrong, source transaction has no request event')
33
+ }
34
+
35
+ const { actionId, bridger, position, sourceChainId, targetChainId, metadata} = transaction.requestEvent;
36
+
37
+ const sourceChainProvider = new ethers.providers.JsonRpcProvider(getRpcProviderUrl(targetChainId as ChainId));
38
+ const sourceWallet = new ethers.Wallet(config.privateKey, sourceChainProvider);
39
+ const contractAddress = addresses[sourceChainId].interopXContract;
40
+ const contract = getContract<InteropXContract>(contractAddress, abi.interopXContract, sourceWallet);
41
+
42
+ const sourceToken = tokens[sourceChainId].find(t => t.address.toLowerCase() === position.withdraw[0].sourceToken.toLowerCase());
43
+
44
+ if (!sourceToken) {
45
+ throw Error('Source token not found')
46
+ }
47
+
48
+ const targetToken = tokens[targetChainId].find(t => t.address.toLowerCase() === position.withdraw[0].targetToken.toLowerCase());
49
+
50
+ if (!targetToken) {
51
+ throw Error('Target token not found')
52
+ }
53
+
54
+ if (sourceToken.aliases.some(alias => targetToken.aliases.includes(alias))) {
55
+ throw Error('Source and target token must be the same')
56
+ }
57
+
58
+ const { data } = await contract.populateTransaction.withdrawRequested(
59
+ actionId,
60
+ bridger,
61
+ position.withdraw[0].sourceToken,
62
+ position.withdraw[0].targetToken,
63
+ position.withdraw[0].amount,
64
+ targetChainId,
65
+ transaction.requestTransactionHash,
66
+ metadata,
67
+ );
68
+
69
+ transactions.push({
70
+ to: contractAddress,
71
+ data: data!,
72
+ value: '0',
73
+ operation: OperationType.Call,
74
+ });
75
+
76
+ return { transactions, logs }
77
+ }
@@ -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 === 'success' ? 'target' : 'source')
7
+
8
+ if (actions.hasOwnProperty(transaction.actionId)) {
9
+
10
+ const { transactions, logs } = await actions[transaction.actionId](transaction, type);
11
+
12
+ return {
13
+ data: encodeMulti(transactions).data,
14
+ logs
15
+ };
16
+ }
17
+
18
+ throw new Error(`Unknown action: ${transaction.actionId}`);
19
+ }
package/src/index.ts CHANGED
@@ -1,21 +1,132 @@
1
- import { assert } from "console";
1
+ import './alias'
2
+ import expandHomeDir from "expand-home-dir";
3
+ import fs from 'fs-extra'
4
+
2
5
  import dotenv from "dotenv";
3
- import { Tasks } from "tasks";
4
- import Logger from "./logger";
5
- import { startPeer } from "./net";
6
+ import chalk from 'chalk';
7
+ import { ethers } from "ethers";
8
+ import packageJson from '../package.json'
6
9
  dotenv.config();
7
10
 
8
- assert(process.env.PRIVATE_KEY, "PRIVATE_KEY is not defined");
9
-
11
+ import Logger from "@/logger";
10
12
  const logger = new Logger('Process')
11
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()
20
+
21
+ console.log('Usage:')
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'))
50
+ process.exit(0)
51
+ }
52
+
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
+ }
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
+ }
70
+ try {
71
+ new ethers.Wallet(process.env.PRIVATE_KEY!)
72
+ } catch (e) {
73
+ console.error(chalk.bgRed.white('Invalid private key\n'))
74
+ printUsage()
75
+ process.exit(1)
76
+ }
77
+
78
+ logger.debug(`Starting Interop X Node (v${packageJson.version} - rev.${GIT_SHORT_HASH})`)
79
+
80
+ import { Tasks } from "@/tasks";
81
+ import { startPeer, protocol, peerPool } from "@/net";
82
+ import { startApiServer } from '@/api';
83
+ import { Transaction } from './db';
84
+ import { shortenHash } from './utils';
85
+
12
86
  async function main() {
13
87
 
14
88
  startPeer({})
15
89
 
16
90
  const tasks = new Tasks()
17
91
 
18
- tasks.start();
92
+ setTimeout(() => {
93
+ tasks.start();
94
+ }, 10000)
95
+
96
+ startApiServer()
97
+
98
+ protocol.on('TransactionStatus', async (payload) => {
99
+ if (!peerPool.isLeadNode(payload.peerId)) {
100
+ const peer = peerPool.getPeer(payload.peerId)
101
+
102
+ if (!peer) {
103
+ return;
104
+ }
105
+
106
+ logger.info(`ignored transaction status from ${payload.peerId} ${shortenHash(peer.publicAddress)} `)
107
+ return;
108
+ }
109
+
110
+ const transaction = await Transaction.findOne({ where: { transactionHash: payload.data.transactionHash } })
111
+
112
+ if (!transaction) {
113
+ return;
114
+ }
115
+
116
+ transaction.sourceStatus = payload.data.sourceStatus
117
+ transaction.sourceTransactionHash = payload.data.sourceTransactionHash
118
+ transaction.sourceErrors = payload.data.sourceErrors
119
+ transaction.sourceLogs = payload.data.sourceLogs
120
+
121
+ transaction.targetStatus = payload.data.targetStatus
122
+ transaction.targetTransactionHash = payload.data.targetTransactionHash
123
+ transaction.targetErrors = payload.data.targetErrors
124
+ transaction.targetLogs = payload.data.targetLogs
125
+
126
+ transaction.status = payload.data.status
127
+
128
+ await transaction.save()
129
+ })
19
130
  }
20
131
 
21
132
  main()
@@ -5,7 +5,7 @@ import WS from "libp2p-websockets";
5
5
  //@ts-ignore
6
6
  import Mplex from "libp2p-mplex";
7
7
  import { NOISE } from "libp2p-noise";
8
- import Logger from "../../logger";
8
+ import Logger from "@/logger";
9
9
  import Bootstrap from "libp2p-bootstrap";
10
10
  import wait from "waait";
11
11
  import Gossipsub from "@achingbrain/libp2p-gossipsub";
@@ -15,8 +15,9 @@ import MulticastDNS from "libp2p-mdns";
15
15
  import KadDHT from "libp2p-kad-dht";
16
16
  //@ts-ignore
17
17
  import PubsubPeerDiscovery from "libp2p-pubsub-peer-discovery";
18
- import { protocol } from "../protocol";
19
- import config from "../../config";
18
+ import { protocol } from "@/net";
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
- import { Event } from "../../types";
2
- import config from "../../config";
1
+ import { Event } from "@/types";
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
 
@@ -1,7 +1,7 @@
1
1
  import pipe from 'it-pipe';
2
2
  import Libp2p from 'libp2p';
3
3
  import PeerId from 'peer-id';
4
- import { asyncCallWithTimeout } from '../../../utils';
4
+ import { asyncCallWithTimeout } from '@/utils';
5
5
  import wait from 'waait';
6
6
 
7
7
  export class BaseDialProtocol<TRequest extends any, TResponse extends any> {