@ledgerhq/coin-tron
Version:
Ledger Tron Coin integration
302 lines • 11.9 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createTronWeb = createTronWeb;
exports.decodeTransaction = decodeTransaction;
exports.getTronResources = getTronResources;
const crypto_1 = require("crypto");
const tronweb_1 = __importDefault(require("tronweb"));
const config_1 = __importDefault(require("../config"));
const get_1 = __importDefault(require("lodash/get"));
const bignumber_js_1 = __importDefault(require("bignumber.js"));
function createTronWeb(trongridUrl) {
if (!trongridUrl) {
trongridUrl = config_1.default.getCoinConfig().explorer.url;
}
const HttpProvider = tronweb_1.default.providers.HttpProvider;
const fullNode = new HttpProvider(trongridUrl);
const solidityNode = new HttpProvider(trongridUrl);
const eventServer = new HttpProvider(trongridUrl);
return new tronweb_1.default(fullNode, solidityNode, eventServer);
}
/**
* Convert `raw_data_hex` value from {@link https://developers.tron.network/reference/createtransaction|createTransaction API} to `raw_data` value.
* The function try to find the correct Protobuf deserialization to use for inner (Contract)[] object.
* @param rawTx
* @returns
*/
async function decodeTransaction(rawTx) {
const { Transaction } = globalThis.TronWebProto;
const transaction = Transaction.raw.deserializeBinary(Buffer.from(rawTx, "hex"));
return {
txID: (0, crypto_1.createHash)("sha256").update(Buffer.from(rawTx, "hex")).digest("hex"),
raw_data: convertTxFromRaw(transaction),
raw_data_hex: rawTx,
};
}
/**
* @see https://github.com/tronprotocol/protocol/blob/master/core/Tron.proto#L431
* @param tx
*/
function convertTxFromRaw(tx) {
let transactionRawData = {
ref_block_bytes: convertBufferToHex(tx.getRefBlockBytes()),
ref_block_hash: convertBufferToHex(tx.getRefBlockHash()),
expiration: tx.getExpiration(),
contract: tx.getContractList().map(convertContractFromRaw),
timestamp: tx.getTimestamp(),
};
if (tx.getRefBlockNum()) {
transactionRawData = {
...transactionRawData,
ref_block_num: tx.getRefBlockNum(),
};
}
if (tx.getFeeLimit()) {
transactionRawData = {
...transactionRawData,
fee_limit: tx.getFeeLimit(),
};
}
if (tx.getData()) {
transactionRawData = {
...transactionRawData,
data: tx.getData(),
};
}
if (tx.getScripts()) {
transactionRawData = {
...transactionRawData,
scripts: tx.getScripts(),
};
}
return transactionRawData;
}
/**
* @see https://github.com/tronprotocol/protocol/blob/master/core/contract/balance_contract.proto#L32
* @param contract
*/
function convertContractFromRaw(contract) {
let value;
switch (contract.getType()) {
case 1:
value = convertTransferContractFromRaw(contract);
break;
case 2:
value = convertTransferAssetContractFromRaw(contract);
break;
case 31:
value = convertTriggerSmartContractFromRaw(contract);
break;
default:
throw new Error(`Missing deserializer for this contract: "${contract.getParameter().getTypeUrl()}"`);
}
return {
type: convertNumberToContractType(contract.getType()),
parameter: {
value,
type_url: contract.getParameter().getTypeUrl(),
},
// provider: contract.getProvider(),
// Permission_id: contract.getPermissionId(),
};
}
function convertTransferContractFromRaw(contract) {
const { TransferContract } = globalThis.TronWebProto;
const transferContract = TransferContract.deserializeBinary(contract.getParameter().getValue());
// Expected address format in Contract are in Hex and not in Base58,
// despite what (tron API portal may say)[https://developers.tron.network/reference/createtransaction]
return {
amount: transferContract.getAmount(),
owner_address: convertBufferToHex(transferContract.getOwnerAddress()),
to_address: convertBufferToHex(transferContract.getToAddress()),
};
}
function convertTransferAssetContractFromRaw(contract) {
const { TransferAssetContract } = globalThis.TronWebProto;
const transferContract = TransferAssetContract.deserializeBinary(contract.getParameter().getValue());
// Expected address format in Contract are in Hex and not in Base58,
// despite what (tron API portal may say)[https://developers.tron.network/reference/transferasset]
return {
amount: transferContract.getAmount(),
asset_name: convertBufferToString(transferContract.getAssetName()),
owner_address: convertBufferToHex(transferContract.getOwnerAddress()),
to_address: convertBufferToHex(transferContract.getToAddress()),
};
}
function convertTriggerSmartContractFromRaw(contract) {
const { TriggerSmartContract } = globalThis.TronWebProto;
const transferContract = TriggerSmartContract.deserializeBinary(contract.getParameter().getValue());
// Expected address format in Contract are in Hex and not in Base58,
// despite what (tron API portal may say)[https://developers.tron.network/reference/triggersmartcontract]
return {
data: convertBufferToHex(transferContract.getData()),
owner_address: convertBufferToHex(transferContract.getOwnerAddress()),
contract_address: convertBufferToHex(transferContract.getContractAddress()),
};
}
/**
* @see https://github.com/tronprotocol/protocol/blob/master/core/Tron.proto#L338
*/
const CONTRACT_TYPE = {
0: "AccountCreateContract",
1: "TransferContract",
2: "TransferAssetContract",
3: "VoteAssetContract",
4: "VoteWitnessContract",
5: "WitnessCreateContract",
6: "AssetIssueContract",
8: "WitnessUpdateContract",
9: "ParticipateAssetIssueContract",
10: "AccountUpdateContract",
11: "FreezeBalanceContract",
12: "UnfreezeBalanceContract",
13: "WithdrawBalanceContract",
14: "UnfreezeAssetContract",
15: "UpdateAssetContract",
16: "ProposalCreateContract",
17: "ProposalApproveContract",
18: "ProposalDeleteContract",
19: "SetAccountIdContract",
20: "CustomContract",
30: "CreateSmartContract",
31: "TriggerSmartContract",
32: "GetContract",
33: "UpdateSettingContract",
41: "ExchangeCreateContract",
42: "ExchangeInjectContract",
43: "ExchangeWithdrawContract",
44: "ExchangeTransactionContract",
45: "UpdateEnergyLimitContract",
46: "AccountPermissionUpdateContract",
48: "ClearABIContract",
49: "UpdateBrokerageContract",
51: "ShieldedTransferContract",
52: "MarketSellAssetContract",
53: "MarketCancelOrderContract",
54: "FreezeBalanceV2Contract",
55: "UnfreezeBalanceV2Contract",
56: "WithdrawExpireUnfreezeContract",
57: "DelegateResourceContract",
58: "UnDelegateResourceContract",
59: "CancelAllUnfreezeV2Contract",
};
const convertNumberToContractType = (value) => CONTRACT_TYPE[value];
/**
* Convert for instance: "41FD49EDA0F23FF7EC1D03B52C3A45991C24CD440E" to "TZ4UXDV5ZhNW7fb2AMSbgfAEZ7hWsnYS2g"
* @param address
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
function convertHexToBase58(address) {
return tronweb_1.default.address.fromHex(address);
}
function convertBufferToHex(address) {
return tronweb_1.default.utils.bytes.byteArray2hexStr(address).toLowerCase();
}
function convertBufferToString(address) {
return tronweb_1.default.utils.bytes.bytesToString(address);
}
function getTronResources(acc) {
const delegatedFrozenBandwidth = (0, get_1.default)(acc, "delegated_frozenV2_balance_for_bandwidth", undefined);
const delegatedFrozenEnergy = (0, get_1.default)(acc, "account_resource.delegated_frozenV2_balance_for_energy", undefined);
const frozenBalances = (0, get_1.default)(acc, "frozenV2", []);
const legacyFrozenBandwidth = (0, get_1.default)(acc, "frozen[0]", undefined);
const legacyFrozenEnergy = (0, get_1.default)(acc, "account_resource.frozen_balance_for_energy", undefined);
const legacyFrozen = {
bandwidth: legacyFrozenBandwidth
? {
amount: new bignumber_js_1.default(legacyFrozenBandwidth.frozen_balance),
expiredAt: new Date(legacyFrozenBandwidth.expire_time),
}
: undefined,
energy: legacyFrozenEnergy
? {
amount: new bignumber_js_1.default(legacyFrozenEnergy.frozen_balance),
expiredAt: new Date(legacyFrozenEnergy.expire_time),
}
: undefined,
};
const { frozenEnergy, frozenBandwidth } = frozenBalances.reduce((accum, cur) => {
const amount = new bignumber_js_1.default(cur?.amount ?? 0);
if (cur.type === "ENERGY") {
accum.frozenEnergy = accum.frozenEnergy.plus(amount);
}
else if (cur.type === undefined) {
accum.frozenBandwidth = accum.frozenBandwidth.plus(amount);
}
return accum;
}, {
frozenEnergy: new bignumber_js_1.default(0),
frozenBandwidth: new bignumber_js_1.default(0),
});
const unFrozenBalances = (0, get_1.default)(acc, "unfrozenV2", []);
const unFrozen = unFrozenBalances
? unFrozenBalances.reduce((accum, cur) => {
if (cur && cur.type === "ENERGY") {
accum.energy.push({
amount: new bignumber_js_1.default(cur.unfreeze_amount),
expireTime: new Date(cur.unfreeze_expire_time),
});
}
else if (cur) {
accum.bandwidth.push({
amount: new bignumber_js_1.default(cur.unfreeze_amount),
expireTime: new Date(cur.unfreeze_expire_time),
});
}
return accum;
}, { bandwidth: [], energy: [] })
: { bandwidth: [], energy: [] };
const frozen = {
bandwidth: frozenBandwidth.isGreaterThan(0)
? {
amount: frozenBandwidth,
}
: undefined,
energy: frozenEnergy.isGreaterThan(0)
? {
amount: frozenEnergy,
}
: undefined,
};
const delegatedFrozen = {
bandwidth: delegatedFrozenBandwidth
? {
amount: new bignumber_js_1.default(delegatedFrozenBandwidth),
}
: undefined,
energy: delegatedFrozenEnergy
? {
amount: new bignumber_js_1.default(delegatedFrozenEnergy),
}
: undefined,
};
const tronPower = new bignumber_js_1.default((0, get_1.default)(frozen, "bandwidth.amount", 0))
.plus((0, get_1.default)(frozen, "energy.amount", 0))
.plus((0, get_1.default)(delegatedFrozen, "bandwidth.amount", 0))
.plus((0, get_1.default)(delegatedFrozen, "energy.amount", 0))
.plus((0, get_1.default)(legacyFrozen, "energy.amount", 0))
.plus((0, get_1.default)(legacyFrozen, "bandwidth.amount", 0))
.dividedBy(1_000_000)
.integerValue(bignumber_js_1.default.ROUND_FLOOR)
.toNumber();
const votes = (0, get_1.default)(acc, "votes", []).map((v) => ({
address: v.vote_address,
voteCount: v.vote_count,
}));
const lastWithdrawnRewardDate = acc.latest_withdraw_time
? new Date(acc.latest_withdraw_time)
: undefined;
return {
frozen,
unFrozen,
delegatedFrozen,
legacyFrozen,
votes,
tronPower,
lastWithdrawnRewardDate,
};
}
//# sourceMappingURL=utils.js.map