@instadapp/interop-x 0.0.0-dev.75809ae → 0.0.0-dev.7adf1b5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (112) hide show
  1. package/.env.example +2 -1
  2. package/dist/package.json +73 -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 +15 -0
  6. package/dist/src/abi/interopBridgeToken.json +298 -0
  7. package/dist/src/abi/interopXGateway.json +184 -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 +2 -0
  12. package/dist/src/constants/itokens.js +13 -0
  13. package/dist/src/constants/tokens.js +107 -0
  14. package/dist/{db → src/db}/index.js +0 -0
  15. package/dist/{db → src/db}/models/index.js +1 -1
  16. package/dist/src/db/models/transaction.js +62 -0
  17. package/dist/{db → src/db}/sequelize.js +2 -1
  18. package/dist/src/gnosis/actions/deposit.js +48 -0
  19. package/dist/src/gnosis/actions/index.js +11 -0
  20. package/dist/src/gnosis/actions/withdraw.js +50 -0
  21. package/dist/src/gnosis/index.js +20 -0
  22. package/dist/src/index.js +130 -0
  23. package/dist/{logger → src/logger}/index.js +0 -0
  24. package/dist/{net → src/net}/index.js +0 -0
  25. package/dist/{net → src/net}/peer/index.js +13 -8
  26. package/dist/{net → src/net}/pool/index.js +34 -11
  27. package/dist/{net → src/net}/protocol/dial/BaseDialProtocol.js +1 -1
  28. package/dist/{net → src/net}/protocol/dial/SignatureDialProtocol.js +17 -14
  29. package/dist/src/net/protocol/dial/TransactionStatusDialProtocol.js +28 -0
  30. package/dist/{net → src/net}/protocol/index.js +44 -4
  31. package/dist/src/tasks/AutoUpdateTask.js +70 -0
  32. package/dist/{tasks → src/tasks}/BaseTask.js +14 -6
  33. package/dist/src/tasks/InteropBridge/ProcessWithdrawEvents.js +162 -0
  34. package/dist/src/tasks/InteropBridge/SyncBurnEvents.js +71 -0
  35. package/dist/src/tasks/InteropBridge/SyncMintEvents.js +67 -0
  36. package/dist/src/tasks/InteropXGateway/ProcessDepositEvents.js +164 -0
  37. package/dist/src/tasks/InteropXGateway/SyncDepositEvents.js +74 -0
  38. package/dist/src/tasks/InteropXGateway/SyncWithdrawtEvents.js +72 -0
  39. package/dist/src/tasks/Transactions/SyncTransactionStatusTask.js +53 -0
  40. package/dist/src/tasks/index.js +55 -0
  41. package/dist/src/typechain/Erc20.js +2 -0
  42. package/dist/src/typechain/GnosisSafe.js +2 -0
  43. package/dist/src/typechain/InteropBridgeToken.js +2 -0
  44. package/dist/src/typechain/InteropXGateway.js +2 -0
  45. package/dist/src/typechain/common.js +2 -0
  46. package/dist/src/typechain/factories/Erc20__factory.js +367 -0
  47. package/dist/src/typechain/factories/GnosisSafe__factory.js +1174 -0
  48. package/dist/src/typechain/factories/InteropBridgeToken__factory.js +471 -0
  49. package/dist/src/typechain/factories/InteropXGateway__factory.js +265 -0
  50. package/dist/src/typechain/factories/index.js +14 -0
  51. package/dist/src/typechain/index.js +35 -0
  52. package/dist/{types.js → src/types.js} +0 -0
  53. package/dist/src/utils/index.js +157 -0
  54. package/package.json +21 -7
  55. package/patches/@ethersproject+properties+5.6.0.patch +13 -0
  56. package/src/abi/erc20.json +350 -0
  57. package/src/abi/gnosisSafe.json +747 -0
  58. package/src/abi/index.ts +11 -0
  59. package/src/abi/interopBridgeToken.json +298 -0
  60. package/src/abi/interopXGateway.json +184 -0
  61. package/src/api/index.ts +36 -0
  62. package/src/config/index.ts +18 -2
  63. package/src/constants/addresses.ts +9 -2
  64. package/src/constants/index.ts +2 -0
  65. package/src/constants/itokens.ts +10 -0
  66. package/src/constants/tokens.ts +104 -0
  67. package/src/db/index.ts +1 -1
  68. package/src/db/models/index.ts +1 -1
  69. package/src/db/models/transaction.ts +106 -0
  70. package/src/db/sequelize.ts +2 -1
  71. package/src/gnosis/actions/deposit.ts +63 -0
  72. package/src/gnosis/actions/index.ts +7 -0
  73. package/src/gnosis/actions/withdraw.ts +67 -0
  74. package/src/gnosis/index.ts +19 -0
  75. package/src/index.ts +128 -6
  76. package/src/net/peer/index.ts +12 -10
  77. package/src/net/pool/index.ts +43 -13
  78. package/src/net/protocol/dial/BaseDialProtocol.ts +1 -1
  79. package/src/net/protocol/dial/SignatureDialProtocol.ts +20 -17
  80. package/src/net/protocol/dial/TransactionStatusDialProtocol.ts +31 -0
  81. package/src/net/protocol/index.ts +60 -4
  82. package/src/tasks/AutoUpdateTask.ts +82 -0
  83. package/src/tasks/BaseTask.ts +16 -7
  84. package/src/tasks/InteropBridge/ProcessWithdrawEvents.ts +249 -0
  85. package/src/tasks/InteropBridge/SyncBurnEvents.ts +119 -0
  86. package/src/tasks/InteropBridge/SyncMintEvents.ts +99 -0
  87. package/src/tasks/InteropXGateway/ProcessDepositEvents.ts +260 -0
  88. package/src/tasks/InteropXGateway/SyncDepositEvents.ts +124 -0
  89. package/src/tasks/InteropXGateway/SyncWithdrawtEvents.ts +105 -0
  90. package/src/tasks/Transactions/SyncTransactionStatusTask.ts +65 -0
  91. package/src/tasks/index.ts +45 -1
  92. package/src/typechain/Erc20.ts +491 -0
  93. package/src/typechain/GnosisSafe.ts +1728 -0
  94. package/src/typechain/InteropBridgeToken.ts +692 -0
  95. package/src/typechain/InteropXGateway.ts +407 -0
  96. package/src/typechain/common.ts +44 -0
  97. package/src/typechain/factories/Erc20__factory.ts +368 -0
  98. package/src/typechain/factories/GnosisSafe__factory.ts +1178 -0
  99. package/src/typechain/factories/InteropBridgeToken__factory.ts +478 -0
  100. package/src/typechain/factories/InteropXGateway__factory.ts +272 -0
  101. package/src/typechain/factories/index.ts +7 -0
  102. package/src/typechain/index.ts +12 -0
  103. package/src/types.ts +2 -2
  104. package/src/utils/index.ts +87 -5
  105. package/tsconfig.json +3 -0
  106. package/dist/config/index.js +0 -17
  107. package/dist/constants/addresses.js +0 -13
  108. package/dist/db/models/execution.js +0 -38
  109. package/dist/index.js +0 -34
  110. package/dist/tasks/index.js +0 -19
  111. package/dist/utils/index.js +0 -89
  112. package/src/db/models/execution.ts +0 -57
