Invalid signature when siging EIP-712 data - javascript

I am trying call transferWithAuthorization on the USDC contract (which implements EIP-3009). To do this I need to sign the transaction data and then execute the transaction, however I am getting the error: Fail with error 'FiatTokenV2: invalid signature'
Example transaction error:
https://goerli.etherscan.io/tx/0x3d2cee8414682bcf55bc8adf86c2deaf14eb77448824c417629cca0d3f9bea94
Any ideas why?
const { ethers } = require('ethers');
const abi = require('./abi');
async function main() {
/* Generate Signature */
const sendingWallet = ethers.Wallet.createRandom();
const sendingAddress = await sendingWallet.getAddress();
const types = {
TransferWithAuthorization: [
{ name: 'from', type: 'address' },
{ name: 'to', type: 'address' },
{ name: 'value', type: 'uint256' },
{ name: 'validAfter', type: 'uint256' },
{ name: 'validBefore', type: 'uint256' },
{ name: 'nonce', type: 'bytes32' },
],
};
const domain = {
name: 'testapp',
version: '1',
chainId: '5',
verifyingContract: '0x07865c6E87B9F70255377e024ace6630C1Eaa37F', // USDC Contract
};
const message = {
from: sendingAddress,
to: '0x1bC152F3E47CC7baDF5629bc77CBEf9DaE813843', // Receiver wallet
value: 100000,
validAfter: 0,
validBefore: Math.floor(Date.now() / 1000) + 3600, // Valid for an hour
nonce: ethers.utils.hexValue(ethers.utils.randomBytes(32)), // 32 byte hex string
};
const signature = await sendingWallet._signTypedData(domain, types, message);
console.log(signature);
const { v, r, s } = ethers.utils.splitSignature(signature);
console.log(v, r, s);
/* Execute transaction */
// Throw away wallet :)
const wallet = ethers.Wallet.fromMnemonic(
'youth tool amount venue exact birth opinion derive lend charge roof food',
);
const connection = new ethers.providers.InfuraProvider(
'goerli', // or 'ropsten', 'rinkeby', 'kovan', 'goerli'
'x', // Infura API Key
);
const signer = wallet.connect(connection);
const contract = new ethers.Contract(
'0x07865c6E87B9F70255377e024ace6630C1Eaa37F',
abi,
signer,
);
const res = await contract.transferWithAuthorization(
message.from,
message.to,
message.value,
message.validAfter,
message.validBefore,
message.nonce,
v,
r,
s,
{
gasLimit: 1000000,
},
);
console.log(res);
const receipt = await res.wait();
console.log(receipt);
}
main();

Related

How would I make a POST request using Axios to enter two inputs and get data returned?

