Compare commits
10
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
408c5a81fa | ||
|
|
352291791e | ||
|
|
aabbb149e8 | ||
|
|
d59450f814 | ||
|
|
7d9a4c6abc | ||
|
|
99806e595d | ||
|
|
21c21c1adf | ||
|
|
4b10719047 | ||
|
|
989cf7347c | ||
|
|
72227b2e16 |
@@ -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
|
||||
|
||||
@@ -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/**}"
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
# @thirdweb-dev/auth
|
||||
|
||||
## 2.0.23
|
||||
|
||||
## 2.0.22
|
||||
|
||||
## 2.0.21
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/auth",
|
||||
"version": "2.0.21",
|
||||
"version": "2.0.23",
|
||||
"exports": {
|
||||
"./next": {
|
||||
"module": "./next/dist/thirdweb-dev-auth-next.esm.js",
|
||||
|
||||
@@ -1,5 +1,19 @@
|
||||
# thirdweb
|
||||
|
||||
## 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,7 +1,7 @@
|
||||
{
|
||||
"name": "thirdweb",
|
||||
"main": "dist/cli/index.js",
|
||||
"version": "0.8.7",
|
||||
"version": "0.8.9",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/cli",
|
||||
"author": "thirdweb eng <[email protected]>",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# @thirdweb-dev/react
|
||||
|
||||
## 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,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/react",
|
||||
"version": "3.4.0",
|
||||
"version": "3.4.2",
|
||||
"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,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(
|
||||
() => ({
|
||||
|
||||
@@ -212,6 +212,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
|
||||
|
||||
+2
-2
@@ -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 { 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)),
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -14,6 +14,8 @@ 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";
|
||||
|
||||
// NFT Collection
|
||||
export * from "./hooks/nft/collection/useMintNFT";
|
||||
|
||||
@@ -1,5 +1,19 @@
|
||||
# @thirdweb-dev/sdk
|
||||
|
||||
## 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,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/sdk",
|
||||
"version": "3.4.0",
|
||||
"version": "3.4.2",
|
||||
"description": "The main thirdweb SDK.",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/sdk",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,6 +1,6 @@
|
||||
{
|
||||
"name": "e2e-cra-5",
|
||||
"version": "0.1.1",
|
||||
"version": "0.1.2",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@thirdweb-dev/react": "*",
|
||||
|
||||
@@ -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,6 +1,6 @@
|
||||
{
|
||||
"name": "e2e-next-12",
|
||||
"version": "0.1.1",
|
||||
"version": "0.1.2",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "next build",
|
||||
|
||||
@@ -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,7 +1,7 @@
|
||||
{
|
||||
"name": "e2e-vite-3",
|
||||
"private": true,
|
||||
"version": "0.0.1",
|
||||
"version": "0.0.2",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "vite build",
|
||||
|
||||
Reference in New Issue
Block a user