@@ -0,0 +1,104 @@
1
+ export const tokens = {
2
+ 1: [
3
+ {
4
+ symbol: "ETH",
5
+ name: "Ethereum",
6
+ address: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
7
+ decimals: 18,
8
+ },
9
+ {
10
+ symbol: "DAI",
11
+ name: "DAI Stable",
12
+ address: "0x6B175474E89094C44Da98b954EedeAC495271d0F",
13
+ decimals: 18,
14
+ },
15
+ {
16
+ symbol: "USDC",
17
+ name: "USD Coin",
18
+ address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
19
+ decimals: 6,
20
+ },
21
+ {
22
+ symbol: "USDT",
23
+ name: "Tether USD Coin",
24
+ address: "0xdAC17F958D2ee523a2206206994597C13D831ec7",
25
+ decimals: 6,
26
+ },
27
+ {
28
+ symbol: "WBTC",
29
+ name: "Wrapped BTC",
30
+ address: "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599",
31
+ decimals: 8,
32
+ },
33
+ ],
34
+ 137: [
35
+ {
36
+ symbol: "ETH",
37
+ name: "Ethereum",
38
+ address: "0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619",
39
+ decimals: 18,
40
+ },
41
+ {
42
+ symbol: "DAI",
43
+ name: "DAI Stable",
44
+ address: "0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063",
45
+ decimals: 18,
46
+ },
47
+ {
48
+ symbol: "USDC",
49
+ name: "USD Coin",
50
+ address: "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174",
51
+ decimals: 6,
52
+ },
53
+ {
54
+ symbol: "USDT",
55
+ name: "Tether USD Coin",
56
+ address: "0xc2132D05D31c914a87C6611C10748AEb04B58e8F",
57
+ decimals: 6,
58
+ },
59
+ {
60
+ symbol: "WBTC",
61
+ name: "Wrapped BTC",
62
+ address: "0x1BFD67037B42Cf73acF2047067bd4F2C47D9BfD6",
63
+ decimals: 8,
64
+ },
65
+ {
66
+ symbol: "AVAX",
67
+ name: "Avalanche Token",
68
+ address: "0x2C89bbc92BD86F8075d1DEcc58C7F4E0107f286b",
69
+ decimals: 18,
70
+ },
71
+ ],
72
+ 43114: [
73
+ {
74
+ symbol: "ETH",
75
+ name: "Ethereum",
76
+ address: "0x49D5c2BdFfac6CE2BFdB6640F4F80f226bc10bAB",
77
+ decimals: 18,
78
+ },
79
+ {
80
+ symbol: "DAI",
81
+ name: "DAI Stable",
82
+ address: "0xd586E7F844cEa2F87f50152665BCbc2C279D8d70",
83
+ decimals: 18,
84
+ },
85
+ {
86
+ symbol: "USDC",
87
+ name: "USD Coin",
88
+ address: "0xA7D7079b0FEaD91F3e65f86E8915Cb59c1a4C664",
89
+ decimals: 6,
90
+ },
91
+ {
92
+ symbol: "USDT",
93
+ name: "Tether USD Coin",
94
+ address: "0xc7198437980c041c805A1EDcbA50c1Ce5db95118",
95
+ decimals: 6,
96
+ },
97
+ {
98
+ symbol: "WBTC",
99
+ name: "Wrapped BTC",
100
+ address: "0x50b7545627a5162F82A992c33b87aDc75187B218",
101
+ decimals: 8,
102
+ },
103
+ ],
104
+ };
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,106 @@
1
+ import { sequelize } from '@/db/sequelize'
2
+ import { CreationOptional, InferAttributes, InferCreationAttributes, Model, DataTypes } from 'sequelize';
3
+
4
+ export class Transaction extends Model<InferAttributes<Transaction>, InferCreationAttributes<Transaction>> {
5
+ declare id: CreationOptional<number>;
6
+
7
+ declare transactionHash: string;
8
+ declare action: string;
9
+ declare from: string;
10
+ declare to: string;
11
+
12
+ declare submitTransactionHash: string;
13
+ declare submitBlockNumber: number;
14
+
15
+ declare sourceChainId: number;
16
+ declare sourceTransactionHash: CreationOptional<string>;
17
+ declare sourceBlockNumber: CreationOptional<number>;
18
+ declare sourceStatus: string;
19
+ declare sourceErrors: CreationOptional<string[]>;
20
+ declare sourceLogs: CreationOptional<any[]>;
21
+ declare sourceCreatedAt: CreationOptional<Date>;
22
+ declare sourceDelayUntil: CreationOptional<Date>;
23
+
24
+ declare targetChainId: number;
25
+ declare targetTransactionHash: CreationOptional<string>;
26
+ declare targetBlockNumber: CreationOptional<number>;
27
+ declare targetStatus: string;
28
+ declare targetErrors: CreationOptional<string[]>;
29
+ declare targetLogs: CreationOptional<any[]>;
30
+ declare targetCreatedAt: CreationOptional<Date>;
31
+ declare targetDelayUntil: CreationOptional<Date>;
32
+
33
+ declare submitEvent: any;
34
+ declare sourceEvent: CreationOptional<any>;
35
+ declare targetEvent: CreationOptional<any>;
36
+
37
+ declare metadata: CreationOptional<any>;
38
+
39
+ declare status: string;
40
+
41
+ declare createdAt: CreationOptional<Date>;
42
+ declare updatedAt: CreationOptional<Date>;
43
+ }
44
+
45
+ Transaction.init({
46
+ id: {
47
+ type: DataTypes.INTEGER,
48
+ autoIncrement: true,
49
+ primaryKey: true
50
+ },
51
+
52
+ submitTransactionHash: DataTypes.NUMBER,
53
+ submitBlockNumber: DataTypes.NUMBER,
54
+
55
+ transactionHash: DataTypes.STRING,
56
+ action: DataTypes.STRING,
57
+
58
+ from: DataTypes.STRING,
59
+ to: DataTypes.STRING,
60
+
61
+ sourceChainId: DataTypes.NUMBER,
62
+ sourceTransactionHash: DataTypes.STRING,
63
+ sourceBlockNumber: DataTypes.NUMBER,
64
+ sourceStatus: DataTypes.STRING,
65
+ sourceErrors: {
66
+ type: DataTypes.JSON,
67
+ // defaultValue: [],
68
+ },
69
+ sourceLogs: {
70
+ type: DataTypes.JSON,
71
+ // defaultValue: [],
72
+ },
73
+ sourceCreatedAt: {
74
+ type: DataTypes.DATE,
75
+ defaultValue: Date.now()
76
+ },
77
+ sourceDelayUntil: DataTypes.STRING,
78
+
79
+ targetChainId: DataTypes.NUMBER,
80
+ targetTransactionHash: DataTypes.STRING,
81
+ targetBlockNumber: DataTypes.NUMBER,
82
+ targetStatus: DataTypes.STRING,
83
+ targetErrors: {
84
+ type: DataTypes.JSON,
85
+ // defaultValue: [],
86
+ },
87
+ targetLogs: {
88
+ type: DataTypes.JSON,
89
+ // defaultValue: [],
90
+ },
91
+ targetCreatedAt: DataTypes.DATE,
92
+ targetDelayUntil: DataTypes.DATE,
93
+
94
+ submitEvent: DataTypes.JSON,
95
+ sourceEvent: DataTypes.JSON,
96
+ targetEvent: DataTypes.JSON,
97
+
98
+ metadata: DataTypes.JSON,
99
+
100
+ status: {
101
+ type: DataTypes.STRING,
102
+ defaultValue: 'pending'
103
+ },
104
+ createdAt: DataTypes.DATE,
105
+ updatedAt: DataTypes.DATE,
106
+ }, { 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,63 @@
1
+ import abi from "@/abi";
2
+ import config from "@/config";
3
+ import { itokens, tokens } from "@/constants";
4
+ import { Transaction } from "@/db";
5
+ import { InteropBridgeToken } 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.sourceStatus === 'pending') {
16
+ throw Error('Cannot build data for pending deposit transaction');
17
+ }
18
+
19
+ if (!transaction.submitEvent) {
20
+ throw Error('Cannot build data for transaction without submitEvent');
21
+ }
22
+
23
+
24
+ const token = tokens[transaction.sourceChainId].find(token => token.address.toLowerCase() === transaction.submitEvent.token.toLowerCase());
25
+
26
+ if (!token) {
27
+ throw Error(`Unsupported token ${transaction.submitEvent.token}`);
28
+ }
29
+
30
+ const itoken = itokens[transaction.targetChainId].find(t => t.symbol.toLowerCase() === token.symbol.toLowerCase());
31
+
32
+ if (!itoken) {
33
+ throw Error(`Unsupported itoken ${token.symbol}`);
34
+ }
35
+
36
+ const targetChainProvider = new ethers.providers.JsonRpcProvider(getRpcProviderUrl(transaction.targetChainId as ChainId));
37
+ const targetWallet = new ethers.Wallet(config.privateKey, targetChainProvider);
38
+ const interopBridgeContract = getContract<InteropBridgeToken>(itoken.address, abi.interopBridgeToken, targetWallet);
39
+
40
+ const { data } = await interopBridgeContract.populateTransaction.mint(
41
+ transaction.submitEvent.user,
42
+ ethers.BigNumber.from(transaction.submitEvent.amount.toString()),
43
+ ethers.BigNumber.from(transaction.submitEvent.sourceChainId.toString()),
44
+ transaction.submitTransactionHash,
45
+ );
46
+
47
+ transactions.push({
48
+ to: itoken.address,
49
+ data: data!,
50
+ value: '0',
51
+ operation: OperationType.Call,
52
+ });
53
+
54
+ logs.push({
55
+ type: 'mint', // mint, approved, burn, transfer, borrow, swap, repay, collected, traded, .....
56
+ message: `Minted ${transaction.submitEvent.amount / 10 ** token.decimals} ${token.symbol} to ${transaction.submitEvent.user}`,
57
+ })
58
+
59
+ return {
60
+ transactions,
61
+ logs,
62
+ }
63
+ }
@@ -0,0 +1,7 @@
1
+ import deposit from "./deposit"
2
+ import withdraw from "./withdraw"
3
+
4
+ export default {
5
+ deposit,
6
+ withdraw,
7
+ }
@@ -0,0 +1,67 @@
1
+ import abi from "@/abi";
2
+ import config from "@/config";
3
+ import { addresses, itokens, tokens } from "@/constants";
4
+ import { Transaction } from "@/db";
5
+ import { InteropXGateway } 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 (transaction.action === 'withdraw' && transaction.sourceStatus === 'pending') {
20
+ throw Error('Cannot build data for pending withdraw transaction');
21
+ }
22
+
23
+ if (!transaction.submitEvent) {
24
+ throw Error('Cannot build data for transaction without submitEvent');
25
+ }
26
+
27
+ const { to, amount, sourceChainId, targetChainId, itoken: itokenAddress } = transaction.submitEvent;
28
+
29
+ const itoken = itokens[sourceChainId].find(token => token.address.toLowerCase() === itokenAddress.toLowerCase());
30
+
31
+ if (!itoken) {
32
+ throw Error(`Unsupported itoken ${itokenAddress}`);
33
+ }
34
+
35
+ const token = tokens[targetChainId].find(t => t.symbol.toLowerCase() === itoken.symbol.toLowerCase());
36
+
37
+ if (!token) {
38
+ throw Error(`Unsupported token ${itoken.symbol}`);
39
+ }
40
+
41
+ const targetChainProvider = new ethers.providers.JsonRpcProvider(getRpcProviderUrl(targetChainId as ChainId));
42
+ const targetWallet = new ethers.Wallet(config.privateKey, targetChainProvider);
43
+ const gatewayAddress = addresses[targetChainId].interopXGateway;
44
+ const interopBridgeContract = getContract<InteropXGateway>(gatewayAddress, abi.interopXGateway, targetWallet);
45
+
46
+ const { data } = await interopBridgeContract.populateTransaction.systemWithdraw(
47
+ ethers.BigNumber.from(amount.toString()),
48
+ to,
49
+ token.address,
50
+ ethers.BigNumber.from(sourceChainId.toString()),
51
+ transaction.submitTransactionHash,
52
+ );
53
+
54
+ transactions.push({
55
+ to: gatewayAddress,
56
+ data: data!,
57
+ value: '0',
58
+ operation: OperationType.Call,
59
+ });
60
+
61
+ logs.push({
62
+ type: 'transfer',
63
+ message: `Transfer ${amount / 10 ** token.decimals} ${token.symbol} to ${to}`,
64
+ })
65
+
66
+ return { transactions, logs }
67
+ }
@@ -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,14 +1,103 @@
1
- import { assert } from "console";
1
+ import moduleAlias from 'module-alias';
2
+ import expandHomeDir from "expand-home-dir";
3
+ import fs from 'fs-extra'
4
+ moduleAlias.addAliases({
5
+ "@/": __dirname + "/",
6
+ "@/logger": __dirname + "/logger",
7
+ "@/tasks": __dirname + "/tasks",
8
+ "@/utils": __dirname + "/utils",
9
+ "@/api": __dirname + "/api",
10
+ "@/net": __dirname + "/net",
11
+ "@/db": __dirname + "/db",
12
+ "@/config": __dirname + "/config",
13
+ "@/types": __dirname + "/types",
14
+ "@/abi": __dirname + "/abi",
15
+ "@/constants": __dirname + "/constants",
16
+ "@/typechain": __dirname + "/typechain"
17
+ })
18
+
19
+ moduleAlias();
2
20
  import dotenv from "dotenv";
