@opensea/cli 0.3.0 → 0.4.1

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.
package/dist/index.js CHANGED
@@ -1,18 +1,15 @@
1
1
  // src/client.ts
2
2
  var DEFAULT_BASE_URL = "https://api.opensea.io";
3
- var DEFAULT_GRAPHQL_URL = "https://gql.opensea.io/graphql";
4
3
  var DEFAULT_TIMEOUT_MS = 3e4;
5
4
  var OpenSeaClient = class {
6
5
  apiKey;
7
6
  baseUrl;
8
- graphqlUrl;
9
7
  defaultChain;
10
8
  timeoutMs;
11
9
  verbose;
12
10
  constructor(config) {
13
11
  this.apiKey = config.apiKey;
14
12
  this.baseUrl = config.baseUrl ?? DEFAULT_BASE_URL;
15
- this.graphqlUrl = config.graphqlUrl ?? DEFAULT_GRAPHQL_URL;
16
13
  this.defaultChain = config.chain ?? "ethereum";
17
14
  this.timeoutMs = config.timeout ?? DEFAULT_TIMEOUT_MS;
18
15
  this.verbose = config.verbose ?? false;
@@ -80,40 +77,6 @@ var OpenSeaClient = class {
80
77
  }
81
78
  return response.json();
82
79
  }
83
- async graphql(query, variables) {
84
- if (this.verbose) {
85
- console.error(`[verbose] POST ${this.graphqlUrl}`);
86
- }
87
- const response = await fetch(this.graphqlUrl, {
88
- method: "POST",
89
- headers: {
90
- "Content-Type": "application/json",
91
- Accept: "application/json",
92
- "x-api-key": this.apiKey
93
- },
94
- body: JSON.stringify({ query, variables }),
95
- signal: AbortSignal.timeout(this.timeoutMs)
96
- });
97
- if (this.verbose) {
98
- console.error(`[verbose] ${response.status} ${response.statusText}`);
99
- }
100
- if (!response.ok) {
101
- const body = await response.text();
102
- throw new OpenSeaAPIError(response.status, body, "graphql");
103
- }
104
- const json = await response.json();
105
- if (json.errors?.length) {
106
- throw new OpenSeaAPIError(
107
- 400,
108
- json.errors.map((e) => e.message).join("; "),
109
- "graphql"
110
- );
111
- }
112
- if (!json.data) {
113
- throw new OpenSeaAPIError(500, "GraphQL response missing data", "graphql");
114
- }
115
- return json.data;
116
- }
117
80
  getDefaultChain() {
118
81
  return this.defaultChain;
119
82
  }
@@ -128,98 +91,320 @@ var OpenSeaAPIError = class extends Error {
128
91
  }
129
92
  };
130
93
 
