Skip to content
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
34 changes: 34 additions & 0 deletions .changeset/purple-bats-march.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
"thirdweb": patch
---

Use insight for erc821/getNFT, erc721/getNFTs and erc721/getOwnedNFTs

Standard ERC721 getNFT, getNFTs and getOwnedNFTs now use insight, our in house indexer by default. If indexer is not availbale, will fallback to RPC.

You can also use the indexer directly using the Insight API:

for an entire collection

```ts
import { Insight } from "thirdweb";

const events = await Insight.getContractNFTs({
client,
chains: [sepolia],
contractAddress: "0x1234567890123456789012345678901234567890",
});
```

or for a single NFT

```ts
import { Insight } from "thirdweb";

const events = await Insight.getNFT({
client,
chains: [sepolia],
contractAddress: "0x1234567890123456789012345678901234567890",
tokenId: 1n,
});
```
1 change: 1 addition & 0 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
TW_SECRET_KEY: ${{ secrets.TW_SECRET_KEY }}
TW_CLIENT_ID: ${{ secrets.TW_CLIENT_ID }}
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

jobs:
Expand Down
3 changes: 3 additions & 0 deletions apps/dashboard/src/@/actions/getWalletNFTs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ export async function getWalletNFTs(params: {
const result = await transformMoralisResponseToNFT(
await parsedResponse,
owner,
chainId,
);

return { result };
Expand Down Expand Up @@ -194,6 +195,8 @@ async function getWalletNFTsFromInsight(params: {
tokenURI: nft.metadata_url,
type: nft.token_type === "erc721" ? "ERC721" : "ERC1155",
supply: nft.balance,
tokenAddress: nft.contract.address,
chainId: nft.contract.chain_id,
};

return walletNFT;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,8 @@ export const CreateListingsForm: React.FC<CreateListingsFormProps> = ({
owner: nft.owner,
type: "ERC721",
tokenURI: nft.tokenURI,
chainId: nft.chainId,
tokenAddress: nft.tokenAddress,
};
}
return {
Expand All @@ -216,6 +218,8 @@ export const CreateListingsForm: React.FC<CreateListingsFormProps> = ({
owner: nft.owner,
type: "ERC1155",
tokenURI: nft.tokenURI,
chainId: nft.chainId,
tokenAddress: nft.tokenAddress,
};
}) as WalletNFT[];
}, [ownedNFTs, form]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const dummyMetadata: (idx: number) => NFTWithContract = (idx) => ({
owner: `0x_fake_${idx}`,
type: "ERC721",
supply: 1n,
tokenAddress: ZERO_ADDRESS,
});

interface NFTCardsProps {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export const NftsOwned: React.FC<NftsOwnedProps> = ({
type: nft.type,
contractAddress: nft.contractAddress,
chainId: contract.chain.id,
tokenAddress: nft.tokenAddress,
}))}
allNfts
isPending={isWalletNFTsLoading}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { SkeletonContainer } from "@/components/ui/skeleton";
import { TrackedLinkTW } from "@/components/ui/tracked-link";
import { ArrowRightIcon } from "lucide-react";
import { useMemo } from "react";
import type { ThirdwebContract } from "thirdweb";
import { type ThirdwebContract, ZERO_ADDRESS } from "thirdweb";
import {
type DirectListing,
type EnglishAuction,
Expand Down Expand Up @@ -237,13 +237,17 @@ const dummyMetadata: (idx: number) => ListingData = (idx) => ({
supply: BigInt(1),
tokenURI: "",
type: "ERC721",
tokenAddress: ZERO_ADDRESS,
chainId: 1,
},
currencyValuePerToken: {
decimals: 18,
displayValue: "0.0",
name: "Ether",
symbol: "ETH",
value: 0n,
tokenAddress: ZERO_ADDRESS,
chainId: 1,
},
creatorAddress: "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef",
type: "direct-listing",
Expand All @@ -253,6 +257,8 @@ const dummyMetadata: (idx: number) => ListingData = (idx) => ({
value: 0n,
displayValue: "0.0",
decimals: 18,
tokenAddress: ZERO_ADDRESS,
chainId: 1,
},
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,15 @@ export const TokenDetailsCard: React.FC<TokenBalancesProps> = ({
tokenSupplyQuery.data,
tokenMetadataQuery.data.decimals,
),
tokenAddress: contract.address,
chainId: contract.chain.id,
};
}, [tokenMetadataQuery.data, tokenSupplyQuery.data]);
}, [
tokenMetadataQuery.data,
tokenSupplyQuery.data,
contract.address,
contract.chain.id,
]);

