@instadapp/interop-x 0.0.0-dev.7a02577 → 0.0.0-dev.7c2b0e5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/package.json +6 -3
- package/dist/src/index.js +1 -1
- package/dist/src/net/peer/index.js +6 -2
- package/dist/src/net/pool/index.js +16 -9
- package/dist/src/net/protocol/dial/SignatureDialProtocol.js +11 -4
- package/dist/src/tasks/BaseTask.js +1 -1
- package/dist/src/tasks/InteropXGateway/ProcessDepositEvents.js +25 -7
- package/dist/src/tasks/InteropXGateway/SyncDepositEvents.js +3 -3
- package/dist/src/tasks/index.js +4 -0
- package/dist/src/utils/index.js +44 -3
- package/package.json +6 -3
- package/patches/@ethersproject+properties+5.6.0.patch +13 -0
- package/src/net/peer/index.ts +7 -6
- package/src/net/pool/index.ts +20 -10
- package/src/net/protocol/dial/SignatureDialProtocol.ts +12 -4
- package/src/tasks/BaseTask.ts +1 -1
- package/src/tasks/InteropXGateway/ProcessDepositEvents.ts +33 -12
- package/src/tasks/InteropXGateway/SyncDepositEvents.ts +5 -5
- package/src/tasks/index.ts +7 -2
- package/src/utils/index.ts +58 -5
package/dist/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@instadapp/interop-x",
|
3
|
-
"version": "0.0.0-dev.
|
3
|
+
"version": "0.0.0-dev.7c2b0e5",
|
4
4
|
"license": "MIT",
|
5
5
|
"main": "dist/index.js",
|
6
6
|
"engines": {
|
@@ -12,7 +12,8 @@
|
|
12
12
|
"build": "yarn generate-abi-types && export GIT_REF=$(git rev-parse --short HEAD) && rimraf ./dist && tsc -p tsconfig.json && replace-in-file '@GIT_SHORT_HASH@' $GIT_REF ./dist/**/*.js",
|
13
13
|
"dev": "yarn generate-abi-types && NODE_ENV=development nodemon",
|
14
14
|
"generate-abi-types": "typechain --target=ethers-v5 'src/abi/*.json' --out-dir 'src/typechain'",
|
15
|
-
"prepublishOnly": "yarn build"
|
15
|
+
"prepublishOnly": "yarn build",
|
16
|
+
"postinstall": "patch-package"
|
16
17
|
},
|
17
18
|
"nodemonConfig": {
|
18
19
|
"watch": [
|
@@ -45,7 +46,7 @@
|
|
45
46
|
"libp2p-websockets": "^0.16.2",
|
46
47
|
"luxon": "^2.3.2",
|
47
48
|
"module-alias": "^2.2.2",
|
48
|
-
"sequelize": "
|
49
|
+
"sequelize": "6.18.0",
|
49
50
|
"sqlite3": "^5.0.5",
|
50
51
|
"waait": "^1.0.5"
|
51
52
|
},
|
@@ -59,6 +60,8 @@
|
|
59
60
|
"@types/fs-extra": "^9.0.13",
|
60
61
|
"@types/node": "^17.0.17",
|
61
62
|
"nodemon": "^2.0.15",
|
63
|
+
"patch-package": "^6.4.7",
|
64
|
+
"postinstall-postinstall": "^2.1.0",
|
62
65
|
"replace-in-file": "^6.3.2",
|
63
66
|
"rimraf": "^3.0.2",
|
64
67
|
"ts-node": "^10.5.0",
|
package/dist/src/index.js
CHANGED
@@ -40,7 +40,7 @@ catch (e) {
|
|
40
40
|
logger.error('Invalid private key');
|
41
41
|
process.exit(1);
|
42
42
|
}
|
43
|
-
logger.debug(`Starting Interop X Node (v${package_json_1.default.version} - rev.
|
43
|
+
logger.debug(`Starting Interop X Node (v${package_json_1.default.version} - rev.7c2b0e5)`);
|
44
44
|
const tasks_1 = require("@/tasks");
|
45
45
|
const net_1 = require("@/net");
|
46
46
|
const api_1 = require("@/api");
|
@@ -82,8 +82,12 @@ const startPeer = async ({}) => {
|
|
82
82
|
net_1.protocol.start({
|
83
83
|
libp2p: node
|
84
84
|
});
|
85
|
-
node.on("peer:discovery", (peer) =>
|
86
|
-
|
85
|
+
node.on("peer:discovery", (peer) => {
|
86
|
+
// logger.log(`Discovered peer ${peer}`)
|
87
|
+
}); // peer disc.
|
88
|
+
node.connectionManager.on("peer:connect", (connection) => {
|
89
|
+
// logger.log(`Connected to ${connection.remotePeer.toB58String()}`)
|
90
|
+
});
|
87
91
|
logger.log("Peer discovery started");
|
88
92
|
await (0, waait_1.default)(1000);
|
89
93
|
setInterval(() => net_1.protocol.sendPeerInfo({
|
@@ -6,6 +6,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.peerPool = exports.PeerPool = void 0;
|
7
7
|
const types_1 = require("@/types");
|
8
8
|
const config_1 = __importDefault(require("@/config"));
|
9
|
+
const logger_1 = __importDefault(require("@/logger"));
|
10
|
+
const logger = new logger_1.default('PeerPool');
|
9
11
|
class PeerPool {
|
10
12
|
constructor() {
|
11
13
|
this.PEERS_CLEANUP_TIME_LIMIT = 1;
|
@@ -62,10 +64,14 @@ class PeerPool {
|
|
62
64
|
* @emits {@link Event.POOL_PEER_ADDED}
|
63
65
|
*/
|
64
66
|
add(peer) {
|
65
|
-
if (peer && peer.id
|
67
|
+
if (peer && peer.id) {
|
68
|
+
const newPeer = !this.pool.get(peer.id);
|
66
69
|
this.pool.set(peer.id, peer);
|
67
70
|
peer.pooled = true;
|
68
|
-
|
71
|
+
if (newPeer) {
|
72
|
+
config_1.default.events.emit(types_1.Event.POOL_PEER_ADDED, peer);
|
73
|
+
logger.info(`Peer ${peer.id} with address ${peer.publicAddress} added to pool`);
|
74
|
+
}
|
69
75
|
}
|
70
76
|
}
|
71
77
|
/**
|
@@ -78,6 +84,7 @@ class PeerPool {
|
|
78
84
|
if (this.pool.delete(peer.id)) {
|
79
85
|
peer.pooled = false;
|
80
86
|
config_1.default.events.emit(types_1.Event.POOL_PEER_REMOVED, peer);
|
87
|
+
logger.info(`Peer ${peer.id} with address ${peer.publicAddress} removed from pool`);
|
81
88
|
}
|
82
89
|
}
|
83
90
|
}
|
@@ -94,13 +101,13 @@ class PeerPool {
|
|
94
101
|
return this.activePeers.map((p) => p.id);
|
95
102
|
}
|
96
103
|
cleanup() {
|
97
|
-
let compDate = Date.now() - this.PEERS_CLEANUP_TIME_LIMIT * 60
|
98
|
-
this.peers.forEach((peerInfo) => {
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
})
|
104
|
+
// let compDate = Date.now() - this.PEERS_CLEANUP_TIME_LIMIT * 60
|
105
|
+
// this.peers.forEach((peerInfo) => {
|
106
|
+
// if (peerInfo.updated.getTime() < compDate) {
|
107
|
+
// console.log(`Peer ${peerInfo.id} idle for ${this.PEERS_CLEANUP_TIME_LIMIT} minutes`)
|
108
|
+
// this.remove(peerInfo)
|
109
|
+
// }
|
110
|
+
// })
|
104
111
|
}
|
105
112
|
}
|
106
113
|
exports.PeerPool = PeerPool;
|
@@ -33,12 +33,19 @@ class SignatureDialProtocol extends BaseDialProtocol_1.BaseDialProtocol {
|
|
33
33
|
error: 'Event not found'
|
34
34
|
};
|
35
35
|
}
|
36
|
+
console.log("signing:", {
|
37
|
+
to: constants_1.addresses[transaction.targetChainId].multisend,
|
38
|
+
data: await (0, utils_1.buildDataForTransaction)(transaction, data.type),
|
39
|
+
chainId: transaction.targetChainId,
|
40
|
+
safeTxGas: data.safeTxGas,
|
41
|
+
nonce: data.safeNonce,
|
42
|
+
});
|
36
43
|
const signedData = await (0, utils_1.signGnosisSafeTx)({
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
chainId: transaction.sourceChainId,
|
44
|
+
to: constants_1.addresses[transaction.targetChainId].multisend,
|
45
|
+
data: await (0, utils_1.buildDataForTransaction)(transaction, data.type),
|
46
|
+
chainId: transaction.targetChainId,
|
41
47
|
safeTxGas: data.safeTxGas,
|
48
|
+
nonce: data.safeNonce,
|
42
49
|
}, { signer });
|
43
50
|
return {
|
44
51
|
signer: signer.address,
|
@@ -28,7 +28,7 @@ class BaseTask extends events_1.default {
|
|
28
28
|
}
|
29
29
|
}
|
30
30
|
catch (err) {
|
31
|
-
this.logger.error(`poll check error
|
31
|
+
this.logger.error(`poll check error:\n${err.message}\ntrace: ${err.stack}`);
|
32
32
|
}
|
33
33
|
await this.postPollHandler();
|
34
34
|
}
|
@@ -15,6 +15,7 @@ const sequelize_1 = require("sequelize");
|
|
15
15
|
const waait_1 = __importDefault(require("waait"));
|
16
16
|
const net_1 = require("@/net");
|
17
17
|
const generateGnosisTransaction = async (transactionData, safeContract) => {
|
18
|
+
console.log(transactionData);
|
18
19
|
let isExecuted = await safeContract.dataHashes(await safeContract.getTransactionHash(transactionData.to, transactionData.value, transactionData.data, transactionData.operation, transactionData.safeTxGas, transactionData.baseGas, transactionData.gasPrice, transactionData.gasToken, transactionData.refundReceiver, transactionData.nonce));
|
19
20
|
while (isExecuted == 1) {
|
20
21
|
transactionData.safeTxGas = ethers_1.BigNumber.from(String(transactionData.safeTxGas)).add(1).toString();
|
@@ -37,30 +38,38 @@ class ProcessDepositEvents extends BaseTask_1.BaseTask {
|
|
37
38
|
where: {
|
38
39
|
status: 'pending',
|
39
40
|
sourceStatus: 'success',
|
41
|
+
targetStatus: 'uninitialised',
|
40
42
|
action: 'deposit',
|
41
43
|
sourceCreatedAt: {
|
42
44
|
[sequelize_1.Op.gte]: new Date(Date.now() - 12 * 60 * 60 * 1000),
|
43
45
|
},
|
46
|
+
targetDelayUntil: {
|
47
|
+
[sequelize_1.Op.or]: {
|
48
|
+
[sequelize_1.Op.is]: null,
|
49
|
+
[sequelize_1.Op.lt]: new Date(),
|
50
|
+
}
|
51
|
+
},
|
44
52
|
sourceBlockNumber: {
|
45
53
|
[sequelize_1.Op.lt]: blockNumber - 12,
|
46
|
-
}
|
54
|
+
},
|
55
|
+
sourceChainId: this.chainId,
|
47
56
|
}
|
48
57
|
});
|
49
58
|
if (!transaction) {
|
50
59
|
return;
|
51
60
|
}
|
52
|
-
transaction.
|
61
|
+
transaction.targetStatus = 'pending';
|
53
62
|
await transaction.save();
|
54
63
|
// refresh event data?
|
55
64
|
const targetChainProvider = new ethers_1.ethers.providers.JsonRpcProvider((0, utils_1.getRpcProviderUrl)(transaction.targetChainId));
|
56
65
|
const targetWallet = new ethers_1.ethers.Wallet(config_1.default.privateKey, targetChainProvider);
|
57
66
|
const safeAddress = constants_1.addresses[transaction.targetChainId].gnosisSafe;
|
58
|
-
const safeContract =
|
67
|
+
const safeContract = (0, utils_1.getContract)(safeAddress, abi_1.default.gnosisSafe, targetWallet);
|
59
68
|
const ownersThreshold = await safeContract.getThreshold();
|
60
69
|
await (0, waait_1.default)(10000);
|
61
70
|
let gnosisTx = await generateGnosisTransaction({
|
62
71
|
baseGas: "0",
|
63
|
-
data: (0, utils_1.buildDataForTransaction)(transaction),
|
72
|
+
data: await (0, utils_1.buildDataForTransaction)(transaction),
|
64
73
|
gasPrice: "0",
|
65
74
|
gasToken: "0x0000000000000000000000000000000000000000",
|
66
75
|
nonce: '0',
|
@@ -74,6 +83,7 @@ class ProcessDepositEvents extends BaseTask_1.BaseTask {
|
|
74
83
|
const owners = await safeContract.getOwners().then(owners => owners.map(owner => owner.toLowerCase()));
|
75
84
|
const ownerPeerIds = net_1.peerPool.activePeers.filter(peer => owners.includes(peer.publicAddress.toLowerCase())).map(peer => peer.id);
|
76
85
|
console.log(`Collecting signatures for execution ${transaction.transactionHash}`);
|
86
|
+
console.log(ownerPeerIds);
|
77
87
|
const signatures = await net_1.protocol.requestSignatures({
|
78
88
|
type: 'source',
|
79
89
|
transactionHash: transaction.transactionHash,
|
@@ -84,8 +94,8 @@ class ProcessDepositEvents extends BaseTask_1.BaseTask {
|
|
84
94
|
console.log({ signatures, validSignatures, ownersThreshold: ownersThreshold.toString() });
|
85
95
|
if (validSignatures.length === 0 || ownersThreshold.gt(validSignatures.length)) {
|
86
96
|
await transaction.save();
|
87
|
-
transaction.
|
88
|
-
transaction.
|
97
|
+
transaction.targetDelayUntil = new Date(Date.now() + 30 * 1000);
|
98
|
+
transaction.targetStatus = 'uninitialised';
|
89
99
|
await transaction.save();
|
90
100
|
const errorMessage = (_a = signatures.find(s => !!s.error)) === null || _a === void 0 ? void 0 : _a.error;
|
91
101
|
throw new Error(`Not enough signatures` + (errorMessage ? `: ${errorMessage}` : ''));
|
@@ -107,6 +117,14 @@ class ProcessDepositEvents extends BaseTask_1.BaseTask {
|
|
107
117
|
execTransactionParams
|
108
118
|
});
|
109
119
|
const { data: txData } = await safeContract.populateTransaction.execTransaction(gnosisTx.to, gnosisTx.value, gnosisTx.data, gnosisTx.operation, gnosisTx.safeTxGas, gnosisTx.baseGas, gnosisTx.gasPrice, gnosisTx.gasToken, gnosisTx.refundReceiver, (0, utils_1.buildSignatureBytes)(validSignatures));
|
120
|
+
console.log({
|
121
|
+
from: targetWallet.address,
|
122
|
+
gasPrice: ethers_1.BigNumber.from(120 * 10 ** 9).toString(),
|
123
|
+
gasLimit: ethers_1.BigNumber.from(6000000).toString(),
|
124
|
+
to: safeAddress,
|
125
|
+
data: txData,
|
126
|
+
});
|
127
|
+
return;
|
110
128
|
const txSent = await targetWallet.sendTransaction({
|
111
129
|
from: targetWallet.address,
|
112
130
|
gasPrice: ethers_1.BigNumber.from(120 * 10 ** 9),
|
@@ -133,7 +151,7 @@ class ProcessDepositEvents extends BaseTask_1.BaseTask {
|
|
133
151
|
this.logger.info(`Starting execution watcher on interop chain`);
|
134
152
|
this.contractAddress = constants_1.addresses[this.chainId].interopXGateway;
|
135
153
|
this.provider = new ethers_1.ethers.providers.JsonRpcProvider((0, utils_1.getRpcProviderUrl)(this.chainId));
|
136
|
-
this.contract =
|
154
|
+
this.contract = (0, utils_1.getContract)(this.contractAddress, abi_1.default.interopXGateway, new ethers_1.ethers.Wallet(config_1.default.privateKey, this.provider));
|
137
155
|
await super.start();
|
138
156
|
}
|
139
157
|
}
|
@@ -45,14 +45,14 @@ class SyncDepositEvents extends BaseTask_1.BaseTask {
|
|
45
45
|
sourceChainId: sourceChainId.toString(),
|
46
46
|
targetChainId: targetChainId.toString(),
|
47
47
|
token: token,
|
48
|
-
|
48
|
+
amount: amount.toString(),
|
49
49
|
vnonce: vnonce.toString(),
|
50
50
|
}, sourceEvent: {
|
51
51
|
user,
|
52
52
|
sourceChainId: sourceChainId.toString(),
|
53
53
|
targetChainId: targetChainId.toString(),
|
54
54
|
token: token,
|
55
|
-
|
55
|
+
amount: amount.toString(),
|
56
56
|
vnonce: vnonce.toString(),
|
57
57
|
}, status: "pending" }));
|
58
58
|
this.logger.info(`Execution queued: ${event.transactionHash} ${event.blockNumber}`);
|
@@ -68,7 +68,7 @@ class SyncDepositEvents extends BaseTask_1.BaseTask {
|
|
68
68
|
this.logger.info(`Starting execution watcher on interop chain`);
|
69
69
|
this.contractAddress = constants_1.addresses[this.chainId].interopXGateway;
|
70
70
|
this.provider = new ethers_1.ethers.providers.JsonRpcProvider((0, utils_1.getRpcProviderUrl)(this.chainId));
|
71
|
-
this.contract =
|
71
|
+
this.contract = (0, utils_1.getContract)(this.contractAddress, abi_1.default.interopXGateway, new ethers_1.ethers.Wallet(config_1.default.privateKey, this.provider));
|
72
72
|
await super.start();
|
73
73
|
}
|
74
74
|
}
|
package/dist/src/tasks/index.js
CHANGED
@@ -4,12 +4,16 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
4
|
};
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
6
6
|
exports.Tasks = void 0;
|
7
|
+
const ProcessDepositEvents_1 = __importDefault(require("./InteropXGateway/ProcessDepositEvents"));
|
7
8
|
const SyncDepositEvents_1 = __importDefault(require("./InteropXGateway/SyncDepositEvents"));
|
8
9
|
class Tasks {
|
9
10
|
constructor() {
|
10
11
|
this.tasks = [
|
11
12
|
new SyncDepositEvents_1.default({
|
12
13
|
chainId: 43114
|
14
|
+
}),
|
15
|
+
new ProcessDepositEvents_1.default({
|
16
|
+
chainId: 43114
|
13
17
|
})
|
14
18
|
];
|
15
19
|
}
|
package/dist/src/utils/index.js
CHANGED
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
4
4
|
};
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
6
|
-
exports.buildDataForTransaction = exports.generateInteropTransactionHash = exports.asyncCallWithTimeout = exports.buildSignatureBytes = exports.getRpcProviderUrl = exports.signGnosisSafeTx = exports.short = exports.http = void 0;
|
6
|
+
exports.getContract = exports.buildDataForTransaction = exports.generateInteropTransactionHash = exports.asyncCallWithTimeout = exports.buildSignatureBytes = exports.getRpcProviderUrl = exports.signGnosisSafeTx = exports.short = exports.http = void 0;
|
7
7
|
/**
|
8
8
|
* @module util
|
9
9
|
*/
|
@@ -124,8 +124,8 @@ const buildDataForTransaction = async (transaction, type) => {
|
|
124
124
|
}
|
125
125
|
const targetChainProvider = new ethers_1.ethers.providers.JsonRpcProvider((0, exports.getRpcProviderUrl)(transaction.targetChainId));
|
126
126
|
const targetWallet = new ethers_1.ethers.Wallet(config_1.default.privateKey, targetChainProvider);
|
127
|
-
const interopBridgeContract =
|
128
|
-
const { data } = await interopBridgeContract.populateTransaction.mint(transaction.submitEvent.
|
127
|
+
const interopBridgeContract = getContract(itoken.address, abi_1.default.interopBridgeToken, targetWallet);
|
128
|
+
const { data } = await interopBridgeContract.populateTransaction.mint(transaction.submitEvent.user, ethers_1.ethers.BigNumber.from(transaction.submitEvent.amount.toString()), ethers_1.ethers.BigNumber.from(transaction.submitEvent.sourceChainId.toString()), transaction.sourceTransactionHash);
|
129
129
|
transactions.push({
|
130
130
|
to: itoken.address,
|
131
131
|
data: data,
|
@@ -135,3 +135,44 @@ const buildDataForTransaction = async (transaction, type) => {
|
|
135
135
|
return (0, ethers_multisend_1.encodeMulti)(transactions).data;
|
136
136
|
};
|
137
137
|
exports.buildDataForTransaction = buildDataForTransaction;
|
138
|
+
function getContract(address, contractInterface, signerOrProvider) {
|
139
|
+
if (!ethers_1.ethers.utils.getAddress(address) || address === ethers_1.ethers.constants.AddressZero) {
|
140
|
+
throw Error(`Invalid 'address' parameter '${address}'.`);
|
141
|
+
}
|
142
|
+
const contract = new ethers_1.ethers.Contract(address, contractInterface, signerOrProvider);
|
143
|
+
return new Proxy(contract, {
|
144
|
+
get(target, prop, receiver) {
|
145
|
+
const value = Reflect.get(target, prop, receiver);
|
146
|
+
if (typeof value === 'function' && (contract.functions.hasOwnProperty(prop) || ['queryFilter'].includes(String(prop)))) {
|
147
|
+
return async (...args) => {
|
148
|
+
try {
|
149
|
+
return await value.bind(contract)(...args);
|
150
|
+
}
|
151
|
+
catch (error) {
|
152
|
+
throw new Error(`Error calling "${String(prop)}" on "${address}": ${error.reason || error.message}`);
|
153
|
+
}
|
154
|
+
};
|
155
|
+
}
|
156
|
+
if (typeof value === 'object' && ['populateTransaction', 'estimateGas', 'functions', 'callStatic'].includes(String(prop))) {
|
157
|
+
const parentProp = String(prop);
|
158
|
+
return new Proxy(value, {
|
159
|
+
get(target, prop, receiver) {
|
160
|
+
const value = Reflect.get(target, prop, receiver);
|
161
|
+
if (typeof value === 'function') {
|
162
|
+
return async (...args) => {
|
163
|
+
try {
|
164
|
+
return await value.bind(contract)(...args);
|
165
|
+
}
|
166
|
+
catch (error) {
|
167
|
+
throw new Error(`Error calling "${String(prop)}" using "${parentProp}" on "${address}": ${error.reason || error.message}`);
|
168
|
+
}
|
169
|
+
};
|
170
|
+
}
|
171
|
+
}
|
172
|
+
});
|
173
|
+
}
|
174
|
+
return value;
|
175
|
+
},
|
176
|
+
});
|
177
|
+
}
|
178
|
+
exports.getContract = getContract;
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@instadapp/interop-x",
|
3
|
-
"version": "0.0.0-dev.
|
3
|
+
"version": "0.0.0-dev.7c2b0e5",
|
4
4
|
"license": "MIT",
|
5
5
|
"main": "dist/index.js",
|
6
6
|
"engines": {
|
@@ -12,7 +12,8 @@
|
|
12
12
|
"build": "yarn generate-abi-types && export GIT_REF=$(git rev-parse --short HEAD) && rimraf ./dist && tsc -p tsconfig.json && replace-in-file '@GIT_SHORT_HASH@' $GIT_REF ./dist/**/*.js",
|
13
13
|
"dev": "yarn generate-abi-types && NODE_ENV=development nodemon",
|
14
14
|
"generate-abi-types": "typechain --target=ethers-v5 'src/abi/*.json' --out-dir 'src/typechain'",
|
15
|
-
"prepublishOnly": "yarn build"
|
15
|
+
"prepublishOnly": "yarn build",
|
16
|
+
"postinstall": "patch-package"
|
16
17
|
},
|
17
18
|
"nodemonConfig": {
|
18
19
|
"watch": [
|
@@ -45,7 +46,7 @@
|
|
45
46
|
"libp2p-websockets": "^0.16.2",
|
46
47
|
"luxon": "^2.3.2",
|
47
48
|
"module-alias": "^2.2.2",
|
48
|
-
"sequelize": "
|
49
|
+
"sequelize": "6.18.0",
|
49
50
|
"sqlite3": "^5.0.5",
|
50
51
|
"waait": "^1.0.5"
|
51
52
|
},
|
@@ -59,6 +60,8 @@
|
|
59
60
|
"@types/fs-extra": "^9.0.13",
|
60
61
|
"@types/node": "^17.0.17",
|
61
62
|
"nodemon": "^2.0.15",
|
63
|
+
"patch-package": "^6.4.7",
|
64
|
+
"postinstall-postinstall": "^2.1.0",
|
62
65
|
"replace-in-file": "^6.3.2",
|
63
66
|
"rimraf": "^3.0.2",
|
64
67
|
"ts-node": "^10.5.0",
|
@@ -0,0 +1,13 @@
|
|
1
|
+
diff --git a/node_modules/@ethersproject/properties/lib/index.js b/node_modules/@ethersproject/properties/lib/index.js
|
2
|
+
index 41e0b52..4c7a9e3 100644
|
3
|
+
--- a/node_modules/@ethersproject/properties/lib/index.js
|
4
|
+
+++ b/node_modules/@ethersproject/properties/lib/index.js
|
5
|
+
@@ -44,7 +44,7 @@ function defineReadOnly(object, name, value) {
|
6
|
+
Object.defineProperty(object, name, {
|
7
|
+
enumerable: true,
|
8
|
+
value: value,
|
9
|
+
- writable: false,
|
10
|
+
+ writable: true,
|
11
|
+
});
|
12
|
+
}
|
13
|
+
exports.defineReadOnly = defineReadOnly;
|
package/src/net/peer/index.ts
CHANGED
@@ -88,12 +88,13 @@ export const startPeer = async ({ }: IPeerOptions) => {
|
|
88
88
|
libp2p: node
|
89
89
|
})
|
90
90
|
|
91
|
-
node.on("peer:discovery", (peer) =>
|
92
|
-
logger.log(`Discovered peer ${peer}`)
|
93
|
-
); // peer disc.
|
94
|
-
|
95
|
-
|
96
|
-
|
91
|
+
node.on("peer:discovery", (peer) => {
|
92
|
+
// logger.log(`Discovered peer ${peer}`)
|
93
|
+
}); // peer disc.
|
94
|
+
|
95
|
+
node.connectionManager.on("peer:connect", (connection) => {
|
96
|
+
// logger.log(`Connected to ${connection.remotePeer.toB58String()}`)
|
97
|
+
});
|
97
98
|
|
98
99
|
logger.log("Peer discovery started");
|
99
100
|
|
package/src/net/pool/index.ts
CHANGED
@@ -1,5 +1,9 @@
|
|
1
1
|
import { Event } from "@/types";
|
2
2
|
import config from "@/config";
|
3
|
+
import Logger from "@/logger";
|
4
|
+
|
5
|
+
|
6
|
+
const logger = new Logger('PeerPool')
|
3
7
|
|
4
8
|
export interface IPeerInfo {
|
5
9
|
id: string;
|
@@ -75,10 +79,15 @@ export class PeerPool {
|
|
75
79
|
* @emits {@link Event.POOL_PEER_ADDED}
|
76
80
|
*/
|
77
81
|
add(peer?: IPeerInfo) {
|
78
|
-
if (peer && peer.id
|
82
|
+
if (peer && peer.id) {
|
83
|
+
const newPeer = !this.pool.get(peer.id);
|
79
84
|
this.pool.set(peer.id, peer)
|
80
85
|
peer.pooled = true
|
81
|
-
|
86
|
+
|
87
|
+
if(newPeer) {
|
88
|
+
config.events.emit(Event.POOL_PEER_ADDED, peer)
|
89
|
+
logger.info(`Peer ${peer.id} with address ${peer.publicAddress} added to pool`)
|
90
|
+
}
|
82
91
|
}
|
83
92
|
}
|
84
93
|
|
@@ -92,6 +101,7 @@ export class PeerPool {
|
|
92
101
|
if (this.pool.delete(peer.id)) {
|
93
102
|
peer.pooled = false
|
94
103
|
config.events.emit(Event.POOL_PEER_REMOVED, peer)
|
104
|
+
logger.info(`Peer ${peer.id} with address ${peer.publicAddress} removed from pool`)
|
95
105
|
}
|
96
106
|
}
|
97
107
|
}
|
@@ -114,14 +124,14 @@ export class PeerPool {
|
|
114
124
|
|
115
125
|
|
116
126
|
cleanup() {
|
117
|
-
let compDate = Date.now() - this.PEERS_CLEANUP_TIME_LIMIT * 60
|
118
|
-
|
119
|
-
this.peers.forEach((peerInfo) => {
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
})
|
127
|
+
// let compDate = Date.now() - this.PEERS_CLEANUP_TIME_LIMIT * 60
|
128
|
+
|
129
|
+
// this.peers.forEach((peerInfo) => {
|
130
|
+
// if (peerInfo.updated.getTime() < compDate) {
|
131
|
+
// console.log(`Peer ${peerInfo.id} idle for ${this.PEERS_CLEANUP_TIME_LIMIT} minutes`)
|
132
|
+
// this.remove(peerInfo)
|
133
|
+
// }
|
134
|
+
// })
|
125
135
|
}
|
126
136
|
}
|
127
137
|
|
@@ -47,12 +47,20 @@ export class SignatureDialProtocol extends BaseDialProtocol<ISignatureRequest, I
|
|
47
47
|
};
|
48
48
|
}
|
49
49
|
|
50
|
+
console.log("signing:", {
|
51
|
+
to: addresses[transaction.targetChainId].multisend,
|
52
|
+
data: await buildDataForTransaction(transaction, data.type),
|
53
|
+
chainId: transaction.targetChainId as ChainId,
|
54
|
+
safeTxGas: data.safeTxGas,
|
55
|
+
nonce: data.safeNonce,
|
56
|
+
});
|
57
|
+
|
50
58
|
const signedData = await signGnosisSafeTx({
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
chainId: transaction.sourceChainId as ChainId,
|
59
|
+
to: addresses[transaction.targetChainId].multisend,
|
60
|
+
data: await buildDataForTransaction(transaction, data.type),
|
61
|
+
chainId: transaction.targetChainId as ChainId,
|
55
62
|
safeTxGas: data.safeTxGas,
|
63
|
+
nonce: data.safeNonce,
|
56
64
|
}, { signer });
|
57
65
|
|
58
66
|
return {
|
package/src/tasks/BaseTask.ts
CHANGED
@@ -37,7 +37,7 @@ export class BaseTask extends EventEmitter implements IBaseTask {
|
|
37
37
|
await this.pollHandler()
|
38
38
|
}
|
39
39
|
} catch (err) {
|
40
|
-
this.logger.error(`poll check error
|
40
|
+
this.logger.error(`poll check error:\n${err.message}\ntrace: ${err.stack}`)
|
41
41
|
}
|
42
42
|
|
43
43
|
await this.postPollHandler()
|
@@ -3,7 +3,7 @@ import Logger from '@/logger';
|
|
3
3
|
import { BigNumber, ethers } from "ethers";
|
4
4
|
import abi from "@/abi";
|
5
5
|
import { Transaction } from "@/db";
|
6
|
-
import { buildDataForTransaction, buildSignatureBytes, getRpcProviderUrl, Signature } from "@/utils";
|
6
|
+
import { buildDataForTransaction, buildSignatureBytes, getContract, getRpcProviderUrl, Signature } from "@/utils";
|
7
7
|
import { addresses } from "@/constants";
|
8
8
|
import { ChainId } from "@/types";
|
9
9
|
import config from "@/config";
|
@@ -13,7 +13,9 @@ import wait from "waait";
|
|
13
13
|
import { peerPool, protocol } from "@/net";
|
14
14
|
import { LogDescription } from "ethers/lib/utils";
|
15
15
|
|
16
|
-
const generateGnosisTransaction = async (transactionData: any, safeContract:
|
16
|
+
const generateGnosisTransaction = async (transactionData: any, safeContract: GnosisSafe) => {
|
17
|
+
console.log(transactionData);
|
18
|
+
|
17
19
|
let isExecuted = await safeContract.dataHashes(
|
18
20
|
await safeContract.getTransactionHash(
|
19
21
|
transactionData.to,
|
@@ -72,13 +74,21 @@ class ProcessDepositEvents extends BaseTask {
|
|
72
74
|
where: {
|
73
75
|
status: 'pending',
|
74
76
|
sourceStatus: 'success',
|
77
|
+
targetStatus: 'uninitialised',
|
75
78
|
action: 'deposit',
|
76
79
|
sourceCreatedAt: {
|
77
80
|
[Op.gte]: new Date(Date.now() - 12 * 60 * 60 * 1000),
|
78
81
|
},
|
82
|
+
targetDelayUntil: {
|
83
|
+
[Op.or]: {
|
84
|
+
[Op.is]: null,
|
85
|
+
[Op.lt]: new Date(),
|
86
|
+
}
|
87
|
+
},
|
79
88
|
sourceBlockNumber: {
|
80
89
|
[Op.lt]: blockNumber - 12,
|
81
|
-
}
|
90
|
+
},
|
91
|
+
sourceChainId: this.chainId,
|
82
92
|
}
|
83
93
|
})
|
84
94
|
|
@@ -87,7 +97,7 @@ class ProcessDepositEvents extends BaseTask {
|
|
87
97
|
}
|
88
98
|
|
89
99
|
|
90
|
-
transaction.
|
100
|
+
transaction.targetStatus = 'pending';
|
91
101
|
await transaction.save();
|
92
102
|
|
93
103
|
|
@@ -101,19 +111,19 @@ class ProcessDepositEvents extends BaseTask {
|
|
101
111
|
|
102
112
|
const safeAddress = addresses[transaction.targetChainId].gnosisSafe;
|
103
113
|
|
104
|
-
|
114
|
+
|
115
|
+
const safeContract = getContract<GnosisSafe>(
|
105
116
|
safeAddress,
|
106
117
|
abi.gnosisSafe,
|
107
118
|
targetWallet
|
108
|
-
)
|
119
|
+
)
|
109
120
|
|
110
121
|
const ownersThreshold = await safeContract.getThreshold();
|
111
|
-
|
112
122
|
await wait(10000);
|
113
123
|
|
114
124
|
let gnosisTx = await generateGnosisTransaction({
|
115
125
|
baseGas: "0",
|
116
|
-
data: buildDataForTransaction(transaction),
|
126
|
+
data: await buildDataForTransaction(transaction),
|
117
127
|
gasPrice: "0",
|
118
128
|
gasToken: "0x0000000000000000000000000000000000000000",
|
119
129
|
nonce: '0',
|
@@ -131,6 +141,8 @@ class ProcessDepositEvents extends BaseTask {
|
|
131
141
|
|
132
142
|
console.log(`Collecting signatures for execution ${transaction.transactionHash}`)
|
133
143
|
|
144
|
+
console.log(ownerPeerIds);
|
145
|
+
|
134
146
|
const signatures = await protocol.requestSignatures({
|
135
147
|
type: 'source',
|
136
148
|
transactionHash: transaction.transactionHash,
|
@@ -145,8 +157,8 @@ class ProcessDepositEvents extends BaseTask {
|
|
145
157
|
|
146
158
|
if (validSignatures.length === 0 || ownersThreshold.gt(validSignatures.length)) {
|
147
159
|
await transaction.save();
|
148
|
-
transaction.
|
149
|
-
transaction.
|
160
|
+
transaction.targetDelayUntil = new Date(Date.now() + 30 * 1000);
|
161
|
+
transaction.targetStatus = 'uninitialised'
|
150
162
|
|
151
163
|
await transaction.save();
|
152
164
|
const errorMessage = signatures.find(s => !!s.error)?.error;
|
@@ -185,6 +197,15 @@ class ProcessDepositEvents extends BaseTask {
|
|
185
197
|
buildSignatureBytes(validSignatures)
|
186
198
|
);
|
187
199
|
|
200
|
+
console.log({
|
201
|
+
from: targetWallet.address,
|
202
|
+
gasPrice: BigNumber.from(120 * 10 ** 9).toString(),
|
203
|
+
gasLimit: BigNumber.from(6_000_000).toString(),
|
204
|
+
to: safeAddress,
|
205
|
+
data: txData,
|
206
|
+
})
|
207
|
+
return;
|
208
|
+
|
188
209
|
const txSent = await targetWallet.sendTransaction({
|
189
210
|
from: targetWallet.address,
|
190
211
|
gasPrice: BigNumber.from(120 * 10 ** 9),
|
@@ -219,11 +240,11 @@ class ProcessDepositEvents extends BaseTask {
|
|
219
240
|
getRpcProviderUrl(this.chainId)
|
220
241
|
);
|
221
242
|
|
222
|
-
this.contract =
|
243
|
+
this.contract = getContract<InteropXGateway>(
|
223
244
|
this.contractAddress,
|
224
245
|
abi.interopXGateway,
|
225
246
|
new ethers.Wallet(config.privateKey!, this.provider)
|
226
|
-
)
|
247
|
+
);
|
227
248
|
|
228
249
|
await super.start()
|
229
250
|
}
|
@@ -3,7 +3,7 @@ import Logger from '@/logger';
|
|
3
3
|
import { ethers } from "ethers";
|
4
4
|
import abi from "@/abi";
|
5
5
|
import { Transaction } from "@/db";
|
6
|
-
import { generateInteropTransactionHash, getRpcProviderUrl } from "@/utils";
|
6
|
+
import { generateInteropTransactionHash, getContract, getRpcProviderUrl } from "@/utils";
|
7
7
|
import { addresses } from "@/constants";
|
8
8
|
import { ChainId } from "@/types";
|
9
9
|
import config from "@/config";
|
@@ -77,7 +77,7 @@ class SyncDepositEvents extends BaseTask {
|
|
77
77
|
sourceChainId: sourceChainId.toString(),
|
78
78
|
targetChainId: targetChainId.toString(),
|
79
79
|
token: token,
|
80
|
-
|
80
|
+
amount: amount.toString(),
|
81
81
|
vnonce: vnonce.toString(),
|
82
82
|
},
|
83
83
|
|
@@ -86,7 +86,7 @@ class SyncDepositEvents extends BaseTask {
|
|
86
86
|
sourceChainId: sourceChainId.toString(),
|
87
87
|
targetChainId: targetChainId.toString(),
|
88
88
|
token: token,
|
89
|
-
|
89
|
+
amount: amount.toString(),
|
90
90
|
vnonce: vnonce.toString(),
|
91
91
|
},
|
92
92
|
status: "pending",
|
@@ -113,11 +113,11 @@ class SyncDepositEvents extends BaseTask {
|
|
113
113
|
getRpcProviderUrl(this.chainId)
|
114
114
|
);
|
115
115
|
|
116
|
-
this.contract =
|
116
|
+
this.contract = getContract<InteropXGateway>(
|
117
117
|
this.contractAddress,
|
118
118
|
abi.interopXGateway,
|
119
119
|
new ethers.Wallet(config.privateKey!, this.provider)
|
120
|
-
)
|
120
|
+
);
|
121
121
|
|
122
122
|
await super.start()
|
123
123
|
}
|
package/src/tasks/index.ts
CHANGED
@@ -1,10 +1,15 @@
|
|
1
1
|
import { BaseTask } from "./BaseTask";
|
2
|
-
import
|
2
|
+
import InteropXGatewayProcessDepositEvents from "./InteropXGateway/ProcessDepositEvents";
|
3
|
+
import InteropXGatewaySyncDepositEvents from "./InteropXGateway/SyncDepositEvents";
|
3
4
|
|
4
5
|
export class Tasks {
|
5
6
|
|
6
7
|
tasks: BaseTask[] = [
|
7
|
-
new
|
8
|
+
new InteropXGatewaySyncDepositEvents({
|
9
|
+
chainId: 43114
|
10
|
+
}),
|
11
|
+
|
12
|
+
new InteropXGatewayProcessDepositEvents({
|
8
13
|
chainId: 43114
|
9
14
|
})
|
10
15
|
];
|
package/src/utils/index.ts
CHANGED
@@ -138,7 +138,7 @@ export const buildDataForTransaction = async (transaction: Transaction, type?: '
|
|
138
138
|
|
139
139
|
const transactions: MetaTransaction[] = [];
|
140
140
|
|
141
|
-
if(transaction.action != 'deposit') {
|
141
|
+
if (transaction.action != 'deposit') {
|
142
142
|
throw new Error('Invalid action');
|
143
143
|
}
|
144
144
|
|
@@ -165,12 +165,12 @@ export const buildDataForTransaction = async (transaction: Transaction, type?: '
|
|
165
165
|
|
166
166
|
const targetChainProvider = new ethers.providers.JsonRpcProvider(getRpcProviderUrl(transaction.targetChainId as ChainId));
|
167
167
|
const targetWallet = new ethers.Wallet(config.privateKey, targetChainProvider);
|
168
|
-
const interopBridgeContract =
|
168
|
+
const interopBridgeContract = getContract<InteropBridgeToken>(itoken.address, abi.interopBridgeToken, targetWallet);
|
169
169
|
|
170
170
|
const { data } = await interopBridgeContract.populateTransaction.mint(
|
171
|
-
transaction.submitEvent.
|
172
|
-
transaction.submitEvent.amount,
|
173
|
-
transaction.sourceChainId,
|
171
|
+
transaction.submitEvent.user,
|
172
|
+
ethers.BigNumber.from(transaction.submitEvent.amount.toString()),
|
173
|
+
ethers.BigNumber.from(transaction.submitEvent.sourceChainId.toString()),
|
174
174
|
transaction.sourceTransactionHash,
|
175
175
|
);
|
176
176
|
|
@@ -183,3 +183,56 @@ export const buildDataForTransaction = async (transaction: Transaction, type?: '
|
|
183
183
|
|
184
184
|
return encodeMulti(transactions).data
|
185
185
|
}
|
186
|
+
|
187
|
+
|
188
|
+
export function getContract<TContract extends ethers.Contract>(address: string, contractInterface: ethers.ContractInterface | any, signerOrProvider?: ethers.Signer | ethers.providers.Provider) {
|
189
|
+
if (!ethers.utils.getAddress(address) || address === ethers.constants.AddressZero) {
|
190
|
+
throw Error(`Invalid 'address' parameter '${address}'.`)
|
191
|
+
}
|
192
|
+
|
193
|
+
const contract = new ethers.Contract(
|
194
|
+
address,
|
195
|
+
contractInterface,
|
196
|
+
signerOrProvider
|
197
|
+
) as TContract
|
198
|
+
|
199
|
+
|
200
|
+
return new Proxy(contract, {
|
201
|
+
get(target, prop, receiver) {
|
202
|
+
const value = Reflect.get(target, prop, receiver);
|
203
|
+
|
204
|
+
if (typeof value === 'function' && (contract.functions.hasOwnProperty(prop) || ['queryFilter'].includes(String(prop)))) {
|
205
|
+
return async (...args: any[]) => {
|
206
|
+
try {
|
207
|
+
return await value.bind(contract)(...args);
|
208
|
+
} catch (error) {
|
209
|
+
throw new Error(`Error calling "${String(prop)}" on "${address}": ${error.reason || error.message}`)
|
210
|
+
}
|
211
|
+
}
|
212
|
+
}
|
213
|
+
|
214
|
+
|
215
|
+
if (typeof value === 'object' && ['populateTransaction', 'estimateGas', 'functions', 'callStatic'].includes(String(prop))) {
|
216
|
+
const parentProp = String(prop);
|
217
|
+
|
218
|
+
return new Proxy(value, {
|
219
|
+
get(target, prop, receiver) {
|
220
|
+
const value = Reflect.get(target, prop, receiver);
|
221
|
+
|
222
|
+
if (typeof value === 'function') {
|
223
|
+
return async (...args: any[]) => {
|
224
|
+
try {
|
225
|
+
return await value.bind(contract)(...args);
|
226
|
+
} catch (error) {
|
227
|
+
throw new Error(`Error calling "${String(prop)}" using "${parentProp}" on "${address}": ${error.reason || error.message}`)
|
228
|
+
}
|
229
|
+
}
|
230
|
+
}
|
231
|
+
}
|
232
|
+
})
|
233
|
+
}
|
234
|
+
|
235
|
+
return value;
|
236
|
+
},
|
237
|
+
});
|
238
|
+
}
|