@harmony-js/transaction
Version:
transaction package for harmony
359 lines • 15.3 kB
JavaScript
"use strict";
/**
* @packageDocumentation
* @module harmony-transaction
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.Transaction = void 0;
var tslib_1 = require("tslib");
var crypto_1 = require("@harmony-js/crypto");
var utils_1 = require("@harmony-js/utils");
var network_1 = require("@harmony-js/network");
var types_1 = require("./types");
var utils_2 = require("./utils");
var transactionBase_1 = require("./transactionBase");
var Transaction = /** @class */ (function (_super) {
tslib_1.__extends(Transaction, _super);
/**
*
* @Params
* ```javascript
* id: string;
from: string;
to: string;
nonce: number | string;
gasLimit: number | string | BN;
gasPrice: number | string | BN;
shardID: number | string;
toShardID: number | string;
data: string;
value: number | string | BN;
chainId: number;
rawTransaction: string;
unsignedRawTransaction: string;
signature: Signature;
receipt?: TransasctionReceipt;
* ```
*/
function Transaction(params, messenger, txStatus) {
if (messenger === void 0) { messenger = utils_2.defaultMessenger; }
if (txStatus === void 0) { txStatus = types_1.TxStatus.INTIALIZED; }
var _this = _super.call(this, messenger, txStatus) || this;
// intialize transaction
_this.id = params && params.id ? params.id : '0x';
_this.from = params && params.from ? params.from : '0x';
_this.nonce = params && params.nonce ? params.nonce : 0;
_this.gasPrice =
params && params.gasPrice
? new utils_1.Unit(params.gasPrice).asWei().toWei()
: new utils_1.Unit(0).asWei().toWei();
_this.gasLimit =
params && params.gasLimit
? new utils_1.Unit(params.gasLimit).asWei().toWei()
: new utils_1.Unit(0).asWei().toWei();
_this.shardID =
params && params.shardID !== undefined ? params.shardID : _this.messenger.currentShard;
_this.toShardID =
params && params.toShardID !== undefined ? params.toShardID : _this.messenger.currentShard;
_this.to = params && params.to ? Transaction.normalizeAddress(params.to) : '0x';
_this.value =
params && params.value ? new utils_1.Unit(params.value).asWei().toWei() : new utils_1.Unit(0).asWei().toWei();
_this.data = params && params.data ? params.data : '0x';
// chainid should change with different network settings
_this.chainId = params && params.chainId ? params.chainId : _this.messenger.chainId;
_this.rawTransaction = params && params.rawTransaction ? params.rawTransaction : '0x';
_this.unsignedRawTransaction =
params && params.unsignedRawTransaction ? params.unsignedRawTransaction : '0x';
_this.signature =
params && params.signature
? params.signature
: {
r: '',
s: '',
recoveryParam: 0,
v: 0,
};
_this.receipt = params && params.receipt ? params.receipt : undefined;
_this.cxStatus = _this.isCrossShard() ? types_1.TxStatus.INTIALIZED : types_1.TxStatus.NONE;
return _this;
}
/**
*
* @example
* ```javascript
* const unsigned = txn.getRLPUnsigned(txn);
* console.log(unsigned);
* ```
*/
Transaction.prototype.getRLPUnsigned = function () {
var _this = this;
var raw = [];
// temp setting to be compatible with eth
var fields = this.messenger.chainType === utils_1.ChainType.Harmony ? utils_2.transactionFields : utils_2.transactionFieldsETH;
fields.forEach(function (field) {
var value = _this.txParams[field.name] || [];
value = crypto_1.arrayify(crypto_1.hexlify(field.transform === 'hex' ? utils_1.add0xToString(value.toString(16)) : value));
// Fixed-width field
if (field.fix === true && field.length && value.length !== field.length && value.length > 0) {
throw new Error("invalid length for " + field.name);
}
// Variable-width (with a maximum)
if (field.fix === false && field.length) {
value = crypto_1.stripZeros(value);
if (value.length > field.length) {
throw new Error("invalid length for " + field.name);
}
}
raw.push(crypto_1.hexlify(value));
});
if (this.txParams.chainId != null && this.txParams.chainId !== 0) {
raw.push(crypto_1.hexlify(this.txParams.chainId));
raw.push('0x');
raw.push('0x');
}
return [crypto_1.encode(raw), raw];
};
Transaction.prototype.getRLPSigned = function (raw, signature) {
// temp setting to be compatible with eth
var rawLength = this.messenger.chainType === utils_1.ChainType.Harmony ? 11 : 9;
var sig = crypto_1.splitSignature(signature);
var v = 27 + (sig.recoveryParam || 0);
if (raw.length === rawLength) {
raw.pop();
raw.pop();
raw.pop();
v += this.chainId * 2 + 8;
}
raw.push(crypto_1.hexlify(v));
raw.push(crypto_1.stripZeros(crypto_1.arrayify(sig.r) || []));
raw.push(crypto_1.stripZeros(crypto_1.arrayify(sig.s) || []));
return crypto_1.encode(raw);
};
/**
* @example
* ```javascript
* console.log(txn.getRawTransaction());
* ```
*/
Transaction.prototype.getRawTransaction = function () {
return this.rawTransaction;
};
/** @hidden */
Transaction.prototype.recover = function (rawTransaction) {
// temp setting to be compatible with eth
var recovered = this.messenger.chainType === utils_1.ChainType.Harmony
? utils_2.recover(rawTransaction)
: utils_2.recoverETH(rawTransaction);
this.setParams(recovered);
return this;
};
Object.defineProperty(Transaction.prototype, "txPayload", {
/**
* get the payload of transaction
*
* @example
* ```
* const payload = txn.txPayload;
* console.log(payload);
* ```
*/
get: function () {
return {
from: this.txParams.from || '0x',
to: this.txParams.to || '0x',
shardID: this.txParams.shardID ? utils_1.numberToHex(this.shardID) : '0x',
toShardID: this.txParams.toShardID ? utils_1.numberToHex(this.toShardID) : '0x',
gas: this.txParams.gasLimit ? utils_1.numberToHex(this.txParams.gasLimit) : '0x',
gasPrice: this.txParams.gasPrice ? utils_1.numberToHex(this.txParams.gasPrice) : '0x',
value: this.txParams.value ? utils_1.numberToHex(this.txParams.value) : '0x',
data: this.txParams.data || '0x',
nonce: this.txParams.nonce ? utils_1.numberToHex(this.nonce) : '0x',
};
},
enumerable: false,
configurable: true
});
Object.defineProperty(Transaction.prototype, "txParams", {
/**
* get transaction params
*
* @example
* ```
* const txParams = txn.txParams;
* console.log(txParams)
* ```
*/
get: function () {
return {
id: this.id || '0x',
from: this.from || '',
nonce: this.nonce || 0,
gasPrice: this.gasPrice || new utils_1.Unit(0).asWei().toWei(),
gasLimit: this.gasLimit || new utils_1.Unit(0).asWei().toWei(),
shardID: this.shardID !== undefined ? this.shardID : this.messenger.currentShard,
toShardID: this.toShardID !== undefined ? this.toShardID : this.messenger.currentShard,
to: Transaction.normalizeAddress(this.to) || '0x',
value: this.value || new utils_1.Unit(0).asWei().toWei(),
data: this.data || '0x',
chainId: this.chainId || 0,
rawTransaction: this.rawTransaction || '0x',
unsignedRawTransaction: this.unsignedRawTransaction || '0x',
signature: this.signature || '0x',
};
},
enumerable: false,
configurable: true
});
/**
* set the params to the txn
*
* @example
* ```
* txn.setParams({
* to: 'one1ew56rqrucu6p6n598fmjmnfh8dd4xpg6atne9c',
* value: '1200',
* gasLimit: '230000',
* shardID: 1,
* toShardID: 0,
* gasPrice: new hmy.utils.Unit('101').asGwei().toWei(),
* signature: {
* r: '0xd693b532a80fed6392b428604171fb32fdbf953728a3a7ecc7d4062b1652c042',
* s: '0x24e9c602ac800b983b035700a14b23f78a253ab762deab5dc27e3555a750b354',
* v: 0
* },
* });
* console.log(txn);
* ```
*/
Transaction.prototype.setParams = function (params) {
this.id = params && params.id ? params.id : '0x';
this.from = params && params.from ? params.from : '0x';
this.nonce = params && params.nonce ? params.nonce : 0;
this.gasPrice =
params && params.gasPrice
? new utils_1.Unit(params.gasPrice).asWei().toWei()
: new utils_1.Unit(0).asWei().toWei();
this.gasLimit =
params && params.gasLimit
? new utils_1.Unit(params.gasLimit).asWei().toWei()
: new utils_1.Unit(0).asWei().toWei();
this.shardID =
params && params.shardID !== undefined ? params.shardID : this.messenger.currentShard;
this.toShardID =
params && params.toShardID !== undefined ? params.toShardID : this.messenger.currentShard;
this.to = params && params.to ? Transaction.normalizeAddress(params.to) : '0x';
this.value =
params && params.value ? new utils_1.Unit(params.value).asWei().toWei() : new utils_1.Unit(0).asWei().toWei();
this.data = params && params.data ? params.data : '0x';
this.chainId = params && params.chainId ? params.chainId : 0;
this.rawTransaction = params && params.rawTransaction ? params.rawTransaction : '0x';
this.unsignedRawTransaction =
params && params.unsignedRawTransaction ? params.unsignedRawTransaction : '0x';
this.signature =
params && params.signature
? params.signature
: {
r: '',
s: '',
recoveryParam: 0,
v: 0,
};
if (this.rawTransaction !== '0x') {
this.setTxStatus(types_1.TxStatus.SIGNED);
}
else {
this.setTxStatus(types_1.TxStatus.INTIALIZED);
}
};
/** @hidden */
Transaction.prototype.map = function (fn) {
var newParams = fn(this.txParams);
this.setParams(newParams);
return this;
};
/**
* Check whether the transaction is cross shard
*
* @example
* ```javascript
* console.log(txn.isCrossShard());
* ```
*/
Transaction.prototype.isCrossShard = function () {
return new crypto_1.BN(this.txParams.shardID).toString() !== new crypto_1.BN(this.txParams.toShardID).toString();
};
/**
*
* @example
* ```
* txn.sendTransaction().then((value) => {
* console.log(value);
* });
* ```
*/
Transaction.prototype.sendTransaction = function () {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var res;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
if (this.rawTransaction === 'tx' || this.rawTransaction === undefined) {
throw new Error('Transaction not signed');
}
if (!this.messenger) {
throw new Error('Messenger not found');
}
return [4 /*yield*/, this.messenger.send(network_1.RPCMethod.SendRawTransaction, this.rawTransaction, this.messenger.chainType, typeof this.shardID === 'string' ? Number.parseInt(this.shardID, 10) : this.shardID)];
case 1:
res = _a.sent();
// temporarilly hard coded
if (res.isResult()) {
this.id = res.result;
this.emitTransactionHash(this.id);
this.setTxStatus(types_1.TxStatus.PENDING);
// await this.confirm(this.id, 20, 1000);
return [2 /*return*/, [this, res.result]];
}
else if (res.isError()) {
this.emitConfirm("transaction failed:" + res.error.message);
this.setTxStatus(types_1.TxStatus.REJECTED);
return [2 /*return*/, [this, "transaction failed:" + res.error.message]];
}
else {
this.emitError('transaction failed');
throw new Error('transaction failed');
}
return [2 /*return*/];
}
});
});
};
Transaction.prototype.confirm = function (txHash, maxAttempts, interval, shardID, toShardID) {
if (maxAttempts === void 0) { maxAttempts = 20; }
if (interval === void 0) { interval = 1000; }
if (shardID === void 0) { shardID = this.txParams.shardID; }
if (toShardID === void 0) { toShardID = this.txParams.toShardID; }
return tslib_1.__awaiter(this, void 0, void 0, function () {
var txConfirmed, cxConfirmed;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.txConfirm(txHash, maxAttempts, interval, shardID)];
case 1:
txConfirmed = _a.sent();
if (!this.isCrossShard()) {
return [2 /*return*/, txConfirmed];
}
if (!txConfirmed.isConfirmed()) return [3 /*break*/, 3];
return [4 /*yield*/, this.cxConfirm(txHash, maxAttempts, interval, toShardID)];
case 2:
cxConfirmed = _a.sent();
return [2 /*return*/, cxConfirmed];
case 3: return [2 /*return*/, txConfirmed];
}
});
});
};
return Transaction;
}(transactionBase_1.TransactionBase));
exports.Transaction = Transaction;
//# sourceMappingURL=transaction.js.map