Skip to content

Commit 05e23ac

Browse files
authored
Merge pull request #10053 from LedgerHQ/support/fix-solana-tests
test: enable back the tokens and stakes solana tests
2 parents db66eab + 602413d commit 05e23ac

File tree

6 files changed

+144
-5
lines changed

6 files changed

+144
-5
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
const transformIncludePatterns = ["ky"];
2+
3+
/** @type {import('ts-jest/dist/types').JestConfigWithTsJest} */
4+
module.exports = {
5+
preset: "ts-jest",
6+
testEnvironment: "node",
7+
testRegex: ".integration.test.ts$",
8+
testPathIgnorePatterns: ["lib/", "lib-es/", "bridge.integration.test.ts"],
9+
transform: {
10+
[`node_modules/.pnpm/(${transformIncludePatterns.join("|")}).+\\.(js|jsx)?$`]: [
11+
"@swc/jest",
12+
{
13+
jsc: {
14+
target: "esnext",
15+
},
16+
},
17+
],
18+
},
19+
transformIgnorePatterns: [`node_modules/.pnpm/(?!(${transformIncludePatterns.join("|")}))`],
20+
};

libs/coin-modules/coin-solana/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@
9292
"lint": "eslint ./src --no-error-on-unmatched-pattern --ext .ts,.tsx --cache",
9393
"lint:fix": "pnpm lint --fix",
9494
"test": "jest",
95+
"test-integ": "jest --config=jest.integ.config.js",
9596
"typecheck": "tsc --noEmit",
9697
"unimported": "unimported"
9798
}

