@eluvio/elv-client-js 4.0.62 → 4.0.64

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.
@@ -1155,11 +1155,11 @@ var ElvWalletClient = /*#__PURE__*/function () {
1155
1155
  });
1156
1156
  case 3:
1157
1157
  marketplaceInfo = _context17.sent;
1158
- if (!(this.previewMarketplaceId && this.previewMarketplaceId === marketplaceInfo.marketplaceId)) {
1158
+ if (!(this.previewMarketplaceId && Utils.EqualHash(this.previewMarketplaceId, marketplaceInfo.marketplaceId))) {
1159
1159
  _context17.next = 6;
1160
1160
  break;
1161
1161
  }
1162
- return _context17.abrupt("return", this.availableMarketplaces[marketplaceInfo.tenantSlug][marketplaceInfo.marketplaceSlug]["."].source);
1162
+ return _context17.abrupt("return", this.previewMarketplaceHash);
1163
1163
  case 6:
1164
1164
  _context17.next = 8;
1165
1165
  return this.client.ContentObjectMetadata({
@@ -1206,15 +1206,36 @@ var ElvWalletClient = /*#__PURE__*/function () {
1206
1206
  delete this.cachedMarketplaces[marketplaceId];
1207
1207
  }
1208
1208
  if (this.cachedMarketplaces[marketplaceId]) {
1209
- _context19.next = 28;
1209
+ _context19.next = 34;
1210
1210
  break;
1211
1211
  }
1212
- _context19.next = 9;
1212
+ if (!(this.previewMarketplaceId && Utils.EqualHash(marketplaceId, this.previewMarketplaceId))) {
1213
+ _context19.next = 13;
1214
+ break;
1215
+ }
1216
+ _context19.next = 10;
1217
+ return this.client.ContentObjectMetadata({
1218
+ versionHash: this.previewMarketplaceHash,
1219
+ metadataSubtree: "/public/asset_metadata/info",
1220
+ localizationSubtree: this.localization ? UrlJoin("public", "asset_metadata", "localizations", this.localization, "info") : undefined,
1221
+ linkDepthLimit: 1,
1222
+ resolveLinks: true,
1223
+ resolveIgnoreErrors: true,
1224
+ resolveIncludeSource: true,
1225
+ produceLinkUrls: true,
1226
+ authorizationToken: this.publicStaticToken
1227
+ });
1228
+ case 10:
1229
+ marketplace = _context19.sent;
1230
+ _context19.next = 16;
1231
+ break;
1232
+ case 13:
1233
+ _context19.next = 15;
1213
1234
  return this.client.ContentObjectMetadata({
1214
1235
  libraryId: this.mainSiteLibraryId,
1215
1236
  objectId: this.mainSiteId,
1216
1237
  metadataSubtree: UrlJoin("/public", "asset_metadata", "tenants", marketplaceInfo.tenantSlug, "marketplaces", marketplaceInfo.marketplaceSlug, "info"),
1217
- localizationSubtree: this.localization ? UrlJoin("public", "asset_metadata", "localizations", this.localization, "info") : "",
1238
+ localizationSubtree: this.localization ? UrlJoin("/public", "asset_metadata", "tenants", marketplaceInfo.tenantSlug, "marketplaces", marketplaceInfo.marketplaceSlug, "localizations", this.localization, "info") : undefined,
1218
1239
  linkDepthLimit: 1,
1219
1240
  resolveLinks: true,
1220
1241
  resolveIgnoreErrors: true,
@@ -1222,13 +1243,14 @@ var ElvWalletClient = /*#__PURE__*/function () {
1222
1243
  produceLinkUrls: true,
1223
1244
  authorizationToken: this.publicStaticToken
1224
1245
  });
1225
- case 9:
1246
+ case 15:
1226
1247
  marketplace = _context19.sent;
1248
+ case 16:
1227
1249
  if (!marketplace.branding.use_tenant_styling) {
1228
- _context19.next = 17;
1250
+ _context19.next = 23;
1229
1251
  break;
1230
1252
  }
1231
- _context19.next = 13;
1253
+ _context19.next = 19;
1232
1254
  return this.client.ContentObjectMetadata({
1233
1255
  libraryId: this.mainSiteLibraryId,
1234
1256
  objectId: this.mainSiteId,
@@ -1236,17 +1258,17 @@ var ElvWalletClient = /*#__PURE__*/function () {
1236
1258
  authorizationToken: this.publicStaticToken,
1237
1259
  produceLinkUrls: true
1238
1260
  });
1239
- case 13:
1261
+ case 19:
1240
1262
  _context19.t0 = _context19.sent;
1241
1263
  if (_context19.t0) {
1242
- _context19.next = 16;
1264
+ _context19.next = 22;
1243
1265
  break;
1244
1266
  }
1245
1267
  _context19.t0 = {};
1246
- case 16:
1268
+ case 22:
1247
1269
  marketplace.tenantBranding = _context19.t0;
1248
- case 17:
1249
- _context19.next = 19;
1270
+ case 23:
1271
+ _context19.next = 25;
1250
1272
  return Promise.all(marketplace.items.map( /*#__PURE__*/function () {
1251
1273
  var _ref18 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee18(item, index) {
1252
1274
  var authorizationToken;
@@ -1296,7 +1318,7 @@ var ElvWalletClient = /*#__PURE__*/function () {
1296
1318
  return _ref18.apply(this, arguments);
1297
1319
  };
1298
1320
  }()));
1299
- case 19:
1321
+ case 25:
1300
1322
  marketplace.items = _context19.sent;
1301
1323
  marketplace.collections = (marketplace.collections || []).map(function (collection, collectionIndex) {
1302
1324
  return _objectSpread(_objectSpread({}, collection), {}, {
@@ -1332,9 +1354,9 @@ var ElvWalletClient = /*#__PURE__*/function () {
1332
1354
  } catch (error) {}
1333
1355
  });
1334
1356
  this.cachedMarketplaces[marketplaceId] = marketplace;
1335
- case 28:
1357
+ case 34:
1336
1358
  return _context19.abrupt("return", this.cachedMarketplaces[marketplaceId]);
1337
- case 29:
1359
+ case 35:
1338
1360
  case "end":
1339
1361
  return _context19.stop();
1340
1362
  }
@@ -1385,6 +1407,7 @@ var ElvWalletClient = /*#__PURE__*/function () {
1385
1407
  marketplaceInfo,
1386
1408
  marketplace,
1387
1409
  filters,
1410
+ headers,
1388
1411
  path,
1389
1412
  _ref21,
1390
1413
  contents,
@@ -1534,70 +1557,78 @@ var ElvWalletClient = /*#__PURE__*/function () {
1534
1557
  filters.push("info/cap:le:".concat(parseInt(capLimit)));
1535
1558
  }
1536
1559
  _context20.t0 = mode;
1537
- _context20.next = _context20.t0 === "owned" ? 29 : _context20.t0 === "listings" ? 31 : _context20.t0 === "transfers" ? 33 : _context20.t0 === "sales" ? 37 : _context20.t0 === "listing-stats" ? 41 : _context20.t0 === "sales-stats" ? 43 : _context20.t0 === "leaderboard" ? 46 : 48;
1560
+ _context20.next = _context20.t0 === "owned" ? 29 : _context20.t0 === "owned-full-meta" ? 31 : _context20.t0 === "listings" ? 34 : _context20.t0 === "transfers" ? 36 : _context20.t0 === "sales" ? 40 : _context20.t0 === "listing-stats" ? 44 : _context20.t0 === "sales-stats" ? 46 : _context20.t0 === "leaderboard" ? 49 : 51;
1538
1561
  break;
1539
1562
  case 29:
1540
1563
  path = UrlJoin("as", "wlt", userAddress || this.UserAddress());
1541
- return _context20.abrupt("break", 48);
1564
+ return _context20.abrupt("break", 51);
1542
1565
  case 31:
1566
+ path = UrlJoin("as", "apigw", "nfts");
1567
+ headers = {
1568
+ Authorization: "Bearer ".concat(this.AuthToken())
1569
+ };
1570
+ return _context20.abrupt("break", 51);
1571
+ case 34:
1543
1572
  path = UrlJoin("as", "mkt", "f");
1544
- return _context20.abrupt("break", 48);
1545
- case 33:
1573
+ return _context20.abrupt("break", 51);
1574
+ case 36:
1546
1575
  path = UrlJoin("as", "mkt", "hst", "f");
1547
1576
  filters.push("action:eq:TRANSFERRED");
1548
1577
  filters.push("action:eq:SOLD");
1549
- return _context20.abrupt("break", 48);
1550
- case 37:
1578
+ return _context20.abrupt("break", 51);
1579
+ case 40:
1551
1580
  path = UrlJoin("as", "mkt", "hst", "f");
1552
1581
  filters.push("action:eq:SOLD");
1553
1582
  filters.push("seller:co:0x");
1554
- return _context20.abrupt("break", 48);
1555
- case 41:
1583
+ return _context20.abrupt("break", 51);
1584
+ case 44:
1556
1585
  path = UrlJoin("as", "mkt", "stats", "listed");
1557
- return _context20.abrupt("break", 48);
1558
- case 43:
1586
+ return _context20.abrupt("break", 51);
1587
+ case 46:
1559
1588
  path = UrlJoin("as", "mkt", "stats", "sold");
1560
1589
  filters.push("seller:co:0x");
1561
- return _context20.abrupt("break", 48);
1562
- case 46:
1590
+ return _context20.abrupt("break", 51);
1591
+ case 49:
1563
1592
  path = UrlJoin("as", "wlt", "leaders");
1564
- return _context20.abrupt("break", 48);
1565
- case 48:
1593
+ return _context20.abrupt("break", 51);
1594
+ case 51:
1566
1595
  if (filters.length > 0) {
1567
1596
  params.filter = filters;
1568
1597
  }
1569
1598
  if (!mode.includes("stats")) {
1570
- _context20.next = 53;
1599
+ _context20.next = 56;
1571
1600
  break;
1572
1601
  }
1573
- _context20.next = 52;
1602
+ _context20.next = 55;
1574
1603
  return Utils.ResponseToJson(this.client.authClient.MakeAuthServiceRequest({
1575
1604
  path: path,
1576
1605
  method: "GET",
1577
- queryParams: params
1606
+ queryParams: params,
1607
+ headers: headers
1578
1608
  }));
1579
- case 52:
1609
+ case 55:
1580
1610
  return _context20.abrupt("return", _context20.sent);
1581
- case 53:
1611
+ case 56:
1582
1612
  _context20.t2 = Utils;
1583
- _context20.next = 56;
1613
+ _context20.next = 59;
1584
1614
  return this.client.authClient.MakeAuthServiceRequest({
1585
1615
  path: path,
1586
1616
  method: "GET",
1587
- queryParams: params
1617
+ queryParams: params,
1618
+ headers: headers
1588
1619
  });
1589
- case 56:
1620
+ case 59:
1590
1621
  _context20.t3 = _context20.sent;
1591
- _context20.next = 59;
1622
+ _context20.next = 62;
1592
1623
  return _context20.t2.ResponseToJson.call(_context20.t2, _context20.t3);
1593
- case 59:
1624
+ case 62:
1594
1625
  _context20.t1 = _context20.sent;
1595
1626
  if (_context20.t1) {
1596
- _context20.next = 62;
1627
+ _context20.next = 65;
1597
1628
  break;
1598
1629
  }
1599
1630
  _context20.t1 = [];
1600
- case 62:
1631
+ case 65:
1601
1632
  _ref21 = _context20.t1;
1602
1633
  contents = _ref21.contents;
1603
1634
  paging = _ref21.paging;
@@ -1612,11 +1643,11 @@ var ElvWalletClient = /*#__PURE__*/function () {
1612
1643
  return ["owned", "listings"].includes(mode) ? FormatNFT(_this6, item) : item;
1613
1644
  })
1614
1645
  });
1615
- case 68:
1616
- _context20.prev = 68;
1646
+ case 71:
1647
+ _context20.prev = 71;
1617
1648
  _context20.t4 = _context20["catch"](14);
1618
1649
  if (!(_context20.t4.status && _context20.t4.status.toString() === "404")) {
1619
- _context20.next = 72;
1650
+ _context20.next = 75;
1620
1651
  break;
1621
1652
  }
1622
1653
  return _context20.abrupt("return", {
@@ -1628,13 +1659,13 @@ var ElvWalletClient = /*#__PURE__*/function () {
1628
1659
  },
1629
1660
  results: []
1630
1661
  });
1631
- case 72:
1662
+ case 75:
1632
1663
  throw _context20.t4;
1633
- case 73:
1664
+ case 76:
1634
1665
  case "end":
1635
1666
  return _context20.stop();
1636
1667
  }
1637
- }, _callee20, this, [[14, 68]]);
1668
+ }, _callee20, this, [[14, 71]]);
1638
1669
  }));