so I'm trying to make this idea I have come into fruition and I'm having a hard time figuring out where to start. The idea is a Nike Order Check command via discord bot, the user would use '/status' and input their email and order number and the bot would use Axios to get the guest order link 'https://www.nike.com/orders/details/', enter the two inputs the user inputted, click the submit button, then return values. New to using the Axios packages as a whole, so I'm lost on where to start. Does anyone have any ideas? The code below is what I have for before entering the inputs and after the data is captured
const { Discord, CommandInteraction, MessageEmbed } = require('discord.js');
const axios = require('axios');
const requests = require('request')
const wait = require('node:timers/promises').setTimeout;
module.exports = {
name: 'status',
description: 'Check Status Of Nike Order',
permission: 'USE_APPLICATION_COMMANDS',
options: [
{
name: 'email',
description: 'Input Account Email.',
required: true,
type: 'STRING'
},
{
name: 'ordernumber',
description: 'Input Order Number',
required: true,
type: 'STRING'
},
],
/**
*
* #param {CommandInteraction} interaction
*/
async execute(interaction) {
const { options } = interaction;
let email = options.getString("email");
let orderNumber = options.getString("ordernumber");
const baseURL = 'https://www.nike.com/orders/details/';
axios.get(`${baseURL}.json`).then((response) => {
let orderEmbed = new MessageEmbed()
.setTitle('Order Checked 🧪')
.setURL(``)
.addFields(
{ name: '**Account:**', value: `${email}` },
{ name: '**Status:**', value: `` },
{ name: '**Product Name:**', value: ``, inline: true },
{ name: '**Order Date:**', value: ``, inline: true },
{ name: '**Order Number:**', value: `${orderNumber}`, inline: true },
{ name: '**Size:**', value: `` },
)
.setTimestamp()
wait(2000);
interaction.reply({ embeds: [ orderEmbed ]})
})
}
}```
Since there was no answer to how to use axios for this project, I decided to use Puppeteer to integrate into Discord. The following code below is how I got that done.
const { Discord, CommandInteraction, MessageEmbed } = require('discord.js');
const puppeteer = require('puppeteer-extra');
const fs = require('fs');
const ChromeLauncher = require('chrome-launcher');
const StealthPlugin = require('puppeteer-extra-plugin-stealth');
const Ua = require('puppeteer-extra-plugin-anonymize-ua');
const prompt = require("prompt-sync")({ sigint: true });
const util = require('util');
const UserAgent = require('user-agents');
const request = require('request')
const wait = require('node:timers/promises').setTimeout;
puppeteer.use(StealthPlugin());
puppeteer.use(Ua());
//------------------ Proxy Integration ------------------//
var proxyData = "proxies.json";
function getProxies() {
if (fs.existsSync(proxyData)) {
return JSON.parse(fs.readFileSync(proxyData));
}
var proxies = {
proxies: prompt("Input Proxy List Separated By Commas: ")?.split(/,\s*/) ?? [],
proxyUsername: prompt("Input Proxy Username: "),
proxyPassword: prompt("Input Proxy Password: ")
};
fs.writeFileSync(proxyData, JSON.stringify(proxies));
return proxies [Math.floor(Math.random() * proxies.length)];
}
let { proxies, proxyUsername, proxyPassword } = getProxies();
let proxyList = (`${proxies[Math.floor(Math.random() * proxies.length)]}`);
console.log(proxyList)
module.exports = {
name: 'status',
description: 'Check Status Of Nike Order',
permission: 'USE_APPLICATION_COMMANDS',
options: [
{
name: 'email',
description: 'Input Account Email.',
required: true,
type: 'STRING'
},
{
name: 'ordernumber',
description: 'Input Order Number',
required: true,
type: 'STRING'
},
],
/**
*
* #param {CommandInteraction} interaction
*/
async execute(interaction) {
const { options } = interaction;
let email = options.getString("email");
let orderNumber = options.getString("ordernumber");
await interaction.deferReply();
await wait(1000);
try {
const browser = await puppeteer.launch({
headless: false,
executablePath: `C:/Program Files/BraveSoftware/Brave-Browser/Application/brave.exe`,
userDataDir: `%LOCALAPPDATA%/BraveSoftware/Brave-Browser/User Data/Default`,
args: [
'--no-sandbox',
'--disable-setuid-sandbox',
'--disable-web-security',
'--disable-features=IsolateOrigins,site-per-process',
`--enable-auto-reload=true`,
`--proxy-server=http://${proxyList}`
],
})
const page = await browser.newPage()
await page.authenticate({username:proxyUsername, password:proxyPassword});
await page.goto("https://www.nike.com/orders/details/")
await page.evaluate(async() => {
await new Promise(function(resolve) {
setTimeout(resolve, 1000)
});
});
await page.waitForSelector('#orderNumber');
await page.click("#orderNumber", { delay: 250 });
await page.keyboard.type(`${orderNumber}`, { delay: 250 })
await page.waitForSelector('#email');
await page.click('#email', { delay: 500 })
await page.keyboard.type(`${email}`, { delay: 250 })
await page.keyboard.press("Enter", { delay: 250 });
await page.waitForSelector(`p[data-testid="Order Purchase Type"]`)
let purchaseInfo = await page.evaluate(() => {
let purchaseTag = document.querySelectorAll(`p[data-testid="Order Purchase Type"]`);
let purchase = [];
purchaseTag.forEach((tag) => {
purchase.push(tag.innerText)
})
return purchase;
});
await page.waitForSelector(`h3[data-testid="Product Title"]`);
let productInfo = await page.evaluate(() => {
let productTag = document.querySelectorAll(`h3[data-testid="Product Title"]`);
let product = [];
productTag.forEach((tag) => {
product.push(tag.innerText)
})
return product;
});
await page.waitForSelector(`p[data-testid="Product Size"]`);
let productSize = await page.evaluate(() => {
let sizeTag = document.querySelectorAll(`p[data-testid="Product Size"]`);
let size = [];
sizeTag.forEach((tag) => {
size.push(tag.innerHTML)
})
return size;
});
await page.waitForSelector(`div[class="shipment-status-messaging mb3-sm u-full-width"]`);
let deliveryInfo = await page.evaluate(() => {
let deliveryTag = document.querySelectorAll(`div[class="shipment-status-messaging mb3-sm u-full-width"]`);
let delivery = [];
deliveryTag.forEach((tag) => {
delivery.push(tag.innerText)
})
return delivery;
});
await page.waitForSelector(`p[data-testid="Product Style Color"]`);
let skuInfo = await page.evaluate(() => {
let skuTag = document.querySelectorAll(`p[data-testid="Product Style Color"]`);
let sku = [];
skuTag.forEach((tag) => {
sku.push(tag.innerText)
})
return sku.toString();
});
browser.close()
let imgSKU = skuInfo.replace("-", "_")
let updatedSKU = imgSKU.replace("Style ", "")
console.log(updatedSKU)
let orderEmbed = new MessageEmbed()
.setTitle('Order Checked 🧪')
.setColor('#2B2F51')
.addFields(
{ name: '**Account:**', value: `${email}` },
{ name: '**Status:**', value: `${deliveryInfo}` },
{ name: '**Product Name:**', value: `${productInfo}`, inline: true },
{ name: '**Order Date:**', value: `${purchaseInfo}`, inline: true },
{ name: '**Order Number:**', value: `${orderNumber}`, inline: true },
{ name: '**Size:**', value: `${productSize}` },
)
.setTimestamp()
.setThumbnail(`https://images.nike.com/is/image/DotCom/${updatedSKU}?/$OMEGA_PRODUCT$.png`)
wait(2000);
interaction.editReply({ embeds: [ orderEmbed ]})
} catch (error) {
const errorEmbed = new MessageEmbed()
errorEmbed.setTitle('❌ Error Encountered ❌')
errorEmbed.setDescription('No variants/product found')
errorEmbed.setTimestamp()
interaction.editReply({ embeds: [ errorEmbed ]})
}
}
}

