@meterio/devkit
Version:
Typescript library to aid DApp development on Meter network
238 lines • 17.3 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Transaction = void 0;
const address_1 = require("./cry/address");
const blake2b_1 = require("./cry/blake2b");
const secp256k1_1 = require("./cry/secp256k1");
const rlp_1 = require("./rlp");
/** Transaction class defines Meter's multi-clause transaction */
class Transaction {
/** decode from Buffer to transaction
* @param raw encoded buffer
* @param unsigned to indicator if the encoded buffer contains signature
*/
static decode(raw, unsigned) {
let body;
let signature;
if (unsigned) {
body = unsignedTxRLP.decode(raw);
}
else {
const decoded = txRLP.decode(raw);
signature = decoded.signature;
delete decoded.signature;
body = decoded;
}
const reserved = body.reserved;
if (reserved.length > 0) {
if (reserved[reserved.length - 1].length === 0) {
throw new Error('invalid reserved fields: not trimmed');
}
const features = featuresKind.buffer(reserved[0], 'reserved.features').decode();
body.reserved = {
features,
};
if (reserved.length > 1) {
body.reserved.unused = reserved.slice(1);
}
}
else {
delete body.reserved;
}
const tx = new Transaction(body);
if (signature) {
tx.signature = signature;
}
return tx;
}
/**
* construct a transaction object with given body
* @param body body of tx
*/
constructor(body) {
this.body = Object.assign({}, body);
}
/**
* returns transaction ID
* null returned if something wrong (e.g. invalid signature)
*/
get id() {
if (!this._signatureValid) {
return null;
}
try {
const signingHash = this.signingHash();
const pubKey = secp256k1_1.secp256k1.recover(signingHash, this.signature.slice(0, 65));
const origin = (0, address_1.publicKeyToAddress)(pubKey);
return '0x' + (0, blake2b_1.blake2b256)(signingHash, origin).toString('hex');
}
catch (_a) {
return null;
}
}
/**
* compute signing hashes.
* It returns tx hash for origin or delegator depends on param `delegateFor`.
* @param delegateFor address of intended tx origin. If set, the returned hash is for delegator to sign.
*/
signingHash(delegateFor) {
const reserved = this._encodeReserved();
const buf = unsignedTxRLP.encode(Object.assign(Object.assign({}, this.body), { reserved }));
const hash = (0, blake2b_1.blake2b256)(buf);
if (delegateFor) {
if (!/^0x[0-9a-f]{40}$/i.test(delegateFor)) {
throw new Error('delegateFor expected address');
}
return (0, blake2b_1.blake2b256)(hash, Buffer.from(delegateFor.slice(2), 'hex'));
}
return hash;
}
/** returns tx origin. null returned if no signature or not incorrectly signed */
get origin() {
if (!this._signatureValid) {
return null;
}
try {
const signingHash = this.signingHash();
const pubKey = secp256k1_1.secp256k1.recover(signingHash, this.signature.slice(0, 65));
return '0x' + (0, address_1.publicKeyToAddress)(pubKey).toString('hex');
}
catch (_a) {
return null;
}
}
/** returns tx delegator. null returned if no signature or not incorrectly signed */
get delegator() {
if (!this.delegated) {
return null;
}
if (!this._signatureValid) {
return null;
}
const origin = this.origin;
if (!origin) {
return null;
}
try {
const signingHash = this.signingHash(origin);
const pubKey = secp256k1_1.secp256k1.recover(signingHash, this.signature.slice(65));
return '0x' + (0, address_1.publicKeyToAddress)(pubKey).toString('hex');
}
catch (_a) {
return null;
}
}
/** returns whether delegated. see https://github.com/dfinlab/VIPs/blob/master/vips/VIP-191.md */
get delegated() {
return ((((this.body.reserved || {}).features || 0) & Transaction.DELEGATED_MASK) ===
Transaction.DELEGATED_MASK);
}
/** returns intrinsic gas it takes */
get intrinsicGas() {
return Transaction.intrinsicGas(this.body.clauses);
}
/** encode into Buffer */
encode() {
const reserved = this._encodeReserved();
if (this.signature) {
return txRLP.encode(Object.assign(Object.assign({}, this.body), { reserved, signature: this.signature }));
}
return unsignedTxRLP.encode(Object.assign(Object.assign({}, this.body), { reserved }));
}
_encodeReserved() {
const reserved = this.body.reserved || {};
const list = [
featuresKind.data(reserved.features || 0, 'reserved.features').encode(),
...(reserved.unused || []),
];
// trim
while (list.length > 0) {
if (list[list.length - 1].length === 0) {
list.pop();
}
else {
break;
}
}
return list;
}
get _signatureValid() {
const expectedSigLen = this.delegated ? 65 * 2 : 65;
return this.signature ? this.signature.length === expectedSigLen : false;
}
}
Transaction.DELEGATED_MASK = 1;
exports.Transaction = Transaction;
(function (Transaction) {
/**
* calculates intrinsic gas that a tx costs with the given clauses.
* @param clauses
*/
function intrinsicGas(clauses) {
const txGas = 5000;
const clauseGas = 16000;
const clauseGasContractCreation = 48000;
if (clauses.length === 0) {
return txGas + clauseGas;
}
return clauses.reduce((sum, c) => {
if (c.to) {
sum += clauseGas;
}
else {
sum += clauseGasContractCreation;
}
sum += dataGas(c.data);
return sum;
}, txGas);
}
Transaction.intrinsicGas = intrinsicGas;
function dataGas(data) {
const zgas = 4;
const nzgas = 68;
let sum = 0;
for (let i = 2; i < data.length; i += 2) {
if (data.substr(i, 2) === '00') {
sum += zgas;
}
else {
sum += nzgas;
}
}
return sum;
}
})(Transaction = exports.Transaction || (exports.Transaction = {}));
exports.Transaction = Transaction;
const unsignedTxRLP = new rlp_1.RLP({
name: 'tx',
kind: [
{ name: 'chainTag', kind: new rlp_1.RLP.NumericKind(1) },
{ name: 'blockRef', kind: new rlp_1.RLP.CompactFixedBlobKind(8) },
{ name: 'expiration', kind: new rlp_1.RLP.NumericKind(4) },
{
name: 'clauses',
kind: {
item: [
{ name: 'to', kind: new rlp_1.RLP.NullableFixedBlobKind(20) },
{ name: 'value', kind: new rlp_1.RLP.NumericKind(32) },
{ name: 'token', kind: new rlp_1.RLP.NumericKind(1) },
{ name: 'data', kind: new rlp_1.RLP.BlobKind() },
],
},
},
{ name: 'gasPriceCoef', kind: new rlp_1.RLP.NumericKind(1) },
{ name: 'gas', kind: new rlp_1.RLP.NumericKind(8) },
{ name: 'dependsOn', kind: new rlp_1.RLP.NullableFixedBlobKind(32) },
{ name: 'nonce', kind: new rlp_1.RLP.NumericKind(8) },
{ name: 'reserved', kind: { item: new rlp_1.RLP.BufferKind() } },
],
});
const txRLP = new rlp_1.RLP({
name: 'tx',
kind: [
...unsignedTxRLP.profile.kind,
{ name: 'signature', kind: new rlp_1.RLP.BufferKind() },
],
});
const featuresKind = new rlp_1.RLP.NumericKind(4);
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNhY3Rpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvdHJhbnNhY3Rpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsMkNBQW1EO0FBQ25ELDJDQUEyQztBQUMzQywrQ0FBNEM7QUFDNUMsK0JBQTRCO0FBRTVCLGlFQUFpRTtBQUNqRSxNQUFhLFdBQVc7SUFHdEI7OztPQUdHO0lBQ0ksTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFXLEVBQUUsUUFBa0I7UUFDbEQsSUFBSSxJQUFzQixDQUFDO1FBQzNCLElBQUksU0FBNkIsQ0FBQztRQUNsQyxJQUFJLFFBQVEsRUFBRTtZQUNaLElBQUksR0FBRyxhQUFhLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1NBQ2xDO2FBQU07WUFDTCxNQUFNLE9BQU8sR0FBRyxLQUFLLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ2xDLFNBQVMsR0FBRyxPQUFPLENBQUMsU0FBbUIsQ0FBQztZQUN4QyxPQUFPLE9BQU8sQ0FBQyxTQUFTLENBQUM7WUFDekIsSUFBSSxHQUFHLE9BQU8sQ0FBQztTQUNoQjtRQUVELE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxRQUFvQixDQUFDO1FBQzNDLElBQUksUUFBUSxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUU7WUFDdkIsSUFBSSxRQUFRLENBQUMsUUFBUSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFO2dCQUM5QyxNQUFNLElBQUksS0FBSyxDQUFDLHNDQUFzQyxDQUFDLENBQUM7YUFDekQ7WUFFRCxNQUFNLFFBQVEsR0FBRyxZQUFZLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsRUFBRSxtQkFBbUIsQ0FBQyxDQUFDLE1BQU0sRUFBWSxDQUFDO1lBQzFGLElBQUksQ0FBQyxRQUFRLEdBQUc7Z0JBQ2QsUUFBUTthQUNULENBQUM7WUFDRixJQUFJLFFBQVEsQ0FB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QUMsRUFBRSxDQUFDLEVBQUU7UUFDOUQsRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxJQUFJLFNBQUcsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLEVBQUU7UUFDL0MsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxFQUFFLElBQUksRUFBRSxJQUFJLFNBQUcsQ0FBQyxVQUFVLEVBQUUsRUFBRSxFQUFFO0tBQzNEO0NBQ0YsQ0FBQyxDQUFDO0FBRUgsTUFBTSxLQUFLLEdBQUcsSUFBSSxTQUFHLENBQUM7SUFDcEIsSUFBSSxFQUFFLElBQUk7SUFDVixJQUFJLEVBQUU7UUFDSixHQUFJLGFBQWEsQ0FBQyxPQUFPLENBQUMsSUFBc0I7UUFDaEQsRUFBRSxJQUFJLEVBQUUsV0FBVyxFQUFFLElBQUksRUFBRSxJQUFJLFNBQUcsQ0FBQyxVQUFVLEVBQUUsRUFBRTtLQUNsRDtDQUNGLENBQUMsQ0FBQztBQUVILE1BQU0sWUFBWSxHQUFHLElBQUksU0FBRyxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQyJ9