Skip to content

Commit b143166

Browse files
authored
- add List Collections API (#1460)
- add Cancel Order API
1 parent 8e19262 commit b143166

7 files changed

Lines changed: 164 additions & 2 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "opensea-js",
3-
"version": "7.1.7",
3+
"version": "7.1.8",
44
"description": "TypeScript SDK for the OpenSea marketplace helps developers build new experiences using NFTs and our marketplace data",
55
"license": "MIT",
66
"author": "OpenSea Developers",

src/api/api.ts

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { ethers } from "ethers";
22
import {
33
getCollectionPath,
4+
getCollectionsPath,
45
getOrdersAPIPath,
56
getPostCollectionOfferPath,
67
getBuildOfferPath,
@@ -18,10 +19,12 @@ import {
1819
getAccountPath,
1920
getCollectionStatsPath,
2021
getBestListingsAPIPath,
22+
getCancelOrderPath,
2123
} from "./apiPaths";
2224
import {
2325
BuildOfferResponse,
2426
GetCollectionResponse,
27+
GetCollectionsResponse,
2528
ListNFTsResponse,
2629
GetNFTResponse,
2730
ListCollectionOffersResponse,
@@ -31,6 +34,9 @@ import {
3134
GetOffersResponse,
3235
GetListingsResponse,
3336
CollectionOffer,
37+
CollectionOrderByOption,
38+
CancelOrderResponse,
39+
GetCollectionsArgs,
3440
} from "./types";
3541
import { API_BASE_MAINNET, API_BASE_TESTNET } from "../constants";
3642
import {
@@ -532,6 +538,40 @@ export class OpenSeaAPI {
532538
return collectionFromJSON(response);
533539
}
534540

541+
/**
542+
* Fetch a list of OpenSea collections.
543+
* @param orderBy The order to return the collections in. Default: CREATED_DATE
544+
* @param chain The chain to filter the collections on. Default: all chains
545+
* @param creatorUsername The creator's OpenSea username to filter the collections on.
546+
* @param includeHidden If hidden collections should be returned. Default: false
547+
* @param limit The limit of collections to return.
548+
* @param next The cursor for the next page of results. This is returned from a previous request.
549+
* @returns List of {@link OpenSeaCollection} returned by the API.
550+
*/
551+
public async getCollections(
552+
orderBy: CollectionOrderByOption = CollectionOrderByOption.CREATED_DATE,
553+
chain?: Chain,
554+
creatorUsername?: string,
555+
includeHidden: boolean = false,
556+
limit?: number,
557+
next?: string,
558+
): Promise<GetCollectionsResponse> {
559+
const path = getCollectionsPath();
560+
const args: GetCollectionsArgs = {
561+
order_by: orderBy,
562+
chain,
563+
creator_username: creatorUsername,
564+
include_hidden: includeHidden,
565+
limit,
566+
next,
567+
};
568+
const response = await this.get<GetCollectionsResponse>(path, args);
569+
response.collections = response.collections.map((collection) =>
570+
collectionFromJSON(collection),
571+
);
572+
return response;
573+
}
574+
535575
/**
536576
* Fetch stats for an OpenSea collection.
537577
* @param slug The slug (identifier) of the collection.
@@ -592,6 +632,27 @@ export class OpenSeaAPI {
592632
return response;
593633
}
594634

635+
/**
636+
* Offchain cancel an order, offer or listing, by its order hash when protected by the SignedZone.
637+
* Protocol and Chain are required to prevent hash collisions.
638+
* Please note cancellation is only assured if a fulfillment signature was not vended prior to cancellation.
639+
* @param protocolAddress The Seaport address for the order.
640+
* @param orderHash The order hash, or external identifier, of the order.
641+
* @param chain The chain where the order is located.
642+
* @returns The response from the API.
643+
*/
644+
public async offchainCancelOrder(
645+
protocolAddress: string,
646+
orderHash: string,
647+
chain: Chain = this.chain,
648+
): Promise<CancelOrderResponse> {
649+
const response = await this.post<CancelOrderResponse>(
650+
getCancelOrderPath(chain, protocolAddress, orderHash),
651+
{},
652+
);
653+
return response;
654+
}
655+
595656
/**
596657
* Generic fetch method for any API endpoint
597658
* @param apiPath Path to URL endpoint under API

src/api/apiPaths.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ export const getCollectionPath = (slug: string) => {
4040
return `/api/v2/collections/${slug}`;
4141
};
4242

43+
export const getCollectionsPath = () => {
44+
return "/api/v2/collections";
45+
};
46+
4347
export const getCollectionStatsPath = (slug: string) => {
4448
return `/api/v2/collections/${slug}/stats`;
4549
};
@@ -91,3 +95,11 @@ export const getRefreshMetadataPath = (
9195
) => {
9296
return `/v2/chain/${chain}/contract/${address}/nfts/${identifier}/refresh`;
9397
};
98+
99+
export const getCancelOrderPath = (
100+
chain: Chain,
101+
protocolAddress: string,
102+
orderHash: string,
103+
) => {
104+
return `/v2/orders/chain/${chain}/protocol/${protocolAddress}/${orderHash}/cancel`;
105+
};

src/api/types.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,19 @@ type ContractCriteria = {
5454
address: string;
5555
};
5656

57+
/**
58+
* Query args for Get Collections
59+
* @category API Query Args
60+
*/
61+
export interface GetCollectionsArgs {
62+
order_by?: string;
63+
limit?: number;
64+
next?: string;
65+
chain?: string;
66+
creator_username?: string;
67+
include_hidden?: boolean;
68+
}
69+
5770
/**
5871
* Response from OpenSea API for fetching a single collection.
5972
* @category API Response Types
@@ -63,6 +76,24 @@ export type GetCollectionResponse = {
6376
collection: OpenSeaCollection;
6477
};
6578

79+
/**
80+
* Response from OpenSea API for fetching a list of collections.
81+
* @category API Response Types
82+
*/
83+
export type GetCollectionsResponse = QueryCursorsV2 & {
84+
/** List of collections. See {@link OpenSeaCollection} */
85+
collections: OpenSeaCollection[];
86+
};
87+
88+
export enum CollectionOrderByOption {
89+
CREATED_DATE = "created_date",
90+
ONE_DAY_CHANGE = "one_day_change",
91+
SEVEN_DAY_VOLUME = "seven_day_volume",
92+
SEVEN_DAY_CHANGE = "seven_day_change",
93+
NUM_OWNERS = "num_owners",
94+
MARKET_CAP = "market_cap",
95+
}
96+
6697
/**
6798
* Base Order type shared between Listings and Offers.
6899
* @category API Models
@@ -190,6 +221,14 @@ export type GetBestOfferResponse = Offer | CollectionOffer;
190221
*/
191222
export type GetBestListingResponse = Listing;
192223

224+
/**
225+
* Response from OpenSea API for offchain canceling an order.
226+
* @category API Response Types
227+
*/
228+
export type CancelOrderResponse = {
229+
last_signature_issued_valid_until: string | null;
230+
};
231+
193232
/**
194233
* NFT type returned by OpenSea API.
195234
* @category API Models

src/sdk.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -877,7 +877,7 @@ export class OpenSeaSDK {
877877
}
878878

879879
/**
880-
* Cancel an order on-chain, preventing it from ever being fulfilled.
880+
* Cancel an order onchain, preventing it from ever being fulfilled.
881881
* @param options
882882
* @param options.order The order to cancel
883883
* @param options.accountAddress The account address that will be cancelling the order.
@@ -916,6 +916,23 @@ export class OpenSeaSDK {
916916
);
917917
}
918918

919+
/**
920+
* Offchain cancel an order, offer or listing, by its order hash when protected by the SignedZone.
921+
* Protocol and Chain are required to prevent hash collisions.
922+
* Please note cancellation is only assured if a fulfillment signature was not vended prior to cancellation.
923+
* @param protocolAddress The Seaport address for the order.
924+
* @param orderJash The order hash, or external identifier, of the order.
925+
* @param chain The chain where the order is located.
926+
* @returns The response from the API.
927+
*/
928+
public async offchainCancelOrder(
929+
protocolAddress: string,
930+
orderHash: string,
931+
chain: Chain = this.chain,
932+
) {
933+
return this.api.offchainCancelOrder(protocolAddress, orderHash, chain);
934+
}
935+
919936
/**
920937
* Returns whether an order is fulfillable.
921938
* An order may not be fulfillable if a target item's transfer function

test/integration/getCollection.spec.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { assert } from "chai";
22
import { suite, test } from "mocha";
33
import { sdk } from "./setup";
4+
import { CollectionOrderByOption } from "../../src/api/types";
45
import { SafelistStatus } from "../../src/types";
56

67
suite("SDK: getCollection", () => {
@@ -18,6 +19,28 @@ suite("SDK: getCollection", () => {
1819
);
1920
});
2021

22+
test("Get Collections", async () => {
23+
const response = await sdk.api.getCollections();
24+
const { collections, next } = response;
25+
assert(collections[0], "Collection should not be null");
26+
assert(collections[0].name, "Collection name should exist");
27+
assert(next, "Next cursor should be included");
28+
29+
const response2 = await sdk.api.getCollections(
30+
CollectionOrderByOption.MARKET_CAP,
31+
);
32+
const { collections: collectionsByMarketCap, next: nextByMarketCap } =
33+
response2;
34+
assert(collectionsByMarketCap[0], "Collection should not be null");
35+
assert(collectionsByMarketCap[0].name, "Collection name should exist");
36+
assert(nextByMarketCap, "Next cursor should be included");
37+
38+
assert(
39+
collectionsByMarketCap[0].name != collections[0].name,
40+
"Collection order should differ",
41+
);
42+
});
43+
2144
test("Get Collection Stats", async () => {
2245
const slug = "cool-cats-nft";
2346
const stats = await sdk.api.getCollectionStats(slug);

test/integration/postOrder.spec.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,16 @@ suite("SDK: order posting", () => {
115115
};
116116
const offerResponse = await sdk.createCollectionOffer(postOrderRequest);
117117
expect(offerResponse).to.exist.and.to.have.property("protocol_data");
118+
119+
// Cancel the order
120+
const { protocol_address, order_hash } = offerResponse!;
121+
const cancelResponse = await sdk.offchainCancelOrder(
122+
protocol_address,
123+
order_hash,
124+
);
125+
expect(cancelResponse).to.exist.and.to.have.property(
126+
"last_signature_issued_valid_until",
127+
);
118128
});
119129

120130
test("Post Collection Offer - Polygon", async () => {

0 commit comments

Comments
 (0)