@imtbl/sdk 1.43.3 → 1.43.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/dist/Passport.d-011d5035.d.ts +224 -0
  2. package/dist/blockchain-data.d-1634b683.d.ts +3406 -0
  3. package/dist/blockchain_data-d989298c.js +1 -0
  4. package/dist/blockchain_data.d-d538f8d4.d.ts +4543 -0
  5. package/dist/blockchain_data.d.ts +3 -7950
  6. package/dist/blockchain_data.js +1 -6058
  7. package/dist/browser/checkout/sdk.js +4 -4
  8. package/dist/checkout-68675dd1.js +16 -0
  9. package/dist/checkout.d-ae9ca847.d.ts +3392 -0
  10. package/dist/checkout.d.ts +7 -16882
  11. package/dist/checkout.js +1 -37189
  12. package/dist/config-53a9a4ca.js +1 -0
  13. package/dist/config.d-65420620.d.ts +18 -0
  14. package/dist/config.d.ts +1 -30
  15. package/dist/config.js +1 -394
  16. package/dist/event-types.d-42520276.d.ts +332 -0
  17. package/dist/imxProvider.d-cac9e315.d.ts +12538 -0
  18. package/dist/index-14aad537.js +1 -0
  19. package/dist/index-3951cdf0.js +1 -0
  20. package/dist/index-3f40d7f6.js +1 -0
  21. package/dist/index-58a79c29.js +1 -0
  22. package/dist/index-96599707.js +1 -0
  23. package/dist/index-e7002486.js +1 -0
  24. package/dist/index.browser.js +4 -4
  25. package/dist/index.cjs +7 -7
  26. package/dist/index.d-c4a4c17d.d.ts +277 -0
  27. package/dist/index.d-f0845744.d.ts +30 -0
  28. package/dist/index.d-f1471830.d.ts +376 -0
  29. package/dist/index.d.ts +18 -32627
  30. package/dist/index.js +1 -64124
  31. package/dist/json-rpc-provider.d-5c038bd9.d.ts +249 -0
  32. package/dist/minting_backend-04aef147.js +1 -0
  33. package/dist/minting_backend.d-4754ffee.d.ts +104 -0
  34. package/dist/minting_backend.d.ts +5 -3535
  35. package/dist/minting_backend.js +1 -6756
  36. package/dist/orderbook-e71036df.js +1 -0
  37. package/dist/orderbook.d-77162c6c.d.ts +1257 -0
  38. package/dist/orderbook.d.ts +5 -1713
  39. package/dist/orderbook.js +1 -2479
  40. package/dist/passport-0f45e532.js +1 -0
  41. package/dist/passport.d-d3f44798.d.ts +67 -0
  42. package/dist/passport.d.ts +6 -13703
  43. package/dist/passport.js +1 -23137
  44. package/dist/transfer.d-87728423.d.ts +898 -0
  45. package/dist/webhook-a16541bb.js +1 -0
  46. package/dist/webhook.d-4c3cb340.d.ts +75 -0
  47. package/dist/webhook.d.ts +4 -1265
  48. package/dist/webhook.js +1 -488
  49. package/dist/x-a5b39578.js +1 -0
  50. package/dist/x.d-1b51f0c3.d.ts +4879 -0
  51. package/dist/x.d.ts +6 -18663
  52. package/dist/x.js +1 -19242
  53. package/package.json +1 -1