1639
1670
  function FilteredQuery() {
1640
1671
  return _FilteredQuery.apply(this, arguments);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eluvio/elv-client-js",
3
- "version": "4.0.62",
3
+ "version": "4.0.64",
4
4
  "description": "Javascript client for the Eluvio Content Fabric",
5
5
  "main": "src/index.js",
6
6
  "author": "Kevin Talmadge",
package/src/Utils.js CHANGED
@@ -444,6 +444,11 @@ const Utils = {
444
444
  return buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);
445
445
  },
446
446
 
447
+ FromHex: str => {
448
+ str = str.replace(/^0x/, "");
449
+ return Buffer.from(str, "hex").toString();
450
+ },
451
+
447
452
  B64: (str, encoding="utf-8") => {
448
453
  return Buffer.from(str, encoding).toString("base64");
449
454
  },
package/src/Validation.js CHANGED
@@ -88,3 +88,23 @@ exports.ValidateDate = (date) => {
88
88
 
89
89
  return new Date(date).getTime();
90
90
  };
91
+
92
+ exports.ValidateUserWallet = async ({address, client}) => {
93
+ if(!address) {
94
+ throw Error("Address not specified");
95
+ } else if(!client) {
96
+ throw Error("Client not specified");
97
+ }
98
+
99
+ const walletAddress = await client.userProfileClient.UserWalletAddress({address});
100
+
101
+ if(!walletAddress) {
102
+ throw Error(`User address has no wallet: ${address}`);
103
+ }
104
+
105
+ const balance = await client.GetBalance({address});
106
+
107
+ if(balance < 0.1) {
108
+ throw Error(`User has no funds: ${address}`);
109
+ }
110
+ };
@@ -15,7 +15,8 @@ const {
15
15
  ValidatePresence,
16
16
  ValidateLibrary,
17
17
  ValidateObject,
18
- ValidateAddress
18
+ ValidateAddress,
19
+ ValidateUserWallet
19
20
  } = require("../Validation");
