Error: call revert exception (Flashloan with dydx, Uniswap and Kyber) - javascript

So I am trying to set up an Ethereum flashloan script on the Kovan test network, partly because of the great amount of funds needed to execute it on Mainnet.
I have therefore found all the Kovan addresses of the services used (dydx, kyber, the tokens to be exchanged etc.) and made a new key called ‘kovan’ with those addresses within the ‘addresses’ folder.
I then finally succeeded in deploying the contract on Kovan. And the websocket interaction of getting and displaying the blocks also works.
I expect it to be error-free while waiting for a transaction to go through. But every time it receives a new block, it gives me an error saying:
UnhandledPromiseRejectionWarning: Error: call revert exception (method="decimals()", errorSignature=null, errorArgs=[null], reason=null, code=CALL_EXCEPTION, version=abi/5.0.1)
This is the whole console log:
λ node run-arbitrage.js
{
kyber: { kyberNetworkProxy: '0x692f391bCc85cefCe8C237C01e1f636BbD70EA4D' },
uniswap: { router: '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D' },
dydx: { solo: '0x4EC3570cADaAEE08Ae384779B0f3A45EF85289DE' },
tokens: {
dai: '0xc4375b7de8af5a38a93548eb8453a498222c4ff2',
usdc: '0xdcfab8057d08634279f8201b55d311c2a67897d2',
weth: '0xd0a1e359811322d97991e03f863a0c30c2cf029c'
}
}
web3-shh package will be deprecated in version 1.3.5 and will no longer be supported.
web3-bzz package will be deprecated in version 1.3.5 and will no longer be supported.
New block received. Block # 24267204
(node:20188) UnhandledPromiseRejectionWarning: Error: call revert exception (method="decimals()", errorSignature=null, errorArgs=[null], reason=null, code=CALL_EXCEPTION, version=abi/5.0.1)
at Logger.makeError (C:\Users\Frederik\Rod\m3\node_modules\#ethersproject\logger\lib\index.js:179:21)
at Logger.throwError (C:\Users\Frederik\Rod\m3\node_modules\#ethersproject\logger\lib\index.js:188:20)
at Interface.decodeFunctionResult (C:\Users\Frederik\Rod\m3\node_modules\#ethersproject\contracts\node_modules\#ethersproject\abi\lib\interface.js:286:23)
at Contract.<anonymous> (C:\Users\Frederik\Rod\m3\node_modules\#ethersproject\contracts\lib\index.js:300:56)
at step (C:\Users\Frederik\Rod\m3\node_modules\#ethersproject\contracts\lib\index.js:46:23)
at Object.next (C:\Users\Frederik\Rod\m3\node_modules\#ethersproject\contracts\lib\index.js:27:53)
at fulfilled (C:\Users\Frederik\Rod\m3\node_modules\#ethersproject\contracts\lib\index.js:18:58)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
(node:20188) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:20188) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
And this is my run-arbitrage.js file:
require("dotenv").config()
const Web3 = require('web3');
const { ChainId, Token, TokenAmount, Pair } = require('#uniswap/sdk');
const abis = require('./abis');
const { kovan: addresses } = require('./addresses');
console.log(addresses)
const Flashloan = require('./build/contracts/Flashloan.json');
const web3 = new Web3(
new Web3.providers.WebsocketProvider(process.env.INFURA_KOVAN_URL)
);
const { address: admin } = web3.eth.accounts.wallet.add(process.env.PRIVATE_KEY);
const kyber = new web3.eth.Contract(
abis.kyber.kyberNetworkProxy,
addresses.kyber.kyberNetworkProxy
);
const ONE_WEI = web3.utils.toBN(web3.utils.toWei('1'));
const AMOUNT_DAI_WEI = web3.utils.toBN(web3.utils.toWei('20000'));
const DIRECTION = {
KYBER_TO_UNISWAP: 0,
UNISWAP_TO_KYBER: 1
};
const init = async () => {
const networkId = await web3.eth.net.getId();
const flashloan = new web3.eth.Contract(
Flashloan.abi,
Flashloan.networks[networkId].address
);
let ethPrice;
const updateEthPrice = async () => {
const results = await kyber
.methods
.getExpectedRate(
'0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee',
addresses.tokens.dai,
1
)
.call();
ethPrice = web3.utils.toBN('1').mul(web3.utils.toBN(results.expectedRate)).div(ONE_WEI);
}
await updateEthPrice();
setInterval(updateEthPrice, 15000);
web3.eth.subscribe('newBlockHeaders')
.on('data', async block => {
console.log(`New block received. Block # ${block.number}`);
const [dai, weth] = await Promise.all(
[addresses.tokens.dai, addresses.tokens.weth].map(tokenAddress => (
Token.fetchData(
ChainId.MAINNET,
tokenAddress,
)
)));
const daiWeth = await Pair.fetchData(
dai,
weth,
);
const amountsEth = await Promise.all([
kyber
.methods
.getExpectedRate(
addresses.tokens.dai,
'0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee',
AMOUNT_DAI_WEI
)
.call(),
daiWeth.getOutputAmount(new TokenAmount(dai, AMOUNT_DAI_WEI)),
]);
const ethFromKyber = AMOUNT_DAI_WEI.mul(web3.utils.toBN(amountsEth[0].expectedRate)).div(ONE_WEI);
const ethFromUniswap = web3.utils.toBN(amountsEth[1][0].raw.toString());
const amountsDai = await Promise.all([
kyber
.methods
.getExpectedRate(
'0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee',
addresses.tokens.dai,
ethFromUniswap.toString()
)
.call(),
daiWeth.getOutputAmount(new TokenAmount(weth, ethFromKyber.toString())),
]);
const daiFromKyber = ethFromUniswap.mul(web3.utils.toBN(amountsDai[0].expectedRate)).div(ONE_WEI);
const daiFromUniswap = web3.utils.toBN(amountsDai[1][0].raw.toString());
console.log(`Kyber -> Uniswap. Dai input / output: ${web3.utils.fromWei(AMOUNT_DAI_WEI.toString())} / ${web3.utils.fromWei(daiFromUniswap.toString())}`);
console.log(`Uniswap -> Kyber. Dai input / output: ${web3.utils.fromWei(AMOUNT_DAI_WEI.toString())} / ${web3.utils.fromWei(daiFromKyber.toString())}`);
if(daiFromUniswap.gt(AMOUNT_DAI_WEI)) {
const tx = flashloan.methods.initiateFlashloan(
addresses.dydx.solo,
addresses.tokens.dai,
AMOUNT_DAI_WEI,
DIRECTION.KYBER_TO_UNISWAP
);
const [gasPrice, gasCost] = await Promise.all([
web3.eth.getGasPrice(),
tx.estimateGas({from: admin}),
]);
const txCost = web3.utils.toBN(gasCost).mul(web3.utils.toBN(gasPrice)).mul(ethPrice);
const profit = daiFromUniswap.sub(AMOUNT_DAI_WEI).sub(txCost);
if(profit > 0) {
console.log('Arb opportunity found Kyber -> Uniswap!');
console.log(`Expected profit: ${web3.utils.fromWei(profit)} Dai`);
const data = tx.encodeABI();
const txData = {
from: admin,
to: flashloan.options.address,
data,
gas: gasCost,
gasPrice
};
const receipt = await web3.eth.sendTransaction(txData);
console.log(`Transaction hash: ${receipt.transactionHash}`);
}
}
if(daiFromKyber.gt(AMOUNT_DAI_WEI)) {
const tx = flashloan.methods.initiateFlashloan(
addresses.dydx.solo,
addresses.tokens.dai,
AMOUNT_DAI_WEI,
DIRECTION.UNISWAP_TO_KYBER
);
const [gasPrice, gasCost] = await Promise.all([
web3.eth.getGasPrice(),
tx.estimateGas({from: admin}),
]);
const txCost = web3.utils.toBN(gasCost).mul(web3.utils.toBN(gasPrice)).mul(ethPrice);
const profit = daiFromKyber.sub(AMOUNT_DAI_WEI).sub(txCost);
if(profit > 0) {
console.log('Arb opportunity found Uniswap -> Kyber!');
console.log(`Expected profit: ${web3.utils.fromWei(profit)} Dai`);
const data = tx.encodeABI();
const txData = {
from: admin,
to: flashloan.options.address,
data,
gas: gasCost,
gasPrice
};
const receipt = await web3.eth.sendTransaction(txData);
console.log(`Transaction hash: ${receipt.transactionHash}`);
}
}
})
.on('error', error => {
console.log(error);
});
}
init();

Related

Firebase: Cloud function changing data in firestore - Permission denied on resource project [X:YYYYYYYYYY:web:KKKKKKKKKKKK]

I am trying to add data to my firestore collection via firebase cloud functions. However, when executing the function the following error appears.
My cloud function code is:
import * as functions from "firebase-functions";
import * as admin from "firebase-admin";
admin.initializeApp();
const Firestore = require("#google-cloud/firestore");
const PROJECTID = "[...]";
const firestore = new Firestore({
projectId: PROJECTID,
timestampsInSnapshots: true,
});
exports.createNewChat = functions.region("europe-west1")
.https.onRequest((request, response) => {
console.log("!!!!!!");
console.log("THe BodY: " + request);
console.log("THe BodY: " + request.rawBody);
console.log("THe BodY: " + request.body);
try {
const groupName = request.body.groupName;
const members: string[] = request.body.members;
firestore.collection("chats").add({
groupName: groupName,
members: members,
lastMessage: new Date(),
messages: [],
}).then((doc: any) => {
const chatId = doc.id;
members.forEach((member) => {
firestore.collection("myChats/" + member).add({
chatKey: chatId,
});
});
return response.status(200).send(doc);
});
} catch (e) {
functions.logger.log("catch clause " + e);
response.status(500).send(e);
}
});
My postman request looks like this:
Header: Content-Type -> application/json
Body (raw, json):
{
"groupName": "someGroupName",
"members": [
"123321aklslasl"
]
}
The exception which is thrown is:
! Google API requested!
URL: "https://oauth2.googleapis.com/token"
Be careful, this may be a production service.
(node:23224) UnhandledPromiseRejectionWarning: Error: 7 PERMISSION_DENIED: Permission denied on resource project [...].
at Object.callErrorFromStatus (E:\Workspaces\cloudFunctions\functions\node_modules#grpc\grpc-js\build\src\call.js:31:26)
at Object.onReceiveStatus (E:\Workspaces\cloudFunctions\functions\node_modules#grpc\grpc-js\build\src\client.js:179:52)
at Object.onReceiveStatus (E:\Workspaces\cloudFunctions\functions\node_modules#grpc\grpc-js\build\src\client-interceptors.js:336:141)
at Object.onReceiveStatus (E:\Workspaces\cloudFunctions\functions\node_modules#grpc\grpc-js\build\src\client-interceptors.js:299:181)
at E:\Workspaces\cloudFunctions\functions\node_modules#grpc\grpc-js\build\src\call-stream.js:145:78
at processTicksAndRejections (internal/process/task_queues.js:79:11)
Caused by: Error
at WriteBatch.commit (E:\Workspaces\cloudFunctions\functions\node_modules#google-cloud\firestore\build\src\write-batch.js:414:23)
at DocumentReference.create (E:\Workspaces\cloudFunctions\functions\node_modules#google-cloud\firestore\build\src\reference.js:291:14)
at CollectionReference.add (E:\Workspaces\cloudFunctions\functions\node_modules#google-cloud\firestore\build\src\reference.js:1967:28)
at E:\Workspaces\cloudFunctions\functions\lib\index.js:39:39
at C:\Users\XXXXX\AppData\Roaming\npm\node_modules\firebase-tools\lib\emulator\functionsEmulatorRuntime.js:560:16
at runFunction (C:\Users\XXXXX\AppData\Roaming\npm\node_modules\firebase-tools\lib\emulator\functionsEmulatorRuntime.js:533:15)
at runHTTPS (C:\Users\XXXXX\AppData\Roaming\npm\node_modules\firebase-tools\lib\emulator\functionsEmulatorRuntime.js:559:11)
at handler (C:\Users\XXXXX\AppData\Roaming\npm\node_modules\firebase-tools\lib\emulator\functionsEmulatorRuntime.js:479:23)
at Layer.handle [as handle_request] (C:\Users\XXXXX\AppData\Roaming\npm\node_modules\firebase-tools\node_modules\express\lib\router\layer.js:95:5)
at next (C:\Users\XXXXX\AppData\Roaming\npm\node_modules\firebase-tools\node_modules\express\lib\router\route.js:137:13)
(node:23224) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). T
o terminate the node process on unhandled promise rejection, use the CLI flag --unhandled-rejections=strict (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 3)
(node:23224) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
In a Cloud Function for Firebase you should use the Admin SDK for Node.js and not the standard JS SDK.
In addition, you need to use Promise.all() to execute in parallel the calls to the asynchronous add() method in the forEach() loop.
So the following set of adaptations should solve your problem:
import * as functions from "firebase-functions";
import * as admin from "firebase-admin";
admin.initializeApp();
exports.createNewChat = functions.region("europe-west1")
.https.onRequest((request, response) => {
const groupName = request.body.groupName;
const members: string[] = request.body.members;
const db = admin.firestore();
db.collection("chats").add({
groupName: groupName,
members: members,
lastMessage: new Date(),
messages: [],
}).then((doc: any) => {
const chatId = doc.id;
const promises = [];
members.forEach((member) => {
promises.push(db.collection("myChats/" + member).add({
chatKey: chatId,
}));
});
return Promise.all(promises);
})
.then(() => {
response.status(200).send(JSON.stringify(doc));
})
.catch(e => {
functions.logger.log("catch clause " + e);
response.status(500).send(JSON.stringify(e));
});
});

SSH2 issues wiht Node.js

I got this code that it seems to be working but it does not.
let REMOTE_SSH_HOST = '190.444.01.75:55554'
let REMOTE_SSH_USERNAME = 'olec'
let REMOTE_SSH_PASSWORD = 'm3uW4jkbaEwVChklFszpbm4'
const Client = require('ssh2-sftp-client');
const sshConfig = {
host: process.env.REMOTE_SSH_HOST,
//port: 22,
username: process.env.REMOTE_SSH_USERNAME,
password: process.env.REMOTE_SSH_PASSWORD,
readyTimeout: 99999,
};
let sftp = new Client();
async function Read(directory) {
console.log('Read(' + directory + ')');
const result = await sftp.list(directory);
for(const sub of result) {
if (sub['type'] === 'd') {
await Read(directory + '/ ' + sub['name']);
}
}
}
async function main(directory) {
try{
const myList = await sftp.list(directory);
}catch(err){console.log(err)}//NEVER forget to catch
finally {
console.log('Closing session...');
await sftp.end();
console.log('Session closed.');
}
}
console.log('Application started');
main('/home/user/path').then(r => {
console.log('Application ended.');
});
I get the error message of:
(Use node --trace-warnings ... to show where the warning was created)
(node:16240) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag --unhandled-rejections=strict (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 5)
(node:16240) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled
will terminate the Node.js process with a non-zero exit code.
I think you might need something like
const sftp = new Client();
await sftp.connect({
host: hostAddress,
username: '...',
privateKey: ...,
});
The issue is you are using environment variables where you have set consts. (also you are setting consts as lets... don't ever use a let where something will never change.
const Client = require('ssh2-sftp-client');
const REMOTE_SSH_HOST = '190.444.01.75'
const REMOTE_SSH_PORT = '55554';
const REMOTE_SSH_USERNAME = 'olec'
const REMOTE_SSH_PASSWORD = 'm3uW4jkbaEwVChklFszpbm4'
const sshConfig = {
host: REMOTE_SSH_HOST,
port: REMOTE_SSH_PORT,
username: REMOTE_SSH_USERNAME,
password: REMOTE_SSH_PASSWORD,
readyTimeout: 99999,
};
Thnx gonna try this and get back to you!
There are a series of errors on your script that are causing the issue. The main one is that you are not handling errors in your async code. You should add a catch chain function to your main call because, even though you are using a try/catch clause inside your main function, it doesn't consider the code that runs inside the finally block.
On the other hand, your code seems to be failing because you are running sftp.list before running sftp.connect.
There are a couple of minor errors that could potentially cause problems in your script:
The address 190.444.01.75 is not a valid IPv4 address.
You should provide default values when reading env variables where they make sense.
You are not really using the Read function yet, but I would suggest you name functions in lower case.
You are declaring the variable of the for-of loop inside the Read function with const. It would be best to use let instead since the engine will update it on each iteration.
Here is a modified example of your script that works:
const Client = require('ssh2-sftp-client')
/**
* Global variables
*/
const SSH_CONFIG = {
host : process.env.REMOTE_SSH_HOST || '190.44.1.75:55554',
port : process.env.REMOTE_SSH_PORT || 22,
username : process.env.REMOTE_SSH_USERNAME || 'olec',
password : process.env.REMOTE_SSH_PASSWORD,
readyTimeout: 99999,
}
const ROOT = process.env.ROOT || '/home/user/path'
/**
* Constructors
*/
const sftp = new Client()
/**
* Main
*/
console.log("Application Started!")
main(ROOT)
.then ((response) => console.log(response))
.catch((err) => console.error(err))
/**
* Functions
*/
async function main(directory) {
let myList
try {
await sftp.connect(SSH_CONFIG)
return await sftp.list(directory)
} catch(err) {
console.error(err)
} finally {
console.log('Closing session...')
await sftp.end()
console.log('Session closed.')
}
}
And here is how you would call it:
env REMOTE_SSH_HOST=10.0.0.10 \
env REMOTE_SSH_USERNAME=conatel \
env REMOTE_SSH_PASSWORD=C0n4t3lC0n4t3l \
env REMOTE_SSH_PORT=22 \
env ROOT=/home/conatel \
node ssh.js

Error: concatUint8Array: Data must be in the form of a Uint8Array

I am using Jest to test a small function of mine that makes use of OpenPGP.js https://openpgpjs.org/ (the latest version, 4.10.9).
I saw some workarounds using the library text-encoding-utf-8 and I did this on my tests, but unfortunately, the error persists.
Even with:
const textEncoding = await import("text-encoding-utf-8")
global.TextEncoder = textEncoding.TextEncoder
global.TextDecoder = textEncoding.TextDecoder
My function:
import * as openpgp from "openpgp"
export async function decryptMessage(privateKeyArmored, passphrase, message) {
const {
keys: [privateKey],
} = await openpgp.key.readArmored(privateKeyArmored)
await privateKey.decrypt(passphrase)
const { data } = await openpgp.decrypt({
message: await openpgp.message.readArmored(message),
privateKeys: [privateKey],
})
return data
}
And this is my test
import * as openpgp from "openpgp"
import { decryptMessage } from "../src/crypto"
let privateKey
let publicKey
const passphrase = "password"
const oldTextEncoder = global.TextEncoder
const oldTextDecoder = global.TextDecoder
describe("crypto test suite", () => {
beforeAll(async () => {
// workaround to openpgp works with jest
const textEncoding = await import("text-encoding-utf-8")
global.TextEncoder = textEncoding.TextEncoder
global.TextDecoder = textEncoding.TextDecoder
const { privateKeyArmored, publicKeyArmored } = await openpgp.generateKey({
userIds: [{ name: "username" }],
curve: "ed25519",
passphrase,
})
privateKey = privateKeyArmored
publicKey = publicKeyArmored
})
afterAll(() => {
global.TextEncoder = oldTextEncoder
global.TextDecoder = oldTextDecoder
})
test("decrypt message", async () => {
const text = "test"
const { data } = await openpgp.encrypt({
message: openpgp.message.fromText(text),
publicKeys: (await openpgp.key.readArmored(publicKey)).keys,
})
const result = decryptMessage(privateKey, passphrase, data)
expect(result).toBe(text)
})
})
When I run, I got:
(node:10804) UnhandledPromiseRejectionWarning: Error: concatUint8Array: Data must be in the form of a Uint8Array
(node:10804) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 25)
Any clues?
I was getting the same issue and then I had to use a specific openpgp version. This is what ended up working for me:
"openpgp": "4.10.10",
"text-encoding-utf-8": "^1.0.2",
So, I had to use the proper functions inherent to this openpgp version as follows:
test('Encrypts a file using the GPG file', async () => {
const textEncoding = await import("text-encoding-utf-8")
global.TextEncoder = textEncoding.TextEncoder
global.TextDecoder = textEncoding.TextDecoder
const publicKey = fs.readFileSync('/path/file.asc')
const input = fs.createReadStream('a.txt')
const encrypted = await openpgp.encrypt({
message: await openpgp.message.fromBinary(input),
publicKeys: (await openpgp.key.readArmored(publicKey)).keys,
})
console.log(encrypted)
Let me know if it works for you

How to fix Timeout exceeded error for async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves

I am trying to deploy a simple contract using mocha and ganache, but I got this error:
Acontract
1) "before each" hook for "Deploys a Contract"
0 passing (30s)
1 failing
1) "before each" hook for "Deploys a Contract":
Error: Timeout of 30000ms exceeded. For async tests and hooks, ensure
"done()" is called; if returning a Promise, ensure it resolves.
The contract code :
pragma solidity ^0.4.17;
contract Acontract {
string public message; // new variable
function Acontract(string initialMessage) public {
message = initialMessage;
}
function setMessage(string newMessage) public {
message = newMessage;
}
}
The test file code:
const assert = require('assert');
const ganache = require('ganache-cli');
const Web3 = require('web3');
const web3 = new Web3(ganache.provider());
const { interface, bytecode} = require('../compile');
let accounts;
let result;
beforeEach( async () => {
accounts = await web3.eth.getAccounts();
result = await new web3.eth.Contract(JSON.parse(interface))
.deploy ({ data: bytecode, arguments: ['WOW'] })
.send({ from: accounts[0], gas: '1000000'});
});
describe('Acontract', ()=> {
it('Deploys a Contract', async ()=>{
console.log(result)
});
});
How to solve this error, the code is simple, I tested getting accounts and it was ok, also deploy seems ok, when it comes to sending the code does not work! any suggestions?
I ran into a similar issue and fixed it like this: (You may try number 2 first).
Installed web3#1.0.0-beta.37 (Note: your dependencies can be very different from mine as you are using solidity ^0.4.17)
Added ganache provider in the code.
const assert = require('assert');
const ganache = require('ganache-cli');
const Web3 = require('web3');
//Ganache Provider
const provider = ganache.provider();
const web3 = new Web3(provider);
const { interface, bytecode} = require('../compile');
let accounts;
let result;
beforeEach( async () => {
accounts = await web3.eth.getAccounts();
result = await new web3.eth.Contract(JSON.parse(interface))
.deploy ({ data: bytecode, arguments: ['WOW'] })
.send({ from: accounts[0], gas: '1000000'});
//Set provider
result.setProvider(provider);
});
describe('Acontract', ()=> {
it('Deploys a Contract', async ()=>{
console.log(result)
});
});
"Contract" object structure is changed a bit in this version. So, I had to update compile.js export a bit as well (You may not need it with your version of solidity compiler).

NodeJS Forever's restarting function is not working when app gets an error

I develop parsing app with NodeJS and Puppeteer. It works well but sometimes web page is not loaded so it gives me an error. So I fix my code and I only need to restart the app when the error comes.
I found that forever can restart the app when it has an error. So I start my app with this command
forever start -o out.log -e err.log band.js
But even If app got some error it didn't start it again. Just it stops and do nothing.
[ERROR Message]
(node:11032) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'replace' of null
at C:\Users\Downloads\Projects\Bander-Statistics\band.js:67:47
at process._tickCallback (internal/process/next_tick.js:68:7)
(node:11032) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:11032) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
[band.js]
'use strict';
const fs = require('fs');
let article = fs.readFileSync("db.txt");
let lineArray = article.toString().split('\n')[0];
/* Initial Setting */
const initData = {
chromePath: 'C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe',
userDataDir: 'C:\\Users\\AppData\\Local\\Google\\Chrome\\User Data',
bandNum: 58075840, // Parse Band Number
startNum: lineArray, // This variable will be read in db.txt first line
untilNum: 90000 // Parse Until What Number
}
const puppeteer = require('puppeteer'); // Puppeteer 모듈 Load
(async () => {
const browser = await puppeteer.launch({ // Puppeteer 모듈을 사용하지 않고 기존의 크롬 사용자 정보를 사용 (Auth 인증을 패스하기 위하여)
executablePath: initData.chromePath,
userDataDir: initData.userDataDir, // 설치시 개인 크롬 Directory로 수정하여야함
headless: true
});
const page = await browser.newPage(); // Broswer Open
await page.setViewport({ // Viewport 설정 가로의 경우 일반적으로 최대 1920, 새로의 경우 예상되는 최대 px를 지정해주면됨
width: 800,
height: 6000
});
page.on('dialog', async dialog => { // 삭제된 게시글의 경우 Band에서 Dialog를 띄우는데 이를 제거하기 위하여 필요
console.log(dialog.message());
await dialog.dismiss(); // Dialog 창 닫음
await postNumber++; // 삭제된 게시글의 경우 Dialog 창이 닫힌후에 이전 URL로 돌아가므로 postNumber 1증가 시켜줌
await page.goto(`https://band.us/band/${initData.bandNum}/post/${postNumber}`, {
waitUntil: 'networkidle0'
});
})
let postNumber = initData.startNum; // 시작되는 PostNumber * 이 부분 부터 시작 *
while (postNumber <= initData.untilNum) { // PostNumber 끝값 * 이 부분은 마지막 값 *
await page.goto(`https://band.us/band/${initData.bandNum}/post/${postNumber}`, {
waitUntil: 'networkidle0' // 페이지가 완전히 Load된후 작동
});
let [by, date] = await page.evaluate(() => {
const textNode = document.getElementsByClassName('text')[0];
const timeNode = document.getElementsByClassName('time')[0];
return [
textNode && textNode.innerText,
timeNode && timeNode.innerText,
];
});
if (!by || !date) {
// by or date is undefined
console.log(`Not working for ID: ${postNumber}`);
await page.reload()
postNumber++;
console.log('ERROR!')
// await element.screenshot({ path: `error-${postNumber}.png` });
await page.goto(`https://band.us/band/${initData.bandNum}/post/${postNumber}`, {
waitUntil: 'networkidle0'
});
}
let element = await page.$('.boardList'); // 게시글, 댓글 전체 Class
await element.screenshot({ // ScreenShot Function
path: `./image/${postNumber}-${by.replace("/","_")}-${date.replace(":","_")}.png` // 파일 저장 위치 & 파일이름 지정, replace 메소드의 경우 Windows 탐색기에서 :를 파일명으로 지원하지 않기때문
});
console.log(`${postNumber}-${by.replace("/","_")}-${date.replace(":","_")}.png`) // Console.log에서 파일 확인
let lastTriedNum = postNumber;
fs.writeFileSync("db.txt", '\ufeff' + lastTriedNum + '\n', {
encoding: 'utf8'
});
await postNumber++; // 최종 성공시 postnumber 증가
}
await browser.close(); // 종료
})();
I already tried Supervisor, PM2, Forever but non of them provide the function I wanted.
I just need the ability to restart the whole app if an error occurs.

Categories

Resources