[Dashboard] Remove extensionDetectedState (#4557)

<!-- start pr-codex -->

## PR-Codex overview
This PR focuses on exposing Marketplace extensions for feature detection. It updates extension detection states and refactors extension method imports.

### Detailed summary
- Exposed Marketplace extensions for feature detection
- Refactored extension method imports to use `ExtensionDetectedState`
- Added functions to check support for specific methods in Marketplace extensions

> The following files were skipped due to too many changes: `packages/thirdweb/src/extensions/marketplace/direct-listings/read/getListing.ts`, `packages/thirdweb/src/extensions/marketplace/direct-listings/write/buyFromListing.ts`, `packages/thirdweb/src/exports/extensions/marketplace.ts`, `packages/thirdweb/src/extensions/marketplace/english-auctions/read/getWinningBid.ts`, `packages/thirdweb/src/extensions/marketplace/english-auctions/write/bidInAuction.ts`, `apps/dashboard/src/contract-ui/hooks/useRouteConfig.tsx`

> ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}`

<!-- end pr-codex -->
This commit is contained in:
kien-ngo
2024-09-14 01:26:53 +00:00
parent b142b8a893
commit fb0daabbf6
20 changed files with 225 additions and 148 deletions
+5
View File
@@ -0,0 +1,5 @@
---
"thirdweb": patch
---
Expose some Marketplace extensions for detecting supported features
@@ -1,65 +0,0 @@
import type { useContract } from "@thirdweb-dev/react";
import {
type ContractWrapper,
type FeatureName,
detectContractFeature,
} from "@thirdweb-dev/sdk";
interface ExtensionDetectedStateParams {
/**
* The feature or features to check
*/
feature: FeatureName | FeatureName[];
/**
* The contract instance to check
*/
contractQuery: ReturnType<typeof useContract>;
/**
* the feature match strategy (default: any)
* - any: any of the features must be available
* - all: all of the features must be available
*/
matchStrategy?: "any" | "all";
}
export type ExtensionDetectedState = "enabled" | "disabled" | "loading";
export function extensionDetectedState({
contractQuery,
feature,
matchStrategy = "any",
}: ExtensionDetectedStateParams): ExtensionDetectedState {
// if contract is loading return "loading"
if ("contract" in contractQuery && contractQuery.isLoading) {
return "loading";
}
const actualContract =
"contract" in contractQuery ? contractQuery.contract : contractQuery;
// we're not loading but don't have a contract, so we'll assumed feature is disabled (really this is an error state?)
if (!actualContract) {
return "disabled";
}
// biome-ignore lint/suspicious/noExplicitAny: FIXME
const contractWrapper = // biome-ignore lint/suspicious/noExplicitAny: FIXME
(actualContract as any).contractWrapper as ContractWrapper<any>;
if (!Array.isArray(feature)) {
return detectContractFeature(contractWrapper, feature)
? "enabled"
: "disabled";
}
if (matchStrategy === "all") {
return feature.every((f) => detectContractFeature(contractWrapper, f))
? "enabled"
: "disabled";
}
return feature.some((f) => detectContractFeature(contractWrapper, f))
? "enabled"
: "disabled";
}
@@ -0,0 +1 @@
export type ExtensionDetectedState = "enabled" | "disabled" | "loading";
@@ -1,6 +1,3 @@
import { useContract } from "@thirdweb-dev/react";
import { extensionDetectedState } from "components/buttons/ExtensionDetectButton";
import { useEns } from "components/contract-components/hooks";
import { ContractOverviewPage } from "contract-ui/tabs/overview/page"; import { ContractOverviewPage } from "contract-ui/tabs/overview/page";
import type { EnhancedRoute } from "contract-ui/types/types"; import type { EnhancedRoute } from "contract-ui/types/types";
import dynamic from "next/dynamic"; import dynamic from "next/dynamic";
@@ -11,6 +8,7 @@ import * as ERC20Ext from "thirdweb/extensions/erc20";
import * as ERC721Ext from "thirdweb/extensions/erc721"; import * as ERC721Ext from "thirdweb/extensions/erc721";
import * as ERC1155Ext from "thirdweb/extensions/erc1155"; import * as ERC1155Ext from "thirdweb/extensions/erc1155";
import * as ERC4337Ext from "thirdweb/extensions/erc4337"; import * as ERC4337Ext from "thirdweb/extensions/erc4337";
import * as MarketplaceExt from "thirdweb/extensions/marketplace";
import * as PermissionExt from "thirdweb/extensions/permissions"; import * as PermissionExt from "thirdweb/extensions/permissions";
import * as ThirdwebExt from "thirdweb/extensions/thirdweb"; import * as ThirdwebExt from "thirdweb/extensions/thirdweb";
import * as ModularExt from "thirdweb/modules"; import * as ModularExt from "thirdweb/modules";
@@ -229,35 +227,25 @@ export function useContractRouteConfig(
].every(Boolean); ].every(Boolean);
}, [functionSelectorQuery.data]); }, [functionSelectorQuery.data]);
// old const isDirectListing = useMemo(() => {
const ensQuery = useEns(contract.address); return [
MarketplaceExt.isCreateListingSupported(functionSelectorQuery.data),
MarketplaceExt.isCancelListingSupported(functionSelectorQuery.data),
MarketplaceExt.isBuyFromListingSupported(functionSelectorQuery.data),
].every(Boolean);
}, [functionSelectorQuery.data]);
// TODO: remove const isEnglishAuction = useMemo(() => {
const contractQuery = useContract(ensQuery.data?.address); return [
// TODO: remove all below MarketplaceExt.isCreateAuctionSupported(functionSelectorQuery.data),
const contractData = useMemo(() => { MarketplaceExt.isCancelAuctionSupported(functionSelectorQuery.data),
const detectedEnglishAuctions = extensionDetectedState({ MarketplaceExt.isBidInAuctionSupported(functionSelectorQuery.data),
contractQuery, ].every(Boolean);
feature: "EnglishAuctions", }, [functionSelectorQuery.data]);
});
const detectedDirectListings = extensionDetectedState({
contractQuery,
feature: "DirectListings",
});
return {
detectedEnglishAuctions,
detectedDirectListings,
};
}, [contractQuery]);
const embedType: "marketplace-v3" | "erc20" | "erc1155" | "erc721" | null = const embedType: "marketplace-v3" | "erc20" | "erc1155" | "erc721" | null =
useMemo(() => { useMemo(() => {
if ( if (isEnglishAuction && isDirectListing) {
contractData.detectedEnglishAuctions === "enabled" &&
contractData.detectedDirectListings === "enabled"
) {
// this means its marketplace v3 // this means its marketplace v3
return "marketplace-v3"; return "marketplace-v3";
} }
@@ -277,10 +265,11 @@ export function useContractRouteConfig(
// otherwise null // otherwise null
return null; return null;
}, [ }, [
contractData,
hasClaimConditions, hasClaimConditions,
isERC721Query.data, isERC721Query.data,
isERC1155Query.data, isERC1155Query.data,
isDirectListing,
isEnglishAuction,
]); ]);
return [ return [
@@ -291,10 +280,8 @@ export function useContractRouteConfig(
component: () => ( component: () => (
<ContractOverviewPage <ContractOverviewPage
contract={contract} contract={contract}
hasDirectListings={contractData.detectedDirectListings === "enabled"} hasDirectListings={isDirectListing}
hasEnglishAuctions={ hasEnglishAuctions={isEnglishAuction}
contractData.detectedEnglishAuctions === "enabled"
}
isErc1155={isERC1155Query.data || false} isErc1155={isERC1155Query.data || false}
isErc20={isERC20} isErc20={isERC20}
isErc721={isERC721Query.data || false} isErc721={isERC721Query.data || false}
@@ -402,13 +389,21 @@ export function useContractRouteConfig(
{ {
title: "Direct Listings", title: "Direct Listings",
path: "direct-listings", path: "direct-listings",
isEnabled: contractData.detectedDirectListings, isEnabled: functionSelectorQuery.isLoading
? "loading"
: isDirectListing
? "enabled"
: "disabled",
component: () => <LazyContractDirectListingsPage contract={contract} />, component: () => <LazyContractDirectListingsPage contract={contract} />,
}, },
{ {
title: "English Auctions", title: "English Auctions",
path: "english-auctions", path: "english-auctions",
isEnabled: contractData.detectedEnglishAuctions, isEnabled: functionSelectorQuery.isLoading
? "loading"
: isEnglishAuction
? "enabled"
: "disabled",
component: () => <LazyContractEnglishAuctionsPage contract={contract} />, component: () => <LazyContractEnglishAuctionsPage contract={contract} />,
}, },
{ {
@@ -1,5 +1,5 @@
import { Flex, Icon, SimpleGrid, Spinner } from "@chakra-ui/react"; import { Flex, Icon, SimpleGrid, Spinner } from "@chakra-ui/react";
import type { ExtensionDetectedState } from "components/buttons/ExtensionDetectButton"; import type { ExtensionDetectedState } from "components/buttons/ExtensionDetectedState";
import { FiExternalLink } from "react-icons/fi"; import { FiExternalLink } from "react-icons/fi";
import { VscExtensions } from "react-icons/vsc"; import { VscExtensions } from "react-icons/vsc";
import { Heading, Text, TrackedLink } from "tw-components"; import { Heading, Text, TrackedLink } from "tw-components";
@@ -9,7 +9,7 @@ import {
Textarea, Textarea,
} from "@chakra-ui/react"; } from "@chakra-ui/react";
import { zodResolver } from "@hookform/resolvers/zod"; import { zodResolver } from "@hookform/resolvers/zod";
import type { ExtensionDetectedState } from "components/buttons/ExtensionDetectButton"; import type { ExtensionDetectedState } from "components/buttons/ExtensionDetectedState";
import { TransactionButton } from "components/buttons/TransactionButton"; import { TransactionButton } from "components/buttons/TransactionButton";
import { FileInput } from "components/shared/FileInput"; import { FileInput } from "components/shared/FileInput";
import { CommonContractSchema } from "constants/schemas"; import { CommonContractSchema } from "constants/schemas";
@@ -1,7 +1,7 @@
import { AdminOnly } from "@3rdweb-sdk/react/components/roles/admin-only"; import { AdminOnly } from "@3rdweb-sdk/react/components/roles/admin-only";
import { Flex, FormControl } from "@chakra-ui/react"; import { Flex, FormControl } from "@chakra-ui/react";
import { zodResolver } from "@hookform/resolvers/zod"; import { zodResolver } from "@hookform/resolvers/zod";
import type { ExtensionDetectedState } from "components/buttons/ExtensionDetectButton"; import type { ExtensionDetectedState } from "components/buttons/ExtensionDetectedState";
import { TransactionButton } from "components/buttons/TransactionButton"; import { TransactionButton } from "components/buttons/TransactionButton";
import { BasisPointsInput } from "components/inputs/BasisPointsInput"; import { BasisPointsInput } from "components/inputs/BasisPointsInput";
import { AddressOrEnsSchema, BasisPointsSchema } from "constants/schemas"; import { AddressOrEnsSchema, BasisPointsSchema } from "constants/schemas";
@@ -1,7 +1,7 @@
import { AdminOnly } from "@3rdweb-sdk/react/components/roles/admin-only"; import { AdminOnly } from "@3rdweb-sdk/react/components/roles/admin-only";
import { Flex, FormControl } from "@chakra-ui/react"; import { Flex, FormControl } from "@chakra-ui/react";
import { zodResolver } from "@hookform/resolvers/zod"; import { zodResolver } from "@hookform/resolvers/zod";
import type { ExtensionDetectedState } from "components/buttons/ExtensionDetectButton"; import type { ExtensionDetectedState } from "components/buttons/ExtensionDetectedState";
import { TransactionButton } from "components/buttons/TransactionButton"; import { TransactionButton } from "components/buttons/TransactionButton";
import { AddressOrEnsSchema } from "constants/schemas"; import { AddressOrEnsSchema } from "constants/schemas";
import { SolidityInput } from "contract-ui/components/solidity-inputs"; import { SolidityInput } from "contract-ui/components/solidity-inputs";
@@ -1,7 +1,7 @@
import { AdminOnly } from "@3rdweb-sdk/react/components/roles/admin-only"; import { AdminOnly } from "@3rdweb-sdk/react/components/roles/admin-only";
import { Flex, FormControl } from "@chakra-ui/react"; import { Flex, FormControl } from "@chakra-ui/react";
import { zodResolver } from "@hookform/resolvers/zod"; import { zodResolver } from "@hookform/resolvers/zod";
import type { ExtensionDetectedState } from "components/buttons/ExtensionDetectButton"; import type { ExtensionDetectedState } from "components/buttons/ExtensionDetectedState";
import { TransactionButton } from "components/buttons/TransactionButton"; import { TransactionButton } from "components/buttons/TransactionButton";
import { BasisPointsInput } from "components/inputs/BasisPointsInput"; import { BasisPointsInput } from "components/inputs/BasisPointsInput";
import { AddressOrEnsSchema, BasisPointsSchema } from "constants/schemas"; import { AddressOrEnsSchema, BasisPointsSchema } from "constants/schemas";
@@ -1,4 +1,4 @@
import type { ExtensionDetectedState } from "components/buttons/ExtensionDetectButton"; import type { ExtensionDetectedState } from "components/buttons/ExtensionDetectedState";
import type { ComponentType } from "react"; import type { ComponentType } from "react";
// biome-ignore lint/suspicious/noExplicitAny: FIXME // biome-ignore lint/suspicious/noExplicitAny: FIXME
@@ -1,5 +1,5 @@
import { Box, Flex, Image, Skeleton, useDisclosure } from "@chakra-ui/react"; import { Box, Flex, Image, Skeleton, useDisclosure } from "@chakra-ui/react";
import type { ExtensionDetectedState } from "components/buttons/ExtensionDetectButton"; import type { ExtensionDetectedState } from "components/buttons/ExtensionDetectedState";
import type { EnhancedRoute } from "contract-ui/types/types"; import type { EnhancedRoute } from "contract-ui/types/types";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { useMemo } from "react"; import { useMemo } from "react";
@@ -9,6 +9,7 @@ export { totalListings } from "../../extensions/marketplace/__generated__/IDirec
export { export {
getListing, getListing,
type GetListingParams, type GetListingParams,
isGetListingSupported,
} from "../../extensions/marketplace/direct-listings/read/getListing.js"; } from "../../extensions/marketplace/direct-listings/read/getListing.js";
export { export {
getAllListings, getAllListings,
@@ -31,10 +32,13 @@ export {
type CurrencyPriceForListingParams, type CurrencyPriceForListingParams,
} from "../../extensions/marketplace/direct-listings/read/currencyPriceForListing.js"; } from "../../extensions/marketplace/direct-listings/read/currencyPriceForListing.js";
export { isCancelListingSupported } from "../../extensions/marketplace/__generated__/IDirectListings/write/cancelListing.js";
// WRITE // WRITE
export { export {
createListing, createListing,
type CreateListingParams, type CreateListingParams,
isCreateListingSupported,
} from "../../extensions/marketplace/direct-listings/write/createListing.js"; } from "../../extensions/marketplace/direct-listings/write/createListing.js";
export { export {
updateListing, updateListing,
@@ -47,6 +51,7 @@ export {
export { export {
buyFromListing, buyFromListing,
type BuyFromListingParams, type BuyFromListingParams,
isBuyFromListingSupported,
} from "../../extensions/marketplace/direct-listings/write/buyFromListing.js"; } from "../../extensions/marketplace/direct-listings/write/buyFromListing.js";
export { export {
approveBuyerForListing, approveBuyerForListing,
@@ -94,6 +99,7 @@ export { totalAuctions } from "../../extensions/marketplace/__generated__/IEngli
export { export {
getAuction, getAuction,
type GetAuctionParams, type GetAuctionParams,
isGetAuctionSupported,
} from "../../extensions/marketplace/english-auctions/read/getAuction.js"; } from "../../extensions/marketplace/english-auctions/read/getAuction.js";
export { export {
getAllAuctions, getAllAuctions,
@@ -106,6 +112,7 @@ export {
export { export {
getWinningBid, getWinningBid,
type GetWinningBidParams, type GetWinningBidParams,
isGetWinningBidSupported,
} from "../../extensions/marketplace/english-auctions/read/getWinningBid.js"; } from "../../extensions/marketplace/english-auctions/read/getWinningBid.js";
export { export {
isNewWinningBid, isNewWinningBid,
@@ -116,14 +123,17 @@ export {
export { export {
createAuction, createAuction,
type CreateAuctionParams, type CreateAuctionParams,
isCreateAuctionSupported,
} from "../../extensions/marketplace/english-auctions/write/createAuction.js"; } from "../../extensions/marketplace/english-auctions/write/createAuction.js";
export { export {
bidInAuction, bidInAuction,
type BidInAuctionParams, type BidInAuctionParams,
isBidInAuctionSupported,
} from "../../extensions/marketplace/english-auctions/write/bidInAuction.js"; } from "../../extensions/marketplace/english-auctions/write/bidInAuction.js";
export { export {
cancelAuction, cancelAuction,
type CancelAuctionParams, type CancelAuctionParams,
isCancelAuctionSupported,
} from "../../extensions/marketplace/__generated__/IEnglishAuctions/write/cancelAuction.js"; } from "../../extensions/marketplace/__generated__/IEnglishAuctions/write/cancelAuction.js";
export { export {
buyoutAuction, buyoutAuction,
@@ -1,18 +1,14 @@
import { eth_getBlockByNumber } from "../../../../rpc/actions/eth_getBlockByNumber.js"; import { eth_getBlockByNumber } from "../../../../rpc/actions/eth_getBlockByNumber.js";
import { getRpcClient } from "../../../../rpc/rpc.js"; import { getRpcClient } from "../../../../rpc/rpc.js";
import type { BaseTransactionOptions } from "../../../../transaction/types.js"; import type { BaseTransactionOptions } from "../../../../transaction/types.js";
import * as GetListing from "../../__generated__/IDirectListings/read/getListing.js";
import {
type GetListingParams as GetListingParamsGenerated,
getListing as getListingGenerated,
} from "../../__generated__/IDirectListings/read/getListing.js";
import type { DirectListing } from "../types.js"; import type { DirectListing } from "../types.js";
import { mapDirectListing } from "../utils.js"; import { mapDirectListing } from "../utils.js";
/** /**
* @extension MARKETPLACE * @extension MARKETPLACE
*/ */
export type GetListingParams = GetListingParamsGenerated; export type GetListingParams = GetListing.GetListingParams;
/** /**
* Retrieves a direct listing based on the provided options. * Retrieves a direct listing based on the provided options.
@@ -32,7 +28,7 @@ export async function getListing(
): Promise<DirectListing> { ): Promise<DirectListing> {
const rpcClient = getRpcClient(options.contract); const rpcClient = getRpcClient(options.contract);
const [rawListing, latestBlock] = await Promise.all([ const [rawListing, latestBlock] = await Promise.all([
getListingGenerated(options), GetListing.getListing(options),
eth_getBlockByNumber(rpcClient, { eth_getBlockByNumber(rpcClient, {
blockTag: "latest", blockTag: "latest",
}), }),
@@ -44,3 +40,19 @@ export async function getListing(
rawListing, rawListing,
}); });
} }
/**
* Checks if the `isGetListingSupported` method is supported by the given contract.
* @param availableSelectors An array of 4byte function selectors of the contract. You can get this in various ways, such as using "whatsabi" or if you have the ABI of the contract available you can use it to generate the selectors.
* @returns A boolean indicating if the `isGetListingSupported` method is supported.
* @extension MARKETPLACE
* @example
* ```ts
* import { isGetListingSupported } from "thirdweb/extensions/marketplace";
*
* const supported = isGetListingSupported(["0x..."]);
* ```
*/
export function isGetListingSupported(availableSelectors: string[]) {
return GetListing.isGetListingSupported(availableSelectors);
}
@@ -1,8 +1,8 @@
import type { Address } from "abitype"; import type { Address } from "abitype";
import { isNativeTokenAddress } from "../../../../constants/addresses.js"; import { isNativeTokenAddress } from "../../../../constants/addresses.js";
import type { BaseTransactionOptions } from "../../../../transaction/types.js"; import type { BaseTransactionOptions } from "../../../../transaction/types.js";
import { buyFromListing as generatedBuyFromListing } from "../../__generated__/IDirectListings/write/buyFromListing.js"; import * as BuyFromListing from "../../__generated__/IDirectListings/write/buyFromListing.js";
import { getListing } from "../read/getListing.js"; import * as GetListing from "../read/getListing.js";
import { isListingValid } from "../utils.js"; import { isListingValid } from "../utils.js";
/** /**
@@ -38,10 +38,10 @@ export type BuyFromListingParams = {
export function buyFromListing( export function buyFromListing(
options: BaseTransactionOptions<BuyFromListingParams>, options: BaseTransactionOptions<BuyFromListingParams>,
) { ) {
return generatedBuyFromListing({ return BuyFromListing.buyFromListing({
contract: options.contract, contract: options.contract,
asyncParams: async () => { asyncParams: async () => {
const listing = await getListing({ const listing = await GetListing.getListing({
contract: options.contract, contract: options.contract,
listingId: options.listingId, listingId: options.listingId,
}); });
@@ -71,3 +71,22 @@ export function buyFromListing(
}, },
}); });
} }
/**
* Checks if the `buyFromListing` method is supported by the given contract.
* @param availableSelectors An array of 4byte function selectors of the contract. You can get this in various ways, such as using "whatsabi" or if you have the ABI of the contract available you can use it to generate the selectors.
* @returns A boolean indicating if the `buyFromListing` method is supported.
* @extension MARKETPLACE
* @example
* ```ts
* import { isBuyFromListingSupported } from "thirdweb/extensions/marketplace";
*
* const supported = isBuyFromListingSupported(["0x..."]);
* ```
*/
export function isBuyFromListingSupported(availableSelectors: string[]) {
return (
BuyFromListing.isBuyFromListingSupported(availableSelectors) &&
GetListing.isGetListingSupported(availableSelectors)
);
}
@@ -10,7 +10,7 @@ import type { BaseTransactionOptions } from "../../../../transaction/types.js";
import { toUnits } from "../../../../utils/units.js"; import { toUnits } from "../../../../utils/units.js";
import { isERC721 } from "../../../erc721/read/isERC721.js"; import { isERC721 } from "../../../erc721/read/isERC721.js";
import { isERC1155 } from "../../../erc1155/read/isERC1155.js"; import { isERC1155 } from "../../../erc1155/read/isERC1155.js";
import { createListing as generatedCreateListing } from "../../__generated__/IDirectListings/write/createListing.js"; import * as CreateListing from "../../__generated__/IDirectListings/write/createListing.js";
/** /**
* @extension MARKETPLACE * @extension MARKETPLACE
@@ -88,7 +88,7 @@ export type CreateListingParams = {
export function createListing( export function createListing(
options: BaseTransactionOptions<CreateListingParams>, options: BaseTransactionOptions<CreateListingParams>,
) { ) {
return generatedCreateListing({ return CreateListing.createListing({
contract: options.contract, contract: options.contract,
asyncParams: async () => { asyncParams: async () => {
const assetContract = getContract({ const assetContract = getContract({
@@ -182,3 +182,19 @@ export function createListing(
}, },
}); });
} }
/**
* Checks if the `createListing` method is supported by the given contract.
* @param availableSelectors An array of 4byte function selectors of the contract. You can get this in various ways, such as using "whatsabi" or if you have the ABI of the contract available you can use it to generate the selectors.
* @returns A boolean indicating if the `createListing` method is supported.
* @extension MARKETPLACE
* @example
* ```ts
* import { isCreateAuctionSupported } from "thirdweb/extensions/marketplace";
*
* const supported = isCreateAuctionSupported(["0x..."]);
* ```
*/
export function isCreateListingSupported(availableSelectors: string[]) {
return CreateListing.isCreateListingSupported(availableSelectors);
}
@@ -1,18 +1,14 @@
import { eth_getBlockByNumber } from "../../../../rpc/actions/eth_getBlockByNumber.js"; import { eth_getBlockByNumber } from "../../../../rpc/actions/eth_getBlockByNumber.js";
import { getRpcClient } from "../../../../rpc/rpc.js"; import { getRpcClient } from "../../../../rpc/rpc.js";
import type { BaseTransactionOptions } from "../../../../transaction/types.js"; import type { BaseTransactionOptions } from "../../../../transaction/types.js";
import * as GetAuction from "../../__generated__/IEnglishAuctions/read/getAuction.js";
import {
type GetAuctionParams as GetAuctionParamsGenerated,
getAuction as getAuctionGenerated,
} from "../../__generated__/IEnglishAuctions/read/getAuction.js";
import type { EnglishAuction } from "../types.js"; import type { EnglishAuction } from "../types.js";
import { mapEnglishAuction } from "../utils.js"; import { mapEnglishAuction } from "../utils.js";
/** /**
* @extension MARKETPLACE * @extension MARKETPLACE
*/ */
export type GetAuctionParams = GetAuctionParamsGenerated; export type GetAuctionParams = GetAuction.GetAuctionParams;
/** /**
* Retrieves an auction listing based on the provided options. * Retrieves an auction listing based on the provided options.
@@ -32,7 +28,7 @@ export async function getAuction(
): Promise<EnglishAuction> { ): Promise<EnglishAuction> {
const rpcClient = getRpcClient(options.contract); const rpcClient = getRpcClient(options.contract);
const [rawAuction, latestBlock] = await Promise.all([ const [rawAuction, latestBlock] = await Promise.all([
getAuctionGenerated(options), GetAuction.getAuction(options),
eth_getBlockByNumber(rpcClient, { eth_getBlockByNumber(rpcClient, {
blockTag: "latest", blockTag: "latest",
}), }),
@@ -44,3 +40,19 @@ export async function getAuction(
rawAuction, rawAuction,
}); });
} }
/**
* Checks if the `getAuction` method is supported by the given contract.
* @param availableSelectors An array of 4byte function selectors of the contract. You can get this in various ways, such as using "whatsabi" or if you have the ABI of the contract available you can use it to generate the selectors.
* @returns A boolean indicating if the `getAuction` method is supported.
* @extension MARKETPLACE
* @example
* ```ts
* import { isGetAuctionSupported } from "thirdweb/extensions/marketplace";
*
* const supported = isGetAuctionSupported(["0x..."]);
* ```
*/
export function isGetAuctionSupported(availableSelectors: string[]) {
return GetAuction.isGetAuctionSupported(availableSelectors);
}
@@ -1,15 +1,12 @@
import { ADDRESS_ZERO } from "../../../../constants/addresses.js"; import { ZERO_ADDRESS } from "../../../../constants/addresses.js";
import type { BaseTransactionOptions } from "../../../../transaction/types.js"; import type { BaseTransactionOptions } from "../../../../transaction/types.js";
import { resolveCurrencyValue } from "../../../../utils/extensions/resolve-currency-value.js"; import { resolveCurrencyValue } from "../../../../utils/extensions/resolve-currency-value.js";
import { import * as GetWinningBid from "../../__generated__/IEnglishAuctions/read/getWinningBid.js";
type GetWinningBidParams as GeneratedWinningBidParams,
getWinningBid as getWinningBidGenerated,
} from "../../__generated__/IEnglishAuctions/read/getWinningBid.js";
/** /**
* @extension MARKETPLACE * @extension MARKETPLACE
*/ */
export type GetWinningBidParams = GeneratedWinningBidParams; export type GetWinningBidParams = GetWinningBid.GetWinningBidParams;
/** /**
* Retrieves the winning bid information for a given auction. * Retrieves the winning bid information for a given auction.
@@ -31,9 +28,9 @@ export async function getWinningBid(
options: BaseTransactionOptions<GetWinningBidParams>, options: BaseTransactionOptions<GetWinningBidParams>,
) { ) {
const [bidderAddress, currencyAddress, bidAmountWei] = const [bidderAddress, currencyAddress, bidAmountWei] =
await getWinningBidGenerated(options); await GetWinningBid.getWinningBid(options);
if (bidderAddress === ADDRESS_ZERO) { if (bidderAddress === ZERO_ADDRESS) {
return undefined; return undefined;
} }
@@ -49,3 +46,19 @@ export async function getWinningBid(
}), }),
}; };
} }
/**
* Checks if the `getWinningBid` method is supported by the given contract.
* @param availableSelectors An array of 4byte function selectors of the contract. You can get this in various ways, such as using "whatsabi" or if you have the ABI of the contract available you can use it to generate the selectors.
* @returns A boolean indicating if the `getWinningBid` method is supported.
* @extension MARKETPLACE
* @example
* ```ts
* import { isGetWinningBidSupported } from "thirdweb/extensions/marketplace";
*
* const supported = isGetWinningBidSupported(["0x..."]);
* ```
*/
export function isGetWinningBidSupported(availableSelectors: string[]) {
return GetWinningBid.isGetWinningBidSupported(availableSelectors);
}
@@ -1,9 +1,9 @@
import { isNativeTokenAddress } from "../../../../constants/addresses.js"; import { isNativeTokenAddress } from "../../../../constants/addresses.js";
import type { BaseTransactionOptions } from "../../../../transaction/types.js"; import type { BaseTransactionOptions } from "../../../../transaction/types.js";
import { isNewWinningBid } from "../../__generated__/IEnglishAuctions/read/isNewWinningBid.js"; import * as IsNewWinningBid from "../../__generated__/IEnglishAuctions/read/isNewWinningBid.js";
import { bidInAuction as generatedBidInAuction } from "../../__generated__/IEnglishAuctions/write/bidInAuction.js"; import * as BidInAuction from "../../__generated__/IEnglishAuctions/write/bidInAuction.js";
import { getAuction } from "../read/getAuction.js"; import * as GetAuction from "../read/getAuction.js";
import { getWinningBid } from "../read/getWinningBid.js"; import * as GetWinningBid from "../read/getWinningBid.js";
/** /**
* @extension MARKETPLACE * @extension MARKETPLACE
@@ -39,10 +39,10 @@ export type BidInAuctionParams = {
export function bidInAuction( export function bidInAuction(
options: BaseTransactionOptions<BidInAuctionParams>, options: BaseTransactionOptions<BidInAuctionParams>,
) { ) {
return generatedBidInAuction({ return BidInAuction.bidInAuction({
contract: options.contract, contract: options.contract,
asyncParams: async () => { asyncParams: async () => {
const auction = await getAuction({ const auction = await GetAuction.getAuction({
contract: options.contract, contract: options.contract,
auctionId: options.auctionId, auctionId: options.auctionId,
}); });
@@ -70,13 +70,13 @@ export function bidInAuction(
if (resolvedBidAmountWei > auction.buyoutCurrencyValue.value) { if (resolvedBidAmountWei > auction.buyoutCurrencyValue.value) {
throw new Error("Bid amount is above the buyout amount"); throw new Error("Bid amount is above the buyout amount");
} }
const existingWinningBid = await getWinningBid({ const existingWinningBid = await GetWinningBid.getWinningBid({
auctionId: options.auctionId, auctionId: options.auctionId,
contract: options.contract, contract: options.contract,
}); });
if (existingWinningBid) { if (existingWinningBid) {
// check if the bid amount is sufficient to outbid the existing winning bid // check if the bid amount is sufficient to outbid the existing winning bid
const isNewWinner = await isNewWinningBid({ const isNewWinner = await IsNewWinningBid.isNewWinningBid({
contract: options.contract, contract: options.contract,
auctionId: options.auctionId, auctionId: options.auctionId,
bidAmount: resolvedBidAmountWei, bidAmount: resolvedBidAmountWei,
@@ -106,3 +106,24 @@ export function bidInAuction(
}, },
}); });
} }
/**
* Checks if the `bidInAuction` method is supported by the given contract.
* @param availableSelectors An array of 4byte function selectors of the contract. You can get this in various ways, such as using "whatsabi" or if you have the ABI of the contract available you can use it to generate the selectors.
* @returns A boolean indicating if the `bidInAuction` method is supported.
* @extension MARKETPLACE
* @example
* ```ts
* import { isBidInAuctionSupported } from "thirdweb/extensions/marketplace";
*
* const supported = isBidInAuctionSupported(["0x..."]);
* ```
*/
export function isBidInAuctionSupported(availableSelectors: string[]) {
return (
BidInAuction.isBidInAuctionSupported(availableSelectors) &&
GetWinningBid.isGetWinningBidSupported(availableSelectors) &&
GetAuction.isGetAuctionSupported(availableSelectors) &&
IsNewWinningBid.isIsNewWinningBidSupported(availableSelectors)
);
}
@@ -1,6 +1,9 @@
import type { BaseTransactionOptions } from "../../../../transaction/types.js"; import type { BaseTransactionOptions } from "../../../../transaction/types.js";
import { cancelAuction as generatedCancelAuction } from "../../__generated__/IEnglishAuctions/write/cancelAuction.js"; import * as CancelAuction from "../../__generated__/IEnglishAuctions/write/cancelAuction.js";
import { getWinningBid } from "../read/getWinningBid.js"; import {
getWinningBid,
isGetWinningBidSupported,
} from "../read/getWinningBid.js";
/** /**
* @extension MARKETPLACE * @extension MARKETPLACE
@@ -32,7 +35,7 @@ export type CancelAuctionParams = {
export function cancelAuction( export function cancelAuction(
options: BaseTransactionOptions<CancelAuctionParams>, options: BaseTransactionOptions<CancelAuctionParams>,
) { ) {
return generatedCancelAuction({ return CancelAuction.cancelAuction({
contract: options.contract, contract: options.contract,
asyncParams: async () => { asyncParams: async () => {
const winningBid = await getWinningBid({ const winningBid = await getWinningBid({
@@ -51,3 +54,22 @@ export function cancelAuction(
}, },
}); });
} }
/**
* Checks if the `cancelAuction` method is supported by the given contract.
* @param availableSelectors An array of 4byte function selectors of the contract. You can get this in various ways, such as using "whatsabi" or if you have the ABI of the contract available you can use it to generate the selectors.
* @returns A boolean indicating if the `cancelAuction` method is supported.
* @extension MARKETPLACE
* @example
* ```ts
* import { isCancelAuctionSupported } from "thirdweb/extensions/marketplace";
*
* const supported = isCancelAuctionSupported(["0x..."]);
* ```
*/
export function isCancelAuctionSupported(availableSelectors: string[]) {
return (
CancelAuction.isCancelAuctionSupported(availableSelectors) &&
isGetWinningBidSupported(availableSelectors)
);
}
@@ -10,7 +10,7 @@ import type { BaseTransactionOptions } from "../../../../transaction/types.js";
import { toUnits } from "../../../../utils/units.js"; import { toUnits } from "../../../../utils/units.js";
import { isERC721 } from "../../../erc721/read/isERC721.js"; import { isERC721 } from "../../../erc721/read/isERC721.js";
import { isERC1155 } from "../../../erc1155/read/isERC1155.js"; import { isERC1155 } from "../../../erc1155/read/isERC1155.js";
import { createAuction as generatedCreateAuction } from "../../__generated__/IEnglishAuctions/write/createAuction.js"; import * as CreateAuction from "../../__generated__/IEnglishAuctions/write/createAuction.js";
/** /**
* @extension MARKETPLACE * @extension MARKETPLACE
@@ -119,7 +119,7 @@ export type CreateAuctionParams = {
export function createAuction( export function createAuction(
options: BaseTransactionOptions<CreateAuctionParams>, options: BaseTransactionOptions<CreateAuctionParams>,
) { ) {
return generatedCreateAuction({ return CreateAuction.createAuction({
...options, ...options,
asyncParams: async () => { asyncParams: async () => {
const assetContract = getContract({ const assetContract = getContract({
@@ -245,3 +245,19 @@ export function createAuction(
}, },
}); });
} }
/**
* Checks if the `createAuction` method is supported by the given contract.
* @param availableSelectors An array of 4byte function selectors of the contract. You can get this in various ways, such as using "whatsabi" or if you have the ABI of the contract available you can use it to generate the selectors.
* @returns A boolean indicating if the `createAuction` method is supported.
* @extension MARKETPLACE
* @example
* ```ts
* import { isCreateAuctionSupported } from "thirdweb/extensions/marketplace";
*
* const supported = isCreateAuctionSupported(["0x..."]);
* ```
*/
export function isCreateAuctionSupported(availableSelectors: string[]) {
return CreateAuction.isCreateAuctionSupported(availableSelectors);
}