Fetch API Data In Node JS and Save In MongoDB Database

I'm new to mongooseDB and i'm trying to insert data from this API to the database, it creates the Collection but not the documents, any idea what could i be doing wrong?
import fetch from 'node-fetch';
import mongoose, { mongo } from 'mongoose';
mongoose.connect("mongodb://localhost/highscore");
const postSchema = new mongoose.Schema({
position: {
type: Number,
required: true
},
id: {
type: Number,
required: true
},
score: {
type: Number,
required: true
},
});
const Post = mongoose.model('Players', postSchema);
async function getPlayers() {
const getPlayers = await fetch("http://localhost:3008/api/highscore/players");
const response = await getPlayers.json();
for (let i = 0; i < response.lenght; i++) {
const post = new Post({
position: response[i]['position'],
id: response[i]['id'],
score: response[i]['score'],
});
post.save()
}
}
getPlayers();```
MongoDB provides Api to insert many documents at the same time, example below.
// check if your mongoDb is connected
mongoose.connect(URI).then(err => {
if(err) console.error({err});
else console.info("Database Connected");
});
async function getPlayers() {
const getPlayers = await fetch("http://localhost:3008/api/highscore/players");
try{
const response = await getPlayers.json();
// And then check if you are getting players
console.log({response});
const posts = response.map((player) => ({
position: player['position'],
id: player['id'],
score: player['score'],
}))
// it's not required to await it, just to be sure it did insert
await Post.insertMany(posts);
}catch(error){
console.log({error})
}
}
This line:
for (let i = 0; i < response.lenght; i++) {
response.length
now your array is empty so the save never happens
EDIT
Are you sure about the imports?
Following code works:
//const fetch = require('fetch');
const mongoose = require('mongoose');
mongoose.connect("mongodb://localhost/highscore");
const postSchema = new mongoose.Schema({
position: {
type: Number,
required: true
},
id: {
type: Number,
required: true
},
score: {
type: Number,
required: true
},
});
const Post = mongoose.model('Players', postSchema);
async function getPlayers() {
/*
const getPlayers = await fetch("http://localhost:3008/api/highscore/players");
const response = await getPlayers.json();
for (let i = 0; i < response.lenght; i++) {
*/
const post = new Post({
position: '12',
id: '15',
score: '300',
});
post.save()
} //} getPlayers();
Solution:
import fetch from 'node-fetch';
import mongoose, { mongo } from 'mongoose';
mongoose.connect("mongodb://127.0.0.1:27017/highscore");
const postSchema = new mongoose.Schema({
position: {
type: Number,
required: true
},
id: {
type: Number,
required: true
},
score: {
type: Number,
required: true
},
});
const Post = mongoose.model('Players', postSchema);
async function getPosts() {
const getPlayers = await fetch("http://localhost:3008/api/highscore/players");
const response = await getPlayers.json();
for( let i = 0;i < response.players.length; i++){
const post = new Post({
position: response.players[i]['position'],
id: response.players[i]['id'],
score: response.players[i]['score'],
});
post.save();
}
}
getPosts();
By default mongodb runs on localhost: 27017
Check your mongodb connection url
mongoose.connect('mongodb://localhost:27017/highscore')

Unable to fill mongodb document with external api data

I am trying to fill my mongodb document with data from unsplash and randomuser api.
const userdata = await axios.get("https://randomuser.me/api/?results=51");
const imagedat = await axios.get(
"https://api.unsplash.com/photos/random/?count=51&client_id=GWDzPpjHk743C2QnVBRxu8PtmOI3npF5sePZZ7o0pg4"
);
I call both apis for 51 results but after 22 results the code under catch gets displayed and only 22 documents get created
how to store all 51 results
const seeddata = async () => {
const userdata = await axios.get("https://randomuser.me/api/?results=51");
const imagedat = await axios.get(
"https://api.unsplash.com/photos/random/?count=51&client_id=GWDzPpjHk743C2QnVBRxu8PtmOI3npF5sePZZ7o0pg4"
);
try {
await MemoModel.deleteMany({});
const userarr = await userdata.data;
const imagedata = await imagedat.data;
for (let i = 0; i < 50; i++) {
const data = new MemoModel({
name: {
firstname: `${userarr.results[i].name.first}`,
lastname: `${userarr.results[i].name.last}`,
username: `${userarr.results[i].login.username}`,
},
about: {
user: `${userarr.results[i].gender} aged ${userarr.results[i].dob.age}. Rotting here for ${userarr.results[i].registered.age} `,
},
location: {
country: `${
countryarr[Math.floor(Math.random() * countryarr.length)]
}`,
state: `${userarr.results[i].location.state}`,
city: `${userarr.results[i].location.city}`,
address: `${userarr.results[i].location.street.name} ,${userarr.results[i].location.street.number}`,
zipcode: `${userarr.results[i].location.postcode}`,
},
email: {
user: `${userarr.results[i].email}`,
},
image: {
dp: `${userarr.results[i].picture.large}`,
coverimage: "https://source.unsplash.com/random/?mountains",
},
posts: {
postno: i,
posttitle: `${imagedata[i].description}`,
postcontent: `${imagedata[i].urls.regular}`,
postlikesno: imagedata[i].likes,
postcommentno: imagedata[i].width,
},
});
await data.save();
}
} catch {
console.log("catastrophic Failure");
}
};
seeddata().then(() => {
mongoose.connection.close();
});
Can you add (err) after your catch and console it instead of "catastrophic error"? It will give us the whole error that break your code:
catch(err) {
console.error(err)
}

Hyperledger sawtooth JavaScript SDK:submitted batches are invalid

I am trying to implement hyperledger sawtooth transaction through javascript SDK following this https://sawtooth.hyperledger.org/docs/core/releases/1.0/_autogen/sdk_submit_tutorial_js.html#encoding-your-payload.
/*
*Create the transaction header
*/
const createTransactionHeader = function createTransactionHeader(payloadBytes) {
return protobuf.TransactionHeader.encode({
familyName: 'intkey',
familyVersion: '1.0',
inputs: [],
outputs: [],
signerPublicKey: '02cb65a26f7af4286d5f8118400262f7790e20018f2d01e1a9ffc25de1aafabdda',
batcherPublicKey: '02cb65a26f7af4286d5f8118400262f7790e20018f2d01e1a9ffc25de1aafabdda',
dependencies: [],
payloadSha512: createHash('sha512').update(payloadBytes).digest('hex')
}).finish();
}
/*
* Create the transactions
*/
const createTransaction = function createTransaction(transactionHeaderBytes, payloadBytes) {
const signature = signer.sign(transactionHeaderBytes)
return transaction = protobuf.Transaction.create({
header: transactionHeaderBytes,
headerSignature: Buffer.from(signature, 'utf8').toString('hex'),
payload: payloadBytes
});
}
While submitting the transaction I am getting the following error from REST API
{
"error": {
"code": 30,
"message": "The submitted BatchList was rejected by the validator. It was poorly formed, or has an invalid signature.",
"title": "Submitted Batches Invalid"
}
}
Found the following issue similar to my problem
Sawtooth Invalid Batch or Signature
But its implemented in java the solution not work for my case
This should work, try this:
const cbor = require('cbor');
const {createContext, CryptoFactory} = require('sawtooth-sdk/signing');
const {createHash} = require('crypto');
const {protobuf} = require('sawtooth-sdk');
const request = require('request');
const crypto = require('crypto');
const context = createContext('secp256k1');
const privateKey = context.newRandomPrivateKey();
const signer = CryptoFactory(context).newSigner(privateKey);
// Here's how you can generate the input output address
const FAMILY_NAMESPACE = crypto.createHash('sha512').update('intkey').digest('hex').toLowerCase().substr(0, 6);
const address = FAMILY_NAMESPACE + crypto.createHash('sha512').update('foo').digest('hex').toLowerCase().substr(0, 64);
const payload = {
Verb: 'set',
Name: 'foo',
Value: 42
};
const payloadBytes = cbor.encode(payload);
const transactionHeaderBytes = protobuf.TransactionHeader.encode({
familyName: 'intkey',
familyVersion: '1.0',
inputs: [address],
outputs: [address],
signerPublicKey: signer.getPublicKey().asHex(),
batcherPublicKey: signer.getPublicKey().asHex(),
dependencies: [],
payloadSha512: createHash('sha512').update(payloadBytes).digest('hex')
}).finish();
const transactionHeaderSignature = signer.sign(transactionHeaderBytes);
const transaction = protobuf.Transaction.create({
header: transactionHeaderBytes,
headerSignature: transactionHeaderSignature,
payload: payloadBytes
});
const transactions = [transaction]
const batchHeaderBytes = protobuf.BatchHeader.encode({
signerPublicKey: signer.getPublicKey().asHex(),
transactionIds: transactions.map((txn) => txn.headerSignature),
}).finish();
const batchHeaderSignature = signer.sign(batchHeaderBytes)
const batch = protobuf.Batch.create({
header: batchHeaderBytes,
headerSignature: batchHeaderSignature,
transactions: transactions
};
const batchListBytes = protobuf.BatchList.encode({
batches: [batch]
}).finish();
request.post({
url: 'http://rest.api.domain/batches',
body: batchListBytes,
headers: {'Content-Type': 'application/octet-stream'}
}, (err, response) => {
if(err) {
return console.log(err);
}
console.log(response.body);
});

Promise in cron job

I try to run the code without success.
Only the first call works in start of node.
Here is my current code:
const Product = require('../models/Product');
const Price = require('../models/Price');
const cron = require('node-cron');
const amazon = require('amazon-product-api');
const util = require('util');
const _ = require('underscore')
/**
* Cron job
* Tracking price
*/
exports.track = () => {
cron.schedule('* * * * *', () => {
const client = amazon.createClient({
awsId: process.env.AWS_ID,
awsSecret: process.env.AWS_SECRET,
assocId: process.env.AWS_TAG
});
Promise.all([Product.getAsin()])
.then(([asin]) => {
let listId = _.pluck(asin, '_id');
let listAsin = _.pluck(asin, 'asin');
if (asin.length === 0) {
return
}
client.itemLookup({
idType: 'ASIN',
itemId: listAsin,
domain: 'webservices.amazon.fr',
responseGroup: 'ItemAttributes,OfferFull,SalesRank'
}).then((results) => {
for(i=0; i<listId.length; i++){
results[i].id = listId[i];
}
for(res of results) {
Price.addPrice({
asin: res.ASIN[0],
product: res.id,
salePrice: res.Offers[0].Offer[0].OfferListing[0].Price[0].Amount[0],
})
}
console.log(listId);
Product.makeUpdate(listId);
}).catch(function(err) {
console.log(err);
console.log(util.inspect(err, true, null));
});
})
.catch((err) => {
console.log(err);
})
})
}
Requests to MongoDB are asynchronous.
Product
const mongoose = require('mongoose');
mongoose.Promise = Promise;
const _ = require('underscore');
const moment = require('moment');
const productSchema = new mongoose.Schema({
name: String,
domain: String,
originUrl: { type: String, unique: true },
check: { type: Number, default: 0 },
ean: String,
asin: String
}, { timestamps: true });
Object.assign(productSchema.statics, {
getAsin() {
return this.find(
{ updatedAt: { $lt: oneMin },
asin: { $ne: null }
}
).limit(10)
.select({ asin: 1 })
.exec()//.then((tuples) => _.pluck(tuples, 'asin'))
},
makeUpdate(id) {
console.log('list des ID updated => ' + id);
return this.update({ _id: { $in: id } }, { $inc : { "check": 1 } } , {multi: true}).exec();
}
});
const Product = mongoose.model('Product', productSchema);
module.exports = Product;
const oneMin = moment().subtract(1, 'minutes').format();
Also, since I'm absolutely new to JavaScript and Node.js in general, any best practices or general tips will be greatly appreciated! :)

Categories

Resources