Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix approve operations tron #7762

Merged
merged 3 commits into from
Sep 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/curly-terms-rescue.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@ledgerhq/coin-tron": patch
---

Fix approve operations on Tron
77 changes: 77 additions & 0 deletions libs/coin-modules/coin-tron/src/logic/utils.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { OperationType } from "@ledgerhq/types-live";
import { TrongridTxInfo, TrongridTxType } from "../types";
import { txInfoToOperation } from "./utils";

jest.mock("@ledgerhq/coin-framework/operation", () => ({
encodeOperationId: jest.fn(() => "encodedOpId"),
}));

let mockTx: TrongridTxInfo;

const testingMap: Record<TrongridTxType, OperationType> = {
TransferContract: "IN",
TransferAssetContract: "IN",
TriggerSmartContract: "IN",
ContractApproval: "APPROVE",
ExchangeTransactionContract: "OUT",
VoteWitnessContract: "VOTE",
WithdrawBalanceContract: "REWARD",
FreezeBalanceContract: "FREEZE",
FreezeBalanceV2Contract: "FREEZE",
UnfreezeBalanceV2Contract: "UNFREEZE",
WithdrawExpireUnfreezeContract: "WITHDRAW_EXPIRE_UNFREEZE",
UnDelegateResourceContract: "UNDELEGATE_RESOURCE",
UnfreezeBalanceContract: "LEGACY_UNFREEZE",
};

describe("txInfoToOperation", () => {
beforeEach(() => {
mockTx = {} as TrongridTxInfo;
});

it.each(Object.keys(testingMap))(
`should return correct operation type for %p trongrid tx type`,
trongridTxType => {
const tx: TrongridTxInfo = {
...mockTx,
type: trongridTxType as TrongridTxType,
};

expect(txInfoToOperation("accountId", "address", tx)?.type).toEqual(
testingMap[trongridTxType as keyof Record<TrongridTxType, OperationType>],
);
},
);

it.each(["TransferContract", "TransferAssetContract", "TriggerSmartContract"])(
"should return OUT operation type when from is equal to user address for %p trongrid tx type",
trongridTxType => {
const tx: TrongridTxInfo = {
...mockTx,
type: trongridTxType as TrongridTxType,
from: "address",
};

expect(txInfoToOperation("accountId", "address", tx)?.type).toEqual("OUT");
},
);

it("should return undefined operation type for unknown tx type", () => {
const tx: TrongridTxInfo = {
...mockTx,
type: "Unknown" as TrongridTxType,
};

expect(txInfoToOperation("accountId", "address", tx)).toBeUndefined();
});

it("should return correct encoded operation id", () => {
const tx: TrongridTxInfo = {
...mockTx,
type: "TransferContract",
txID: "txId",
};

expect(txInfoToOperation("accountId", "address", tx)?.id).toEqual("encodedOpId");
});
});
4 changes: 4 additions & 0 deletions libs/coin-modules/coin-tron/src/logic/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ const parentTx = [
"UnDelegateResourceContract",
"FreezeBalanceContract",
"UnfreezeBalanceContract",
"ContractApproval",
];

