@instadapp/interop-x 0.0.0-dev.75809ae → 0.0.0-dev.76d0265

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) 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 +130 -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 +115 -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 +159 -0
  32. package/dist/src/tasks/InteropXContract/SyncBridgeCommittedEvents.js +93 -0
  33. package/dist/src/tasks/InteropXContract/SyncBridgeRequestEvents.js +78 -0
  34. package/dist/src/tasks/InteropXContract/SyncBridgeRequestSentEvents.js +90 -0
  35. package/dist/src/tasks/Transactions/SyncTransactionStatusTask.js +55 -0
  36. package/dist/src/tasks/index.js +41 -0
  37. package/dist/src/typechain/Erc20.js +2 -0
  38. package/dist/src/typechain/GnosisSafe.js +2 -0
  39. package/dist/src/typechain/InteropXContract.js +2 -0
  40. package/dist/src/typechain/common.js +2 -0
  41. package/dist/src/typechain/factories/Erc20__factory.js +367 -0
  42. package/dist/src/typechain/factories/GnosisSafe__factory.js +1174 -0
  43. package/dist/src/typechain/factories/InteropXContract__factory.js +635 -0
  44. package/dist/src/typechain/factories/index.js +12 -0
  45. package/dist/src/typechain/index.js +33 -0
  46. package/dist/{types.js → src/types.js} +0 -0
  47. package/dist/src/utils/index.js +193 -0
  48. package/package.json +30 -15
  49. package/patches/@ethersproject+properties+5.6.0.patch +13 -0
  50. package/src/abi/erc20.json +350 -0
  51. package/src/abi/gnosisSafe.json +747 -0
  52. package/src/abi/index.ts +9 -0
  53. package/src/abi/interopXContract.json +454 -0
  54. package/src/alias.ts +6 -0
  55. package/src/api/index.ts +36 -0
  56. package/src/config/index.ts +18 -2
  57. package/src/constants/addresses.ts +13 -6
  58. package/src/constants/index.ts +1 -0
  59. package/src/constants/tokens.ts +127 -0
  60. package/src/db/index.ts +1 -1
  61. package/src/db/models/index.ts +1 -1
  62. package/src/db/models/transaction.ts +145 -0
  63. package/src/db/sequelize.ts +2 -1
  64. package/src/gnosis/actions/index.ts +5 -0
  65. package/src/gnosis/actions/withdraw/index.ts +155 -0
  66. package/src/gnosis/index.ts +19 -0
  67. package/src/index.ts +118 -7
  68. package/src/net/peer/index.ts +12 -10
  69. package/src/net/pool/index.ts +43 -13
  70. package/src/net/protocol/dial/BaseDialProtocol.ts +1 -1
  71. package/src/net/protocol/dial/SignatureDialProtocol.ts +24 -17
  72. package/src/net/protocol/dial/TransactionStatusDialProtocol.ts +33 -0
  73. package/src/net/protocol/index.ts +70 -4
  74. package/src/tasks/AutoUpdateTask.ts +82 -0
  75. package/src/tasks/BaseTask.ts +16 -7
  76. package/src/tasks/InteropXContract/ProcessBridgeRequestEvents.ts +227 -0
  77. package/src/tasks/InteropXContract/SyncBridgeCommittedEvents.ts +125 -0
  78. package/src/tasks/InteropXContract/SyncBridgeRequestEvents.ts +115 -0
  79. package/src/tasks/InteropXContract/SyncBridgeRequestSentEvents.ts +121 -0
  80. package/src/tasks/Transactions/SyncTransactionStatusTask.ts +67 -0
  81. package/src/tasks/index.ts +28 -2
  82. package/src/typechain/Erc20.ts +491 -0
  83. package/src/typechain/GnosisSafe.ts +1728 -0
  84. package/src/typechain/InteropXContract.ts +680 -0
  85. package/src/typechain/common.ts +44 -0
  86. package/src/typechain/factories/Erc20__factory.ts +368 -0
  87. package/src/typechain/factories/GnosisSafe__factory.ts +1178 -0
  88. package/src/typechain/factories/InteropXContract__factory.ts +642 -0
  89. package/src/typechain/factories/index.ts +6 -0
  90. package/src/typechain/index.ts +10 -0
  91. package/src/types.ts +2 -2
  92. package/src/utils/index.ts +163 -4
  93. package/tsconfig.json +8 -0
  94. package/dist/config/index.js +0 -17
  95. package/dist/constants/addresses.js +0 -13
  96. package/dist/db/models/execution.js +0 -38
  97. package/dist/index.js +0 -34
  98. package/dist/tasks/index.js +0 -19
  99. package/dist/utils/index.js +0 -89
  100. package/src/db/models/execution.ts +0 -57
