How to include large numbers in transactions >=1e21 - node.js

I am testing an ERC20 Token on the Rinkeby testnet.
I am sending transfer transactions of 1e23 units.
The response from web3 says
I have tried converting the amount to a string using the Javascript toString method.
And converting with web3.utils.toHex().
Both return errors
dat=token.methods.transfer(w3.utils.toHex(to),web3.utils.toHex(amount)).encodeABI()
/*
OR
dat=token.methods.transfer(w3.utils.toHex(to),web3.utils.toHex(amount)).encodeABI()
*/
w3.eth.sendTransaction({from:from,to:TOKEN_ADDRESS,data:dat,gas:gasLimit()},(err,txhash)=>{
if(err) throw err
console.log(txhash)
callback(txhash)
})
Uncaught Error: Please pass numbers as strings or BigNumber objects to avoid precision errors.

TLDR
Use the built-in util functions to convert ether to wei:
var amount = web3.utils.toWei('1000000','ether');
Old answer below:
Literally just follow the advise of the error.
The to number should initially be of type string because the number type in javascript is too small to store addresses.
If the amount starts of as a reasonable number then convert it to BigNumber using a bignumber library. Web3 internally uses bn.js as its bignumber library so for full compatibility you should also use the same but bignum is also compatible in my experience:
const BN = require('bn.js');
token.methods.transfer(new BN(to),new BN(amount)).encodeABI()
Based on your comment it appears you are trying to pass 1e+24 as a number. The problem is it is too large to fit in a double without losing precision. Web3 is refusing to use the number because it has already lost precision even before web3 has a chance to process it. The fix is to use a string instead:
var amount = '1000000000000000000000000';
token.methods.transfer(to,amount).encodeABI()
If you really don't want to type 24 zeros you can use string operations:
var amount = '1' + '0'.repeat(24);
Or if this is amount is really a million ethers it's better to use the built-in util functions to show what you really mean:
var amount = web3.utils.toWei('1000000','ether');

I know this is old but i was having troubble with some tests for solidity using chai and i added this comment:
/* global BigInt */
With that you can use big numbers
const testValue = 2000000000000000000n;

Related

How to know if a customized random string function returns a string that matches a particular regex on Python 3?

Context:
One of the great features that the Binance API has is to allow its users to set a custom order id (a.k.a. newClientOrderId) for every trade they place on the Binance Futures market, this feature becomes useful if someone wants to keep a track of the trades that were placed following a particular trading strategy.
According to its Offical Docs, the parameter to be sent in the POST request to place the new order must be newClientOrderId and its value has to match this regex criteria: ^[\.A-Z\:/a-z0-9_-]{1,36}$
Problem:
I wrote a simple random string function on Python3 that returns a random string based on 2 parameters which are a string and the length of the desired string to combine, here it is:
import random, string
def randstr(s, length):
all_chars = string.ascii_lowercase
result = s
for i in range(length):
result += random.choice(all_chars)
return(result)
Tests
randstr('test1',5)
Out[14]: 'test1uljgp'
randstr('test1',2)
Out[15]: 'test1mo'
randstr('test1',5)
Out[16]: 'test1pbgjw'
How can I know if the output of my custom randstr function matches this regex criteria: ^[\.A-Z\:/a-z0-9_-]{1,36}$? By knowing this, I will ensure that future developments related to this API will keep working nonstop.

What is a good way to derive a numbers from random seed?

I have a game I am working on. There is one random seed generated at some point. At later point, I want to use this seed to derive some attributes like attack or defense of a character.
I want attributes to not be correlated to each other. One way I thought of is using hash functions like so:
const attackHex = createHash('md5')
.update(seed)
.update('attack')
.digest('hex')
const attack = Number(attackHex);
console.log('attack', attackHex, attack)
const defenseHex = createHash('md5')
.update(seed)
.update('defense')
.digest('hex')
const defense = Number(defenseHex);
console.log('defense', defenseHex, defense)
Outputs:
attack 73341812d1bd6fc73c022b4971618c27 NaN
defense 0620fbd637b7cf2f7d83dc3c8d5f8528 NaN
But the number conversion is not too happy... I guess it is too big of a number.
I would appreciate any help.
Oooh I should do const defense = Number('0x' + defenseHex);... I also end up making the number smaller by:
const defense = Number('0x' + defenseHex.slice(0, 6));