131
- // src/queries.ts
132
- var SEARCH_COLLECTIONS_QUERY = `
133
- query SearchCollections($query: String!, $limit: Int, $chains: [ChainIdentifier!]) {
134
- collectionsByQuery(query: $query, limit: $limit, chains: $chains) {
135
- slug
136
- name
137
- description
138
- imageUrl
139
- chain {
140
- identifier
141
- name
94
+ // src/toon.ts
95
+ var INDENT = " ";
96
+ var NUMERIC_RE = /^-?\d+(?:\.\d+)?(?:e[+-]?\d+)?$/i;
97
+ var LEADING_ZERO_RE = /^0\d+$/;
98
+ var UNQUOTED_KEY_RE = /^[A-Za-z_][A-Za-z0-9_.]*$/;
99
+ function escapeString(s) {
100
+ return s.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t");
101
+ }
102
+ function needsQuoting(value, delimiter) {
103
+ if (value === "") return true;
104
+ if (value !== value.trim()) return true;
105
+ if (value === "true" || value === "false" || value === "null") return true;
106
+ if (NUMERIC_RE.test(value) || LEADING_ZERO_RE.test(value)) return true;
107
+ if (/[:"\\[\]{}]/.test(value)) return true;
108
+ if (/[\n\r\t]/.test(value)) return true;
109
+ if (value.includes(delimiter)) return true;
110
+ if (value.startsWith("-")) return true;
111
+ return false;
112
+ }
113
+ function encodeKey(key) {
114
+ if (UNQUOTED_KEY_RE.test(key)) return key;
115
+ return `"${escapeString(key)}"`;
116
+ }
117
+ function encodePrimitive(value, delimiter) {
118
+ if (value === null) return "null";
119
+ if (value === void 0) return "null";
120
+ if (typeof value === "boolean") return String(value);
121
+ if (typeof value === "number") return String(value);
122
+ if (typeof value === "string") {
123
+ if (needsQuoting(value, delimiter)) {
124
+ return `"${escapeString(value)}"`;
142
125
  }
143
- stats {
144
- totalSupply
145
- ownerCount
146
- volume {
147
- usd
148
- }
149
- sales
126
+ return value;
127
+ }
128
+ return `"${escapeString(String(value))}"`;
129
+ }
130
+ function isPrimitive(value) {
131
+ return value === null || value === void 0 || typeof value === "boolean" || typeof value === "number" || typeof value === "string";
132
+ }
133
+ function isTabular(arr) {
134
+ if (arr.length === 0) return false;
135
+ const first = arr[0];
136
+ if (first === null || typeof first !== "object" || Array.isArray(first))
137
+ return false;
138
+ const keys = Object.keys(first).sort();
139
+ for (const item of arr) {
140
+ if (item === null || typeof item !== "object" || Array.isArray(item))
141
+ return false;
142
+ const itemKeys = Object.keys(item).sort();
143
+ if (itemKeys.length !== keys.length) return false;
144
+ for (let i = 0; i < keys.length; i++) {
145
+ if (itemKeys[i] !== keys[i]) return false;
150
146
  }
151
- floorPrice {
152
- pricePerItem {
153
- usd
154
- native {
155
- unit
156
- symbol
157
- }
158
- }
147
+ for (const k of keys) {
148
+ if (!isPrimitive(item[k])) return false;
159
149
  }
160
150
  }
161
- }`;
162
- var SEARCH_NFTS_QUERY = `
163
- query SearchItems($query: String!, $collectionSlug: String, $limit: Int, $chains: [ChainIdentifier!]) {
164
- itemsByQuery(query: $query, collectionSlug: $collectionSlug, limit: $limit, chains: $chains) {
165
- tokenId
166
- name
167
- description
168
- imageUrl
169
- contractAddress
170
- collection {
171
- slug
172
- name
151
+ return true;
152
+ }
153
+ function isPrimitiveArray(arr) {
154
+ return arr.every(isPrimitive);
155
+ }
156
+ function encodeValue(value, depth, delimiter) {
157
+ if (isPrimitive(value)) {
158
+ return encodePrimitive(value, delimiter);
159
+ }
160
+ if (Array.isArray(value)) {
161
+ return encodeArray(value, depth, delimiter);
162
+ }
163
+ if (typeof value === "object" && value !== null) {
164
+ return encodeObject(value, depth, delimiter);
165
+ }
166
+ return encodePrimitive(value, delimiter);
167
+ }
168
+ function encodeObject(obj, depth, delimiter) {
169
+ const entries = Object.entries(obj);
170
+ if (entries.length === 0) return "";
171
+ const lines = [];
172
+ const prefix = INDENT.repeat(depth);
173
+ for (const [key, value] of entries) {
174
+ const encodedKey = encodeKey(key);
175
+ if (isPrimitive(value)) {
176
+ lines.push(`${prefix}${encodedKey}: ${encodePrimitive(value, delimiter)}`);
177
+ } else if (Array.isArray(value)) {
178
+ lines.push(encodeArrayField(encodedKey, value, depth, delimiter));
179
+ } else if (typeof value === "object" && value !== null) {
180
+ const nested = value;
181
+ if (Object.keys(nested).length === 0) {
182
+ lines.push(`${prefix}${encodedKey}:`);
183
+ } else {
184
+ lines.push(`${prefix}${encodedKey}:`);
185
+ lines.push(encodeObject(nested, depth + 1, delimiter));
186
+ }
173
187
  }
174
- chain {
175
- identifier
176
- name
188
+ }
189
+ return lines.join("\n");
190
+ }
191
+ function encodeArrayField(encodedKey, arr, depth, delimiter) {
192
+ const prefix = INDENT.repeat(depth);
193
+ if (arr.length === 0) {
194
+ return `${prefix}${encodedKey}[0]:`;
195
+ }
196
+ if (isPrimitiveArray(arr)) {
197
+ const values = arr.map((v) => encodePrimitive(v, delimiter)).join(delimiter);
198
+ return `${prefix}${encodedKey}[${arr.length}]: ${values}`;
199
+ }
200
+ if (isTabular(arr)) {
201
+ const firstObj = arr[0];
202
+ const fields = Object.keys(firstObj);
203
+ const fieldHeader = fields.map(encodeKey).join(delimiter);
204
+ const lines = [];
205
+ lines.push(`${prefix}${encodedKey}[${arr.length}]{${fieldHeader}}:`);
206
+ const rowPrefix = INDENT.repeat(depth + 1);
207
+ for (const item of arr) {
208
+ const obj = item;
209
+ const row = fields.map((f) => encodePrimitive(obj[f], delimiter)).join(delimiter);
210
+ lines.push(`${rowPrefix}${row}`);
177
211
  }
178
- bestListing {
179
- pricePerItem {
180
- usd
181
- native {
182
- unit
183
- symbol
212
+ return lines.join("\n");
213
+ }
214
+ return encodeExpandedList(encodedKey, arr, depth, delimiter);
215
+ }
216
+ function encodeExpandedList(encodedKey, arr, depth, delimiter) {
217
+ const prefix = INDENT.repeat(depth);
218
+ const itemPrefix = INDENT.repeat(depth + 1);
219
+ const lines = [];
220
+ lines.push(`${prefix}${encodedKey}[${arr.length}]:`);
221
+ for (const item of arr) {
222
+ if (isPrimitive(item)) {
223
+ lines.push(`${itemPrefix}- ${encodePrimitive(item, delimiter)}`);
224
+ } else if (Array.isArray(item)) {
225
+ if (isPrimitiveArray(item)) {
226
+ const values = item.map((v) => encodePrimitive(v, delimiter)).join(delimiter);
227
+ lines.push(`${itemPrefix}- [${item.length}]: ${values}`);
228
+ } else {
229
+ lines.push(`${itemPrefix}- [${item.length}]:`);
230
+ for (const inner of item) {
231
+ lines.push(encodeValue(inner, depth + 2, delimiter));
232
+ }
233
+ }
234
+ } else if (typeof item === "object" && item !== null) {
235
+ const obj = item;
236
+ const entries = Object.entries(obj);
237
+ if (entries.length === 0) {
238
+ lines.push(`${itemPrefix}-`);
239
+ } else {
240
+ const [firstKey, firstValue] = entries[0];
241
+ const ek = encodeKey(firstKey);
242
+ if (Array.isArray(firstValue)) {
243
+ const arrayLine = encodeArrayField(ek, firstValue, 0, delimiter);
244
+ lines.push(`${itemPrefix}- ${arrayLine.trimStart()}`);
245
+ } else if (isPrimitive(firstValue)) {
246
+ lines.push(
247
+ `${itemPrefix}- ${ek}: ${encodePrimitive(firstValue, delimiter)}`
248
+ );
249
+ } else {
250
+ lines.push(`${itemPrefix}- ${ek}:`);
251
+ lines.push(
252
+ encodeObject(
253
+ firstValue,
254
+ depth + 2,
255
+ delimiter
256
+ )
257
+ );
258
+ }
259
+ for (let i = 1; i < entries.length; i++) {
260
+ const [k, v] = entries[i];
261
+ const encodedK = encodeKey(k);
262
+ if (isPrimitive(v)) {
263
+ lines.push(
264
+ `${INDENT.repeat(depth + 2)}${encodedK}: ${encodePrimitive(v, delimiter)}`
265
+ );
266
+ } else if (Array.isArray(v)) {
267
+ lines.push(encodeArrayField(encodedK, v, depth + 2, delimiter));
268
+ } else if (typeof v === "object" && v !== null) {
269
+ lines.push(`${INDENT.repeat(depth + 2)}${encodedK}:`);
270
+ lines.push(
271
+ encodeObject(v, depth + 3, delimiter)
272
+ );
273
+ }
184
274
  }
185
275
  }
186
- }
187
- owner {
188
- address
189
- displayName
190
276
  }
191
277
  }
192
- }`;
193
- var SEARCH_TOKENS_QUERY = `
194
- query SearchCurrencies($query: String!, $limit: Int, $chain: ChainIdentifier) {
195
- currenciesByQuery(query: $query, limit: $limit, chain: $chain, allowlistOnly: false) {
196
- name
197
- symbol
198
- imageUrl
199
- usdPrice
200
- contractAddress
201
- chain {
202
- identifier
203
- name
278
+ return lines.join("\n");
279
+ }
280
+ function encodeArray(arr, depth, delimiter) {
281
+ const prefix = INDENT.repeat(depth);
282
+ if (arr.length === 0) {
283
+ return `${prefix}[0]:`;
284
+ }
285
+ if (isPrimitiveArray(arr)) {
286
+ const values = arr.map((v) => encodePrimitive(v, delimiter)).join(delimiter);
287
+ return `${prefix}[${arr.length}]: ${values}`;
288
+ }
289
+ if (isTabular(arr)) {
290
+ const firstObj = arr[0];
291
+ const fields = Object.keys(firstObj);
292
+ const fieldHeader = fields.map(encodeKey).join(delimiter);
293
+ const lines2 = [];
294
+ lines2.push(`${prefix}[${arr.length}]{${fieldHeader}}:`);
295
+ const rowPrefix = INDENT.repeat(depth + 1);
296
+ for (const item of arr) {
297
+ const obj = item;
298
+ const row = fields.map((f) => encodePrimitive(obj[f], delimiter)).join(delimiter);
299
+ lines2.push(`${rowPrefix}${row}`);
204
300
  }
205
- stats {
206
- marketCapUsd
207
- oneDay {
208
- priceChange
209
- volume
301
+ return lines2.join("\n");
302
+ }
303
+ const lines = [];
304
+ lines.push(`${prefix}[${arr.length}]:`);
305
+ const itemPrefix = INDENT.repeat(depth + 1);
306
+ for (const item of arr) {
307
+ if (isPrimitive(item)) {
308
+ lines.push(`${itemPrefix}- ${encodePrimitive(item, delimiter)}`);
309
+ } else if (Array.isArray(item)) {
310
+ if (isPrimitiveArray(item)) {
311
+ const values = item.map((v) => encodePrimitive(v, delimiter)).join(delimiter);
312
+ lines.push(`${itemPrefix}- [${item.length}]: ${values}`);
313
+ } else {
314
+ lines.push(`${itemPrefix}- [${item.length}]:`);
315
+ }
316
+ } else if (typeof item === "object" && item !== null) {
317
+ const obj = item;
318
+ const entries = Object.entries(obj);
319
+ if (entries.length > 0) {
320
+ const [firstKey, firstValue] = entries[0];
321
+ const ek = encodeKey(firstKey);
322
+ if (isPrimitive(firstValue)) {
323
+ lines.push(
324
+ `${itemPrefix}- ${ek}: ${encodePrimitive(firstValue, delimiter)}`
325
+ );
326
+ } else {
327
+ lines.push(`${itemPrefix}- ${ek}:`);
328
+ lines.push(encodeValue(firstValue, depth + 2, delimiter));
329
+ }
330
+ for (let i = 1; i < entries.length; i++) {
331
+ const [k, v] = entries[i];
332
+ const encodedK = encodeKey(k);
333
+ if (isPrimitive(v)) {
334
+ lines.push(
335
+ `${INDENT.repeat(depth + 2)}${encodedK}: ${encodePrimitive(v, delimiter)}`
336
+ );
337
+ } else if (Array.isArray(v)) {
338
+ lines.push(encodeArrayField(encodedK, v, depth + 2, delimiter));
339
+ } else if (typeof v === "object" && v !== null) {
340
+ lines.push(`${INDENT.repeat(depth + 2)}${encodedK}:`);
341
+ lines.push(
342
+ encodeObject(v, depth + 3, delimiter)
343
+ );
344
+ }
345
+ }
210
346
  }
211
347
  }
212
348
  }
213
- }`;
214
- var SEARCH_ACCOUNTS_QUERY = `
215
- query SearchAccounts($query: String!, $limit: Int) {
216
- accountsByQuery(query: $query, limit: $limit) {
217
- address
218
- username
219
- imageUrl
220
- isVerified
349
+ return lines.join("\n");
350
+ }
351
+ function formatToon(data) {
352
+ if (isPrimitive(data)) {
353
+ return encodePrimitive(data, ",");
354
+ }
355
+ if (Array.isArray(data)) {
356
+ return encodeArray(data, 0, ",");
221
357
  }
222
- }`;
358
+ if (typeof data === "object" && data !== null) {
359
+ return encodeObject(data, 0, ",");
360
+ }
361
+ return String(data);
362
+ }
363
+
364
+ // src/output.ts
365
+ function formatOutput(data, format) {
366
+ if (format === "table") {
367
+ return formatTable(data);
368
+ }
369
+ if (format === "toon") {
370
+ return formatToon(data);
371
+ }
372
+ return JSON.stringify(data, null, 2);
373
+ }
374
+ function formatTable(data) {
375
+ if (Array.isArray(data)) {
376
+ if (data.length === 0) return "(empty)";
377
+ const keys = Object.keys(data[0]);
378
+ const widths = keys.map(
379
+ (key) => Math.max(
380
+ key.length,
381
+ ...data.map((row) => {
382
+ const val = row[key];
383
+ return String(val ?? "").length;
384
+ })
385
+ )
386
+ );
387
+ const header = keys.map((key, i) => key.padEnd(widths[i])).join(" ");
388
+ const separator = widths.map((w) => "-".repeat(w)).join(" ");
389
+ const rows = data.map(
390
+ (row) => keys.map((key, i) => {
391
+ const val = row[key];
392
+ return String(val ?? "").padEnd(widths[i]);
393
+ }).join(" ")
394
+ );
395
+ return [header, separator, ...rows].join("\n");
396
+ }
397
+ if (data && typeof data === "object") {
398
+ const entries = Object.entries(data);
399
+ if (entries.length === 0) return "(empty)";
400
+ const maxKeyLength = Math.max(...entries.map(([k]) => k.length));
401
+ return entries.map(([key, value]) => {
402
+ const displayValue = typeof value === "object" && value !== null ? JSON.stringify(value) : String(value ?? "");
403
+ return `${key.padEnd(maxKeyLength)} ${displayValue}`;
404
+ }).join("\n");
405
+ }
406
+ return String(data);
407
+ }
223
408
 
