Save console.log output into a file - javascript

I have a JavaScript code that is printing a few statements that I would like to save in a file, which I will parse with a Python code.
I have saw multiple solutions, but I am having a hard time to modifying my code to save the console.log output.
Here is my JavaScript code:
import { JSBI } from "#uniswap/sdk";
import { ethers } from 'ethers';
import * as fs from 'fs';
// ERC20 json abi file
let ERC20Abi = fs.readFileSync('ERC20.json');
const ERC20 = JSON.parse(ERC20Abi);
// V3 pool abi json file
let pool = fs.readFileSync('V3PairAbi.json');
const IUniswapV3PoolABI = JSON.parse(pool);
// V3 factory abi json
let facto = fs.readFileSync('V3factory.json');
const IUniswapV3FactoryABI = JSON.parse(facto);
let NFT = fs.readFileSync('UniV3NFT.json');
const IUniswapV3NFTmanagerABI = JSON.parse(NFT);
const provider = new ethers.providers.JsonRpcProvider(ALCHEMY)
// V3 standard addresses (different for celo)
const factory = FACTORY;
const NFTmanager = NFTMANAGER;
async function getData(tokenID){
let FactoryContract = new ethers.Contract(factory, IUniswapV3FactoryABI, provider);
let NFTContract = new ethers.Contract(NFTmanager, IUniswapV3NFTmanagerABI, provider);
let position = await NFTContract.positions(tokenID);
let token0contract = new ethers.Contract(position.token0, ERC20, provider);
let token1contract = new ethers.Contract(position.token1, ERC20, provider);
let token0Decimal = await token0contract.decimals();
let token1Decimal = await token1contract.decimals();
let token0sym = await token0contract.symbol();
let token1sym = await token1contract.symbol();
let V3pool = await FactoryContract.getPool(position.token0, position.token1, position.fee);
let poolContract = new ethers.Contract(V3pool, IUniswapV3PoolABI, provider);
let slot0 = await poolContract.slot0();
let pairName = token0sym +"/"+ token1sym;
let dict = {"SqrtX96" : slot0.sqrtPriceX96.toString(), "Pair": pairName, "T0d": token0Decimal, "T1d": token1Decimal, "tickLow": position.tickLower, "tickHigh": position.tickUpper, "liquidity": position.liquidity.toString()}
return dict
}
const Q96 = JSBI.exponentiate(JSBI.BigInt(2), JSBI.BigInt(96));
const MIN_TICK = -887272;
const MAX_TICK = 887272;
function getTickAtSqrtRatio(sqrtPriceX96){
let tick = Math.floor(Math.log((sqrtPriceX96/Q96)**2)/Math.log(1.0001));
return tick;
}
async function getTokenAmounts(liquidity,sqrtPriceX96,tickLow,tickHigh,token0Decimal,token1Decimal){
let sqrtRatioA = Math.sqrt(1.0001**tickLow).toFixed(18);
let sqrtRatioB = Math.sqrt(1.0001**tickHigh).toFixed(18);
let currentTick = getTickAtSqrtRatio(sqrtPriceX96);
let sqrtPrice = sqrtPriceX96 / Q96;
let amount0wei = 0;
let amount1wei = 0;
if(currentTick <= tickLow){
amount0wei = Math.floor(liquidity*((sqrtRatioB-sqrtRatioA)/(sqrtRatioA*sqrtRatioB)));
}
if(currentTick > tickHigh){
amount1wei = Math.floor(liquidity*(sqrtRatioB-sqrtRatioA));
}
if(currentTick >= tickLow && currentTick < tickHigh){
amount0wei = Math.floor(liquidity*((sqrtRatioB-sqrtPrice)/(sqrtPrice*sqrtRatioB)));
amount1wei = Math.floor(liquidity*(sqrtPrice-sqrtRatioA));
}
let amount0Human = (amount0wei/(10**token0Decimal)).toFixed(token0Decimal);
let amount1Human = (amount1wei/(10**token1Decimal)).toFixed(token1Decimal);
console.log("Amount Token0 wei: "+amount0wei);
console.log("Amount Token1 wei: "+amount1wei);
console.log("Amount Token0 : "+amount0Human);
console.log("Amount Token1 : "+amount1Human);
return [amount0wei, amount1wei]
}
async function start(positionID){
let data = await getData(positionID);
let tokens = await getTokenAmounts(data.liquidity, data.SqrtX96, data.tickLow, data.tickHigh, data.T0d, data.T1d);
}
start(POOLID)
// Also it can be used without the position data if you pull the data it will work for any range
getTokenAmounts(12558033400096537032, 20259533801624375790673555415)

Related

how to populate async call from inside another