3
- import { Tasks } from "tasks";
4
- import Logger from "./logger";
5
- import { startPeer } from "./net";
21
+ import chalk from 'chalk';
22
+ import { ethers } from "ethers";
23
+ import packageJson from '../package.json'
6
24
  dotenv.config();
7
25
 
8
- assert(process.env.PRIVATE_KEY, "PRIVATE_KEY is not defined");
9
-
26
+ import Logger from "@/logger";
10
27
  const logger = new Logger('Process')
11
28
 
29
+ const GIT_SHORT_HASH = '@GIT_SHORT_HASH@';
30
+
31
+ const printUsage = () => {
32
+ console.log()
33
+ console.log(`Interop X Node (v${packageJson.version} - rev.${GIT_SHORT_HASH})`)
34
+ console.log()
35
+
36
+ console.log('Usage:')
37
+ console.log(' interop-x help Show this message')
38
+ console.log(' interop-x version Print out the installed version of Interop X')
39
+
40
+ console.log()
41
+
42
+ console.log(' interop-x down Put the node into maintenance mode')
43
+ console.log(' interop-x up Take the node out of maintenance mode')
44
+
45
+ console.log()
46
+
47
+ console.log(' PRIVATE_KEY=abcd1234 interop-x Start the node with the given private key')
48
+ console.log(' PRIVATE_KEY=abcd1234 STAGING=true interop-x Start the node in staging mode')
49
+ console.log(' PRIVATE_KEY=abcd1234 AUTO_UPDATE=true interop-x Start the node in auto update mode')
50
+ 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')
51
+ console.log()
52
+
53
+ }
54
+
55
+ if (process.argv.at(-1) === 'help') {
56
+ printUsage()
57
+ process.exit(0)
58
+ }
59
+
60
+ const basePath = expandHomeDir(`~/.interop-x`);
61
+
62
+ if (process.argv.at(-1) === 'down') {
63
+ fs.outputFileSync(basePath + '/maintenance', Date.now().toString())
64
+ console.log(chalk.red('Maintenance mode enabled'))
65
+ process.exit(0)
66
+ }
67
+
68
+ if (process.argv.at(-1) === 'up') {
69
+ fs.removeSync(basePath + '/maintenance')
70
+ console.log(chalk.green('Maintenance mode disabled'))
71
+ process.exit(0)
72
+ }
73
+
74
+
75
+ if (process.argv.at(-1) === 'version') {
76
+ console.log(`Interop X Node (v${packageJson.version} - rev.${GIT_SHORT_HASH})`)
77
+ process.exit(0)
78
+ }
79
+
80
+ if (!process.env.PRIVATE_KEY) {
81
+ console.error(chalk.bgRed.white.bold('Please provide a private key\n'))
82
+ printUsage()
83
+ process.exit(1)
84
+ }
85
+ try {
86
+ new ethers.Wallet(process.env.PRIVATE_KEY!)
87
+ } catch (e) {
88
+ console.error(chalk.bgRed.white('Invalid private key\n'))
89
+ printUsage()
90
+ process.exit(1)
91
+ }
92
+
93
+ logger.debug(`Starting Interop X Node (v${packageJson.version} - rev.${GIT_SHORT_HASH})`)
94
+
95
+ import { Tasks } from "@/tasks";
96
+ import { startPeer, protocol, peerPool } from "@/net";
97
+ import { startApiServer } from '@/api';
98
+ import { Transaction } from './db';
99
+ import { shortenHash } from './utils';
100
+
12
101
  async function main() {
13
102
 
14
103
  startPeer({})
@@ -16,6 +105,39 @@ async function main() {
16
105
  const tasks = new Tasks()
17
106
 
18
107
  tasks.start();
108
+
109
+ startApiServer()
110
+
111
+ protocol.on('TransactionStatus', async (payload) => {
112
+ if (!peerPool.isLeadNode(payload.peerId)) {
113
+ const peer = peerPool.getPeer(payload.peerId)
114
+
115
+ if (!peer) {
116
+ return;
117
+ }
118
+
119
+ logger.info(`ignored transaction status from ${payload.peerId} ${shortenHash(peer.publicAddress)} `)
120
+ return;
121
+ }
122
+
123
+ const transaction = await Transaction.findOne({ where: { transactionHash: payload.data.transactionHash } })
124
+
125
+ if (!transaction) {
126
+ return;
127
+ }
128
+
129
+ transaction.sourceStatus = payload.data.sourceStatus
130
+ transaction.sourceTransactionHash = payload.data.sourceTransactionHash
131
+ transaction.sourceErrors = payload.data.sourceErrors
132
+
133
+ transaction.targetStatus = payload.data.targetStatus
134
+ transaction.targetTransactionHash = payload.data.targetTransactionHash
135
+ transaction.targetErrors = payload.data.targetErrors
136
+
137
+ transaction.status = payload.data.status
138
+
139
+ await transaction.save()
140
+ })
19
141
  }
20
142
 
21
143
  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