libs/coin-modules/coin-solana/src/prepareTransaction.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -907,7 +907,7 @@ async function validateRecipientCommon(
907907
const mintTokenAccount = await getMaybeMintAccount(tx.recipient, api);
908908

909909
if (mintTokenAccount instanceof Error) {
910-
throw recipientTokenAccount;
910+
throw mintTokenAccount;
911911
}
912912

913913
if (mintTokenAccount) {

libs/coin-modules/coin-solana/src/tests/tokens-bridge-integration.test.ts renamed to libs/coin-modules/coin-solana/src/tests/tokens-bridge.unit.test.ts

+122-4
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import cloneDeep from "lodash/cloneDeep";
33
import {
44
SolanaAccount,
55
SolanaTokenAccount,
6+
SolanaTokenProgram,
67
TokenTransferCommand,
78
TokenTransferTransaction,
89
Transaction,
@@ -24,7 +25,11 @@ import { prepareTransaction } from "../prepareTransaction";
2425
import { encodeAccountId } from "@ledgerhq/coin-framework/lib/account/accountId";
2526
import { NonTransferableExt, TransferFeeConfigExt } from "../network/chain/account/tokenExtensions";
2627
import { PublicKey } from "@solana/web3.js";
27-
import { ASSOCIATED_TOKEN_PROGRAM_ID, TOKEN_PROGRAM_ID } from "@solana/spl-token";
28+
import {
29+
ASSOCIATED_TOKEN_PROGRAM_ID,
30+
TOKEN_2022_PROGRAM_ID,
31+
TOKEN_PROGRAM_ID,
32+
} from "@solana/spl-token";
2833
import { calculateToken2022TransferFees } from "../helpers/token";
2934
import { PARSED_PROGRAMS } from "../network/chain/program/constants";
3035

@@ -58,8 +63,8 @@ const wSolSubAccId = encodeAccountIdWithTokenAccountAddress(mainAccId, testData.
5863
const wSolToken = findTokenByAddressInCurrency(testData.mintAddress, "solana") as TokenCurrency;
5964

6065
const baseAccount = {
61-
balance: new BigNumber(0),
62-
spendableBalance: new BigNumber(0),
66+
balance: new BigNumber(10000),
67+
spendableBalance: new BigNumber(10000),
6368
} as Account;
6469

6570
const baseAPI = {
@@ -83,11 +88,23 @@ const baseAPI = {
8388
},
8489
getSimulationComputeUnits: (_ixs: any[], _payer: any) => Promise.resolve(1000),
8590
getBalance: (_: string) => Promise.resolve(10),
91+
findAssocTokenAccAddress: (owner: string, mint: string, program: SolanaTokenProgram) => {
92+
return Promise.resolve(
93+
PublicKey.findProgramAddressSync(
94+
[
95+
new PublicKey(owner).toBuffer(),
96+
program === "spl-token" ? TOKEN_PROGRAM_ID.toBuffer() : TOKEN_2022_PROGRAM_ID.toBuffer(),
97+
new PublicKey(mint).toBuffer(),
98+
],
99+
ASSOCIATED_TOKEN_PROGRAM_ID,
100+
)[0].toBase58(),
101+
);
102+
},
86103
} as ChainAPI;
87104

88105
// Broken tests as the address used is not support anymore
89106
// Returning other errors we don't expect
90-
describe.skip("Solana tokens bridge integration tests", () => {
107+
describe("Solana tokens bridge integration tests", () => {
91108
const baseSolanaAccount: SolanaAccount = {
92109
...baseAccount,
93110
freshAddress: testData.address1,
@@ -234,13 +251,93 @@ describe.skip("Solana tokens bridge integration tests", () => {
234251
};
235252
};
236253

254+
test("token.transfer :: status is success", async () => {
255+
const api = {
256+
...baseAPI,
257+
getAccountInfo: (address: string) => {
258+
if (address === wSolToken.contractAddress) {
259+
return Promise.resolve(baseTokenMintMock as any);
260+
}
261+
if (address === testData.address2) {
262+
return Promise.resolve({ data: {} });
263+
}
264+
return Promise.resolve({ data: baseAtaMock } as any);
265+
},
266+
} as ChainAPI;
267+
268+
const account: SolanaAccount = {
269+
...baseSolanaAccount,
270+
subAccounts: [mockedTokenAcc],
271+
};
272+
273+
const preparedTx = await prepareTransaction(account, baseTx, api);
274+
const receivedTxStatus = await getTransactionStatus(account, preparedTx);
275+
const expectedTxStatus: TransactionStatus = {
276+
amount: new BigNumber(10),
277+
estimatedFees: new BigNumber(testData.fees),
278+
totalSpent: new BigNumber(10),
279+
errors: {},
280+
warnings: {},
281+
};
282+
283+
expect(receivedTxStatus).toEqual(expectedTxStatus);
284+
});
285+
286+
// Send flow
287+
test("token.transfer :: status is success: transfer with subAccountId", async () => {
288+
const api = {
289+
...baseAPI,
290+
getAccountInfo: (address: string) => {
291+
if (address === wSolToken.contractAddress) {
292+
return Promise.resolve(baseTokenMintMock as any);
293+
}
294+
if (address === testData.address2) {
295+
return Promise.resolve({ data: {} });
296+
}
297+
return Promise.resolve({ data: baseAtaMock } as any);
298+
},
299+
} as ChainAPI;
300+
301+
const account: SolanaAccount = {
302+
...baseSolanaAccount,
303+
subAccounts: [mockedTokenAcc],
304+
};
305+
306+
const transferTxWithSubAccountId: Transaction = {
307+
model: {
308+
kind: "transfer",
309+
uiState: {},
310+
},
311+
amount: new BigNumber(10),
312+
recipient: testData.address2,
313+
family: "solana",
314+
subAccountId: wSolSubAccId,
315+
};
316+
317+
const preparedTx = await prepareTransaction(account, transferTxWithSubAccountId, api);
318+
const receivedTxStatus = await getTransactionStatus(account, preparedTx);
319+
const expectedTxStatus: TransactionStatus = {
320+
amount: new BigNumber(10),
321+
estimatedFees: new BigNumber(testData.fees),
322+
totalSpent: new BigNumber(10),
323+
errors: {},
324+
warnings: {},
325+
};
326+
327+
expect(preparedTx.model.commandDescriptor?.command.kind).toEqual("token.transfer");
328+
expect(receivedTxStatus).toEqual(expectedTxStatus);
329+
});
330+
237331
test("token.transfer :: status is error: sender ATA is frozen", async () => {
238332
const api = {
239333
...baseAPI,
240334
getAccountInfo: (address: string) => {
241335
if (address === wSolToken.contractAddress) {
242336
return Promise.resolve(baseTokenMintMock as any);
243337
}
338+
if (address === testData.address2) {
339+
return Promise.resolve({ data: {} });
340+
}
244341
return Promise.resolve({ data: baseAtaMock } as any);
245342
},
246343
} as ChainAPI;
@@ -276,6 +373,9 @@ describe.skip("Solana tokens bridge integration tests", () => {
276373
if (address === wSolToken.contractAddress) {
277374
return Promise.resolve(baseTokenMintMock as any);
278375
}
376+
if (address === testData.address2) {
377+
return Promise.resolve({ data: {} });
378+
}
279379
return Promise.resolve({ data: frozenAtaMock } as any);
280380
},
281381
} as ChainAPI;
@@ -310,6 +410,9 @@ describe.skip("Solana tokens bridge integration tests", () => {
310410
if (address === wSolToken.contractAddress) {
311411
return Promise.resolve(baseToken2022MintMock as any);
312412
}
413+
if (address === testData.address2) {
414+
return Promise.resolve({ data: {} });
415+
}
313416
return Promise.resolve({ data: baseAta2022Mock } as any);
314417
},
315418
} as ChainAPI;
@@ -346,6 +449,9 @@ describe.skip("Solana tokens bridge integration tests", () => {
346449
if (address === wSolToken.contractAddress) {
347450
return Promise.resolve(baseToken2022MintMock as any);
348451
}
452+
if (address === testData.address2) {
453+
return Promise.resolve({ data: {} });
454+
}
349455
return Promise.resolve({ data: ataWithRequiredMemoMock } as any);
350456
},
351457
getBalance: () => Promise.resolve(10),
@@ -381,6 +487,9 @@ describe.skip("Solana tokens bridge integration tests", () => {
381487
if (address === wSolToken.contractAddress) {
382488
return Promise.resolve(mintWithTransferFeeMock as any);
383489
}
490+
if (address === testData.address2) {
491+
return Promise.resolve({ data: {} });
492+
}
384493
return Promise.resolve({ data: baseAta2022Mock });
385494
},
386495
getBalance: () => Promise.resolve(BigNumber(100).times(magnitude).toNumber()),
@@ -444,6 +553,9 @@ describe.skip("Solana tokens bridge integration tests", () => {
444553
if (address === wSolToken.contractAddress) {
445554
return Promise.resolve(mintWithTransferFeeMock as any);
446555
}
556+
if (address === testData.address2) {
557+
return Promise.resolve({ data: {} });
558+
}
447559
return Promise.resolve({ data: baseAta2022Mock });
448560
},
449561
getBalance: () => Promise.resolve(balance.toNumber()),
@@ -519,6 +631,9 @@ describe.skip("Solana tokens bridge integration tests", () => {
519631
if (address === wSolToken.contractAddress) {
520632
return Promise.resolve(mintWithTransferFeeMock as any);
521633
}
634+
if (address === testData.address2) {
635+
return Promise.resolve({ data: {} });
636+
}
522637
return Promise.resolve({ data: baseAta2022Mock });
523638
},
524639
getBalance: () => Promise.resolve(balance.toNumber()),
@@ -563,6 +678,9 @@ describe.skip("Solana tokens bridge integration tests", () => {
563678
if (address === wSolToken.contractAddress) {
564679
return Promise.resolve(mintWithNonTransferableExtensionMock as any);
565680
}
681+
if (address === testData.address2) {
682+
return Promise.resolve({ data: {} });
683+
}
566684
return Promise.resolve({ data: baseAta2022Mock } as any);
567685
},
568686
} as ChainAPI;

0 commit comments

Comments
 (0)