UNPKG

@ledgerhq/coin-multiversx

Version:
283 lines 12.2 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.broadcastTransaction = exports.getFees = exports.getESDTOperations = exports.hasESDTTokens = exports.getAccountDelegations = exports.getAccountESDTTokens = exports.getEGLDOperations = exports.getAccountNonce = exports.getNetworkConfig = exports.getProviders = exports.getAccount = void 0; const operation_1 = require("@ledgerhq/coin-framework/operation"); const index_1 = require("@ledgerhq/coin-framework/serialization/index"); const cryptoassets_1 = require("@ledgerhq/cryptoassets"); const live_env_1 = require("@ledgerhq/live-env"); const sdk_core_1 = require("@multiversx/sdk-core"); const bignumber_js_1 = require("bignumber.js"); const constants_1 = require("../constants"); const types_1 = require("../types"); const binary_utils_1 = require("../utils/binary.utils"); const apiCalls_1 = __importDefault(require("./apiCalls")); const multiversx_account_1 = require("./dtos/multiversx-account"); const api = new apiCalls_1.default((0, live_env_1.getEnv)("MULTIVERSX_API_ENDPOINT"), (0, live_env_1.getEnv)("MULTIVERSX_DELEGATION_API_ENDPOINT")); const networkConfig = { clientName: "ledger-live" }; const proxy = new sdk_core_1.ApiNetworkProvider((0, live_env_1.getEnv)("MULTIVERSX_API_ENDPOINT"), networkConfig); /** * Get account balances and nonce */ const getAccount = async (addr) => { const { balance, nonce, isGuarded } = await api.getAccountDetails(addr); const blockHeight = await api.getBlockchainBlockHeight(); const account = new multiversx_account_1.MultiversXAccount(new bignumber_js_1.BigNumber(balance), nonce, isGuarded, blockHeight); return account; }; exports.getAccount = getAccount; const getProviders = async () => { const providers = await api.getProviders(); return providers; }; exports.getProviders = getProviders; const getNetworkConfig = async () => { return await proxy.getNetworkConfig(); }; exports.getNetworkConfig = getNetworkConfig; const getAccountNonce = async (addr) => { const address = new sdk_core_1.Address(addr); const account = await proxy.getAccount(address); return account.nonce; }; exports.getAccountNonce = getAccountNonce; /** * Returns true if account is the signer */ function isSender(transaction, addr) { return transaction.sender === addr; } function isSelfSend(transaction) { return (!!transaction.sender && !!transaction.receiver && transaction.sender === transaction.receiver); } /** * Map transaction to an Operation Type */ function getEGLDOperationType(transaction, addr) { if (transaction.action && transaction.action.category === "stake") { const stakeAction = transaction.action.name; switch (stakeAction) { case "delegate": return "DELEGATE"; case "unDelegate": return "UNDELEGATE"; case "withdraw": return "WITHDRAW_UNBONDED"; case "claimRewards": return "REWARD"; case "reDelegateRewards": return "DELEGATE"; } } return isSender(transaction, addr) ? transaction.transfer === types_1.MultiversXTransferOptions.esdt ? "FEES" : "OUT" : "IN"; } function getESDTOperationValue(transaction, tokenIdentifier) { const hasFailed = !transaction.status || transaction.status === "fail" || transaction.status === "invalid"; if (!transaction.action || hasFailed) { return new bignumber_js_1.BigNumber(0); } let token1, token2; switch (transaction.action.name) { case "transfer": return new bignumber_js_1.BigNumber(transaction.action.arguments.transfers[0].value ?? 0); case "swap": token1 = transaction.action.arguments.transfers[0]; token2 = transaction.action.arguments.transfers[1]; if (token1.token === tokenIdentifier) { return new bignumber_js_1.BigNumber(token1.value); } else { return new bignumber_js_1.BigNumber(token2.value); } default: return new bignumber_js_1.BigNumber(transaction.tokenValue ?? 0); } } function getStakingAmount(transaction, address) { const operation = transaction.operations?.find(({ sender, receiver, action, type }) => action === "transfer" && type === "egld" && sender === transaction.receiver && (receiver === address || receiver === constants_1.MULTIVERSX_STAKING_POOL)); let dataDecoded; switch (transaction.mode) { case "send": return new bignumber_js_1.BigNumber(0); case "delegate": return new bignumber_js_1.BigNumber(transaction.value ?? 0); case "unDelegate": dataDecoded = binary_utils_1.BinaryUtils.base64Decode(transaction.data ?? ""); return new bignumber_js_1.BigNumber(`0x${dataDecoded.split("@")[1]}`); case "reDelegateRewards": case "claimRewards": case "withdraw": default: return new bignumber_js_1.BigNumber(operation?.value ?? new bignumber_js_1.BigNumber(0)); } } /** * Map transaction to a correct Operation Value (affecting account balance) */ function getEGLDOperationValue(transaction, address) { if (transaction.mode === "send") { if (transaction.transfer === types_1.MultiversXTransferOptions.esdt) { // Only fees paid in EGLD for token transactions return isSender(transaction, address) && transaction.fee ? new bignumber_js_1.BigNumber(transaction.fee) : new bignumber_js_1.BigNumber(0); } else { return isSender(transaction, address) ? isSelfSend(transaction) ? new bignumber_js_1.BigNumber(transaction.fee ?? 0) // Self-send, only fees are paid : new bignumber_js_1.BigNumber(transaction.value ?? 0).plus(transaction.fee ?? 0) // The sender pays the amount and the fees : new bignumber_js_1.BigNumber(transaction.value ?? 0); // The recipient gets the amount } } else { // Operation value for staking transactions are just the fees, plus possible rewards // Other amounts are put in extra.amount return new bignumber_js_1.BigNumber(transaction.fee ?? 0); } } /** * Map the MultiversX history transaction to a Ledger Live Operation */ function transactionToEGLDOperation(accountId, addr, transaction, subAccounts) { const type = getEGLDOperationType(transaction, addr); const fee = new bignumber_js_1.BigNumber(transaction.fee ?? 0); const hasFailed = !transaction.status || transaction.status === "fail" || transaction.status === "invalid"; const delegationAmount = getStakingAmount(transaction, addr); const value = hasFailed ? isSender(transaction, addr) ? fee : new bignumber_js_1.BigNumber(0) : transaction.mode === "claimRewards" ? delegationAmount.minus(fee) : getEGLDOperationValue(transaction, addr); const operation = { id: (0, operation_1.encodeOperationId)(accountId, transaction.txHash ?? "", type), accountId, fee, value, type, hash: transaction.txHash ?? "", blockHash: transaction.miniBlockHash, blockHeight: transaction.round, date: new Date(transaction.timestamp ? transaction.timestamp * 1000 : 0), extra: { amount: delegationAmount, }, senders: (type === "OUT" || type === "IN") && transaction.sender ? [transaction.sender] : [], recipients: (type === "OUT" || type === "IN") && transaction.receiver ? [transaction.receiver] : [], transactionSequenceNumber: isSender(transaction, addr) && transaction.nonce !== undefined ? new bignumber_js_1.BigNumber(transaction.nonce.toString()) : undefined, hasFailed, }; const subOperations = subAccounts ? (0, index_1.inferSubOperations)(transaction.txHash ?? "", subAccounts) : undefined; if (subOperations) { operation.subOperations = subOperations; } let contract = undefined; if (transaction.receiver) { const isReceiverSmartContract = sdk_core_1.Address.newFromBech32(transaction.receiver).isSmartContract(); contract = isReceiverSmartContract ? transaction.receiver : undefined; } if (contract) { operation.contract = contract; } return operation; } const getESDTOperationType = (transaction, address) => { return isSender(transaction, address) ? "OUT" : "IN"; }; const transactionToESDTOperation = (tokenAccountId, addr, transaction, tokenIdentifier) => { const type = getESDTOperationType(transaction, addr); const value = getESDTOperationValue(transaction, tokenIdentifier); const fee = new bignumber_js_1.BigNumber(transaction.fee ?? 0); const senders = transaction.sender ? [transaction.sender] : []; const recipients = transaction.receiver ? [transaction.receiver] : []; const hash = transaction.txHash ?? ""; const blockHeight = transaction.round; const date = new Date(transaction.timestamp ? transaction.timestamp * 1000 : 0); return { id: (0, operation_1.encodeOperationId)(tokenAccountId, hash, type), accountId: tokenAccountId, hash, date, type, value, fee, senders, recipients, blockHeight, blockHash: transaction.miniBlockHash, extra: {}, }; }; /** * Fetch operation list */ const getEGLDOperations = async (accountId, addr, startAt, subAccounts) => { const rawTransactions = await api.getHistory(addr, startAt); if (!rawTransactions) return rawTransactions; return rawTransactions.map(transaction => transactionToEGLDOperation(accountId, addr, transaction, subAccounts)); }; exports.getEGLDOperations = getEGLDOperations; const getAccountESDTTokens = async (address) => { return await api.getESDTTokensForAddress(address); }; exports.getAccountESDTTokens = getAccountESDTTokens; const getAccountDelegations = async (address) => { return await api.getAccountDelegations(address); }; exports.getAccountDelegations = getAccountDelegations; const hasESDTTokens = async (address) => { const tokensCount = await api.getESDTTokensCountForAddress(address); return tokensCount > 0; }; exports.hasESDTTokens = hasESDTTokens; const getESDTOperations = async (tokenAccountId, address, tokenIdentifier, startAt) => { const accountESDTTransactions = await api.getESDTTransactionsForAddress(address, tokenIdentifier, startAt); return accountESDTTransactions.map(transaction => transactionToESDTOperation(tokenAccountId, address, transaction, tokenIdentifier)); }; exports.getESDTOperations = getESDTOperations; /** * Obtain fees from blockchain */ const getFees = async (t) => { const networkConfig = { MinGasLimit: constants_1.MIN_GAS_LIMIT, GasPerDataByte: constants_1.GAS_PER_DATA_BYTE, GasPriceModifier: constants_1.GAS_PRICE_MODIFIER, ChainID: constants_1.CHAIN_ID, }; const transaction = new sdk_core_1.Transaction({ data: sdk_core_1.TransactionPayload.fromEncoded(t.data?.trim()), receiver: new sdk_core_1.Address((0, cryptoassets_1.getAbandonSeedAddress)("elrond")), chainID: constants_1.CHAIN_ID, gasPrice: constants_1.GAS_PRICE, gasLimit: t.gasLimit ?? networkConfig.MinGasLimit, sender: sdk_core_1.Address.empty(), }); const feesStr = transaction.computeFee(networkConfig).toFixed(); return new bignumber_js_1.BigNumber(feesStr); }; exports.getFees = getFees; /** * Broadcast blob to blockchain */ const broadcastTransaction = async (signedOperation) => { return await api.submit(signedOperation); }; exports.broadcastTransaction = broadcastTransaction; //# sourceMappingURL=sdk.js.map