@@ -0,0 +1,127 @@
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
+ 43114: [
84
+ {
85
+ aliases: ['eth', 'weth'],
86
+ symbol: "ETH",
87
+ name: "Ethereum",
88
+ address: "0x49D5c2BdFfac6CE2BFdB6640F4F80f226bc10bAB",
89
+ decimals: 18,
90
+ },
91
+ {
92
+ aliases: ['dai'],
93
+ symbol: "DAI",
94
+ name: "DAI Stable",
95
+ address: "0xd586E7F844cEa2F87f50152665BCbc2C279D8d70",
96
+ decimals: 18,
97
+ },
98
+ {
99
+ aliases: ['usdc'],
100
+ symbol: "USDC",
101
+ name: "USD Coin",
102
+ address: "0xA7D7079b0FEaD91F3e65f86E8915Cb59c1a4C664",
103
+ decimals: 6,
104
+ },
105
+ {
106
+ aliases: ['usdt'],
107
+ symbol: "USDt",
108
+ name: "Tether USD Coin",
109
+ address: "0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7",
110
+ decimals: 6,
111
+ },
112
+ {
113
+ aliases: ['usdt'],
114
+ symbol: "USDT.e",
115
+ name: "Tether USD",
116
+ address: "0xc7198437980c041c805A1EDcbA50c1Ce5db95118",
117
+ decimals: 6,
118
+ },
119
+ {
120
+ aliases: ["wbtc"],
121
+ symbol: "WBTC",
122
+ name: "Wrapped BTC",
123
+ address: "0x50b7545627a5162F82A992c33b87aDc75187B218",
124
+ decimals: 8,
125
+ },
126
+ ],
127
+ } 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,145 @@
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<{
62
+ actionId: string;
63
+ bridger: string;
64
+ metadata: string;
65
+ position: IPosition;
66
+ sourceChainId: number;
67
+ targetChainId: number;
68
+ requestTransactionHash: string;
69
+ }>;
70
+ declare completedEvent: CreationOptional<any>;
71
+
72
+ declare status: CreationOptional<string>;
73
+
74
+ declare createdAt: CreationOptional<Date>;
75
+ declare updatedAt: CreationOptional<Date>;
76
+ }
77
+
78
+ Transaction.init({
79
+ id: {
80
+ type: DataTypes.INTEGER,
81
+ autoIncrement: true,
82
+ primaryKey: true
83
+ },
84
+
85
+ requestTransactionHash: DataTypes.NUMBER,
86
+ requestBlockNumber: DataTypes.NUMBER,
87
+
88
+ transactionHash: DataTypes.STRING,
89
+ actionId: DataTypes.STRING,
90
+ bridger: DataTypes.STRING,
91
+
92
+ sourceChainId: DataTypes.NUMBER,
93
+ sourceTransactionHash: DataTypes.STRING,
94
+ sourceBlockNumber: DataTypes.NUMBER,
95
+ sourceStatus: {
96
+ type: DataTypes.STRING,
97
+ defaultValue: 'uninitialised'
98
+ },
99
+ sourceErrors: {
100
+ type: DataTypes.JSON,
101
+ // defaultValue: [],
102
+ },
103
+ sourceLogs: {
104
+ type: DataTypes.JSON,
105
+ // defaultValue: [],
106
+ },
107
+ sourceCreatedAt: {
108
+ type: DataTypes.DATE,
109
+ defaultValue: Date.now()
110
+ },
111
+ sourceDelayUntil: DataTypes.STRING,
112
+
113
+ targetChainId: DataTypes.NUMBER,
114
+ targetTransactionHash: DataTypes.STRING,
115
+ targetBlockNumber: DataTypes.NUMBER,
116
+ targetStatus: {
117
+ type: DataTypes.STRING,
118
+ defaultValue: 'uninitialised'
119
+ },
120
+ targetErrors: {
121
+ type: DataTypes.JSON,
122
+ // defaultValue: [],
123
+ },
124
+ targetLogs: {
125
+ type: DataTypes.JSON,
126
+ // defaultValue: [],
127
+ },
128
+ targetCreatedAt: DataTypes.DATE,
129
+ targetDelayUntil: DataTypes.DATE,
130
+
131
+ requestEvent: {
132
+ type: DataTypes.JSON,
133
+ allowNull: false
134
+ },
135
+ requestSentEvent: DataTypes.JSON,
136
+ committedEvent: DataTypes.JSON,
137
+ completedEvent: DataTypes.JSON,
138
+
139
+ status: {
140
+ type: DataTypes.STRING,
141
+ defaultValue: 'pending'
142
+ },
143
+ createdAt: DataTypes.DATE,
144
+ updatedAt: DataTypes.DATE,
145
+ }, { 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,155 @@
1
+ import abi from "@/abi";
2
+ import config from "@/config";
3
+ import { addresses, tokens } from "@/constants";
4
+ import { Transaction } from "@/db";
5
+ import { Erc20, InteropXContract } from "@/typechain";
6
+ import { ChainId } from "@/types";
7
+ import { getContract, getRpcProviderUrl, LiquidityError } from "@/utils";
8
+ import { BigNumber, ethers } from "ethers";
9
+ import { MetaTransaction, OperationType } from "ethers-multisend";
10
+
11
+
12
+ const getBridgeAmounts = async (user: string, tokens: string[], chainId: ChainId) => {
13
+ const sourceChainProvider = new ethers.providers.JsonRpcProvider(getRpcProviderUrl(chainId));
14
+ const sourceWallet = new ethers.Wallet(config.privateKey, sourceChainProvider);
15
+ const contractAddress = addresses[chainId].interopXContract;
16
+ const contract = getContract<InteropXContract>(contractAddress, abi.interopXContract, sourceWallet);
17
+ const data = await contract.getBridgeAmounts(user, tokens);
18
+
19
+
20
+ return data.map((item, index) => ({
21
+ token: tokens[index],
22
+ deposit: item.deposit,
23
+ withdraw: item.withdraw,
24
+ }))
25
+ }
26
+
27
+ export default async function (transaction: Transaction, type: 'source' | 'target') {
28
+ const transactions: MetaTransaction[] = [];
29
+ const logs: any[] = [];
30
+
31
+ if (transaction.actionId !== 'withdraw') {
32
+ throw new Error(`Invalid action: ${transaction.actionId}`)
33
+ }
34
+
35
+ if (type !== 'source') {
36
+ throw new Error(`[WIP] Type not supported: ${type}`)
37
+ }
38
+
39
+ if (transaction.sourceStatus === 'pending') {
40
+ throw Error('Source transaction already processesing')
41
+ }
42
+
43
+ if (transaction.sourceStatus === 'pending') {
44
+ throw Error('Source transaction already processed')
45
+ }
46
+
47
+ if (!transaction.requestEvent) {
48
+ throw Error('Something went wrong, source transaction has no request event')
49
+ }
50
+
51
+ const { actionId, bridger, position, sourceChainId, targetChainId, metadata } = transaction.requestEvent;
52
+
53
+ const sourceChainProvider = new ethers.providers.JsonRpcProvider(getRpcProviderUrl(sourceChainId as ChainId));
54
+ const sourceWallet = new ethers.Wallet(config.privateKey, sourceChainProvider);
55
+ const contractAddress = addresses[sourceChainId].interopXContract;
56
+ const contract = getContract<InteropXContract>(contractAddress, abi.interopXContract, sourceWallet);
57
+
58
+ const sourceToken = tokens[sourceChainId].find(t => t.address.toLowerCase() === position.withdraw[0].sourceToken.toLowerCase());
59
+
60
+ if (!sourceToken) {
61
+ throw Error('Source token not found')
62
+ }
63
+
64
+ const targetToken = tokens[targetChainId].find(t => t.address.toLowerCase() === position.withdraw[0].targetToken.toLowerCase());
65
+
66
+ if (!targetToken) {
67
+ throw Error('Target token not found')
68
+ }
69
+
70
+ if (!sourceToken.aliases.some(alias => targetToken.aliases.includes(alias))) {
71
+ throw Error('Source and target token must be the same')
72
+ }
73
+
74
+ const networks: ChainId[] = [137, 43114];
75
+ const networkUserData = {}
76
+ for (const network of networks) {
77
+ networkUserData[network] = await getBridgeAmounts(bridger, tokens[network].map(t => t.address), network)
78
+ }
79
+
80
+ for (const tokenSymbol of ["dai", "usdc", "usdt", "eth", "wbtc"]) {
81
+ let totalDeposit = BigNumber.from(0)
82
+ let totalWithdraw = BigNumber.from(0)
83
+
84
+ for (const network of networks) {
85
+ // on avax might we have 2 usdc/usdt tokens
86
+ const matchedTokens = tokens[network].filter(t => t.aliases.includes(tokenSymbol));
87
+
88
+ for (const matchedToken of matchedTokens) {
89
+ const data = networkUserData[network].find(t => t.token.toLowerCase() === matchedToken.address.toLowerCase());
90
+
91
+ if (data) {
92
+ totalDeposit = totalDeposit.add(data.deposit)
93
+ totalWithdraw = totalWithdraw.add(data.withdraw)
94
+ }
95
+ }
96
+
97
+ // on Mainent add weth too
98
+ if (tokenSymbol === "eth" && network === 1) {
99
+ const weth = tokens[1].find(t => t.symbol === 'WETH');
100
+
101
+ if (weth) {
102
+ const data = networkUserData[1].find(t => t.token.toLowerCase() === weth.address.toLowerCase());
103
+
104
+ if (data) {
105
+ totalDeposit = totalDeposit.add(data.deposit)
106
+ totalWithdraw = totalWithdraw.add(data.withdraw)
107
+ }
108
+ }
109
+ }
110
+
111
+ if (totalWithdraw.gt(totalDeposit)) {
112
+ throw Error(`if withdraw > deposit, user has debt and we can't process the withdraw and reject it`)
113
+ }
114
+
115
+ if (totalWithdraw.lt(totalDeposit)) {
116
+ throw Error('Something went wrong')
117
+ }
118
+ }
119
+ }
120
+
121
+ let balance = BigNumber.from(0);
122
+
123
+ if (position.withdraw[0].sourceToken.toLowerCase() === '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE'.toLowerCase()) {
124
+ balance = await sourceChainProvider.getBalance(bridger);
125
+
126
+ } else {
127
+ const erc20 = getContract<Erc20>(position.withdraw[0].sourceToken, abi.erc20, sourceChainProvider);
128
+ balance = await erc20.balanceOf(addresses[sourceChainId].gnosisSafe);
129
+ }
130
+
131
+ if (balance.lt(position.withdraw[0].amount)) {
132
+ throw new LiquidityError()
133
+ }
134
+
135
+
136
+ const { data } = await contract.populateTransaction.withdrawRequested(
137
+ actionId,
138
+ bridger,
139
+ position.withdraw[0].sourceToken,
140
+ position.withdraw[0].targetToken,
141
+ position.withdraw[0].amount,
142
+ targetChainId,
143
+ transaction.requestTransactionHash,
144
+ metadata,
145
+ );
146
+
147
+ transactions.push({
148
+ to: contractAddress,
149
+ data: data!,
150
+ value: '0',
151
+ operation: OperationType.Call,
152
+ });
153
+
154
+ return { transactions, logs }
155
+ }
@@ -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