return (
<TokenDetailsCardUI
Expand Down
3 changes: 3 additions & 0 deletions apps/dashboard/src/lib/wallet/nfts/moralis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export function generateMoralisUrl({ chainId, owner }: GenerateURLParams) {
export async function transformMoralisResponseToNFT(
moralisResponse: MoralisResponse,
owner: string,
chainId: number,
): Promise<WalletNFT[]> {
return (
await Promise.all(
Expand All @@ -47,6 +48,8 @@ export async function transformMoralisResponseToNFT(
tokenURI: moralisNft.token_uri,
supply: moralisNft.amount || "1",
type: moralisNft.contract_type,
tokenAddress: moralisNft.token_address,
chainId,
} as WalletNFT;
} catch {
return undefined as unknown as WalletNFT;
Expand Down
10 changes: 6 additions & 4 deletions packages/thirdweb/src/chains/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -296,8 +296,9 @@
`https://api.thirdweb.com/v1/chains/${chainId}`,
);
if (!res.ok) {
res.body?.cancel();
throw new Error(`Failed to fetch chain data for chainId ${chainId}`);
throw new Error(
`Failed to fetch chain data for chainId ${chainId}. ${res.status} ${res.statusText}`,
);
}

const response = (await res.json()) as FetchChainResponse;
Expand Down Expand Up @@ -356,8 +357,9 @@
`https://api.thirdweb.com/v1/chains/${chainId}/services`,
);
if (!res.ok) {
res.body?.cancel();
throw new Error(`Failed to fetch services for chainId ${chainId}`);
throw new Error(
`Failed to fetch services for chainId ${chainId}. ${res.status} ${res.statusText}`,
);

Check warning on line 362 in packages/thirdweb/src/chains/utils.ts

View check run for this annotation

Codecov / codecov/patch

packages/thirdweb/src/chains/utils.ts#L360-L362

Added lines #L360 - L362 were not covered by tests
}

const response = (await res.json()) as FetchChainServiceResponse;
Expand Down
14 changes: 1 addition & 13 deletions packages/thirdweb/src/event/actions/get-events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
ExtractAbiEventNames,
} from "abitype";
import { type Log, formatLog } from "viem";
import { getChainServices } from "../../chains/utils.js";
import { resolveContractAbi } from "../../contract/actions/resolve-abi.js";
import type { ThirdwebContract } from "../../contract/contract.js";
import { getContractEvents as getContractEventsInsight } from "../../insight/get-events.js";
Expand Down Expand Up @@ -197,7 +196,7 @@
),
);
} catch (e) {
console.warn("Error fetching from insight", e);
console.warn("Error fetching from insight, falling back to rpc", e);

Check warning on line 199 in packages/thirdweb/src/event/actions/get-events.ts

View check run for this annotation

Codecov / codecov/patch

packages/thirdweb/src/event/actions/get-events.ts#L199

Added line #L199 was not covered by tests
// fetch from rpc
logs = await Promise.all(
logsParams.map((ethLogParams) => eth_getLogs(rpcRequest, ethLogParams)),
Expand Down Expand Up @@ -225,17 +224,6 @@
}): Promise<Log[]> {
const { params, contract } = options;

const chainServices = await getChainServices(contract.chain);
const insightEnabled = chainServices.some(
(c) => c.service === "insight" && c.enabled,
);

if (!insightEnabled) {
throw new Error(
`Insight is not available for chainId ${contract.chain.id}`,
);
}

const fromBlock =
typeof params.fromBlock === "bigint" ? Number(params.fromBlock) : undefined;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ describe.runIf(process.env.TW_SECRET_KEY)("erc1155.getNFT", () => {
});
expect(nft).toMatchInlineSnapshot(`
{
"chainId": 1,
"id": 2n,
"metadata": {
"animation_url": "ipfs://QmYoM63qaumQznBRx38tQjkY4ewbymeFb2KWBhkfMqNHax/3.mp4",
Expand All @@ -36,6 +37,7 @@ describe.runIf(process.env.TW_SECRET_KEY)("erc1155.getNFT", () => {
},
"owner": null,
"supply": 2519n,
"tokenAddress": "0x42d3641255C946CC451474295d29D3505173F22A",
"tokenURI": "ipfs://QmbMXdbnNUAuGRoY6c6G792c6T9utfaBGqRUaMaRUf52Cb/2",
"type": "ERC1155",
}
Expand Down
2 changes: 2 additions & 0 deletions packages/thirdweb/src/extensions/erc1155/read/getNFT.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ export async function getNFT(
type: "ERC1155",
owner: null,
supply,
tokenAddress: options.contract.address,
chainId: options.contract.chain.id,
},
);
}
Loading
Loading