@ledgerhq/coin-hedera
Version:
Ledger Hedera Coin integration
175 lines • 6.76 kB
JavaScript
import { findSubAccountById } from "@ledgerhq/ledger-wallet-framework/account/helpers";
import { encodeOperationId } from "@ledgerhq/ledger-wallet-framework/operation";
import BigNumber from "bignumber.js";
import invariant from "invariant";
import { HEDERA_TRANSACTION_MODES, MAP_STAKING_MODE_TO_OPERATION_TYPE } from "../constants";
import { safeParseAccountId, isTokenAssociateTransaction, isStakingTransaction, } from "../logic/utils";
const buildOptimisticTokenAssociateOperation = async ({ account, transaction, }) => {
invariant(isTokenAssociateTransaction(transaction), "invalid transaction properties");
const fee = transaction.maxFee ?? new BigNumber(0);
const type = "ASSOCIATE_TOKEN";
const operation = {
id: encodeOperationId(account.id, "", type),
hash: "",
type,
value: fee,
fee,
blockHash: null,
blockHeight: null,
senders: [account.freshAddress.toString()],
recipients: [transaction.recipient],
accountId: account.id,
date: new Date(),
extra: {
associatedTokenId: transaction.properties.token.contractAddress,
},
};
return operation;
};
const buildOptimisticCoinOperation = async ({ account, transaction, transactionType, }) => {
const fee = transactionType === "FEES" ? transaction.amount : (transaction.maxFee ?? new BigNumber(0));
const value = transaction.amount;
const type = transactionType ?? "OUT";
const [_, recipientAddress] = await safeParseAccountId(transaction.recipient);
const recipientWithoutChecksum = recipientAddress?.accountId ?? transaction.recipient;
const memo = transaction.memo;
const operation = {
id: encodeOperationId(account.id, "", type),
hash: "",
type,
value,
fee,
blockHash: null,
blockHeight: null,
senders: [account.freshAddress.toString()],
recipients: [recipientWithoutChecksum],
accountId: account.id,
date: new Date(),
extra: {
...(memo && { memo }),
},
};
return operation;
};
const buildOptimisticHTSTokenOperation = async ({ account, tokenAccount, transaction, }) => {
const fee = transaction.maxFee ?? new BigNumber(0);
const value = transaction.amount;
const type = "OUT";
const [_, recipientAddress] = await safeParseAccountId(transaction.recipient);
const recipientWithoutChecksum = recipientAddress?.accountId ?? transaction.recipient;
const memo = transaction.memo;
const coinOperation = await buildOptimisticCoinOperation({
account,
transaction: {
...transaction,
amount: fee,
},
transactionType: "FEES",
});
const operation = {
...coinOperation,
subOperations: [
{
id: encodeOperationId(tokenAccount.id, "", type),
hash: "",
type,
value,
fee,
blockHash: null,
blockHeight: null,
senders: [account.freshAddress.toString()],
recipients: [recipientWithoutChecksum],
accountId: tokenAccount.id,
date: new Date(),
extra: {
...(memo && { memo }),
},
},
],
};
return operation;
};
const buildOptimisticERC20TokenOperation = async ({ account, tokenAccount, transaction, }) => {
const fee = transaction.maxFee ?? new BigNumber(0);
const value = transaction.amount;
const type = "OUT";
const memo = transaction.memo;
const coinOperation = await buildOptimisticCoinOperation({
account,
transaction: {
...transaction,
amount: fee,
},
transactionType: "FEES",
});
const operation = {
...coinOperation,
subOperations: [
{
id: encodeOperationId(tokenAccount.id, "", type),
hash: "",
type,
value,
fee,
blockHash: null,
blockHeight: null,
senders: [account.freshAddress.toString()],
recipients: [transaction.recipient],
accountId: tokenAccount.id,
date: new Date(),
extra: {
...(memo && { memo }),
},
},
],
};
return operation;
};
const buildOptimisticUpdateAccountOperation = async ({ account, transaction, }) => {
invariant(isStakingTransaction(transaction), "invalid transaction properties");
const fee = transaction.maxFee ?? new BigNumber(0);
const value = transaction.amount;
const type = MAP_STAKING_MODE_TO_OPERATION_TYPE[transaction.mode];
const operation = {
id: encodeOperationId(account.id, "", type),
hash: "",
type,
value,
fee,
blockHash: null,
blockHeight: null,
senders: [account.freshAddress.toString()],
recipients: [transaction.recipient],
accountId: account.id,
date: new Date(),
extra: {
memo: transaction.memo ?? null,
targetStakingNodeId: transaction.properties?.stakingNodeId ?? null,
previousStakingNodeId: account.hederaResources?.delegation?.nodeId ?? null,
},
};
return operation;
};
export const buildOptimisticOperation = async ({ account, transaction, }) => {
const subAccount = findSubAccountById(account, transaction.subAccountId || "");
const isHTSTokenTransaction = transaction.mode === HEDERA_TRANSACTION_MODES.Send && subAccount?.token.tokenType === "hts";
const isERC20TokenTransaction = transaction.mode === HEDERA_TRANSACTION_MODES.Send && subAccount?.token.tokenType === "erc20";
if (isTokenAssociateTransaction(transaction)) {
return buildOptimisticTokenAssociateOperation({ account, transaction });
}
else if (isHTSTokenTransaction) {
return buildOptimisticHTSTokenOperation({ account, tokenAccount: subAccount, transaction });
}
else if (isERC20TokenTransaction) {
return buildOptimisticERC20TokenOperation({ account, tokenAccount: subAccount, transaction });
}
else if (transaction.mode === HEDERA_TRANSACTION_MODES.Redelegate ||
transaction.mode === HEDERA_TRANSACTION_MODES.Undelegate ||
transaction.mode === HEDERA_TRANSACTION_MODES.Delegate) {
return buildOptimisticUpdateAccountOperation({ account, transaction });
}
else {
return buildOptimisticCoinOperation({ account, transaction });
}
};
//# sourceMappingURL=buildOptimisticOperation.js.map