I have a script that makes multiple API calls, and the result of one call effects the others.
async function getPlugin(id){
const fetchCardPlugin = `https://*********..amazonaws.com/*****/cardPlugin?id=${id}`
const cp = await fetch(fetchCardPlugin)
let pluginData = await cp.text();
pluginData = JSON.parse(pluginData);
if (typeof pluginData[0] != undefined){
return pluginData[0]['value'].split(':').pop().split('')[0]
}
else {
return ''
}
}
elm.addEventListener('click',()=>{
return t.get('board','shared','bid')
.then(data=>{
(async function(){
const sheetId = data;
const cardList = [];
const mm = {};
const fetchCardData = `https://*******.execute-api.******.amazonaws.com/******/cardData?id=${boardId}`
const cd = await fetch(fetchCardData)
let cardData = await cd.text();
cardData = JSON.parse(cardData);
await cardData.map(x=>{
const cardDict = {};
// console.log(getPlugin(x.shortLink));
cardDict['points'] = getPlugin(x.shortLink);
cardDict['id'] = x.id;
cardDict['title'] = x.name;
})
My first call goes to my fetchCardData. I then use the data from this return to both create an object, and make another call.
await cardData.map(x=>{
const cardDict = {};
// console.log(getPlugin(x.shortLink));
cardDict['points'] = getPlugin(x.shortLink);
cardDict['id'] = x.id;
My big sticking point is that, I need to use data from the second call to populate the object. Currently when I do this I am getting a Promise for the objects point value.
comments:0
description:""
id:"6354b75ddared4ba013aa06440"
labels:""
last activity:"Sat Oct 22 2022"
list:"To Do"
members:""
points:Promise
[[Prototype]]:Promise
[[PromiseState]]:"fulfilled"
[[PromiseResult]]:"5"
title:"test"
url:"https://trello.com/c/*******/**"
What I would like is this:
comments:0
description:""
id:"6354b75ddared4ba013aa06440"
labels:""
last activity:"Sat Oct 22 2022"
list:"To Do"
members:""
points:5
title:"test"
url:"https://trello.com/c/*******/**"
const cardListPromises = cardData.map(async (x) => {
const cardDict = {};
cardDict['points'] = await getPlugin(x.shortLink);
cardDict['id'] = x.id;
cardDict['title'] = x.name;
return cardDict;
})
const cardList = await Promise.all(cardListPromises);
console.log(cardList) // this is the final result you need.

Convert iterative function to recursive kind using javascript

I have written a function to pull stream data from the fetch API. I want to convert the function to a recursive one and would like to write it as an async function.
Here is the code which works but not asynchronous:
const productsStream = async () => {
const request = {
searchRange: ['fragrance', 'perfumery', 'cologne'],
exclusionCategory: ['discounted']
}
const response = await fetch('/products/stream', {
method: 'POST',
body: JSON.stringify(request)
});
const decoder = new TextDecoderStream();
const reader = response.body.pipeThrough(decoder).getReader();
let line = "";
while (true) {
const { done, value } = await reader.read();
let chunk = remainder + value;
let products = []
let newlineIndex;
while ((newlineIndex = chunk.indexOf("\n")) != -1) {
let item = chunk.substring(0, newlineIndex);
chunk = chunk.substring(newlineIndex);
if (chunk.length > 1) chunk = chunk.substring(1);
}
line = chunk;
products = []
if ( done ) break;
}
}
I'd welcome any help in converting this.

check if array contains string in node.js

I try to write a code that will create a file with an amount of random jokes using this npm and Environment Variables in an env file but I can't get it to work.
here is the code:
let oneLinerJoke = require("one-liner-joke");
require("dotenv").config();
let fs = require("fs");
var getRandomJokeWithTag = oneLinerJoke.getRandomJokeWithTag(
`${process.env.JOKE_SUBJECT}`
);
let arrayJokes = [];
let i = 0;
let counter = 0;
let amount = parseInt(`${process.env.JOKE_AMOUNT}`);
while (i <= amount) {
let joke = oneLinerJoke.getRandomJokeWithTag(process.env.JOKE_SUBJECT);
joke = joke.body.replace(",", "");
if (arrayJokes.includes(joke)) {
arrayJokes.push((joke + "\n"));
i++;
}
}
const createFile = fs.writeFileSync('./created_files/jokes.txt', arrayJokes.toString().replace(/,/g, ""));
Add __dirname to specify the directory.
const createFile = fs.writeFileSync(__dirname + '/created_files/jokes.txt', arrayJokes.toString().replace(/,/g, ""));

Sapper is not reloading data when hitting link

I’m building a site using sapper and requesting data from an API. It has been working smooth until now.
When I’m going from site.com/title/id1 to site.com/title/id2 the new information is not loaded until I hit a manual refresh. Any ideas?
import { stores, goto } from "#sapper/app";
import Card from "../_titlecard.svelte";
const { page } = stores();
const { slug } = $page.params;
import { onMount } from "svelte";
let looper = [];
let artistName = "";
let titleName = "";
let dvdCover = "";
let titleCover = "";
let genre = "";
let tracks = [];
onMount(async () => {
const res = await fetch(`https://.com/api/title/${slug}`);
const data = await res.json();
artistName = data.artistName;
titleName = data.name;
dvdCover = data.graphics.dvd;
titleCover = data.graphics.landscape;
genre = data.genre;
tracks = data.tracks.length;
const res2 = await fetch(`https://.com/api/artists/all`);
const data2 = await res2.json();
let moreTitles = [];
const more = data2.map((x) => {
if (x.titles.length > 0 && x.genre === genre) {
looper.push(x.titles[0]);
looper = moreTitles;
}
});
});
And then I have this in the html
{#each looper.slice(0, 4) as item, i}
<Card imgurl={item.graphics.dvd} concert={item.name} id={item.id} />
{/each}
A page component is not unmounted and mounted again if the navigation results in the same page component being used, so your onMount will only be run once with the first id.
You could use a reactive statement to make sure you run the desired code every time $page.params.slug changes.
Example
import { stores, goto } from "#sapper/app";
import Card from "../_titlecard.svelte";
const { page } = stores();
let looper = [];
let artistName = "";
let titleName = "";
let dvdCover = "";
let titleCover = "";
let genre = "";
let tracks = [];
$: (async () => {
const { slug } = $page.params;
const res = await fetch(`https://.com/api/title/${slug}`);
const data = await res.json();
artistName = data.artistName;
titleName = data.name;
dvdCover = data.graphics.dvd;
titleCover = data.graphics.landscape;
genre = data.genre;
tracks = data.tracks.length;
const res2 = await fetch(`https://.com/api/artists/all`);
const data2 = await res2.json();
let moreTitles = [];
data2.forEach((x) => {
if (x.titles.length > 0 && x.genre === genre) {
moreTitles.push(x.titles[0]);
}
});
looper = moreTitles;
})();

Refactoring async functions in javascript

I have written a program to extract links to download photos in three steps:
The getPersons() function get the complete list of people to traverse.
Get the photos download links from the list of persons.
Download from the list created in step 2.
I am trying to refactor step 2 into an async function.
Is there an easy way to refactor second step into a function to make the code more readable?
Ideally, I would like to retrieve all the links and only then, start the download.
const axios = require("axios");
const cheerio = require("cheerio");
const url = "https://www.website.com";
const persons = [];
async function getPersons() {
await axios.get(url).then(response => {
const html = response.data;
const $ = cheerio.load(html);
const personList = $(".bio-btn");
console.log(personList.length);
personList.each(function() {
const link_raw = $(this).attr("href");
const link = url + link_raw;
const name = link_raw.replace("/bio/", "");
person.push({
name,
link
});
});
});
}
getPersons().then(function() {
persons.forEach(async function(person) {
var personLink = person.link;
await axios.get(personLink).then(response => {
const html = response.data;
const $ = cheerio.load(html);
const snapshots = $(".ratio-4-3");
snapshots.each(function() {
const pic = $(this).attr("style");
if (pic != undefined && pic.includes("biopicture")) {
var bioPhoto = s[1];
}
});
});
});
});
You are hardly getting much benefit out of your asynchronicity, as you end up making serial requests. I'd write it this way (untested):
async function getPersons() {
const response = await axios.get(url);
const html = response.data;
const $ = cheerio.load(html);
const personList = $('.bio-btn');
const persons = [];
personList.each(function() {
const link_raw = $(this).attr('href');
const link = url + link_raw;
const name = link_raw.replace("/bio/", "");
persons.push({
name,
link,
});
});
return persons;
};
async function getSnapshots() {
const persons = await getPersons();
const linkPromises = persons.map(person => axios.get(person.link));
const linkResponses = await Promise.all(linkPromises);
linkResults.forEach(response => {
const html = response.data;
const $ = cheerio.load(html);
const snapshots = $(".ratio-4-3");
// ...
});
}
I would refactor it like this. Removing .then() methods and the function keyword on anonymous functions makes the code look cleaner.
Using Promise.all() enables you to start all the downloads asynchronously which could be better than downloading images one by one.
const axios = require('axios');
const cheerio = require('cheerio');
const url = 'https://www.website.com';
async function getPersons() {
const response = await axios.get(url);
return extractPersonList(response);
}
// Step 1
function extractPersonList(response) {
const persons = [];
const html = response.data;
const $ = cheerio.load(html);
const personList = $('.bio-btn');
console.log(personList.length);
personList.each(() => {
const link_raw = $(this).attr('href');
const link = url + link_raw;
const name = link_raw.replace('/bio/', '');
persons.push({
name,
link
});
});
return persons;
}
async function getPhotos() {
const persons = await getPersons();
const promisies = persons.map(p => axios.get(p.link));
// Step 2
const responses = await Promise.all(promisies);
// Step 3
responses.forEach(response => {
const html = response.data;
const $ = cheerio.load(html);
const snapshots = $('.ratio-4-3');
snapshots.each(() => {
const pic = $(this).attr('style');
if (pic && pic.includes('biopicture')) {
var bioPhoto = s[1];
}
});
});
}
// Call getPhotos to start the process
getPhotos();

Categories