Skip to content

Commit 23d8bd1

Browse files
committed
add tests
1 parent 5f6403f commit 23d8bd1

File tree

2 files changed

+373
-0
lines changed

2 files changed

+373
-0
lines changed

test/api/getOrderByHash.spec.ts

Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
1+
import { expect } from "chai";
2+
import { suite, test } from "mocha";
3+
import * as sinon from "sinon";
4+
import { OrdersAPI } from "../../src/api/orders";
5+
import {
6+
GetOrderByHashResponse,
7+
Offer,
8+
Listing,
9+
OrderStatus,
10+
} from "../../src/api/types";
11+
import { OrderType, ProtocolData } from "../../src/orders/types";
12+
import { Chain } from "../../src/types";
13+
import { createMockFetcher } from "../fixtures/fetcher";
14+
15+
suite("API: OrdersAPI.getOrderByHash", () => {
16+
let mockGet: sinon.SinonStub;
17+
let ordersAPI: OrdersAPI;
18+
19+
beforeEach(() => {
20+
const { fetcher, mockGet: getMock } = createMockFetcher();
21+
mockGet = getMock;
22+
ordersAPI = new OrdersAPI(fetcher, Chain.Mainnet);
23+
});
24+
25+
afterEach(() => {
26+
sinon.restore();
27+
});
28+
29+
test("returns an Offer type response", async () => {
30+
const mockOffer: Offer = {
31+
order_hash:
32+
"0x143be64aaf5d170c61e56ceb37dff0f8494e2630a7eae3eb24c8edbef09af9d5",
33+
chain: "ethereum",
34+
protocol_data: {
35+
parameters: {
36+
offerer: "0xaf68f720d7e51b88a76ec35aab2b1694f8f0892a",
37+
offer: [
38+
{
39+
itemType: 1,
40+
token: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
41+
identifierOrCriteria: "0",
42+
startAmount: "5480000000000000000",
43+
endAmount: "5480000000000000000",
44+
},
45+
],
46+
consideration: [],
47+
startTime: "1765058920",
48+
endTime: "1765318120",
49+
orderType: 2,
50+
zone: "0x000056f7000000ece9003ca63978907a00ffd100",
51+
zoneHash:
52+
"0x0000000000000000000000000000000000000000000000000000000000000000",
53+
salt: "0x3d958fe20000000000000000000000000000000000000000aed879ed15914a7b",
54+
conduitKey:
55+
"0x0000007b02230091a7ed01230072f7006a004d60a8d4e71d599b8104250f0000",
56+
totalOriginalConsiderationItems: 2,
57+
counter: 0,
58+
},
59+
signature: null,
60+
} as unknown as ProtocolData,
61+
protocol_address: "0x0000000000000068f116a894984e2db1123eb395",
62+
price: {
63+
currency: "WETH",
64+
decimals: 18,
65+
value: "5480000000000000000",
66+
},
67+
criteria: {
68+
collection: { slug: "boredapeyachtclub" },
69+
contract: { address: "0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d" },
70+
},
71+
status: OrderStatus.ACTIVE,
72+
};
73+
74+
mockGet.resolves({ order: mockOffer });
75+
76+
const result = await ordersAPI.getOrderByHash(
77+
"0x143be64aaf5d170c61e56ceb37dff0f8494e2630a7eae3eb24c8edbef09af9d5",
78+
"0x0000000000000068f116a894984e2db1123eb395",
79+
);
80+
81+
expect(mockGet.calledOnce).to.be.true;
82+
expect(mockGet.firstCall.args[0]).to.equal(
83+
"/api/v2/orders/chain/ethereum/protocol/0x0000000000000068f116a894984e2db1123eb395/0x143be64aaf5d170c61e56ceb37dff0f8494e2630a7eae3eb24c8edbef09af9d5",
84+
);
85+
86+
// Verify it returns the raw API response (Offer type)
87+
expect(result.order_hash).to.equal(
88+
"0x143be64aaf5d170c61e56ceb37dff0f8494e2630a7eae3eb24c8edbef09af9d5",
89+
);
90+
expect(result.protocol_address).to.equal(
91+
"0x0000000000000068f116a894984e2db1123eb395",
92+
);
93+
expect(result.protocol_data.parameters.offerer).to.equal(
94+
"0xaf68f720d7e51b88a76ec35aab2b1694f8f0892a",
95+
);
96+
expect((result as Offer).criteria?.collection.slug).to.equal(
97+
"boredapeyachtclub",
98+
);
99+
});
100+
101+
test("returns a Listing type response", async () => {
102+
const mockListing: Listing = {
103+
order_hash:
104+
"0xabc123def456789012345678901234567890123456789012345678901234abcd",
105+
chain: "ethereum",
106+
protocol_data: {
107+
parameters: {
108+
offerer: "0x1234567890123456789012345678901234567890",
109+
offer: [
110+
{
111+
itemType: 2,
112+
token: "0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d",
113+
identifierOrCriteria: "1234",
114+
startAmount: "1",
115+
endAmount: "1",
116+
},
117+
],
118+
consideration: [],
119+
startTime: "1765058920",
120+
endTime: "1765318120",
121+
orderType: 0,
122+
zone: "0x000056f7000000ece9003ca63978907a00ffd100",
123+
zoneHash:
124+
"0x0000000000000000000000000000000000000000000000000000000000000000",
125+
salt: "0x1234",
126+
conduitKey:
127+
"0x0000007b02230091a7ed01230072f7006a004d60a8d4e71d599b8104250f0000",
128+
totalOriginalConsiderationItems: 1,
129+
counter: 0,
130+
},
131+
signature: "0xsignature",
132+
} as unknown as ProtocolData,
133+
protocol_address: "0x0000000000000068f116a894984e2db1123eb395",
134+
type: OrderType.BASIC,
135+
price: {
136+
current: {
137+
currency: "ETH",
138+
decimals: 18,
139+
value: "1000000000000000000",
140+
},
141+
},
142+
remaining_quantity: 1,
143+
status: OrderStatus.ACTIVE,
144+
};
145+
146+
mockGet.resolves({ order: mockListing });
147+
148+
const result = await ordersAPI.getOrderByHash(
149+
"0xabc123def456789012345678901234567890123456789012345678901234abcd",
150+
"0x0000000000000068f116a894984e2db1123eb395",
151+
);
152+
153+
// Verify it returns the raw API response (Listing type)
154+
expect(result.order_hash).to.equal(
155+
"0xabc123def456789012345678901234567890123456789012345678901234abcd",
156+
);
157+
expect(result.protocol_address).to.equal(
158+
"0x0000000000000068f116a894984e2db1123eb395",
159+
);
160+
expect((result as Listing).remaining_quantity).to.equal(1);
161+
expect((result as Listing).type).to.equal(OrderType.BASIC);
162+
});
163+
164+
test("response can be used for order cancellation", async () => {
165+
const mockOffer: Offer = {
166+
order_hash: "0x123",
167+
chain: "ethereum",
168+
protocol_data: {
169+
parameters: {
170+
offerer: "0xofferer",
171+
offer: [],
172+
consideration: [],
173+
startTime: "0",
174+
endTime: "0",
175+
orderType: 0,
176+
zone: "0x0",
177+
zoneHash: "0x0",
178+
salt: "0",
179+
conduitKey: "0x0",
180+
totalOriginalConsiderationItems: 0,
181+
counter: 0,
182+
},
183+
signature: null,
184+
} as unknown as ProtocolData,
185+
protocol_address: "0xprotocol",
186+
price: {
187+
currency: "ETH",
188+
decimals: 18,
189+
value: "1000000000000000000",
190+
},
191+
status: OrderStatus.ACTIVE,
192+
};
193+
194+
mockGet.resolves({ order: mockOffer });
195+
196+
const result: GetOrderByHashResponse = await ordersAPI.getOrderByHash(
197+
"0x123",
198+
"0xprotocol",
199+
);
200+
201+
// Verify the response has the fields needed for cancellation
202+
expect(result.protocol_address).to.equal("0xprotocol");
203+
expect(result.protocol_data).to.exist;
204+
expect(result.protocol_data.parameters).to.exist;
205+
expect(result.protocol_data.parameters.offerer).to.equal("0xofferer");
206+
});
207+
208+
test("passes chain parameter correctly", async () => {
209+
// Create a new API instance for this test with Polygon chain
210+
const { fetcher, mockGet: polygonMockGet } = createMockFetcher();
211+
const polygonOrdersAPI = new OrdersAPI(fetcher, Chain.Polygon);
212+
213+
const mockOffer: Offer = {
214+
order_hash: "0x123",
215+
chain: "polygon",
216+
protocol_data: {
217+
parameters: {
218+
offerer: "0x1",
219+
offer: [],
220+
consideration: [],
221+
startTime: "0",
222+
endTime: "0",
223+
orderType: 0,
224+
zone: "0x0",
225+
zoneHash: "0x0",
226+
salt: "0",
227+
conduitKey: "0x0",
228+
totalOriginalConsiderationItems: 0,
229+
counter: 0,
230+
},
231+
signature: null,
232+
} as unknown as ProtocolData,
233+
protocol_address: "0xprotocol",
234+
price: {
235+
currency: "ETH",
236+
decimals: 18,
237+
value: "1000000000000000000",
238+
},
239+
status: OrderStatus.ACTIVE,
240+
};
241+
242+
polygonMockGet.resolves({ order: mockOffer });
243+
244+
await polygonOrdersAPI.getOrderByHash("0x123", "0xprotocol");
245+
246+
expect(polygonMockGet.firstCall.args[0]).to.include("/chain/polygon/");
247+
});
248+
});
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
import { assert } from "chai";
2+
import { JsonRpcProvider } from "ethers";
3+
import { suite, test } from "mocha";
4+
import { OpenSeaSDK } from "../../src/sdk";
5+
import { Chain } from "../../src/types";
6+
import { OPENSEA_API_KEY } from "../utils/env";
7+
8+
// Create SDK without wallet - only needs API key for read-only operations
9+
const provider = new JsonRpcProvider("https://cloudflare-eth.com");
10+
const sdk = new OpenSeaSDK(provider, {
11+
chain: Chain.Mainnet,
12+
apiKey: OPENSEA_API_KEY,
13+
});
14+
15+
suite("SDK: getOrderByHash", () => {
16+
test("Get Order By Hash - Offer", async () => {
17+
const slug = "boredapeyachtclub";
18+
19+
// First get an offer to get its hash and protocol address
20+
const offersResponse = await sdk.api.getAllOffers(slug);
21+
assert(offersResponse.offers.length > 0, "Should have at least one offer");
22+
23+
const offer = offersResponse.offers[0];
24+
const orderHash = offer.order_hash;
25+
const protocolAddress = offer.protocol_address;
26+
27+
// Now fetch the same order by hash
28+
const response = await sdk.api.getOrderByHash(orderHash, protocolAddress);
29+
30+
assert(response, "Response should not be null");
31+
assert.equal(
32+
response.order_hash,
33+
orderHash,
34+
"Order hash should match the requested hash",
35+
);
36+
assert.equal(
37+
response.protocol_address,
38+
protocolAddress,
39+
"Protocol address should match",
40+
);
41+
assert(response.protocol_data, "Protocol data should not be null");
42+
assert(
43+
response.protocol_data.parameters,
44+
"Protocol data parameters should not be null",
45+
);
46+
assert(
47+
response.protocol_data.parameters.offerer,
48+
"Offerer should not be null",
49+
);
50+
});
51+
52+
test("Get Order By Hash - Listing", async () => {
53+
const slug = "boredapeyachtclub";
54+
55+
// First get a listing to get its hash and protocol address
56+
const listingsResponse = await sdk.api.getAllListings(slug);
57+
assert(
58+
listingsResponse.listings.length > 0,
59+
"Should have at least one listing",
60+
);
61+
62+
const listing = listingsResponse.listings[0];
63+
const orderHash = listing.order_hash;
64+
const protocolAddress = listing.protocol_address;
65+
66+
// Now fetch the same order by hash
67+
const response = await sdk.api.getOrderByHash(orderHash, protocolAddress);
68+
69+
assert(response, "Response should not be null");
70+
assert.equal(
71+
response.order_hash,
72+
orderHash,
73+
"Order hash should match the requested hash",
74+
);
75+
assert.equal(
76+
response.protocol_address,
77+
protocolAddress,
78+
"Protocol address should match",
79+
);
80+
assert(response.protocol_data, "Protocol data should not be null");
81+
assert(
82+
response.protocol_data.parameters,
83+
"Protocol data parameters should not be null",
84+
);
85+
});
86+
87+
test("Get Order By Hash returns data usable for cancellation", async () => {
88+
const slug = "boredapeyachtclub";
89+
90+
// Get an offer
91+
const offersResponse = await sdk.api.getAllOffers(slug);
92+
assert(offersResponse.offers.length > 0, "Should have at least one offer");
93+
94+
const offer = offersResponse.offers[0];
95+
96+
// Fetch by hash
97+
const response = await sdk.api.getOrderByHash(
98+
offer.order_hash,
99+
offer.protocol_address,
100+
);
101+
102+
// Verify the response has fields needed for cancellation
103+
assert(
104+
response.protocol_address,
105+
"protocol_address is required for cancel",
106+
);
107+
assert(response.protocol_data, "protocol_data is required for cancel");
108+
assert(
109+
response.protocol_data.parameters,
110+
"protocol_data.parameters is required for cancel",
111+
);
112+
assert(
113+
response.protocol_data.parameters.offerer,
114+
"offerer is required for cancel",
115+
);
116+
assert(
117+
Array.isArray(response.protocol_data.parameters.offer),
118+
"offer array is required for cancel",
119+
);
120+
assert(
121+
Array.isArray(response.protocol_data.parameters.consideration),
122+
"consideration array is required for cancel",
123+
);
124+
});
125+
});

0 commit comments

Comments
 (0)