Profile.js

Back
  1. const Utils = require("../Utils");
  2. const UrlJoin = require("url-join");
  3. const StateStorePath = ({network, path}) => {
  4. return UrlJoin(network === "main" ? "/main" : "/dv3", path);
  5. };
  6. const UserProfilePath = ({network, appId, userAddress, key, type, mode}) => {
  7. return StateStorePath({network, path: UrlJoin(type === "app" ? "app" : "usr", type === "app" ? appId : "", userAddress, mode === "public" ? "pub" : "pri", key || "")});
  8. };
  9. /**
  10. * Methods related to getting and setting user profile data.
  11. *
  12. * @module ProfileMethods
  13. */
  14. /**
  15. * Retrieve user profile metadata for the specified user
  16. *
  17. * @methodGroup ProfileMetadata
  18. * @namedParams
  19. * @param {string=} type="app" - Specify `app` or `user` metadata.
  20. * @param {string=} mode="public" - Specify `public` or `private` metadata. If private is specified, you may only retrieve metadata for the current user.
  21. * @param {string=} appId - Namespace to use for the metadata, if retrieving app metadata. Uses the app ID specified on client initialization by default.
  22. * @param {string=} userAddress - User to retrieve metadata for. If not specified, will retrieve metadata for the current user
  23. * @param {string=} key - The metadata key to retrieve
  24. *
  25. * @returns {Promise<Object|String>} - Returns the specified metadata
  26. */
  27. exports.ProfileMetadata = async function({type="app", mode="public", appId, userAddress, key}) {
  28. try {
  29. const response = await this.stateStoreClient.Request({
  30. path: UserProfilePath({
  31. network: this.network,
  32. appId: appId || this.appId,
  33. userAddress: userAddress || this.UserAddress(),
  34. type,
  35. mode,
  36. key
  37. }),
  38. headers: mode === "private" ?
  39. {Authorization: `Bearer ${this.AuthToken()}`} : undefined
  40. });
  41. if(!response.ok) {
  42. throw response;
  43. }
  44. return (await Utils.ResponseToJson(response))[key];
  45. } catch(error) {
  46. if(error.status === 404) {
  47. return undefined;
  48. }
  49. throw error;
  50. }
  51. };
  52. /**
  53. * Set user profile metadata for the current user
  54. *
  55. * @methodGroup ProfileMetadata
  56. * @namedParams
  57. * @param {string=} type="app" - Specify `app` or `user` metadata.
  58. * @param {string=} mode="public" - Specify `public` or `private` metadata.
  59. * @param {string=} appId - Namespace to use for the metadata, if retrieving app metadata. Uses the app ID specified on client initialization by default.
  60. * @param {string} key - The metadata key to set
  61. * @param {string} value - The metadata value to set
  62. */
  63. exports.SetProfileMetadata = async function({type="app", mode="public", appId, key, value}) {
  64. await this.stateStoreClient.Request({
  65. method: "POST",
  66. path: UserProfilePath({
  67. network: this.network,
  68. appId: appId || this.appId,
  69. userAddress: this.UserAddress(),
  70. type,
  71. mode,
  72. key
  73. }),
  74. body: value,
  75. bodyType: typeof value === "object" ? "JSON" : "string",
  76. headers: {
  77. Authorization: `Bearer ${this.AuthToken()}`
  78. }
  79. });
  80. };
  81. /**
  82. * Remove user profile metadata for the current user
  83. *
  84. * @methodGroup ProfileMetadata
  85. * @namedParams
  86. * @param {string=} type="app" - Specify `app` or `user` metadata.
  87. * @param {string=} mode="public" - Specify `public` or `private` metadata.
  88. * @param {string=} appId - Namespace to use for the metadata, if retrieving app metadata.. Uses the app ID specified on client initialization by default.
  89. * @param {string} key - The metadata key to set
  90. */
  91. exports.RemoveProfileMetadata = async function({type="app", mode="public", appId, key}) {
  92. await this.stateStoreClient.Request({
  93. method: "DELETE",
  94. path: UserProfilePath({
  95. network: this.network,
  96. appId: appId || this.appId,
  97. userAddress: this.UserAddress(),
  98. type,
  99. mode,
  100. key
  101. }),
  102. headers: {
  103. Authorization: `Bearer ${this.AuthToken()}`
  104. }
  105. });
  106. };
  107. /**
  108. * Retrieve profile info for the specified user, including address, username, profile image (if set) and badges (if any)
  109. *
  110. * @methodGroup Profile
  111. * @param {string=} userAddress - Address of the user
  112. * @param {string=} userName - Username of the user
  113. *
  114. * @returns {Promise<Object>} - Profile info of the specified user
  115. */
  116. exports.Profile = async function({userAddress, userName}) {
  117. if(userName) {
  118. userAddress = await this.UserNameToAddress({userName});
  119. }
  120. if(!userAddress) {
  121. throw Error("Eluvio Wallet Client: Unable to determine profile - user address not specified");
  122. }
  123. if(!userName) {
  124. userName = await this.ProfileMetadata({type: "user", userAddress, key: "username"});
  125. }
  126. const imageUrl = await this.ProfileMetadata({type: "user", userAddress, key: "icon_url"});
  127. let badgeData = await this.ProfileMetadata({
  128. type: "app",
  129. mode: "public",
  130. appId: "elv-badge-srv",
  131. userAddress: this.badgerAddress,
  132. key: `badges_${Utils.FormatAddress(userAddress)}`
  133. });
  134. let badges = [];
  135. if(badgeData) {
  136. try {
  137. badgeData = (JSON.parse(badgeData)).badges;
  138. badges = Object.keys(badgeData).map(badgeName => ({
  139. ...badgeData[badgeName],
  140. name: badgeName
  141. }));
  142. } catch(error) {
  143. this.Log(`Failed to load badge info for ${userName || userAddress}`, true);
  144. this.Log(error, true);
  145. }
  146. }
  147. return {
  148. userAddress: Utils.FormatAddress(userAddress),
  149. userName,
  150. imageUrl,
  151. badges
  152. };
  153. };
  154. exports.UserNameToAddress = async function({userName}) {
  155. try {
  156. const response = await this.stateStoreClient.Request({
  157. method: "GET",
  158. path: StateStorePath({network: this.network, path: UrlJoin("usr", "profile_for_username", userName)}),
  159. });
  160. if(!response.ok) {
  161. throw response;
  162. }
  163. return (await Utils.ResponseToJson(response)).address;
  164. } catch(error) {
  165. if(error.status !== 404) {
  166. throw error;
  167. }
  168. }
  169. return undefined;
  170. };