@eluvio/elv-client-js 3.2.4 → 3.2.7

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 (46) hide show
  1. package/dist/ElvClient-min.js +15 -11
  2. package/dist/ElvClient-node-min.js +17 -13
  3. package/dist/ElvFrameClient-min.js +12 -8
  4. package/dist/ElvPermissionsClient-min.js +13 -9
  5. package/dist/ElvWalletClient-min.js +58 -0
  6. package/dist/ElvWalletClient-node-min.js +78 -0
  7. package/dist/src/AuthorizationClient.js +2248 -1990
  8. package/dist/src/ContentObjectVerification.js +164 -173
  9. package/dist/src/Crypto.js +376 -324
  10. package/dist/src/ElvClient.js +1198 -1019
  11. package/dist/src/ElvWallet.js +119 -95
  12. package/dist/src/EthClient.js +1040 -896
  13. package/dist/src/FrameClient.js +331 -300
  14. package/dist/src/HttpClient.js +153 -147
  15. package/dist/src/Id.js +1 -3
  16. package/dist/src/PermissionsClient.js +1294 -1168
  17. package/dist/src/RemoteSigner.js +263 -211
  18. package/dist/src/UserProfileClient.js +1164 -1023
  19. package/dist/src/Utils.js +229 -184
  20. package/dist/src/client/ABRPublishing.js +895 -858
  21. package/dist/src/client/AccessGroups.js +1102 -959
  22. package/dist/src/client/ContentAccess.js +3724 -3431
  23. package/dist/src/client/ContentManagement.js +2252 -2068
  24. package/dist/src/client/Contracts.js +647 -563
  25. package/dist/src/client/Files.js +1886 -1757
  26. package/dist/src/client/NFT.js +126 -112
  27. package/dist/src/client/NTP.js +478 -422
  28. package/dist/src/index.js +11 -0
  29. package/dist/src/marketplaceClient/ClientMethods.js +1918 -0
  30. package/dist/src/marketplaceClient/Configuration.js +29 -0
  31. package/dist/src/marketplaceClient/Utils.js +304 -0
  32. package/dist/src/marketplaceClient/index.js +1553 -0
  33. package/dist/src/walletClient/ClientMethods.js +2080 -0
  34. package/dist/src/walletClient/Configuration.js +29 -0
  35. package/dist/src/walletClient/Utils.js +304 -0
  36. package/dist/src/walletClient/index.js +1770 -0
  37. package/package.json +8 -4
  38. package/src/ElvClient.js +5 -2
  39. package/src/Utils.js +22 -4
  40. package/src/index.js +7 -0
  41. package/src/walletClient/ClientMethods.js +1111 -0
  42. package/src/walletClient/Configuration.js +40 -0
  43. package/src/walletClient/README.md +191 -0
  44. package/src/walletClient/Utils.js +234 -0
  45. package/src/walletClient/index.js +977 -0
  46. package/testScripts/TestMarketplaceClient.js +25 -0
