Compare commits

...
Author SHA1 Message Date
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
2e8d3fd6e7 Version Packages (#358)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-10-28 18:14:35 -07:00
Nacho IacovinoandGitHub cc4613b5fd [React] Add Pack and Multiwrap as NFTContract types (#356) 2022-10-29 01:28:40 +02:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
78566babaa Version Packages (#354)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-10-28 10:29:57 -07:00
Joaquim VergesandGitHub 65fc7ba6ff [SDK] Expose claimCondtions.getClaimerProofs(address) (#357) 2022-10-28 10:25:36 -07:00
Nacho IacovinoandGitHub 1c24c3c3c4 [Multi] Add useUpdateCreator hook, fix CreatorInput schema (#353) 2022-10-26 18:19:32 +00:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
408c5a81fa Version Packages (#347)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-10-26 08:38:25 -07:00
Joaquim VergesandGitHub 352291791e [SDK, React] expose marketplace.auction.executeSale (#352) 2022-10-26 00:19:01 +00:00
Jonas DanielsandGitHub aabbb149e8 [React] - fix wallet connection during hot reload (#351) 2022-10-25 22:48:39 +00:00
Jonas DanielsandGitHub d59450f814 do not release e2e tests (#350) 2022-10-25 20:29:22 +00:00
7d9a4c6abc Update name of useRoyalty, and update (#348)
Co-authored-by: Jonas Daniels <[email protected]>
2022-10-25 19:56:09 +00:00
Jonas DanielsandGitHub 99806e595d [VARIOUS] - exclude sizes of test files etc (#349) 2022-10-25 18:39:30 +00:00
Nacho IacovinoandGitHub 21c21c1adf resolveReleasesFromAddress -> resolveContractUriFromAddress (#344) 2022-10-24 23:43:43 +00:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
4b10719047 Version Packages (#345)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-10-24 16:18:44 -07:00
Joaquim VergesandGitHub 989cf7347c [React, SDK] Small fixes for useOffers and makeOffers (#346) 2022-10-24 23:09:32 +00:00
Joaquim VergesandGitHub 72227b2e16 [SDK, React] Expose new useOffers and useMakeOffer hooks (#343) 2022-10-24 15:28:34 -07:00
39 changed files with 689 additions and 94 deletions
+1 -1
View File
@@ -7,7 +7,7 @@
"access": "public",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": [],
"ignore": ["e2e-cra-5", "e2e-next-12", "e2e-vite-3"],
"___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH": {
"updateInternalDependents": "always",
"onlyUpdatePeerDependentsWhenOutOfRange": true
+2
View File
@@ -15,3 +15,5 @@ jobs:
repo-token: "${{ secrets.GITHUB_TOKEN }}"
strip-hash: "\\-(\\w{8})(?:\\.esm|\\.cjs)"
minimum-change-threshold: 100
# exclude source maps, node modules and any test related files
exclude: "{**/*.map,**/node_modules/**,**/test/**}"
+8
View File
@@ -1,5 +1,13 @@
# @thirdweb-dev/auth
## 2.0.25
## 2.0.24
## 2.0.23
## 2.0.22
## 2.0.21
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/auth",
"version": "2.0.21",
"version": "2.0.25",
"exports": {
"./next": {
"module": "./next/dist/thirdweb-dev-auth-next.esm.js",
+28
View File
@@ -1,5 +1,33 @@
# thirdweb
## 0.8.11
### Patch Changes
- Updated dependencies []:
- @thirdweb-dev/sdk@3.4.4
## 0.8.10
### Patch Changes
- Updated dependencies [[`1c24c3c`](https://github.com/thirdweb-dev/js/commit/1c24c3c3c48476a824f817e09e7bf0fbe67c1db5), [`65fc7ba`](https://github.com/thirdweb-dev/js/commit/65fc7ba6fff093a971b53cb0979c39768e090ba1)]:
- @thirdweb-dev/sdk@3.4.3
## 0.8.9
### Patch Changes
- Updated dependencies [[`21c21c1`](https://github.com/thirdweb-dev/js/commit/21c21c1adfd09b60ad563bfd4c308597140de33c), [`3522917`](https://github.com/thirdweb-dev/js/commit/352291791ee900e1500f84f095290497934d2f60)]:
- @thirdweb-dev/sdk@3.4.2
## 0.8.8
### Patch Changes
- Updated dependencies [[`72227b2`](https://github.com/thirdweb-dev/js/commit/72227b2e166a3a68bbb41cf2b389322f5b7547a2)]:
- @thirdweb-dev/sdk@3.4.1
## 0.8.7
### Patch Changes
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "thirdweb",
"main": "dist/cli/index.js",
"version": "0.8.7",
"version": "0.8.11",
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/cli",
"author": "thirdweb eng <[email protected]>",
"license": "Apache-2.0",
+29
View File
@@ -1,5 +1,34 @@
# @thirdweb-dev/react
## 3.4.4
### Patch Changes
- [#356](https://github.com/thirdweb-dev/js/pull/356) [`cc4613b`](https://github.com/thirdweb-dev/js/commit/cc4613b5fd69840f4f9cfd0ac1c4e6743e62fe52) Thanks [@nachoiacovino](https://github.com/nachoiacovino)! - Add Pack and Multiwrap as NFTContract types
## 3.4.3
### Patch Changes
- [#353](https://github.com/thirdweb-dev/js/pull/353) [`1c24c3c`](https://github.com/thirdweb-dev/js/commit/1c24c3c3c48476a824f817e09e7bf0fbe67c1db5) Thanks [@nachoiacovino](https://github.com/nachoiacovino)! - Add useUpdateCreators hook, fix CreatorInput schema
## 3.4.2
### Patch Changes
- [#348](https://github.com/thirdweb-dev/js/pull/348) [`7d9a4c6`](https://github.com/thirdweb-dev/js/commit/7d9a4c6abcad1b4f43e431ce7b0b38db9016ea9a) Thanks [@nachoiacovino](https://github.com/nachoiacovino)! - [SOL] - add `useUpdateRoyaltySettings()` hook
[SOL] - change `useRoyalty()` hook -> `useRoyaltySettings()` for consistency
- [#352](https://github.com/thirdweb-dev/js/pull/352) [`3522917`](https://github.com/thirdweb-dev/js/commit/352291791ee900e1500f84f095290497934d2f60) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - expose useExecuteAuctionSale and useAcceptDirectListingOffer
- [#351](https://github.com/thirdweb-dev/js/pull/351) [`aabbb14`](https://github.com/thirdweb-dev/js/commit/aabbb149e81d6824015a4797b2b6c929ca359545) Thanks [@jnsdls](https://github.com/jnsdls)! - [EVM] - fix wallet connection during dev (hot reload)
## 3.4.1
### Patch Changes
- [#343](https://github.com/thirdweb-dev/js/pull/343) [`72227b2`](https://github.com/thirdweb-dev/js/commit/72227b2e166a3a68bbb41cf2b389322f5b7547a2) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Expose new useOffers and useMakeOffer hooks
## 3.4.0
### Minor Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/react",
"version": "3.4.0",
"version": "3.4.4",
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/react",
"author": "thirdweb eng <[email protected]>",
"license": "Apache-2.0",
@@ -33,7 +33,17 @@ export const ThirdwebConnectedWalletProvider: React.FC<
const { rpcUrlMap } = useThirdwebConfigContext();
const [contextValue, setContextValue] =
useState<ThirdwebConnectedWalletContext>(INITIAL_CONTEXT_VALUE);
useState<ThirdwebConnectedWalletContext>({
...INITIAL_CONTEXT_VALUE,
signer: signer ? signer : undefined,
});
useEffect(() => {
setContextValue((val) => ({
...val,
signer: signer ? signer : undefined,
}));
}, [signer]);
useEffect(() => {
let s = signer;
@@ -3,13 +3,20 @@ import {
requiredParamInvariant,
} from "../../../core/query-utils/required-param";
import { useSDKChainId } from "../../providers/base";
import { BuyNowParams, MakeBidParams } from "../../types";
import {
AcceptDirectOffer,
BuyNowParams,
ExecuteAuctionSale,
MakeBidParams,
MakeOfferParams,
} from "../../types";
import {
cacheKeys,
invalidateContractAndBalances,
} from "../../utils/cache-keys";
import { useQueryWithNetwork } from "../query-utils/useQueryWithNetwork";
import { useAddress } from "../wallet";
import { useContractEvents } from "./contracts";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import type {
AuctionListing,
@@ -514,6 +521,203 @@ export function useMakeBid(contract: RequiredParam<Marketplace>) {
);
}
/**
* Use this to make an offer on direct or auction listing from your marketplace contract.
*
* @example
* ```jsx
* const Component = () => {
* const {
* mutate: makeOffer,
* isLoading,
* error,
* } = useMakeOffer(">>YourMarketplaceContractInstance<<");
*
* if (error) {
* console.error("failed to make a bid", error);
* }
*
* return (
* <button
* disabled={isLoading}
* onClick={() => makeOffer({ listingId: 1, pricePerToken: 0.5, quantity: 1 })}
* >
* Bid!
* </button>
* );
* };
* ```
*
* @param contract - an instance of a Marketplace contract
* @returns a mutation object that can be used to make a bid on an auction listing
* @beta
*/
export function useMakeOffer(contract: RequiredParam<Marketplace>) {
const activeChainId = useSDKChainId();
const contractAddress = contract?.getAddress();
const queryClient = useQueryClient();
const walletAddress = useAddress();
return useMutation(
async (data: MakeOfferParams) => {
invariant(walletAddress, "no wallet connected, cannot make bid");
requiredParamInvariant(contract, "No Contract instance provided");
return await contract.makeOffer(
data.listingId,
data.pricePerToken,
data.quantity,
);
},
{
onSettled: () =>
invalidateContractAndBalances(
queryClient,
contractAddress,
activeChainId,
),
},
);
}
/**
* Accept an offer on a direct listing from an offeror, will accept the latest offer by the given offeror.
*
* @example
* ```jsx
* const Component = () => {
* const {
* mutate: acceptOffer,
* isLoading,
* error,
* } = useAcceptDirectListingOffer(">>YourMarketplaceContractInstance<<");
*
* if (error) {
* console.error("failed to accept offer", error);
* }
*
* return (
* <button
* disabled={isLoading}
* onClick={() => acceptOffer({ listingId: 1, addressOfOfferor: "0x..." })}
* >
* Accept offer
* </button>
* );
* };
* ```
*
* @param contract - an instance of a Marketplace contract
* @returns a mutation object that can be used to accept an offer on a direct listing
* @beta
*/
export function useAcceptDirectListingOffer(
contract: RequiredParam<Marketplace>,
) {
const activeChainId = useSDKChainId();
const contractAddress = contract?.getAddress();
const queryClient = useQueryClient();
const walletAddress = useAddress();
return useMutation(
async (data: AcceptDirectOffer) => {
invariant(walletAddress, "no wallet connected, cannot make bid");
requiredParamInvariant(contract?.direct, "No Direct instance provided");
return await contract.direct.acceptOffer(
data.listingId,
data.addressOfOfferor,
);
},
{
onSettled: () =>
invalidateContractAndBalances(
queryClient,
contractAddress,
activeChainId,
),
},
);
}
/**
* Execute an auction sale. Can only be executed once the auction has ended and the auction has a winning bid.
*
* @example
* ```jsx
* const Component = () => {
* const {
* mutate: executeAuctionSale,
* isLoading,
* error,
* } = useExecuteAuctionSale(">>YourMarketplaceContractInstance<<");
*
* if (error) {
* console.error("failed to execute sale", error);
* }
*
* return (
* <button
* disabled={isLoading}
* onClick={() => executeAuctionSale({ listingId: 1 })}
* >
* Execute sale
* </button>
* );
* };
* ```
*
* @param contract - an instance of a Marketplace contract
* @returns a mutation object that can be used to accept an offer on a direct listing
* @beta
*/
export function useExecuteAuctionSale(contract: RequiredParam<Marketplace>) {
const activeChainId = useSDKChainId();
const contractAddress = contract?.getAddress();
const queryClient = useQueryClient();
const walletAddress = useAddress();
return useMutation(
async (data: ExecuteAuctionSale) => {
invariant(walletAddress, "no wallet connected, cannot make bid");
requiredParamInvariant(
contract?.auction,
"No Auction marketplace instance provided",
);
return await contract.auction.executeSale(data.listingId);
},
{
onSettled: () =>
invalidateContractAndBalances(
queryClient,
contractAddress,
activeChainId,
),
},
);
}
/**
* Get all the offers for a listing
*
* @remarks Fetch all the offers for a specified direct or auction listing.
* @example
* ```javascript
* const { data: offers, isLoading, error } = useOffers(<YourMarketplaceContractInstance>, <listingId>);
* ```
*
* @param contract - an instance of a Marketplace contract
* @param listingId - the id of the listing to fetch offers for
* @beta
*/
export function useOffers(
contract: RequiredParam<Marketplace>,
listingId: RequiredParam<BigNumberish>,
) {
const result = useContractEvents(contract, "NewOffer");
return {
...result,
data: result.data
?.filter((ev) => ev.data.listingId.eq(listingId))
?.map((ev) => ev.data),
};
}
/**
* Use this to buy out an auction listing from your marketplace contract.
*
+21 -6
View File
@@ -21,7 +21,7 @@ import {
} from "@thirdweb-dev/sdk";
import { ThirdwebStorage } from "@thirdweb-dev/storage";
import { Signer } from "ethers";
import { createContext, useContext, useEffect, useMemo } from "react";
import { createContext, useContext, useEffect, useMemo, useState } from "react";
import invariant from "tiny-invariant";
interface TWSDKContext {
@@ -60,21 +60,36 @@ export const WrappedThirdwebSDKProvider: ComponentWithChildren<
}) => {
const { signer } = useThirdwebConnectedWalletContext();
const sdk = useMemo(() => {
const [sdk, setSDK] = useState<ThirdwebSDK>();
useEffect(() => {
if (!desiredChainId || typeof window === "undefined") {
return undefined;
}
const _sdk = new ThirdwebSDK(provider, sdkOptions, storageInterface);
// if we already have a signer from the wallet context, use it immediately
if (signer) {
_sdk.updateSignerOrProvider(signer);
}
(_sdk as any)._constructedAt = Date.now();
(_sdk as any)._chainId = desiredChainId;
return _sdk;
setSDK(_sdk);
// explicitly *not* passing the signer, if we have it we use it if we don't we don't
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [provider, sdkOptions, storageInterface, desiredChainId]);
useEffect(() => {
if (signer && sdk && (sdk as any)._chainId === desiredChainId) {
sdk.updateSignerOrProvider(signer);
if (sdk && (sdk as any)._chainId === desiredChainId) {
if (signer) {
sdk.updateSignerOrProvider(signer);
} else {
sdk.updateSignerOrProvider(provider);
}
}
}, [signer, sdk, desiredChainId]);
}, [signer, sdk, desiredChainId, provider]);
const ctxValue = useMemo(
() => ({
+16
View File
@@ -14,6 +14,8 @@ import type {
ClaimOptions,
NFTMetadataOrUri,
Token,
Multiwrap,
Pack,
} from "@thirdweb-dev/sdk";
import type { Edition } from "@thirdweb-dev/sdk/dist/declarations/src/evm/contracts/prebuilt-implementations/edition";
import type { EditionDrop } from "@thirdweb-dev/sdk/dist/declarations/src/evm/contracts/prebuilt-implementations/edition-drop";
@@ -68,6 +70,8 @@ export type TokenBurnParams = {
export type NFTContract =
| NFTCollection
| Edition
| Pack
| Multiwrap
| Exclude<DropContract, "TokenDrop">;
/**
@@ -212,6 +216,18 @@ export type ClaimNFTReturnType =
// MARKETPLACE //
export type MakeBidParams = { listingId: BigNumberish; bid: Price };
export type MakeOfferParams = {
listingId: BigNumberish;
pricePerToken: Price;
quantity?: Amount;
};
export type AcceptDirectOffer = {
listingId: BigNumberish;
addressOfOfferor: string;
};
export type ExecuteAuctionSale = {
listingId: BigNumberish;
};
export type BuyNowParams<TListingType = ListingType> =
TListingType extends ListingType.Direct
@@ -30,7 +30,7 @@ export function nftRoyaltyQuery(
*
* export default function Component() {
* const { program } = useProgram("{{program_address}}");
* const { data: royalty, isLoading } = useRoyalty(program);
* const { data: royalty, isLoading } = useRoyaltySettings(program);
*
* return (
* <p>{royalty}</p>
@@ -40,6 +40,6 @@ export function nftRoyaltyQuery(
*
* @public
*/
export function useRoyalty(program: RequiredParam<NFTCollection | NFTDrop>) {
export function useRoyaltySettings(program: RequiredParam<NFTCollection | NFTDrop>) {
return useQuery(nftRoyaltyQuery(program));
}
@@ -0,0 +1,47 @@
import { createSOLProgramQueryKey } from "../../../core/query-utils/query-key";
import {
requiredParamInvariant,
RequiredParam,
} from "../../../core/query-utils/required-param";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import type { CreatorInput, NFTCollection, NFTDrop } from "@thirdweb-dev/sdk/solana";
/**
* Update the creators for an NFT program
* @param program - The NFT program instance to update the creators for
*
* @example
* ```jsx
* import { useProgram, useUpdateCreators } from "@thirdweb-dev/react/solana";
*
* export default function Component() {
* const { program } = useProgram("{{program_address}}");
* const { mutateAsync: updateCreators, isLoading, error } = useUpdateCreators(program);
*
* return (
* <button
* onClick={() => updateCreators([{ address: "0x...", share: 10 }])}
* >
* Update Creators
* </button>
* )
* }
* ```
*
* @public
*/
export function useUpdateCreators(
program: RequiredParam<NFTCollection | NFTDrop>,
) {
const queryClient = useQueryClient();
return useMutation(
async (creators: CreatorInput[]) => {
requiredParamInvariant(program, "program is required");
return await program.updateCreators(creators);
},
{
onSettled: () =>
queryClient.invalidateQueries(createSOLProgramQueryKey(program)),
},
);
}
@@ -0,0 +1,47 @@
import { createSOLProgramQueryKey } from "../../../core/query-utils/query-key";
import {
requiredParamInvariant,
RequiredParam,
} from "../../../core/query-utils/required-param";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import type { NFTCollection, NFTDrop } from "@thirdweb-dev/sdk/solana";
/**
* Update the royalty for an NFT program
* @param program - The NFT program instance to update the royalty for
*
* @example
* ```jsx
* import { useProgram, useUpdateRoyaltySettings } from "@thirdweb-dev/react/solana";
*
* export default function Component() {
* const { program } = useProgram("{{program_address}}");
* const { mutateAsync: updateRoyalties, isLoading, error } = useUpdateRoyaltySettings(program);
*
* return (
* <button
* onClick={() => updateRoyalties(300)}
* >
* Update Royalties
* </button>
* )
* }
* ```
*
* @public
*/
export function useUpdateRoyaltySettings(
program: RequiredParam<NFTCollection | NFTDrop>,
) {
const queryClient = useQueryClient();
return useMutation(
async (sellerFeeBasisPoints: number) => {
requiredParamInvariant(program, "program is required");
return await program.updateRoyalty(sellerFeeBasisPoints);
},
{
onSettled: () =>
queryClient.invalidateQueries(createSOLProgramQueryKey(program)),
},
);
}
+4
View File
@@ -14,6 +14,10 @@ export * from "./hooks/program/useProgramAccountType";
export * from "./hooks/nft/useNFTs";
export * from "./hooks/nft/useTransferNFT";
export * from "./hooks/nft/useBurnNFT";
export * from "./hooks/nft/useRoyaltySettings";
export * from "./hooks/nft/useUpdateRoyaltySettings";
export * from "./hooks/nft/useCreators";
export * from "./hooks/nft/useUpdateCreators";
// NFT Collection
export * from "./hooks/nft/collection/useMintNFT";
+24
View File
@@ -1,5 +1,29 @@
# @thirdweb-dev/sdk
## 3.4.4
## 3.4.3
### Patch Changes
- [#353](https://github.com/thirdweb-dev/js/pull/353) [`1c24c3c`](https://github.com/thirdweb-dev/js/commit/1c24c3c3c48476a824f817e09e7bf0fbe67c1db5) Thanks [@nachoiacovino](https://github.com/nachoiacovino)! - Add useUpdateCreators hook, fix CreatorInput schema
- [#357](https://github.com/thirdweb-dev/js/pull/357) [`65fc7ba`](https://github.com/thirdweb-dev/js/commit/65fc7ba6fff093a971b53cb0979c39768e090ba1) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Expose claimConditions.getClaimerProofs(address) to get allowlist information for a given address
## 3.4.2
### Patch Changes
- [#344](https://github.com/thirdweb-dev/js/pull/344) [`21c21c1`](https://github.com/thirdweb-dev/js/commit/21c21c1adfd09b60ad563bfd4c308597140de33c) Thanks [@nachoiacovino](https://github.com/nachoiacovino)! - Update internal function resolveContractUriFromAddress -> resolveContractUriFromAddress
- [#352](https://github.com/thirdweb-dev/js/pull/352) [`3522917`](https://github.com/thirdweb-dev/js/commit/352291791ee900e1500f84f095290497934d2f60) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Expose marketplace.auction.executeSale(listingId)
## 3.4.1
### Patch Changes
- [#343](https://github.com/thirdweb-dev/js/pull/343) [`72227b2`](https://github.com/thirdweb-dev/js/commit/72227b2e166a3a68bbb41cf2b389322f5b7547a2) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Expose general marketplace.makeOffer() function
## 3.4.0
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/sdk",
"version": "3.4.0",
"version": "3.4.4",
"description": "The main thirdweb SDK.",
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/sdk",
"license": "Apache-2.0",
+2 -2
View File
@@ -72,12 +72,12 @@ export const BigNumberTransformSchema = z
export const BasisPointsSchema = z
.number()
.max(MAX_BPS, "Cannot exeed 100%")
.max(MAX_BPS, "Cannot exceed 100%")
.min(0, "Cannot be below 0%");
export const PercentSchema = z
.number()
.max(100, "Cannot exeed 100%")
.max(100, "Cannot exceed 100%")
.min(0, "Cannot be below 0%");
export const HexColor = z.union([
+1 -2
View File
@@ -24,13 +24,12 @@ export const NATIVE_TOKENS: Record<
symbol: "WETH",
},
},
[ChainId.Goerli]: {
name: "Görli Ether",
symbol: "GOR",
decimals: 18,
wrapped: {
address: "0x0bb7509324ce409f7bbc4b701f932eaca9736ab7",
address: "0xb4fbf271143f4fbf7b91a5ded31805e42b2208d6",
name: "Wrapped Ether",
symbol: "WETH",
},
@@ -1,7 +1,12 @@
import { DEFAULT_QUERY_ALL_COUNT } from "../../../core/schema/QueryParams";
import { ListingNotFoundError } from "../../common";
import { isNativeToken } from "../../common/currency";
import { mapOffer } from "../../common/marketplace";
import { getRoleHash } from "../../common/role";
import {
NATIVE_TOKENS,
SUPPORTED_CHAIN_ID,
} from "../../constants";
import { ContractEncoder } from "../../core/classes/contract-encoder";
import { ContractEvents } from "../../core/classes/contract-events";
import { ContractInterceptor } from "../../core/classes/contract-interceptor";
@@ -17,6 +22,7 @@ import { NetworkOrSignerOrProvider, TransactionResult } from "../../core/types";
import { ListingType } from "../../enums";
import { MarketplaceContractSchema } from "../../schema/contracts/marketplace";
import { SDKOptions } from "../../schema/sdk-options";
import { Price } from "../../types/currency";
import { AuctionListing, DirectListing, Offer } from "../../types/marketplace";
import { MarketplaceFilter } from "../../types/marketplace/MarketPlaceFilter";
import { UnmappedOffer } from "../../types/marketplace/UnmappedOffer";
@@ -324,22 +330,22 @@ export class Marketplace implements UpdateableNetwork {
// get only the events for this listing id
const listingEvents = events.filter((e) => e.data.listingId.eq(listingId));
// derive the offers from the events
const offers = await Promise.all(
return await Promise.all(
listingEvents.map(async (e): Promise<Offer> => {
const offer = await mapOffer(
return await mapOffer(
this.contractWrapper.getProvider(),
BigNumber.from(listingId),
{
quantityWanted: e.data.quantityWanted,
pricePerToken: e.data.totalOfferAmount.div(e.data.quantityWanted),
pricePerToken: e.data.quantityWanted.gt(0)
? e.data.totalOfferAmount.div(e.data.quantityWanted)
: e.data.totalOfferAmount,
currency: e.data.currency,
offeror: e.data.offeror,
} as UnmappedOffer,
);
return offer;
}),
);
return offers;
}
/** ******************************
@@ -391,6 +397,60 @@ export class Marketplace implements UpdateableNetwork {
}
}
/**
* Make an offer for a Direct or Auction Listing
*
* @remarks Make an offer on a direct or auction listing
*
* @example
* ```javascript
* // The listing ID of the asset you want to offer on
* const listingId = 0;
* // The price you are willing to offer per token
* const pricePerToken = 0.5;
* // The quantity of tokens you want to receive for this offer
* const quantity = 1;
*
* await contract.makeOffer(
* listingId,
* pricePerToken,
* quantity,
* );
* ```
*/
public async makeOffer(
listingId: BigNumberish,
pricePerToken: Price,
quantity?: BigNumberish,
): Promise<TransactionResult> {
const listing = await this.contractWrapper.readContract.listings(listingId);
if (listing.listingId.toString() !== listingId.toString()) {
throw new ListingNotFoundError(this.getAddress(), listingId.toString());
}
const chainId = await this.contractWrapper.getChainID();
switch (listing.listingType) {
case ListingType.Direct: {
invariant(
quantity,
"quantity is required when making an offer on a direct listing",
);
return await this.direct.makeOffer(
listingId,
quantity,
isNativeToken(listing.currency)
? NATIVE_TOKENS[chainId as SUPPORTED_CHAIN_ID].wrapped.address
: listing.currency,
pricePerToken,
);
}
case ListingType.Auction: {
return await this.auction.makeBid(listingId, pricePerToken);
}
default:
throw Error(`Unknown listing type: ${listing.listingType}`);
}
}
/**
* Set the Auction bid buffer
* @remarks A percentage (e.g. 5%) in basis points (5% = 500, 100% = 10000). A new bid is considered to be a winning bid only if its bid amount is at least the bid buffer (e.g. 5%) greater than the previous winning bid. This prevents buyers from making very slightly higher bids to win the auctioned items.
@@ -195,13 +195,13 @@ export class ContractPublisher extends RPCConnectionHandler {
* @internal
* TODO clean this up (see method above, too)
*/
public async resolveReleasesFromAddress(address: string) {
public async resolveContractUriFromAddress(address: string) {
const contractUri = await resolveContractUriFromAddress(
address,
this.getProvider(),
);
invariant(contractUri, "Could not resolve contract URI from address");
return await this.resolvePublishMetadataFromCompilerMetadata(contractUri);
return contractUri;
}
/**
@@ -1,5 +1,6 @@
import { includesErrorMessage } from "../../common";
import {
fetchSnapshotEntryForAddress,
getClaimerProofs,
prepareClaim,
processClaimConditionInputs,
@@ -14,7 +15,7 @@ import {
import { isNode } from "../../common/utils";
import { NATIVE_TOKEN_ADDRESS } from "../../constants/index";
import { ClaimEligibility } from "../../enums";
import { AmountSchema } from "../../schema";
import { AmountSchema, SnapshotEntryWithProof } from "../../schema";
import {
Amount,
ClaimCondition,
@@ -339,6 +340,31 @@ export class DropClaimConditions<
return reasons;
}
/**
* Returns allow list information and merkle proofs for the given address.
* @param claimerAddress
*/
public async getClaimerProofs(
claimerAddress: string,
): Promise<SnapshotEntryWithProof | null> {
const claimCondition = await this.getActive();
const merkeRoot = claimCondition.merkleRootHash;
const merkleRootArray = ethers.utils.stripZeros(
claimCondition.merkleRootHash,
);
if (merkleRootArray.length > 0) {
const metadata = await this.metadata.get();
return await fetchSnapshotEntryForAddress(
claimerAddress,
merkeRoot.toString(),
metadata.merkle,
this.storage,
);
} else {
return null;
}
}
/** ***************************************
* WRITE FUNCTIONS
*****************************************/
@@ -1,5 +1,6 @@
import { includesErrorMessage } from "../../common";
import {
fetchSnapshotEntryForAddress,
getClaimerProofs,
prepareClaim,
processClaimConditionInputs,
@@ -11,6 +12,7 @@ import { hasFunction } from "../../common/feature-detection";
import { isNode } from "../../common/utils";
import { NATIVE_TOKEN_ADDRESS } from "../../constants/index";
import { ClaimEligibility } from "../../enums";
import { SnapshotEntryWithProof } from "../../schema";
import {
ClaimCondition,
ClaimConditionFetchOptions,
@@ -342,6 +344,33 @@ export class DropErc1155ClaimConditions<
return reasons;
}
/**
* Returns allow list information and merkle proofs for the given address.
* @param tokenId
* @param claimerAddress
*/
public async getClaimerProofs(
tokenId: BigNumberish,
claimerAddress: string,
): Promise<SnapshotEntryWithProof | null> {
const claimCondition = await this.getActive(tokenId);
const merkeRoot = claimCondition.merkleRootHash;
const merkleRootArray = ethers.utils.stripZeros(
claimCondition.merkleRootHash,
);
if (merkleRootArray.length > 0) {
const metadata = await this.metadata.get();
return await fetchSnapshotEntryForAddress(
claimerAddress,
merkeRoot.toString(),
metadata.merkle,
this.storage,
);
} else {
return null;
}
}
/** ***************************************
* WRITE FUNCTIONS
*****************************************/
@@ -26,9 +26,13 @@ import {
Offer,
} from "../../types/marketplace";
import { TransactionResult, TransactionResultWithId } from "../types";
import { ContractEncoder } from "./contract-encoder";
import { ContractWrapper } from "./contract-wrapper";
import type { IMarketplace, Marketplace } from "@thirdweb-dev/contracts-js";
import { ListingAddedEvent } from "@thirdweb-dev/contracts-js/dist/declarations/src/Marketplace";
import {
ListingAddedEvent,
Marketplace as MarketplaceContract,
} from "@thirdweb-dev/contracts-js/dist/declarations/src/Marketplace";
import { ThirdwebStorage } from "@thirdweb-dev/storage";
import { BigNumber, BigNumberish, ethers, constants } from "ethers";
import invariant from "tiny-invariant";
@@ -40,6 +44,7 @@ import invariant from "tiny-invariant";
export class MarketplaceAuction {
private contractWrapper: ContractWrapper<Marketplace>;
private storage: ThirdwebStorage;
public encoder: ContractEncoder<MarketplaceContract>;
constructor(
contractWrapper: ContractWrapper<Marketplace>,
@@ -47,6 +52,7 @@ export class MarketplaceAuction {
) {
this.contractWrapper = contractWrapper;
this.storage = storage;
this.encoder = new ContractEncoder<Marketplace>(contractWrapper);
}
getAddress(): string {
@@ -401,9 +407,9 @@ export class MarketplaceAuction {
}
/**
* Close the Auction
* Close the Auction for the buyer or the seller
*
* @remarks Closes the Auction and executes the sale.
* @remarks Closes the Auction and executes the sale for the buyer or the seller.
*
* @example
* ```javascript
@@ -442,6 +448,49 @@ export class MarketplaceAuction {
}
}
/**
* Execute the Auction Sale
*
* @remarks Closes the Auction and executes the sale for both parties.
*
* @example
* ```javascript
* // The listing ID of the auction listing you want to close
* const listingId = "0";
* await contract.auction.executeSale(listingId);
* ```
*
* @param listingId - the auction listing ud to close
*/
public async executeSale(listingId: BigNumberish) {
const listing = await this.validateListing(BigNumber.from(listingId));
try {
const winningBid = await this.getWinningBid(listingId);
invariant(winningBid, "No winning bid found");
const closeForSeller = this.encoder.encode("closeAuction", [
listingId,
listing.sellerAddress,
]);
const closeForBuyer = this.encoder.encode("closeAuction", [
listingId,
winningBid.buyerAddress,
]);
return await this.contractWrapper.multiCall([
closeForSeller,
closeForBuyer,
]);
} catch (err: any) {
if (err.message.includes("cannot close auction before it has ended")) {
throw new AuctionHasNotEndedError(
listingId.toString(),
listing.endTimeInEpochSeconds.toString(),
);
} else {
throw err;
}
}
}
/**
* Update an Auction listing with new metadata
* @param listing - the listing id to update
+2 -2
View File
@@ -57,12 +57,12 @@ export const BigNumberTransformSchema = z
export const BasisPointsSchema = z
.number()
.max(MAX_BPS, "Cannot exeed 100%")
.max(MAX_BPS, "Cannot exceed 100%")
.min(0, "Cannot be below 0%");
export const PercentSchema = z
.number()
.max(100, "Cannot exeed 100%")
.max(100, "Cannot exceed 100%")
.min(0, "Cannot be below 0%");
export const AddressSchema = z.string().refine(
@@ -13,14 +13,14 @@ export function enforceCreator(
// If no creators are specified, we assume the owner is the creator
creators = creators.concat({
address: owner.toBase58(),
sharePercentage: 100,
share: 100,
verified: true,
});
}
return creators.map((creator) => ({
verified: creator.verified || false,
address: new PublicKey(creator.address),
share: creator.sharePercentage,
share: creator.share,
}));
}
+2 -2
View File
@@ -12,7 +12,7 @@ export const MAX_BPS = 10000;
*/
export const BasisPointsSchema = z
.number()
.max(MAX_BPS, "Cannot exeed 100%")
.max(MAX_BPS, "Cannot exceed 100%")
.min(0, "Cannot be below 0%");
/**
@@ -20,7 +20,7 @@ export const BasisPointsSchema = z
*/
export const PercentSchema = z
.number()
.max(100, "Cannot exeed 100%")
.max(100, "Cannot exceed 100%")
.min(0, "Cannot be below 0%");
/**
@@ -1,4 +1,4 @@
import { AmountSchema, FileOrBufferOrStringSchema } from "../common";
import { AmountSchema, FileOrBufferOrStringSchema, PercentSchema } from "../common";
import { Creator } from "@metaplex-foundation/js";
import { z } from "zod";
@@ -27,7 +27,7 @@ export const CommonContractOutputSchema = CommonContractSchema.extend({
*/
export const CreatorInputSchema = z.object({
address: z.string(),
sharePercentage: z.number(),
share: PercentSchema,
verified: z.boolean().default(false),
});
+18 -49
View File
@@ -200,7 +200,7 @@ describe("Marketplace Contract", async () => {
});
const id = tx.id;
sdk.updateSignerOrProvider(samWallet);
await marketplaceContract.auction.makeBid(id, 0.1);
await marketplaceContract.makeOffer(id, 0.1);
});
it("Should list with native currency address", async () => {
@@ -429,13 +429,7 @@ describe("Marketplace Contract", async () => {
"The buyer should start with no tokens",
);
await marketplaceContract.direct.makeOffer(
directListingId,
10,
tokenAddress,
0.034,
new Date(Date.now() + 60 * 60 * 24 * 10 * 1000),
);
await marketplaceContract.makeOffer(directListingId, 0.034, 10);
await sdk.updateSignerOrProvider(adminWallet);
await marketplaceContract.direct.acceptOffer(
@@ -482,12 +476,7 @@ describe("Marketplace Contract", async () => {
"0",
"The buyer should start with no tokens",
);
await marketplaceContract.direct.makeOffer(
directListingId,
1,
customTokenContract.getAddress(),
0.05,
);
await marketplaceContract.makeOffer(directListingId, 0.05, 1);
await marketplaceContract.buyoutListing(directListingId, 1);
const balance = await dummyNftContract.balanceOf(bobWallet.address);
assert.equal(
@@ -517,12 +506,7 @@ describe("Marketplace Contract", async () => {
it("should allow offers to be made on direct listings", async () => {
sdk.updateSignerOrProvider(bobWallet);
await marketplaceContract.direct.makeOffer(
directListingId,
1,
tokenAddress,
"1",
);
await marketplaceContract.makeOffer(directListingId, 1, "1");
const offer = (await marketplaceContract.direct.getActiveOffer(
directListingId,
@@ -537,12 +521,7 @@ describe("Marketplace Contract", async () => {
assert.equal(offer.listingId.toString(), directListingId.toString());
sdk.updateSignerOrProvider(samWallet);
await marketplaceContract.direct.makeOffer(
directListingId,
1,
tokenAddress,
"1",
);
await marketplaceContract.makeOffer(directListingId, 1, "1");
const secondOffer = (await marketplaceContract.direct.getActiveOffer(
directListingId,
@@ -567,8 +546,8 @@ describe("Marketplace Contract", async () => {
it("should allow bids by the same person", async () => {
await sdk.updateSignerOrProvider(bobWallet);
await marketplaceContract.auction.makeBid(auctionListingId, 0.06);
await marketplaceContract.auction.makeBid(auctionListingId, 0.08);
await marketplaceContract.makeOffer(auctionListingId, 0.06);
await marketplaceContract.makeOffer(auctionListingId, 0.08);
const winningBid = (await marketplaceContract.auction.getWinningBid(
auctionListingId,
@@ -583,7 +562,7 @@ describe("Marketplace Contract", async () => {
it("should allow bids to be made on auction listings", async () => {
await sdk.updateSignerOrProvider(bobWallet);
await marketplaceContract.auction.makeBid(auctionListingId, 0.06);
await marketplaceContract.makeOffer(auctionListingId, 0.06);
let winningBid = (await marketplaceContract.auction.getWinningBid(
auctionListingId,
@@ -601,7 +580,7 @@ describe("Marketplace Contract", async () => {
// Make a higher winning bid
await sdk.updateSignerOrProvider(samWallet);
await marketplaceContract.auction.makeBid(auctionListingId, 0.09);
await marketplaceContract.makeOffer(auctionListingId, 0.09);
winningBid = (await marketplaceContract.auction.getWinningBid(
auctionListingId,
@@ -620,21 +599,11 @@ describe("Marketplace Contract", async () => {
it("should return all offers for a listing when queried", async () => {
// make an offer as bob
sdk.updateSignerOrProvider(bobWallet);
await marketplaceContract.direct.makeOffer(
directListingId,
1,
tokenAddress,
"0.5",
);
await marketplaceContract.makeOffer(directListingId, "0.5", 1);
// make an offer as sam
sdk.updateSignerOrProvider(samWallet);
await marketplaceContract.direct.makeOffer(
directListingId,
1,
tokenAddress,
"1",
);
await marketplaceContract.makeOffer(directListingId, "1", 1);
// fetch all offers for the listing
sdk.updateSignerOrProvider(adminWallet);
@@ -725,7 +694,7 @@ describe("Marketplace Contract", async () => {
"0",
"The buyer should start with no tokens",
);
await marketplaceContract.auction.makeBid(auctionListingId, "20");
await marketplaceContract.makeOffer(auctionListingId, "20");
const balance = await dummyNftContract.balanceOf(bobWallet.address);
assert.equal(
@@ -748,7 +717,7 @@ describe("Marketplace Contract", async () => {
"0",
"The buyer should start with no tokens",
);
await marketplaceContract.auction.makeBid(auctionListingId, "2");
await marketplaceContract.makeOffer(auctionListingId, "2");
const winningBid = (await marketplaceContract.auction.getWinningBid(
auctionListingId,
@@ -782,9 +751,9 @@ describe("Marketplace Contract", async () => {
"0",
"The buyer should start with no tokens",
);
await marketplaceContract.auction.makeBid(auctionListingId, "2");
await marketplaceContract.makeOffer(auctionListingId, "2");
try {
await marketplaceContract.auction.makeBid(auctionListingId, "2.01");
await marketplaceContract.makeOffer(auctionListingId, "2.01");
// eslint-disable-next-line no-empty
} catch (err) {}
});
@@ -860,7 +829,7 @@ describe("Marketplace Contract", async () => {
});
it("should throw an error when trying to close an auction that already started (with bids)", async () => {
await marketplaceContract.auction.makeBid(auctionListingId, 0.06);
await marketplaceContract.makeOffer(auctionListingId, 0.06);
try {
await marketplaceContract.auction.cancelListing(auctionListingId);
assert.fail("should have thrown an error");
@@ -933,7 +902,7 @@ describe("Marketplace Contract", async () => {
await sdk.updateSignerOrProvider(bobWallet);
await marketplaceContract.auction.makeBid(listingId, 2);
await marketplaceContract.makeOffer(listingId, 2);
await fastForwardTime(60 * 60 * 24);
@@ -1185,7 +1154,7 @@ describe("Marketplace Contract", async () => {
// place a bid
sdk.updateSignerOrProvider(samWallet);
await marketplaceContract.auction.makeBid(listingId, 0.06);
await marketplaceContract.makeOffer(listingId, 0.06);
const minimumNextBid =
await marketplaceContract.auction.getMinimumNextBid(listingId);
+5
View File
@@ -97,6 +97,11 @@ describe("NFT Drop Contract", async () => {
(c) => c.merkleRootHash,
);
expect(roots).length(2);
const proof = await dropContract.claimConditions.getClaimerProofs(
bobWallet.address,
);
expect(proof.address).to.eq(bobWallet.address);
});
it("should return snapshot data on claim conditions", async () => {
@@ -143,8 +143,8 @@ describe("NFTCollection", async () => {
const newCreator = Keypair.generate().publicKey.toBase58();
await collection.updateCreators([
{ address: sdk.wallet.getAddress() as string, sharePercentage: 75 },
{ address: newCreator, sharePercentage: 25 },
{ address: sdk.wallet.getAddress() as string, share: 75 },
{ address: newCreator, share: 25 },
]);
creators = await collection.getCreators();
+2 -2
View File
@@ -133,8 +133,8 @@ describe("NFTDrop", async () => {
const newCreator = Keypair.generate().publicKey.toBase58();
await drop.updateCreators([
{ address: sdk.wallet.getAddress() as string, sharePercentage: 75 },
{ address: newCreator, sharePercentage: 25 },
{ address: sdk.wallet.getAddress() as string, share: 75 },
{ address: newCreator, share: 25 },
]);
creators = await drop.getCreators();
+8
View File
@@ -1,5 +1,13 @@
# e2e-cra-5
## 0.1.2
### Patch Changes
- Updated dependencies [[`72227b2`](https://github.com/thirdweb-dev/js/commit/72227b2e166a3a68bbb41cf2b389322f5b7547a2), [`72227b2`](https://github.com/thirdweb-dev/js/commit/72227b2e166a3a68bbb41cf2b389322f5b7547a2)]:
- @thirdweb-dev/react@3.4.1
- @thirdweb-dev/sdk@3.4.1
## 0.1.1
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "e2e-cra-5",
"version": "0.1.1",
"version": "0.1.2",
"private": true,
"dependencies": {
"@thirdweb-dev/react": "*",
+8
View File
@@ -1,5 +1,13 @@
# e2e-next-12
## 0.1.2
### Patch Changes
- Updated dependencies [[`72227b2`](https://github.com/thirdweb-dev/js/commit/72227b2e166a3a68bbb41cf2b389322f5b7547a2), [`72227b2`](https://github.com/thirdweb-dev/js/commit/72227b2e166a3a68bbb41cf2b389322f5b7547a2)]:
- @thirdweb-dev/react@3.4.1
- @thirdweb-dev/sdk@3.4.1
## 0.1.1
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "e2e-next-12",
"version": "0.1.1",
"version": "0.1.2",
"private": true,
"scripts": {
"build": "next build",
+8
View File
@@ -1,5 +1,13 @@
# e2e-vite-3
## 0.0.2
### Patch Changes
- Updated dependencies [[`72227b2`](https://github.com/thirdweb-dev/js/commit/72227b2e166a3a68bbb41cf2b389322f5b7547a2), [`72227b2`](https://github.com/thirdweb-dev/js/commit/72227b2e166a3a68bbb41cf2b389322f5b7547a2)]:
- @thirdweb-dev/react@3.4.1
- @thirdweb-dev/sdk@3.4.1
## 0.0.1
### Patch Changes
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "e2e-vite-3",
"private": true,
"version": "0.0.1",
"version": "0.0.2",
"type": "module",
"scripts": {
"build": "vite build",