export const isParentTx = (tx: TrongridTxInfo): boolean => parentTx.includes(tx.type);
Expand Down Expand Up @@ -109,6 +110,9 @@ const getOperationType = (
case "TriggerSmartContract":
return tx.from === accountAddr ? "OUT" : "IN";

case "ContractApproval":
return "APPROVE";

case "ExchangeTransactionContract":
return "OUT";

Expand Down
61 changes: 61 additions & 0 deletions libs/coin-modules/coin-tron/src/network/format.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import BigNumber from "bignumber.js";
import { formatTrongridTrc20TxResponse } from "./format";
import { Trc20API } from "./types";

describe("formatTrongridTrc20TxResponse", () => {
it("should return correct TrongridTxInfo for Approval tx type", () => {
const tx = {
from: "from",
to: "to",
block_timestamp: 1,
detail: {
ret: [{ fee: 1 }],
},
value: 1,
transaction_id: "txId",
token_info: {},
type: "Approval",
};
const result = formatTrongridTrc20TxResponse(tx as unknown as Trc20API);
expect(result).toEqual({
txID: "txId",
date: new Date(1),
type: "ContractApproval",
tokenId: undefined,
from: "from",
to: "to",
blockHeight: undefined,
value: new BigNumber(1),
fee: new BigNumber(1),
hasFailed: false,
});
});

it("should return correct TrongridTxInfo for Transfer tx type", () => {
const tx = {
from: "from",
to: "to",
block_timestamp: 1,
detail: {
ret: [{ fee: 1 }],
},
value: 1,
transaction_id: "txId",
token_info: { address: "tokenId" },
type: "Transfer",
};
const result = formatTrongridTrc20TxResponse(tx as unknown as Trc20API);
expect(result).toEqual({
txID: "txId",
date: new Date(1),
type: "TriggerSmartContract",
tokenId: "tokenId",
from: "from",
to: "to",
blockHeight: undefined,
value: new BigNumber(1),
fee: new BigNumber(1),
hasFailed: false,
});
});
});
33 changes: 24 additions & 9 deletions libs/coin-modules/coin-tron/src/network/format.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import get from "lodash/get";
import { TrongridExtraTxInfo, TrongridTxInfo, TronTransactionInfo } from "../types";
import { TrongridExtraTxInfo, TrongridTxInfo, TrongridTxType, TronTransactionInfo } from "../types";
import { TransactionTronAPI, Trc20API } from "./types";
import BigNumber from "bignumber.js";
import { log } from "@ledgerhq/logs";
Expand All @@ -12,24 +12,39 @@ export const encode58Check = (hex: string): string => bs58check.encode(Buffer.fr

export const formatTrongridTrc20TxResponse = (tx: Trc20API): TrongridTxInfo | null | undefined => {
try {
const { from, to, block_timestamp, detail, value, transaction_id, token_info } = tx;
const type = "TriggerSmartContract";
const { from, to, block_timestamp, detail, value, transaction_id, token_info, type } = tx;
const txID = transaction_id;
const date = new Date(block_timestamp);
const tokenId = token_info.address ?? undefined;
const formattedValue = value ? new BigNumber(value) : new BigNumber(0);
let txType: TrongridTxType;
let tokenId: string | undefined;
const fee = tx.detail.ret[0].fee || undefined;
const bnFee = new BigNumber(fee || 0);
let formattedValue;

switch (type) {
case "Approval":
txType = "ContractApproval";
formattedValue = bnFee;
break;
default:
txType = "TriggerSmartContract";
tokenId = token_info.address ?? undefined;
formattedValue = value ? new BigNumber(value) : new BigNumber(0);
break;
}

const date = new Date(block_timestamp);

const blockHeight = detail ? detail.blockNumber : undefined;
return {
txID,
date,
type,
tokenId,
type: txType,
tokenId: tokenId,
from,
to,
blockHeight,
value: formattedValue,
fee: new BigNumber(fee || 0),
fee: bnFee,
hasFailed: false, // trc20 txs are succeeded if returned by trongrid,
};
} catch (e) {
Expand Down
2 changes: 1 addition & 1 deletion libs/coin-modules/coin-tron/src/network/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ export type Trc20API = {
from: string;
to: string;
detail: TransactionTronAPI<Trc20Contract>;
type: string;
type: "Approval" | "Transfer";
value?: string;
};

Expand Down
1 change: 1 addition & 0 deletions libs/coin-modules/coin-tron/src/types/bridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ export type TrongridTxType =
| "UnfreezeBalanceContract"
| "VoteWitnessContract"
| "TriggerSmartContract"
| "ContractApproval"
| "WithdrawBalanceContract"
| "ExchangeTransactionContract"
| "FreezeBalanceV2Contract"
Expand Down
Loading