opensea-js
Advanced tools
Comparing version 6.1.7 to 6.1.8
@@ -147,2 +147,12 @@ import { ethers } from "ethers"; | ||
/** | ||
* Fetch NFTs owned by an account. | ||
* @param address The address of the account | ||
* @param limit The number of NFTs to retrieve. Must be greater than 0 and less than 51. | ||
* @param next Cursor to retrieve the next page of NFTs | ||
* @param retries Number of times to retry if the service is unavailable for any reason. | ||
* @param chain The chain to query. Defaults to the chain set in the constructor. | ||
* @returns The {@link ListNFTsResponse} returned by the API. | ||
*/ | ||
getNFTsByAccount(address: string, limit?: number | undefined, next?: string | undefined, retries?: number, chain?: Chain): Promise<ListNFTsResponse>; | ||
/** | ||
* Fetch metadata, traits, ownership information, and rarity for a single NFT. | ||
@@ -149,0 +159,0 @@ * @param chain The NFT's chain. |
@@ -286,2 +286,28 @@ "use strict"; | ||
/** | ||
* Fetch NFTs owned by an account. | ||
* @param address The address of the account | ||
* @param limit The number of NFTs to retrieve. Must be greater than 0 and less than 51. | ||
* @param next Cursor to retrieve the next page of NFTs | ||
* @param retries Number of times to retry if the service is unavailable for any reason. | ||
* @param chain The chain to query. Defaults to the chain set in the constructor. | ||
* @returns The {@link ListNFTsResponse} returned by the API. | ||
*/ | ||
getNFTsByAccount(address, limit = undefined, next = undefined, retries = 1, chain = this.chain) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
let response; | ||
try { | ||
response = yield this.get((0, utils_1.getListNFTsByAccountPath)(chain, address), { | ||
limit, | ||
next, | ||
}); | ||
} | ||
catch (error) { | ||
_throwOrContinue(error, retries); | ||
yield (0, utils_2.delay)(1000); | ||
return this.getNFTsByAccount(address, limit, next, retries - 1, chain); | ||
} | ||
return response; | ||
}); | ||
} | ||
/** | ||
* Fetch metadata, traits, ownership information, and rarity for a single NFT. | ||
@@ -288,0 +314,0 @@ * @param chain The NFT's chain. |
@@ -7,2 +7,3 @@ export declare const INVERSE_BASIS_POINT = 10000; | ||
export declare const DEFAULT_ZONE = "0x0000000000000000000000000000000000000000"; | ||
export declare const ENGLISH_AUCTION_ZONE = "0x110b2b128a9ed1be5ef3232d8e4e41640df5c2cd"; | ||
export declare const SHARED_STOREFRONT_ADDRESS_MAINNET = "0x495f947276749ce646f68ac8c248420045cb7b5e"; | ||
@@ -9,0 +10,0 @@ export declare const SHARED_STOREFRONT_ADDRESS_GOERLI = "0x804159144aefb1dc17b171afcefa5b33746c722f"; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.SHARED_STOREFRONT_LAZY_MINT_ADAPTER_CROSS_CHAIN_ADDRESS = exports.SHARED_STOREFRONT_ADDRESSES = exports.SHARED_STOREFRONT_ADDRESS_GOERLI = exports.SHARED_STOREFRONT_ADDRESS_MAINNET = exports.DEFAULT_ZONE = exports.API_V1_PATH = exports.API_BASE_TESTNET = exports.API_BASE_MAINNET = exports.MAX_EXPIRATION_MONTHS = exports.INVERSE_BASIS_POINT = void 0; | ||
exports.SHARED_STOREFRONT_LAZY_MINT_ADAPTER_CROSS_CHAIN_ADDRESS = exports.SHARED_STOREFRONT_ADDRESSES = exports.SHARED_STOREFRONT_ADDRESS_GOERLI = exports.SHARED_STOREFRONT_ADDRESS_MAINNET = exports.ENGLISH_AUCTION_ZONE = exports.DEFAULT_ZONE = exports.API_V1_PATH = exports.API_BASE_TESTNET = exports.API_BASE_MAINNET = exports.MAX_EXPIRATION_MONTHS = exports.INVERSE_BASIS_POINT = void 0; | ||
const ethers_1 = require("ethers"); | ||
@@ -11,2 +11,3 @@ exports.INVERSE_BASIS_POINT = 10000; // 100 basis points per 1% | ||
exports.DEFAULT_ZONE = ethers_1.ethers.constants.AddressZero; | ||
exports.ENGLISH_AUCTION_ZONE = "0x110b2b128a9ed1be5ef3232d8e4e41640df5c2cd"; | ||
// Ignore eslint no-unused-modules for below to keep backward compatibility | ||
@@ -13,0 +14,0 @@ // in case a downstream user was already using these imports directly. |
@@ -11,2 +11,3 @@ import { OrderProtocol, OrdersQueryOptions, OrderSide, OrderV2, SerializedOrderV2, ProtocolData } from "./types"; | ||
export declare const getListNFTsByContractPath: (chain: Chain, address: string) => string; | ||
export declare const getListNFTsByAccountPath: (chain: Chain, address: string) => string; | ||
export declare const getNFTPath: (chain: Chain, address: string, identifier: string) => string; | ||
@@ -13,0 +14,0 @@ export declare const getRefreshMetadataPath: (chain: Chain, address: string, identifier: string) => string; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.deserializeOrder = exports.serializeOrdersQueryOptions = exports.getFulfillOfferPayload = exports.getFulfillListingPayload = exports.getFulfillmentDataPath = exports.getBuildCollectionOfferPayload = exports.getPostCollectionOfferPayload = exports.getRefreshMetadataPath = exports.getNFTPath = exports.getListNFTsByContractPath = exports.getListNFTsByCollectionPath = exports.getCollectionOffersPath = exports.getPostCollectionOfferPath = exports.getBuildOfferPath = exports.getCollectionPath = exports.getOrdersAPIPath = exports.DEFAULT_SEAPORT_CONTRACT_ADDRESS = void 0; | ||
exports.deserializeOrder = exports.serializeOrdersQueryOptions = exports.getFulfillOfferPayload = exports.getFulfillListingPayload = exports.getFulfillmentDataPath = exports.getBuildCollectionOfferPayload = exports.getPostCollectionOfferPayload = exports.getRefreshMetadataPath = exports.getNFTPath = exports.getListNFTsByAccountPath = exports.getListNFTsByContractPath = exports.getListNFTsByCollectionPath = exports.getCollectionOffersPath = exports.getPostCollectionOfferPath = exports.getBuildOfferPath = exports.getCollectionPath = exports.getOrdersAPIPath = exports.DEFAULT_SEAPORT_CONTRACT_ADDRESS = void 0; | ||
const constants_1 = require("@opensea/seaport-js/lib/constants"); | ||
@@ -37,2 +37,6 @@ const ethers_1 = require("ethers"); | ||
exports.getListNFTsByContractPath = getListNFTsByContractPath; | ||
const getListNFTsByAccountPath = (chain, address) => { | ||
return `/v2/chain/${chain}/account/${address}/nfts`; | ||
}; | ||
exports.getListNFTsByAccountPath = getListNFTsByAccountPath; | ||
const getNFTPath = (chain, address, identifier) => { | ||
@@ -39,0 +43,0 @@ return `/v2/chain/${chain}/contract/${address}/nfts/${identifier}`; |
@@ -120,2 +120,3 @@ import { Seaport } from "@opensea/seaport-js"; | ||
* @param options.buyerAddress Optional address that's allowed to purchase this item. If specified, no other address will be able to take the order, unless its value is the null address. | ||
* @param options.englishAuction If true, the order will be listed as an English auction. | ||
* @returns The {@link OrderV2} that was created. | ||
@@ -128,3 +129,3 @@ * | ||
*/ | ||
createSellOrder({ asset, accountAddress, startAmount, endAmount, quantity, domain, salt, listingTime, expirationTime, paymentTokenAddress, buyerAddress, }: { | ||
createSellOrder({ asset, accountAddress, startAmount, endAmount, quantity, domain, salt, listingTime, expirationTime, paymentTokenAddress, buyerAddress, englishAuction, }: { | ||
asset: Asset; | ||
@@ -141,2 +142,3 @@ accountAddress: string; | ||
buyerAddress?: string; | ||
englishAuction?: boolean; | ||
}): Promise<OrderV2>; | ||
@@ -260,4 +262,2 @@ /** | ||
* @param endAmount The end value for the order, in the token's main units (e.g. ETH instead of wei). If unspecified, the order's `extra` attribute will be 0 | ||
* @param waitingForBestCounterOrder | ||
* @param englishAuctionReservePrice | ||
*/ | ||
@@ -264,0 +264,0 @@ private _getPriceParameters; |
@@ -260,2 +260,3 @@ "use strict"; | ||
* @param options.buyerAddress Optional address that's allowed to purchase this item. If specified, no other address will be able to take the order, unless its value is the null address. | ||
* @param options.englishAuction If true, the order will be listed as an English auction. | ||
* @returns The {@link OrderV2} that was created. | ||
@@ -268,3 +269,3 @@ * | ||
*/ | ||
createSellOrder({ asset, accountAddress, startAmount, endAmount, quantity = 1, domain, salt, listingTime, expirationTime, paymentTokenAddress = ethers_1.ethers.constants.AddressZero, buyerAddress, }) { | ||
createSellOrder({ asset, accountAddress, startAmount, endAmount, quantity = 1, domain, salt, listingTime, expirationTime, paymentTokenAddress = ethers_1.ethers.constants.AddressZero, buyerAddress, englishAuction, }) { | ||
var _a; | ||
@@ -278,2 +279,5 @@ return __awaiter(this, void 0, void 0, function* () { | ||
const offerAssetItems = this.getNFTItems([nft], [ethers_1.BigNumber.from(quantity !== null && quantity !== void 0 ? quantity : 1)]); | ||
if (englishAuction && paymentTokenAddress == ethers_1.ethers.constants.AddressZero) { | ||
throw new Error(`English auctions must use wrapped ETH or an ERC-20 token.`); | ||
} | ||
const { basePrice, endPrice } = yield this._getPriceParameters(types_1.OrderSide.Sell, paymentTokenAddress, expirationTime !== null && expirationTime !== void 0 ? expirationTime : (0, utils_3.getMaxOrderExpirationTimestamp)(), startAmount, endAmount !== null && endAmount !== void 0 ? endAmount : undefined); | ||
@@ -300,7 +304,7 @@ const collection = yield this.api.getCollection(nft.collection); | ||
endTime: (_a = expirationTime === null || expirationTime === void 0 ? void 0 : expirationTime.toString()) !== null && _a !== void 0 ? _a : (0, utils_3.getMaxOrderExpirationTimestamp)().toString(), | ||
zone: constants_2.DEFAULT_ZONE, | ||
zone: englishAuction ? constants_2.ENGLISH_AUCTION_ZONE : constants_2.DEFAULT_ZONE, | ||
domain, | ||
salt: ethers_1.BigNumber.from(salt !== null && salt !== void 0 ? salt : 0).toString(), | ||
restrictedByZone: false, | ||
allowPartialFills: true, | ||
restrictedByZone: englishAuction ? true : false, | ||
allowPartialFills: englishAuction ? false : true, | ||
}, accountAddress); | ||
@@ -420,5 +424,5 @@ const order = yield executeAllActions(); | ||
// must be included with the order to successfully fulfill. | ||
const fulfillmentOrder = result.fulfillment_data.transaction.input_data.orders[0]; | ||
if ("extraData" in fulfillmentOrder) { | ||
extraData = fulfillmentOrder.extraData; | ||
const inputData = result.fulfillment_data.transaction.input_data; | ||
if ("orders" in inputData && "extraData" in inputData.orders[0]) { | ||
extraData = inputData.orders[0].extraData; | ||
} | ||
@@ -632,6 +636,4 @@ const signature = result.fulfillment_data.orders[0].signature; | ||
* @param endAmount The end value for the order, in the token's main units (e.g. ETH instead of wei). If unspecified, the order's `extra` attribute will be 0 | ||
* @param waitingForBestCounterOrder | ||
* @param englishAuctionReservePrice | ||
*/ | ||
_getPriceParameters(orderSide, tokenAddress, expirationTime, startAmount, endAmount, waitingForBestCounterOrder = false, englishAuctionReservePrice) { | ||
_getPriceParameters(orderSide, tokenAddress, expirationTime, startAmount, endAmount) { | ||
var _a; | ||
@@ -658,5 +660,2 @@ return __awaiter(this, void 0, void 0, function* () { | ||
const extra = priceDiffWei; | ||
const reservePrice = englishAuctionReservePrice | ||
? ethers_1.ethers.utils.parseUnits(startAmount.toString(), decimals) | ||
: undefined; | ||
// Validation | ||
@@ -681,5 +680,2 @@ if (startAmount == null || startAmountWei.lt(0)) { | ||
} | ||
if (isEther && waitingForBestCounterOrder) { | ||
throw new Error(`English auctions must use wrapped ETH or an ERC-20 token.`); | ||
} | ||
if (isEther && orderSide === types_1.OrderSide.Buy) { | ||
@@ -694,10 +690,3 @@ throw new Error(`Offers must use wrapped ETH or an ERC-20 token.`); | ||
} | ||
const reservePriceIsDefinedAndNonZero = reservePrice && !reservePrice.isZero(); | ||
if (reservePriceIsDefinedAndNonZero && !waitingForBestCounterOrder) { | ||
throw new Error("Reserve prices may only be set on English auctions."); | ||
} | ||
if (reservePriceIsDefinedAndNonZero && (reservePrice === null || reservePrice === void 0 ? void 0 : reservePrice.lt(startAmountWei))) { | ||
throw new Error("Reserve price must be greater than or equal to the start amount."); | ||
} | ||
return { basePrice, extra, paymentToken, reservePrice, endPrice }; | ||
return { basePrice, extra, paymentToken, endPrice }; | ||
}); | ||
@@ -704,0 +693,0 @@ } |
@@ -154,9 +154,2 @@ import { BigNumber, BigNumberish } from "ethers"; | ||
/** | ||
* Type of sale. | ||
*/ | ||
export declare enum SaleKind { | ||
FixedPrice = 0, | ||
DutchAuction = 1 | ||
} | ||
/** | ||
* Types of asset contracts | ||
@@ -556,8 +549,2 @@ * Given by the asset_contract_type in the OpenSea API | ||
export type ExchangeMetadata = ExchangeMetadataForAsset | ExchangeMetadataForBundle; | ||
export declare enum HowToCall { | ||
Call = 0, | ||
DelegateCall = 1, | ||
StaticCall = 2, | ||
Create = 3 | ||
} | ||
export interface UnsignedOrder { | ||
@@ -586,8 +573,3 @@ hash?: string; | ||
side: OrderSide; | ||
saleKind: SaleKind; | ||
howToCall: HowToCall; | ||
quantity: BigNumber; | ||
makerReferrerFee: BigNumber; | ||
waitingForBestCounterOrder: boolean; | ||
englishAuctionReservePrice?: BigNumber; | ||
metadata: ExchangeMetadata; | ||
@@ -616,3 +598,2 @@ } | ||
assetBundle?: OpenSeaAssetBundle; | ||
nonce?: number; | ||
} | ||
@@ -635,5 +616,3 @@ /** | ||
side: number; | ||
saleKind: number; | ||
target: string; | ||
howToCall: number; | ||
calldata: string; | ||
@@ -649,8 +628,5 @@ replacementPattern: string; | ||
salt: string; | ||
makerReferrerFee: string; | ||
quantity: string; | ||
englishAuctionReservePrice: string | undefined; | ||
createdTime?: number | string; | ||
metadata: ExchangeMetadata; | ||
nonce?: number; | ||
} | ||
@@ -657,0 +633,0 @@ /** |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.HowToCall = exports.SafelistStatus = exports.TokenStandard = exports.AssetContractType = exports.SaleKind = exports.FeeMethod = exports.OrderSide = exports.Chain = exports.EventType = void 0; | ||
exports.SafelistStatus = exports.TokenStandard = exports.AssetContractType = exports.FeeMethod = exports.OrderSide = exports.Chain = exports.EventType = void 0; | ||
/** | ||
@@ -36,3 +36,2 @@ * Events emitted by the SDK which can be used by frontends applications | ||
EventType["UnwrapWeth"] = "UnwrapWeth"; | ||
// Basic actions: matching orders, creating orders, and cancelling orders | ||
/** | ||
@@ -123,10 +122,2 @@ * Emitted when fulfilling a public or private order. | ||
/** | ||
* Type of sale. | ||
*/ | ||
var SaleKind; | ||
(function (SaleKind) { | ||
SaleKind[SaleKind["FixedPrice"] = 0] = "FixedPrice"; | ||
SaleKind[SaleKind["DutchAuction"] = 1] = "DutchAuction"; | ||
})(SaleKind || (exports.SaleKind = SaleKind = {})); | ||
/** | ||
* Types of asset contracts | ||
@@ -192,9 +183,2 @@ * Given by the asset_contract_type in the OpenSea API | ||
})(AssetEventType || (AssetEventType = {})); | ||
var HowToCall; | ||
(function (HowToCall) { | ||
HowToCall[HowToCall["Call"] = 0] = "Call"; | ||
HowToCall[HowToCall["DelegateCall"] = 1] = "DelegateCall"; | ||
HowToCall[HowToCall["StaticCall"] = 2] = "StaticCall"; | ||
HowToCall[HowToCall["Create"] = 3] = "Create"; | ||
})(HowToCall || (exports.HowToCall = HowToCall = {})); | ||
//# sourceMappingURL=types.js.map |
{ | ||
"name": "opensea-js", | ||
"version": "6.1.7", | ||
"version": "6.1.8", | ||
"description": "JavaScript SDK for the OpenSea marketplace helps developers build new experiences using NFTs and our marketplace data!", | ||
@@ -5,0 +5,0 @@ "license": "MIT", |
165
README.md
@@ -23,3 +23,2 @@ <p align="center"> | ||
- [Making Offers](#making-offers) | ||
- [Bidding on ENS Short Name Auctions](#bidding-on-ens-short-name-auctions) | ||
- [Offer Limits](#offer-limits) | ||
@@ -30,3 +29,2 @@ - [Making Listings / Selling Items](#making-listings--selling-items) | ||
- [Accepting Offers](#accepting-offers) | ||
- [Transferring Items or Coins (Gifting)](#transferring-items-or-coins-gifting) | ||
- [Advanced](#advanced) | ||
@@ -48,3 +46,3 @@ - [Scheduling Future Listings](#scheduling-future-listings) | ||
It allows developers to access the official orderbook, filter it, create buy orders (**offers**), create sell orders (**auctions**), and complete trades programmatically. | ||
It allows developers to access the official orderbook, filter it, create buy orders (**offers**), create sell orders (**listings**), and complete trades programmatically. | ||
@@ -57,3 +55,3 @@ Get started by [requesting an API key](https://docs.opensea.io/reference/api-keys) and instantiating your own OpenSea SDK instance. Then you can create orders off-chain or fulfill orders on-chain, and listen to events (like `ApproveAllAssets` or `WrapEth`) in the process. | ||
Switching to Node.js version 16 is required for SDK Version 3.0+ and to make sure common crypto dependencies work. Execute `nvm use`, if you have Node Version Manager. | ||
Node.js version 16 is the minimum required for the SDK. Execute `nvm use`, if you have Node Version Manager. | ||
@@ -176,33 +174,2 @@ Then, in your project, run: | ||
#### Bidding on ENS Short Name Auctions | ||
The Ethereum Name Service (ENS) is auctioning short (3-6 character) names that can be used for labeling wallet addresses and more. Learn more on the [ENS FAQ](https://opensea.io/ens). | ||
To bid, you must use the ENS Short Name schema: | ||
```typescript | ||
const { | ||
tokenId, | ||
// Token address should be `0xfac7bea255a6990f749363002136af6556b31e04` on mainnet | ||
tokenAddress, | ||
// Name must have `.eth` at the end and correspond with the tokenId | ||
name | ||
} = ENS_ASSET // You can get an ENS asset from `openseaSDK.api.getAsset(...)` | ||
const offer = await openseaSDK.createBuyOrder({ | ||
asset: { | ||
tokenId, | ||
tokenAddress, | ||
name, | ||
// Only needed for the short-name auction, not ENS names | ||
// that have been sold once already: | ||
tokenStandard: "ENSShortNameAuction" | ||
}, | ||
// Your wallet address (the bidder's address): | ||
accountAddress: "0x1234..." | ||
// Value of the offer, in wrapped ETH: | ||
startAmount: 1.2, | ||
}) | ||
``` | ||
#### Offer Limits | ||
@@ -242,3 +209,3 @@ | ||
To create an English Auction, create a listing that waits for the highest bid by setting `waitForHighestBid` to `true`: | ||
To create an English Auction set `englishAuction` to `true`: | ||
@@ -251,3 +218,3 @@ ```typescript | ||
const auction = await openseaSDK.createSellOrder({ | ||
const order = await openseaSDK.createSellOrder({ | ||
asset: { | ||
@@ -261,3 +228,3 @@ tokenId, | ||
paymentTokenAddress, | ||
waitForHighestBid: true, | ||
englishAuction: true, | ||
}); | ||
@@ -300,3 +267,2 @@ ``` | ||
* Attrs used by orderbook to make queries easier | ||
* More to come soon! | ||
*/ | ||
@@ -308,3 +274,2 @@ side: "bid" | "ask", // "bid" for buy orders, "ask" for sell orders | ||
owner?: string, // Address of owner of the order's item | ||
sale_kind?: SaleKind, // 0 for fixed-price, 1 for Dutch auctions | ||
assetContractAddress?: string, // Contract address for order's item | ||
@@ -351,53 +316,2 @@ paymentTokenAddress?: string; // Contract address for order's payment token | ||
### Transferring Items or Coins (Gifting) | ||
A handy feature in OpenSea.js is the ability to transfer any supported asset (fungible or non-fungible tokens) in one line of JavaScript. | ||
To transfer an ERC-721 asset or an ERC-1155 asset, it's just one call: | ||
```typescript | ||
const transactionHash = await openseaSDK.transfer({ | ||
asset: { tokenId, tokenAddress }, | ||
fromAddress, // Must own the asset | ||
toAddress, | ||
}); | ||
``` | ||
For fungible ERC-1155 assets, you can set `tokenStandard` to "ERC1155" and pass a `quantity` in to transfer multiple at once: | ||
```typescript | ||
const transactionHash = await openseaSDK.transfer({ | ||
asset: { | ||
tokenId, | ||
tokenAddress, | ||
tokenStandard: "ERC1155", | ||
}, | ||
fromAddress, // Must own the asset | ||
toAddress, | ||
quantity: 2, | ||
}); | ||
``` | ||
To transfer fungible assets without token IDs, like ERC20 tokens, you can pass in an `OpenSeaFungibleToken` as the `asset`, set `tokenStandard` to "ERC20", and include `quantity` in base units (e.g. wei) to indicate how many. | ||
Example for transferring 2 DAI ($2) to another address: | ||
```typescript | ||
const paymentToken = (await openseaSDK.api.getPaymentTokens({ symbol: "DAI" })) | ||
.tokens[0]; | ||
const quantity = ethers.utils.parseUnits("2", paymentToken.decimals); | ||
const transactionHash = await openseaSDK.transfer({ | ||
asset: { | ||
tokenId: null, | ||
tokenAddress: paymentToken.address, | ||
tokenStandard: "ERC20", | ||
}, | ||
fromAddress, // Must own the tokens | ||
toAddress, | ||
quantity, | ||
}); | ||
``` | ||
For more information, check out the [documentation](https://projectopensea.github.io/opensea-js/). | ||
## Advanced | ||
@@ -412,3 +326,3 @@ | ||
```typescript | ||
const auction = await openseaSDK.createSellOrder({ | ||
const order = await openseaSDK.createSellOrder({ | ||
tokenAddress, | ||
@@ -469,10 +383,5 @@ tokenId, | ||
**Fun note:** soon, all ERC-20 tokens will be allowed! This will mean you can create crazy offers on crypto collectibles **using your own ERC-20 token**. However, opensea.io will only display offers and auctions in ERC-20 tokens that it knows about, optimizing the user experience of order takers. Orders made with the following tokens will be shown on OpenSea: | ||
- MANA, Decentraland's currency: https://etherscan.io/token/0x0f5d2fb29fb7d3cfee444a200298f468908cc942 | ||
- DAI, Maker's stablecoin, pegged to $1 USD: https://etherscan.io/token/0x89d24a6b4ccb1b6faa2625fe562bdd9a23260359 | ||
### Private Auctions | ||
Now you can make auctions and listings that can only be fulfilled by an address or email of your choosing. This allows you to negotiate a price in some channel and sell for your chosen price on OpenSea, **without having to trust that the counterparty will abide by your terms!** | ||
You can make offers and listings that can only be fulfilled by an address or email of your choosing. This allows you to negotiate a price in some channel and sell for your chosen price on OpenSea, **without having to trust that the counterparty will abide by your terms!** | ||
@@ -499,76 +408,36 @@ Here's an example of listing a Decentraland parcel for 10 ETH with a specific buyer address allowed to take it. No more needing to worry about whether they'll give you enough back! | ||
Our recommendation is that you "forward" OpenSea events to your own store or state management system. Here's an example of doing that with a Redux action: | ||
Our recommendation is that you "forward" OpenSea events to your own store or state management system. Here are examples of listening to the events: | ||
```typescript | ||
import { openSeaSDK, EventType } from 'opensea-js' | ||
import * as ActionTypes from './index' | ||
// ... | ||
handleSDKEvents() { | ||
return async function(dispatch, getState) { | ||
openSeaSDK.addListener(EventType.TransactionCreated, ({ transactionHash, event }) => { | ||
console.info({ transactionHash, event }) | ||
dispatch({ type: ActionTypes.SET_PENDING_TRANSACTION_HASH, hash: transactionHash }) | ||
console.info('Transaction created: ', { transactionHash, event }) | ||
}) | ||
openSeaSDK.addListener(EventType.TransactionConfirmed, ({ transactionHash, event }) => { | ||
console.info({ transactionHash, event }) | ||
// Only reset your exchange UI if we're finishing an order fulfillment or cancellation | ||
if (event == EventType.MatchOrders || event == EventType.CancelOrder) { | ||
dispatch({ type: ActionTypes.RESET_EXCHANGE }) | ||
} | ||
console.info('Transaction confirmed: ',{ transactionHash, event }) | ||
}) | ||
openSeaSDK.addListener(EventType.TransactionDenied, ({ transactionHash, event }) => { | ||
console.info({ transactionHash, event }) | ||
dispatch({ type: ActionTypes.RESET_EXCHANGE }) | ||
console.info('Transaction denied: ',{ transactionHash, event }) | ||
}) | ||
openSeaSDK.addListener(EventType.TransactionFailed, ({ transactionHash, event }) => { | ||
console.info({ transactionHash, event }) | ||
dispatch({ type: ActionTypes.RESET_EXCHANGE }) | ||
console.info('Transaction failed: ',{ transactionHash, event }) | ||
}) | ||
openSeaSDK.addListener(EventType.InitializeAccount, ({ accountAddress }) => { | ||
console.info({ accountAddress }) | ||
dispatch({ type: ActionTypes.INITIALIZE_PROXY }) | ||
}) | ||
openSeaSDK.addListener(EventType.WrapEth, ({ accountAddress, amount }) => { | ||
console.info({ accountAddress, amount }) | ||
dispatch({ type: ActionTypes.WRAP_ETH }) | ||
console.info('Wrap ETH: ',{ accountAddress, amount }) | ||
}) | ||
openSeaSDK.addListener(EventType.UnwrapWeth, ({ accountAddress, amount }) => { | ||
console.info({ accountAddress, amount }) | ||
dispatch({ type: ActionTypes.UNWRAP_WETH }) | ||
console.info('Unwrap ETH: ',{ accountAddress, amount }) | ||
}) | ||
openSeaSDK.addListener(EventType.ApproveCurrency, ({ accountAddress, tokenAddress }) => { | ||
console.info({ accountAddress, tokenAddress }) | ||
dispatch({ type: ActionTypes.APPROVE_WETH }) | ||
}) | ||
openSeaSDK.addListener(EventType.ApproveAllAssets, ({ accountAddress, tokenAddress }) => { | ||
console.info({ accountAddress, tokenAddress }) | ||
dispatch({ type: ActionTypes.APPROVE_ALL_ASSETS }) | ||
}) | ||
openSeaSDK.addListener(EventType.ApproveAsset, ({ accountAddress, tokenAddress, tokenId }) => { | ||
console.info({ accountAddress, tokenAddress, tokenId }) | ||
dispatch({ type: ActionTypes.APPROVE_ASSET }) | ||
}) | ||
openSeaSDK.addListener(EventType.CreateOrder, ({ order, accountAddress }) => { | ||
console.info({ order, accountAddress }) | ||
dispatch({ type: ActionTypes.CREATE_ORDER }) | ||
}) | ||
openSeaSDK.addListener(EventType.OrderDenied, ({ order, accountAddress }) => { | ||
console.info({ order, accountAddress }) | ||
dispatch({ type: ActionTypes.RESET_EXCHANGE }) | ||
}) | ||
openSeaSDK.addListener(EventType.MatchOrders, ({ buy, sell, accountAddress }) => { | ||
console.info({ buy, sell, accountAddress }) | ||
dispatch({ type: ActionTypes.FULFILL_ORDER }) | ||
console.info('Match orders: ', { buy, sell, accountAddress }) | ||
}) | ||
openSeaSDK.addListener(EventType.CancelOrder, ({ order, accountAddress }) => { | ||
console.info({ order, accountAddress }) | ||
dispatch({ type: ActionTypes.CANCEL_ORDER }) | ||
console.info('Cancel order: ', { order, accountAddress }) | ||
}) | ||
} | ||
} | ||
``` | ||
To remove all listeners and start over, just call `openseaSDK.removeAllListeners()`. | ||
To remove all listeners call `openseaSDK.removeAllListeners()`. | ||
@@ -575,0 +444,0 @@ ## Learning More |
@@ -42,2 +42,3 @@ import { ethers } from "ethers"; | ||
getCollectionOffersPath, | ||
getListNFTsByAccountPath, | ||
} from "../orders/utils"; | ||
@@ -421,2 +422,36 @@ import { | ||
/** | ||
* Fetch NFTs owned by an account. | ||
* @param address The address of the account | ||
* @param limit The number of NFTs to retrieve. Must be greater than 0 and less than 51. | ||
* @param next Cursor to retrieve the next page of NFTs | ||
* @param retries Number of times to retry if the service is unavailable for any reason. | ||
* @param chain The chain to query. Defaults to the chain set in the constructor. | ||
* @returns The {@link ListNFTsResponse} returned by the API. | ||
*/ | ||
public async getNFTsByAccount( | ||
address: string, | ||
limit: number | undefined = undefined, | ||
next: string | undefined = undefined, | ||
retries = 1, | ||
chain = this.chain, | ||
): Promise<ListNFTsResponse> { | ||
let response; | ||
try { | ||
response = await this.get<ListNFTsResponse>( | ||
getListNFTsByAccountPath(chain, address), | ||
{ | ||
limit, | ||
next, | ||
}, | ||
); | ||
} catch (error) { | ||
_throwOrContinue(error, retries); | ||
await delay(1000); | ||
return this.getNFTsByAccount(address, limit, next, retries - 1, chain); | ||
} | ||
return response; | ||
} | ||
/** | ||
* Fetch metadata, traits, ownership information, and rarity for a single NFT. | ||
@@ -423,0 +458,0 @@ * @param chain The NFT's chain. |
@@ -11,2 +11,4 @@ import { ethers } from "ethers"; | ||
export const DEFAULT_ZONE = ethers.constants.AddressZero; | ||
export const ENGLISH_AUCTION_ZONE = | ||
"0x110b2b128a9ed1be5ef3232d8e4e41640df5c2cd"; | ||
@@ -13,0 +15,0 @@ // Ignore eslint no-unused-modules for below to keep backward compatibility |
@@ -50,2 +50,6 @@ import { CROSS_CHAIN_SEAPORT_V1_5_ADDRESS } from "@opensea/seaport-js/lib/constants"; | ||
export const getListNFTsByAccountPath = (chain: Chain, address: string) => { | ||
return `/v2/chain/${chain}/account/${address}/nfts`; | ||
}; | ||
export const getNFTPath = ( | ||
@@ -52,0 +56,0 @@ chain: Chain, |
@@ -22,4 +22,8 @@ import EventEmitter = require("events"); | ||
import { Offer, NFT } from "./api/types"; | ||
import { INVERSE_BASIS_POINT, DEFAULT_ZONE } from "./constants"; | ||
import { | ||
INVERSE_BASIS_POINT, | ||
DEFAULT_ZONE, | ||
ENGLISH_AUCTION_ZONE, | ||
} from "./constants"; | ||
import { | ||
constructPrivateListingCounterOrder, | ||
@@ -433,2 +437,3 @@ getPrivateListingConsiderations, | ||
* @param options.buyerAddress Optional address that's allowed to purchase this item. If specified, no other address will be able to take the order, unless its value is the null address. | ||
* @param options.englishAuction If true, the order will be listed as an English auction. | ||
* @returns The {@link OrderV2} that was created. | ||
@@ -453,2 +458,3 @@ * | ||
buyerAddress, | ||
englishAuction, | ||
}: { | ||
@@ -466,2 +472,3 @@ asset: Asset; | ||
buyerAddress?: string; | ||
englishAuction?: boolean; | ||
}): Promise<OrderV2> { | ||
@@ -484,2 +491,8 @@ await this._requireAccountIsAvailable(accountAddress); | ||
if (englishAuction && paymentTokenAddress == ethers.constants.AddressZero) { | ||
throw new Error( | ||
`English auctions must use wrapped ETH or an ERC-20 token.`, | ||
); | ||
} | ||
const { basePrice, endPrice } = await this._getPriceParameters( | ||
@@ -522,7 +535,7 @@ OrderSide.Sell, | ||
getMaxOrderExpirationTimestamp().toString(), | ||
zone: DEFAULT_ZONE, | ||
zone: englishAuction ? ENGLISH_AUCTION_ZONE : DEFAULT_ZONE, | ||
domain, | ||
salt: BigNumber.from(salt ?? 0).toString(), | ||
restrictedByZone: false, | ||
allowPartialFills: true, | ||
restrictedByZone: englishAuction ? true : false, | ||
allowPartialFills: englishAuction ? false : true, | ||
}, | ||
@@ -714,6 +727,5 @@ accountAddress, | ||
// must be included with the order to successfully fulfill. | ||
const fulfillmentOrder = | ||
result.fulfillment_data.transaction.input_data.orders[0]; | ||
if ("extraData" in fulfillmentOrder) { | ||
extraData = (fulfillmentOrder as AdvancedOrder).extraData; | ||
const inputData = result.fulfillment_data.transaction.input_data; | ||
if ("orders" in inputData && "extraData" in inputData.orders[0]) { | ||
extraData = (inputData.orders[0] as AdvancedOrder).extraData; | ||
} | ||
@@ -998,4 +1010,2 @@ | ||
* @param endAmount The end value for the order, in the token's main units (e.g. ETH instead of wei). If unspecified, the order's `extra` attribute will be 0 | ||
* @param waitingForBestCounterOrder | ||
* @param englishAuctionReservePrice | ||
*/ | ||
@@ -1008,4 +1018,2 @@ private async _getPriceParameters( | ||
endAmount?: BigNumberish, | ||
waitingForBestCounterOrder = false, | ||
englishAuctionReservePrice?: BigNumberish, | ||
) { | ||
@@ -1037,5 +1045,2 @@ const isEther = tokenAddress === ethers.constants.AddressZero; | ||
const extra = priceDiffWei; | ||
const reservePrice = englishAuctionReservePrice | ||
? ethers.utils.parseUnits(startAmount.toString(), decimals) | ||
: undefined; | ||
@@ -1064,7 +1069,2 @@ // Validation | ||
} | ||
if (isEther && waitingForBestCounterOrder) { | ||
throw new Error( | ||
`English auctions must use wrapped ETH or an ERC-20 token.`, | ||
); | ||
} | ||
if (isEther && orderSide === OrderSide.Buy) { | ||
@@ -1083,14 +1083,3 @@ throw new Error(`Offers must use wrapped ETH or an ERC-20 token.`); | ||
} | ||
const reservePriceIsDefinedAndNonZero = | ||
reservePrice && !reservePrice.isZero(); | ||
if (reservePriceIsDefinedAndNonZero && !waitingForBestCounterOrder) { | ||
throw new Error("Reserve prices may only be set on English auctions."); | ||
} | ||
if (reservePriceIsDefinedAndNonZero && reservePrice?.lt(startAmountWei)) { | ||
throw new Error( | ||
"Reserve price must be greater than or equal to the start amount.", | ||
); | ||
} | ||
return { basePrice, extra, paymentToken, reservePrice, endPrice }; | ||
return { basePrice, extra, paymentToken, endPrice }; | ||
} | ||
@@ -1097,0 +1086,0 @@ |
@@ -28,3 +28,2 @@ /* eslint-disable import/no-unused-modules */ | ||
TransactionFailed = "TransactionFailed", | ||
/** | ||
@@ -38,4 +37,2 @@ * Emitted when the {@link OpenSeaSDK.wrapEth} method is called. | ||
UnwrapWeth = "UnwrapWeth", | ||
// Basic actions: matching orders, creating orders, and cancelling orders | ||
/** | ||
@@ -173,10 +170,2 @@ * Emitted when fulfilling a public or private order. | ||
/** | ||
* Type of sale. | ||
*/ | ||
export enum SaleKind { | ||
FixedPrice = 0, | ||
DutchAuction = 1, | ||
} | ||
/** | ||
* Types of asset contracts | ||
@@ -684,9 +673,2 @@ * Given by the asset_contract_type in the OpenSea API | ||
export enum HowToCall { | ||
Call = 0, | ||
DelegateCall = 1, | ||
StaticCall = 2, | ||
Create = 3, | ||
} | ||
export interface UnsignedOrder { | ||
@@ -716,11 +698,4 @@ hash?: string; | ||
side: OrderSide; | ||
saleKind: SaleKind; | ||
howToCall: HowToCall; | ||
quantity: BigNumber; | ||
// OpenSea-specific | ||
makerReferrerFee: BigNumber; | ||
waitingForBestCounterOrder: boolean; | ||
englishAuctionReservePrice?: BigNumber; | ||
metadata: ExchangeMetadata; | ||
@@ -752,3 +727,2 @@ } | ||
assetBundle?: OpenSeaAssetBundle; | ||
nonce?: number; | ||
} | ||
@@ -773,5 +747,3 @@ | ||
side: number; | ||
saleKind: number; | ||
target: string; | ||
howToCall: number; | ||
calldata: string; | ||
@@ -788,5 +760,3 @@ replacementPattern: string; | ||
makerReferrerFee: string; | ||
quantity: string; | ||
englishAuctionReservePrice: string | undefined; | ||
@@ -796,4 +766,2 @@ // createdTime is undefined when order hasn't been posted yet | ||
metadata: ExchangeMetadata; | ||
nonce?: number; | ||
} | ||
@@ -800,0 +768,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
2791837
67690
511