@ledgerhq/coin-filecoin
Version:
Ledger Filecoin Coin integration
180 lines • 6.91 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.valueFromUnit = exports.getSubAccount = exports.getAccountShape = exports.getTxToBroadcast = exports.getAddress = exports.mapTxToOps = exports.processTxs = exports.getUnit = void 0;
const logs_1 = require("@ledgerhq/logs");
const currencies_1 = require("@ledgerhq/coin-framework/currencies");
const cryptoassets_1 = require("@ledgerhq/cryptoassets");
const bignumber_js_1 = require("bignumber.js");
const types_1 = require("../types");
const api_1 = require("../api/api");
const account_1 = require("@ledgerhq/coin-framework/account");
const operation_1 = require("@ledgerhq/coin-framework/operation");
const flatMap_1 = __importDefault(require("lodash/flatMap"));
const tokenAccounts_1 = require("../erc20/tokenAccounts");
const getUnit = () => (0, cryptoassets_1.getCryptoCurrencyById)("filecoin").units[0];
exports.getUnit = getUnit;
const processTxs = (txs) => {
// Group all tx types related to same tx cid into the same object
const txsByTxCid = txs.reduce((txsByTxCidResult, currentTx) => {
const { hash: txCid, type: txType } = currentTx;
const txByType = txsByTxCidResult[txCid] || {};
switch (txType) {
case "Send":
txByType.Send = currentTx;
break;
case "InvokeContract":
txByType.InvokeContract = currentTx;
break;
case "Fee":
txByType.Fee = currentTx;
break;
default:
(0, logs_1.log)("warn", `tx type [${txType}] on tx cid [${txCid}] was not recognized.`);
break;
}
txsByTxCidResult[txCid] = txByType;
return txsByTxCidResult;
}, {});
// Once all tx types have been grouped, we want to find
const processedTxs = [];
for (const txCid in txsByTxCid) {
const item = txsByTxCid[txCid];
const feeTx = item.Fee;
let mainTx;
if ("Send" in item) {
mainTx = item.Send;
}
else if ("InvokeContract" in item) {
mainTx = item.InvokeContract;
}
else {
(0, logs_1.log)("warn", `unexpected tx type, tx with cid [${txCid}] and payload [${JSON.stringify(item)}]`);
}
if (!mainTx) {
if (feeTx) {
(0, logs_1.log)("warn", `feeTx [${feeTx.hash}] found without a mainTx linked to it.`);
}
continue;
}
if (feeTx) {
mainTx.fee = feeTx.amount;
}
processedTxs.push(mainTx);
}
return processedTxs;
};
exports.processTxs = processTxs;
const mapTxToOps = (accountId, { address }) => (tx) => {
const { to, from, hash, timestamp, amount, fee, status } = tx;
const ops = [];
const date = new Date(timestamp * 1000);
const value = (0, currencies_1.parseCurrencyUnit)((0, exports.getUnit)(), amount.toString());
const feeToUse = (0, currencies_1.parseCurrencyUnit)((0, exports.getUnit)(), (fee || 0).toString());
const isSending = address === from;
const isReceiving = address === to;
const hasFailed = status !== types_1.TxStatus.Ok;
if (isSending) {
const type = value.eq(0) ? "FEES" : "OUT";
ops.push({
id: (0, operation_1.encodeOperationId)(accountId, hash, type),
hash,
type,
value: value.plus(feeToUse),
fee: feeToUse,
blockHeight: tx.height,
blockHash: null,
accountId,
senders: [from],
recipients: [to],
date,
extra: {},
hasFailed,
});
}
if (isReceiving) {
const type = value.eq(0) ? "FEES" : "IN";
ops.push({
id: (0, operation_1.encodeOperationId)(accountId, hash, type),
hash,
type,
value,
fee: feeToUse,
blockHeight: tx.height,
blockHash: null,
accountId,
senders: [from],
recipients: [to],
date,
extra: {},
hasFailed,
});
}
return ops;
};
exports.mapTxToOps = mapTxToOps;
const getAddress = (a) => ({ address: a.freshAddress, derivationPath: a.freshAddressPath });
exports.getAddress = getAddress;
const getTxToBroadcast = (operation, signature, rawData) => {
const { sender, recipient, gasLimit, gasFeeCap, gasPremium, method, version, nonce, signatureType, params, value, } = rawData;
return {
message: {
version,
method,
nonce,
params: params ?? "",
to: recipient,
from: sender,
gaslimit: gasLimit.toNumber(),
gaspremium: gasPremium.toString(),
gasfeecap: gasFeeCap.toString(),
value,
},
signature: {
type: signatureType,
data: signature,
},
};
};
exports.getTxToBroadcast = getTxToBroadcast;
const getAccountShape = async (info) => {
const { address, currency, derivationMode } = info;
const accountId = (0, account_1.encodeAccountId)({
type: "js",
version: "2",
currencyId: currency.id,
xpubOrAddress: address,
derivationMode,
});
const blockHeight = await (0, api_1.fetchBlockHeight)();
const balance = await (0, api_1.fetchBalances)(address);
const rawTxs = await (0, api_1.fetchTxs)(address);
const tokenAccounts = await (0, tokenAccounts_1.buildTokenAccounts)(address, accountId, info.initialAccount);
const result = {
id: accountId,
subAccounts: tokenAccounts,
balance: new bignumber_js_1.BigNumber(balance.total_balance),
spendableBalance: new bignumber_js_1.BigNumber(balance.spendable_balance),
operations: (0, flatMap_1.default)((0, exports.processTxs)(rawTxs), (0, exports.mapTxToOps)(accountId, info)).sort((a, b) => b.date.getTime() - a.date.getTime()),
blockHeight: blockHeight.current_block_identifier.index,
};
return result;
};
exports.getAccountShape = getAccountShape;
const getSubAccount = (account, tx) => {
const subAccount = tx.subAccountId && account.subAccounts
? account.subAccounts.find(sa => sa.id === tx.subAccountId)
: null;
return subAccount;
};
exports.getSubAccount = getSubAccount;
/**
* convert a value in a given unit to a normalized value
* For instance, for 1 BTC, valueFromUnit(1, btcUnit) returns 100000000
* @memberof countervalue
*/
const valueFromUnit = (valueInUnit, unit) => valueInUnit.times(new bignumber_js_1.BigNumber(10).pow(unit.magnitude));
exports.valueFromUnit = valueFromUnit;
//# sourceMappingURL=utils.js.map