Edit:
Resolved the issue with below code:
String tokenId="0x1800000000001289000000000000000000000000000000000000000000000000";
BigInteger token1;
if (tokenId.startsWith("0x")){
token1=new BigInteger(tokenId.substring(2),16);
I have a long String that I need to assign as BigInteger and pass it to another method of Web3j library. However, I keep receiving number format exception. Any help on this ?
Below is the method throwing exception:
public void getBalance1155(String walletAddress) throws ExecutionException, InterruptedException {
//define constant values
Web3j web3j=Web3j.build(new HttpService("https://mainnet.infura.io/v3/<apiKey>>"));
String contractAddress = "0xfaaFDc07907ff5120a76b34b731b278c38d6043C";
BigInteger tokenId=new BigInteger("0x1800000000001289000000000000000000000000000000000000000000000000",16);
NoOpProcessor processor = new NoOpProcessor(web3j);
Credentials credentials = Credentials.create("privatekey");
TransactionManager txManager = new FastRawTransactionManager(web3j, credentials, processor);
//Query Blockchain to get balance of WALLETADDRESS from Contract for given TokenID
ERC1155 token = ERC1155.load(contractAddress, web3j, txManager, DefaultGasProvider.GAS_PRICE, DefaultGasProvider.GAS_LIMIT);
RemoteCall<BigInteger> sendCall = token.balanceOf(walletAddress, tokenId);
BigInteger balance=sendCall.sendAsync().get();
log.info("balance >>>>>> " +balance);
}
Here's the Exception:
java.lang.NumberFormatException: For input string: "0x1800000000001289000000000000000000000000000000000000000000000000"
at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.base/java.lang.Long.parseLong(Long.java:692)
at java.base/java.lang.Long.parseLong(Long.java:817)
Drop the extraneous 0x from the string.
The documentation for BigInteger's constructor says
The String representation consists of an optional minus or plus sign followed by a sequence of one or more digits in the specified radix.
[...] The String may not contain any extraneous characters
No mention of prefixes like 0x (or 0 for octal).
You need to remove the 0x, you can retrieve the hexa value by using toString(16) on your BigInteger
BigInteger tokenId=new BigInteger("1800000000001289000000000000000000000000000000000000000000000000",16);
System.out.println("tokenId.toString(16) = " + tokenId.toString(16));
System.out.println("tokenId.toString(10) = " + tokenId.toString(10));
String originalString = "0x" + tokenId.toString(16);
System.out.println("originalString = " + originalString);
outputs:
tokenId.toString(16) = 1800000000001289000000000000000000000000000000000000000000000000
tokenId.toString(10) = 10855508365998423105807514254364715762064874182780947284375732482585619595264
originalString = 0x1800000000001289000000000000000000000000000000000000000000000000
As you are already using web3j you can use Numeric.decodeQuantity("0x1800000000001289000000000000000000000000000000000000000000000000") this decode the hexideimal into a BigInteger
Related
I have a string than I want to encrypt to send it over an insecure channel.
I want to:
Convert to int my-val & my-private-key. Then, multiply both. Send it. When receiving it, divide by my-private-key converted as int and get my-val.
I tried to used Integer.parseInt and Integer.toString as suggested here. It seems to work with System.out.println(Integer.parseInt("Kona", 27)); (as Java's documentation said)
So I made this:
int base = 27;
String key = "some key";
String cmd = "some val";
int based = Integer.parseInt(cmd, base);
System.out.println("Based: " + based);
int crypted = based * Integer.parseInt(key, base);
System.out.println("Crypted: " + crypted);
// here use un-secure channel to send/receive
int received = crypted;
int back = received / Integer.parseInt(key, base);
System.out.println("Get back: " + back);
System.out.println("Final result: " + Integer.toString(back, base));
But I get Exception in thread "main" java.lang.NumberFormatException: For input string: "some val" at the 4st line.
I tried with base 10, 16, 27, 32. Even if I understand why 10 & 16 doesn't work, why 27 & 32 don't ? How can I fix it ?
Based on below wikipedia link of numeral system, Java will check each character of your input string against the range of radix parameter and if its not in range than it will throw exception.
Visit https://en.wikipedia.org/wiki/List_of_numeral_systems,
Apart from that, Below is explanation from geeksforgeek site.
The string is null or of zero-length
The value represented by the string is not a value of type int
Specifically for the parseInt(String s, int radix) variant of the function:
The second argument radix is either smaller than Character.MIN_RADIX or larger than Character.MAX_RADIX
*
Each character of input string has min and max radix parameter.
Any character of the string is not a digit of the specified radix, except that the first character may be a minus sign ‘-‘ (‘\u002D’) or plus sign ‘+’ (‘\u002B’) provided that the string is longer than length 1
Custom logic for conversion
String name = "some val";
long key = 0;
for (int i = 0;i<name.length();i++)
key+= (name.charAt(i) - 'a'+1 ) * Math.pow(26,name.length() - i - 1 );
System.out.println(key);
Above code is taken Converting name to a key using radix-26
I was looking to encrypt with another string. I get the idea to multiply both, and so convert them into int. But, it seems to have informations lost with operation.
So, I searched for another way, and I found this one:
private static final String ALGORITHM = "AES";
private static final Key MY_KEY = new SecretKeySpec("16-char priv key".getBytes(), ALGORITHM);
private Cipher getCipher(int mode) throws Exception {
Cipher c = Cipher.getInstance(ALGORITHM);
c.init(mode, MY_KEY);
return c;
}
public String encrypt(String valueToEnc) throws Exception {
return Base64.getEncoder().encodeToString(getCipher(Cipher.ENCRYPT_MODE).doFinal(valueToEnc.getBytes()));
}
public String decrypt(String encryptedValue) throws Exception {
return new String(getCipher(Cipher.DECRYPT_MODE).doFinal(Base64.getDecoder().decode(encryptedValue)));
}
How it works ? It encrypt and decrypt with a key. This key should be a 16-chars one. Also, to make it easier to show/send/receive, it's converted into base 64.
Example of how to use:
String myVal = "some val";
String encrypt = encrypt(myVal);
System.out.println("Encrypt: " + encrypt);
String decrypt = decrypt(encrypt);
System.out.println("Decrypt: " + decrypt);
Output:
Encrypt: ERJZ7ZOJcNpQEAvrb6wPOA==
Decrypt: some val
I used SCALE Codec for java offline address generation. but I see that generated address and polkadot.js generated address are not alike.
I use bitcoinj 's MnemonicCode generation mnemonic, and I toseed the mnemonic get seed;
this is my code;
public void createAddress() throws Exception {
System.out.println("Generate a new Root Key + derive a `demo` address from that key");
int number = 0;
byte[] initialEntropy = new byte[128 / 8];
SecureRandomUtils.secureRandom().nextBytes(initialEntropy);
String mnemonic = "devote fatigue dice clock lock cross creek neutral minute achieve betray curve";
String[] mm = mnemonic.split(" ");
List<String> strings = Arrays.asList(mm.clone());
System.out.println(mnemonic);
String n = Utils.SPACE_JOINER.join(strings);
System.out.println(n);
byte[] seed = toSeed(strings, "");
String s = Hex.encodeHexString(seed);
System.out.println(s);
Schnorrkel instance = Schnorrkel.getInstance();
Schnorrkel.KeyPair rootKey = instance.generateKeyPairFromSeed(seed);
System.out.println(" Root Key: " + Hex.encodeHexString(rootKey.getSecretKey()));
Schnorrkel.KeyPair key = instance.deriveKeyPair(rootKey, Schnorrkel.ChainCode.from("".getBytes()));
Address address = new Address(SS58Type.Network.LIVE, key.getPublicKey());
System.out.println(" Address: " + address);
System.out.println("Public Key: " + Hex.encodeHexString(key.getPublicKey()));
System.out.println("Secret Key: " + Hex.encodeHexString(key.getSecretKey()));
}
public static byte[] toSeed(List<String> words, String passphrase) {
checkNotNull(passphrase, "A null passphrase is not allowed.");
// To create binary seed from mnemonic, we use PBKDF2 function
// with mnemonic sentence (in UTF-8) used as a password and
// string "mnemonic" + passphrase (again in UTF-8) used as a
// salt. Iteration count is set to 4096 and HMAC-SHA512 is
// used as a pseudo-random function. Desired length of the
// derived key is 512 bits (= 64 bytes).
//
String pass = Utils.SPACE_JOINER.join(words);
String salt = "mnemonic" + passphrase;
final Stopwatch watch = Stopwatch.createStarted();
byte[] seed = PBKDF2SHA512.derive(pass, salt, 2048, 32);
watch.stop();
System.out.println("PBKDF2 took {}" + watch);
return seed;
}
polkadot.js generated address is "12EgmkT6NHjTjtwcvfBFu1dkPEN9TLFo3ftA4L2ZcmkCfQCp";
i use my code generated address is "12YTJRjPRsw34wBp2Ewfr9oBP9w47RpKKw4CPZF2zaCga1Hk"
how do I generate similar polkadot.js' address ?
I have the following code:
#SuppressWarnings("resource")
public void changeSkin(String name){
try {
URL uuidURL = new URL("https://api.mojang.com/users/profiles/minecraft/" + name);
String uuid = new Scanner(uuidURL.openStream(), "UTF-8").useDelimiter("\\A").next();
uuid = uuid.substring(7, 39);
System.out.println(uuid); // works
URL valueURL = new URL("https://sessionserver.mojang.com/session/minecraft/profile/" + uuid + "?unsigned=false");
String value = new Scanner(valueURL.openStream(), "UTF-8").useDelimiter("\\A").next();
value = value.replace('"', '!');
value = value.replaceAll("!value!:!", "*");
value = value.replaceAll("=!,", "+");
value = value.substring(value.charAt('*'), value.charAt('+')); // Gives an error outOfBounds: -13
String signature = new Scanner(valueURL.openStream(), "UTF-8").useDelimiter("\\A").next();
signature = signature.replaceAll("!signature!:!", "_");
signature = signature.replaceAll("=!}]}", "~");
signature = signature.substring(value.charAt('_'), value.charAt('~'));
System.out.println(signature);
System.out.println(value);
//profile.getProperties().put("textures", new Property(value, signature));
} catch (Exception e) {
e.printStackTrace();
}
}
While running it throws and outOfBoundsException: -13
But how can that throw a negative number?
Thanks for any help
Edit: Here is the website: https://sessionserver.mojang.com/session/minecraft/profile/e96ca9800c6c4a1588a2922a02ae1080?unsigned=false
I guess you are making some kind of minecraft bot or something ... but that's irrelevant.
You are using charAt incorrectly.
https://docs.oracle.com/javase/7/docs/api/java/lang/String.html#charAt(int)
What you are looking for is indexOf
https://docs.oracle.com/javase/7/docs/api/java/lang/String.html#indexOf(int)
You ask for the character position for '*' and THEN ask for the position '+'. The problem is that the plus is located BEFORE the star in the string, so it's returning a negative number.
To remedy, I would suggest breaking the substring into two lines:
value = value.substring(value.indexOf('*'));
value = value.substring(0, value.indexOf('+'));
Though it may seem irrelevant, breaking it into two lines breaks the string at the first instance of the * and then at the NEXT first instance of the +.
I have the following code:
private static final String PATTERN = "file_%d.txt";
int no; // 1-3
String filename = String.format(PATTERN, no ,Locale.US);
and later on I get an exception saying that
java.io.FileNotFoundException: file_٣.txt
which indicates that %d got replaced with an arabic number. How can that be if I explicitely specify Locale.US?
The locale needs to be the first parameter:
String.format(Locale.US,PATTERN, no);
I am working on a homework assignment, and I am going a little "above and beyond" what is called for by the assignment. I am getting a run-time error in my code, and can not for the life of me figure out what it is that I have done wrong.
Here is the assignment:
Write a program that displays a simulated paycheck. The program should ask the user to enter the date, the payee’s name, and the amount of the check. It should then display a simulated check with the dollar amount spelled out.
Here is my code:
CheckWriter:
/* CheckWriter.java */
// Imported Dependencies
import java.util.InputMismatchException;
import java.util.Scanner;
public class CheckWriter {
public static void main(String args[]) {
Scanner keyboard = new Scanner(System.in);
// Try to get the name
String name = "";
NameValidator validateName = new NameValidator();
while (validateName.validate(name) == false) {
System.out.println("Enter the name: ");
name = keyboard.nextLine();
if (validateName.validate(name) == false) {
System.out.println("Not a valid name.");
}
}
// Get the date
String date = "";
DateValidator validateDate = new DateValidator();
while (!validateDate.validate(date)) {
System.out.println("Enter the date (dd/mm/yyyy): ");
date = keyboard.nextLine();
if (!validateDate.validate(date)) {
System.out.println("Not a valid date.");
}
}
// Try to get the amount of the check
String checkAmount = "";
CurrencyValidator validateCurrency = new CurrencyValidator();
while (!validateCurrency.validate(checkAmount)) {
System.out.print("Enter the Check Amount (XX.XX): $");
checkAmount = keyboard.nextLine();
if (!validateCurrency.validate(checkAmount)) {
System.out.println("Not a valid check amount.");
}
}
String checkWords = checkToWords(checkAmount); // ERROR! (48)
System.out
.println("------------------------------------------------------\n"
+ "Date: "
+ date
+ "\n"
+ "Pay to the Order of: "
+ name
+ " $"
+ checkAmount
+ "\n"
+ checkWords
+ "\n"
+ "------------------------------------------------------\n");
}
private static String checkToWords(String checkAmount) {
/**
* Here I will use the string.split() method to separate out
* the integer and decimal portions of the checkAmount.
*/
String delimiter = "\\.\\$";
/* Remove any commas from checkAmount */
checkAmount.replace(",", "");
/* Split the checkAmount string into an array */
String[] splitAmount = checkAmount.split(delimiter);
/* Convert the integer portion of checkAmount to words */
NumberToWords intToWord = new NumberToWords();
long intPortion = Long.parseLong(splitAmount[0]); // ERROR! (84)
intToWord.convert(intPortion);
String intAmount = intToWord.getString() + " dollars";
/* Convert the decimal portion of checkAmount to words */
String decAmount = "";
long decPortion = Long.parseLong(splitAmount[1]);
if (decPortion != 0) {
NumberToWords decToWord = new NumberToWords();
decToWord.convert(Long.parseLong(splitAmount[1]));
decAmount = " and " + decToWord.getString() + " cents.";
}
return (intAmount + decAmount);
}
}
Note that I am using external class files to handle validation of the name, date, currency, and conversion from numbers to words. These class files all work as intended.
The error I am getting is:
Exception in thread "main" java.lang.NumberFormatException: For input string: ""
at java.lang.NumberFormatException.forInputString(Unknown Source)
at java.lang.Long.parseLong(Unknown Source)
at java.lang.Long.parseLong(Unknown Source)
at CheckWriter.checkToWords(CheckWriter.java:82)
at CheckWriter.main(CheckWriter.java:46)
I have commented the lines in my code that are causing the errors that I am experiencing.
Could someone please assist me in figuring where my code is going wrong? I can include the other class files if you feel that it would be needed.
EDIT: When I run the code, it asks for the name and date. Before asking for the check amount is when it throws the error.
EDIT 2: A huge thank you to cotton.m! Thanks to his advice, I have changed the while statements to look like this:
while(!validateDate.validate(date) && date == "")
This has now fixed my issue. It would appear that when validating data with a regex expression, an empty string will return true.
The String you are trying to parse in an empty length string.
My suggestion would be to
1) Check the value of checkAmount at the start of checkToWords - if it is blank there's your problem
2) Don't do that split. Just replace the $ like you did the , (I think this is your real problem)
Also you are going to have another issue in that 10000.00 is not a long. I see you are splitting out the . but is that really what you want?
It is NumberFormatException, the value in checkAmount (method parameter) is not a valid Number.
You need to set checkAmount=checkAmount.replace(",", "");
Otherwise checkAmount will still have , inside and causes NumberFormatExcpetion.
Your issue is with your delimiter regex, currently you are using \.\$ which will split on a literal . followed by a literal $. I'm assuming that what you are actually intending to do is to split on either a . or a $, so change your delimiter to one of the following:
String delimiter = "\\.|\\$"
or
String delimiter = "[\\.\\$]"
As your code is now, checkAmount.split(delimiter) is not actually successfully splitting the string anywhere, so Long.parseLong(splitAmount[0]) is equivalent to Long.parseLong(checkAmount).
It should be:
String delimiter = "[\\.\\$]";
and then you have to check that splitWord[i] is not empty.