20
21
 
21
22
 
@@ -137,22 +138,39 @@ exports.AccessGroupMembers = async function({contractAddress}) {
137
138
 
138
139
  this.Log(`Retrieving members for group ${contractAddress}`);
139
140
 
140
- const length = (await this.CallContractMethod({
141
+ const hasMethod = await this.authClient.ContractHasMethod({
141
142
  contractAddress,
142
- methodName: "membersNum"
143
- })).toNumber();
144
-
145
- return await Promise.all(
146
- [...Array(length)].map(async (_, i) =>
147
- this.utils.FormatAddress(
148
- await this.CallContractMethod({
149
- contractAddress,
150
- methodName: "membersList",
151
- methodArgs: [i]
152
- })
143
+ methodName: "membersList"
144
+ });
145
+
146
+ if(hasMethod) {
147
+ const length = (await this.CallContractMethod({
148
+ contractAddress,
149
+ methodName: "membersNum"
150
+ })).toNumber();
151
+
152
+ return await Promise.all(
153
+ [...Array(length)].map(async (_, i) =>
154
+ this.utils.FormatAddress(
155
+ await this.CallContractMethod({
156
+ contractAddress,
157
+ methodName: "membersList",
158
+ methodArgs: [i]
159
+ })
160
+ )
153
161
  )
154
- )
155
- );
162
+ );
163
+ } else {
164
+ const response = this.utils.FromHex(
165
+ await this.CallContractMethod({
166
+ contractAddress,
167
+ methodName: "getMeta",
168
+ methodArgs: ["members"]
169
+ })
170
+ );
171
+
172
+ return response && JSON.parse(response) ? JSON.parse(response) : [];
173
+ }
156
174
  };
157
175
 
158
176
  /**
@@ -170,22 +188,39 @@ exports.AccessGroupManagers = async function({contractAddress}) {
170
188
 
171
189
  this.Log(`Retrieving managers for group ${contractAddress}`);
172
190
 
173
- const length = (await this.CallContractMethod({
191
+ const hasMethod = await this.authClient.ContractHasMethod({
174
192
  contractAddress,
175
- methodName: "managersNum"
176
- })).toNumber();
177
-
178
- return await Promise.all(
179
- [...Array(length)].map(async (_, i) =>
180
- this.utils.FormatAddress(
181
- await this.CallContractMethod({
182
- contractAddress,
183
- methodName: "managersList",
184
- methodArgs: [i]
185
- })
193
+ methodName: "managersList"
194
+ });
195
+
196
+ if(hasMethod) {
197
+ const length = (await this.CallContractMethod({
198
+ contractAddress,
199
+ methodName: "managersNum"
200
+ })).toNumber();
201
+
202
+ return await Promise.all(
203
+ [...Array(length)].map(async (_, i) =>
204
+ this.utils.FormatAddress(
205
+ await this.CallContractMethod({
206
+ contractAddress,
207
+ methodName: "managersList",
208
+ methodArgs: [i]
209
+ })
210
+ )
186
211
  )
187
- )
188
- );
212
+ );
213
+ } else {
214
+ const response = this.utils.FromHex(
215
+ await this.CallContractMethod({
216
+ contractAddress,
217
+ methodName: "getMeta",
218
+ methodArgs: ["managers"]
219
+ })
220
+ );
221
+
222
+ return response && JSON.parse(response) ? JSON.parse(response) : [];
223
+ }
189
224
  };
190
225
 
191
226
  /**
@@ -202,12 +237,13 @@ exports.AccessGroupManagers = async function({contractAddress}) {
202
237
  *
203
238
  * @returns {Promise<string>} - Contract address of created access group
204
239
  */
205
- exports.CreateAccessGroup = async function({name, description, metadata={}}={}) {
240
+ exports.CreateAccessGroup = async function({name, description, metadata={}, visibility=1}={}) {
206
241
  this.Log(`Creating access group: ${name || ""} ${description || ""}`);
207
242
  let { contractAddress } = await this.authClient.CreateAccessGroup();
208
243
  contractAddress = this.utils.FormatAddress(contractAddress);
209
244
 
210
245
  const objectId = this.utils.AddressToObjectId(contractAddress);
246
+ const tenantId = await this.userProfileClient.TenantId();
211
247
 
212
248
  this.Log(`Access group: ${contractAddress} ${objectId}`);
213
249
 
@@ -216,19 +252,47 @@ exports.CreateAccessGroup = async function({name, description, metadata={}}={})
216
252
  objectId: objectId
217
253
  });
218
254
 
255
+ const groupMetadata = {
256
+ public: {
257
+ name,
258
+ description
259
+ },
260
+ name,
261
+ description,
262
+ ...metadata
263
+ };
264
+
265
+ if(tenantId) {
266
+ let tenantAdminGroupAddress = this.utils.HashToAddress(tenantId);
267
+
268
+ await this.AddContentObjectGroupPermission({
269
+ objectId,
270
+ groupAddress: tenantAdminGroupAddress,
271
+ permission: "manage"
272
+ });
273
+
274
+ await this.ReplaceContractMetadata({
275
+ contractAddress,
276
+ metadataKey: "_tenantId",
277
+ metadata: tenantId
278
+ });
279
+
280
+ groupMetadata["tenantId"] = tenantId;
281
+ } else {
282
+ console.warn("No tenant ID associated with current tenant.");
283
+ }
284
+
219
285
  await this.ReplaceMetadata({
220
286
  libraryId: this.contentSpaceLibraryId,
221
287
  objectId,
222
288
  writeToken: editResponse.write_token,
223
- metadata: {
224
- public: {
225
- name,
226
- description
227
- },
228
- name,
229
- description,
230
- ...metadata
231
- }
289
+ metadata: groupMetadata
290
+ });
291
+
292
+ await this.CallContractMethodAndWait({
293
+ contractAddress,
294
+ methodName: "setVisibility",
295
+ methodArgs: [visibility],
232
296
  });
233
297
 
234
298
  await this.FinalizeContentObject({
@@ -332,13 +396,39 @@ exports.AccessGroupMembershipMethod = async function({
332
396
  exports.AddAccessGroupMember = async function({contractAddress, memberAddress}) {
333
397
  contractAddress = ValidateAddress(contractAddress);
334
398
  memberAddress = ValidateAddress(memberAddress);
399
+ await ValidateUserWallet({address: memberAddress, client: this});
335
400
 
336
- return await this.AccessGroupMembershipMethod({
401
+ const hasMethod = await this.authClient.ContractHasMethod({
402
+ contractAddress,
403
+ methodName: "membersList"
404
+ });
405
+
406
+ const response = await this.AccessGroupMembershipMethod({
337
407
  contractAddress,
338
408
  memberAddress,
339
409
  methodName: "grantAccess",
340
410
  eventName: "MemberAdded"
341
411
  });
412
+
413
+ if(!hasMethod) {
414
+ let memberList = await this.AccessGroupMembers({
415
+ contractAddress
416
+ });
417
+
418
+ memberList.push(memberAddress);
419
+
420
+ memberList = memberList.filter((value, index, self) => {
421
+ return self.indexOf(value) === index;
422
+ });
423
+
424
+ await this.ReplaceContractMetadata({
425
+ contractAddress,
426
+ metadataKey: "members",
427
+ metadata: memberList
428
+ });
429
+ }
430
+
431
+ return response;
342
432
  };
343
433
 
344
434
  /**
@@ -357,12 +447,33 @@ exports.RemoveAccessGroupMember = async function({contractAddress, memberAddress
357
447
  contractAddress = ValidateAddress(contractAddress);
358
448
  memberAddress = ValidateAddress(memberAddress);
359
449
 
360
- return await this.AccessGroupMembershipMethod({
450
+ const hasMethod = await this.authClient.ContractHasMethod({
451
+ contractAddress,
452
+ methodName: "membersList"
453
+ });
454
+
455
+ const response = await this.AccessGroupMembershipMethod({
361
456
  contractAddress,
362
457
  memberAddress,
363
458
  methodName: "revokeAccess",
364
459
  eventName: "MemberRevoked"
365
460
  });
461
+
462
+ if(!hasMethod) {
463
+ let memberList = await this.AccessGroupMembers({
464
+ contractAddress
465
+ });
466
+
467
+ memberList = memberList.filter(element => element !== memberAddress);
468
+
469
+ return await this.ReplaceContractMetadata({
470
+ contractAddress,
471
+ metadataKey: "members",
472
+ metadata: memberList
473
+ });
474
+ }
475
+
476
+ return response;
366
477
  };
367
478
 
368
479
  /**
@@ -380,13 +491,39 @@ exports.RemoveAccessGroupMember = async function({contractAddress, memberAddress
380
491
  exports.AddAccessGroupManager = async function({contractAddress, memberAddress}) {
381
492
  contractAddress = ValidateAddress(contractAddress);
382
493
  memberAddress = ValidateAddress(memberAddress);
494
+ await ValidateUserWallet({address: memberAddress, client: this});
383
495
 
384
- return await this.AccessGroupMembershipMethod({
496
+ const hasMethod = await this.authClient.ContractHasMethod({
497
+ contractAddress,
498
+ methodName: "membersList"
499
+ });
500
+
501
+ const response = await this.AccessGroupMembershipMethod({
385
502
  contractAddress,
386
503
  memberAddress,
387
504
  methodName: "grantManagerAccess",
388
505
  eventName: "ManagerAccessGranted"
389
506
  });
507
+
508
+ if(!hasMethod) {
509
+ let managerList = await this.AccessGroupManagers({
510
+ contractAddress
511
+ });
512
+
513
+ managerList.push(memberAddress);
514
+
515
+ managerList = managerList.filter((value, index, self) => {
516
+ return self.indexOf(value) === index;
517
+ });
518
+
519
+ await this.ReplaceContractMetadata({
520
+ contractAddress,
521
+ metadataKey: "managers",
522
+ metadata: managerList
523
+ });
524
+ }
525
+
526
+ return response;
390
527
  };
391
528
 
392
529
  /**
@@ -405,12 +542,33 @@ exports.RemoveAccessGroupManager = async function({contractAddress, memberAddres
405
542
  contractAddress = ValidateAddress(contractAddress);
406
543
  memberAddress = ValidateAddress(memberAddress);
407
544
 
408
- return await this.AccessGroupMembershipMethod({
545
+ const hasMethod = await this.authClient.ContractHasMethod({
546
+ contractAddress,
547
+ methodName: "managersList"
548
+ });
549
+
550
+ const response = await this.AccessGroupMembershipMethod({
409
551
  contractAddress,
410
552
  memberAddress,
411
553
  methodName: "revokeManagerAccess",
412
554
  eventName: "ManagerAccessRevoked"
413
555
  });
556
+
557
+ if(!hasMethod) {
558
+ let managerList = await this.AccessGroupManagers({
559
+ contractAddress
560
+ });
561
+
562
+ managerList = managerList.filter(element => element !== memberAddress);
563
+
564
+ return await this.ReplaceContractMetadata({
565
+ contractAddress,
566
+ metadataKey: "managers",
567
+ metadata: managerList
568
+ });
569
+ }
570
+
571
+ return response;
414
572
  };
415
573
 
416
574
  /**
@@ -232,6 +232,7 @@ exports.UserItemAttributes = async function({marketplaceParams, displayName, use
232
232
  *
233
233
  * @methodGroup User
234
234
  * @namedParams
235
+ * @param {boolean=} includeFullMetadata=false - If true, will include full metadata for each item. Ignored if not logged in.
235
236
  * @param {string=} userAddress - Address of a user. If not specified, will return results for current user
236
237
  * @param {integer=} start=0 - PAGINATION: Index from which the results should start
237
238
  * @param {integer=} limit=50 - PAGINATION: Maximum number of results to return
@@ -245,8 +246,12 @@ exports.UserItemAttributes = async function({marketplaceParams, displayName, use
245
246
  *
246
247
  * @returns {Promise<Object>} - Results of the query and pagination info
247
248
  */
248
- exports.UserItems = async function({sortBy="default"}={}) {
249
- return this.FilteredQuery({mode: "owned", sortBy, ...(arguments[0] || {})});
249
+ exports.UserItems = async function ({sortBy = "default", includeFullMetadata = false} = {}) {
250
+ if(includeFullMetadata && this.loggedIn) {
251
+ return this.FilteredQuery({mode: "owned-full-meta", sortBy, ...(arguments[0] || {})});
252
+ } else {
253
+ return this.FilteredQuery({mode: "owned", sortBy, ...(arguments[0] || {})});
254
+ }
250
255
  };
251
256
 
252
257
  /**