From b71538b8b53dcab8b1aff13061497cecad38aeb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Guimar=C3=A3es?= Date: Tue, 31 Dec 2024 18:03:13 +0000 Subject: [PATCH 1/5] feat(aptos): improve bot specs file --- libs/ledger-live-common/jest.config.ts | 2 +- .../aptos/getFeesForTransaction.test.ts | 169 ++++++++++++++++++ .../families/aptos/getFeesForTransaction.ts | 2 +- 3 files changed, 171 insertions(+), 2 deletions(-) create mode 100644 libs/ledger-live-common/src/families/aptos/getFeesForTransaction.test.ts diff --git a/libs/ledger-live-common/jest.config.ts b/libs/ledger-live-common/jest.config.ts index 38b398820b24..6dab9c7ee021 100644 --- a/libs/ledger-live-common/jest.config.ts +++ b/libs/ledger-live-common/jest.config.ts @@ -78,6 +78,6 @@ export default { : undefined, collectCoverage: true, collectCoverageFrom: ["src/**/*.{ts,tsx}"], - coverageReporters: ["json", "lcov", "clover", "json-summary"], + coverageReporters: ["html", "json", "lcov", "clover", "json-summary"], projects: [defaultConfig], }; diff --git a/libs/ledger-live-common/src/families/aptos/getFeesForTransaction.test.ts b/libs/ledger-live-common/src/families/aptos/getFeesForTransaction.test.ts new file mode 100644 index 000000000000..f239ef2363bb --- /dev/null +++ b/libs/ledger-live-common/src/families/aptos/getFeesForTransaction.test.ts @@ -0,0 +1,169 @@ +import BigNumber from "bignumber.js"; +import { createFixtureAccount } from "../../mock/fixtures/cryptoCurrencies"; +import createTransaction from "./createTransaction"; +import { getFee } from "./getFeesForTransaction"; +import { AptosAPI } from "./api"; + +let simulateTransaction = jest.fn(); + +jest.mock("./api", () => { + return { + AptosAPI: function () { + return { + generateTransaction: jest.fn(() => "tx"), + simulateTransaction, + }; + }, + }; +}); + +jest.mock("@aptos-labs/ts-sdk", () => { + return { + Ed25519PublicKey: jest.fn(), + }; +}); + +describe("getFeesForTransaction Test", () => { + describe("when using getFee", () => { + describe("with vm_status as SEQUENCE_NUMBER", () => { + it("should return a fee estimation object", async () => { + simulateTransaction = jest.fn(() => [ + { + success: false, + vm_status: ["SEQUENCE_NUMBER"], + expiration_timestamp_secs: 5, + }, + ]); + + const account = createFixtureAccount(); + const transaction = createTransaction(); + const aptosClient = new AptosAPI(account.currency.id); + + transaction.amount = new BigNumber(1); + account.xpub = "xpub"; + account.spendableBalance = new BigNumber(100000000); + + const result = await getFee(account, transaction, aptosClient); + + const expected = { + fees: new BigNumber(20000), + estimate: { + maxGasAmount: "200", + gasUnitPrice: "100", + sequenceNumber: "", + expirationTimestampSecs: 5, + }, + errors: { + sequenceNumber: ["SEQUENCE_NUMBER"], + }, + }; + + expect(result).toEqual(expected); + }); + }); + + describe("with vm_status as TRANSACTION_EXPIRED", () => { + it("should return a fee estimation object", async () => { + simulateTransaction = jest.fn(() => [ + { + success: false, + vm_status: ["TRANSACTION_EXPIRED"], + expiration_timestamp_secs: 5, + }, + ]); + + const account = createFixtureAccount(); + const transaction = createTransaction(); + const aptosClient = new AptosAPI(account.currency.id); + + transaction.amount = new BigNumber(1); + account.xpub = "xpub"; + account.spendableBalance = new BigNumber(100000000); + + const result = await getFee(account, transaction, aptosClient); + + const expected = { + fees: new BigNumber(20000), + estimate: { + maxGasAmount: "200", + gasUnitPrice: "100", + sequenceNumber: "", + expirationTimestampSecs: 5, + }, + errors: { + expirationTimestampSecs: ["TRANSACTION_EXPIRED"], + }, + }; + + expect(result).toEqual(expected); + }); + }); + + describe("with vm_status as INSUFFICIENT_BALANCE", () => { + it("should return a fee estimation object", async () => { + simulateTransaction = jest.fn(() => [ + { + success: false, + vm_status: ["INSUFFICIENT_BALANCE"], + expiration_timestamp_secs: 5, + }, + ]); + + const account = createFixtureAccount(); + const transaction = createTransaction(); + const aptosClient = new AptosAPI(account.currency.id); + + transaction.amount = new BigNumber(1); + account.xpub = "xpub"; + account.spendableBalance = new BigNumber(100000000); + + const result = await getFee(account, transaction, aptosClient); + + const expected = { + fees: new BigNumber(20000), + estimate: { + maxGasAmount: "200", + gasUnitPrice: "100", + sequenceNumber: "", + expirationTimestampSecs: 5, + }, + errors: {}, + }; + + expect(result).toEqual(expected); + }); + }); + + describe("with vm_status as DUMMY_STATE", () => { + it("should return a fee estimation object", () => { + simulateTransaction = jest.fn(() => [ + { + success: false, + vm_status: ["DUMMY_STATE"], + expiration_timestamp_secs: 5, + }, + ]); + + const account = createFixtureAccount(); + const transaction = createTransaction(); + const aptosClient = new AptosAPI(account.currency.id); + + transaction.amount = new BigNumber(1); + account.xpub = "xpub"; + account.spendableBalance = new BigNumber(100000000); + + expect(async () => { + await getFee(account, transaction, aptosClient); + }).rejects.toThrow("Simulation failed with following error: DUMMY_STATE"); + }); + }); + }); + + describe("when using getCacheKey", () => { + it("should return tx", async () => {}); + }); + + describe("when using getEstimatedGas", () => { + it("should return tx", async () => {}); + }); +}); diff --git a/libs/ledger-live-common/src/families/aptos/getFeesForTransaction.ts b/libs/ledger-live-common/src/families/aptos/getFeesForTransaction.ts index dd2cfe335316..70d4e18d2db0 100644 --- a/libs/ledger-live-common/src/families/aptos/getFeesForTransaction.ts +++ b/libs/ledger-live-common/src/families/aptos/getFeesForTransaction.ts @@ -69,7 +69,7 @@ export const getFee = async ( res.errors.expirationTimestampSecs = completedTx.vm_status; break; } - case completedTx.vm_status.includes("EINSUFFICIENT_BALANCE"): { + case completedTx.vm_status.includes("INSUFFICIENT_BALANCE"): { // skip, processed in getTransactionStatus break; } From f38c86899f228a59f513e29e24ab3f92fabe3c0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Guimar=C3=A3es?= Date: Tue, 31 Dec 2024 18:20:59 +0000 Subject: [PATCH 2/5] feat(aptos): improve bot specs file --- libs/ledger-live-common/jest.config.ts | 2 +- .../aptos/getFeesForTransaction.test.ts | 53 ++++++++++++++++--- 2 files changed, 48 insertions(+), 7 deletions(-) diff --git a/libs/ledger-live-common/jest.config.ts b/libs/ledger-live-common/jest.config.ts index 6dab9c7ee021..38b398820b24 100644 --- a/libs/ledger-live-common/jest.config.ts +++ b/libs/ledger-live-common/jest.config.ts @@ -78,6 +78,6 @@ export default { : undefined, collectCoverage: true, collectCoverageFrom: ["src/**/*.{ts,tsx}"], - coverageReporters: ["html", "json", "lcov", "clover", "json-summary"], + coverageReporters: ["json", "lcov", "clover", "json-summary"], projects: [defaultConfig], }; diff --git a/libs/ledger-live-common/src/families/aptos/getFeesForTransaction.test.ts b/libs/ledger-live-common/src/families/aptos/getFeesForTransaction.test.ts index f239ef2363bb..a4d15f9eb93d 100644 --- a/libs/ledger-live-common/src/families/aptos/getFeesForTransaction.test.ts +++ b/libs/ledger-live-common/src/families/aptos/getFeesForTransaction.test.ts @@ -1,7 +1,7 @@ import BigNumber from "bignumber.js"; import { createFixtureAccount } from "../../mock/fixtures/cryptoCurrencies"; import createTransaction from "./createTransaction"; -import { getFee } from "./getFeesForTransaction"; +import { getFee, getEstimatedGas } from "./getFeesForTransaction"; import { AptosAPI } from "./api"; let simulateTransaction = jest.fn(); @@ -159,11 +159,52 @@ describe("getFeesForTransaction Test", () => { }); }); - describe("when using getCacheKey", () => { - it("should return tx", async () => {}); - }); - describe("when using getEstimatedGas", () => { - it("should return tx", async () => {}); + describe("when key not in cache", () => { + it("should return cached fee", async () => { + const account = createFixtureAccount(); + const transaction = createTransaction(); + const aptosClient = new AptosAPI(account.currency.id); + + const result = await getEstimatedGas(account, transaction, aptosClient); + + const expected = { + errors: {}, + estimate: { + expirationTimestampSecs: "", + gasUnitPrice: "100", + maxGasAmount: "200", + sequenceNumber: "", + }, + fees: new BigNumber("20000"), + }; + + expect(result).toEqual(expected); + }); + }); + + describe("when key is in cache", () => { + it("should return cached fee", async () => { + const account = createFixtureAccount(); + const transaction = createTransaction(); + const aptosClient = new AptosAPI(account.currency.id); + + await getEstimatedGas(account, transaction, aptosClient); + const result = await getEstimatedGas(account, transaction, aptosClient); + + const expected = { + errors: {}, + estimate: { + expirationTimestampSecs: "", + gasUnitPrice: "100", + maxGasAmount: "200", + sequenceNumber: "", + }, + fees: new BigNumber("20000"), + }; + + expect(result).toEqual(expected); + }); + }); }); }); From b3549e01a7f963c756906965135ae73ee748957d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Guimar=C3=A3es?= Date: Thu, 2 Jan 2025 15:15:17 +0000 Subject: [PATCH 3/5] test(aptos): improve unit tests --- .../aptos/getFeesForTransaction.test.ts | 51 +++++++++++-------- .../families/aptos/getFeesForTransaction.ts | 2 +- 2 files changed, 32 insertions(+), 21 deletions(-) diff --git a/libs/ledger-live-common/src/families/aptos/getFeesForTransaction.test.ts b/libs/ledger-live-common/src/families/aptos/getFeesForTransaction.test.ts index a4d15f9eb93d..014c0c3617e1 100644 --- a/libs/ledger-live-common/src/families/aptos/getFeesForTransaction.test.ts +++ b/libs/ledger-live-common/src/families/aptos/getFeesForTransaction.test.ts @@ -10,8 +10,10 @@ jest.mock("./api", () => { return { AptosAPI: function () { return { + estimateGasPrice: jest.fn(() => ({ gas_estimate: 101 })), generateTransaction: jest.fn(() => "tx"), simulateTransaction, + getAccount: jest.fn(() => ({ sequence_number: "123" })), }; }, }; @@ -23,6 +25,15 @@ jest.mock("@aptos-labs/ts-sdk", () => { }; }); +jest.mock("./logic", () => { + return { + DEFAULT_GAS: 201, + DEFAULT_GAS_PRICE: 101, + ESTIMATE_GAS_MUL: 1, + normalizeTransactionOptions: jest.fn(), + }; +}); + describe("getFeesForTransaction Test", () => { describe("when using getFee", () => { describe("with vm_status as SEQUENCE_NUMBER", () => { @@ -46,11 +57,11 @@ describe("getFeesForTransaction Test", () => { const result = await getFee(account, transaction, aptosClient); const expected = { - fees: new BigNumber(20000), + fees: new BigNumber(20301), estimate: { - maxGasAmount: "200", - gasUnitPrice: "100", - sequenceNumber: "", + maxGasAmount: "201", + gasUnitPrice: "101", + sequenceNumber: "123", expirationTimestampSecs: 5, }, errors: { @@ -83,11 +94,11 @@ describe("getFeesForTransaction Test", () => { const result = await getFee(account, transaction, aptosClient); const expected = { - fees: new BigNumber(20000), + fees: new BigNumber(20301), estimate: { - maxGasAmount: "200", - gasUnitPrice: "100", - sequenceNumber: "", + maxGasAmount: "201", + gasUnitPrice: "101", + sequenceNumber: "123", expirationTimestampSecs: 5, }, errors: { @@ -120,11 +131,11 @@ describe("getFeesForTransaction Test", () => { const result = await getFee(account, transaction, aptosClient); const expected = { - fees: new BigNumber(20000), + fees: new BigNumber(20301), estimate: { - maxGasAmount: "200", - gasUnitPrice: "100", - sequenceNumber: "", + maxGasAmount: "201", + gasUnitPrice: "101", + sequenceNumber: "123", expirationTimestampSecs: 5, }, errors: {}, @@ -172,11 +183,11 @@ describe("getFeesForTransaction Test", () => { errors: {}, estimate: { expirationTimestampSecs: "", - gasUnitPrice: "100", - maxGasAmount: "200", - sequenceNumber: "", + gasUnitPrice: "101", + maxGasAmount: "201", + sequenceNumber: "123", }, - fees: new BigNumber("20000"), + fees: new BigNumber("20301"), }; expect(result).toEqual(expected); @@ -196,11 +207,11 @@ describe("getFeesForTransaction Test", () => { errors: {}, estimate: { expirationTimestampSecs: "", - gasUnitPrice: "100", - maxGasAmount: "200", - sequenceNumber: "", + gasUnitPrice: "101", + maxGasAmount: "201", + sequenceNumber: "123", }, - fees: new BigNumber("20000"), + fees: new BigNumber("20301"), }; expect(result).toEqual(expected); diff --git a/libs/ledger-live-common/src/families/aptos/getFeesForTransaction.ts b/libs/ledger-live-common/src/families/aptos/getFeesForTransaction.ts index 70d4e18d2db0..9c0d7be17504 100644 --- a/libs/ledger-live-common/src/families/aptos/getFeesForTransaction.ts +++ b/libs/ledger-live-common/src/families/aptos/getFeesForTransaction.ts @@ -127,7 +127,7 @@ export const getEstimatedGas = async ( return CACHE.get(key); } - CACHE.set(key, getFee(account, transaction, aptosClient)); + CACHE.set(key, await getFee(account, transaction, aptosClient)); return CACHE.get(key); }; From 760ce80a6173819aa1065f81b0b3606fa82617a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Guimar=C3=A3es?= Date: Thu, 2 Jan 2025 17:07:18 +0000 Subject: [PATCH 4/5] test(aptos): improve unit tests --- .../src/families/aptos/getFeesForTransaction.test.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libs/ledger-live-common/src/families/aptos/getFeesForTransaction.test.ts b/libs/ledger-live-common/src/families/aptos/getFeesForTransaction.test.ts index 014c0c3617e1..03a3896cfe5b 100644 --- a/libs/ledger-live-common/src/families/aptos/getFeesForTransaction.test.ts +++ b/libs/ledger-live-common/src/families/aptos/getFeesForTransaction.test.ts @@ -179,6 +179,8 @@ describe("getFeesForTransaction Test", () => { const result = await getEstimatedGas(account, transaction, aptosClient); + jest.resetAllMocks(); + const expected = { errors: {}, estimate: { @@ -201,6 +203,10 @@ describe("getFeesForTransaction Test", () => { const aptosClient = new AptosAPI(account.currency.id); await getEstimatedGas(account, transaction, aptosClient); + + account.spendableBalance = account.spendableBalance.plus(new BigNumber(1)); + transaction.fees = new BigNumber(2001); + const result = await getEstimatedGas(account, transaction, aptosClient); const expected = { From e463a2cf0d5799d4d3540ac7a3df56dda62ac49d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Guimar=C3=A3es?= Date: Fri, 3 Jan 2025 17:56:02 +0000 Subject: [PATCH 5/5] test(aptos): improve unit tests --- .../aptos/getFeesForTransaction.test.ts | 51 ++++++++++++------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/libs/ledger-live-common/src/families/aptos/getFeesForTransaction.test.ts b/libs/ledger-live-common/src/families/aptos/getFeesForTransaction.test.ts index 03a3896cfe5b..2d8945043fc0 100644 --- a/libs/ledger-live-common/src/families/aptos/getFeesForTransaction.test.ts +++ b/libs/ledger-live-common/src/families/aptos/getFeesForTransaction.test.ts @@ -1,7 +1,7 @@ import BigNumber from "bignumber.js"; import { createFixtureAccount } from "../../mock/fixtures/cryptoCurrencies"; import createTransaction from "./createTransaction"; -import { getFee, getEstimatedGas } from "./getFeesForTransaction"; +import * as getFeesForTransaction from "./getFeesForTransaction"; import { AptosAPI } from "./api"; let simulateTransaction = jest.fn(); @@ -54,7 +54,7 @@ describe("getFeesForTransaction Test", () => { account.xpub = "xpub"; account.spendableBalance = new BigNumber(100000000); - const result = await getFee(account, transaction, aptosClient); + const result = await getFeesForTransaction.getFee(account, transaction, aptosClient); const expected = { fees: new BigNumber(20301), @@ -62,7 +62,7 @@ describe("getFeesForTransaction Test", () => { maxGasAmount: "201", gasUnitPrice: "101", sequenceNumber: "123", - expirationTimestampSecs: 5, + expirationTimestampSecs: "", }, errors: { sequenceNumber: ["SEQUENCE_NUMBER"], @@ -91,7 +91,7 @@ describe("getFeesForTransaction Test", () => { account.xpub = "xpub"; account.spendableBalance = new BigNumber(100000000); - const result = await getFee(account, transaction, aptosClient); + const result = await getFeesForTransaction.getFee(account, transaction, aptosClient); const expected = { fees: new BigNumber(20301), @@ -99,7 +99,7 @@ describe("getFeesForTransaction Test", () => { maxGasAmount: "201", gasUnitPrice: "101", sequenceNumber: "123", - expirationTimestampSecs: 5, + expirationTimestampSecs: "", }, errors: { expirationTimestampSecs: ["TRANSACTION_EXPIRED"], @@ -128,7 +128,7 @@ describe("getFeesForTransaction Test", () => { account.xpub = "xpub"; account.spendableBalance = new BigNumber(100000000); - const result = await getFee(account, transaction, aptosClient); + const result = await getFeesForTransaction.getFee(account, transaction, aptosClient); const expected = { fees: new BigNumber(20301), @@ -136,7 +136,7 @@ describe("getFeesForTransaction Test", () => { maxGasAmount: "201", gasUnitPrice: "101", sequenceNumber: "123", - expirationTimestampSecs: 5, + expirationTimestampSecs: "", }, errors: {}, }; @@ -164,7 +164,7 @@ describe("getFeesForTransaction Test", () => { account.spendableBalance = new BigNumber(100000000); expect(async () => { - await getFee(account, transaction, aptosClient); + await getFeesForTransaction.getFee(account, transaction, aptosClient); }).rejects.toThrow("Simulation failed with following error: DUMMY_STATE"); }); }); @@ -177,9 +177,11 @@ describe("getFeesForTransaction Test", () => { const transaction = createTransaction(); const aptosClient = new AptosAPI(account.currency.id); - const result = await getEstimatedGas(account, transaction, aptosClient); - - jest.resetAllMocks(); + const result = await getFeesForTransaction.getEstimatedGas( + account, + transaction, + aptosClient, + ); const expected = { errors: {}, @@ -196,18 +198,32 @@ describe("getFeesForTransaction Test", () => { }); }); - describe("when key is in cache", () => { + describe("when key is in cache 22", () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + it("should return cached fee", async () => { + const mocked = jest.spyOn(getFeesForTransaction, "getFee"); + const account = createFixtureAccount(); const transaction = createTransaction(); const aptosClient = new AptosAPI(account.currency.id); - await getEstimatedGas(account, transaction, aptosClient); + transaction.amount = new BigNumber(10); - account.spendableBalance = account.spendableBalance.plus(new BigNumber(1)); - transaction.fees = new BigNumber(2001); + const result1 = await getFeesForTransaction.getEstimatedGas( + account, + transaction, + aptosClient, + ); + const result2 = await getFeesForTransaction.getEstimatedGas( + account, + transaction, + aptosClient, + ); - const result = await getEstimatedGas(account, transaction, aptosClient); + expect(mocked).toHaveBeenCalledTimes(1); const expected = { errors: {}, @@ -220,7 +236,8 @@ describe("getFeesForTransaction Test", () => { fees: new BigNumber("20301"), }; - expect(result).toEqual(expected); + expect(result1).toEqual(expected); + expect(result2).toEqual(expected); }); }); });