package/dist/orderbook.js CHANGED
@@ -1,2479 +1 @@
1
- import axios from 'axios';
2
- import FormData from 'form-data';
3
- import { providers, BigNumber, constants as constants$1 } from 'ethers';
4
- import { ethers, FetchRequest, JsonRpcProvider, JsonRpcSigner, keccak256, toUtf8Bytes, concat, TypedDataEncoder, zeroPadValue, toBeHex, AbiCoder } from 'ethers-v6';
5
- import { MerkleTree } from 'merkletreejs';
6
- import { memorise } from 'lru-memorise';
7
- import { getGlobalisedValue as getGlobalisedValue$1 } from 'global-const';
8
- import { Seaport as Seaport$1 } from '@opensea/seaport-js';
9
-
10
- const isNode = () => typeof window === 'undefined';
11
- const isBrowser = () => !isNode();
12
-
13
- var Detail;
14
- (function (Detail) {
15
- Detail["RUNTIME_ID"] = "rid";
16
- Detail["PASSPORT_CLIENT_ID"] = "passportClientId";
17
- Detail["ENVIRONMENT"] = "env";
18
- Detail["PUBLISHABLE_API_KEY"] = "pak";
19
- Detail["IDENTITY"] = "uid";
20
- Detail["DOMAIN"] = "domain";
21
- Detail["SDK_VERSION"] = "sdkVersion";
22
- })(Detail || (Detail = {}));
23
-
24
- const IMTBL_API = 'https://api.immutable.com';
25
- async function post(path, data) {
26
- const client = axios.create({
27
- baseURL: IMTBL_API,
28
- });
29
- const payload = JSON.stringify(data);
30
- const body = {
31
- payload: Buffer.from(payload).toString('base64'),
32
- };
33
- const response = await client.post(path, body);
34
- return response.data;
35
- }
36
-
37
- /**
38
- * Abstraction on localstorage
39
- */
40
- const localStoragePrefix = '__IMX-';
41
- const hasLocalstorage = () => isBrowser() && window.localStorage;
42
- const parseItem = (payload) => {
43
- // Try to parse, if can't be parsed assume string
44
- // and return string
45
- if (payload === null)
46
- return undefined;
47
- try {
48
- return JSON.parse(payload);
49
- }
50
- catch (error) {
51
- // Assumes it's a string.
52
- return payload;
53
- }
54
- };
55
- const serialiseItem = (payload) => {
56
- if (typeof payload === 'string') {
57
- return payload;
58
- }
59
- return JSON.stringify(payload);
60
- };
61
- /**
62
- * GenKey will take into account the namespace
63
- * as well as if being run in the Link, it will tap into the link
64
- * @param {string} key
65
- * @returns key
66
- */
67
- const genKey = (key) => `${localStoragePrefix}${key}`;
68
- function getItem(key) {
69
- if (hasLocalstorage()) {
70
- return parseItem(window.localStorage.getItem(genKey(key)));
71
- }
72
- return undefined;
73
- }
74
- const setItem = (key, payload) => {
75
- if (hasLocalstorage()) {
76
- window.localStorage.setItem(genKey(key), serialiseItem(payload));
77
- return true;
78
- }
79
- return false;
80
- };
81
-
82
- var Store;
83
- (function (Store) {
84
- Store["EVENTS"] = "events";
85
- Store["RUNTIME"] = "runtime";
86
- })(Store || (Store = {}));
87
- // In memory storage for events and other data
88
- let EVENT_STORE;
89
- let RUNTIME_DETAILS;
90
- // Initialise store and runtime
91
- const initialise$1 = () => {
92
- EVENT_STORE = getItem(Store.EVENTS) || [];
93
- RUNTIME_DETAILS = getItem(Store.RUNTIME) || {};
94
- };
95
- initialise$1();
96
- // Runtime Details
97
- const storeDetail = (key, value) => {
98
- RUNTIME_DETAILS = {
99
- ...RUNTIME_DETAILS,
100
- [key]: value,
101
- };
102
- setItem(Store.RUNTIME, RUNTIME_DETAILS);
103
- };
104
- const getDetail$1 = (key) => {
105
- // Handle the scenario where detail is a falsy value
106
- if (RUNTIME_DETAILS[key] === undefined) {
107
- return undefined;
108
- }
109
- return RUNTIME_DETAILS[key];
110
- };
111
- const getAllDetails = () => RUNTIME_DETAILS;
112
- // Events
113
- const getEvents = () => EVENT_STORE;
114
- const addEvent = (event) => {
115
- EVENT_STORE.push(event);
116
- setItem(Store.EVENTS, EVENT_STORE);
117
- };
118
- const removeSentEvents = (numberOfEvents) => {
119
- EVENT_STORE = EVENT_STORE.slice(numberOfEvents);
120
- setItem(Store.EVENTS, EVENT_STORE);
121
- };
122
- const flattenProperties = (properties) => {
123
- const propertyMap = [];
124
- Object.entries(properties).forEach(([key, value]) => {
125
- if (typeof key === 'string'
126
- || typeof value === 'string'
127
- || typeof value === 'number'
128
- || typeof value === 'boolean') {
129
- propertyMap.push([key, value.toString()]);
130
- }
131
- });
132
- return propertyMap;
133
- };
134
-
135
- // WARNING: DO NOT CHANGE THE STRING BELOW. IT GETS REPLACED AT BUILD TIME.
136
- const SDK_VERSION = '1.43.3';
137
- const getFrameParentDomain = () => {
138
- if (isNode()) {
139
- return '';
140
- }
141
- // If available for supported browsers (all except Firefox)
142
- if (window.location.ancestorOrigins
143
- && window.location.ancestorOrigins.length > 0) {
144
- return new URL(window.location.ancestorOrigins[0]).hostname;
145
- }
146
- // Fallback to using the referrer
147
- return document.referrer ? new URL(window.document.referrer).hostname : '';
148
- };
149
- const runtimeHost = () => {
150
- if (isNode()) {
151
- return '';
152
- }
153
- let domain;
154
- try {
155
- if (window.self !== window.top) {
156
- domain = getFrameParentDomain();
157
- }
158
- }
159
- catch (error) {
160
- // Do nothing
161
- }
162
- // Fallback to current domain if can't detect parent domain
163
- if (!domain) {
164
- domain = window.location.hostname;
165
- }
166
- return domain;
167
- };
168
- const getRuntimeDetails = () => {
169
- storeDetail(Detail.SDK_VERSION, SDK_VERSION);
170
- if (isNode()) {
171
- return { browser: 'nodejs', sdkVersion: SDK_VERSION };
172
- }
173
- const domain = runtimeHost();
174
- if (domain) {
175
- storeDetail(Detail.DOMAIN, domain);
176
- }
177
- return {
178
- sdkVersion: SDK_VERSION,
179
- browser: window.navigator.userAgent,
180
- domain,
181
- tz: Intl.DateTimeFormat().resolvedOptions().timeZone,
182
- screen: `${window.screen.width}x${window.screen.height}`,
183
- };
184
- };
185
- let initialised = false;
186
- const isInitialised = () => initialised;
187
- const initialise = async () => {
188
- initialised = true;
189
- try {
190
- const runtimeDetails = flattenProperties(getRuntimeDetails());
191
- const existingRuntimeId = getDetail$1(Detail.RUNTIME_ID);
192
- const body = {
193
- version: 1,
194
- data: {
195
- runtimeDetails,
196
- runtimeId: existingRuntimeId,
197
- },
198
- };
199
- const response = await post('/v1/sdk/initialise', body);
200
- // Get runtimeId and store it
201
- const { runtimeId } = response;
202
- storeDetail(Detail.RUNTIME_ID, runtimeId);
203
- }
204
- catch (error) {
205
- initialised = false;
206
- }
207
- };
208
-
209
- function errorBoundary(fn, fallbackResult) {
210
- return (...args) => {
211
- try {
212
- // Execute the original function
213
- const result = fn(...args);
214
- if (result instanceof Promise) {
215
- // Silent fail for now, in future
216
- // we can send errors to a logging service
217
- return result.catch(() => fallbackResult);
218
- }
219
- return result;
220
- }
221
- catch (error) {
222
- // As above, fail silently for now
223
- return fallbackResult;
224
- }
225
- };
226
- }
227
-
228
- function isTestEnvironmentFn() {
229
- if (isBrowser()) {
230
- return false;
231
- }
232
- if (typeof process === 'undefined') {
233
- return false;
234
- }
235
- // Consider using `ci-info` package for better results, though might fail as not browser safe.
236
- // Just use process.env.CI for now.
237
- return process.env.JEST_WORKER_ID !== undefined;
238
- }
239
- const isTestEnvironment = errorBoundary(isTestEnvironmentFn, false);
240
-
241
- const GLOBALISE_KEY = 'imtbl__metrics';
242
- const MEMORISE_TIMEFRAME = 5000;
243
- const MEMORISE_MAX = 1000;
244
- const getGlobalisedValue = (key, value) => getGlobalisedValue$1(GLOBALISE_KEY, key, value);
245
- const getGlobalisedCachedFunction = (key, fn) => {
246
- // Some applications (esp backend, or frontends using the split bundles) can sometimes
247
- // initialise the same request multiple times. This will prevent multiple of the
248
- // same event,value from being reported in a 1 second period.
249
- const memorisedFn = memorise(fn, {
250
- lruOptions: { ttl: MEMORISE_TIMEFRAME, max: MEMORISE_MAX },
251
- });
252
- return getGlobalisedValue$1(GLOBALISE_KEY, key, memorisedFn);
253
- };
254
-
255
- const POLLING_FREQUENCY = 5000;
256
- const trackFn = (moduleName, eventName, properties) => {
257
- const event = {
258
- event: `${moduleName}.${eventName}`,
259
- time: new Date().toISOString(),
260
- ...(properties && { properties: flattenProperties(properties) }),
261
- };
262
- addEvent(event);
263
- };
264
- /**
265
- * Track an event completion.
266
- * @param moduleName Name of the module being tracked (for namespacing purposes), e.g. `passport`
267
- * @param eventName Name of the event, use camelCase e.g. `clickItem`
268
- * @param properties Other properties to be sent with the event
269
- *
270
- * e.g.
271
- *
272
- * ```ts
273
- * track("passport", "performTransaction");
274
- * track("passport", "performTransaction", { transationType: "transfer" });
275
- * ```
276
- */
277
- errorBoundary(getGlobalisedCachedFunction('track', trackFn));
278
- // Sending events to the server
279
- const flushFn = async () => {
280
- // Don't flush if not initialised
281
- if (isInitialised() === false) {
282
- await initialise();
283
- return;
284
- }
285
- const events = getEvents();
286
- if (events.length === 0) {
287
- return;
288
- }
289
- // Track events length here, incase
290
- const numEvents = events.length;
291
- // Get details and send it with the track request
292
- const details = getAllDetails();
293
- const metricsPayload = {
294
- version: 1,
295
- data: {
296
- events,
297
- details,
298
- },
299
- };
300
- const response = await post('/v1/sdk/metrics', metricsPayload);
301
- if (response instanceof Error) {
302
- return;
303
- }
304
- // Clear events if successfully posted
305
- removeSentEvents(numEvents);
306
- };
307
- const flush = errorBoundary(flushFn);
308
- // Flush events every 5 seconds
309
- const flushPoll = async () => {
310
- await flush();
311
- setTimeout(flushPoll, POLLING_FREQUENCY);
312
- };
313
- let flushingStarted = false;
314
- const startFlushing = () => {
315
- if (flushingStarted) {
316
- return;
317
- }
318
- flushingStarted = true;
319
- flushPoll();
320
- };
321
- // This will get initialised when module is imported.
322
- if (!isTestEnvironment()) {
323
- errorBoundary(getGlobalisedValue('startFlushing', startFlushing))();
324
- }
325
-
326
- const setEnvironmentFn = (env) => {
327
- storeDetail(Detail.ENVIRONMENT, env);
328
- };
329
- errorBoundary(getGlobalisedValue('setEnvironment', setEnvironmentFn));
330
- const setPassportClientIdFn = (passportClientId) => {
331
- storeDetail(Detail.PASSPORT_CLIENT_ID, passportClientId);
332
- };
333
- errorBoundary(getGlobalisedValue('setPassportClientId', setPassportClientIdFn));
334
- const setPublishableApiKeyFn = (publishableApiKey) => {
335
- storeDetail(Detail.PUBLISHABLE_API_KEY, publishableApiKey);
336
- };
337
- errorBoundary(getGlobalisedValue('setPublishableApiKey', setPublishableApiKeyFn));
338
- errorBoundary(getGlobalisedValue('getDetail', getDetail$1));
339
-
340
- var Environment;
341
- (function (Environment) {
342
- Environment["PRODUCTION"] = "production";
343
- Environment["SANDBOX"] = "sandbox";
344
- })(Environment || (Environment = {}));
345
- var KeyHeaders;
346
- (function (KeyHeaders) {
347
- KeyHeaders["API_KEY"] = "x-immutable-api-key";
348
- KeyHeaders["PUBLISHABLE_KEY"] = "x-immutable-publishable-key";
349
- KeyHeaders["RATE_LIMITING_KEY"] = "x-api-key";
350
- })(KeyHeaders || (KeyHeaders = {}));
351
-
352
- class BaseHttpRequest {
353
- config;
354
- constructor(config) {
355
- this.config = config;
356
- }
357
- }
358
-
359
- class ApiError extends Error {
360
- url;
361
- status;
362
- statusText;
363
- body;
364
- request;
365
- constructor(request, response, message) {
366
- super(message);
367
- this.name = 'ApiError';
368
- this.url = response.url;
369
- this.status = response.status;
370
- this.statusText = response.statusText;
371
- this.body = response.body;
372
- this.request = request;
373
- }
374
- }
375
-
376
- /* istanbul ignore file */
377
- /* tslint:disable */
378
- /* eslint-disable */
379
- class CancelError extends Error {
380
- constructor(message) {
381
- super(message);
382
- this.name = 'CancelError';
383
- }
384
- get isCancelled() {
385
- return true;
386
- }
387
- }
388
- class CancelablePromise {
389
- [Symbol.toStringTag];
390
- _isResolved;
391
- _isRejected;
392
- _isCancelled;
393
- _cancelHandlers;
394
- _promise;
395
- _resolve;
396
- _reject;
397
- constructor(executor) {
398
- this._isResolved = false;
399
- this._isRejected = false;
400
- this._isCancelled = false;
401
- this._cancelHandlers = [];
402
- this._promise = new Promise((resolve, reject) => {
403
- this._resolve = resolve;
404
- this._reject = reject;
405
- const onResolve = (value) => {
406
- if (this._isResolved || this._isRejected || this._isCancelled) {
407
- return;
408
- }
409
- this._isResolved = true;
410
- this._resolve?.(value);
411
- };
412
- const onReject = (reason) => {
413
- if (this._isResolved || this._isRejected || this._isCancelled) {
414
- return;
415
- }
416
- this._isRejected = true;
417
- this._reject?.(reason);
418
- };
419
- const onCancel = (cancelHandler) => {
420
- if (this._isResolved || this._isRejected || this._isCancelled) {
421
- return;
422
- }
423
- this._cancelHandlers.push(cancelHandler);
424
- };
425
- Object.defineProperty(onCancel, 'isResolved', {
426
- get: () => this._isResolved,
427
- });
428
- Object.defineProperty(onCancel, 'isRejected', {
429
- get: () => this._isRejected,
430
- });
431
- Object.defineProperty(onCancel, 'isCancelled', {
432
- get: () => this._isCancelled,
433
- });
434
- return executor(onResolve, onReject, onCancel);
435
- });
436
- }
437
- then(onFulfilled, onRejected) {
438
- return this._promise.then(onFulfilled, onRejected);
439
- }
440
- catch(onRejected) {
441
- return this._promise.catch(onRejected);
442
- }
443
- finally(onFinally) {
444
- return this._promise.finally(onFinally);
445
- }
446
- cancel() {
447
- if (this._isResolved || this._isRejected || this._isCancelled) {
448
- return;
449
- }
450
- this._isCancelled = true;
451
- if (this._cancelHandlers.length) {
452
- try {
453
- for (const cancelHandler of this._cancelHandlers) {
454
- cancelHandler();
455
- }
456
- }
457
- catch (error) {
458
- console.warn('Cancellation threw an error', error);
459
- return;
460
- }
461
- }
462
- this._cancelHandlers.length = 0;
463
- this._reject?.(new CancelError('Request aborted'));
464
- }
465
- get isCancelled() {
466
- return this._isCancelled;
467
- }
468
- }
469
-
470
- /* istanbul ignore file */
471
- /* tslint:disable */
472
- /* eslint-disable */
473
- const isDefined = (value) => {
474
- return value !== undefined && value !== null;
475
- };
476
- const isString = (value) => {
477
- return typeof value === 'string';
478
- };
479
- const isStringWithValue = (value) => {
480
- return isString(value) && value !== '';
481
- };
482
- const isBlob = (value) => {
483
- return (typeof value === 'object' &&
484
- typeof value.type === 'string' &&
485
- typeof value.stream === 'function' &&
486
- typeof value.arrayBuffer === 'function' &&
487
- typeof value.constructor === 'function' &&
488
- typeof value.constructor.name === 'string' &&
489
- /^(Blob|File)$/.test(value.constructor.name) &&
490
- /^(Blob|File)$/.test(value[Symbol.toStringTag]));
491
- };
492
- const isFormData = (value) => {
493
- return value instanceof FormData;
494
- };
495
- const isSuccess = (status) => {
496
- return status >= 200 && status < 300;
497
- };
498
- const base64 = (str) => {
499
- try {
500
- return btoa(str);
501
- }
502
- catch (err) {
503
- // @ts-ignore
504
- return Buffer.from(str).toString('base64');
505
- }
506
- };
507
- const getQueryString = (params) => {
508
- const qs = [];
509
- const append = (key, value) => {
510
- qs.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`);
511
- };
512
- const process = (key, value) => {
513
- if (isDefined(value)) {
514
- if (Array.isArray(value)) {
515
- value.forEach(v => {
516
- process(key, v);
517
- });
518
- }
519
- else if (typeof value === 'object') {
520
- Object.entries(value).forEach(([k, v]) => {
521
- process(`${key}[${k}]`, v);
522
- });
523
- }
524
- else {
525
- append(key, value);
526
- }
527
- }
528
- };
529
- Object.entries(params).forEach(([key, value]) => {
530
- process(key, value);
531
- });
532
- if (qs.length > 0) {
533
- return `?${qs.join('&')}`;
534
- }
535
- return '';
536
- };
537
- const getUrl = (config, options) => {
538
- const encoder = config.ENCODE_PATH || encodeURI;
539
- const path = options.url
540
- .replace('{api-version}', config.VERSION)
541
- .replace(/{(.*?)}/g, (substring, group) => {
542
- if (options.path?.hasOwnProperty(group)) {
543
- return encoder(String(options.path[group]));
544
- }
545
- return substring;
546
- });
547
- const url = `${config.BASE}${path}`;
548
- if (options.query) {
549
- return `${url}${getQueryString(options.query)}`;
550
- }
551
- return url;
552
- };
553
- const getFormData = (options) => {
554
- if (options.formData) {
555
- const formData = new FormData();
556
- const process = (key, value) => {
557
- if (isString(value) || isBlob(value)) {
558
- formData.append(key, value);
559
- }
560
- else {
561
- formData.append(key, JSON.stringify(value));
562
- }
563
- };
564
- Object.entries(options.formData)
565
- .filter(([_, value]) => isDefined(value))
566
- .forEach(([key, value]) => {
567
- if (Array.isArray(value)) {
568
- value.forEach(v => process(key, v));
569
- }
570
- else {
571
- process(key, value);
572
- }
573
- });
574
- return formData;
575
- }
576
- return undefined;
577
- };
578
- const resolve = async (options, resolver) => {
579
- if (typeof resolver === 'function') {
580
- return resolver(options);
581
- }
582
- return resolver;
583
- };
584
- const getHeaders = async (config, options, formData) => {
585
- const token = await resolve(options, config.TOKEN);
586
- const username = await resolve(options, config.USERNAME);
587
- const password = await resolve(options, config.PASSWORD);
588
- const additionalHeaders = await resolve(options, config.HEADERS);
589
- const formHeaders = typeof formData?.getHeaders === 'function' && formData?.getHeaders() || {};
590
- const headers = Object.entries({
591
- Accept: 'application/json',
592
- ...additionalHeaders,
593
- ...options.headers,
594
- ...formHeaders,
595
- })
596
- .filter(([_, value]) => isDefined(value))
597
- .reduce((headers, [key, value]) => ({
598
- ...headers,
599
- [key]: String(value),
600
- }), {});
601
- if (isStringWithValue(token)) {
602
- headers['Authorization'] = `Bearer ${token}`;
603
- }
604
- if (isStringWithValue(username) && isStringWithValue(password)) {
605
- const credentials = base64(`${username}:${password}`);
606
- headers['Authorization'] = `Basic ${credentials}`;
607
- }
608
- if (options.body) {
609
- if (options.mediaType) {
610
- headers['Content-Type'] = options.mediaType;
611
- }
612
- else if (isBlob(options.body)) {
613
- headers['Content-Type'] = options.body.type || 'application/octet-stream';
614
- }
615
- else if (isString(options.body)) {
616
- headers['Content-Type'] = 'text/plain';
617
- }
618
- else if (!isFormData(options.body)) {
619
- headers['Content-Type'] = 'application/json';
620
- }
621
- }
622
- return headers;
623
- };
624
- const getRequestBody = (options) => {
625
- if (options.body) {
626
- return options.body;
627
- }
628
- return undefined;
629
- };
630
- const sendRequest = async (config, options, url, body, formData, headers, onCancel) => {
631
- const source = axios.CancelToken.source();
632
- const requestConfig = {
633
- url,
634
- headers,
635
- data: body ?? formData,
636
- method: options.method,
637
- withCredentials: config.WITH_CREDENTIALS,
638
- cancelToken: source.token,
639
- };
640
- onCancel(() => source.cancel('The user aborted a request.'));
641
- try {
642
- return await axios.request(requestConfig);
643
- }
644
- catch (error) {
645
- const axiosError = error;
646
- if (axiosError.response) {
647
- return axiosError.response;
648
- }
649
- throw error;
650
- }
651
- };
652
- const getResponseHeader = (response, responseHeader) => {
653
- if (responseHeader) {
654
- const content = response.headers[responseHeader];
655
- if (isString(content)) {
656
- return content;
657
- }
658
- }
659
- return undefined;
660
- };
661
- const getResponseBody = (response) => {
662
- if (response.status !== 204) {
663
- return response.data;
664
- }
665
- return undefined;
666
- };
667
- const catchErrorCodes = (options, result) => {
668
- const errors = {
669
- 400: 'Bad Request',
670
- 401: 'Unauthorized',
671
- 403: 'Forbidden',
672
- 404: 'Not Found',
673
- 500: 'Internal Server Error',
674
- 502: 'Bad Gateway',
675
- 503: 'Service Unavailable',
676
- ...options.errors,
677
- };
678
- const error = errors[result.status];
679
- if (error) {
680
- throw new ApiError(options, result, error);
681
- }
682
- if (!result.ok) {
683
- throw new ApiError(options, result, 'Generic Error');
684
- }
685
- };
686
- /**
687
- * Request method
688
- * @param config The OpenAPI configuration object
689
- * @param options The request options from the service
690
- * @returns CancelablePromise<T>
691
- * @throws ApiError
692
- */
693
- const request = (config, options) => {
694
- return new CancelablePromise(async (resolve, reject, onCancel) => {
695
- try {
696
- const url = getUrl(config, options);
697
- const formData = getFormData(options);
698
- const body = getRequestBody(options);
699
- const headers = await getHeaders(config, options, formData);
700
- if (!onCancel.isCancelled) {
701
- const response = await sendRequest(config, options, url, body, formData, headers, onCancel);
702
- const responseBody = getResponseBody(response);
703
- const responseHeader = getResponseHeader(response, options.responseHeader);
704
- const result = {
705
- url,
706
- ok: isSuccess(response.status),
707
- status: response.status,
708
- statusText: response.statusText,
709
- body: responseHeader ?? responseBody,
710
- };
711
- catchErrorCodes(options, result);
712
- resolve(result.body);
713
- }
714
- }
715
- catch (error) {
716
- reject(error);
717
- }
718
- });
719
- };
720
-
721
- class AxiosHttpRequest extends BaseHttpRequest {
722
- constructor(config) {
723
- super(config);
724
- }
725
- /**
726
- * Request method
727
- * @param options The request options from the service
728
- * @returns CancelablePromise<T>
729
- * @throws ApiError
730
- */
731
- request(options) {
732
- return request(this.config, options);
733
- }
734
- }
735
-
736
- class OrdersService {
737
- httpRequest;
738
- constructor(httpRequest) {
739
- this.httpRequest = httpRequest;
740
- }
741
- /**
742
- * Cancel one or more orders
743
- * Cancel one or more orders
744
- * @returns CancelOrdersResult Orders cancellation response.
745
- * @throws ApiError
746
- */
747
- cancelOrders({ chainName, requestBody, }) {
748
- return this.httpRequest.request({
749
- method: 'POST',
750
- url: '/v1/chains/{chain_name}/orders/cancel',
751
- path: {
752
- 'chain_name': chainName,
753
- },
754
- body: requestBody,
755
- mediaType: 'application/json',
756
- errors: {
757
- 400: `Bad Request (400)`,
758
- 401: `Unauthorised Request (401)`,
759
- 404: `The specified resource was not found (404)`,
760
- 429: `Too Many Requests (429)`,
761
- 500: `Internal Server Error (500)`,
762
- 501: `Not Implemented Error (501)`,
763
- },
764
- });
765
- }
766
- /**
767
- * List all listings
768
- * List all listings
769
- * @returns ListListingsResult OK response.
770
- * @throws ApiError
771
- */
772
- listListings({ chainName, status, sellItemContractAddress, buyItemType, buyItemContractAddress, accountAddress, sellItemMetadataId, sellItemTokenId, fromUpdatedAt, pageSize, sortBy, sortDirection, pageCursor, }) {
773
- return this.httpRequest.request({
774
- method: 'GET',
775
- url: '/v1/chains/{chain_name}/orders/listings',
776
- path: {
777
- 'chain_name': chainName,
778
- },
779
- query: {
780
- 'status': status,
781
- 'sell_item_contract_address': sellItemContractAddress,
782
- 'buy_item_type': buyItemType,
783
- 'buy_item_contract_address': buyItemContractAddress,
784
- 'account_address': accountAddress,
785
- 'sell_item_metadata_id': sellItemMetadataId,
786
- 'sell_item_token_id': sellItemTokenId,
787
- 'from_updated_at': fromUpdatedAt,
788
- 'page_size': pageSize,
789
- 'sort_by': sortBy,
790
- 'sort_direction': sortDirection,
791
- 'page_cursor': pageCursor,
792
- },
793
- errors: {
794
- 400: `Bad Request (400)`,
795
- 404: `The specified resource was not found (404)`,
796
- 500: `Internal Server Error (500)`,
797
- },
798
- });
799
- }
800
- /**
801
- * Create a listing
802
- * Create a listing
803
- * @returns ListingResult Created response.
804
- * @throws ApiError
805
- */
806
- createListing({ chainName, requestBody, }) {
807
- return this.httpRequest.request({
808
- method: 'POST',
809
- url: '/v1/chains/{chain_name}/orders/listings',
810
- path: {
811
- 'chain_name': chainName,
812
- },
813
- body: requestBody,
814
- mediaType: 'application/json',
815
- errors: {
816
- 400: `Bad Request (400)`,
817
- 404: `The specified resource was not found (404)`,
818
- 500: `Internal Server Error (500)`,
819
- },
820
- });
821
- }
822
- /**
823
- * Get a single listing by ID
824
- * Get a single listing by ID
825
- * @returns ListingResult OK response.
826
- * @throws ApiError
827
- */
828
- getListing({ chainName, listingId, }) {
829
- return this.httpRequest.request({
830
- method: 'GET',
831
- url: '/v1/chains/{chain_name}/orders/listings/{listing_id}',
832
- path: {
833
- 'chain_name': chainName,
834
- 'listing_id': listingId,
835
- },
836
- errors: {
837
- 400: `Bad Request (400)`,
838
- 404: `The specified resource was not found (404)`,
839
- 500: `Internal Server Error (500)`,
840
- },
841
- });
842
- }
843
- /**
844
- * Retrieve fulfillment data for orders
845
- * Retrieve signed fulfillment data based on the list of order IDs and corresponding fees.
846
- * @returns any Successful response
847
- * @throws ApiError
848
- */
849
- fulfillmentData({ chainName, requestBody, }) {
850
- return this.httpRequest.request({
851
- method: 'POST',
852
- url: '/v1/chains/{chain_name}/orders/fulfillment-data',
853
- path: {
854
- 'chain_name': chainName,
855
- },
856
- body: requestBody,
857
- mediaType: 'application/json',
858
- errors: {
859
- 400: `Bad Request (400)`,
860
- 404: `The specified resource was not found (404)`,
861
- 500: `Internal Server Error (500)`,
862
- },
863
- });
864
- }
865
- /**
866
- * List all trades
867
- * List all trades
868
- * @returns ListTradeResult OK response.
869
- * @throws ApiError
870
- */
871
- listTrades({ chainName, accountAddress, sellItemContractAddress, fromIndexedAt, pageSize, sortBy, sortDirection, pageCursor, }) {
872
- return this.httpRequest.request({
873
- method: 'GET',
874
- url: '/v1/chains/{chain_name}/trades',
875
- path: {
876
- 'chain_name': chainName,
877
- },
878
- query: {
879
- 'account_address': accountAddress,
880
- 'sell_item_contract_address': sellItemContractAddress,
881
- 'from_indexed_at': fromIndexedAt,
882
- 'page_size': pageSize,
883
- 'sort_by': sortBy,
884
- 'sort_direction': sortDirection,
885
- 'page_cursor': pageCursor,
886
- },
887
- errors: {
888
- 400: `Bad Request (400)`,
889
- 404: `The specified resource was not found (404)`,
890
- 500: `Internal Server Error (500)`,
891
- },
892
- });
893
- }
894
- /**
895
- * Get a single trade by ID
896
- * Get a single trade by ID
897
- * @returns TradeResult OK response.
898
- * @throws ApiError
899
- */
900
- getTrade({ chainName, tradeId, }) {
901
- return this.httpRequest.request({
902
- method: 'GET',
903
- url: '/v1/chains/{chain_name}/trades/{trade_id}',
904
- path: {
905
- 'chain_name': chainName,
906
- 'trade_id': tradeId,
907
- },
908
- errors: {
909
- 400: `Bad Request (400)`,
910
- 404: `The specified resource was not found (404)`,
911
- 500: `Internal Server Error (500)`,
912
- },
913
- });
914
- }
915
- }
916
-
917
- class OrderBookClient {
918
- orders;
919
- request;
920
- constructor(config, HttpRequest = AxiosHttpRequest) {
921
- this.request = new HttpRequest({
922
- BASE: config?.BASE ?? 'https://api.immutable.com',
923
- VERSION: config?.VERSION ?? '1.0.0',
924
- WITH_CREDENTIALS: config?.WITH_CREDENTIALS ?? false,
925
- CREDENTIALS: config?.CREDENTIALS ?? 'include',
926
- TOKEN: config?.TOKEN,
927
- USERNAME: config?.USERNAME,
928
- PASSWORD: config?.PASSWORD,
929
- HEADERS: config?.HEADERS,
930
- ENCODE_PATH: config?.ENCODE_PATH,
931
- });
932
- this.orders = new OrdersService(this.request);
933
- }
934
- }
935
-
936
- /* istanbul ignore file */
937
- /* tslint:disable */
938
- /* eslint-disable */
939
- var CancelledOrderStatus;
940
- (function (CancelledOrderStatus) {
941
- (function (cancellation_type) {
942
- cancellation_type["ON_CHAIN"] = "ON_CHAIN";
943
- cancellation_type["OFF_CHAIN"] = "OFF_CHAIN";
944
- cancellation_type["UNDERFUNDED"] = "UNDERFUNDED";
945
- })(CancelledOrderStatus.cancellation_type || (CancelledOrderStatus.cancellation_type = {}));
946
- })(CancelledOrderStatus || (CancelledOrderStatus = {}));
947
-
948
- /* istanbul ignore file */
949
- /* tslint:disable */
950
- /* eslint-disable */
951
- var FailedOrderCancellation;
952
- (function (FailedOrderCancellation) {
953
- (function (reason_code) {
954
- reason_code["FILLED"] = "FILLED";
955
- })(FailedOrderCancellation.reason_code || (FailedOrderCancellation.reason_code = {}));
956
- })(FailedOrderCancellation || (FailedOrderCancellation = {}));
957
-
958
- /* istanbul ignore file */
959
- /* tslint:disable */
960
- /* eslint-disable */
961
- var Fee;
962
- (function (Fee) {
963
- (function (type) {
964
- type["ROYALTY"] = "ROYALTY";
965
- type["MAKER_ECOSYSTEM"] = "MAKER_ECOSYSTEM";
966
- type["TAKER_ECOSYSTEM"] = "TAKER_ECOSYSTEM";
967
- type["PROTOCOL"] = "PROTOCOL";
968
- })(Fee.type || (Fee.type = {}));
969
- })(Fee || (Fee = {}));
970
-
971
- /* istanbul ignore file */
972
- /* tslint:disable */
973
- /* eslint-disable */
974
- var Order;
975
- (function (Order) {
976
- (function (type) {
977
- type["LISTING"] = "LISTING";
978
- })(Order.type || (Order.type = {}));
979
- })(Order || (Order = {}));
980
-
981
- /* istanbul ignore file */
982
- /* tslint:disable */
983
- /* eslint-disable */
984
- /**
985
- * The Order status
986
- */
987
- var OrderStatusName;
988
- (function (OrderStatusName) {
989
- OrderStatusName["PENDING"] = "PENDING";
990
- OrderStatusName["ACTIVE"] = "ACTIVE";
991
- OrderStatusName["INACTIVE"] = "INACTIVE";
992
- OrderStatusName["FILLED"] = "FILLED";
993
- OrderStatusName["EXPIRED"] = "EXPIRED";
994
- OrderStatusName["CANCELLED"] = "CANCELLED";
995
- })(OrderStatusName || (OrderStatusName = {}));
996
-
997
- /* istanbul ignore file */
998
- /* tslint:disable */
999
- /* eslint-disable */
1000
- var ProtocolData;
1001
- (function (ProtocolData) {
1002
- (function (order_type) {
1003
- order_type["FULL_RESTRICTED"] = "FULL_RESTRICTED";
1004
- order_type["PARTIAL_RESTRICTED"] = "PARTIAL_RESTRICTED";
1005
- })(ProtocolData.order_type || (ProtocolData.order_type = {}));
1006
- })(ProtocolData || (ProtocolData = {}));
1007
-
1008
- var FeeType;
1009
- (function (FeeType) {
1010
- FeeType["MAKER_ECOSYSTEM"] = "MAKER_ECOSYSTEM";
1011
- FeeType["TAKER_ECOSYSTEM"] = "TAKER_ECOSYSTEM";
1012
- FeeType["PROTOCOL"] = "PROTOCOL";
1013
- FeeType["ROYALTY"] = "ROYALTY";
1014
- })(FeeType || (FeeType = {}));
1015
- var TransactionPurpose;
1016
- (function (TransactionPurpose) {
1017
- TransactionPurpose["APPROVAL"] = "APPROVAL";
1018
- TransactionPurpose["FULFILL_ORDER"] = "FULFILL_ORDER";
1019
- TransactionPurpose["CANCEL"] = "CANCEL";
1020
- })(TransactionPurpose || (TransactionPurpose = {}));
1021
- var SignablePurpose;
1022
- (function (SignablePurpose) {
1023
- SignablePurpose["CREATE_LISTING"] = "CREATE_LISTING";
1024
- SignablePurpose["OFF_CHAIN_CANCELLATION"] = "OFF_CHAIN_CANCELLATION";
1025
- })(SignablePurpose || (SignablePurpose = {}));
1026
- var ActionType;
1027
- (function (ActionType) {
1028
- ActionType["TRANSACTION"] = "TRANSACTION";
1029
- ActionType["SIGNABLE"] = "SIGNABLE";
1030
- })(ActionType || (ActionType = {}));
1031
-
1032
- function mapFromOpenApiOrder(order) {
1033
- const buyItems = order.buy.map((item) => {
1034
- if (item.type === 'ERC20') {
1035
- return {
1036
- type: 'ERC20',
1037
- contractAddress: item.contract_address,
1038
- amount: item.amount,
1039
- };
1040
- }
1041
- if (item.type === 'NATIVE') {
1042
- return {
1043
- type: 'NATIVE',
1044
- amount: item.amount,
1045
- };
1046
- }
1047
- throw new Error('Buy items must be either ERC20 or NATIVE');
1048
- });
1049
- const sellItems = order.sell.map((item) => {
1050
- if (item.type === 'ERC721') {
1051
- return {
1052
- type: 'ERC721',
1053
- contractAddress: item.contract_address,
1054
- tokenId: item.token_id,
1055
- };
1056
- }
1057
- if (item.type === 'ERC1155') {
1058
- return {
1059
- type: 'ERC1155',
1060
- contractAddress: item.contract_address,
1061
- tokenId: item.token_id,
1062
- amount: item.amount,
1063
- };
1064
- }
1065
- throw new Error('Sell items must ERC721 or ERC1155');
1066
- });
1067
- return {
1068
- id: order.id,
1069
- type: order.type,
1070
- accountAddress: order.account_address,
1071
- buy: buyItems,
1072
- sell: sellItems,
1073
- fees: order.fees.map((fee) => ({
1074
- amount: fee.amount,
1075
- recipientAddress: fee.recipient_address,
1076
- type: fee.type,
1077
- })),
1078
- fillStatus: order.fill_status,
1079
- chain: order.chain,
1080
- createdAt: order.created_at,
1081
- endAt: order.end_at,
1082
- orderHash: order.order_hash,
1083
- protocolData: {
1084
- orderType: order.protocol_data.order_type,
1085
- counter: order.protocol_data.counter,
1086
- seaportAddress: order.protocol_data.seaport_address,
1087
- seaportVersion: order.protocol_data.seaport_version,
1088
- zoneAddress: order.protocol_data.zone_address,
1089
- },
1090
- salt: order.salt,
1091
- signature: order.signature,
1092
- startAt: order.start_at,
1093
- status: order.status,
1094
- updatedAt: order.updated_at,
1095
- };
1096
- }
1097
- function mapFromOpenApiTrade(trade) {
1098
- const buyItems = trade.buy.map((item) => {
1099
- if (item.type === 'ERC20') {
1100
- return {
1101
- type: 'ERC20',
1102
- contractAddress: item.contract_address,
1103
- amount: item.amount,
1104
- };
1105
- }
1106
- if (item.type === 'NATIVE') {
1107
- return {
1108
- type: 'NATIVE',
1109
- amount: item.amount,
1110
- };
1111
- }
1112
- throw new Error('Buy items must be either ERC20 or NATIVE');
1113
- });
1114
- const sellItems = trade.sell.map((item) => {
1115
- if (item.type === 'ERC721') {
1116
- return {
1117
- type: 'ERC721',
1118
- contractAddress: item.contract_address,
1119
- tokenId: item.token_id,
1120
- };
1121
- }
1122
- if (item.type === 'ERC1155') {
1123
- return {
1124
- type: 'ERC1155',
1125
- contractAddress: item.contract_address,
1126
- tokenId: item.token_id,
1127
- amount: item.amount,
1128
- };
1129
- }
1130
- throw new Error('Sell items must ERC721');
1131
- });
1132
- return {
1133
- id: trade.id,
1134
- orderId: trade.order_id,
1135
- buy: buyItems,
1136
- sell: sellItems,
1137
- buyerFees: trade.buyer_fees.map((fee) => ({
1138
- amount: fee.amount,
1139
- recipientAddress: fee.recipient_address,
1140
- type: fee.type,
1141
- })),
1142
- chain: trade.chain,
1143
- indexedAt: trade.indexed_at,
1144
- blockchainMetadata: {
1145
- blockNumber: trade.blockchain_metadata.block_number,
1146
- logIndex: trade.blockchain_metadata.log_index,
1147
- transactionHash: trade.blockchain_metadata.transaction_hash,
1148
- transactionIndex: trade.blockchain_metadata.transaction_index,
1149
- },
1150
- buyerAddress: trade.buyer_address,
1151
- makerAddress: trade.maker_address,
1152
- sellerAddress: trade.seller_address,
1153
- takerAddress: trade.taker_address,
1154
- };
1155
- }
1156
- function mapFromOpenApiPage(page) {
1157
- return {
1158
- nextCursor: page.next_cursor,
1159
- previousCursor: page.previous_cursor,
1160
- };
1161
- }
1162
-
1163
- /* eslint-disable */
1164
- // TODO: Resolve these from seaport-js.
1165
- // There is some bundling issue that is preventing this from working
1166
- const SEAPORT_CONTRACT_NAME = 'ImmutableSeaport';
1167
- // export const SEAPORT_CONTRACT_VERSION_V1_4 = '1.4';
1168
- const SEAPORT_CONTRACT_VERSION_V1_5 = '1.5';
1169
- const EIP_712_ORDER_TYPE = {
1170
- OrderComponents: [
1171
- { name: 'offerer', type: 'address' },
1172
- { name: 'zone', type: 'address' },
1173
- { name: 'offer', type: 'OfferItem[]' },
1174
- { name: 'consideration', type: 'ConsiderationItem[]' },
1175
- { name: 'orderType', type: 'uint8' },
1176
- { name: 'startTime', type: 'uint256' },
1177
- { name: 'endTime', type: 'uint256' },
1178
- { name: 'zoneHash', type: 'bytes32' },
1179
- { name: 'salt', type: 'uint256' },
1180
- { name: 'conduitKey', type: 'bytes32' },
1181
- { name: 'counter', type: 'uint256' },
1182
- ],
1183
- OfferItem: [
1184
- { name: 'itemType', type: 'uint8' },
1185
- { name: 'token', type: 'address' },
1186
- { name: 'identifierOrCriteria', type: 'uint256' },
1187
- { name: 'startAmount', type: 'uint256' },
1188
- { name: 'endAmount', type: 'uint256' },
1189
- ],
1190
- ConsiderationItem: [
1191
- { name: 'itemType', type: 'uint8' },
1192
- { name: 'token', type: 'address' },
1193
- { name: 'identifierOrCriteria', type: 'uint256' },
1194
- { name: 'startAmount', type: 'uint256' },
1195
- { name: 'endAmount', type: 'uint256' },
1196
- { name: 'recipient', type: 'address' },
1197
- ],
1198
- };
1199
- var OrderType;
1200
- (function (OrderType) {
1201
- OrderType[OrderType["FULL_OPEN"] = 0] = "FULL_OPEN";
1202
- OrderType[OrderType["PARTIAL_OPEN"] = 1] = "PARTIAL_OPEN";
1203
- OrderType[OrderType["FULL_RESTRICTED"] = 2] = "FULL_RESTRICTED";
1204
- OrderType[OrderType["PARTIAL_RESTRICTED"] = 3] = "PARTIAL_RESTRICTED";
1205
- })(OrderType || (OrderType = {}));
1206
- var ItemType;
1207
- (function (ItemType) {
1208
- ItemType[ItemType["NATIVE"] = 0] = "NATIVE";
1209
- ItemType[ItemType["ERC20"] = 1] = "ERC20";
1210
- ItemType[ItemType["ERC721"] = 2] = "ERC721";
1211
- ItemType[ItemType["ERC1155"] = 3] = "ERC1155";
1212
- ItemType[ItemType["ERC721_WITH_CRITERIA"] = 4] = "ERC721_WITH_CRITERIA";
1213
- ItemType[ItemType["ERC1155_WITH_CRITERIA"] = 5] = "ERC1155_WITH_CRITERIA";
1214
- })(ItemType || (ItemType = {}));
1215
- var Side;
1216
- (function (Side) {
1217
- Side[Side["OFFER"] = 0] = "OFFER";
1218
- Side[Side["CONSIDERATION"] = 1] = "CONSIDERATION";
1219
- })(Side || (Side = {}));
1220
- var BasicOrderRouteType;
1221
- (function (BasicOrderRouteType) {
1222
- BasicOrderRouteType[BasicOrderRouteType["ETH_TO_ERC721"] = 0] = "ETH_TO_ERC721";
1223
- BasicOrderRouteType[BasicOrderRouteType["ETH_TO_ERC1155"] = 1] = "ETH_TO_ERC1155";
1224
- BasicOrderRouteType[BasicOrderRouteType["ERC20_TO_ERC721"] = 2] = "ERC20_TO_ERC721";
1225
- BasicOrderRouteType[BasicOrderRouteType["ERC20_TO_ERC1155"] = 3] = "ERC20_TO_ERC1155";
1226
- BasicOrderRouteType[BasicOrderRouteType["ERC721_TO_ERC20"] = 4] = "ERC721_TO_ERC20";
1227
- BasicOrderRouteType[BasicOrderRouteType["ERC1155_TO_ERC20"] = 5] = "ERC1155_TO_ERC20";
1228
- })(BasicOrderRouteType || (BasicOrderRouteType = {}));
1229
-
1230
- const baseDefaults = {
1231
- integer: 0,
1232
- address: ethers.zeroPadValue('0x', 20),
1233
- bool: false,
1234
- bytes: '0x',
1235
- string: '',
1236
- };
1237
- const isNullish = (value) => {
1238
- if (value === undefined)
1239
- return false;
1240
- return (value !== undefined
1241
- && value !== null
1242
- && ((['string', 'number'].includes(typeof value) && BigInt(value) === 0n)
1243
- || (Array.isArray(value) && value.every(isNullish))
1244
- || (typeof value === 'object' && Object.values(value).every(isNullish))
1245
- || (typeof value === 'boolean' && value === false)));
1246
- };
1247
- function getDefaultForBaseType(type) {
1248
- // bytesXX
1249
- const [, width] = type.match(/^bytes(\d+)$/) ?? [];
1250
- // eslint-disable-next-line radix
1251
- if (width)
1252
- return zeroPadValue('0x', parseInt(width));
1253
- // eslint-disable-next-line no-param-reassign
1254
- if (type.match(/^(u?)int(\d*)$/))
1255
- type = 'integer';
1256
- return baseDefaults[type];
1257
- }
1258
- class DefaultGetter {
1259
- types;
1260
- defaultValues = {};
1261
- constructor(types) {
1262
- this.types = types;
1263
- // eslint-disable-next-line no-restricted-syntax, guard-for-in
1264
- for (const name in types) {
1265
- const defaultValue = this.getDefaultValue(name);
1266
- this.defaultValues[name] = defaultValue;
1267
- if (!isNullish(defaultValue)) {
1268
- throw new Error(`Got non-empty value for type ${name} in default generator: ${defaultValue}`);
1269
- }
1270
- }
1271
- }
1272
- static from(types, type) {
1273
- const { defaultValues } = new DefaultGetter(types);
1274
- if (type)
1275
- return defaultValues[type];
1276
- return defaultValues;
1277
- }
1278
- /* eslint-enable no-dupe-class-members */
1279
- getDefaultValue(type) {
1280
- if (this.defaultValues[type])
1281
- return this.defaultValues[type];
1282
- // Basic type (address, bool, uint256, etc)
1283
- const basic = getDefaultForBaseType(type);
1284
- if (basic !== undefined)
1285
- return basic;
1286
- // Array
1287
- const match = type.match(/^(.*)(\x5b(\d*)\x5d)$/);
1288
- if (match) {
1289
- const subtype = match[1];
1290
- // eslint-disable-next-line radix
1291
- const length = parseInt(match[3]);
1292
- if (length > 0) {
1293
- const baseValue = this.getDefaultValue(subtype);
1294
- return Array(length).fill(baseValue);
1295
- }
1296
- return [];
1297
- }
1298
- // Struct
1299
- const fields = this.types[type];
1300
- if (fields) {
1301
- return fields.reduce(
1302
- // eslint-disable-next-line @typescript-eslint/no-shadow
1303
- (obj, { name, type }) => ({
1304
- ...obj,
1305
- [name]: this.getDefaultValue(type),
1306
- }), {});
1307
- }
1308
- throw new Error(`unknown type: ${type}`);
1309
- }
1310
- }
1311
-
1312
- const makeArray = (len, getValue) => Array(len)
1313
- .fill(0)
1314
- .map((_, i) => getValue(i));
1315
- // eslint-disable-next-line max-len
1316
- const chunk = (array, size) => makeArray(Math.ceil(array.length / size), (i) => array.slice(i * size, (i + 1) * size));
1317
- const bufferToHex = (buf) => toBeHex(buf.toString('hex'));
1318
- const hexToBuffer = (value) => Buffer.from(value.slice(2), 'hex');
1319
- const bufferKeccak = (value) => hexToBuffer(keccak256(value));
1320
- const hashConcat = (arr) => bufferKeccak(concat(arr));
1321
- const fillArray = (arr, length, value) => {
1322
- if (length > arr.length)
1323
- arr.push(...Array(length - arr.length).fill(value));
1324
- return arr;
1325
- };
1326
- const getRoot = (elements, hashLeaves = true) => {
1327
- if (elements.length === 0)
1328
- throw new Error('empty tree');
1329
- const leaves = elements.map((e) => {
1330
- const leaf = Buffer.isBuffer(e) ? e : hexToBuffer(e);
1331
- return hashLeaves ? bufferKeccak(leaf) : leaf;
1332
- });
1333
- const layers = [leaves];
1334
- // Get next layer until we reach the root
1335
- while (layers[layers.length - 1].length > 1) {
1336
- // eslint-disable-next-line @typescript-eslint/no-use-before-define
1337
- layers.push(getNextLayer(layers[layers.length - 1]));
1338
- }
1339
- return layers[layers.length - 1][0];
1340
- };
1341
- const getNextLayer = (elements) => chunk(elements, 2).map(hashConcat);
1342
-
1343
- // eslint-disable-next-line max-len
1344
- const getTree = (leaves, defaultLeafHash) => new MerkleTree(leaves.map(hexToBuffer), bufferKeccak, {
1345
- complete: true,
1346
- sort: false,
1347
- hashLeaves: false,
1348
- fillDefaultHash: hexToBuffer(defaultLeafHash),
1349
- });
1350
- const encodeProof = (key, proof, signature = `0x${'ff'.repeat(64)}`) => concat([
1351
- signature,
1352
- `0x${key.toString(16).padStart(6, '0')}`,
1353
- AbiCoder.defaultAbiCoder().encode([`uint256[${proof.length}]`], [proof]),
1354
- ]);
1355
- class Eip712MerkleTree {
1356
- types;
1357
- rootType;
1358
- leafType;
1359
- elements;
1360
- depth;
1361
- tree;
1362
- leafHasher;
1363
- defaultNode;
1364
- defaultLeaf;
1365
- encoder;
1366
- get completedSize() {
1367
- return 2 ** this.depth;
1368
- }
1369
- /** Returns the array of elements in the tree, padded to the complete size with empty items. */
1370
- getCompleteElements() {
1371
- const { elements } = this;
1372
- return fillArray([...elements], this.completedSize, this.defaultNode);
1373
- }
1374
- // eslint-disable-next-line max-len
1375
- /** Returns the array of leaf nodes in the tree, padded to the complete size with default hashes. */
1376
- getCompleteLeaves() {
1377
- const leaves = this.elements.map(this.leafHasher);
1378
- return fillArray([...leaves], this.completedSize, this.defaultLeaf);
1379
- }
1380
- get root() {
1381
- return this.tree.getHexRoot();
1382
- }
1383
- getProof(i) {
1384
- const leaves = this.getCompleteLeaves();
1385
- const leaf = leaves[i];
1386
- const proof = this.tree.getHexProof(leaf, i);
1387
- const root = this.tree.getHexRoot();
1388
- return { leaf, proof, root };
1389
- }
1390
- getEncodedProofAndSignature(i, signature) {
1391
- const { proof } = this.getProof(i);
1392
- return encodeProof(i, proof, signature);
1393
- }
1394
- getDataToSign() {
1395
- let layer = this.getCompleteElements();
1396
- while (layer.length > 2) {
1397
- layer = chunk(layer, 2);
1398
- }
1399
- return layer;
1400
- }
1401
- add(element) {
1402
- this.elements.push(element);
1403
- }
1404
- getBulkOrderHash() {
1405
- const structHash = this.encoder.hashStruct('BulkOrder', {
1406
- tree: this.getDataToSign(),
1407
- });
1408
- const leaves = this.getCompleteLeaves().map(hexToBuffer);
1409
- const rootHash = bufferToHex(getRoot(leaves, false));
1410
- const typeHash = keccak256(toUtf8Bytes(this.encoder.types.BulkOrder[0].type));
1411
- const bulkOrderHash = keccak256(concat([typeHash, rootHash]));
1412
- if (bulkOrderHash !== structHash) {
1413
- throw new Error('expected derived bulk order hash to match');
1414
- }
1415
- return structHash;
1416
- }
1417
- constructor(types, rootType, leafType, elements, depth) {
1418
- this.types = types;
1419
- this.rootType = rootType;
1420
- this.leafType = leafType;
1421
- this.elements = elements;
1422
- this.depth = depth;
1423
- const encoder = TypedDataEncoder.from(types);
1424
- this.encoder = encoder;
1425
- this.leafHasher = (leaf) => encoder.hashStruct(leafType, leaf);
1426
- this.defaultNode = DefaultGetter.from(types, leafType);
1427
- this.defaultLeaf = this.leafHasher(this.defaultNode);
1428
- this.tree = getTree(this.getCompleteLeaves(), this.defaultLeaf);
1429
- }
1430
- }
1431
-
1432
- function getBulkOrderTypes(height) {
1433
- return {
1434
- ...EIP_712_ORDER_TYPE,
1435
- // eslint-disable-next-line @typescript-eslint/naming-convention
1436
- BulkOrder: [{ name: 'tree', type: `OrderComponents${'[2]'.repeat(height)}` }],
1437
- };
1438
- }
1439
- function getBulkOrderTreeHeight(length) {
1440
- return Math.max(Math.ceil(Math.log2(length)), 1);
1441
- }
1442
- function getBulkOrderTree(orderComponents, startIndex = 0, height = getBulkOrderTreeHeight(orderComponents.length + startIndex)) {
1443
- const types = getBulkOrderTypes(height);
1444
- const defaultNode = DefaultGetter.from(types, 'OrderComponents');
1445
- let elements = [...orderComponents];
1446
- if (startIndex > 0) {
1447
- elements = [
1448
- ...fillArray([], startIndex, defaultNode),
1449
- ...orderComponents,
1450
- ];
1451
- }
1452
- const tree = new Eip712MerkleTree(types, 'BulkOrder', 'OrderComponents', elements, height);
1453
- return tree;
1454
- }
1455
-
1456
- function getOrderComponentsFromMessage(orderMessage) {
1457
- const data = JSON.parse(orderMessage);
1458
- const orderComponents = data.message;
1459
- orderComponents.salt = BigNumber.from(orderComponents.salt).toHexString();
1460
- return orderComponents;
1461
- }
1462
- function getBulkOrderComponentsFromMessage(orderMessage) {
1463
- const data = JSON.parse(orderMessage);
1464
- const orderComponents = data.message.tree.flat(Infinity)
1465
- // Filter off the zero nodes in the tree. The will get rebuilt bu `getBulkOrderTree`
1466
- // when creating the listings
1467
- .filter((o) => o.offerer !== '0x0000000000000000000000000000000000000000');
1468
- // eslint-disable-next-line no-restricted-syntax
1469
- for (const orderComponent of orderComponents) {
1470
- orderComponent.salt = BigNumber.from(orderComponent.salt).toHexString();
1471
- }
1472
- return { components: orderComponents, types: data.types, value: data.message };
1473
- }
1474
- function getBulkSeaportOrderSignatures(signature, orderComponents) {
1475
- const tree = getBulkOrderTree(orderComponents);
1476
- return orderComponents.map((_, i) => tree.getEncodedProofAndSignature(i, signature));
1477
- }
1478
-
1479
- // Add 20% more gas than estimate to prevent out of gas errors
1480
- // This can always be overwritten by the user signing the transaction
1481
- function prepareTransaction(transactionMethods,
1482
- // chainId is required for EIP155
1483
- chainId, callerAddress) {
1484
- return async () => {
1485
- const v6ContractTransaction = await transactionMethods.buildTransaction();
1486
- const v5PopulatedTransaction = {
1487
- to: v6ContractTransaction.to,
1488
- from: callerAddress,
1489
- type: v6ContractTransaction.type,
1490
- maxFeePerGas: v6ContractTransaction.maxFeePerGas
1491
- ? BigNumber.from(v6ContractTransaction.maxFeePerGas)
1492
- : undefined,
1493
- maxPriorityFeePerGas: v6ContractTransaction.maxPriorityFeePerGas
1494
- ? BigNumber.from(v6ContractTransaction.maxPriorityFeePerGas)
1495
- : undefined,
1496
- value: v6ContractTransaction.value ? BigNumber.from(v6ContractTransaction.value) : undefined,
1497
- data: v6ContractTransaction.data,
1498
- nonce: v6ContractTransaction.nonce,
1499
- chainId,
1500
- };
1501
- v5PopulatedTransaction.gasLimit = BigNumber.from(await transactionMethods.estimateGas());
1502
- v5PopulatedTransaction.gasLimit = v5PopulatedTransaction.gasLimit
1503
- .add(v5PopulatedTransaction.gasLimit.div(5));
1504
- return v5PopulatedTransaction;
1505
- };
1506
- }
1507
-
1508
- function mapImmutableOrderToSeaportOrderComponents(order) {
1509
- const considerationItems = order.buy.map((buyItem) => {
1510
- switch (buyItem.type) {
1511
- case 'NATIVE':
1512
- return {
1513
- startAmount: buyItem.amount,
1514
- endAmount: buyItem.amount,
1515
- itemType: ItemType.NATIVE,
1516
- recipient: order.account_address,
1517
- token: constants$1.AddressZero,
1518
- identifierOrCriteria: '0',
1519
- };
1520
- case 'ERC20':
1521
- return {
1522
- startAmount: buyItem.amount,
1523
- endAmount: buyItem.amount,
1524
- itemType: ItemType.ERC20,
1525
- recipient: order.account_address,
1526
- token: buyItem.contract_address || constants$1.AddressZero,
1527
- identifierOrCriteria: '0',
1528
- };
1529
- default: // ERC721
1530
- return {
1531
- startAmount: '1',
1532
- endAmount: '1',
1533
- itemType: ItemType.ERC721,
1534
- recipient: order.account_address,
1535
- token: buyItem.contract_address || constants$1.AddressZero,
1536
- identifierOrCriteria: '0',
1537
- };
1538
- }
1539
- });
1540
- const fees = order.fees.map((fee) => ({
1541
- amount: fee.amount,
1542
- itemType: order.buy[0].type === 'ERC20' ? ItemType.ERC20 : ItemType.NATIVE,
1543
- recipient: fee.recipient_address,
1544
- token: order.buy[0].type === 'ERC20'
1545
- ? order.buy[0].contract_address
1546
- : constants$1.AddressZero,
1547
- identifierOrCriteria: '0',
1548
- }));
1549
- return {
1550
- orderComponents: {
1551
- conduitKey: constants$1.HashZero,
1552
- consideration: [...considerationItems],
1553
- offer: order.sell.map((sellItem) => {
1554
- let tokenItem;
1555
- switch (sellItem.type) {
1556
- case 'ERC1155':
1557
- tokenItem = sellItem;
1558
- return {
1559
- startAmount: tokenItem.amount,
1560
- endAmount: tokenItem.amount,
1561
- itemType: ItemType.ERC1155,
1562
- recipient: order.account_address,
1563
- token: tokenItem.contract_address,
1564
- identifierOrCriteria: tokenItem.token_id,
1565
- };
1566
- default: // ERC721
1567
- tokenItem = sellItem;
1568
- return {
1569
- startAmount: '1',
1570
- endAmount: '1',
1571
- itemType: ItemType.ERC721,
1572
- recipient: order.account_address,
1573
- token: tokenItem.contract_address,
1574
- identifierOrCriteria: tokenItem.token_id,
1575
- };
1576
- }
1577
- }),
1578
- counter: order.protocol_data.counter,
1579
- endTime: Math.round(new Date(order.end_at).getTime() / 1000).toString(),
1580
- startTime: Math.round(new Date(order.start_at).getTime() / 1000).toString(),
1581
- salt: order.salt,
1582
- offerer: order.account_address,
1583
- zone: order.protocol_data.zone_address,
1584
- // this should be the fee exclusive number of items the user signed for
1585
- totalOriginalConsiderationItems: considerationItems.length,
1586
- orderType: order.sell[0].type === 'ERC1155' ? OrderType.PARTIAL_RESTRICTED : OrderType.FULL_RESTRICTED,
1587
- zoneHash: constants$1.HashZero,
1588
- },
1589
- tips: fees,
1590
- };
1591
- }
1592
-
1593
- function determineFillableUnits(order, amountToFill) {
1594
- if (order.sell[0].type === 'ERC1155' && !amountToFill) {
1595
- // fill status is expressed as a ratio
1596
- const { numerator, denominator } = order.fill_status;
1597
- const originalOfferAmt = BigInt(order.sell[0].amount);
1598
- if (numerator === '0' || denominator === '0') {
1599
- return originalOfferAmt.toString();
1600
- }
1601
- // calculate the remaining amount to fill
1602
- // remaining = ((denominator - numerator) * originalOfferAmt) / denominator
1603
- const remaining = ((BigInt(denominator) - BigInt(numerator)) * BigInt(originalOfferAmt))
1604
- / BigInt(denominator);
1605
- return remaining.toString();
1606
- }
1607
- return amountToFill;
1608
- }
1609
-
1610
- class Seaport {
1611
- seaportLibFactory;
1612
- provider;
1613
- seaportContractAddress;
1614
- zoneContractAddress;
1615
- rateLimitingKey;
1616
- constructor(seaportLibFactory, provider, seaportContractAddress, zoneContractAddress, rateLimitingKey) {
1617
- this.seaportLibFactory = seaportLibFactory;
1618
- this.provider = provider;
1619
- this.seaportContractAddress = seaportContractAddress;
1620
- this.zoneContractAddress = zoneContractAddress;
1621
- this.rateLimitingKey = rateLimitingKey;
1622
- }
1623
- async prepareBulkSeaportOrders(offerer, orderInputs) {
1624
- const { actions: seaportActions } = await this.createSeaportOrders(offerer, orderInputs);
1625
- const approvalActions = seaportActions.filter((action) => action.type === 'approval');
1626
- const network = await this.provider.getNetwork();
1627
- const listingActions = approvalActions.map((approvalAction) => ({
1628
- type: ActionType.TRANSACTION,
1629
- purpose: TransactionPurpose.APPROVAL,
1630
- buildTransaction: prepareTransaction(approvalAction.transactionMethods, network.chainId, offerer),
1631
- }));
1632
- const createAction = seaportActions.find((action) => action.type === 'createBulk');
1633
- if (!createAction) {
1634
- throw new Error('No create bulk order action found');
1635
- }
1636
- const orderMessageToSign = await createAction.getMessageToSign();
1637
- const { components, types, value } = getBulkOrderComponentsFromMessage(orderMessageToSign);
1638
- listingActions.push({
1639
- type: ActionType.SIGNABLE,
1640
- purpose: SignablePurpose.CREATE_LISTING,
1641
- message: await this.getTypedDataFromBulkOrderComponents(types, value),
1642
- });
1643
- return {
1644
- actions: listingActions,
1645
- preparedListings: components.map((orderComponent) => ({
1646
- orderComponents: orderComponent,
1647
- orderHash: this.getSeaportLib().getOrderHash(orderComponent),
1648
- })),
1649
- };
1650
- }
1651
- async prepareSeaportOrder(offerer, listingItem, considerationItem, orderStart, orderExpiry) {
1652
- const { actions: seaportActions } = await this.createSeaportOrder(offerer, listingItem, considerationItem, orderStart, orderExpiry);
1653
- const listingActions = [];
1654
- const approvalAction = seaportActions.find((action) => action.type === 'approval');
1655
- if (approvalAction) {
1656
- listingActions.push({
1657
- type: ActionType.TRANSACTION,
1658
- purpose: TransactionPurpose.APPROVAL,
1659
- buildTransaction: prepareTransaction(approvalAction.transactionMethods, (await this.provider.getNetwork()).chainId, offerer),
1660
- });
1661
- }
1662
- const createAction = seaportActions.find((action) => action.type === 'create');
1663
- if (!createAction) {
1664
- throw new Error('No create order action found');
1665
- }
1666
- const orderMessageToSign = await createAction.getMessageToSign();
1667
- const orderComponents = getOrderComponentsFromMessage(orderMessageToSign);
1668
- listingActions.push({
1669
- type: ActionType.SIGNABLE,
1670
- purpose: SignablePurpose.CREATE_LISTING,
1671
- message: await this.getTypedDataFromOrderComponents(orderComponents),
1672
- });
1673
- return {
1674
- actions: listingActions,
1675
- orderComponents,
1676
- orderHash: this.getSeaportLib().getOrderHash(orderComponents),
1677
- };
1678
- }
1679
- async fulfillOrder(order, account, extraData, unitsToFill) {
1680
- const { orderComponents, tips } = mapImmutableOrderToSeaportOrderComponents(order);
1681
- const seaportLib = this.getSeaportLib(order);
1682
- const { actions: seaportActions } = await seaportLib.fulfillOrders({
1683
- accountAddress: account,
1684
- fulfillOrderDetails: [
1685
- {
1686
- order: {
1687
- parameters: orderComponents,
1688
- signature: order.signature,
1689
- },
1690
- unitsToFill: determineFillableUnits(order, unitsToFill),
1691
- extraData,
1692
- tips,
1693
- },
1694
- ],
1695
- });
1696
- const fulfillmentActions = [];
1697
- const approvalAction = seaportActions.find((action) => action.type === 'approval');
1698
- if (approvalAction) {
1699
- fulfillmentActions.push({
1700
- type: ActionType.TRANSACTION,
1701
- buildTransaction: prepareTransaction(approvalAction.transactionMethods, (await this.provider.getNetwork()).chainId, account),
1702
- purpose: TransactionPurpose.APPROVAL,
1703
- });
1704
- }
1705
- const fulfilOrderAction = seaportActions.find((action) => action.type === 'exchange');
1706
- if (!fulfilOrderAction) {
1707
- throw new Error('No exchange action found');
1708
- }
1709
- fulfillmentActions.push({
1710
- type: ActionType.TRANSACTION,
1711
- buildTransaction: prepareTransaction(fulfilOrderAction.transactionMethods, (await this.provider.getNetwork()).chainId, account),
1712
- purpose: TransactionPurpose.FULFILL_ORDER,
1713
- });
1714
- return {
1715
- actions: fulfillmentActions,
1716
- expiration: Seaport.getExpirationISOTimeFromExtraData(extraData),
1717
- order: mapFromOpenApiOrder(order),
1718
- };
1719
- }
1720
- async fulfillBulkOrders(fulfillingOrders, account) {
1721
- const fulfillOrderDetails = fulfillingOrders.map((o) => {
1722
- const { orderComponents, tips } = mapImmutableOrderToSeaportOrderComponents(o.order);
1723
- return {
1724
- order: {
1725
- parameters: orderComponents,
1726
- signature: o.order.signature,
1727
- },
1728
- unitsToFill: determineFillableUnits(o.order, o.unitsToFill),
1729
- extraData: o.extraData,
1730
- tips,
1731
- };
1732
- });
1733
- const { actions: seaportActions } = await this.getSeaportLib().fulfillOrders({
1734
- fulfillOrderDetails,
1735
- accountAddress: account,
1736
- });
1737
- const fulfillmentActions = [];
1738
- const approvalAction = seaportActions.find((action) => action.type === 'approval');
1739
- if (approvalAction) {
1740
- fulfillmentActions.push({
1741
- type: ActionType.TRANSACTION,
1742
- buildTransaction: prepareTransaction(approvalAction.transactionMethods, (await this.provider.getNetwork()).chainId, account),
1743
- purpose: TransactionPurpose.APPROVAL,
1744
- });
1745
- }
1746
- const fulfilOrderAction = seaportActions.find((action) => action.type === 'exchange');
1747
- if (!fulfilOrderAction) {
1748
- throw new Error('No exchange action found');
1749
- }
1750
- fulfillmentActions.push({
1751
- type: ActionType.TRANSACTION,
1752
- buildTransaction: prepareTransaction(fulfilOrderAction.transactionMethods, (await this.provider.getNetwork()).chainId, account),
1753
- purpose: TransactionPurpose.FULFILL_ORDER,
1754
- });
1755
- return {
1756
- actions: fulfillmentActions,
1757
- // return the shortest expiration out of all extraData - they should be very close
1758
- expiration: fulfillOrderDetails
1759
- .map((d) => Seaport.getExpirationISOTimeFromExtraData(d.extraData))
1760
- .reduce((p, c) => (new Date(p) < new Date(c) ? p : c)),
1761
- };
1762
- }
1763
- async cancelOrders(orders, account) {
1764
- const orderComponents = orders.map((order) => mapImmutableOrderToSeaportOrderComponents(order).orderComponents);
1765
- const seaportLib = this.getSeaportLib(orders[0]);
1766
- const cancellationTransaction = await seaportLib.cancelOrders(orderComponents, account);
1767
- return {
1768
- type: ActionType.TRANSACTION,
1769
- buildTransaction: prepareTransaction(cancellationTransaction, (await this.provider.getNetwork()).chainId, account),
1770
- purpose: TransactionPurpose.CANCEL,
1771
- };
1772
- }
1773
- createSeaportOrders(offerer, orderInputs) {
1774
- const seaportLib = this.getSeaportLib();
1775
- return seaportLib.createBulkOrders(orderInputs.map((orderInput) => {
1776
- const { listingItem, considerationItem, orderStart, orderExpiry, } = orderInput;
1777
- const offerItem = listingItem.type === 'ERC721'
1778
- ? {
1779
- itemType: ItemType.ERC721,
1780
- token: listingItem.contractAddress,
1781
- identifier: listingItem.tokenId,
1782
- }
1783
- : {
1784
- itemType: ItemType.ERC1155,
1785
- token: listingItem.contractAddress,
1786
- identifier: listingItem.tokenId,
1787
- amount: listingItem.amount,
1788
- };
1789
- return {
1790
- allowPartialFills: listingItem.type === 'ERC1155',
1791
- offer: [offerItem],
1792
- consideration: [
1793
- {
1794
- token: considerationItem.type === 'ERC20' ? considerationItem.contractAddress : undefined,
1795
- amount: considerationItem.amount,
1796
- recipient: offerer,
1797
- },
1798
- ],
1799
- startTime: (orderStart.getTime() / 1000).toFixed(0),
1800
- endTime: (orderExpiry.getTime() / 1000).toFixed(0),
1801
- zone: this.zoneContractAddress,
1802
- restrictedByZone: true,
1803
- };
1804
- }), offerer);
1805
- }
1806
- createSeaportOrder(offerer, listingItem, considerationItem, orderStart, orderExpiry) {
1807
- const seaportLib = this.getSeaportLib();
1808
- const offerItem = listingItem.type === 'ERC721'
1809
- ? {
1810
- itemType: ItemType.ERC721,
1811
- token: listingItem.contractAddress,
1812
- identifier: listingItem.tokenId,
1813
- }
1814
- : {
1815
- itemType: ItemType.ERC1155,
1816
- token: listingItem.contractAddress,
1817
- identifier: listingItem.tokenId,
1818
- amount: listingItem.amount,
1819
- };
1820
- return seaportLib.createOrder({
1821
- allowPartialFills: listingItem.type === 'ERC1155',
1822
- offer: [offerItem],
1823
- consideration: [
1824
- {
1825
- token: considerationItem.type === 'ERC20' ? considerationItem.contractAddress : undefined,
1826
- amount: considerationItem.amount,
1827
- recipient: offerer,
1828
- },
1829
- ],
1830
- startTime: (orderStart.getTime() / 1000).toFixed(0),
1831
- endTime: (orderExpiry.getTime() / 1000).toFixed(0),
1832
- zone: this.zoneContractAddress,
1833
- restrictedByZone: true,
1834
- }, offerer);
1835
- }
1836
- // Types and value are JSON parsed from the seaport-js string, so the types are
1837
- // reflected as any
1838
- async getTypedDataFromBulkOrderComponents(types, value) {
1839
- // We must remove EIP712Domain from the types object
1840
- // eslint-disable-next-line no-param-reassign
1841
- delete types.EIP712Domain;
1842
- const { chainId } = await this.provider.getNetwork();
1843
- const domainData = {
1844
- name: SEAPORT_CONTRACT_NAME,
1845
- version: SEAPORT_CONTRACT_VERSION_V1_5,
1846
- chainId,
1847
- verifyingContract: this.seaportContractAddress,
1848
- };
1849
- return {
1850
- domain: domainData,
1851
- types,
1852
- value,
1853
- };
1854
- }
1855
- async getTypedDataFromOrderComponents(orderComponents) {
1856
- const { chainId } = await this.provider.getNetwork();
1857
- const domainData = {
1858
- name: SEAPORT_CONTRACT_NAME,
1859
- version: SEAPORT_CONTRACT_VERSION_V1_5,
1860
- chainId,
1861
- verifyingContract: this.seaportContractAddress,
1862
- };
1863
- return {
1864
- domain: domainData,
1865
- types: EIP_712_ORDER_TYPE,
1866
- value: orderComponents,
1867
- };
1868
- }
1869
- getSeaportLib(order) {
1870
- const seaportAddress = order?.protocol_data?.seaport_address ?? this.seaportContractAddress;
1871
- return this.seaportLibFactory.create(seaportAddress, this.rateLimitingKey);
1872
- }
1873
- static getExpirationISOTimeFromExtraData(extraData) {
1874
- // Expirtaion bytes in SIP7 extra data [21:29]
1875
- // In hex string -> [21 * 2 + 2 (0x) : 29 * 2]
1876
- // In JS slice (start, end_inclusive), (44,60)
1877
- // 8 bytes uint64 epoch time in seconds
1878
- const expirationHex = extraData.slice(44, 60);
1879
- const expirationInSeconds = parseInt(expirationHex, 16);
1880
- return new Date(expirationInSeconds * 1000).toISOString();
1881
- }
1882
- }
1883
-
1884
- class ImmutableApiClient {
1885
- orderbookService;
1886
- chainName;
1887
- seaportAddress;
1888
- constructor(orderbookService, chainName, seaportAddress) {
1889
- this.orderbookService = orderbookService;
1890
- this.chainName = chainName;
1891
- this.seaportAddress = seaportAddress;
1892
- }
1893
- async fulfillmentData(requests) {
1894
- return this.orderbookService.fulfillmentData({
1895
- chainName: this.chainName,
1896
- requestBody: requests,
1897
- });
1898
- }
1899
- async getListing(listingId) {
1900
- return this.orderbookService.getListing({
1901
- chainName: this.chainName,
1902
- listingId,
1903
- });
1904
- }
1905
- async getTrade(tradeId) {
1906
- return this.orderbookService.getTrade({
1907
- chainName: this.chainName,
1908
- tradeId,
1909
- });
1910
- }
1911
- async listListings(listOrderParams) {
1912
- return this.orderbookService.listListings({
1913
- chainName: this.chainName,
1914
- ...listOrderParams,
1915
- });
1916
- }
1917
- async listTrades(listTradesParams) {
1918
- return this.orderbookService.listTrades({
1919
- chainName: this.chainName,
1920
- ...listTradesParams,
1921
- });
1922
- }
1923
- async cancelOrders(orderIds, accountAddress, signature) {
1924
- return this.orderbookService.cancelOrders({
1925
- chainName: this.chainName,
1926
- requestBody: {
1927
- account_address: accountAddress,
1928
- orders: orderIds,
1929
- signature,
1930
- },
1931
- });
1932
- }
1933
- async createListing({ orderHash, orderComponents, orderSignature, makerFees, }) {
1934
- if (orderComponents.offer.length !== 1) {
1935
- throw new Error('Only one item can be listed at a time');
1936
- }
1937
- if (Number(orderComponents.offer[0].itemType) !== ItemType.ERC721
1938
- && Number(orderComponents.offer[0].itemType) !== ItemType.ERC1155) {
1939
- throw new Error('Only ERC721 / ERC1155 tokens can be listed');
1940
- }
1941
- const orderTypes = [
1942
- ...orderComponents.consideration.map((c) => c.itemType),
1943
- ];
1944
- const isSameConsiderationType = new Set(orderTypes).size === 1;
1945
- if (!isSameConsiderationType) {
1946
- throw new Error('All consideration items must be of the same type');
1947
- }
1948
- return this.orderbookService.createListing({
1949
- chainName: this.chainName,
1950
- requestBody: {
1951
- account_address: orderComponents.offerer,
1952
- buy: [
1953
- {
1954
- type: Number(orderComponents.consideration[0].itemType)
1955
- === ItemType.NATIVE
1956
- ? 'NATIVE'
1957
- : 'ERC20',
1958
- amount: orderComponents.consideration[0].startAmount,
1959
- contract_address: orderComponents.consideration[0].token,
1960
- },
1961
- ],
1962
- fees: makerFees.map((x) => ({
1963
- amount: x.amount,
1964
- type: FeeType.MAKER_ECOSYSTEM,
1965
- recipient_address: x.recipientAddress,
1966
- })),
1967
- end_at: new Date(parseInt(`${orderComponents.endTime.toString()}000`, 10)).toISOString(),
1968
- order_hash: orderHash,
1969
- protocol_data: {
1970
- order_type: Number(orderComponents.offer[0].itemType) === ItemType.ERC1155
1971
- ? ProtocolData.order_type.PARTIAL_RESTRICTED : ProtocolData.order_type.FULL_RESTRICTED,
1972
- zone_address: orderComponents.zone,
1973
- seaport_address: this.seaportAddress,
1974
- seaport_version: SEAPORT_CONTRACT_VERSION_V1_5,
1975
- counter: orderComponents.counter.toString(),
1976
- },
1977
- salt: orderComponents.salt,
1978
- sell: Number(orderComponents.offer[0].itemType) === ItemType.ERC1155
1979
- ? [{
1980
- contract_address: orderComponents.offer[0].token,
1981
- token_id: orderComponents.offer[0].identifierOrCriteria,
1982
- type: 'ERC1155',
1983
- amount: orderComponents.offer[0].startAmount,
1984
- }] : [{
1985
- contract_address: orderComponents.offer[0].token,
1986
- token_id: orderComponents.offer[0].identifierOrCriteria,
1987
- type: 'ERC721',
1988
- }],
1989
- signature: orderSignature,
1990
- start_at: new Date(parseInt(`${orderComponents.startTime.toString()}000`, 10)).toISOString(),
1991
- },
1992
- });
1993
- }
1994
- }
1995
-
1996
- class ImmutableApiClientFactory {
1997
- chainName;
1998
- seaportAddress;
1999
- orderbookClient;
2000
- constructor(apiEndpoint, chainName, seaportAddress, rateLimitingKey) {
2001
- this.chainName = chainName;
2002
- this.seaportAddress = seaportAddress;
2003
- this.orderbookClient = new OrderBookClient({
2004
- // eslint-disable-next-line @typescript-eslint/naming-convention
2005
- BASE: apiEndpoint,
2006
- // eslint-disable-next-line @typescript-eslint/naming-convention
2007
- HEADERS: rateLimitingKey ? {
2008
- // eslint-disable-next-line @typescript-eslint/naming-convention
2009
- 'x-api-key': rateLimitingKey,
2010
- } : undefined,
2011
- });
2012
- }
2013
- create() {
2014
- return new ImmutableApiClient(this.orderbookClient.orders, this.chainName, this.seaportAddress);
2015
- }
2016
- }
2017
-
2018
- const TESTNET_CHAIN_NAME = 'imtbl-zkevm-testnet';
2019
- const MAINNET_CHAIN_NAME = 'imtbl-zkevm-mainnet';
2020
- function getConfiguredProvider(url, rateLimitingKey) {
2021
- return new providers.JsonRpcProvider({
2022
- url,
2023
- headers: rateLimitingKey ? {
2024
- // eslint-disable-next-line @typescript-eslint/naming-convention
2025
- 'x-api-key': rateLimitingKey,
2026
- } : undefined,
2027
- });
2028
- }
2029
- function getOrderbookConfig(config) {
2030
- switch (config.baseConfig.environment) {
2031
- case Environment.SANDBOX:
2032
- return {
2033
- seaportContractAddress: '0x7d117aA8BD6D31c4fa91722f246388f38ab1942c',
2034
- zoneContractAddress: '0x1004f9615E79462c711Ff05a386BdbA91a7628C3',
2035
- apiEndpoint: 'https://api.sandbox.immutable.com',
2036
- chainName: TESTNET_CHAIN_NAME,
2037
- provider: getConfiguredProvider('https://rpc.testnet.immutable.com', config.baseConfig.rateLimitingKey),
2038
- };
2039
- // not yet deployed
2040
- case Environment.PRODUCTION:
2041
- return {
2042
- seaportContractAddress: '0x6c12aD6F0bD274191075Eb2E78D7dA5ba6453424',
2043
- zoneContractAddress: '0x1004f9615E79462c711Ff05a386BdbA91a7628C3',
2044
- apiEndpoint: 'https://api.immutable.com',
2045
- chainName: MAINNET_CHAIN_NAME,
2046
- provider: getConfiguredProvider('https://rpc.immutable.com', config.baseConfig.rateLimitingKey),
2047
- };
2048
- default:
2049
- return null;
2050
- }
2051
- }
2052
-
2053
- // The order book module only supports V5 JsonRpcProviders. These are instantiated
2054
- // by the environment or by providing an RPC URL override. For this reason we can
2055
- // safely instantiate a V6 provider for the V5 provider URL.
2056
- function convertToV6Provider(provider, rateLimitingKey) {
2057
- const fetch = new FetchRequest(provider.connection.url);
2058
- if (rateLimitingKey) {
2059
- fetch.setHeader('x-api-key', rateLimitingKey);
2060
- }
2061
- const overwrittenProvider = new JsonRpcProvider(fetch);
2062
- // Need to override the getSigner method to mimic V5 behaviour
2063
- overwrittenProvider.getSigner = async function getSigner(address) {
2064
- if (address == null) {
2065
- // eslint-disable-next-line no-param-reassign
2066
- address = 0;
2067
- }
2068
- const accountsPromise = this.send('eth_accounts', []);
2069
- // Account index
2070
- if (typeof (address) === 'number') {
2071
- const accounts = (await accountsPromise);
2072
- if (address >= accounts.length) {
2073
- throw new Error('no such account');
2074
- }
2075
- return new JsonRpcSigner(this, accounts[address]);
2076
- }
2077
- // Account address
2078
- // This is where the override comes in to effect. We explicitly do not confirm if the
2079
- // provider has access to the address as a signer.
2080
- return new JsonRpcSigner(this, address);
2081
- };
2082
- return overwrittenProvider;
2083
- }
2084
- class SeaportLibFactory {
2085
- defaultSeaportContractAddress;
2086
- provider;
2087
- constructor(defaultSeaportContractAddress, provider) {
2088
- this.defaultSeaportContractAddress = defaultSeaportContractAddress;
2089
- this.provider = provider;
2090
- }
2091
- create(orderSeaportAddress, rateLimitingKey) {
2092
- const seaportContractAddress = orderSeaportAddress ?? this.defaultSeaportContractAddress;
2093
- return new Seaport$1(convertToV6Provider(this.provider, rateLimitingKey), {
2094
- balanceAndApprovalChecksOnOrderCreation: true,
2095
- overrides: {
2096
- contractAddress: seaportContractAddress,
2097
- },
2098
- });
2099
- }
2100
- }
2101
-
2102
- /**
2103
- * zkEVM orderbook SDK
2104
- * @constructor
2105
- * @param {OrderbookModuleConfiguration} config - Configuration for Immutable services.
2106
- */
2107
- class Orderbook {
2108
- apiClient;
2109
- seaport;
2110
- orderbookConfig;
2111
- constructor(config) {
2112
- const obConfig = getOrderbookConfig(config);
2113
- const finalConfig = {
2114
- ...obConfig,
2115
- ...config.overrides,
2116
- };
2117
- if (config.overrides?.jsonRpcProviderUrl) {
2118
- finalConfig.provider = getConfiguredProvider(config.overrides?.jsonRpcProviderUrl, config.baseConfig.rateLimitingKey);
2119
- }
2120
- if (!finalConfig) {
2121
- throw new Error('Orderbook configuration not passed, please specify the environment under config.baseConfig.environment');
2122
- }
2123
- this.orderbookConfig = finalConfig;
2124
- const { apiEndpoint, chainName } = this.orderbookConfig;
2125
- if (!apiEndpoint) {
2126
- throw new Error('API endpoint must be provided');
2127
- }
2128
- this.apiClient = new ImmutableApiClientFactory(apiEndpoint, chainName, this.orderbookConfig.seaportContractAddress, config.baseConfig.rateLimitingKey).create();
2129
- const seaportLibFactory = new SeaportLibFactory(this.orderbookConfig.seaportContractAddress, this.orderbookConfig.provider);
2130
- this.seaport = new Seaport(seaportLibFactory, this.orderbookConfig.provider, this.orderbookConfig.seaportContractAddress, this.orderbookConfig.zoneContractAddress, config.baseConfig.rateLimitingKey);
2131
- }
2132
- /**
2133
- * Return the configuration for the orderbook module.
2134
- * @return {OrderbookModuleConfiguration} The configuration for the orderbook module.
2135
- */
2136
- config() {
2137
- return this.orderbookConfig;
2138
- }
2139
- /**
2140
- * Get an order by ID
2141
- * @param {string} listingId - The listingId to find.
2142
- * @return {ListingResult} The returned order result.
2143
- */
2144
- async getListing(listingId) {
2145
- const apiListing = await this.apiClient.getListing(listingId);
2146
- return {
2147
- result: mapFromOpenApiOrder(apiListing.result),
2148
- };
2149
- }
2150
- /**
2151
- * Get a trade by ID
2152
- * @param {string} tradeId - The tradeId to find.
2153
- * @return {TradeResult} The returned order result.
2154
- */
2155
- async getTrade(tradeId) {
2156
- const apiListing = await this.apiClient.getTrade(tradeId);
2157
- return {
2158
- result: mapFromOpenApiTrade(apiListing.result),
2159
- };
2160
- }
2161
- /**
2162
- * List orders. This method is used to get a list of orders filtered by conditions specified
2163
- * in the params object.
2164
- * @param {ListListingsParams} listOrderParams - Filtering, ordering and page parameters.
2165
- * @return {ListListingsResult} The paged orders.
2166
- */
2167
- async listListings(listOrderParams) {
2168
- const apiListings = await this.apiClient.listListings(listOrderParams);
2169
- return {
2170
- page: mapFromOpenApiPage(apiListings.page),
2171
- result: apiListings.result.map(mapFromOpenApiOrder),
2172
- };
2173
- }
2174
- /**
2175
- * List trades. This method is used to get a list of trades filtered by conditions specified
2176
- * in the params object
2177
- * @param {ListTradesParams} listTradesParams - Filtering, ordering and page parameters.
2178
- * @return {ListTradesResult} The paged trades.
2179
- */
2180
- async listTrades(listTradesParams) {
2181
- const apiListings = await this.apiClient.listTrades(listTradesParams);
2182
- return {
2183
- page: mapFromOpenApiPage(apiListings.page),
2184
- result: apiListings.result.map(mapFromOpenApiTrade),
2185
- };
2186
- }
2187
- /**
2188
- * Get required transactions and messages for signing to facilitate creating bulk listings.
2189
- * Once the transactions are submitted and the message signed, call the completeListings method
2190
- * provided in the return type with the signature. This method supports up to 20 listing creations
2191
- * at a time. It can also be used for individual listings to simplify integration code paths.
2192
- * @param {PrepareBulkListingsParams} prepareBulkListingsParams - Details about the listings
2193
- * to be created.
2194
- * @return {PrepareBulkListingsResponse} PrepareListingResponse includes
2195
- * any unsigned approval transactions, the typed bulk order message for signing and
2196
- * the createListings method that can be called with the signature to create the listings.
2197
- */
2198
- async prepareBulkListings({ makerAddress, listingParams, }) {
2199
- // Limit bulk listing creation to 20 orders to prevent API and order evaluation spam
2200
- if (listingParams.length > 20) {
2201
- throw new Error('Bulk listing creation is limited to 20 orders');
2202
- }
2203
- // In the event of a single order, delegate to prepareListing as the signature is more
2204
- // gas efficient
2205
- if (listingParams.length === 1) {
2206
- const prepareListingResponse = await this.seaport.prepareSeaportOrder(makerAddress, listingParams[0].sell, listingParams[0].buy, new Date(), listingParams[0].orderExpiry || new Date(Date.now() + 1000 * 60 * 60 * 24 * 365 * 2));
2207
- return {
2208
- actions: prepareListingResponse.actions,
2209
- completeListings: async (signature) => {
2210
- const createListingResult = await this.createListing({
2211
- makerFees: listingParams[0].makerFees,
2212
- orderComponents: prepareListingResponse.orderComponents,
2213
- orderHash: prepareListingResponse.orderHash,
2214
- orderSignature: signature,
2215
- });
2216
- return {
2217
- result: [{
2218
- success: true,
2219
- orderHash: prepareListingResponse.orderHash,
2220
- order: createListingResult.result,
2221
- }],
2222
- };
2223
- },
2224
- };
2225
- }
2226
- const { actions, preparedListings } = await this.seaport.prepareBulkSeaportOrders(makerAddress, listingParams.map((orderParam) => ({
2227
- listingItem: orderParam.sell,
2228
- considerationItem: orderParam.buy,
2229
- orderStart: new Date(),
2230
- orderExpiry: orderParam.orderExpiry || new Date(Date.now() + 1000 * 60 * 60 * 24 * 365 * 2),
2231
- })));
2232
- return {
2233
- actions,
2234
- completeListings: async (bulkOrderSignature) => {
2235
- const orderComponents = preparedListings.map((orderParam) => orderParam.orderComponents);
2236
- const signatures = getBulkSeaportOrderSignatures(bulkOrderSignature, orderComponents);
2237
- const createOrdersApiListingResponse = await Promise.all(orderComponents.map((orderComponent, i) => {
2238
- const sig = signatures[i];
2239
- const listing = preparedListings[i];
2240
- const listingParam = listingParams[i];
2241
- return this.apiClient.createListing({
2242
- orderComponents: orderComponent,
2243
- orderHash: listing.orderHash,
2244
- orderSignature: sig,
2245
- makerFees: listingParam.makerFees,
2246
- // Swallow failed creations - this gets mapped in the response to the caller as failed
2247
- }).catch(() => undefined);
2248
- }));
2249
- return {
2250
- result: createOrdersApiListingResponse.map((apiListingResponse, i) => ({
2251
- success: !!apiListingResponse,
2252
- orderHash: preparedListings[i].orderHash,
2253
- order: apiListingResponse ? mapFromOpenApiOrder(apiListingResponse.result) : undefined,
2254
- })),
2255
- };
2256
- },
2257
- };
2258
- }
2259
- /**
2260
- * Get required transactions and messages for signing prior to creating a listing
2261
- * through the createListing method
2262
- * @param {PrepareListingParams} prepareListingParams - Details about the listing to be created.
2263
- * @return {PrepareListingResponse} PrepareListingResponse includes
2264
- * the unsigned approval transaction, the typed order message for signing and
2265
- * the order components that can be submitted to `createListing` with a signature.
2266
- */
2267
- async prepareListing({ makerAddress, sell, buy, orderExpiry, }) {
2268
- return this.seaport.prepareSeaportOrder(makerAddress, sell, buy,
2269
- // Default order start to now
2270
- new Date(),
2271
- // Default order expiry to 2 years from now
2272
- orderExpiry || new Date(Date.now() + 1000 * 60 * 60 * 24 * 365 * 2));
2273
- }
2274
- /**
2275
- * Create an order
2276
- * @param {CreateListingParams} createListingParams - create an order with the given params.
2277
- * @return {ListingResult} The result of the order created in the Immutable services.
2278
- */
2279
- async createListing(createListingParams) {
2280
- const apiListingResponse = await this.apiClient.createListing({
2281
- ...createListingParams,
2282
- });
2283
- return {
2284
- result: mapFromOpenApiOrder(apiListingResponse.result),
2285
- };
2286
- }
2287
- /**
2288
- * Get unsigned transactions that can be submitted to fulfil an open order. If the approval
2289
- * transaction exists it must be signed and submitted to the chain before the fulfilment
2290
- * transaction can be submitted or it will be reverted.
2291
- * @param {string} listingId - The listingId to fulfil.
2292
- * @param {string} takerAddress - The address of the account fulfilling the order.
2293
- * @param {FeeValue[]} takerFees - Taker ecosystem fees to be paid.
2294
- * @param {string} amountToFill - Amount of the order to fill, defaults to sell item amount.
2295
- * Only applies to ERC1155 orders
2296
- * @return {FulfillOrderResponse} Approval and fulfilment transactions.
2297
- */
2298
- async fulfillOrder(listingId, takerAddress, takerFees, amountToFill) {
2299
- const fulfillmentDataRes = await this.apiClient.fulfillmentData([
2300
- {
2301
- order_id: listingId,
2302
- taker_address: takerAddress,
2303
- fees: takerFees.map((fee) => ({
2304
- amount: fee.amount,
2305
- type: FeeType.TAKER_ECOSYSTEM,
2306
- recipient_address: fee.recipientAddress,
2307
- })),
2308
- },
2309
- ]);
2310
- if (fulfillmentDataRes.result.unfulfillable_orders?.length > 0) {
2311
- throw new Error(`Unable to prepare fulfillment date: ${fulfillmentDataRes.result.unfulfillable_orders[0].reason}`);
2312
- }
2313
- else if (fulfillmentDataRes.result.fulfillable_orders?.length !== 1) {
2314
- throw new Error('unexpected fulfillable order result length');
2315
- }
2316
- const extraData = fulfillmentDataRes.result.fulfillable_orders[0].extra_data;
2317
- const orderResult = fulfillmentDataRes.result.fulfillable_orders[0].order;
2318
- if (orderResult.status.name !== OrderStatusName.ACTIVE) {
2319
- throw new Error(`Cannot fulfil order that is not active. Current status: ${orderResult.status}`);
2320
- }
2321
- return this.seaport.fulfillOrder(orderResult, takerAddress, extraData, amountToFill);
2322
- }
2323
- /**
2324
- * Get unsigned transactions that can be submitted to fulfil multiple open orders. If approval
2325
- * transactions exist, they must be signed and submitted to the chain before the fulfilment
2326
- * transaction can be submitted or it will be reverted.
2327
- * @param {Array<FulfillmentListing>} listings - The details of the listings to fulfil, amounts
2328
- * to fill and taker ecosystem fees to be paid.
2329
- * @param {string} takerAddress - The address of the account fulfilling the order.
2330
- * @return {FulfillBulkOrdersResponse} Approval and fulfilment transactions.
2331
- */
2332
- async fulfillBulkOrders(listings, takerAddress) {
2333
- const fulfillmentDataRes = await this.apiClient.fulfillmentData(listings.map((listingRequest) => ({
2334
- order_id: listingRequest.listingId,
2335
- taker_address: takerAddress,
2336
- fees: listingRequest.takerFees.map((fee) => ({
2337
- amount: fee.amount,
2338
- type: FeeType.TAKER_ECOSYSTEM,
2339
- recipient_address: fee.recipientAddress,
2340
- })),
2341
- })));
2342
- try {
2343
- const fulfillableOrdersWithUnits = fulfillmentDataRes.result.fulfillable_orders
2344
- .map((fulfillmentData) => {
2345
- // Find the listing that corresponds to the order for the units
2346
- const listing = listings.find((l) => l.listingId === fulfillmentData.order.id);
2347
- if (!listing) {
2348
- throw new Error(`Could not find listing for order ${fulfillmentData.order.id}`);
2349
- }
2350
- return {
2351
- extraData: fulfillmentData.extra_data,
2352
- order: fulfillmentData.order,
2353
- unitsToFill: listing.amountToFill,
2354
- };
2355
- });
2356
- return {
2357
- ...(await this.seaport.fulfillBulkOrders(fulfillableOrdersWithUnits, takerAddress)),
2358
- fulfillableOrders: fulfillmentDataRes.result.fulfillable_orders.map((o) => mapFromOpenApiOrder(o.order)),
2359
- unfulfillableOrders: fulfillmentDataRes.result.unfulfillable_orders.map((o) => ({
2360
- orderId: o.order_id,
2361
- reason: o.reason,
2362
- })),
2363
- sufficientBalance: true,
2364
- };
2365
- }
2366
- catch (e) {
2367
- // if insufficient balance error, we return FulfillBulkOrdersInsufficientBalanceResponse
2368
- if (String(e).includes('The fulfiller does not have the balances needed to fulfill.')) {
2369
- return {
2370
- fulfillableOrders: fulfillmentDataRes.result.fulfillable_orders.map((o) => mapFromOpenApiOrder(o.order)),
2371
- unfulfillableOrders: fulfillmentDataRes.result.unfulfillable_orders.map((o) => ({
2372
- orderId: o.order_id,
2373
- reason: o.reason,
2374
- })),
2375
- sufficientBalance: false,
2376
- };
2377
- }
2378
- // if some other error is thrown,
2379
- // there likely is a race condition of the original order validity
2380
- // we throw the error back out
2381
- throw e;
2382
- }
2383
- }
2384
- /**
2385
- * Cancelling orders is a gasless alternative to on-chain cancellation exposed with
2386
- * `cancelOrdersOnChain`. For the orderbook to authenticate the cancellation, the creator
2387
- * of the orders must sign an EIP712 message containing the orderIds
2388
- * @param {string} orderIds - The orderIds to attempt to cancel.
2389
- * @return {PrepareCancelOrdersResponse} The signable action to cancel the orders.
2390
- */
2391
- async prepareOrderCancellations(orderIds) {
2392
- const network = await this.orderbookConfig.provider.getNetwork();
2393
- const domain = {
2394
- name: 'imtbl-order-book',
2395
- chainId: network.chainId,
2396
- verifyingContract: this.orderbookConfig.seaportContractAddress,
2397
- };
2398
- const types = {
2399
- // eslint-disable-next-line @typescript-eslint/naming-convention
2400
- CancelPayload: [
2401
- { name: 'orders', type: 'Order[]' },
2402
- ],
2403
- // eslint-disable-next-line @typescript-eslint/naming-convention
2404
- Order: [
2405
- { name: 'id', type: 'string' },
2406
- ],
2407
- };
2408
- const cancelMessage = {
2409
- orders: orderIds.map((id) => ({ id })),
2410
- };
2411
- return {
2412
- signableAction: {
2413
- purpose: SignablePurpose.OFF_CHAIN_CANCELLATION,
2414
- type: ActionType.SIGNABLE,
2415
- message: {
2416
- domain,
2417
- types,
2418
- value: cancelMessage,
2419
- },
2420
- },
2421
- };
2422
- }
2423
- /**
2424
- * Cancelling orders is a gasless alternative to on-chain cancellation exposed with
2425
- * `cancelOrdersOnChain`. Orders cancelled this way cannot be fulfilled and will be removed
2426
- * from the orderbook. If there is pending fulfillment data outstanding for the order, its
2427
- * cancellation will be pending until the fulfillment window has passed.
2428
- * `prepareOffchainOrderCancellations` can be used to get the signable action that is signed
2429
- * to get the signature required for this call.
2430
- * @param {string[]} orderIds - The orderIds to attempt to cancel.
2431
- * @param {string} accountAddress - The address of the account cancelling the orders.
2432
- * @param {string} accountAddress - The address of the account cancelling the orders.
2433
- * @return {CancelOrdersResult} The result of the off-chain cancellation request
2434
- */
2435
- async cancelOrders(orderIds, accountAddress, signature) {
2436
- return this.apiClient.cancelOrders(orderIds, accountAddress, signature);
2437
- }
2438
- /**
2439
- * Get an unsigned order cancellation transaction. Orders can only be cancelled by
2440
- * the account that created them. All of the orders must be from the same seaport contract.
2441
- * If trying to cancel orders from multiple seaport contracts, group the orderIds by seaport
2442
- * contract and call this method for each group.
2443
- * @param {string[]} orderIds - The orderIds to cancel.
2444
- * @param {string} accountAddress - The address of the account cancelling the order.
2445
- * @return {CancelOrdersOnChainResponse} The unsigned cancel order action
2446
- */
2447
- async cancelOrdersOnChain(orderIds, accountAddress) {
2448
- const orderResults = await Promise.all(orderIds.map((id) => this.apiClient.getListing(id)));
2449
- // eslint-disable-next-line no-restricted-syntax
2450
- for (const orderResult of orderResults) {
2451
- if (orderResult.result.status.name !== OrderStatusName.ACTIVE
2452
- && orderResult.result.status.name !== OrderStatusName.INACTIVE
2453
- && orderResult.result.status.name !== OrderStatusName.PENDING) {
2454
- throw new Error(`Cannot cancel order with status ${orderResult.result.status}`);
2455
- }
2456
- if (orderResult.result.account_address !== accountAddress.toLowerCase()) {
2457
- throw new Error(`Only account ${orderResult.result.account_address} can cancel order ${orderResult.result.id}`);
2458
- }
2459
- }
2460
- const orders = orderResults.map((orderResult) => orderResult.result);
2461
- const seaportAddresses = orders.map((o) => o.protocol_data.seaport_address);
2462
- const distinctSeaportAddresses = new Set(...[seaportAddresses]);
2463
- if (distinctSeaportAddresses.size !== 1) {
2464
- throw new Error('Cannot cancel multiple orders from different seaport contracts. Please group your orderIds accordingly');
2465
- }
2466
- const cancellationAction = await this.seaport.cancelOrders(orders, accountAddress);
2467
- return { cancellationAction };
2468
- }
2469
- }
2470
-
2471
- // Consumers might want an estimated gas limit for fulfilling an order
2472
- // without calling the transaction builder. This is an estimate that
2473
- // should work for all fulfillment scenarios.
2474
- const ESTIMATED_FULFILLMENT_GAS_GWEI = 400000;
2475
- const constants = {
2476
- estimatedFulfillmentGasGwei: ESTIMATED_FULFILLMENT_GAS_GWEI,
2477
- };
2478
-
2479
- export { ActionType, FeeType, OrderStatusName, Orderbook, SignablePurpose, TransactionPurpose, constants };
1
+ export{A as ActionType,F as FeeType,O as OrderStatusName,a as Orderbook,S as SignablePurpose,T as TransactionPurpose,c as constants}from"./index-e7002486.js";import"axios";import"form-data";import"ethers";import"ethers-v6";import"merkletreejs";import"./index-14aad537.js";import"lru-memorise";import"global-const";import"@opensea/seaport-js";