@eluvio/elv-client-js 3.2.6 → 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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eluvio/elv-client-js",
3
- "version": "3.2.6",
3
+ "version": "3.2.7",
4
4
  "description": "Javascript client for the Eluvio Content Fabric",
5
5
  "main": "src/index.js",
6
6
  "author": "Kevin Talmadge",
package/src/ElvClient.js CHANGED
@@ -609,7 +609,7 @@ class ElvClient {
609
609
  idToken,
610
610
  authToken,
611
611
  tenantId,
612
- provider: this.ethClient.provider,
612
+ provider: await this.ethClient.Provider(),
613
613
  extraData,
614
614
  unsignedPublicAuth
615
615
  });
@@ -24,6 +24,7 @@ exports.UserInfo = function() {
24
24
  if(!this.loggedIn) { return; }
25
25
 
26
26
  return {
27
+ name: this.__authorization.email || this.UserAddress(),
27
28
  address: this.UserAddress() ,
28
29
  email: this.__authorization.email,
29
30
  walletType: this.__authorization.walletType,
@@ -127,20 +128,18 @@ exports.UserWalletBalance = async function(checkOnboard=false) {
127
128
 
128
129
 
129
130
  /**
130
- * <b><i>Requires login</i></b>
131
- *
132
- * Returns basic contract info about the items the current user owns, organized by contract address + token ID
131
+ * Returns basic contract info about the items the specified/current user owns, organized by contract address + token ID
133
132
  *
134
133
  * This method is significantly faster than <a href="#.UserItems">UserItems</a>, but does not include any NFT metadata.
135
134
  *
136
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.
137
138
  *
138
139
  * @returns {Promise<Object>} - Basic info about all owned items.
139
140
  */
140
- exports.UserItemInfo = async function () {
141
- if(!this.loggedIn) { return {}; }
142
-
143
- const accountId = `iusr${Utils.AddressToHash(this.UserAddress())}`;
141
+ exports.UserItemInfo = async function ({userAddress}={}) {
142
+ const accountId = `iusr${Utils.AddressToHash(userAddress || this.UserAddress())}`;
144
143
  this.profileData = await this.client.ethClient.MakeProviderCall({
145
144
  methodName: "send",
146
145
  args: [
@@ -263,6 +262,35 @@ exports.UserSales = async function({sortBy="created", sortDesc=false, contractAd
263
262
  ).results;
264
263
  };
265
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
+ };
266
294
 
267
295
  /* TENANT */
268
296
 
@@ -650,6 +678,41 @@ exports.Sales = async function() {
650
678
  return this.FilteredQuery({mode: "sales", ...(arguments[0] || {})});
651
679
  };
652
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
+
653
716
  /**
654
717
  * Retrieve stats for listings matching the specified parameters.
655
718
  *
@@ -6,6 +6,12 @@ For information about the embedded wallet app frame client, see [here](https://e
6
6
 
7
7
  ## Initializing the Client
8
8
 
9
+ Import the client using the following path:
10
+
11
+ ```javascript
12
+ import {ElvWalletClient} from "@eluvio/elv-client-js/src/walletClient/index";
13
+ ```
14
+
9
15
  Initializing the client is as simple as calling the static Initialize method with the network (main or demo) and the mode (production or staging) the client should operate upon, as well as (optionally) the marketplace to associate the client with.
10
16
 
11
17
  ```javascript
@@ -3,6 +3,7 @@ const Configuration = require("./Configuration");
3
3
  const {LinkTargetHash, FormatNFT, ActionPopup} = require("./Utils");
4
4
  const UrlJoin = require("url-join");
5
5
  const Utils = require("../Utils");
6
+ const Ethers = require("ethers");
6
7
 
7
8
 
8
9
  /**
@@ -117,6 +118,89 @@ class ElvWalletClient {
117
118
 
118
119
  /* Login and authorization */
119
120
 
121
+ /**
122
+ * Check if this client can sign without opening a popup.
123
+ *
124
+ * Generally, Eluvio custodial wallet users will require a popup prompt, while Metamask and custom OAuth users will not.
125
+ *
126
+ * @methodGroup Signatures
127
+ * @returns {boolean} - Whether or not this client can sign a message without a popup.
128
+ */
129
+ CanSign() {
130
+ if(!this.loggedIn) { return false; }
131
+
132
+ return !!this.__authorization.clusterToken ||
133
+ !!(this.UserInfo().walletName.toLowerCase() === "metamask" && window.ethereum && window.ethereum.isMetaMask && window.ethereum.chainId);
134
+ }
135
+
136
+ /**
137
+ * <b><i>Requires login</i></b>
138
+ *
139
+ * Request the current user sign the specified message.
140
+ *
141
+ * If this client is not able to perform the signature (Eluvio custodial OAuth users), a popup will be opened and the user will be prompted to sign.
142
+ *
143
+ * To check if the signature can be done without a popup, use the <a href="#CanSign">CanSign</a> method.
144
+ *
145
+ * @methodGroup Signatures
146
+ * @namedParams
147
+ * @param {string} message - The message to sign
148
+ *
149
+ * @throws - If the user rejects the signature or closes the popup, an error will be thrown.
150
+ *
151
+ * @returns {Promise<string>} - The signature of the message
152
+ */
153
+ async PersonalSign({message}) {
154
+ if(!this.loggedIn) { throw Error("ElvWalletClient: Unable to perform signature - Not logged in"); }
155
+
156
+ // Able to sign locally with either cluster token or metamask
157
+ if(this.CanSign()) {
158
+ if(this.__authorization.clusterToken) {
159
+ // Custodial wallet sign
160
+
161
+ message = typeof message === "object" ? JSON.stringify(message) : message;
162
+ message = Ethers.utils.keccak256(Buffer.from(`\x19Ethereum Signed Message:\n${message.length}${message}`, "utf-8"));
163
+
164
+ return await this.client.authClient.Sign(message);
165
+ } else if(this.UserInfo().walletName.toLowerCase() === "metamask") {
166
+ return this.SignMetamask({message, address: this.UserAddress()});
167
+ } else {
168
+ throw Error("ElvWalletClient: Unable to sign");
169
+ }
170
+ }
171
+
172
+ const parameters = {
173
+ action: "personal-sign",
174
+ message,
175
+ logIn: true
176
+ };
177
+
178
+ let url = new URL(this.appUrl);
179
+ url.hash = UrlJoin("/action", "sign", Utils.B58(JSON.stringify(parameters)));
180
+ url.searchParams.set("origin", window.location.origin);
181
+
182
+ return await new Promise(async (resolve, reject) => {
183
+ await ActionPopup({
184
+ mode: "tab",
185
+ url: url.toString(),
186
+ onCancel: () => reject("User cancelled sign"),
187
+ onMessage: async (event, Close) => {
188
+ if(!event || !event.data || event.data.type !== "FlowResponse") {
189
+ return;
190
+ }
191
+
192
+ try {
193
+ resolve(event.data.response);
194
+ } catch(error) {
195
+ reject(error);
196
+ } finally {
197
+ Close();
198
+ }
199
+ }
200
+ });
201
+ });
202
+ }
203
+
120
204
  /**
121
205
  * Direct the user to the Eluvio Media Wallet login page.
122
206
  *
@@ -415,11 +499,16 @@ class ElvWalletClient {
415
499
  throw Error("ElvWalletClient: Unable to initialize - Metamask not available");
416
500
  }
417
501
 
418
- await window.ethereum.request({method: "eth_requestAccounts"});
419
- const from = address || window.ethereum.selectedAddress;
502
+ address = address || this.UserAddress();
503
+
504
+ const accounts = await window.ethereum.request({method: "eth_requestAccounts"});
505
+ if(address && !Utils.EqualAddress(accounts[0], address)) {
506
+ throw Error(`ElvWalletClient: Incorrect MetaMask account selected. Expected ${address}, got ${accounts[0]}`);
507
+ }
508
+
420
509
  return await window.ethereum.request({
421
510
  method: "personal_sign",
422
- params: [message, from, ""],
511
+ params: [message, address, ""],
423
512
  });
424
513
  }
425
514
 
@@ -750,6 +839,10 @@ class ElvWalletClient {
750
839
  path = UrlJoin("as", "mkt", "f");
751
840
  break;
752
841
 
842
+ case "transfers":
843
+ path = UrlJoin("as", "mkt", "hst", "f");
844
+ break;
845
+
753
846
  case "sales":
754
847
  path = UrlJoin("as", "mkt", "hst", "f");
755
848
  filters.push("action:eq:SOLD");