@onekeyfe/blockchain-libs
Version:
OneKey Blockchain Libs
262 lines • 11.3 kB
JavaScript
"use strict";
/* Copyright (c) 2019 Algorand, llc */
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Transaction = exports.ALGORAND_MIN_TX_FEE = void 0;
const hi_base32_1 = __importDefault(require("hi-base32"));
const address = __importStar(require("./address"));
const encoding = __importStar(require("./encoding"));
const nacl = __importStar(require("./naclWrappers"));
const types_1 = require("./types");
const utils = __importStar(require("./utils"));
const ALGORAND_TRANSACTION_LENGTH = 52;
exports.ALGORAND_MIN_TX_FEE = 1000; // version v5
const ALGORAND_TRANSACTION_LEASE_LENGTH = 32;
const NUM_ADDL_BYTES_AFTER_SIGNING = 75; // NUM_ADDL_BYTES_AFTER_SIGNING is the number of bytes added to a txn after signing it
/**
* Transaction enables construction of Algorand transactions
* */
class Transaction {
constructor({ ...transaction }) {
this.name = 'Transaction';
this.tag = Buffer.from('TX');
// Populate defaults
const defaults = {
type: types_1.TransactionType.pay,
flatFee: false,
nonParticipation: false,
};
// Default type
if (typeof transaction.type === 'undefined') {
transaction.type = defaults.type;
}
// Default flatFee
if (typeof transaction.flatFee ===
'undefined') {
transaction.flatFee =
defaults.flatFee;
}
// Move suggested parameters from its object to inline
if (transaction.suggestedParams !== undefined) {
// Create a temporary reference to the transaction object that has params inline and also as a suggested params object
// - Helpful for moving params from named object to inline
const reference = transaction;
reference.genesisHash = reference.suggestedParams.genesisHash;
reference.fee = reference.suggestedParams.fee;
if (reference.suggestedParams.flatFee !== undefined)
reference.flatFee = reference.suggestedParams.flatFee;
reference.firstRound = reference.suggestedParams.firstRound;
reference.lastRound = reference.suggestedParams.lastRound;
reference.genesisID = reference.suggestedParams.genesisID;
}
// At this point all suggestedParams have been moved to be inline, so we can reassign the transaction object type
// to one which is more useful as we prepare properties for storing
const txn = transaction;
txn.from = address.decodeAddress(txn.from);
if (txn.to !== undefined)
txn.to = address.decodeAddress(txn.to);
if (txn.closeRemainderTo !== undefined)
txn.closeRemainderTo = address.decodeAddress(txn.closeRemainderTo);
if (txn.assetRevocationTarget !== undefined)
txn.assetRevocationTarget = address.decodeAddress(txn.assetRevocationTarget);
if (txn.reKeyTo !== undefined)
txn.reKeyTo = address.decodeAddress(txn.reKeyTo);
if (txn.genesisHash === undefined)
throw Error('genesis hash must be specified and in a base64 string.');
txn.genesisHash = Buffer.from(txn.genesisHash, 'base64');
if (txn.amount !== undefined &&
(!(Number.isSafeInteger(txn.amount) ||
(typeof txn.amount === 'bigint' &&
txn.amount <= BigInt('0xffffffffffffffff'))) ||
txn.amount < 0))
throw Error('Amount must be a positive number and smaller than 2^64-1');
if (!Number.isSafeInteger(txn.fee) || txn.fee < 0)
throw Error('fee must be a positive number and smaller than 2^53-1');
if (!Number.isSafeInteger(txn.firstRound) || txn.firstRound < 0)
throw Error('firstRound must be a positive number');
if (!Number.isSafeInteger(txn.lastRound) || txn.lastRound < 0)
throw Error('lastRound must be a positive number');
if (txn.extraPages !== undefined &&
(!Number.isInteger(txn.extraPages) ||
txn.extraPages < 0 ||
txn.extraPages > 3))
throw Error('extraPages must be an Integer between and including 0 to 3');
if (txn.assetIndex !== undefined &&
(!Number.isSafeInteger(txn.assetIndex) || txn.assetIndex < 0))
throw Error('Asset index must be a positive number and smaller than 2^53-1');
if (txn.note !== undefined) {
if (txn.note.constructor !== Uint8Array)
throw Error('note must be a Uint8Array.');
}
else {
txn.note = new Uint8Array(0);
}
if (txn.lease !== undefined) {
if (txn.lease.constructor !== Uint8Array)
throw Error('lease must be a Uint8Array.');
if (txn.lease.length !== ALGORAND_TRANSACTION_LEASE_LENGTH)
throw Error(`lease must be of length ${ALGORAND_TRANSACTION_LEASE_LENGTH.toString()}.`);
if (txn.lease.every((value) => value === 0)) {
// if lease contains all 0s, omit it
txn.lease = new Uint8Array(0);
}
}
else {
txn.lease = new Uint8Array(0);
}
// Remove unwanted properties and store transaction on instance
delete txn.suggestedParams;
Object.assign(this, utils.removeUndefinedProperties(txn));
// Modify Fee
if (!txn.flatFee) {
this.fee *= this.estimateSize();
// If suggested fee too small and will be rejected, set to min tx fee
if (this.fee < exports.ALGORAND_MIN_TX_FEE) {
this.fee = exports.ALGORAND_MIN_TX_FEE;
}
}
// say we are aware of groups
this.group = undefined;
}
// eslint-disable-next-line camelcase
get_obj_for_encoding() {
var _a, _b, _c, _d;
if (this.type === 'pay') {
const txn = {
amt: this.amount,
fee: this.fee,
fv: this.firstRound,
lv: this.lastRound,
note: Buffer.from(this.note),
snd: Buffer.from(this.from.publicKey),
type: 'pay',
gen: this.genesisID,
gh: this.genesisHash,
lx: Buffer.from(this.lease),
grp: this.group,
};
// parse close address
if (this.closeRemainderTo !== undefined &&
address.encodeAddress(this.closeRemainderTo.publicKey) !==
address.ALGORAND_ZERO_ADDRESS_STRING) {
txn.close = Buffer.from(this.closeRemainderTo.publicKey);
}
if (this.reKeyTo !== undefined) {
txn.rekey = Buffer.from(this.reKeyTo.publicKey);
}
// allowed zero values
if (this.to !== undefined)
txn.rcv = Buffer.from(this.to.publicKey);
if (!((_a = txn.note) === null || _a === void 0 ? void 0 : _a.length))
delete txn.note;
if (!txn.amt)
delete txn.amt;
if (!txn.fee)
delete txn.fee;
if (!txn.fv)
delete txn.fv;
if (!txn.gen)
delete txn.gen;
if (txn.grp === undefined)
delete txn.grp;
if (!((_b = txn.lx) === null || _b === void 0 ? void 0 : _b.length))
delete txn.lx;
if (!txn.rekey)
delete txn.rekey;
return txn;
}
if (this.type === 'axfer') {
// asset transfer, acceptance, revocation, mint, or burn
const txn = {
aamt: this.amount,
fee: this.fee,
fv: this.firstRound,
lv: this.lastRound,
note: Buffer.from(this.note),
snd: Buffer.from(this.from.publicKey),
arcv: Buffer.from(this.to.publicKey),
type: this.type,
gen: this.genesisID,
gh: this.genesisHash,
lx: Buffer.from(this.lease),
grp: this.group,
xaid: this.assetIndex,
};
if (this.closeRemainderTo !== undefined)
txn.aclose = Buffer.from(this.closeRemainderTo.publicKey);
if (this.assetRevocationTarget !== undefined)
txn.asnd = Buffer.from(this.assetRevocationTarget.publicKey);
// allowed zero values
if (!((_c = txn.note) === null || _c === void 0 ? void 0 : _c.length))
delete txn.note;
if (!((_d = txn.lx) === null || _d === void 0 ? void 0 : _d.length))
delete txn.lx;
if (!txn.aamt)
delete txn.aamt;
if (!txn.amt)
delete txn.amt;
if (!txn.fee)
delete txn.fee;
if (!txn.fv)
delete txn.fv;
if (!txn.gen)
delete txn.gen;
if (txn.grp === undefined)
delete txn.grp;
if (!txn.aclose)
delete txn.aclose;
if (!txn.asnd)
delete txn.asnd;
if (!txn.rekey)
delete txn.rekey;
if (this.reKeyTo !== undefined) {
txn.rekey = Buffer.from(this.reKeyTo.publicKey);
}
return txn;
}
return undefined;
}
estimateSize() {
return this.toByte().length + NUM_ADDL_BYTES_AFTER_SIGNING;
}
bytesToSign() {
const encodedMsg = this.toByte();
return Buffer.from(utils.concatArrays(this.tag, encodedMsg));
}
toByte() {
return encoding.encode(this.get_obj_for_encoding());
}
rawTxID() {
const enMsg = this.toByte();
const gh = Buffer.from(utils.concatArrays(this.tag, enMsg));
return Buffer.from(nacl.genericHash(gh));
}
txID() {
const hash = this.rawTxID();
return hi_base32_1.default.encode(hash).slice(0, ALGORAND_TRANSACTION_LENGTH);
}
}
exports.Transaction = Transaction;
exports.default = Transaction;
//# sourceMappingURL=transaction.js.map