224
409
  // src/sdk.ts
225
410
  var OpenSeaCLI = class {
@@ -435,37 +620,13 @@ var SearchAPI = class {
435
620
  constructor(client) {
436
621
  this.client = client;
437
622
  }
438
- async collections(query, options) {
439
- const result = await this.client.graphql(SEARCH_COLLECTIONS_QUERY, {
440
- query,
441
- limit: options?.limit,
442
- chains: options?.chains
443
- });
444
- return result.collectionsByQuery;
445
- }
446
- async nfts(query, options) {
447
- const result = await this.client.graphql(SEARCH_NFTS_QUERY, {
448
- query,
449
- collectionSlug: options?.collection,
450
- limit: options?.limit,
451
- chains: options?.chains
452
- });
453
- return result.itemsByQuery;
454
- }
455
- async tokens(query, options) {
456
- const result = await this.client.graphql(SEARCH_TOKENS_QUERY, {
457
- query,
458
- limit: options?.limit,
459
- chain: options?.chain
460
- });
461
- return result.currenciesByQuery;
462
- }
463
- async accounts(query, options) {
464
- const result = await this.client.graphql(SEARCH_ACCOUNTS_QUERY, {
623
+ async query(query, options) {
624
+ return this.client.get("/api/v2/search", {
465
625
  query,
626
+ asset_types: options?.assetTypes?.join(","),
627
+ chains: options?.chains?.join(","),
466
628
  limit: options?.limit
467
629
  });
468
- return result.accountsByQuery;
469
630
  }
470
631
  };
471
632
  var SwapsAPI = class {
@@ -488,6 +649,8 @@ var SwapsAPI = class {
488
649
  export {
489
650
  OpenSeaAPIError,
490
651
  OpenSeaCLI,
491
- OpenSeaClient
652
+ OpenSeaClient,
653
+ formatOutput,
654
+ formatToon
492
655
  };
493
656
  //# sourceMappingURL=index.js.map