diff --git a/.changeset/blue-vans-try.md b/.changeset/blue-vans-try.md new file mode 100644 index 000000000000..5a21803067f0 --- /dev/null +++ b/.changeset/blue-vans-try.md @@ -0,0 +1,6 @@ +--- +"live-mobile": patch +"@ledgerhq/coin-framework": patch +--- + +Fix generate Accounts+NFTs in Debug diff --git a/apps/ledger-live-mobile/src/screens/Settings/Debug/Generators/GenerateMockAccountsNFTs.tsx b/apps/ledger-live-mobile/src/screens/Settings/Debug/Generators/GenerateMockAccountsNFTs.tsx index 76edde201b60..9925b25c5b43 100644 --- a/apps/ledger-live-mobile/src/screens/Settings/Debug/Generators/GenerateMockAccountsNFTs.tsx +++ b/apps/ledger-live-mobile/src/screens/Settings/Debug/Generators/GenerateMockAccountsNFTs.tsx @@ -8,6 +8,8 @@ import SettingsRow from "~/components/SettingsRow"; import accountModel from "~/logic/accountModel"; import { saveAccounts } from "../../../../db"; import { useReboot } from "~/context/Reboot"; +import { useFeatureFlags } from "@ledgerhq/live-common/featureFlags/index"; + import { initialState as liveWalletInitialState, accountUserDataExportSelector, @@ -32,7 +34,7 @@ async function injectMockAccountsInDB(count: number) { }); } -export default function GenerateMockAccountsButton({ +export default function GenerateMockAccountsAndNFTsButton({ count, title, desc, @@ -41,7 +43,12 @@ export default function GenerateMockAccountsButton({ desc: string; count: number; }) { + const featureFlagsProvider = useFeatureFlags(); const reboot = useReboot(); + + const disableSimpleHash = () => + featureFlagsProvider.overrideFeature("nftsFromSimplehash", { enabled: false }); + return ( { + disableSimpleHash(); await injectMockAccountsInDB(count); reboot(); }, diff --git a/libs/coin-framework/src/mocks/fixtures/nfts.test.ts b/libs/coin-framework/src/mocks/fixtures/nfts.test.ts index 77582492cfbc..09d8588c58de 100644 --- a/libs/coin-framework/src/mocks/fixtures/nfts.test.ts +++ b/libs/coin-framework/src/mocks/fixtures/nfts.test.ts @@ -11,11 +11,13 @@ describe("nfts fixtures", () => { expect(FIXTURE.tokenId).not.toBeUndefined(); expect(FIXTURE.id).toContain("account-mock"); - expect(NFTs.map(nft => nft.tokenId).includes(FIXTURE.tokenId)).toBeTruthy(); + expect(NFTs.map(nft => nft.collection.contract).includes(FIXTURE.contract)).toBeTruthy(); const FIXTURE_POL = createFixtureNFT("account-mock-pol", POL); expect(FIXTURE_POL.currencyId).toEqual("polygon"); - expect(NFTs_POLYGON.map(nft => nft.tokenId).includes(FIXTURE_POL.tokenId)).toBeTruthy(); + expect( + NFTs_POLYGON.map(nft => nft.collection.contract).includes(FIXTURE_POL.contract), + ).toBeTruthy(); }); }); diff --git a/libs/coin-framework/src/mocks/fixtures/nfts.ts b/libs/coin-framework/src/mocks/fixtures/nfts.ts index de68f542ada1..d8551e337c13 100644 --- a/libs/coin-framework/src/mocks/fixtures/nfts.ts +++ b/libs/coin-framework/src/mocks/fixtures/nfts.ts @@ -1,6 +1,13 @@ import BigNumber from "bignumber.js"; import type { CryptoCurrency } from "@ledgerhq/types-cryptoassets"; -import type { Account, AccountLike, NFTStandard, Operation, ProtoNFT } from "@ledgerhq/types-live"; +import type { + Account, + AccountLike, + NFTMetadata, + NFTStandard, + Operation, + ProtoNFT, +} from "@ledgerhq/types-live"; import { cryptocurrenciesById } from "@ledgerhq/cryptoassets"; import Prando from "prando"; import { inferSubOperations } from "../../serialization"; @@ -9,292 +16,34 @@ import { encodeNftId } from "../../nft/nftId"; const defaultEthCryptoFamily = cryptocurrenciesById["ethereum"]; +const MAX_SUPPLY = 1000; + export const NFTs = [ { - id: "js:2:ethereum:0xB98d10d9f6d07bA283bFD21B2dFEc050f9Ae282A:+0xb1540922Be7c7Ed011cb41cc0Cc4adDf089b3AaF+7833", - tokenId: "7833", - amount: "1", - collection: { - contract: "0xb1540922Be7c7Ed011cb41cc0Cc4adDf089b3AaF", - standard: "ERC721", - }, - }, - { - id: "js:2:ethereum:0xB98d10d9f6d07bA283bFD21B2dFEc050f9Ae282A:+0xb1540922Be7c7Ed011cb41cc0Cc4adDf089b3AaF+2372", - tokenId: "2372", - amount: "1", - collection: { - contract: "0xb1540922Be7c7Ed011cb41cc0Cc4adDf089b3AaF", - standard: "ERC721", - }, - }, - { - id: "js:2:ethereum:0xB98d10d9f6d07bA283bFD21B2dFEc050f9Ae282A:+0x9191DFd6Ec2Ec31A7aaE86D89B44f94a70096194+203", - tokenId: "203", - amount: "1", - collection: { - contract: "0x9191DFd6Ec2Ec31A7aaE86D89B44f94a70096194", - standard: "ERC721", - }, - }, - { - id: "js:2:ethereum:0xB98d10d9f6d07bA283bFD21B2dFEc050f9Ae282A:+0x65498bF901A0C47ba9507C8a778d2bdee4Db12b4+4628", - tokenId: "4628", - amount: "1", - collection: { - contract: "0x65498bF901A0C47ba9507C8a778d2bdee4Db12b4", - standard: "ERC721", - }, - }, - { - id: "js:2:ethereum:0xB98d10d9f6d07bA283bFD21B2dFEc050f9Ae282A:+0x85ff6EC2BD7446C90F24F6a5e5acdD82Bcd2D4BE+4628", - tokenId: "4628", - amount: "1", - collection: { - contract: "0x85ff6EC2BD7446C90F24F6a5e5acdD82Bcd2D4BE", - standard: "ERC721", - }, - }, - { - id: "js:2:ethereum:0xB98d10d9f6d07bA283bFD21B2dFEc050f9Ae282A:+0x495f947276749Ce646f68AC8c248420045cb7b5e+15219551248750507857885240633851073364192113972571174309573660185104102719489", - tokenId: "15219551248750507857885240633851073364192113972571174309573660185104102719489", - amount: "1", - collection: { - contract: "0x495f947276749Ce646f68AC8c248420045cb7b5e", - standard: "ERC1155", - }, - }, - { - id: "js:2:ethereum:0xB98d10d9f6d07bA283bFD21B2dFEc050f9Ae282A:+0x7A56a078da312bbfB5916CE118786f39cf6DF74f+323", - tokenId: "323", - amount: "1", - collection: { - contract: "0x7A56a078da312bbfB5916CE118786f39cf6DF74f", - standard: "ERC721", - }, - }, - { - id: "js:2:ethereum:0xB98d10d9f6d07bA283bFD21B2dFEc050f9Ae282A:+0x7A56a078da312bbfB5916CE118786f39cf6DF74f+711", - tokenId: "711", - amount: "1", - collection: { - contract: "0x7A56a078da312bbfB5916CE118786f39cf6DF74f", - standard: "ERC721", - }, - }, - { - id: "js:2:ethereum:0xB98d10d9f6d07bA283bFD21B2dFEc050f9Ae282A:+0xCa98FdF936243Edc3bbD65dc1dCc386Ec7a7d540+1203", - tokenId: "1203", - amount: "1", - collection: { - contract: "0xCa98FdF936243Edc3bbD65dc1dCc386Ec7a7d540", - standard: "ERC721", - }, - }, - { - id: "js:2:ethereum:0xB98d10d9f6d07bA283bFD21B2dFEc050f9Ae282A:+0xCa98FdF936243Edc3bbD65dc1dCc386Ec7a7d540+203", - tokenId: "203", - amount: "1", - collection: { - contract: "0xCa98FdF936243Edc3bbD65dc1dCc386Ec7a7d540", - standard: "ERC721", - }, - }, - { - id: "js:2:ethereum:0xB98d10d9f6d07bA283bFD21B2dFEc050f9Ae282A:+0xA04C6BD65E4352B30DCc6B0f21CF58aDEcc52781+16", - tokenId: "16", - amount: "1", - collection: { - contract: "0xA04C6BD65E4352B30DCc6B0f21CF58aDEcc52781", - standard: "ERC721", - }, - }, - { - id: "js:2:ethereum:0xB98d10d9f6d07bA283bFD21B2dFEc050f9Ae282A:+0xA35f12D3b934E21b9212e82f3CADdE20a0820352+5502", - tokenId: "5502", - amount: "1", - collection: { - contract: "0xA35f12D3b934E21b9212e82f3CADdE20a0820352", - standard: "ERC721", - }, - }, - { - id: "js:2:ethereum:0xB98d10d9f6d07bA283bFD21B2dFEc050f9Ae282A:+0x8e6da68d4a928e673b3A24014169515B293Ed5A4+19896", - tokenId: "19896", - amount: "1", - collection: { - contract: "0x8e6da68d4a928e673b3A24014169515B293Ed5A4", - standard: "ERC721", - }, - }, - { - id: "js:2:ethereum:0xB98d10d9f6d07bA283bFD21B2dFEc050f9Ae282A:+0x27fd9575a484E374B8e62B6738b5FbF415C9Be4E+112", - tokenId: "112", - amount: "1", - collection: { - contract: "0x27fd9575a484E374B8e62B6738b5FbF415C9Be4E", - standard: "ERC721", - }, - }, - { - id: "js:2:ethereum:0xB98d10d9f6d07bA283bFD21B2dFEc050f9Ae282A:+0x8e6da68d4a928e673b3A24014169515B293Ed5A4+13885", - tokenId: "13885", - amount: "1", - collection: { - contract: "0x8e6da68d4a928e673b3A24014169515B293Ed5A4", - standard: "ERC721", - }, - }, - { - id: "js:2:ethereum:0xB98d10d9f6d07bA283bFD21B2dFEc050f9Ae282A:+0x1447Cd4d3CE6C7FdB0da8d20450d92b08F7c4A54+1208", - tokenId: "1208", - amount: "1", + id: "Pudgy Penguin", collection: { - contract: "0x1447Cd4d3CE6C7FdB0da8d20450d92b08F7c4A54", + contract: "0xbd3531da5cf5857e7cfaa92426877b022e612cf8", standard: "ERC721", }, }, { - id: "js:2:ethereum:0xB98d10d9f6d07bA283bFD21B2dFEc050f9Ae282A:+0xb1778D7Aa4a384757800D1429DfCae58dCD6DB42+1", - tokenId: "1", - amount: "1", + id: "Kanpai Panda", collection: { - contract: "0xb1778D7Aa4a384757800D1429DfCae58dCD6DB42", - standard: "ERC1155", - }, - }, - { - id: "js:2:ethereum:0xB98d10d9f6d07bA283bFD21B2dFEc050f9Ae282A:+0xf61F24c2d93bF2dE187546B14425BF631F28d6dC+4628", - tokenId: "4628", - amount: "1", - collection: { - contract: "0xf61F24c2d93bF2dE187546B14425BF631F28d6dC", - standard: "ERC721", - }, - }, - { - id: "js:2:ethereum:0xB98d10d9f6d07bA283bFD21B2dFEc050f9Ae282A:+0x8e6da68d4a928e673b3A24014169515B293Ed5A4+11117", - tokenId: "11117", - amount: "1", - collection: { - contract: "0x8e6da68d4a928e673b3A24014169515B293Ed5A4", - standard: "ERC721", - }, - }, - { - id: "js:2:ethereum:0xB98d10d9f6d07bA283bFD21B2dFEc050f9Ae282A:+0x184c949436f6E4e8314dA3F4d78B2D38B0222823+3634", - tokenId: "3634", - amount: "1", - collection: { - contract: "0x184c949436f6E4e8314dA3F4d78B2D38B0222823", - standard: "ERC721", - }, - }, - { - id: "js:2:ethereum:0xB98d10d9f6d07bA283bFD21B2dFEc050f9Ae282A:+0x184c949436f6E4e8314dA3F4d78B2D38B0222823+1229", - tokenId: "1229", - amount: "1", - collection: { - contract: "0x184c949436f6E4e8314dA3F4d78B2D38B0222823", - standard: "ERC721", - }, - }, - { - id: "js:2:ethereum:0xB98d10d9f6d07bA283bFD21B2dFEc050f9Ae282A:+0x8e6da68d4a928e673b3A24014169515B293Ed5A4+2278", - tokenId: "2278", - amount: "1", - collection: { - contract: "0x8e6da68d4a928e673b3A24014169515B293Ed5A4", - standard: "ERC721", - }, - }, - { - id: "js:2:ethereum:0xB98d10d9f6d07bA283bFD21B2dFEc050f9Ae282A:+0x2963bA471e265e5F51cAfaFca78310FE87F8E6D1+6348", - tokenId: "6348", - amount: "1", - collection: { - contract: "0x2963bA471e265e5F51cAfaFca78310FE87F8E6D1", - standard: "ERC721", - }, - }, - { - id: "js:2:ethereum:0xB98d10d9f6d07bA283bFD21B2dFEc050f9Ae282A:+0xFBeef911Dc5821886e1dda71586d90eD28174B7d+76100", - tokenId: "76100", - amount: "1", - collection: { - contract: "0xFBeef911Dc5821886e1dda71586d90eD28174B7d", - standard: "ERC721", - }, - }, - { - id: "js:2:ethereum:0xB98d10d9f6d07bA283bFD21B2dFEc050f9Ae282A:+0xBEA73B677c2A8ec4d358a74ff5EC344F34a0d214+7281", - tokenId: "7281", - amount: "1", - collection: { - contract: "0xBEA73B677c2A8ec4d358a74ff5EC344F34a0d214", - standard: "ERC721", - }, - }, - { - id: "js:2:ethereum:0xB98d10d9f6d07bA283bFD21B2dFEc050f9Ae282A:+0xd929FB5B7357Ed59ba770af812eFC116f873C795+1", - tokenId: "1", - amount: "1", - collection: { - contract: "0xd929FB5B7357Ed59ba770af812eFC116f873C795", - standard: "ERC1155", - }, - }, - { - id: "js:2:ethereum:0xB98d10d9f6d07bA283bFD21B2dFEc050f9Ae282A:+0xd1169e5349d1cB9941F3DCbA135C8A4b9eACFDDE+171000106229", - tokenId: "171000106229", - amount: "1", - collection: { - contract: "0xd1169e5349d1cB9941F3DCbA135C8A4b9eACFDDE", - standard: "ERC721", - }, - }, - { - id: "js:2:ethereum:0xB98d10d9f6d07bA283bFD21B2dFEc050f9Ae282A:+0x6315d09bc75eE00B767142C05265Eeb180765093+559", - tokenId: "559", - amount: "1", - collection: { - contract: "0x6315d09bc75eE00B767142C05265Eeb180765093", - standard: "ERC721", - }, - }, - { - id: "js:2:ethereum:0xB98d10d9f6d07bA283bFD21B2dFEc050f9Ae282A:+0xDDB149AE8E6635Df01a530da1E46921Bd78Dc385+1", - tokenId: "1", - amount: "1", - collection: { - contract: "0xDDB149AE8E6635Df01a530da1E46921Bd78Dc385", - standard: "ERC1155", - }, - }, - { - id: "js:2:ethereum:0xB98d10d9f6d07bA283bFD21B2dFEc050f9Ae282A:+0xABB3738f04Dc2Ec20f4AE4462c3d069d02AE045B+9602000", - tokenId: "9602000", - amount: "1", - collection: { - contract: "0xABB3738f04Dc2Ec20f4AE4462c3d069d02AE045B", + contract: "0xacf63e56fd08970b43401492a02f6f38b6635c91", standard: "ERC721", }, }, { - id: "js:2:ethereum:0xB98d10d9f6d07bA283bFD21B2dFEc050f9Ae282A:+0xABB3738f04Dc2Ec20f4AE4462c3d069d02AE045B+9640021", - tokenId: "9640021", - amount: "1", + id: "Bored Ape Yacht Club", collection: { - contract: "0xABB3738f04Dc2Ec20f4AE4462c3d069d02AE045B", + contract: "0xacf63e56fd08970b43401492a02f6f38b6635c91", standard: "ERC721", }, }, { - id: "js:2:ethereum:0xB98d10d9f6d07bA283bFD21B2dFEc050f9Ae282A:+0xa7d8d9ef8D8Ce8992Df33D8b8CF4Aebabd5bD270+282001002", - tokenId: "282001002", - amount: "1", + id: "Imaginary Ones", collection: { - contract: "0xa7d8d9ef8D8Ce8992Df33D8b8CF4Aebabd5bD270", + contract: "0x716f29b8972d551294d9e02b3eb0fc1107fbf4aa", standard: "ERC721", }, }, @@ -303,9 +52,7 @@ export const NFTs = [ // Ethereum NFTs with the special "staxImage" metadata designed to fit the Ledger Stax screen export const NFTs_ETHEREUM_STAX_METADATA = [ { - id: "js:2:ethereum:0xB98d10d9f6d07bA283bFD21B2dFEc050f9Ae282A:+0x0b51eb9d0e54c562fedc07ceba453f05b70c4b79+1", - tokenId: "1", - amount: "1", + id: "Inspired By Ledger", collection: { contract: "0x0b51eb9d0e54c562fedc07ceba453f05b70c4b79", standard: "ERC1155", @@ -315,35 +62,28 @@ export const NFTs_ETHEREUM_STAX_METADATA = [ export const NFTs_POLYGON = [ { - id: "js:2:ethereum:0xB98d10d9f6d07bA283bFD21B2dFEc050f9Ae282A:+0x68a0B29526f342de944BBd6bF61D9c644B96b771+7", - tokenId: "7", - amount: "1", + id: "Crypto Unicorns Market", collection: { - contract: "0x68a0B29526f342de944BBd6bF61D9c644B96b771", - standard: "ERC1155", + contract: "0xdc0479cc5bba033b3e7de9f178607150b3abce1f", + standard: "ERC721", }, }, - { - id: "js:2:ethereum:0xB98d10d9f6d07bA283bFD21B2dFEc050f9Ae282A:+0x68a0b29526f342de944bbd6bf61d9c644b96b771+4", - tokenId: "4", - amount: "1", + id: "Chicken Derby", collection: { - contract: "0x68a0b29526f342de944bbd6bf61d9c644b96b771", - standard: "ERC1155", + contract: "0x8634666ba15ada4bbc83b9dbf285f73d9e46e4c2", + standard: "ERC721", }, }, - { - id: "js:2:ethereum:0xB98d10d9f6d07bA283bFD21B2dFEc050f9Ae282A:+0x68a0b29526f342de944bbd6bf61d9c644b96b771+3", - tokenId: "3", - amount: "1", + id: "y00ts", collection: { - contract: "0x68a0b29526f342de944bbd6bf61d9c644b96b771", - standard: "ERC1155", + contract: "0x670fd103b1a08628e9557cd66b87ded841115190", + standard: "ERC721", }, }, ]; + export function createFixtureNFT( accountId: string, currency: CryptoCurrency = defaultEthCryptoFamily, @@ -352,16 +92,19 @@ export function createFixtureNFT( const nfts = currency.id === "ethereum" ? (useStaxNFTs ? NFTs_ETHEREUM_STAX_METADATA : NFTs) : NFTs_POLYGON; const index = Math.floor(Math.random() * nfts.length); - + const tokenId = useStaxNFTs ? String(13) : String(Math.floor(Math.random() * MAX_SUPPLY) + 1); const nft = nfts[index]; + return { - id: encodeNftId(accountId, nft.collection.contract, nft.tokenId, currency.id), - tokenId: nft.tokenId, + id: encodeNftId(accountId, nft.collection.contract, tokenId, currency.id), + tokenId: tokenId, amount: new BigNumber(0), contract: nft.collection.contract, standard: nft.collection.standard as NFTStandard, currencyId: currency.id, - metadata: undefined, + metadata: useStaxNFTs + ? ({ staxImage: "https://example.com/image.png" } as NFTMetadata) + : undefined, }; } diff --git a/libs/live-nft-react/src/hooks/__tests__/useNftGalleryFilter.test.tsx b/libs/live-nft-react/src/hooks/__tests__/useNftGalleryFilter.test.tsx index c8558c3a3cb9..053b2a67b1c2 100644 --- a/libs/live-nft-react/src/hooks/__tests__/useNftGalleryFilter.test.tsx +++ b/libs/live-nft-react/src/hooks/__tests__/useNftGalleryFilter.test.tsx @@ -13,17 +13,37 @@ jest.setTimeout(30000); // invoke callback instantly notifyManager.setScheduler(cb => cb()); -// TODO better way to make ProtoNFT[] collection -const nftsOwned = NFTs.map(nft => ({ - id: encodeNftId("foo", nft.collection.contract, nft.tokenId, "ethereum"), - tokenId: nft.tokenId, - amount: new BigNumber(0), - contract: nft.collection.contract, - standard: "ERC721" as const, - currencyId: "ethereum", - metadata: undefined, -})); +type FakeNFTRaw = { + id: string; + tokenId: string; + amount: BigNumber; + contract: string; + standard: "ERC721"; + currencyId: string; + metadata: undefined; +}; +const generateNftsOwned = () => { + const nfts: FakeNFTRaw[] = []; + + NFTs.forEach(nft => { + for (let i = 1; i <= 20; i++) { + nfts.push({ + id: encodeNftId("foo", nft.collection.contract, String(i), "ethereum"), + tokenId: String(i), + amount: new BigNumber(0), + contract: nft.collection.contract, + standard: "ERC721" as const, + currencyId: "ethereum", + metadata: undefined, + }); + } + }); + + return nfts; +}; +// TODO better way to make ProtoNFT[] collection +const nftsOwned = generateNftsOwned(); let expected = [...new Set(nftsOwned)]; expected.sort(() => Math.random() - 0.5); expected = expected.slice(3); @@ -86,25 +106,22 @@ describe("useNftGalleryFilter", () => { await waitFor(() => result.current.data); - await act(() => expect(callCount).toBe(1)); - await act(() => expect(result.current.nfts).toEqual(expected.slice(0, pagedBy))); - - result.current.fetchNextPage(); + expect(callCount).toBe(1); + expect(result.current.nfts).toEqual(expected.slice(0, pagedBy)); - await act(() => expect(callCount).toBe(2)); - await act(() => expect(result.current.nfts).toEqual(expected.slice(0, pagedBy * 2))); + await act(() => result.current.fetchNextPage()); + expect(callCount).toBe(2); + expect(result.current.nfts).toEqual(expected.slice(0, pagedBy * 2)); // FIXME something not working here - /* - let n = 2; - while (result.current.hasNextPage) { - console.warn("fetching next page", n); - await act(() => result.current.fetchNextPage()); - await act(() => expect(callCount).toBe(++n)); - await act(() => expect(result.current.nfts).toBe(expected.slice(0, pagedBy * n))); - } - await act(() => expect(result.current.nfts).toEqual(expected)); - */ + + // let n = 2; + // while (result.current.hasNextPage) { + // await act(() => result.current.fetchNextPage()); + // expect(callCount).toBe(++n); + // expect(result.current.nfts).toBe(expected.slice(0, pagedBy * n)); + // } + // expect(result.current.nfts).toEqual(expected); }); test("Threshold validity", async () => {