@instadapp/interop-x 0.0.0-dev.8cb1c22 → 0.0.0-dev.909c44a
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 +9 -2
- package/dist/src/abi/aaveV2Resolver.json +832 -0
- package/dist/src/abi/aaveV3Resolver.json +628 -0
- package/dist/src/abi/balanceResolver.json +211 -0
- package/dist/src/abi/connectors/index.js +2 -2
- package/dist/src/abi/connectors/v2/1INCH-A.js +39 -1
- package/dist/src/abi/connectors/v2/1INCH-V3-A.js +42 -0
- package/dist/src/abi/connectors/v2/1INCH-V4-A.js +42 -0
- package/dist/src/abi/connectors/v2/AAVE-IMPORT-V2-V3-A.js +57 -0
- package/dist/src/abi/connectors/v2/AAVE-V2-A.js +91 -133
- package/dist/src/abi/connectors/v2/AAVE-V2-IMPORT-C.js +4 -0
- package/dist/src/abi/connectors/v2/AAVE-V3-A.js +322 -0
- package/dist/src/abi/connectors/v2/AAVE-V3-CLAIM-A.js +58 -0
- package/dist/src/abi/connectors/v2/AAVE-V3-IMPORT-A.js +59 -0
- package/dist/src/abi/connectors/v2/AAVE-V3-IMPORT-PERMIT-A.js +81 -0
- package/dist/src/abi/connectors/v2/BASIC-A.js +44 -86
- package/dist/src/abi/connectors/v2/BENQI-A.js +901 -0
- package/dist/src/abi/connectors/v2/COMPOUND-IMPORT-C.js +4 -0
- package/dist/src/abi/connectors/v2/COMPOUND-IMPORT-D.js +27 -0
- package/dist/src/abi/connectors/v2/DSA-SPELL-A.js +60 -0
- package/dist/src/abi/connectors/v2/HOP-A.js +41 -0
- package/dist/src/abi/connectors/v2/HOP-MAINNET-A.js +38 -0
- package/dist/src/abi/connectors/v2/INSTA-DEX-SIMULATION-A.js +40 -0
- package/dist/src/abi/connectors/v2/INSTAPOOL-B.js +4 -0
- package/dist/src/abi/connectors/v2/INSTAPOOL-C.js +4 -0
- package/dist/src/abi/connectors/v2/INTEROP-A.js +4 -0
- package/dist/src/abi/connectors/v2/INTEROP-STAGING-A.js +4 -0
- package/dist/src/abi/connectors/v2/LIDO-STETH-A.js +36 -0
- package/dist/src/abi/connectors/v2/LITE-A.js +4 -0
- package/dist/src/abi/connectors/v2/MSTABLE-A.js +4 -0
- package/dist/src/abi/connectors/v2/NOTIONAL-V2-A.js +484 -0
- package/dist/src/abi/connectors/v2/PANGOLIN-A.js +136 -0
- package/dist/src/abi/connectors/v2/PANGOLIN-STAKE-A.js +227 -0
- package/dist/src/abi/connectors/v2/PARASWAP-A.js +26 -1
- package/dist/src/abi/connectors/v2/PARASWAP-V5-A.js +29 -0
- package/dist/src/abi/connectors/v2/POOLTOGETHER-A.js +4 -0
- package/dist/src/abi/connectors/v2/QI-A.js +4 -0
- package/dist/src/abi/connectors/v2/QUICKSWAP-A.js +136 -0
- package/dist/src/abi/connectors/v2/SUSHISWAP-A.js +136 -0
- package/dist/src/abi/connectors/v2/SWAP-AGGREGATOR-A.js +25 -0
- package/dist/src/abi/connectors/v2/UBIQUITY-A.js +73 -0
- package/dist/src/abi/connectors/v2/UNISWAP-SELL-BETA.js +4 -0
- package/dist/src/abi/connectors/v2/UNISWAP-V3-A.js +1 -1
- package/dist/src/abi/connectors/v2/UNISWAP-V3-ROUTER-A.js +4 -0
- package/dist/src/abi/connectors/v2/UNISWAP-V3-STAKER-B.js +193 -0
- package/dist/src/abi/connectors/v2/UNISWAP-V3-SWAP-A.js +74 -0
- package/dist/src/abi/connectors/v2/UNIVERSE-A.js +4 -0
- package/dist/src/abi/connectors/v2/WAVAX-A.js +4 -0
- package/dist/src/abi/connectors/v2/WFTM-A.js +60 -0
- package/dist/src/abi/connectors/v2/WMATIC-A.js +4 -0
- package/dist/src/abi/connectors/v2/ZEROX-A.js +29 -0
- package/dist/src/abi/connectors/v2/ZEROX-V4-A.js +29 -0
- package/dist/src/abi/connectors/v2/index.js +128 -44
- package/dist/src/abi/index.js +8 -0
- package/dist/src/abi/instList.json +232 -0
- package/dist/src/api/index.js +7 -0
- package/dist/src/constants/addresses.js +9 -1
- package/dist/src/constants/capPerChain.js +8 -0
- package/dist/src/constants/index.js +2 -0
- package/dist/src/constants/tokens.js +44 -44
- package/dist/src/constants/wrappedNativeToken.js +8 -0
- package/dist/src/crons/index.js +3 -0
- package/dist/src/crons/prices.js +16 -0
- package/dist/src/db/models/transaction.js +5 -1
- package/dist/src/errors/index.js +30 -0
- package/dist/src/gnosis/actions/aaveV2/source.js +26 -1
- package/dist/src/gnosis/actions/aaveV2/target.js +20 -5
- package/dist/src/gnosis/actions/aaveV3/index.js +11 -0
- package/dist/src/gnosis/actions/aaveV3/source.js +74 -0
- package/dist/src/gnosis/actions/aaveV3/target.js +87 -0
- package/dist/src/gnosis/actions/index.js +2 -0
- package/dist/src/index.js +2 -1
- package/dist/src/providers/index.js +17 -0
- package/dist/src/providers/retry-provider.js +45 -0
- package/dist/src/services/Prices.js +74 -0
- package/dist/src/services/index.js +8 -0
- package/dist/src/tasks/InteropX/{ProcessSubmitSubmitEvents.js → ProcessSubmitEvents.js} +110 -16
- package/dist/src/tasks/InteropX/ProcessValidateEvents.js +30 -10
- package/dist/src/tasks/InteropX/SyncLogExecuteEvents.js +113 -0
- package/dist/src/tasks/InteropX/SyncLogSubmitEvents.js +3 -2
- package/dist/src/tasks/InteropX/SyncLogValidateEvents.js +6 -5
- package/dist/src/tasks/index.js +7 -5
- package/dist/src/typechain/AaveV2Resolver.js +2 -0
- package/dist/src/typechain/AaveV3Resolver.js +2 -0
- package/dist/src/typechain/BalanceResolver.js +2 -0
- package/dist/src/typechain/InstList.js +2 -0
- package/dist/src/typechain/factories/AaveV2Resolver__factory.js +1191 -0
- package/dist/src/typechain/factories/AaveV3Resolver__factory.js +887 -0
- package/dist/src/typechain/factories/BalanceResolver__factory.js +228 -0
- package/dist/src/typechain/factories/InstList__factory.js +249 -0
- package/dist/src/typechain/factories/index.js +9 -1
- package/dist/src/typechain/index.js +9 -1
- package/dist/src/utils/async.js +18 -0
- package/dist/src/utils/dsa.js +36 -0
- package/dist/src/utils/formatting.js +67 -0
- package/dist/src/utils/gnosis.js +87 -0
- package/dist/src/utils/http.js +10 -0
- package/dist/src/utils/index.js +22 -220
- package/dist/src/utils/interop.js +16 -0
- package/dist/src/utils/tokens.js +22 -0
- package/dist/src/utils/validate.js +111 -0
- package/dist/src/utils/web3.js +93 -0
- package/package.json +9 -2
- package/src/abi/aaveV2Resolver.json +832 -0
- package/src/abi/aaveV3Resolver.json +628 -0
- package/src/abi/balanceResolver.json +211 -0
- package/src/abi/connectors/index.ts +5 -5
- package/src/abi/connectors/v2/1INCH-A.ts +39 -1
- package/src/abi/connectors/v2/1INCH-V3-A.ts +41 -0
- package/src/abi/connectors/v2/1INCH-V4-A.ts +41 -0
- package/src/abi/connectors/v2/AAVE-IMPORT-V2-V3-A.ts +56 -0
- package/src/abi/connectors/v2/AAVE-V2-A.ts +93 -135
- package/src/abi/connectors/v2/AAVE-V2-IMPORT-C.ts +3 -0
- package/src/abi/connectors/v2/AAVE-V3-A.ts +321 -0
- package/src/abi/connectors/v2/AAVE-V3-CLAIM-A.ts +57 -0
- package/src/abi/connectors/v2/AAVE-V3-IMPORT-A.ts +58 -0
- package/src/abi/connectors/v2/AAVE-V3-IMPORT-PERMIT-A.ts +80 -0
- package/src/abi/connectors/v2/BASIC-A.ts +44 -86
- package/src/abi/connectors/v2/BENQI-A.ts +900 -0
- package/src/abi/connectors/v2/COMPOUND-IMPORT-C.ts +3 -0
- package/src/abi/connectors/v2/COMPOUND-IMPORT-D.ts +26 -0
- package/src/abi/connectors/v2/DSA-SPELL-A.ts +59 -0
- package/src/abi/connectors/v2/HOP-A.ts +40 -0
- package/src/abi/connectors/v2/HOP-MAINNET-A.ts +37 -0
- package/src/abi/connectors/v2/INSTA-DEX-SIMULATION-A.ts +39 -0
- package/src/abi/connectors/v2/INSTAPOOL-B.ts +3 -0
- package/src/abi/connectors/v2/INSTAPOOL-C.ts +3 -0
- package/src/abi/connectors/v2/INTEROP-A.ts +3 -0
- package/src/abi/connectors/v2/INTEROP-STAGING-A.ts +3 -0
- package/src/abi/connectors/v2/LIDO-STETH-A.ts +35 -0
- package/src/abi/connectors/v2/LITE-A.ts +3 -0
- package/src/abi/connectors/v2/MSTABLE-A.ts +3 -0
- package/src/abi/connectors/v2/NOTIONAL-V2-A.ts +483 -0
- package/src/abi/connectors/v2/PANGOLIN-A.ts +135 -0
- package/src/abi/connectors/v2/PANGOLIN-STAKE-A.ts +226 -0
- package/src/abi/connectors/v2/PARASWAP-A.ts +26 -1
- package/src/abi/connectors/v2/PARASWAP-V5-A.ts +28 -0
- package/src/abi/connectors/v2/POOLTOGETHER-A.ts +3 -0
- package/src/abi/connectors/v2/QI-A.ts +3 -0
- package/src/abi/connectors/v2/QUICKSWAP-A.ts +135 -0
- package/src/abi/connectors/v2/SUSHISWAP-A.ts +135 -0
- package/src/abi/connectors/v2/SWAP-AGGREGATOR-A.ts +24 -0
- package/src/abi/connectors/v2/UBIQUITY-A.ts +72 -0
- package/src/abi/connectors/v2/UNISWAP-SELL-BETA.ts +3 -0
- package/src/abi/connectors/v2/UNISWAP-V3-A.ts +1 -1
- package/src/abi/connectors/v2/UNISWAP-V3-ROUTER-A.ts +3 -0
- package/src/abi/connectors/v2/UNISWAP-V3-STAKER-B.ts +192 -0
- package/src/abi/connectors/v2/UNISWAP-V3-SWAP-A.ts +73 -0
- package/src/abi/connectors/v2/UNIVERSE-A.ts +3 -0
- package/src/abi/connectors/v2/WAVAX-A.ts +3 -0
- package/src/abi/connectors/v2/WFTM-A.ts +59 -0
- package/src/abi/connectors/v2/WMATIC-A.ts +3 -0
- package/src/abi/connectors/v2/ZEROX-A.ts +28 -0
- package/src/abi/connectors/v2/ZEROX-V4-A.ts +28 -0
- package/src/abi/connectors/v2/index.ts +171 -85
- package/src/abi/index.ts +8 -0
- package/src/abi/instList.json +232 -0
- package/src/api/index.ts +8 -0
- package/src/constants/addresses.ts +21 -2
- package/src/constants/capPerChain.ts +5 -0
- package/src/constants/index.ts +2 -0
- package/src/constants/tokens.ts +44 -44
- package/src/constants/wrappedNativeToken.ts +5 -0
- package/src/crons/index.ts +1 -0
- package/src/crons/prices.ts +12 -0
- package/src/db/models/transaction.ts +22 -1
- package/src/errors/index.ts +26 -0
- package/src/gnosis/actions/aaveV2/source.ts +56 -3
- package/src/gnosis/actions/aaveV2/target.ts +35 -7
- package/src/gnosis/actions/aaveV3/index.ts +9 -0
- package/src/gnosis/actions/aaveV3/source.ts +119 -0
- package/src/gnosis/actions/aaveV3/target.ts +142 -0
- package/src/gnosis/actions/index.ts +2 -0
- package/src/index.ts +1 -0
- package/src/providers/index.ts +1 -0
- package/src/providers/retry-provider.ts +51 -0
- package/src/services/Prices.ts +89 -0
- package/src/services/index.ts +1 -0
- package/src/tasks/InteropX/{ProcessSubmitSubmitEvents.ts → ProcessSubmitEvents.ts} +139 -22
- package/src/tasks/InteropX/ProcessValidateEvents.ts +42 -19
- package/src/tasks/InteropX/SyncLogExecuteEvents.ts +161 -0
- package/src/tasks/InteropX/SyncLogSubmitEvents.ts +6 -7
- package/src/tasks/InteropX/SyncLogValidateEvents.ts +9 -10
- package/src/tasks/index.ts +8 -5
- package/src/typechain/AaveV2Resolver.ts +1017 -0
- package/src/typechain/AaveV3Resolver.ts +935 -0
- package/src/typechain/BalanceResolver.ts +266 -0
- package/src/typechain/InstList.ts +402 -0
- package/src/typechain/factories/AaveV2Resolver__factory.ts +1198 -0
- package/src/typechain/factories/AaveV3Resolver__factory.ts +894 -0
- package/src/typechain/factories/BalanceResolver__factory.ts +235 -0
- package/src/typechain/factories/InstList__factory.ts +253 -0
- package/src/typechain/factories/index.ts +4 -0
- package/src/typechain/index.ts +8 -0
- package/src/utils/async.ts +22 -0
- package/src/utils/dsa.ts +56 -0
- package/src/utils/formatting.ts +68 -0
- package/src/utils/gnosis.ts +166 -0
- package/src/utils/http.ts +6 -0
- package/src/utils/index.ts +9 -365
- package/src/utils/interop.ts +28 -0
- package/src/utils/tokens.ts +21 -0
- package/src/utils/validate.ts +179 -0
- package/src/utils/web3.ts +132 -0
@@ -0,0 +1,51 @@
|
|
1
|
+
import { ethers } from "ethers";
|
2
|
+
import wait from "waait";
|
3
|
+
import Bluebird from "bluebird";
|
4
|
+
|
5
|
+
export interface RetryOptions {
|
6
|
+
delay?: number;
|
7
|
+
timeouts: number[];
|
8
|
+
}
|
9
|
+
|
10
|
+
export function promiseTimeout<T>(ms: number, promise: Promise<T>): Promise<T> {
|
11
|
+
return Bluebird.resolve(promise).timeout(ms);
|
12
|
+
}
|
13
|
+
|
14
|
+
export function retryOperation(
|
15
|
+
retriesLeft: number,
|
16
|
+
operation: () => Promise<any>,
|
17
|
+
options: RetryOptions
|
18
|
+
) {
|
19
|
+
return new Promise((resolve, reject) => {
|
20
|
+
const { timeouts } = options;
|
21
|
+
// Find the timeout for this specific iteration
|
22
|
+
const timeout = timeouts[timeouts.length - retriesLeft];
|
23
|
+
|
24
|
+
// Wrap the original operation in a timeout
|
25
|
+
const execution = promiseTimeout(timeout, operation());
|
26
|
+
|
27
|
+
// If the promise is successful, resolve it and bubble the result up
|
28
|
+
return execution.then(resolve).catch((reason: any) => {
|
29
|
+
// If there are any retries left, we call the same retryOperation function again,
|
30
|
+
// but decrementing the number of retries left by 1
|
31
|
+
if (retriesLeft - 1 > 0) {
|
32
|
+
// Delay the new attempt slightly
|
33
|
+
return wait(options.delay || 50)
|
34
|
+
.then(retryOperation.bind(null, retriesLeft - 1, operation, options))
|
35
|
+
.then(resolve)
|
36
|
+
.catch(reject);
|
37
|
+
}
|
38
|
+
// Reject (and bubble the result up) if there are no more retries
|
39
|
+
return reject(reason);
|
40
|
+
});
|
41
|
+
});
|
42
|
+
}
|
43
|
+
|
44
|
+
export class JsonRpcRetryProvider extends ethers.providers.JsonRpcProvider {
|
45
|
+
public perform(method: string, params: any): Promise<any> {
|
46
|
+
const timeouts = [5_000, 10_000];
|
47
|
+
const operation = () => super.perform(method, params);
|
48
|
+
|
49
|
+
return retryOperation(2, operation, { timeouts, delay: 50 });
|
50
|
+
}
|
51
|
+
}
|
@@ -0,0 +1,89 @@
|
|
1
|
+
import Web3Utils from "web3-utils";
|
2
|
+
import path from "path";
|
3
|
+
import fs from "fs";
|
4
|
+
import { tokens } from "@/constants";
|
5
|
+
import expandHomeDir from "expand-home-dir";
|
6
|
+
import config from "@/config";
|
7
|
+
import { http } from "@/utils";
|
8
|
+
|
9
|
+
const basePath = expandHomeDir(`~/.interop-x/data/${config.publicAddress}/${config.staging ? 'staging' : ''}`);
|
10
|
+
const mainnetPricesFilePath = path.resolve(basePath, "./mainnetPrices.json");
|
11
|
+
const networkTokenPricesFilePath = path.resolve(basePath, "./networkTokenPrices.json");
|
12
|
+
|
13
|
+
class Prices {
|
14
|
+
private static mainnetPrices = {};
|
15
|
+
|
16
|
+
private static networkTokenPrices = {};
|
17
|
+
|
18
|
+
static async fetch() {
|
19
|
+
|
20
|
+
if (!fs.existsSync(mainnetPricesFilePath)) {
|
21
|
+
fs.writeFileSync(mainnetPricesFilePath, JSON.stringify({}));
|
22
|
+
}
|
23
|
+
|
24
|
+
if (!fs.existsSync(networkTokenPricesFilePath)) {
|
25
|
+
fs.writeFileSync(networkTokenPricesFilePath, JSON.stringify({}));
|
26
|
+
}
|
27
|
+
|
28
|
+
this.mainnetPrices = JSON.parse(fs.readFileSync(mainnetPricesFilePath, "utf8"));
|
29
|
+
this.networkTokenPrices = JSON.parse(fs.readFileSync(networkTokenPricesFilePath, "utf8"));
|
30
|
+
|
31
|
+
try {
|
32
|
+
const path = tokens["1"]
|
33
|
+
.filter((a) => a.symbol !== "ETH")
|
34
|
+
.map((token) => token.address)
|
35
|
+
.join(",");
|
36
|
+
|
37
|
+
const [response, ethResponse, avaxResponse, polygonResponse] =
|
38
|
+
await Promise.all([
|
39
|
+
http.get(
|
40
|
+
"https://api.coingecko.com/api/v3/simple/token_price/ethereum",
|
41
|
+
{
|
42
|
+
params: { contract_addresses: path, vs_currencies: "usd" },
|
43
|
+
}
|
44
|
+
),
|
45
|
+
http.get("https://api.coingecko.com/api/v3/simple/price", {
|
46
|
+
params: { ids: "ethereum", vs_currencies: "usd" },
|
47
|
+
}),
|
48
|
+
http.get("https://api.coingecko.com/api/v3/simple/price", {
|
49
|
+
params: { ids: "avalanche-2", vs_currencies: "usd" },
|
50
|
+
}),
|
51
|
+
http.get("https://api.coingecko.com/api/v3/simple/price", {
|
52
|
+
params: { ids: "matic-network", vs_currencies: "usd" },
|
53
|
+
}),
|
54
|
+
]);
|
55
|
+
|
56
|
+
this.networkTokenPrices = {
|
57
|
+
"1": ethResponse.data.ethereum.usd.toString(),
|
58
|
+
"137": polygonResponse.data["matic-network"].usd.toString(),
|
59
|
+
"43114": avaxResponse.data["avalanche-2"].usd.toString(),
|
60
|
+
};
|
61
|
+
|
62
|
+
const data = response.data;
|
63
|
+
|
64
|
+
for (const key in data) {
|
65
|
+
const _key = Web3Utils.toChecksumAddress(key);
|
66
|
+
if (!data[key].usd) continue;
|
67
|
+
this.mainnetPrices[_key] = data[key].usd.toString();
|
68
|
+
}
|
69
|
+
|
70
|
+
this.mainnetPrices["0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"] =
|
71
|
+
ethResponse.data.ethereum.usd.toString();
|
72
|
+
} catch (error) { }
|
73
|
+
|
74
|
+
fs.writeFileSync(mainnetPricesFilePath, JSON.stringify(this.mainnetPrices));
|
75
|
+
fs.writeFileSync(networkTokenPricesFilePath, JSON.stringify(this.networkTokenPrices));
|
76
|
+
|
77
|
+
return this.mainnetPrices;
|
78
|
+
}
|
79
|
+
|
80
|
+
static getMainnetPrices() {
|
81
|
+
return this.mainnetPrices;
|
82
|
+
}
|
83
|
+
|
84
|
+
static getNetworkTokenPrices() {
|
85
|
+
return this.networkTokenPrices;
|
86
|
+
}
|
87
|
+
}
|
88
|
+
|
89
|
+
export default Prices;
|
@@ -0,0 +1 @@
|
|
1
|
+
export { default as Prices } from './Prices';
|
@@ -5,12 +5,18 @@ import abi from "@/abi";
|
|
5
5
|
import { Transaction } from "@/db";
|
6
6
|
import {
|
7
7
|
buildSignatureBytes,
|
8
|
+
chainIdToName,
|
9
|
+
generateGnosisSignatureMessage,
|
8
10
|
generateGnosisTransaction,
|
9
|
-
|
11
|
+
getChainIdNativeSymbol,
|
10
12
|
getContract,
|
13
|
+
getExplorerUrl,
|
11
14
|
getRpcProviderUrl,
|
12
|
-
LiquidityError,
|
13
15
|
Signature,
|
16
|
+
validateChains,
|
17
|
+
validateLiquidityCap,
|
18
|
+
validateSourceLiquidity,
|
19
|
+
getGnosisSignatureAddress,
|
14
20
|
} from "@/utils";
|
15
21
|
import { addresses, blockConfirmations } from "@/constants";
|
16
22
|
import { ChainId } from "@/types";
|
@@ -22,9 +28,13 @@ import { buildGnosisAction } from "@/gnosis";
|
|
22
28
|
import { peerPool, protocol } from "@/net";
|
23
29
|
import { LogDescription } from "ethers/lib/utils";
|
24
30
|
import wait from "waait";
|
31
|
+
import { LiquidityError, UnsupportedChaindIdError } from "@/errors";
|
32
|
+
import { BigNumber } from "bignumber.js";
|
33
|
+
import dedent from "dedent";
|
34
|
+
import { JsonRpcRetryProvider } from "@/providers";
|
25
35
|
|
26
|
-
class
|
27
|
-
sourceProvider:
|
36
|
+
export default class ProcessSubmitEvents extends BaseTask {
|
37
|
+
sourceProvider: JsonRpcRetryProvider;
|
28
38
|
sourceGnosisContract: GnosisSafe;
|
29
39
|
sourceWallet: Wallet;
|
30
40
|
chainId: ChainId;
|
@@ -33,7 +43,7 @@ class ProcessSubmitSubmitEvents extends BaseTask {
|
|
33
43
|
|
34
44
|
constructor({ chainId }: { chainId: ChainId }) {
|
35
45
|
super({
|
36
|
-
logger: new Logger("InteropX::
|
46
|
+
logger: new Logger("InteropX::ProcessSubmitEvents"),
|
37
47
|
});
|
38
48
|
this.chainId = chainId;
|
39
49
|
}
|
@@ -73,8 +83,50 @@ class ProcessSubmitSubmitEvents extends BaseTask {
|
|
73
83
|
transaction.sourceStatus = "proccessing";
|
74
84
|
await transaction.save();
|
75
85
|
|
76
|
-
const
|
77
|
-
|
86
|
+
const { submitEvent: { position, sourceChainId, targetChainId, sourceDsaId } } = transaction;
|
87
|
+
try {
|
88
|
+
validateChains({ sourceChainId, targetChainId });
|
89
|
+
} catch (error) {
|
90
|
+
transaction.sourceErrors = [error.message];
|
91
|
+
transaction.sourceStatus = "failed";
|
92
|
+
transaction.targetStatus = "failed";
|
93
|
+
transaction.status = "failed";
|
94
|
+
await transaction.save();
|
95
|
+
return;
|
96
|
+
}
|
97
|
+
|
98
|
+
const walletBalance = (await this.sourceWallet.getBalance()).toString();
|
99
|
+
const currentGasPrice = (await this.sourceWallet.getGasPrice()).toString()
|
100
|
+
|
101
|
+
const minBalanceRequired = new BigNumber(currentGasPrice)
|
102
|
+
.multipliedBy(4_000_000)
|
103
|
+
.multipliedBy(2) // 2x balance
|
104
|
+
|
105
|
+
if (
|
106
|
+
new BigNumber(walletBalance).isLessThan(minBalanceRequired)
|
107
|
+
) {
|
108
|
+
console.log(
|
109
|
+
dedent`Not enough balance in wallet ${getExplorerUrl(sourceChainId, '/address/' + this.sourceWallet.address)} on ${chainIdToName(sourceChainId)}
|
110
|
+
Balance: ${ethers.utils.parseEther(walletBalance)} ${getChainIdNativeSymbol(sourceChainId)}
|
111
|
+
Required Balance: ${ethers.utils.parseEther(minBalanceRequired.toString())}
|
112
|
+
Require more: ${ethers.utils.parseEther(minBalanceRequired.minus(walletBalance).toString())}`
|
113
|
+
);
|
114
|
+
transaction.sourceDelayUntil = moment().add({ minutes: 5 }).toDate();
|
115
|
+
transaction.sourceStatus = "pending";
|
116
|
+
await transaction.save();
|
117
|
+
return;
|
118
|
+
}
|
119
|
+
|
120
|
+
try {
|
121
|
+
await validateLiquidityCap(position, sourceChainId, targetChainId);
|
122
|
+
} catch (error) {
|
123
|
+
transaction.sourceErrors = [error.message];
|
124
|
+
transaction.sourceStatus = "failed";
|
125
|
+
transaction.targetStatus = "failed";
|
126
|
+
transaction.status = "failed";
|
127
|
+
await transaction.save();
|
128
|
+
return;
|
129
|
+
}
|
78
130
|
|
79
131
|
this.logger.debug(`Build gnosis action for ${transaction.transactionHash}`);
|
80
132
|
|
@@ -105,6 +157,38 @@ class ProcessSubmitSubmitEvents extends BaseTask {
|
|
105
157
|
return;
|
106
158
|
}
|
107
159
|
|
160
|
+
try {
|
161
|
+
await validateSourceLiquidity({
|
162
|
+
position,
|
163
|
+
sourceChainId,
|
164
|
+
sourceDsaId,
|
165
|
+
sourceProvider: this.sourceProvider,
|
166
|
+
});
|
167
|
+
} catch (error) {
|
168
|
+
if (error instanceof UnsupportedChaindIdError) {
|
169
|
+
console.log(`Dropping transaction ${transaction.transactionHash}`);
|
170
|
+
|
171
|
+
transaction.sourceErrors = [error.message];
|
172
|
+
transaction.sourceStatus = "failed";
|
173
|
+
transaction.targetStatus = "failed";
|
174
|
+
transaction.status = "failed";
|
175
|
+
await transaction.save();
|
176
|
+
} else {
|
177
|
+
transaction.sourceStatus = "pending";
|
178
|
+
transaction.sourceErrors = [error.message];
|
179
|
+
transaction.sourceDelayUntil = moment().add({ minutes: 5 }).toDate();
|
180
|
+
await transaction.save();
|
181
|
+
|
182
|
+
console.log("[validateSourceLiquidity][Warning]", error.message);
|
183
|
+
return;
|
184
|
+
}
|
185
|
+
}
|
186
|
+
|
187
|
+
const ownersThreshold = await this.sourceGnosisContract.getThreshold();
|
188
|
+
await wait(10000);
|
189
|
+
|
190
|
+
|
191
|
+
|
108
192
|
this.logger.debug(
|
109
193
|
`Generating gnosis tx for ${transaction.transactionHash}`
|
110
194
|
);
|
@@ -126,20 +210,37 @@ class ProcessSubmitSubmitEvents extends BaseTask {
|
|
126
210
|
this.sourceGnosisContract
|
127
211
|
);
|
128
212
|
|
129
|
-
const owners = await this.sourceGnosisContract
|
130
|
-
.getOwners()
|
131
|
-
.then((owners) => owners.map((owner) => owner.toLowerCase()));
|
132
213
|
|
133
|
-
|
134
|
-
|
135
|
-
|
214
|
+
async function getGnosisOwnerPeerIds({
|
215
|
+
gnosisContract
|
216
|
+
}) {
|
217
|
+
const owners = await gnosisContract
|
218
|
+
.getOwners()
|
219
|
+
.then((owners) => owners.map((owner) => owner.toLowerCase()));
|
220
|
+
|
221
|
+
return peerPool.activePeers
|
222
|
+
.filter((peer) => owners.includes(peer.publicAddress.toLowerCase()))
|
223
|
+
.map((peer) => peer.id);
|
224
|
+
}
|
225
|
+
|
226
|
+
const ownerPeerIds = await getGnosisOwnerPeerIds({
|
227
|
+
gnosisContract: this.sourceGnosisContract,
|
228
|
+
});
|
136
229
|
|
137
230
|
console.log(
|
138
|
-
`Collecting signatures for execution ${transaction.transactionHash}`
|
231
|
+
`Collecting signatures for execution ${transaction.transactionHash} `
|
139
232
|
);
|
140
233
|
|
141
234
|
console.log(ownerPeerIds);
|
142
235
|
|
236
|
+
const message = generateGnosisSignatureMessage({
|
237
|
+
to: addresses[this.chainId].multisend,
|
238
|
+
data,
|
239
|
+
chainId: this.chainId,
|
240
|
+
safeTxGas: gnosisTx.safeTxGas,
|
241
|
+
nonce: gnosisTx.safeNonce,
|
242
|
+
});
|
243
|
+
|
143
244
|
const signatures = await protocol.requestSignatures(
|
144
245
|
{
|
145
246
|
type: "source",
|
@@ -151,9 +252,27 @@ class ProcessSubmitSubmitEvents extends BaseTask {
|
|
151
252
|
ownerPeerIds
|
152
253
|
);
|
153
254
|
|
154
|
-
const validSignatures = signatures
|
155
|
-
(
|
156
|
-
|
255
|
+
const validSignatures = signatures
|
256
|
+
.filter(
|
257
|
+
(s) => !!s.data && s.data !== "0x"
|
258
|
+
)
|
259
|
+
.filter((s) => {
|
260
|
+
|
261
|
+
try {
|
262
|
+
|
263
|
+
const address = getGnosisSignatureAddress({
|
264
|
+
message,
|
265
|
+
signature: s.data!,
|
266
|
+
chainId: this.chainId,
|
267
|
+
})
|
268
|
+
|
269
|
+
return address?.toLowerCase() === s.signer.toLowerCase();
|
270
|
+
|
271
|
+
} catch (error) {
|
272
|
+
return false
|
273
|
+
}
|
274
|
+
|
275
|
+
}) as Signature[];
|
157
276
|
|
158
277
|
console.log({
|
159
278
|
signatures,
|
@@ -172,7 +291,7 @@ class ProcessSubmitSubmitEvents extends BaseTask {
|
|
172
291
|
await transaction.save();
|
173
292
|
const errorMessage = signatures.find((s) => !!s.error)?.error;
|
174
293
|
throw new Error(
|
175
|
-
`Not enough signatures` + (errorMessage ? `: ${errorMessage}` : "")
|
294
|
+
`Not enough signatures` + (errorMessage ? `: ${errorMessage} ` : "")
|
176
295
|
);
|
177
296
|
}
|
178
297
|
|
@@ -220,7 +339,7 @@ class ProcessSubmitSubmitEvents extends BaseTask {
|
|
220
339
|
receipt.logs.forEach((log) => {
|
221
340
|
try {
|
222
341
|
parsedLogs.push(this.sourceGnosisContract.interface.parseLog(log));
|
223
|
-
} catch (e) {}
|
342
|
+
} catch (e) { }
|
224
343
|
});
|
225
344
|
|
226
345
|
if (parsedLogs.find((e) => e.name === "ExecutionSuccess")) {
|
@@ -247,7 +366,7 @@ class ProcessSubmitSubmitEvents extends BaseTask {
|
|
247
366
|
async start(): Promise<void> {
|
248
367
|
this.blockConfirmationsCount = blockConfirmations[this.chainId] + 1;
|
249
368
|
|
250
|
-
this.sourceProvider = new
|
369
|
+
this.sourceProvider = new JsonRpcRetryProvider(
|
251
370
|
getRpcProviderUrl(this.chainId)
|
252
371
|
);
|
253
372
|
|
@@ -265,5 +384,3 @@ class ProcessSubmitSubmitEvents extends BaseTask {
|
|
265
384
|
await super.start();
|
266
385
|
}
|
267
386
|
}
|
268
|
-
|
269
|
-
export default ProcessSubmitSubmitEvents;
|
@@ -5,11 +5,12 @@ import abi from "@/abi";
|
|
5
5
|
import { Transaction } from "@/db";
|
6
6
|
import {
|
7
7
|
buildSignatureBytes,
|
8
|
+
generateGnosisSignatureMessage,
|
8
9
|
generateGnosisTransaction,
|
9
|
-
generateInteropTransactionHash,
|
10
10
|
getContract,
|
11
|
+
getGnosisOwnerPeerIds,
|
12
|
+
getGnosisSignatureAddress,
|
11
13
|
getRpcProviderUrl,
|
12
|
-
LiquidityError,
|
13
14
|
Signature,
|
14
15
|
} from "@/utils";
|
15
16
|
import { addresses, blockConfirmations } from "@/constants";
|
@@ -22,9 +23,11 @@ import { buildGnosisAction } from "@/gnosis";
|
|
22
23
|
import { peerPool, protocol } from "@/net";
|
23
24
|
import { LogDescription } from "ethers/lib/utils";
|
24
25
|
import wait from "waait";
|
26
|
+
import { LiquidityError } from "@/errors";
|
27
|
+
import { JsonRpcRetryProvider } from "@/providers";
|
25
28
|
|
26
|
-
class ProcessValidateEvents extends BaseTask {
|
27
|
-
sourceProvider:
|
29
|
+
export default class ProcessValidateEvents extends BaseTask {
|
30
|
+
sourceProvider: JsonRpcRetryProvider;
|
28
31
|
chainId: ChainId;
|
29
32
|
leadNodeOnly: boolean = true;
|
30
33
|
blockConfirmationsCount: number = 12;
|
@@ -75,7 +78,7 @@ class ProcessValidateEvents extends BaseTask {
|
|
75
78
|
|
76
79
|
const { sourceChainId, targetChainId } = transaction.validateEvent
|
77
80
|
|
78
|
-
const targetProvider = new
|
81
|
+
const targetProvider = new JsonRpcRetryProvider(
|
79
82
|
getRpcProviderUrl(targetChainId as ChainId)
|
80
83
|
);
|
81
84
|
|
@@ -141,13 +144,9 @@ class ProcessValidateEvents extends BaseTask {
|
|
141
144
|
targetGnosisContract
|
142
145
|
);
|
143
146
|
|
144
|
-
const
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
const ownerPeerIds = peerPool.activePeers
|
149
|
-
.filter((peer) => owners.includes(peer.publicAddress.toLowerCase()))
|
150
|
-
.map((peer) => peer.id);
|
147
|
+
const ownerPeerIds = await getGnosisOwnerPeerIds({
|
148
|
+
gnosisContract: targetGnosisContract,
|
149
|
+
});
|
151
150
|
|
152
151
|
console.log(
|
153
152
|
`Collecting signatures for execution ${transaction.transactionHash}`
|
@@ -155,6 +154,14 @@ class ProcessValidateEvents extends BaseTask {
|
|
155
154
|
|
156
155
|
console.log(ownerPeerIds);
|
157
156
|
|
157
|
+
const message = generateGnosisSignatureMessage({
|
158
|
+
to: addresses[targetChainId].multisend,
|
159
|
+
data,
|
160
|
+
chainId: targetChainId as ChainId,
|
161
|
+
safeTxGas: gnosisTx.safeTxGas,
|
162
|
+
nonce: gnosisTx.safeNonce,
|
163
|
+
});
|
164
|
+
|
158
165
|
const signatures = await protocol.requestSignatures(
|
159
166
|
{
|
160
167
|
type: "target",
|
@@ -166,9 +173,27 @@ class ProcessValidateEvents extends BaseTask {
|
|
166
173
|
ownerPeerIds
|
167
174
|
);
|
168
175
|
|
169
|
-
const validSignatures = signatures
|
170
|
-
(
|
171
|
-
|
176
|
+
const validSignatures = signatures
|
177
|
+
.filter(
|
178
|
+
(s) => !!s.data && s.data !== "0x"
|
179
|
+
)
|
180
|
+
.filter((s) => {
|
181
|
+
|
182
|
+
try {
|
183
|
+
|
184
|
+
const address = getGnosisSignatureAddress({
|
185
|
+
message,
|
186
|
+
signature: s.data!,
|
187
|
+
chainId: targetChainId as ChainId,
|
188
|
+
})
|
189
|
+
|
190
|
+
return address?.toLowerCase() === s.signer.toLowerCase();
|
191
|
+
|
192
|
+
} catch (error) {
|
193
|
+
return false
|
194
|
+
}
|
195
|
+
|
196
|
+
}) as Signature[];
|
172
197
|
|
173
198
|
console.log({
|
174
199
|
signatures,
|
@@ -263,12 +288,10 @@ class ProcessValidateEvents extends BaseTask {
|
|
263
288
|
async start(): Promise<void> {
|
264
289
|
this.blockConfirmationsCount = blockConfirmations[this.chainId] + 1;
|
265
290
|
|
266
|
-
this.sourceProvider = new
|
291
|
+
this.sourceProvider = new JsonRpcRetryProvider(
|
267
292
|
getRpcProviderUrl(this.chainId)
|
268
293
|
);
|
269
294
|
|
270
295
|
await super.start();
|
271
296
|
}
|
272
|
-
}
|
273
|
-
|
274
|
-
export default ProcessValidateEvents;
|
297
|
+
}
|
@@ -0,0 +1,161 @@
|
|
1
|
+
import { BaseTask } from "../BaseTask";
|
2
|
+
import Logger from "@/logger";
|
3
|
+
import { ethers } from "ethers";
|
4
|
+
import abi from "@/abi";
|
5
|
+
import { Transaction } from "@/db";
|
6
|
+
import {
|
7
|
+
generateInteropTransactionHash,
|
8
|
+
getContract,
|
9
|
+
getRpcProviderUrl,
|
10
|
+
} from "@/utils";
|
11
|
+
import { addresses } from "@/constants";
|
12
|
+
import { ChainId } from "@/types";
|
13
|
+
import config from "@/config";
|
14
|
+
import { InteropX } from "@/typechain";
|
15
|
+
import { Op } from "sequelize";
|
16
|
+
import { JsonRpcRetryProvider } from "@/providers";
|
17
|
+
|
18
|
+
export default class SyncLogExecuteEvents extends BaseTask {
|
19
|
+
contractAddress: string;
|
20
|
+
provider: JsonRpcRetryProvider;
|
21
|
+
contract: InteropX;
|
22
|
+
targetChainId: ChainId;
|
23
|
+
|
24
|
+
constructor({ targetChainId }: { targetChainId: ChainId }) {
|
25
|
+
super({
|
26
|
+
logger: new Logger("InteropX::SyncLogExecuteEvents"),
|
27
|
+
});
|
28
|
+
this.targetChainId = targetChainId;
|
29
|
+
}
|
30
|
+
|
31
|
+
async pollHandler() {
|
32
|
+
const currentBlock = await this.provider.getBlockNumber();
|
33
|
+
|
34
|
+
const events = await this.contract.queryFilter(
|
35
|
+
this.contract.filters.LogExecute(),
|
36
|
+
currentBlock - 2000,
|
37
|
+
currentBlock
|
38
|
+
);
|
39
|
+
|
40
|
+
let processedEvents = 0;
|
41
|
+
|
42
|
+
for (const event of events) {
|
43
|
+
try {
|
44
|
+
if (!event.args) {
|
45
|
+
continue;
|
46
|
+
}
|
47
|
+
|
48
|
+
const {
|
49
|
+
sourceSpells,
|
50
|
+
targetSpells,
|
51
|
+
position,
|
52
|
+
actionId,
|
53
|
+
actionIdHash,
|
54
|
+
sourceSender,
|
55
|
+
sourceDsaId,
|
56
|
+
targetDsaId,
|
57
|
+
sourceChainId,
|
58
|
+
targetChainId,
|
59
|
+
vnonce,
|
60
|
+
metadata,
|
61
|
+
} = event.args;
|
62
|
+
|
63
|
+
const uniqueIdentifier = {
|
64
|
+
actionId,
|
65
|
+
vnonce: vnonce.toString(),
|
66
|
+
sourceSender: sourceSender.toString(),
|
67
|
+
sourceChainId: sourceChainId.toNumber(),
|
68
|
+
targetChainId: targetChainId.toNumber(),
|
69
|
+
sourceDsaId: sourceDsaId.toString(),
|
70
|
+
targetDsaId: targetDsaId.toString(),
|
71
|
+
};
|
72
|
+
|
73
|
+
let transactionHash = generateInteropTransactionHash(uniqueIdentifier);
|
74
|
+
|
75
|
+
const transaction = await Transaction.findOne({
|
76
|
+
where: {
|
77
|
+
transactionHash,
|
78
|
+
executeEvent: { [Op.eq]: null },
|
79
|
+
},
|
80
|
+
});
|
81
|
+
|
82
|
+
if (!transaction) {
|
83
|
+
continue;
|
84
|
+
}
|
85
|
+
|
86
|
+
if (transaction.targetStatus != "success") {
|
87
|
+
transaction.targetStatus = "success";
|
88
|
+
}
|
89
|
+
|
90
|
+
if (transaction.status != "success") {
|
91
|
+
transaction.status = "success";
|
92
|
+
}
|
93
|
+
|
94
|
+
if (!transaction.targetCreatedAt) {
|
95
|
+
transaction.targetCreatedAt = new Date();
|
96
|
+
}
|
97
|
+
|
98
|
+
transaction.targetTransactionHash = event.transactionHash;
|
99
|
+
transaction.targetBlockNumber = event.blockNumber;
|
100
|
+
transaction.targetLogs = [];
|
101
|
+
transaction.executeEvent = {
|
102
|
+
actionId,
|
103
|
+
actionIdHashHash: actionIdHash,
|
104
|
+
actionIdHash,
|
105
|
+
vnonce: vnonce.toString(),
|
106
|
+
sourceSpells: sourceSpells.map(({ connector, data }) => ({
|
107
|
+
connector,
|
108
|
+
data,
|
109
|
+
})),
|
110
|
+
targetSpells: targetSpells.map(({ connector, data }) => ({
|
111
|
+
connector,
|
112
|
+
data,
|
113
|
+
})),
|
114
|
+
position: {
|
115
|
+
withdraw: position.withdraw.map((v) => ({
|
116
|
+
sourceToken: v.sourceToken,
|
117
|
+
targetToken: v.targetToken,
|
118
|
+
amount: v.amount.toString(),
|
119
|
+
})),
|
120
|
+
supply: position.supply.map((v) => ({
|
121
|
+
sourceToken: v.sourceToken,
|
122
|
+
targetToken: v.targetToken,
|
123
|
+
amount: v.amount.toString(),
|
124
|
+
})),
|
125
|
+
},
|
126
|
+
sourceChainId: sourceChainId.toNumber(),
|
127
|
+
targetChainId: targetChainId.toNumber(),
|
128
|
+
sourceSender,
|
129
|
+
sourceDsaId: sourceDsaId.toString(),
|
130
|
+
targetDsaId: targetDsaId.toString(),
|
131
|
+
metadata,
|
132
|
+
};
|
133
|
+
|
134
|
+
await transaction.save();
|
135
|
+
|
136
|
+
this.logger.info(`New InteropX transaction: ${transactionHash} `);
|
137
|
+
} catch (error) {
|
138
|
+
this.logger.error(error);
|
139
|
+
}
|
140
|
+
}
|
141
|
+
|
142
|
+
if (processedEvents > 0)
|
143
|
+
this.logger.info(`${processedEvents} events processed`);
|
144
|
+
}
|
145
|
+
|
146
|
+
async start(): Promise<void> {
|
147
|
+
this.contractAddress = addresses[this.targetChainId].interopX;
|
148
|
+
|
149
|
+
this.provider = new JsonRpcRetryProvider(
|
150
|
+
getRpcProviderUrl(this.targetChainId)
|
151
|
+
);
|
152
|
+
|
153
|
+
this.contract = getContract<InteropX>(
|
154
|
+
this.contractAddress,
|
155
|
+
abi.interopX,
|
156
|
+
new ethers.Wallet(config.privateKey!, this.provider)
|
157
|
+
);
|
158
|
+
|
159
|
+
await super.start();
|
160
|
+
}
|
161
|
+
}
|
@@ -12,10 +12,11 @@ import { addresses } from "@/constants";
|
|
12
12
|
import { ChainId } from "@/types";
|
13
13
|
import config from "@/config";
|
14
14
|
import { InteropX } from "@/typechain";
|
15
|
+
import { JsonRpcRetryProvider } from "@/providers";
|
15
16
|
|
16
|
-
class SyncLogSubmitEvents extends BaseTask {
|
17
|
+
export default class SyncLogSubmitEvents extends BaseTask {
|
17
18
|
contractAddress: string;
|
18
|
-
provider:
|
19
|
+
provider: JsonRpcRetryProvider;
|
19
20
|
contract: InteropX;
|
20
21
|
chainId: ChainId;
|
21
22
|
|
@@ -109,7 +110,7 @@ class SyncLogSubmitEvents extends BaseTask {
|
|
109
110
|
},
|
110
111
|
});
|
111
112
|
|
112
|
-
this.logger.info(`New InteropX
|
113
|
+
this.logger.info(`New InteropX transaction: ${transactionHash} `);
|
113
114
|
} catch (error) {
|
114
115
|
this.logger.error(error);
|
115
116
|
}
|
@@ -122,7 +123,7 @@ class SyncLogSubmitEvents extends BaseTask {
|
|
122
123
|
async start(): Promise<void> {
|
123
124
|
this.contractAddress = addresses[this.chainId].interopX;
|
124
125
|
|
125
|
-
this.provider = new
|
126
|
+
this.provider = new JsonRpcRetryProvider(
|
126
127
|
getRpcProviderUrl(this.chainId)
|
127
128
|
);
|
128
129
|
|
@@ -134,6 +135,4 @@ class SyncLogSubmitEvents extends BaseTask {
|
|
134
135
|
|
135
136
|
await super.start();
|
136
137
|
}
|
137
|
-
}
|
138
|
-
|
139
|
-
export default SyncLogSubmitEvents;
|
138
|
+
}
|