Calculate time differences in nodejs from a manually created format

I wanted to calculate the time differences (in minutes). However the data I gotten is not using a conventional time format, it is using the following format "yyyy-mm-dd-HH-MM-ss" in UTC time. I can't use this directly in moments or other library as seems. What is the recommendations to handle this specific format?
How can I use library such as "moment" to calculate the time differences with this time format from my data?
Not sure but possibly try it with moment, something like:
const moment = require('moment');
const yourSpecialFormat = 'YYYY-MM-DD-HH-mm-ss';
const someDateInYourFormat = '2020-02-22-05-58-57';
let now = moment(moment().format(yourSpecialFormat), yourSpecialFormat);
let then = moment(someDateInYourFormat, yourSpecialFormat);
console.log('Hours ----> ', moment.duration(now.diff(then)).asHours());
console.log('Minutes ----> ', moment.duration(now.diff(then)).asMinutes ());

Different results for SHA-1 hashing between Groovy and Python

This question is related to my query titled "Create WS security headers for REST web service in SoapUI Pro". However that one is different as I raised that because I couldn't get the script to work at all, I came up with a solution for that but it only works about 66% of the time.
I have noticed that the code that I use to hash the string sometimes produces different results when compared to a python script hashing the same input.
Below is my groovy code that hashes an input value.
MessageDigest cript2 = MessageDigest.getInstance("SHA-1");
cript2.update(nonce.getBytes("ASCII"));
PasswordDigest = new String(cript2.digest());
If I run it with the input nonce value 201703281329 it produces the below
ë±ËËÐùìÓ0¼ÕM�¹,óßP‹
If I use the same input value using the Python code below then it produces ëᄆËËÐùìÓ0ᄐÕMマᄍ,óßPヒ
digest = sha.new(nonce).digest()
However if I run the groovy and python scripts with input value 201703281350 then they both produce ..
iàvè©®É¹m:F ˠ¾
Could someone tell me why I am seeing differences for some input values and not others and how I can modify my groovy code so that it produces same values as Python code?
much appreciated.
If you compare the bytes returned by the digest method of both languages, you'll find that they are indeed the same. The reason is that some combinations of bytes do not result in printable Java Strings.
To compare them:
def hexString = PasswordDigest.collect { String.format('%02x', it) }.join()
Compare to the output of sha.hexdigest():
def hexString = sha.new(nonce).hexdigest()
Both should produce ebb1cbcbd0f9ecd330bcd51b4d8fb92cf3df508b
Edited
Perhaps I didn't make it clear that passwordDigest should not be converted to a String. Below is the complete groovy and python code. Both programs produce the same output:
Groovy:
import java.security.*
String nonce = '201703281329'
MessageDigest digest = MessageDigest.getInstance("SHA-1")
digest.update(nonce.getBytes("ASCII"))
byte[] passwordDigest = digest.digest() // byte[], not string
String hexString = passwordDigest.collect { String.format('%02x', it) }.join()
println hexString
Python:
import sha
nonce = '201703281329'
sha.new(nonce).hexdigest()
print sha.new(nonce).hexdigest()
The output of both: ebb1cbcbd0f9ecd330bcd51b4d8fb92cf3df508b.

How to send a message containing different data types over mqtt?

I am trying to send a message to the broker over a websocket. The message contains numbers that represent sensor data, so the message can be a mix of integers and floats. When I run the code I get TypeError: payload must be a string, bytearray, int, float or None. How can the code be changed to send a message containing integers and floats? I am using CloudMQTT as a broker.
Full code:
import paho.mqtt.client as mqtt
import time
client = mqtt.Client()
client.username_pw_set("User", "Password")
client.connect("Server", "Port")
num_one = 5.83
num_two = -12.46
num_three = 2
message = (num_one, num_two, num_three)
while True:
client.publish("topic", message)
time.sleep(1)
It looks like your problem is that the message you're sending is a tuple. You probably want
message = (num_one, num_two, num_three)
message = ''.join([str(x) for x in message])
This will convert each number to a string, then join them to a single string.
Choose an appropriate binary or text based format for your message, and encode your structure in that format. It will then either be a bytearray or string.
Unless there's a good reason to roll your own format, I'd suggest SenML as it is barely more complex than most non-standard JSON formats, but is sufficiently standardised you can at least say you're trying to be compatible with other applications.

Resources