aion-gql-webcomponents
Version:
AION Webcomponents using AION GraphQL
100 lines (99 loc) • 4.71 kB
JavaScript
import rlp from "aion-rlp";
import { AionLong } from "aion-rlp";
import BN from "bn.js";
import nacl from 'tweetnacl';
import { Buffer } from 'buffer';
import { CryptoUtil } from "./CryptoUtil";
import { SignedTransaction } from "../../common/SignedTransaction";
export class TransactionUtil {
static signTransaction(transaction, privateKey) {
if (privateKey) {
if (privateKey.startsWith("0x"))
privateKey = privateKey.substring(2);
}
const rlpOutput = this.rlpEncode(transaction);
const hash = CryptoUtil.blake2b256(rlpOutput);
const privateKeyBuff = CryptoUtil.hex2ua(privateKey);
const keyPair = nacl.sign.keyPair.fromSecretKey(privateKeyBuff);
const signature = nacl.sign.detached(hash, keyPair.secretKey);
if (nacl.sign.detached.verify(hash, signature, keyPair.publicKey) === false) {
throw new Error('Could not verify signature.');
}
let aionPubSigLen = nacl.sign.publicKeyLength + nacl.sign.signatureLength;
const aionPubSig = CryptoUtil.concatBuffer(keyPair.publicKey, signature, aionPubSigLen);
const rawTx = rlp.decode(rlpOutput).concat(Buffer.from(aionPubSig));
const rawTransaction = rlp.encode(rawTx);
const rawTransactionHash = CryptoUtil.uia2hex(rawTransaction);
console.log(rawTransactionHash);
let signedTransaction = new SignedTransaction();
signedTransaction.messageHash = CryptoUtil.uia2hex(hash);
signedTransaction.signature = CryptoUtil.uia2hex(aionPubSig);
signedTransaction.rawTransaction = CryptoUtil.uia2hex(rawTransaction);
signedTransaction.input = transaction;
return signedTransaction;
}
static verifyAndEncodedSignTransaction(transaction, rlpEncoded, signature, publicKey) {
const hash = CryptoUtil.blake2b256(rlpEncoded);
if (nacl.sign.detached.verify(hash, signature, publicKey) === false) {
console.log("Could not verify the signature from ledger");
}
let aionPubSigLen = nacl.sign.publicKeyLength + nacl.sign.signatureLength;
const aionPubSig = CryptoUtil.concatBuffer(publicKey, signature, aionPubSigLen);
const rawTx = rlp.decode(rlpEncoded).concat(Buffer.from(aionPubSig));
const rawTransaction = rlp.encode(rawTx);
const rawTransactionHash = CryptoUtil.uia2hex(rawTransaction);
console.log(rawTransactionHash);
let signedTransaction = new SignedTransaction();
signedTransaction.messageHash = CryptoUtil.uia2hex(hash);
signedTransaction.signature = CryptoUtil.uia2hex(aionPubSig);
signedTransaction.rawTransaction = CryptoUtil.uia2hex(rawTransaction);
signedTransaction.input = transaction;
return signedTransaction;
}
static rlpEncode(transaction) {
const txArray = new Array();
if (transaction.to) {
transaction.to = transaction.to.toLowerCase();
if (!transaction.to.startsWith("0x"))
transaction.to = "0x" + transaction.to;
}
txArray.push(new BN(transaction.nonce));
txArray.push(transaction.to);
txArray.push(transaction.value);
txArray.push(transaction.data);
if (transaction.timestamp !== 0)
txArray.push(transaction.timestamp);
else {
transaction.timestamp = Date.now() * 1000;
txArray.push(transaction.timestamp);
}
if (transaction.gas)
txArray.push(new AionLong(new BN(transaction.gas)));
else {
transaction.gas = "22000";
txArray.push(new AionLong(new BN(transaction.gas)));
}
if (transaction.gasPrice) {
txArray.push(new AionLong(new BN(transaction.gasPrice)));
}
else {
transaction.gasPrice = this.defaultNrgPrice.toString();
txArray.push(new AionLong(new BN(transaction.gasPrice)));
}
if (transaction.type !== 0)
txArray.push(transaction.type);
else {
transaction.type = 1;
txArray.push(transaction.type);
}
const rlpOutput = rlp.encode(txArray);
return rlpOutput;
}
static getAddress(privateKey) {
const privateKeyBuff = CryptoUtil.hex2ua(privateKey);
const keyPair = nacl.sign.keyPair.fromSecretKey(privateKeyBuff);
return [CryptoUtil.createA0Address(keyPair.publicKey), CryptoUtil.uia2hex(keyPair.publicKey)];
}
}
TransactionUtil.defaultNrgPrice = 10000000000;
TransactionUtil.defaultNrgLimit = 22000;