@@ -0,0 +1,1111 @@
1
+ const Utils = require("../Utils");
2
+ const UrlJoin = require("url-join");
3
+ const {FormatNFTDetails, FormatNFTMetadata, FormatNFT} = require("./Utils");
4
+
5
+ /**
6
+ * Methods
7
+ *
8
+ * @module ClientMethods
9
+ */
10
+
11
+ /* USER INFO */
12
+
13
+
14
+ /**
15
+ * <b><i>Requires login</i></b>
16
+ *
17
+ * Retrieve information about the user, including the address, wallet type, and (for custodial users) email address.
18
+ *
19
+ * @methodGroup User
20
+ *
21
+ * @returns {Object} - User info
22
+ */
23
+ exports.UserInfo = function() {
24
+ if(!this.loggedIn) { return; }
25
+
26
+ return {
27
+ name: this.__authorization.email || this.UserAddress(),
28
+ address: this.UserAddress() ,
29
+ email: this.__authorization.email,
30
+ walletType: this.__authorization.walletType,
31
+ walletName: this.__authorization.walletName
32
+ };
33
+ };
34
+
35
+ /**
36
+ * <b><i>Requires login</i></b>
37
+ *
38
+ * Retrieve the address of the current user.
39
+ *
40
+ * @methodGroup User
41
+ *
42
+ * @returns {string} - The address of the current user
43
+ */
44
+ exports.UserAddress = function() {
45
+ if(!this.loggedIn) { return; }
46
+
47
+ return this.client.utils.DecodeSignedToken(this.AuthToken()).payload.adr;
48
+ };
49
+
50
+ /**
51
+ * <b><i>Requires login</i></b>
52
+ *
53
+ * Retrieve the fund balances for the current user
54
+ *
55
+ * @methodGroup User
56
+ * @returns {Promise<{Object}>} - Returns balances for the user. All values are in USD.
57
+ * <ul>
58
+ * <li>- totalWalletBalance - Total balance of the users sales and wallet balance purchases</li>
59
+ * <li>- availableWalletBalance - Balance available for purchasing items</li>
60
+ * <li>- pendingWalletBalance - Balance unavailable for purchasing items</li>
61
+ * <li>- withdrawableWalletBalance - Amount that is available for withdrawal</li>
62
+ * <li>- usedBalance - <i>(Only included if user has set up Solana link with the Phantom wallet)</i> Available USDC balance of the user's Solana wallet</li>
63
+ * </ul>
64
+ */
65
+ exports.UserWalletBalance = async function(checkOnboard=false) {
66
+ if(!this.loggedIn) { return; }
67
+
68
+ // eslint-disable-next-line no-unused-vars
69
+ const { balance, usage_hold, payout_hold, stripe_id, stripe_payouts_enabled } = await this.client.utils.ResponseToJson(
70
+ await this.client.authClient.MakeAuthServiceRequest({
71
+ path: UrlJoin("as", "wlt", "mkt", "bal"),
72
+ method: "GET",
73
+ headers: {
74
+ Authorization: `Bearer ${this.AuthToken()}`
75
+ }
76
+ })
77
+ );
78
+
79
+ const userStripeId = stripe_id;
80
+ const userStripeEnabled = stripe_payouts_enabled;
81
+ const totalWalletBalance = parseFloat(balance || 0);
82
+ const availableWalletBalance = Math.max(0, totalWalletBalance - parseFloat(usage_hold || 0));
83
+ const pendingWalletBalance = Math.max(0, totalWalletBalance - availableWalletBalance);
84
+ const withdrawableWalletBalance = Math.max(0, totalWalletBalance - parseFloat(payout_hold || 0));
85
+
86
+ if(checkOnboard && stripe_id && !stripe_payouts_enabled) {
87
+ // Refresh stripe enabled flag
88
+ const rootUrl = new URL(UrlJoin(window.location.origin, window.location.pathname)).toString();
89
+ await this.client.authClient.MakeAuthServiceRequest({
90
+ path: UrlJoin("as", "wlt", "onb", "stripe"),
91
+ method: "POST",
92
+ body: {
93
+ country: "US",
94
+ mode: this.mode,
95
+ refresh_url: rootUrl.toString(),
96
+ return_url: rootUrl.toString()
97
+ },
98
+ headers: {
99
+ Authorization: `Bearer ${this.AuthToken()}`
100
+ }
101
+ });
102
+
103
+ return await this.UserWalletBalance(false);
104
+ }
105
+
106
+ let balances = {
107
+ totalWalletBalance,
108
+ availableWalletBalance,
109
+ pendingWalletBalance,
110
+ withdrawableWalletBalance,
111
+ };
112
+
113
+ if(userStripeEnabled) {
114
+ balances.userStripeId = userStripeId;
115
+ balances.userStripeEnabled = userStripeEnabled;
116
+ }
117
+
118
+ // TODO: integrate
119
+ /*
120
+ if(cryptoStore.usdcConnected) {
121
+ balances.usdcBalance = cryptoStore.phantomUSDCBalance;
122
+ }
123
+
124
+ */
125
+
126
+ return balances;
127
+ };
128
+
129
+
130
+ /**
131
+ * Returns basic contract info about the items the specified/current user owns, organized by contract address + token ID
132
+ *
133
+ * This method is significantly faster than <a href="#.UserItems">UserItems</a>, but does not include any NFT metadata.
134
+ *
135
+ * @methodGroup User
136
+ * @namedParams
137
+ * @param {string=} userAddress - Address of the user to query for. If unspecified, will use the currently logged in user.
138
+ *
139
+ * @returns {Promise<Object>} - Basic info about all owned items.
140
+ */
141
+ exports.UserItemInfo = async function ({userAddress}={}) {
142
+ const accountId = `iusr${Utils.AddressToHash(userAddress || this.UserAddress())}`;
143
+ this.profileData = await this.client.ethClient.MakeProviderCall({
144
+ methodName: "send",
145
+ args: [
146
+ "elv_getAccountProfile",
147
+ [this.client.contentSpaceId, accountId]
148
+ ]
149
+ });
150
+
151
+ if(!this.profileData || !this.profileData.NFTs) { return {}; }
152
+
153
+ let nftInfo = {};
154
+ Object.keys(this.profileData.NFTs).map(tenantId =>
155
+ this.profileData.NFTs[tenantId].forEach(details => {
156
+ const versionHash = (details.TokenUri || "").split("/").find(s => (s || "").startsWith("hq__"));
157
+
158
+ if(!versionHash) {
159
+ return;
160
+ }
161
+
162
+ if(details.TokenHold) {
163
+ details.TokenHoldDate = new Date(parseInt(details.TokenHold) * 1000);
164
+ }
165
+
166
+ const contractAddress = Utils.FormatAddress(details.ContractAddr);
167
+ const key = `${contractAddress}-${details.TokenIdStr}`;
168
+ nftInfo[key] = {
169
+ ...details,
170
+ ContractAddr: Utils.FormatAddress(details.ContractAddr),
171
+ ContractId: `ictr${Utils.AddressToHash(details.ContractAddr)}`,
172
+ VersionHash: versionHash
173
+ };
174
+ })
175
+ );
176
+
177
+ this.nftInfo = nftInfo;
178
+
179
+ return this.nftInfo;
180
+ };
181
+
182
+
183
+ /**
184
+ * <b><i>Requires login</i></b>
185
+ *
186
+ * Retrieve items owned by the current user matching the specified parameters.
187
+ *
188
+ * @methodGroup User
189
+ * @namedParams
190
+ * @param {integer=} start=0 - PAGINATION: Index from which the results should start
191
+ * @param {integer=} limit=50 - PAGINATION: Maximum number of results to return
192
+ * @param {string=} sortBy="created" - Sort order. Options: `default`, `meta/display_name`
193
+ * @param {boolean=} sortDesc=false - Sort results descending instead of ascending
194
+ * @param {string=} filter - Filter results by item name.
195
+ * @param {string=} contractAddress - Filter results by the address of the NFT contract
196
+ * @param {string=} tokenId - Filter by token ID (if filtering by contract address)
197
+ * @param {Object=} marketplaceParams - Filter results by marketplace
198
+ * @param {integer=} collectionIndex - If filtering by marketplace, filter by collection. The index refers to the index in the array `marketplace.collections`
199
+ *
200
+ * @returns {Promise<Object>} - Results of the query and pagination info
201
+ */
202
+ exports.UserItems = async function() {
203
+ return this.FilteredQuery({mode: "owned", ...(arguments[0] || {})});
204
+ };
205
+
206
+ /**
207
+ * Return all listings for the current user. Not paginated.
208
+ *
209
+ * @methodGroup User
210
+ * @namedParams
211
+ * @param {string=} sortBy="created" - Sort order. Options: `created`, `info/token_id`, `info/ordinal`, `price`, `nft/display_name`
212
+ * @param {boolean=} sortDesc=false - Sort results descending instead of ascending
213
+ * @param {Object=} marketplaceParams - Filter results by marketplace
214
+ * @param {string=} contractAddress - Filter results by the address of the NFT contract
215
+ * @param {string=} tokenId - Filter by token ID (if filtering by contract address)
216
+ *
217
+ * @returns {Promise<Array<Object>>} - List of current user's listings
218
+ */
219
+ exports.UserListings = async function({sortBy="created", sortDesc=false, contractAddress, tokenId, marketplaceParams}={}) {
220
+ return (
221
+ await this.FilteredQuery({
222
+ mode: "listings",
223
+ start: 0,
224
+ limit: 10000,
225
+ sortBy,
226
+ sortDesc,
227
+ sellerAddress: this.UserAddress(),
228
+ marketplaceParams,
229
+ contractAddress,
230
+ tokenId
231
+ })
232
+ ).results;
233
+ };
234
+
235
+ /**
236
+ * Return all sales for the current user. Not paginated.
237
+ *
238
+ * @methodGroup User
239
+ * @namedParams
240
+ * @param {string=} sortBy="created" - Sort order. Options: `created`, `price`, `name`
241
+ * @param {boolean=} sortDesc=false - Sort results descending instead of ascending
242
+ * @param {Object=} marketplaceParams - Filter results by marketplace
243
+ * @param {string=} contractAddress - Filter results by the address of the NFT contract
244
+ * @param {string=} tokenId - Filter by token ID (if filtering by contract address)
245
+ * @param {integer=} lastNDays - Filter by results listed in the past N days
246
+ *
247
+ * @returns {Promise<Array<Object>>} - List of current user's sales
248
+ */
249
+ exports.UserSales = async function({sortBy="created", sortDesc=false, contractAddress, tokenId, marketplaceParams}={}) {
250
+ return (
251
+ await this.FilteredQuery({
252
+ mode: "sales",
253
+ start: 0,
254
+ limit: 10000,
255
+ sortBy,
256
+ sortDesc,
257
+ sellerAddress: this.UserAddress(),
258
+ marketplaceParams,
259
+ contractAddress,
260
+ tokenId
261
+ })
262
+ ).results;
263
+ };
264
+
265
+ /**
266
+ * Return all transfers and sales for the current user. Not paginated.
267
+ *
268
+ * @methodGroup User
269
+ * @namedParams
270
+ * @param {string=} sortBy="created" - Sort order. Options: `created`, `price`, `name`
271
+ * @param {boolean=} sortDesc=false - Sort results descending instead of ascending
272
+ * @param {Object=} marketplaceParams - Filter results by marketplace
273
+ * @param {string=} contractAddress - Filter results by the address of the NFT contract
274
+ * @param {string=} tokenId - Filter by token ID (if filtering by contract address)
275
+ * @param {integer=} lastNDays - Filter by results listed in the past N days
276
+ *
277
+ * @returns {Promise<Array<Object>>} - List of current user's sales
278
+ */
279
+ exports.UserTransfers = async function({sortBy="created", sortDesc=false, contractAddress, tokenId, marketplaceParams}={}) {
280
+ return (
281
+ await this.FilteredQuery({
282
+ mode: "transfers",
283
+ start: 0,
284
+ limit: 10000,
285
+ sortBy,
286
+ sortDesc,
287
+ sellerAddress: this.UserAddress(),
288
+ marketplaceParams,
289
+ contractAddress,
290
+ tokenId
291
+ })
292
+ ).results;
293
+ };
294
+
295
+ /* TENANT */
296
+
297
+ /**
298
+ * Retrieve configuration information about the specified tenant, or the tenant associated with the specified contract.
299
+ *
300
+ * This information includes the royalty rate the tenant receives for secondary sales.
301
+ *
302
+ * @methodGroup Tenants
303
+ * @namedParams
304
+ * @param {string=} tenantId - The ID of the tenant for which to retrieve configuration
305
+ * @param {string=} contractAddress - The ID of an nft contract for which to retrieve configuration
306
+ *
307
+ * @returns {Promise<{Object}>} - The tenant configuration
308
+ */
309
+ exports.TenantConfiguration = async function({tenantId, contractAddress}) {
310
+ try {
311
+ return await Utils.ResponseToJson(
312
+ this.client.authClient.MakeAuthServiceRequest({
313
+ path: contractAddress ?
314
+ UrlJoin("as", "config", "nft", contractAddress) :
315
+ UrlJoin("as", "config", "tnt", tenantId),
316
+ method: "GET",
317
+ })
318
+ );
319
+ } catch(error) {
320
+ this.Log("Failed to load tenant configuration", true);
321
+ this.Log(error, true);
322
+
323
+ return {};
324
+ }
325
+ };
326
+
327
+
328
+ /* MARKETPLACE */
329
+
330
+ /**
331
+ * Retrieve available stock for the specified marketplace, organized by SKU.
332
+ *
333
+ * If a user is logged in, stock information will also include how many of that item the user has purchased.
334
+ *
335
+ * @methodGroup Marketplaces
336
+ * @namedParams
337
+ * @param {Object} marketplaceParams - Parameters of the marketplace
338
+ *
339
+ * @returns {Promise<Object>} - Stock info for items in the marketplace
340
+ */
341
+ exports.MarketplaceStock = async function ({marketplaceParams, tenantId}) {
342
+ if(!tenantId) {
343
+ const marketplaceInfo = this.MarketplaceInfo({marketplaceParams});
344
+ tenantId = marketplaceInfo.tenantId;
345
+ }
346
+
347
+ if(this.loggedIn) {
348
+ return await Utils.ResponseToJson(
349
+ this.client.authClient.MakeAuthServiceRequest({
350
+ path: UrlJoin("as", "wlt", "nft", "info", tenantId),
351
+ method: "GET",
352
+ headers: {
353
+ Authorization: `Bearer ${this.AuthToken()}`
354
+ }
355
+ })
356
+ );
357
+ }
358
+
359
+ return await Utils.ResponseToJson(
360
+ this.client.authClient.MakeAuthServiceRequest({
361
+ path: UrlJoin("as", "nft", "stock", tenantId),
362
+ method: "GET"
363
+ })
364
+ );
365
+ };
366
+
367
+ /**
368
+ * Retrieve basic information about a specific available marketplace with the specified tenant/marketplace slug, ID, or hash.
369
+ *
370
+ * Includes the slugs, ID and hash of the marketplace, as well as branding information.
371
+ *
372
+ * To retrieve full metadata for the marketplace, use the <a href="#.Marketplace">Marketplace</a> method.
373
+ *
374
+ * @methodGroup Marketplaces
375
+ * @namedParams
376
+ * @param {Object} marketplaceParams - Parameters of the marketplace
377
+ *
378
+ * @returns {Promise<Object>} - Info about the marketplace
379
+ */
380
+ exports.MarketplaceInfo = function ({marketplaceParams}) {
381
+ let { tenantSlug, marketplaceSlug, marketplaceId, marketplaceHash } = (marketplaceParams || {});
382
+
383
+ let marketplaceInfo;
384
+ if(tenantSlug && marketplaceSlug) {
385
+ marketplaceInfo = (this.availableMarketplaces[tenantSlug] || {})[marketplaceSlug];
386
+ } else {
387
+ marketplaceId = marketplaceHash ? this.client.utils.DecodeVersionHash(marketplaceHash).objectId : marketplaceId;
388
+ marketplaceInfo = this.availableMarketplacesById[marketplaceId];
389
+ }
390
+
391
+ if(!marketplaceInfo) {
392
+ throw Error(`Eluvio Wallet Client: Unable to find marketplace with parameters ${JSON.stringify(arguments)}`);
393
+ }
394
+
395
+ return marketplaceInfo;
396
+ };
397
+
398
+ /**
399
+ * Retrieve custom CSS for the specified marketplace
400
+ *
401
+ * @methodGroup Marketplaces
402
+ * @namedParams
403
+ * @param {Object} marketplaceParams - Parameters of the marketplace
404
+ *
405
+ * @returns {Promise<string>} - The CSS of the marketplace
406
+ */
407
+ exports.MarketplaceCSS = async function ({marketplaceParams}) {
408
+ const marketplaceInfo = this.MarketplaceInfo({marketplaceParams});
409
+
410
+ const marketplaceHash = marketplaceInfo.marketplaceHash;
411
+
412
+ if(!this.cachedCSS[marketplaceHash]) {
413
+ this.cachedCSS[marketplaceHash] = await this.client.ContentObjectMetadata({
414
+ versionHash: marketplaceHash,
415
+ metadataSubtree: "public/asset_metadata/info/branding/custom_css",
416
+ authorizationToken: this.publicStaticToken,
417
+ noAuth: true
418
+ });
419
+ }
420
+
421
+ return this.cachedCSS[marketplaceHash] || "";
422
+ };
423
+
424
+ /**
425
+ * Retrieve info about all available marketplaces
426
+ *
427
+ * @methodGroup Marketplaces
428
+ * @namedParams
429
+ * @param {boolean=} organizeById - By default, the returned marketplace info is organized by tenant and marketplace slug. If this option is enabled, the marketplaces will be organized by marketplace ID instead.
430
+ * @param {boolean=} forceReload=false - If specified, a new request will be made to check the currently available marketplaces instead of returning cached info
431
+ *
432
+ * @returns {Promise<{Object}>} - Info about available marketplaces
433
+ */
434
+ exports.AvailableMarketplaces = async function ({organizeById, forceReload=false}={}) {
435
+ if(forceReload) {
436
+ await this.LoadAvailableMarketplaces(true);
437
+ }
438
+
439
+ return {
440
+ ...(organizeById ? this.availableMarketplacesById : this.availableMarketplaces)
441
+ };
442
+ };
443
+
444
+ /**
445
+ * Retrieve full information about the specified marketplace
446
+ *
447
+ * <b><i>Note</i></b> - Upon changing login state, the marketplace should be retrieved again as permission info in marketplace items may be different depending on the current user's permissions.
448
+ *
449
+ * @methodGroup Marketplaces
450
+ * @namedParams
451
+ * @param {Object} marketplaceParams - Parameters of the marketplace
452
+ *
453
+ * @returns {Promise<Object>} - The full information for the marketplace
454
+ */
455
+ exports.Marketplace = async function ({marketplaceParams}) {
456
+ return this.LoadMarketplace(marketplaceParams);
457
+ };
458
+
459
+
460
+ /* NFTS */
461
+
462
+ /**
463
+ * Load full info for the specified NFT
464
+ *
465
+ * @methodGroup Items
466
+ * @namedParams
467
+ * @param {string} contractAddress - The contract address of the NFT
468
+ * @param {string} tokenId - The token ID of the NFT
469
+ */
470
+ exports.NFT = async function({tokenId, contractAddress}) {
471
+ let nft = FormatNFTDetails(
472
+ await Utils.ResponseToJson(
473
+ this.client.authClient.MakeAuthServiceRequest({
474
+ path: UrlJoin("as", "nft", "info", contractAddress, tokenId),
475
+ method: "GET"
476
+ })
477
+ )
478
+ );
479
+
480
+ nft.metadata = {
481
+ ...(
482
+ (await this.client.ContentObjectMetadata({
483
+ versionHash: nft.details.VersionHash,
484
+ metadataSubtree: "public/asset_metadata/nft",
485
+ produceLinkUrls: true
486
+ })) || {}
487
+ ),
488
+ ...(nft.metadata || {})
489
+ };
490
+
491
+ nft.config = await this.TenantConfiguration({contractAddress});
492
+
493
+ return FormatNFTMetadata(nft);
494
+ };
495
+
496
+ /**
497
+ * <b><i>Requires login</i></b>
498
+ *
499
+ * Transfer the specified NFT owned by the current user to the specified address
500
+ *
501
+ * @methodGroup NFT
502
+ * @namedParams
503
+ * @param {string} contractAddress - The contract address of the NFT
504
+ * @param {string} tokenId - The token ID of the NFT
505
+ * @param {string} targetAddress - The address to which to transfer the NFT
506
+ */
507
+ exports.TransferNFT = async function({contractAddress, tokenId, targetAddress}) {
508
+ if(!targetAddress || !Utils.ValidAddress(targetAddress)) {
509
+ throw Error("Eluvio Wallet Client: Invalid or missing target address in UserTransferNFT");
510
+ }
511
+
512
+ return await this.client.authClient.MakeAuthServiceRequest({
513
+ path: UrlJoin("as", "wlt", "mkt", "xfer"),
514
+ method: "POST",
515
+ body: {
516
+ contract: Utils.FormatAddress(contractAddress),
517
+ token: tokenId,
518
+ to_addr: Utils.FormatAddress(targetAddress)
519
+ },
520
+ headers: {
521
+ Authorization: `Bearer ${this.AuthToken()}`
522
+ }
523
+ });
524
+ };
525
+
526
+
527
+ /** LISTINGS */
528
+
529
+ /**
530
+ * Retrieve the status of the specified listing
531
+ *
532
+ * @methodGroup Listings
533
+ * @namedParams
534
+ * @param {string=} listingId - The ID of the listing
535
+ *
536
+ * @returns {Promise<Object>} - The status of the listing
537
+ */
538
+ exports.ListingStatus = async function({listingId}) {
539
+ try {
540
+ return await Utils.ResponseToJson(
541
+ await this.client.authClient.MakeAuthServiceRequest({
542
+ path: UrlJoin("as", "mkt", "status", listingId),
543
+ method: "GET"
544
+ })
545
+ );
546
+ } catch(error) {
547
+ if(error.status === 404) { return; }
548
+
549
+ throw error;
550
+ }
551
+ };
552
+
553
+ /**
554
+ * Retrieve a specific listing
555
+ *
556
+ * NOTE: When a listing is sold or deleted, it will no longer be queryable with this API. Use <a href="#.ListingStatus">ListingStatus</a> instead.
557
+ *
558
+ * @methodGroup Listings
559
+ * @namedParams
560
+ * @param {string=} listingId - The ID of the listing
561
+ *
562
+ * @returns {Promise<Object>} - The listing
563
+ */
564
+ exports.Listing = async function({listingId}) {
565
+ return FormatNFT(
566
+ await Utils.ResponseToJson(
567
+ await this.client.authClient.MakeAuthServiceRequest({
568
+ path: UrlJoin("as", "mkt", "l", listingId),
569
+ method: "GET",
570
+ })
571
+ )
572
+ );
573
+ };
574
+
575
+
576
+ /**
577
+ * Retrieve listings matching the specified parameters.
578
+ *
579
+ * @methodGroup Listings
580
+ * @namedParams
581
+ * @param {integer=} start=0 - PAGINATION: Index from which the results should start
582
+ * @param {integer=} limit=50 - PAGINATION: Maximum number of results to return
583
+ * @param {string=} sortBy="created" - Sort order. Options: `created`, `info/token_id`, `info/ordinal`, `price`, `nft/display_name`
584
+ * @param {boolean=} sortDesc=false - Sort results descending instead of ascending
585
+ * @param {string=} filter - Filter results by item name.
586
+ * <br /><br />
587
+ * NOTE: This string must be an <b>exact match</b> on the item name.
588
+ * You can retrieve all available item names from the <a href="#.ListingNames">ListingNames method</a>.
589
+ * @param {string=} editionFilter - Filter results by item edition.
590
+ * <br /><br />
591
+ * NOTE: This string must be an <b>exact match</b> on the edition name.
592
+ * You can retrieve all available item edition names from the <a href="#.ListingEditionNames">ListingEditionNames method</a>.
593
+ * @param {Array<Object>} attributeFilters - Filter results by item attributes. Each entry should include name and value (e.g. `[{name: "attribute-name", value: "attribute-value"}]`)
594
+ * <br /><br />
595
+ * NOTE: These filters must be an <b>exact match</b> on the attribute name and value.
596
+ * You can retrieve all available item attributes from the <a href="#.ListingAttributes">ListingAttributes method</a>.
597
+ * @param {string=} sellerAddress - Filter by a specific seller
598
+ * @param {string=} contractAddress - Filter results by the address of the NFT contract
599
+ * @param {string=} tokenId - Filter by token ID (if filtering by contract address)
600
+ * @param {string=} currency - Filter results by purchase currency. Available options: `usdc`
601
+ * @param {Object=} marketplaceParams - Filter results by marketplace
602
+ * @param {integer=} collectionIndex - If filtering by marketplace, filter by collection. The index refers to the index in the array `marketplace.collections`
603
+ * @param {integer=} lastNDays - Filter by results listed in the past N days
604
+ *
605
+ * @returns {Promise<Object>} - Results of the query and pagination info
606
+ */
607
+ exports.Listings = async function() {
608
+ return this.FilteredQuery({mode: "listings", ...(arguments[0] || {})});
609
+ };
610
+
611
+ /**
612
+ * Retrieve stats for listings matching the specified parameters.
613
+ *
614
+ * @methodGroup Listings
615
+ * @namedParams
616
+ * @param {integer=} start=0 - PAGINATION: Index from which the results should start
617
+ * @param {integer=} limit=50 - PAGINATION: Maximum number of results to return
618
+ * @param {string=} sortBy="created" - Sort order. Options: `created`, `info/token_id`, `info/ordinal`, `price`, `nft/display_name`
619
+ * @param {boolean=} sortDesc=false - Sort results descending instead of ascending
620
+ * @param {string=} filter - Filter results by item name.
621
+ * <br /><br />
622
+ * NOTE: This string must be an <b>exact match</b> on the item name.
623
+ * You can retrieve all available item names from the <a href="#.ListingNames">ListingNames method</a>.
624
+ * @param {string=} editionFilter - Filter results by item edition.
625
+ * <br /><br />
626
+ * NOTE: This string must be an <b>exact match</b> on the edition name.
627
+ * You can retrieve all available item edition names from the <a href="#.ListingEditionNames">ListingEditionNames method</a>.
628
+ * @param {Array<Object>} attributeFilters - Filter results by item attributes. Each entry should include name and value (e.g. `[{name: "attribute-name", value: "attribute-value"}]`)
629
+ * <br /><br />
630
+ * NOTE: These filters must be an <b>exact match</b> on the attribute name and value.
631
+ * You can retrieve all available item attributes from the <a href="#.ListingAttributes">ListingAttributes method</a>.
632
+ * @param {string=} sellerAddress - Filter by a specific seller
633
+ * @param {string=} contractAddress - Filter results by the address of the NFT contract
634
+ * @param {string=} tokenId - Filter by token ID (if filtering by contract address)
635
+ * @param {string=} currency - Filter results by purchase currency. Available options: `usdc`
636
+ * @param {Object=} marketplaceParams - Filter results by marketplace
637
+ * @param {integer=} collectionIndex - If filtering by marketplace, filter by collection. The index refers to the index in the array `marketplace.collections`
638
+ * @param {integer=} lastNDays - Filter by results listed in the past N days
639
+ *
640
+ * @returns {Promise<Object>} - Statistics about listings. All prices in USD.
641
+ */
642
+ exports.ListingStats = async function() {
643
+ return this.FilteredQuery({mode: "listing-stats", ...(arguments[0] || {})});
644
+ };
645
+
646
+ /**
647
+ * Retrieve sales matching the specified parameters.
648
+ *
649
+ * @methodGroup Listings
650
+ * @namedParams
651
+ * @param {integer=} start=0 - PAGINATION: Index from which the results should start
652
+ * @param {integer=} limit=50 - PAGINATION: Maximum number of results to return
653
+ * @param {string=} sortBy="created" - Sort order. Options: `created`, `price`, `name`
654
+ * @param {boolean=} sortDesc=false - Sort results descending instead of ascending
655
+ * @param {string=} filter - Filter results by item name.
656
+ * <br /><br />
657
+ * NOTE: This string must be an <b>exact match</b> on the item name.
658
+ * You can retrieve all available item names from the <a href="#.ListingNames">ListingNames method</a>.
659
+ * @param {string=} editionFilter - Filter results by item edition.
660
+ * <br /><br />
661
+ * NOTE: This string must be an <b>exact match</b> on the edition name.
662
+ * You can retrieve all available item edition names from the <a href="#.ListingEditionNames">ListingEditionNames method</a>.
663
+ * @param {Array<Object>} attributeFilters - Filter results by item attributes. Each entry should include name and value (e.g. `[{name: "attribute-name", value: "attribute-value"}]`)
664
+ * <br /><br />
665
+ * NOTE: These filters must be an <b>exact match</b> on the attribute name and value.
666
+ * You can retrieve all available item attributes from the <a href="#.ListingAttributes">ListingAttributes method</a>.
667
+ * @param {string=} sellerAddress - Filter by a specific seller
668
+ * @param {string=} contractAddress - Filter results by the address of the NFT contract
669
+ * @param {string=} tokenId - Filter by token ID (if filtering by contract address)
670
+ * @param {string=} currency - Filter results by purchase currency. Available options: `usdc`
671
+ * @param {Object=} marketplaceParams - Filter results by marketplace
672
+ * @param {integer=} collectionIndex - If filtering by marketplace, filter by collection. The index refers to the index in the array `marketplace.collections`
673
+ * @param {integer=} lastNDays - Filter by results listed in the past N days
674
+ *
675
+ * @returns {Promise<Object>} - Results of the query and pagination info
676
+ */
677
+ exports.Sales = async function() {
678
+ return this.FilteredQuery({mode: "sales", ...(arguments[0] || {})});
679
+ };
680
+
681
+ /**
682
+ * Retrieve sales and transfers matching the specified parameters.
683
+ *
684
+ * @methodGroup Listings
685
+ * @namedParams
686
+ * @param {integer=} start=0 - PAGINATION: Index from which the results should start
687
+ * @param {integer=} limit=50 - PAGINATION: Maximum number of results to return
688
+ * @param {string=} sortBy="created" - Sort order. Options: `created`, `price`, `name`
689
+ * @param {boolean=} sortDesc=false - Sort results descending instead of ascending
690
+ * @param {string=} filter - Filter results by item name.
691
+ * <br /><br />
692
+ * NOTE: This string must be an <b>exact match</b> on the item name.
693
+ * You can retrieve all available item names from the <a href="#.ListingNames">ListingNames method</a>.
694
+ * @param {string=} editionFilter - Filter results by item edition.
695
+ * <br /><br />
696
+ * NOTE: This string must be an <b>exact match</b> on the edition name.
697
+ * You can retrieve all available item edition names from the <a href="#.ListingEditionNames">ListingEditionNames method</a>.
698
+ * @param {Array<Object>} attributeFilters - Filter results by item attributes. Each entry should include name and value (e.g. `[{name: "attribute-name", value: "attribute-value"}]`)
699
+ * <br /><br />
700
+ * NOTE: These filters must be an <b>exact match</b> on the attribute name and value.
701
+ * You can retrieve all available item attributes from the <a href="#.ListingAttributes">ListingAttributes method</a>.
702
+ * @param {string=} sellerAddress - Filter by a specific seller
703
+ * @param {string=} contractAddress - Filter results by the address of the NFT contract
704
+ * @param {string=} tokenId - Filter by token ID (if filtering by contract address)
705
+ * @param {string=} currency - Filter results by purchase currency. Available options: `usdc`
706
+ * @param {Object=} marketplaceParams - Filter results by marketplace
707
+ * @param {integer=} collectionIndex - If filtering by marketplace, filter by collection. The index refers to the index in the array `marketplace.collections`
708
+ * @param {integer=} lastNDays - Filter by results listed in the past N days
709
+ *
710
+ * @returns {Promise<Object>} - Results of the query and pagination info
711
+ */
712
+ exports.Transfers = async function() {
713
+ return this.FilteredQuery({mode: "transfers", ...(arguments[0] || {})});
714
+ };
715
+
716
+ /**
717
+ * Retrieve stats for listings matching the specified parameters.
718
+ *
719
+ * @methodGroup Listings
720
+ * @namedParams
721
+ * @param {integer=} start=0 - PAGINATION: Index from which the results should start
722
+ * @param {integer=} limit=50 - PAGINATION: Maximum number of results to return
723
+ * @param {string=} sortBy="created" -
724
+ * @param {boolean=} sortDesc=false - Sort results descending instead of ascending
725
+ * @param {string=} filter - Filter results by item name.
726
+ * <br /><br />
727
+ * NOTE: This string must be an <b>exact match</b> on the item name.
728
+ * You can retrieve all available item names from the <a href="#.ListingNames">ListingNames method</a>.
729
+ * @param {string=} editionFilter - Filter results by item edition.
730
+ * <br /><br />
731
+ * NOTE: This string must be an <b>exact match</b> on the edition name.
732
+ * You can retrieve all available item edition names from the <a href="#.ListingEditionNames">ListingEditionNames method</a>.
733
+ * @param {Array<Object>} attributeFilters - Filter results by item attributes. Each entry should include name and value (e.g. `[{name: "attribute-name", value: "attribute-value"}]`)
734
+ * <br /><br />
735
+ * NOTE: These filters must be an <b>exact match</b> on the attribute name and value.
736
+ * You can retrieve all available item attributes from the <a href="#.ListingAttributes">ListingAttributes method</a>.
737
+ * @param {string=} sellerAddress - Filter by a specific seller
738
+ * @param {string=} contractAddress - Filter results by the address of the NFT contract
739
+ * @param {string=} tokenId - Filter by token ID (if filtering by contract address)
740
+ * @param {string=} currency - Filter results by purchase currency. Available options: `usdc`
741
+ * @param {Object=} marketplaceParams - Filter results by marketplace
742
+ * @param {integer=} collectionIndex - If filtering by marketplace, filter by collection. The index refers to the index in the array `marketplace.collections`
743
+ * @param {integer=} lastNDays - Filter by results listed in the past N days
744
+ *
745
+ * @returns {Promise<Object>} - Statistics about sales. All prices in USD.
746
+ */
747
+ exports.SalesStats = async function() {
748
+ return this.FilteredQuery({mode: "sales-stats", ...(arguments[0] || {})});
749
+ };
750
+
751
+
752
+ /**
753
+ * <b><i>Requires login</i></b>
754
+ *
755
+ * Create or update a listing for the specified item
756
+ *
757
+ * @methodGroup Listings
758
+ * @namedParams
759
+ * @param {string} contractAddress - The NFT contract address of the item
760
+ * @param {string} tokenId - The token ID of the item
761
+ * @param {number} price - The price of the listing, in USD
762
+ * @param {string=} listingId - (When editing a listing) The ID of the existing listing
763
+ *
764
+ * @returns {Promise<string>} - The listing ID of the created listing
765
+ */
766
+ exports.CreateListing = async function({contractAddress, tokenId, price, listingId}) {
767
+ contractAddress = Utils.FormatAddress(contractAddress);
768
+
769
+ if(listingId) {
770
+ // Update
771
+ return await Utils.ResponseToFormat(
772
+ "text",
773
+ await this.client.authClient.MakeAuthServiceRequest({
774
+ path: UrlJoin("as", "wlt", "mkt"),
775
+ method: "PUT",
776
+ body: {
777
+ id: listingId,
778
+ price: parseFloat(price)
779
+ },
780
+ headers: {
781
+ Authorization: `Bearer ${this.AuthToken()}`
782
+ }
783
+ })
784
+ );
785
+ } else {
786
+ // Create
787
+ return await Utils.ResponseToJson(
788
+ await this.client.authClient.MakeAuthServiceRequest({
789
+ path: UrlJoin("as", "wlt", "mkt"),
790
+ method: "POST",
791
+ body: {
792
+ contract: contractAddress,
793
+ token: tokenId,
794
+ price: parseFloat(price)
795
+ },
796
+ headers: {
797
+ Authorization: `Bearer ${this.AuthToken()}`
798
+ }
799
+ })
800
+ );
801
+ }
802
+ };
803
+
804
+ /**
805
+ * <b><i>Requires login</i></b>
806
+ *
807
+ * Remove the specified listing
808
+ *
809
+ * @methodGroup Listings
810
+ * @namedParams
811
+ * @param {string} listingId - The ID of the listing to remove
812
+ */
813
+ exports.RemoveListing = async function({listingId}) {
814
+ await this.client.authClient.MakeAuthServiceRequest({
815
+ path: UrlJoin("as", "wlt", "mkt", listingId),
816
+ method: "DELETE",
817
+ headers: {
818
+ Authorization: `Bearer ${this.AuthToken()}`
819
+ }
820
+ });
821
+ };
822
+
823
+ /**
824
+ * Retrieve all valid names for filtering listings. Full item names are required for filtering listing results by name.
825
+ *
826
+ * Specify marketplace information to filter the results to only items offered in that marketplace.
827
+ *
828
+ * @methodGroup Listings
829
+ * @namedParams
830
+ * @param {Object} marketplaceParams - Parameters of a marketplace to filter results by
831
+ *
832
+ * @returns {Promise<Array<String>>} - A list of item names
833
+ */
834
+ exports.ListingNames = async function({marketplaceParams}) {
835
+ let tenantId;
836
+ if(marketplaceParams) {
837
+ tenantId = (await this.MarketplaceInfo({marketplaceParams})).tenantId;
838
+ }
839
+
840
+ return await Utils.ResponseToJson(
841
+ await this.client.authClient.MakeAuthServiceRequest({
842
+ path: UrlJoin("as", "mkt", "names"),
843
+ method: "GET",
844
+ queryParams: tenantId ? { filter: `tenant:eq:${tenantId}` } : {}
845
+ })
846
+ );
847
+ };
848
+
849
+
850
+ /**
851
+ * Retrieve all valid edition names of the specified item. Full item edition names are required for filtering listing results by edition.
852
+ *
853
+ * @methodGroup Listings
854
+ * @namedParams
855
+ * @param {string} displayName - Display name of the item from which to request edition names
856
+ *
857
+ * @returns {Promise<Array<String>>} - A list of item editions
858
+ */
859
+ exports.ListingEditionNames = async function({displayName}) {
860
+ return await Utils.ResponseToJson(
861
+ await this.client.authClient.MakeAuthServiceRequest({
862
+ path: UrlJoin("as", "mkt", "editions"),
863
+ queryParams: {
864
+ filter: `nft/display_name:eq:${displayName}`
865
+ },
866
+ method: "GET"
867
+ })
868
+ );
869
+ };
870
+
871
+ /**
872
+ * Retrieve names of all valid attributes for listed tiems. Full attribute names and values are required for filtering listing results by attributes.
873
+ *
874
+ * Specify marketplace information to filter the results to only items offered in that marketplace.
875
+ *
876
+ * @methodGroup Listings
877
+ * @namedParams
878
+ * @param {Object=} marketplaceParams - Parameters of a marketplace to filter results by
879
+ * @param {string=} displayName - Display name of the item from which to request attributes
880
+ *
881
+ * @returns {Promise<Array<String>>} - A list of valid attributes
882
+ */
883
+ exports.ListingAttributes = async function({marketplaceParams, displayName}={}) {
884
+ let filters = [];
885
+
886
+ if(marketplaceParams) {
887
+ filters.push(`tenant:eq:${(await this.MarketplaceInfo({marketplaceParams})).tenantId}`);
888
+ }
889
+
890
+ if(displayName) {
891
+ filters.push(`nft/display_name:eq:${displayName}`);
892
+ }
893
+
894
+ const attributes = await Utils.ResponseToJson(
895
+ await this.client.authClient.MakeAuthServiceRequest({
896
+ path: UrlJoin("as", "mkt", "attributes"),
897
+ method: "GET",
898
+ queryParams: {
899
+ filter: filters
900
+ }
901
+ })
902
+ );
903
+
904
+ return attributes
905
+ .map(({trait_type, values}) => ({ name: trait_type, values }))
906
+ .filter(({name}) =>
907
+ !["Content Fabric Hash", "Total Minted Supply", "Creator"].includes(name)
908
+ );
909
+ };
910
+
911
+ /* MINTING STATUS */
912
+
913
+ /**
914
+ * Return status of the specified listing purchase
915
+ *
916
+ * @methodGroup Status
917
+ * @namedParams
918
+ * @param {string} listingId - The ID of the listing
919
+ * @param {string} confirmationId - The confirmation ID of the purchase
920
+ *
921
+ * @returns {Promise<Object>} - The status of the purchase
922
+ */
923
+ exports.ListingPurchaseStatus = async function({listingId, confirmationId}) {
924
+ try {
925
+ const listingStatus = await this.ListingStatus({listingId});
926
+
927
+ if(!listingStatus) {
928
+ throw Error("Unable to find info for listing " + listingId);
929
+ }
930
+
931
+ const statuses = await this.MintingStatus({tenantId: listingStatus.tenant});
932
+
933
+ return statuses
934
+ .find(status =>
935
+ status.op === "nft-transfer" &&
936
+ status.extra && status.extra[0] === confirmationId
937
+ ) || { status: "none" };
938
+ } catch(error) {
939
+ this.Log(error, true);
940
+ return { status: "unknown" };
941
+ }
942
+ };
943
+
944
+ /**
945
+ * Return status of the specified marketplace purchase
946
+ *
947
+ * @methodGroup Status
948
+ * @namedParams
949
+ * @param {Object} marketplaceParams - Parameters of the marketplace
950
+ * @param {string} confirmationId - The confirmation ID of the purchase
951
+ *
952
+ * @returns {Promise<Object>} - The minting status of the purchaseed item(s)
953
+ */
954
+ exports.PurchaseStatus = async function({marketplaceParams, confirmationId}) {
955
+ try {
956
+ const marketplaceInfo = await this.MarketplaceInfo({marketplaceParams});
957
+ const statuses = await this.MintingStatus({tenantId: marketplaceInfo.tenant_id});
958
+
959
+ return statuses.find(status => status.op === "nft-buy" && status.confirmationId === confirmationId) || { status: "none" };
960
+ } catch(error) {
961
+ this.Log(error, true);
962
+ return { status: "unknown" };
963
+ }
964
+ };
965
+
966
+ /**
967
+ * Return status of the specified item claim
968
+ *
969
+ * @methodGroup Status
970
+ * @namedParams
971
+ * @param {Object} marketplaceParams - Parameters of the marketplace
972
+ * @param {string} sku - The SKU of the item claimed
973
+ *
974
+ * @returns {Promise<Object>} - The minting status of the claim
975
+ */
976
+ exports.ClaimStatus = async function({marketplaceParams, sku}) {
977
+ try {
978
+ const marketplaceInfo = await this.MarketplaceInfo({marketplaceParams});
979
+ const statuses = await this.MintingStatus({tenantId: marketplaceInfo.tenantId});
980
+
981
+ return statuses.find(status => status.op === "nft-claim" && status.marketplaceId === marketplaceInfo.marketplaceId && status.confirmationId === sku) || { status: "none" };
982
+ } catch(error) {
983
+ this.Log(error, true);
984
+ return { status: "unknown" };
985
+ }
986
+ };
987
+
988
+ /**
989
+ * Return status of the specified pack opening
990
+ *
991
+ * @methodGroup Status
992
+ * @namedParams
993
+ * @param {string} contractAddress - The NFT contract address of the opened pack
994
+ * @param {string} tokenId - The token ID of the opened pack
995
+ *
996
+ * @returns {Promise<Object>} - The status of the pack opening
997
+ */
998
+ exports.PackOpenStatus = async function({contractAddress, tokenId}) {
999
+ try {
1000
+ const tenantConfig = await this.TenantConfiguration({contractAddress});
1001
+
1002
+ const statuses = await this.MintingStatus({tenantId: tenantConfig.tenant});
1003
+
1004
+ return statuses.find(status => status.op === "nft-open" && Utils.EqualAddress(contractAddress, status.address) && status.tokenId === tokenId) || { status: "none" };
1005
+ } catch(error) {
1006
+ this.Log(error, true);
1007
+ return { status: "unknown" };
1008
+ }
1009
+ };
1010
+
1011
+ /**
1012
+ * Return status of the specified collection redemption
1013
+ *
1014
+ * @methodGroup Status
1015
+ * @namedParams
1016
+ * @param {Object} marketplaceParams - Parameters of the marketplace
1017
+ * @param {string} confirmationId - The confirmation ID of the redemption
1018
+ *
1019
+ * @returns {Promise<Object>} - The status of the collection redemption
1020
+ */
1021
+ exports.CollectionRedemptionStatus = async function({marketplaceParams, confirmationId}) {
1022
+ try {
1023
+ const statuses = await this.MintingStatus({marketplaceParams});
1024
+
1025
+ return statuses.find(status => status.op === "nft-redeem" && status.confirmationId === confirmationId) || { status: "none" };
1026
+ } catch(error) {
1027
+ this.Log(error, true);
1028
+ return { status: "unknown" };
1029
+ }
1030
+ };
1031
+
1032
+ /* EVENTS */
1033
+
1034
+
1035
+ exports.LoadDrop = async function({tenantSlug, eventSlug, dropId}) {
1036
+ if(!this.drops){
1037
+ this.drops = {};
1038
+ }
1039
+
1040
+ if(!this.drops[tenantSlug]) {
1041
+ this.drops[tenantSlug] = {};
1042
+ }
1043
+
1044
+ if(!this.drops[tenantSlug][eventSlug]) {
1045
+ this.drops[tenantSlug][eventSlug] = {};
1046
+ }
1047
+
1048
+ if(!this.drops[tenantSlug][eventSlug][dropId]) {
1049
+ const mainSiteHash = await this.client.LatestVersionHash({objectId: this.mainSiteId});
1050
+ const event = (await this.client.ContentObjectMetadata({
1051
+ versionHash: mainSiteHash,
1052
+ metadataSubtree: UrlJoin("public", "asset_metadata", "tenants", tenantSlug, "sites", eventSlug, "info"),
1053
+ resolveLinks: true,
1054
+ linkDepthLimit: 2,
1055
+ resolveIncludeSource: true,
1056
+ produceLinkUrls: true,
1057
+ select: [".", "drops"],
1058
+ noAuth: true
1059
+ })) || [];
1060
+
1061
+ const eventId = Utils.DecodeVersionHash(event["."].source).objectId;
1062
+
1063
+ event.drops.forEach(drop => {
1064
+ drop = {
1065
+ ...drop,
1066
+ eventId
1067
+ };
1068
+
1069
+ this.drops[tenantSlug][eventSlug][drop.uuid] = drop;
1070
+ this.drops[drop.uuid] = drop;
1071
+ });
1072
+ }
1073
+
1074
+ return this.drops[dropId];
1075
+ };
1076
+
1077
+ exports.SubmitDropVote = async function({marketplaceParams, eventId, dropId, sku}) {
1078
+ const marketplaceInfo = await this.MarketplaceInfo({marketplaceParams});
1079
+ await this.client.authClient.MakeAuthServiceRequest({
1080
+ path: UrlJoin("as", "wlt", "act", marketplaceInfo.tenant_id),
1081
+ method: "POST",
1082
+ body: {
1083
+ op: "vote-drop",
1084
+ evt: eventId,
1085
+ id: dropId,
1086
+ itm: sku
1087
+ },
1088
+ headers: {
1089
+ Authorization: `Bearer ${this.AuthToken()}`
1090
+ }
1091
+ });
1092
+ };
1093
+
1094
+ exports.DropStatus = async function({marketplace, eventId, dropId}) {
1095
+ try {
1096
+ const response = await Utils.ResponseToJson(
1097
+ this.client.authClient.MakeAuthServiceRequest({
1098
+ path: UrlJoin("as", "wlt", "act", marketplace.tenant_id, eventId, dropId),
1099
+ method: "GET",
1100
+ headers: {
1101
+ Authorization: `Bearer ${this.AuthToken()}`
1102
+ }
1103
+ })
1104
+ );
1105
+
1106
+ return response.sort((a, b) => a.ts > b.ts ? 1 : -1)[0] || { status: "none" };
1107
+ } catch(error) {
1108
+ this.Log(error, true);
1109
+ return "";
1110
+ }
1111
+ };