@nadohq/mobile-client 0.35.0 → 0.37.0

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 (189) hide show
  1. package/README.md +19 -6
  2. package/dist/{MobileClient-D5TNTnLx.cjs → MobileClient-C9S_o_eC.cjs} +82 -12
  3. package/dist/MobileClient-C9S_o_eC.cjs.map +1 -0
  4. package/dist/MobileClient.cjs +1 -1
  5. package/dist/MobileClient.d.cts +64 -16
  6. package/dist/MobileClient.d.cts.map +1 -1
  7. package/dist/MobileClient.d.ts +64 -16
  8. package/dist/MobileClient.d.ts.map +1 -1
  9. package/dist/MobileClient.js +82 -12
  10. package/dist/MobileClient.js.map +1 -1
  11. package/dist/{MobileServerFailureError-CPFjwUBx.d.cts → MobileServerFailureError-CVK3aLOi.d.cts} +3 -3
  12. package/dist/{MobileServerFailureError-CPFjwUBx.d.cts.map → MobileServerFailureError-CVK3aLOi.d.cts.map} +1 -1
  13. package/dist/{MobileServerFailureError-Terv2Wzy.d.ts → MobileServerFailureError-D-76n3pS.d.ts} +3 -3
  14. package/dist/{MobileServerFailureError-Terv2Wzy.d.ts.map → MobileServerFailureError-D-76n3pS.d.ts.map} +1 -1
  15. package/dist/{buildSignedMobileRequest-BScnCGPF.d.ts → buildSignedMobileRequest-42meR4yV.d.ts} +2 -2
  16. package/dist/{buildSignedMobileRequest-BScnCGPF.d.ts.map → buildSignedMobileRequest-42meR4yV.d.ts.map} +1 -1
  17. package/dist/{buildSignedMobileRequest-CXfnhc-4.d.cts → buildSignedMobileRequest-BDxji7Vy.d.cts} +2 -2
  18. package/dist/{buildSignedMobileRequest-CXfnhc-4.d.cts.map → buildSignedMobileRequest-BDxji7Vy.d.cts.map} +1 -1
  19. package/dist/{canonicalize-CQ-pMYIt.d.ts → canonicalize-BebHhHcF.d.ts} +2 -2
  20. package/dist/canonicalize-BebHhHcF.d.ts.map +1 -0
  21. package/dist/{canonicalize-hzhboB-C.d.cts → canonicalize-CIDJLLgg.d.cts} +2 -2
  22. package/dist/canonicalize-CIDJLLgg.d.cts.map +1 -0
  23. package/dist/{clientTypes-BwakovWk.d.cts → clientTypes-2I3x4TTt.d.ts} +142 -14
  24. package/dist/clientTypes-2I3x4TTt.d.ts.map +1 -0
  25. package/dist/{clientTypes-D-o1_2Yc.d.ts → clientTypes-tLld8E6J.d.cts} +142 -14
  26. package/dist/clientTypes-tLld8E6J.d.cts.map +1 -0
  27. package/dist/dataMappers.cjs +65 -6
  28. package/dist/dataMappers.cjs.map +1 -1
  29. package/dist/dataMappers.d.cts +21 -5
  30. package/dist/dataMappers.d.cts.map +1 -1
  31. package/dist/dataMappers.d.ts +21 -5
  32. package/dist/dataMappers.d.ts.map +1 -1
  33. package/dist/dataMappers.js +62 -7
  34. package/dist/dataMappers.js.map +1 -1
  35. package/dist/{eip712MethodByType-3aiJkrHj.d.cts → eip712MethodByType-2-vyN5SU.d.cts} +2 -2
  36. package/dist/eip712MethodByType-2-vyN5SU.d.cts.map +1 -0
  37. package/dist/{eip712MethodByType-zNvZukU7.d.ts → eip712MethodByType-CAVpvZoS.d.ts} +2 -2
  38. package/dist/eip712MethodByType-CAVpvZoS.d.ts.map +1 -0
  39. package/dist/follow-Bh3UmXMc.d.cts +23 -0
  40. package/dist/follow-Bh3UmXMc.d.cts.map +1 -0
  41. package/dist/follow-DjkQm1vR.d.ts +23 -0
  42. package/dist/follow-DjkQm1vR.d.ts.map +1 -0
  43. package/dist/index.cjs +6 -1
  44. package/dist/index.d.cts +17 -16
  45. package/dist/index.d.ts +17 -16
  46. package/dist/index.js +2 -1
  47. package/dist/{mobileErrorCodes-CuQ5lyBV.d.ts → mobileErrorCodes-B3eR6t4b.d.ts} +8 -2
  48. package/dist/mobileErrorCodes-B3eR6t4b.d.ts.map +1 -0
  49. package/dist/{mobileErrorCodes-D_SyBm0k.d.cts → mobileErrorCodes-DkzBW4v3.d.cts} +8 -2
  50. package/dist/mobileErrorCodes-DkzBW4v3.d.cts.map +1 -0
  51. package/dist/{patterns-B5gi7OfV.d.ts → patterns-C-aUAnKl.d.ts} +1 -1
  52. package/dist/patterns-C-aUAnKl.d.ts.map +1 -0
  53. package/dist/{patterns-Db6fgz8i.d.cts → patterns-DS8P5LH0.d.cts} +1 -1
  54. package/dist/patterns-DS8P5LH0.d.cts.map +1 -0
  55. package/dist/{payloadHash-DVkEt-Rg.d.cts → payloadHash-BVPYKdk4.d.cts} +2 -2
  56. package/dist/payloadHash-BVPYKdk4.d.cts.map +1 -0
  57. package/dist/{payloadHash-BxL26uwq.d.ts → payloadHash-DMqE5aMo.d.ts} +2 -2
  58. package/dist/payloadHash-DMqE5aMo.d.ts.map +1 -0
  59. package/dist/{serverBaseTypes-C8KjE9Fm.d.cts → serverBaseTypes-BybrVE6L.d.cts} +2 -2
  60. package/dist/{serverBaseTypes-C8KjE9Fm.d.cts.map → serverBaseTypes-BybrVE6L.d.cts.map} +1 -1
  61. package/dist/{serverBaseTypes-B_KHFDab.d.ts → serverBaseTypes-DPB1vEvv.d.ts} +2 -2
  62. package/dist/{serverBaseTypes-B_KHFDab.d.ts.map → serverBaseTypes-DPB1vEvv.d.ts.map} +1 -1
  63. package/dist/serverExecuteTypes-DoR0InCd.d.cts +50 -0
  64. package/dist/serverExecuteTypes-DoR0InCd.d.cts.map +1 -0
  65. package/dist/serverExecuteTypes-ih4Xbr3J.d.ts +50 -0
  66. package/dist/serverExecuteTypes-ih4Xbr3J.d.ts.map +1 -0
  67. package/dist/{serverModelTypes-_cX99seo.d.ts → serverModelTypes-DV-eARP8.d.ts} +54 -10
  68. package/dist/serverModelTypes-DV-eARP8.d.ts.map +1 -0
  69. package/dist/{serverModelTypes-CwgibK-l.d.cts → serverModelTypes-KSm0CAcF.d.cts} +54 -10
  70. package/dist/serverModelTypes-KSm0CAcF.d.cts.map +1 -0
  71. package/dist/{serverQueryTypes-NIrPm2Sl.d.ts → serverQueryTypes-B9OOpiJB.d.cts} +32 -9
  72. package/dist/serverQueryTypes-B9OOpiJB.d.cts.map +1 -0
  73. package/dist/{serverQueryTypes-DwE1iJ9f.d.cts → serverQueryTypes-LygPrZn7.d.ts} +32 -9
  74. package/dist/serverQueryTypes-LygPrZn7.d.ts.map +1 -0
  75. package/dist/serverRequestTypes-BDXIPjtw.d.ts +101 -0
  76. package/dist/serverRequestTypes-BDXIPjtw.d.ts.map +1 -0
  77. package/dist/serverRequestTypes-q4xTJHk0.d.cts +101 -0
  78. package/dist/serverRequestTypes-q4xTJHk0.d.cts.map +1 -0
  79. package/dist/{serverResponseGuards-Cep5s7j5.d.ts → serverResponseGuards-BcdkKV30.d.ts} +2 -2
  80. package/dist/{serverResponseGuards-Cep5s7j5.d.ts.map → serverResponseGuards-BcdkKV30.d.ts.map} +1 -1
  81. package/dist/{serverResponseGuards-Dxt9_aGh.d.cts → serverResponseGuards-k6xK1bZ1.d.cts} +2 -2
  82. package/dist/{serverResponseGuards-Dxt9_aGh.d.cts.map → serverResponseGuards-k6xK1bZ1.d.cts.map} +1 -1
  83. package/dist/signing/buildSignedMobileRequest.cjs +1 -1
  84. package/dist/signing/buildSignedMobileRequest.d.cts +1 -1
  85. package/dist/signing/buildSignedMobileRequest.d.ts +1 -1
  86. package/dist/signing/canonicalize.cjs +17 -0
  87. package/dist/signing/canonicalize.cjs.map +1 -1
  88. package/dist/signing/canonicalize.d.cts +1 -1
  89. package/dist/signing/canonicalize.d.ts +1 -1
  90. package/dist/signing/canonicalize.js +17 -0
  91. package/dist/signing/canonicalize.js.map +1 -1
  92. package/dist/signing/eip712MethodByType.cjs +4 -1
  93. package/dist/signing/eip712MethodByType.cjs.map +1 -1
  94. package/dist/signing/eip712MethodByType.d.cts +1 -1
  95. package/dist/signing/eip712MethodByType.d.ts +1 -1
  96. package/dist/signing/eip712MethodByType.js +4 -1
  97. package/dist/signing/eip712MethodByType.js.map +1 -1
  98. package/dist/signing/index.d.cts +6 -6
  99. package/dist/signing/index.d.ts +6 -6
  100. package/dist/signing/payloadHash.cjs +1 -1
  101. package/dist/signing/payloadHash.d.cts +1 -1
  102. package/dist/signing/payloadHash.d.ts +1 -1
  103. package/dist/signing/types.d.cts +2 -2
  104. package/dist/signing/types.d.ts +2 -2
  105. package/dist/types/MobileServerFailureError.cjs +1 -1
  106. package/dist/types/MobileServerFailureError.d.cts +1 -1
  107. package/dist/types/MobileServerFailureError.d.ts +1 -1
  108. package/dist/types/clientTypes.d.cts +2 -2
  109. package/dist/types/clientTypes.d.ts +2 -2
  110. package/dist/types/index.d.cts +9 -9
  111. package/dist/types/index.d.ts +9 -9
  112. package/dist/types/mobileErrorCodes.cjs +13 -1
  113. package/dist/types/mobileErrorCodes.cjs.map +1 -1
  114. package/dist/types/mobileErrorCodes.d.cts +1 -1
  115. package/dist/types/mobileErrorCodes.d.ts +1 -1
  116. package/dist/types/mobileErrorCodes.js +12 -0
  117. package/dist/types/mobileErrorCodes.js.map +1 -1
  118. package/dist/types/serverBaseTypes.d.cts +1 -1
  119. package/dist/types/serverBaseTypes.d.ts +1 -1
  120. package/dist/types/serverExecuteTypes.d.cts +2 -2
  121. package/dist/types/serverExecuteTypes.d.ts +2 -2
  122. package/dist/types/serverModelTypes.cjs.map +1 -1
  123. package/dist/types/serverModelTypes.d.cts +2 -2
  124. package/dist/types/serverModelTypes.d.ts +2 -2
  125. package/dist/types/serverModelTypes.js.map +1 -1
  126. package/dist/types/serverQueryTypes.d.cts +2 -2
  127. package/dist/types/serverQueryTypes.d.ts +2 -2
  128. package/dist/types/serverRequestTypes.d.cts +2 -2
  129. package/dist/types/serverRequestTypes.d.ts +2 -2
  130. package/dist/{types-47IPsDyA.d.cts → types-B8lDIhBP.d.ts} +30 -7
  131. package/dist/types-B8lDIhBP.d.ts.map +1 -0
  132. package/dist/{types-D5kFJzEX.d.ts → types-CClB00EN.d.cts} +30 -7
  133. package/dist/types-CClB00EN.d.cts.map +1 -0
  134. package/dist/utils/follow.cjs +28 -0
  135. package/dist/utils/follow.cjs.map +1 -0
  136. package/dist/utils/follow.d.cts +2 -0
  137. package/dist/utils/follow.d.ts +2 -0
  138. package/dist/utils/follow.js +24 -0
  139. package/dist/utils/follow.js.map +1 -0
  140. package/dist/utils/index.cjs +5 -0
  141. package/dist/utils/index.d.cts +4 -3
  142. package/dist/utils/index.d.ts +4 -3
  143. package/dist/utils/index.js +2 -1
  144. package/dist/utils/patterns.d.cts +1 -1
  145. package/dist/utils/patterns.d.ts +1 -1
  146. package/dist/utils/serverResponseGuards.d.cts +1 -1
  147. package/dist/utils/serverResponseGuards.d.ts +1 -1
  148. package/package.json +3 -3
  149. package/src/MobileClient.ts +138 -21
  150. package/src/dataMappers.ts +89 -5
  151. package/src/signing/canonicalize.ts +20 -0
  152. package/src/signing/eip712MethodByType.ts +3 -0
  153. package/src/signing/signing.test.ts +58 -4
  154. package/src/signing/types.ts +34 -1
  155. package/src/types/clientTypes.ts +148 -11
  156. package/src/types/mobileErrorCodes.ts +12 -0
  157. package/src/types/serverExecuteTypes.ts +40 -2
  158. package/src/types/serverModelTypes.ts +55 -8
  159. package/src/types/serverQueryTypes.ts +35 -4
  160. package/src/types/serverRequestTypes.ts +41 -6
  161. package/src/utils/follow.ts +22 -0
  162. package/src/utils/index.ts +1 -0
  163. package/dist/MobileClient-D5TNTnLx.cjs.map +0 -1
  164. package/dist/canonicalize-CQ-pMYIt.d.ts.map +0 -1
  165. package/dist/canonicalize-hzhboB-C.d.cts.map +0 -1
  166. package/dist/clientTypes-BwakovWk.d.cts.map +0 -1
  167. package/dist/clientTypes-D-o1_2Yc.d.ts.map +0 -1
  168. package/dist/eip712MethodByType-3aiJkrHj.d.cts.map +0 -1
  169. package/dist/eip712MethodByType-zNvZukU7.d.ts.map +0 -1
  170. package/dist/mobileErrorCodes-CuQ5lyBV.d.ts.map +0 -1
  171. package/dist/mobileErrorCodes-D_SyBm0k.d.cts.map +0 -1
  172. package/dist/patterns-B5gi7OfV.d.ts.map +0 -1
  173. package/dist/patterns-Db6fgz8i.d.cts.map +0 -1
  174. package/dist/payloadHash-BxL26uwq.d.ts.map +0 -1
  175. package/dist/payloadHash-DVkEt-Rg.d.cts.map +0 -1
  176. package/dist/serverExecuteTypes-Cb5v7y0A.d.cts +0 -19
  177. package/dist/serverExecuteTypes-Cb5v7y0A.d.cts.map +0 -1
  178. package/dist/serverExecuteTypes-GFjZj_DC.d.ts +0 -19
  179. package/dist/serverExecuteTypes-GFjZj_DC.d.ts.map +0 -1
  180. package/dist/serverModelTypes-CwgibK-l.d.cts.map +0 -1
  181. package/dist/serverModelTypes-_cX99seo.d.ts.map +0 -1
  182. package/dist/serverQueryTypes-DwE1iJ9f.d.cts.map +0 -1
  183. package/dist/serverQueryTypes-NIrPm2Sl.d.ts.map +0 -1
  184. package/dist/serverRequestTypes-516zXnQ6.d.ts +0 -72
  185. package/dist/serverRequestTypes-516zXnQ6.d.ts.map +0 -1
  186. package/dist/serverRequestTypes-GAtVYIda.d.cts +0 -72
  187. package/dist/serverRequestTypes-GAtVYIda.d.cts.map +0 -1
  188. package/dist/types-47IPsDyA.d.cts.map +0 -1
  189. package/dist/types-D5kFJzEX.d.ts.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types-CClB00EN.d.cts","names":[],"sources":["../src/signing/src/signing/types.ts"],"mappings":";;;;;;;;AAmBA;;;;;;;;;;;;KAAY,iBAAA;EACN,IAAA;EAAsB,YAAA;AAAA;EACtB,IAAA;EAA0B,YAAA;AAAA;EAE1B,IAAA;EACA,UAAA;EACA,QAAA,EAAU,0BAAA;EAGV,MAAA;EACA,WAAA;AAAA;EAGA,IAAA;EACA,UAAA,EAAY,GAAA,EAUZ;EARA,YAAA;AAAA;EAGA,IAAA;EACA,UAAA,EAAY,GAAA,EAYZ;EAVA,MAAA,iBAUK;EARL,KAAA;AAAA;EAGA,IAAA;EACA,UAAA,EAAY,GAAA,EAWR;EATJ,MAAA,iBASJ;EAPI,KAAA;AAAA;;;;KAMM,uBAAA,WAAkC,iBAAA,YAC5C,OAAA,CAAQ,iBAAA;EAAqB,IAAA,EAAM,CAAA;AAAA;;AAAC;AAMtC;;KAAY,uBAAA,WAAkC,iBAAA,YAA6B,IAAA,CACzE,uBAAA,CAAwB,CAAA;;;;;KAQd,mBAAA,WACA,iBAAA,GAAoB,iBAAA,IAC5B,CAAA;EACF,SAAA,EAAW,GAAA;EACX,MAAA,EAAQ,GAAA;EACR,KAAA;AAAA;;;;UAMe,8BAAA,SAAuC,yBAAA;EACtD,YAAA,EAAc,uBAAA;EACd,KAAA,EAAO,iBAAA;EAbsB;;;EAiB7B,KAAA;AAAA"}
@@ -0,0 +1,28 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ //#region src/utils/follow.ts
3
+ /**
4
+ * Maximum Followers/Following page size the backend accepts. Requests outside 1–50 fail with
5
+ * `INVALID_FOLLOW_LIMIT`.
6
+ */
7
+ const MOBILE_FOLLOW_LIST_MAX_PAGE_SIZE = 50;
8
+ /**
9
+ * Page size the backend uses when `limit` is omitted from a Followers or Following request.
10
+ */
11
+ const MOBILE_FOLLOW_LIST_DEFAULT_PAGE_SIZE = 25;
12
+ /**
13
+ * Number of Followed By preview identities a follow summary carries. Fixed by the backend rather than
14
+ * requested, so use it to size the preview UI; `followedByCount` still reports the full intersection.
15
+ */
16
+ const MOBILE_FOLLOWED_BY_PREVIEW_LIMIT = 2;
17
+ /**
18
+ * Maximum number of subaccounts a single profiles lookup accepts. An empty list, a duplicate, or more than
19
+ * this many fail with `INVALID_PROFILES_REQUEST`.
20
+ */
21
+ const MOBILE_PROFILES_MAX_BATCH_SIZE = 25;
22
+ //#endregion
23
+ exports.MOBILE_FOLLOWED_BY_PREVIEW_LIMIT = MOBILE_FOLLOWED_BY_PREVIEW_LIMIT;
24
+ exports.MOBILE_FOLLOW_LIST_DEFAULT_PAGE_SIZE = MOBILE_FOLLOW_LIST_DEFAULT_PAGE_SIZE;
25
+ exports.MOBILE_FOLLOW_LIST_MAX_PAGE_SIZE = MOBILE_FOLLOW_LIST_MAX_PAGE_SIZE;
26
+ exports.MOBILE_PROFILES_MAX_BATCH_SIZE = MOBILE_PROFILES_MAX_BATCH_SIZE;
27
+
28
+ //# sourceMappingURL=follow.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"follow.cjs","names":[],"sources":["../../src/utils/follow.ts"],"sourcesContent":["/**\n * Maximum Followers/Following page size the backend accepts. Requests outside 1–50 fail with\n * `INVALID_FOLLOW_LIMIT`.\n */\nexport const MOBILE_FOLLOW_LIST_MAX_PAGE_SIZE = 50;\n\n/**\n * Page size the backend uses when `limit` is omitted from a Followers or Following request.\n */\nexport const MOBILE_FOLLOW_LIST_DEFAULT_PAGE_SIZE = 25;\n\n/**\n * Number of Followed By preview identities a follow summary carries. Fixed by the backend rather than\n * requested, so use it to size the preview UI; `followedByCount` still reports the full intersection.\n */\nexport const MOBILE_FOLLOWED_BY_PREVIEW_LIMIT = 2;\n\n/**\n * Maximum number of subaccounts a single profiles lookup accepts. An empty list, a duplicate, or more than\n * this many fail with `INVALID_PROFILES_REQUEST`.\n */\nexport const MOBILE_PROFILES_MAX_BATCH_SIZE = 25;\n"],"mappings":";;;;;;AAIA,MAAa,mCAAmC;;;;AAKhD,MAAa,uCAAuC;;;;;AAMpD,MAAa,mCAAmC;;;;;AAMhD,MAAa,iCAAiC"}
@@ -0,0 +1,2 @@
1
+ import { i as MOBILE_PROFILES_MAX_BATCH_SIZE, n as MOBILE_FOLLOW_LIST_DEFAULT_PAGE_SIZE, r as MOBILE_FOLLOW_LIST_MAX_PAGE_SIZE, t as MOBILE_FOLLOWED_BY_PREVIEW_LIMIT } from "../follow-Bh3UmXMc.cjs";
2
+ export { MOBILE_FOLLOWED_BY_PREVIEW_LIMIT, MOBILE_FOLLOW_LIST_DEFAULT_PAGE_SIZE, MOBILE_FOLLOW_LIST_MAX_PAGE_SIZE, MOBILE_PROFILES_MAX_BATCH_SIZE };
@@ -0,0 +1,2 @@
1
+ import { i as MOBILE_PROFILES_MAX_BATCH_SIZE, n as MOBILE_FOLLOW_LIST_DEFAULT_PAGE_SIZE, r as MOBILE_FOLLOW_LIST_MAX_PAGE_SIZE, t as MOBILE_FOLLOWED_BY_PREVIEW_LIMIT } from "../follow-DjkQm1vR.js";
2
+ export { MOBILE_FOLLOWED_BY_PREVIEW_LIMIT, MOBILE_FOLLOW_LIST_DEFAULT_PAGE_SIZE, MOBILE_FOLLOW_LIST_MAX_PAGE_SIZE, MOBILE_PROFILES_MAX_BATCH_SIZE };
@@ -0,0 +1,24 @@
1
+ //#region src/utils/follow.ts
2
+ /**
3
+ * Maximum Followers/Following page size the backend accepts. Requests outside 1–50 fail with
4
+ * `INVALID_FOLLOW_LIMIT`.
5
+ */
6
+ const MOBILE_FOLLOW_LIST_MAX_PAGE_SIZE = 50;
7
+ /**
8
+ * Page size the backend uses when `limit` is omitted from a Followers or Following request.
9
+ */
10
+ const MOBILE_FOLLOW_LIST_DEFAULT_PAGE_SIZE = 25;
11
+ /**
12
+ * Number of Followed By preview identities a follow summary carries. Fixed by the backend rather than
13
+ * requested, so use it to size the preview UI; `followedByCount` still reports the full intersection.
14
+ */
15
+ const MOBILE_FOLLOWED_BY_PREVIEW_LIMIT = 2;
16
+ /**
17
+ * Maximum number of subaccounts a single profiles lookup accepts. An empty list, a duplicate, or more than
18
+ * this many fail with `INVALID_PROFILES_REQUEST`.
19
+ */
20
+ const MOBILE_PROFILES_MAX_BATCH_SIZE = 25;
21
+ //#endregion
22
+ export { MOBILE_FOLLOWED_BY_PREVIEW_LIMIT, MOBILE_FOLLOW_LIST_DEFAULT_PAGE_SIZE, MOBILE_FOLLOW_LIST_MAX_PAGE_SIZE, MOBILE_PROFILES_MAX_BATCH_SIZE };
23
+
24
+ //# sourceMappingURL=follow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"follow.js","names":[],"sources":["../../src/utils/follow.ts"],"sourcesContent":["/**\n * Maximum Followers/Following page size the backend accepts. Requests outside 1–50 fail with\n * `INVALID_FOLLOW_LIMIT`.\n */\nexport const MOBILE_FOLLOW_LIST_MAX_PAGE_SIZE = 50;\n\n/**\n * Page size the backend uses when `limit` is omitted from a Followers or Following request.\n */\nexport const MOBILE_FOLLOW_LIST_DEFAULT_PAGE_SIZE = 25;\n\n/**\n * Number of Followed By preview identities a follow summary carries. Fixed by the backend rather than\n * requested, so use it to size the preview UI; `followedByCount` still reports the full intersection.\n */\nexport const MOBILE_FOLLOWED_BY_PREVIEW_LIMIT = 2;\n\n/**\n * Maximum number of subaccounts a single profiles lookup accepts. An empty list, a duplicate, or more than\n * this many fail with `INVALID_PROFILES_REQUEST`.\n */\nexport const MOBILE_PROFILES_MAX_BATCH_SIZE = 25;\n"],"mappings":";;;;;AAIA,MAAa,mCAAmC;;;;AAKhD,MAAa,uCAAuC;;;;;AAMpD,MAAa,mCAAmC;;;;;AAMhD,MAAa,iCAAiC"}
@@ -1,9 +1,14 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_utils_serverResponseGuards = require("./serverResponseGuards.cjs");
3
3
  const require_utils_feed = require("./feed.cjs");
4
+ const require_utils_follow = require("./follow.cjs");
4
5
  const require_utils_patterns = require("./patterns.cjs");
5
6
  exports.MOBILE_DISPLAY_NAME_PATTERN = require_utils_patterns.MOBILE_DISPLAY_NAME_PATTERN;
6
7
  exports.MOBILE_FEED_MAX_PAGE_SIZE = require_utils_feed.MOBILE_FEED_MAX_PAGE_SIZE;
7
8
  exports.MOBILE_FEED_MIN_NOTIONAL_FLOOR = require_utils_feed.MOBILE_FEED_MIN_NOTIONAL_FLOOR;
9
+ exports.MOBILE_FOLLOWED_BY_PREVIEW_LIMIT = require_utils_follow.MOBILE_FOLLOWED_BY_PREVIEW_LIMIT;
10
+ exports.MOBILE_FOLLOW_LIST_DEFAULT_PAGE_SIZE = require_utils_follow.MOBILE_FOLLOW_LIST_DEFAULT_PAGE_SIZE;
11
+ exports.MOBILE_FOLLOW_LIST_MAX_PAGE_SIZE = require_utils_follow.MOBILE_FOLLOW_LIST_MAX_PAGE_SIZE;
12
+ exports.MOBILE_PROFILES_MAX_BATCH_SIZE = require_utils_follow.MOBILE_PROFILES_MAX_BATCH_SIZE;
8
13
  exports.isMobileServerFailureResponse = require_utils_serverResponseGuards.isMobileServerFailureResponse;
9
14
  exports.isMobileServerSuccessResponse = require_utils_serverResponseGuards.isMobileServerSuccessResponse;
@@ -1,4 +1,5 @@
1
1
  import { n as MOBILE_FEED_MIN_NOTIONAL_FLOOR, t as MOBILE_FEED_MAX_PAGE_SIZE } from "../feed-CBIwOhTO.cjs";
2
- import { t as MOBILE_DISPLAY_NAME_PATTERN } from "../patterns-Db6fgz8i.cjs";
3
- import { n as isMobileServerSuccessResponse, t as isMobileServerFailureResponse } from "../serverResponseGuards-Dxt9_aGh.cjs";
4
- export { MOBILE_DISPLAY_NAME_PATTERN, MOBILE_FEED_MAX_PAGE_SIZE, MOBILE_FEED_MIN_NOTIONAL_FLOOR, isMobileServerFailureResponse, isMobileServerSuccessResponse };
2
+ import { i as MOBILE_PROFILES_MAX_BATCH_SIZE, n as MOBILE_FOLLOW_LIST_DEFAULT_PAGE_SIZE, r as MOBILE_FOLLOW_LIST_MAX_PAGE_SIZE, t as MOBILE_FOLLOWED_BY_PREVIEW_LIMIT } from "../follow-Bh3UmXMc.cjs";
3
+ import { t as MOBILE_DISPLAY_NAME_PATTERN } from "../patterns-DS8P5LH0.cjs";
4
+ import { n as isMobileServerSuccessResponse, t as isMobileServerFailureResponse } from "../serverResponseGuards-k6xK1bZ1.cjs";
5
+ export { MOBILE_DISPLAY_NAME_PATTERN, MOBILE_FEED_MAX_PAGE_SIZE, MOBILE_FEED_MIN_NOTIONAL_FLOOR, MOBILE_FOLLOWED_BY_PREVIEW_LIMIT, MOBILE_FOLLOW_LIST_DEFAULT_PAGE_SIZE, MOBILE_FOLLOW_LIST_MAX_PAGE_SIZE, MOBILE_PROFILES_MAX_BATCH_SIZE, isMobileServerFailureResponse, isMobileServerSuccessResponse };
@@ -1,4 +1,5 @@
1
1
  import { n as MOBILE_FEED_MIN_NOTIONAL_FLOOR, t as MOBILE_FEED_MAX_PAGE_SIZE } from "../feed-BF5k6Ryu.js";
2
- import { t as MOBILE_DISPLAY_NAME_PATTERN } from "../patterns-B5gi7OfV.js";
3
- import { n as isMobileServerSuccessResponse, t as isMobileServerFailureResponse } from "../serverResponseGuards-Cep5s7j5.js";
4
- export { MOBILE_DISPLAY_NAME_PATTERN, MOBILE_FEED_MAX_PAGE_SIZE, MOBILE_FEED_MIN_NOTIONAL_FLOOR, isMobileServerFailureResponse, isMobileServerSuccessResponse };
2
+ import { i as MOBILE_PROFILES_MAX_BATCH_SIZE, n as MOBILE_FOLLOW_LIST_DEFAULT_PAGE_SIZE, r as MOBILE_FOLLOW_LIST_MAX_PAGE_SIZE, t as MOBILE_FOLLOWED_BY_PREVIEW_LIMIT } from "../follow-DjkQm1vR.js";
3
+ import { t as MOBILE_DISPLAY_NAME_PATTERN } from "../patterns-C-aUAnKl.js";
4
+ import { n as isMobileServerSuccessResponse, t as isMobileServerFailureResponse } from "../serverResponseGuards-BcdkKV30.js";
5
+ export { MOBILE_DISPLAY_NAME_PATTERN, MOBILE_FEED_MAX_PAGE_SIZE, MOBILE_FEED_MIN_NOTIONAL_FLOOR, MOBILE_FOLLOWED_BY_PREVIEW_LIMIT, MOBILE_FOLLOW_LIST_DEFAULT_PAGE_SIZE, MOBILE_FOLLOW_LIST_MAX_PAGE_SIZE, MOBILE_PROFILES_MAX_BATCH_SIZE, isMobileServerFailureResponse, isMobileServerSuccessResponse };
@@ -1,4 +1,5 @@
1
1
  import { isMobileServerFailureResponse, isMobileServerSuccessResponse } from "./serverResponseGuards.js";
2
2
  import { MOBILE_FEED_MAX_PAGE_SIZE, MOBILE_FEED_MIN_NOTIONAL_FLOOR } from "./feed.js";
3
+ import { MOBILE_FOLLOWED_BY_PREVIEW_LIMIT, MOBILE_FOLLOW_LIST_DEFAULT_PAGE_SIZE, MOBILE_FOLLOW_LIST_MAX_PAGE_SIZE, MOBILE_PROFILES_MAX_BATCH_SIZE } from "./follow.js";
3
4
  import { MOBILE_DISPLAY_NAME_PATTERN } from "./patterns.js";
4
- export { MOBILE_DISPLAY_NAME_PATTERN, MOBILE_FEED_MAX_PAGE_SIZE, MOBILE_FEED_MIN_NOTIONAL_FLOOR, isMobileServerFailureResponse, isMobileServerSuccessResponse };
5
+ export { MOBILE_DISPLAY_NAME_PATTERN, MOBILE_FEED_MAX_PAGE_SIZE, MOBILE_FEED_MIN_NOTIONAL_FLOOR, MOBILE_FOLLOWED_BY_PREVIEW_LIMIT, MOBILE_FOLLOW_LIST_DEFAULT_PAGE_SIZE, MOBILE_FOLLOW_LIST_MAX_PAGE_SIZE, MOBILE_PROFILES_MAX_BATCH_SIZE, isMobileServerFailureResponse, isMobileServerSuccessResponse };
@@ -1,2 +1,2 @@
1
- import { t as MOBILE_DISPLAY_NAME_PATTERN } from "../patterns-Db6fgz8i.cjs";
1
+ import { t as MOBILE_DISPLAY_NAME_PATTERN } from "../patterns-DS8P5LH0.cjs";
2
2
  export { MOBILE_DISPLAY_NAME_PATTERN };
@@ -1,2 +1,2 @@
1
- import { t as MOBILE_DISPLAY_NAME_PATTERN } from "../patterns-B5gi7OfV.js";
1
+ import { t as MOBILE_DISPLAY_NAME_PATTERN } from "../patterns-C-aUAnKl.js";
2
2
  export { MOBILE_DISPLAY_NAME_PATTERN };
@@ -1,2 +1,2 @@
1
- import { n as isMobileServerSuccessResponse, t as isMobileServerFailureResponse } from "../serverResponseGuards-Dxt9_aGh.cjs";
1
+ import { n as isMobileServerSuccessResponse, t as isMobileServerFailureResponse } from "../serverResponseGuards-k6xK1bZ1.cjs";
2
2
  export { isMobileServerFailureResponse, isMobileServerSuccessResponse };
@@ -1,2 +1,2 @@
1
- import { n as isMobileServerSuccessResponse, t as isMobileServerFailureResponse } from "../serverResponseGuards-Cep5s7j5.js";
1
+ import { n as isMobileServerSuccessResponse, t as isMobileServerFailureResponse } from "../serverResponseGuards-BcdkKV30.js";
2
2
  export { isMobileServerFailureResponse, isMobileServerSuccessResponse };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nadohq/mobile-client",
3
- "version": "0.35.0",
3
+ "version": "0.37.0",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "description": "HTTP client for the Nado mobile service API — username claims, profiles, privacy settings, and push notification devices & preferences",
@@ -42,7 +42,7 @@
42
42
  "types": "./dist/index.d.ts",
43
43
  "dependencies": {
44
44
  "@msgpack/msgpack": "3.1.3",
45
- "@nadohq/shared": "^0.35.0",
45
+ "@nadohq/shared": "^0.37.0",
46
46
  "axios": "1.16.1"
47
47
  },
48
48
  "peerDependencies": {
@@ -54,5 +54,5 @@
54
54
  "bignumber.js": "11.1.1",
55
55
  "viem": "2.52.0"
56
56
  },
57
- "gitHead": "232349cb0f432b024dab1b1c623e8ad3b74b8f85"
57
+ "gitHead": "35e47d01ea725fea6311fa911febdf7483118ef4"
58
58
  }
@@ -7,28 +7,37 @@ import {
7
7
  import axios, { AxiosInstance, AxiosResponse } from 'axios';
8
8
  import {
9
9
  mapMobileFeedPage,
10
+ mapMobileFollowListPage,
11
+ mapMobileFollowMutationResult,
10
12
  mapMobileNotificationPreferences,
11
13
  mapMobileNotificationPreferencesToServer,
14
+ mapMobileProfilesIncludeToServer,
12
15
  mapMobilePublicProfile,
13
16
  mapMobileRegisteredWallet,
14
17
  } from './dataMappers';
15
18
  import {
16
19
  buildSignedMobileRequest,
17
20
  MobileSignedInner,
21
+ MobileSignedInnerByType,
18
22
  MobileSignedInnerParams,
19
23
  MobileSignedRequest,
20
24
  } from './signing';
21
25
  import {
22
26
  GetMobileFeedParams,
27
+ GetMobileFollowersParams,
28
+ GetMobileFollowingParams,
23
29
  GetMobileNotificationPreferencesParams,
24
- GetMobilePublicProfileParams,
30
+ GetMobileProfilesParams,
25
31
  GetMobileRegisteredWalletParams,
26
32
  GetMobileUsernameAvailabilityParams,
27
33
  MobileFeedPage,
34
+ MobileFollowListPage,
35
+ MobileFollowMutationResult,
28
36
  MobileNotificationPreferences,
29
37
  MobilePublicProfile,
30
38
  MobileRegisteredWallet,
31
39
  MobileRegisterExpoTokenParams,
40
+ MobileSetFollowParams,
32
41
  MobileSetPrivateModeParams,
33
42
  MobileSetUsernameParams,
34
43
  MobileSignedRequestParams,
@@ -40,15 +49,19 @@ import { MobileServerFailureError } from './types/MobileServerFailureError';
40
49
  import { MobileServerSuccessResponse } from './types/serverBaseTypes';
41
50
  import {
42
51
  MobileServerExecuteResult,
52
+ MobileServerExecuteSuccessResponse,
43
53
  MobileServerPublicExecuteRequest,
44
54
  } from './types/serverExecuteTypes';
45
55
  import {
46
56
  MobileServerPublicQueryRequest,
47
57
  MobileServerPublicQuerySuccessResponse,
58
+ MobileServerSignedQuerySuccessResponse,
48
59
  } from './types/serverQueryTypes';
49
60
  import {
61
+ MobileServerExecuteRequestType,
50
62
  MobileServerPublicQueryRequestByType,
51
63
  MobileServerPublicQueryRequestType,
64
+ MobileServerSignedQueryRequestType,
52
65
  } from './types/serverRequestTypes';
53
66
  import {
54
67
  isMobileServerFailureResponse,
@@ -78,8 +91,8 @@ export interface MobileClientOpts {
78
91
  }
79
92
 
80
93
  /**
81
- * Client for the Nado mobile service API: usernames, public profile lookups, the global trade feed, privacy
82
- * settings, and push notification device/preference management.
94
+ * Client for the Nado mobile service API: usernames, public profile lookups, the global trade feed, the
95
+ * follower/following graph, privacy settings, and push notification device/preference management.
83
96
  */
84
97
  export class MobileClient {
85
98
  readonly opts: MobileClientOpts;
@@ -125,22 +138,32 @@ export class MobileClient {
125
138
  }
126
139
 
127
140
  /**
128
- * Looks up a subaccount's public profile. Every non-isolated subaccount resolves, with `username` and
129
- * `displayName` `null` until a username is claimed. Private Mode does not hide the profile itself, only the
130
- * account's activity.
141
+ * Looks up public profiles, optionally with follower totals and a follow summary. Returns one profile per
142
+ * requested subaccount, in the requested order, so callers can correlate positionally. Every non-isolated
143
+ * subaccount resolves, with `username` and `displayName` `null` until a username is claimed. Private Mode
144
+ * does not hide the profile itself, only the account's activity.
131
145
  *
132
- * @throws {MobileServerFailureError} With error code `PROFILE_NOT_FOUND` if the subaccount is in the
133
- * engine-created isolated namespace, which cannot own a profile.
146
+ * This is the only profile route, so use it for a single subaccount too. It is unsigned, which means
147
+ * `include.followSummary.viewAs` is an unauthenticated claim: the follow *lists* remain signed precisely
148
+ * because they prove the viewer.
149
+ *
150
+ * @throws {MobileServerFailureError} With error code `INVALID_PROFILES_REQUEST` if `subaccounts` is empty,
151
+ * holds duplicates, or exceeds `MOBILE_PROFILES_MAX_BATCH_SIZE` (25), or `PROFILE_NOT_FOUND` if any
152
+ * requested subaccount — or the follow summary's `viewAs` — is in the engine-created isolated namespace.
153
+ * One isolated member fails the whole batch rather than being omitted.
134
154
  */
135
- async getPublicProfile(
136
- params: GetMobilePublicProfileParams,
137
- ): Promise<MobilePublicProfile> {
138
- const body: MobileServerPublicQueryRequest<'profile'> = {
139
- type: 'profile',
140
- subaccount: subaccountToHex(params),
155
+ async getProfiles(
156
+ params: GetMobileProfilesParams,
157
+ ): Promise<MobilePublicProfile[]> {
158
+ const body: MobileServerPublicQueryRequest<'profiles'> = {
159
+ type: 'profiles',
160
+ subaccounts: params.subaccounts.map(subaccountToHex),
161
+ include: params.include
162
+ ? mapMobileProfilesIncludeToServer(params.include)
163
+ : undefined,
141
164
  };
142
165
  const data = await this.publicQuery(body);
143
- return mapMobilePublicProfile(data.profile);
166
+ return data.profiles.map(mapMobilePublicProfile);
144
167
  }
145
168
 
146
169
  /**
@@ -253,6 +276,52 @@ export class MobileClient {
253
276
  return this.publicExecute(body);
254
277
  }
255
278
 
279
+ /*
280
+ Signed queries
281
+ */
282
+
283
+ /**
284
+ * Fetches a page of the accounts that follow the given Profile.
285
+ *
286
+ * Familiar accounts (those the signing Viewer follows) come first, unfamiliar second, and within each group
287
+ * the newest listed relationship first with a bytes32 tie-break. The grouping is evaluated per request
288
+ * against the live graph, so following an account from inside the list moves it between groups on the next
289
+ * page — deduplicate by subaccount and do not re-sort locally.
290
+ *
291
+ * @throws {MobileServerFailureError} With error code `PROFILE_NOT_FOUND` if the viewed Profile is isolated,
292
+ * `INVALID_FOLLOW_CURSOR` if the cursor is malformed or was issued for a different Viewer, Profile, or list
293
+ * direction (discard it and restart from the first page), or `INVALID_FOLLOW_LIMIT` if `limit` is outside
294
+ * 1–50.
295
+ */
296
+ async getFollowers(
297
+ params: GetMobileFollowersParams,
298
+ ): Promise<MobileFollowListPage> {
299
+ const signedRequest = await this.getSignedRequest('followers', params, {
300
+ subaccount: subaccountToHex(params.target),
301
+ cursor: params.cursor ?? null,
302
+ limit: params.limit ?? null,
303
+ });
304
+ const data = await this.signedQuery(signedRequest);
305
+ return mapMobileFollowListPage(data);
306
+ }
307
+
308
+ /**
309
+ * Fetches a page of the accounts the given Profile follows. Ordering, cursor rules, and errors match
310
+ * {@link MobileClient.getFollowers}. When the Viewer reads their own Following list every row is familiar,
311
+ * so every `isFollowing` is `true`.
312
+ */
313
+ async getFollowing(
314
+ params: GetMobileFollowingParams,
315
+ ): Promise<MobileFollowListPage> {
316
+ const signedRequest = await this.getSignedRequest('following', params, {
317
+ subaccount: subaccountToHex(params.target),
318
+ cursor: params.cursor ?? null,
319
+ limit: params.limit ?? null,
320
+ });
321
+ const data = await this.signedQuery(signedRequest);
322
+ return mapMobileFollowListPage(data);
323
+ }
324
+
256
325
  /*
257
326
  Signed executes
258
327
  */
@@ -314,15 +383,43 @@ export class MobileClient {
314
383
  return this.execute(signedRequest);
315
384
  }
316
385
 
386
+ /**
387
+ * Sets whether the signing subaccount follows a Profile. Both directions are idempotent: following again
388
+ * keeps the original relationship creation time, so it does not move the account in recency order, and
389
+ * unfollowing a relationship that does not exist succeeds with `isFollowing: false`. Unfollowing deletes
390
+ * the relationship rather than deactivating it, so a later follow gets a new creation time and moves the
391
+ * account to the front of recency order.
392
+ *
393
+ * Only `isFollowing: true` is checked against the canonical Query DB subaccount index, so unfollowing still
394
+ * works while that index lags.
395
+ *
396
+ * @throws {MobileServerFailureError} With error code `INVALID_FOLLOW_TARGET` if the target is the sender or
397
+ * either party is isolated, `FOLLOWER_NOT_ELIGIBLE` if the sender is not yet in the canonical Query DB
398
+ * subaccount index, or `FOLLOWING_NOT_FOUND` if the target is not. Both index errors are transient for an
399
+ * account that is being recorded, so they are retryable after catch-up — unlike `INVALID_FOLLOW_TARGET`.
400
+ */
401
+ async setFollow(
402
+ params: MobileSetFollowParams,
403
+ ): Promise<MobileFollowMutationResult> {
404
+ const signedRequest = await this.getSignedRequest('set_follow', params, {
405
+ subaccount: subaccountToHex(params.target),
406
+ is_following: params.isFollowing,
407
+ });
408
+ const data = await this.execute(signedRequest);
409
+ return mapMobileFollowMutationResult(data);
410
+ }
411
+
317
412
  /*
318
413
  Base Fns
319
414
  */
320
415
 
416
+ // Returns the request narrowed to `type` so `execute` and `signedQuery` can infer their response from the
417
+ // request they are given, instead of being told the type a second time at the call site.
321
418
  protected async getSignedRequest<T extends MobileSignedInner['type']>(
322
419
  type: T,
323
420
  params: MobileSignedRequestParams,
324
421
  innerParams: MobileSignedInnerParams<T>,
325
- ): Promise<MobileSignedRequest> {
422
+ ): Promise<MobileSignedRequest<MobileSignedInnerByType<T>>> {
326
423
  // Use the linked signer if provided, otherwise use the default signer provided to the client
327
424
  const walletClient =
328
425
  this.opts.linkedSignerWalletClient ?? this.opts.walletClient;
@@ -331,7 +428,10 @@ export class MobileClient {
331
428
  throw new WalletNotProvidedError();
332
429
  }
333
430
 
334
- const inner = { type, ...innerParams } as unknown as MobileSignedInner;
431
+ const inner = {
432
+ type,
433
+ ...innerParams,
434
+ } as unknown as MobileSignedInnerByType<T>;
335
435
  return buildSignedMobileRequest({ ...params, walletClient, inner });
336
436
  }
337
437
 
@@ -367,9 +467,11 @@ export class MobileClient {
367
467
  return response.data as MobileServerSuccessResponse;
368
468
  }
369
469
 
370
- protected async execute(
371
- body: MobileSignedRequest,
372
- ): Promise<MobileServerSuccessResponse> {
470
+ // `T` is inferred from the body's `type` rather than declared by the caller, for the same reason
471
+ // `publicQuery` spells its body out as an intersection: an indexed access is not an inference site.
472
+ protected async execute<T extends MobileServerExecuteRequestType>(
473
+ body: MobileSignedRequest & { type: T },
474
+ ): Promise<MobileServerExecuteSuccessResponse<T>> {
373
475
  const response = await this.axiosInstance.post<MobileServerExecuteResult>(
374
476
  `${this.opts.url}/mobile/execute`,
375
477
  body,
@@ -379,7 +481,22 @@ export class MobileClient {
379
481
  this.checkServerStatus(response);
380
482
 
381
483
  // checkServerStatus catches the failure result and throws the error, so the cast to the success response is acceptable here
382
- return response.data as MobileServerSuccessResponse;
484
+ return response.data as MobileServerExecuteSuccessResponse<T>;
485
+ }
486
+
487
+ protected async signedQuery<T extends MobileServerSignedQueryRequestType>(
488
+ body: MobileSignedRequest & { type: T },
489
+ ): Promise<MobileServerSignedQuerySuccessResponse<T>> {
490
+ const response = await this.axiosInstance.post<unknown>(
491
+ `${this.opts.url}/mobile/query`,
492
+ body,
493
+ );
494
+
495
+ this.checkResponseStatus(response);
496
+ this.checkServerStatus(response);
497
+
498
+ // checkServerStatus throws on failure responses so the cast to the success response is acceptable here
499
+ return response.data as MobileServerSignedQuerySuccessResponse<T>;
383
500
  }
384
501
 
385
502
  /**
@@ -1,24 +1,37 @@
1
+ import { subaccountToHex } from '@nadohq/shared';
1
2
  import {
2
3
  MobileFeedPage,
3
4
  MobileFeedTrade,
5
+ MobileFollowListPage,
6
+ MobileFollowMutationResult,
7
+ MobileFollowSummary,
8
+ MobileIdentitySummary,
4
9
  MobileNotificationPreferenceScope,
5
10
  MobileNotificationPreferences,
11
+ MobileProfilesInclude,
6
12
  MobilePublicProfile,
7
13
  MobileRegisteredWallet,
8
14
  } from './types/clientTypes';
15
+ import { MobileServerFollowMutationResponse } from './types/serverExecuteTypes';
9
16
  import {
10
17
  MobileServerFeedTrade,
18
+ MobileServerFollowSummary,
19
+ MobileServerIdentitySummary,
11
20
  MobileServerNotificationPreferenceScope,
12
21
  MobileServerNotificationPreferences,
13
22
  MobileServerProfile,
14
23
  } from './types/serverModelTypes';
15
24
  import {
16
25
  MobileServerFeedResponse,
26
+ MobileServerFollowListResponse,
17
27
  MobileServerRegisteredWalletResponse,
18
28
  } from './types/serverQueryTypes';
29
+ import { MobileServerProfilesInclude } from './types/serverRequestTypes';
19
30
 
20
31
  /**
21
- * Maps a server-side public profile (snake_case) to its client-side (camelCase) representation.
32
+ * Maps a server-side public profile (snake_case) to its client-side (camelCase) representation. The three
33
+ * include-gated fields stay `undefined` when the backend omitted them, rather than being coerced to `null`
34
+ * or zero, so callers can tell "not requested" from a real value.
22
35
  */
23
36
  export function mapMobilePublicProfile(
24
37
  server: MobileServerProfile,
@@ -28,6 +41,66 @@ export function mapMobilePublicProfile(
28
41
  username: server.username,
29
42
  displayName: server.display_name,
30
43
  privateMode: server.private_mode,
44
+ followerCount: server.follower_count,
45
+ followingCount: server.following_count,
46
+ followSummary: server.follow_summary
47
+ ? mapMobileFollowSummary(server.follow_summary)
48
+ : undefined,
49
+ };
50
+ }
51
+
52
+ /**
53
+ * Maps a server-side identity summary (snake_case) to its client-side (camelCase) representation.
54
+ */
55
+ function mapMobileIdentitySummary(
56
+ server: MobileServerIdentitySummary,
57
+ ): MobileIdentitySummary {
58
+ return {
59
+ subaccount: server.subaccount,
60
+ username: server.username,
61
+ displayName: server.display_name,
62
+ avatarUrl: server.avatar_url,
63
+ };
64
+ }
65
+
66
+ /**
67
+ * Maps a server-side follow summary to its client-side representation.
68
+ */
69
+ function mapMobileFollowSummary(
70
+ server: MobileServerFollowSummary,
71
+ ): MobileFollowSummary {
72
+ return {
73
+ isFollowing: server.is_following,
74
+ followedByCount: server.followed_by_count,
75
+ followedBy: server.followed_by.map(mapMobileIdentitySummary),
76
+ };
77
+ }
78
+
79
+ /**
80
+ * Maps a server-side Followers or Following response to a client-side {@link MobileFollowListPage}.
81
+ */
82
+ export function mapMobileFollowListPage(
83
+ server: MobileServerFollowListResponse,
84
+ ): MobileFollowListPage {
85
+ return {
86
+ accounts: server.accounts.map((account) => ({
87
+ identity: mapMobileIdentitySummary(account.identity),
88
+ isFollowing: account.is_following,
89
+ followerCount: account.follower_count,
90
+ })),
91
+ nextCursor: server.next_cursor,
92
+ };
93
+ }
94
+
95
+ /**
96
+ * Maps a server-side follow or unfollow response to its client-side representation.
97
+ */
98
+ export function mapMobileFollowMutationResult(
99
+ server: MobileServerFollowMutationResponse,
100
+ ): MobileFollowMutationResult {
101
+ return {
102
+ isFollowing: server.is_following,
103
+ followerCount: server.follower_count,
31
104
  };
32
105
  }
33
106
 
@@ -56,6 +129,20 @@ function mapMobileNotificationPreferenceScope(
56
129
  return { type: 'product', productId: server.product_id };
57
130
  }
58
131
 
132
+ /**
133
+ * Maps client-side profiles includes (camelCase) to the server-side (snake_case) wire shape.
134
+ */
135
+ export function mapMobileProfilesIncludeToServer(
136
+ include: MobileProfilesInclude,
137
+ ): MobileServerProfilesInclude {
138
+ return {
139
+ follow_counts: include.followCounts,
140
+ follow_summary: include.followSummary
141
+ ? { view_as: subaccountToHex(include.followSummary.viewAs) }
142
+ : undefined,
143
+ };
144
+ }
145
+
59
146
  /**
60
147
  * Maps client-side notification preferences (camelCase) to the server-side (snake_case) wire shape.
61
148
  */
@@ -86,11 +173,8 @@ function mapMobileNotificationPreferenceScopeToServer(
86
173
  */
87
174
  function mapMobileFeedTrade(server: MobileServerFeedTrade): MobileFeedTrade {
88
175
  return {
176
+ ...mapMobileIdentitySummary(server),
89
177
  orderDigest: server.order_digest,
90
- subaccount: server.subaccount,
91
- username: server.username,
92
- displayName: server.display_name,
93
- avatarUrl: server.avatar_url,
94
178
  productId: server.product_id,
95
179
  quantity: server.quantity,
96
180
  notional: server.notional,
@@ -23,6 +23,26 @@ export function canonicalizeMobileInner(
23
23
  locale: inner.locale,
24
24
  app_version: inner.app_version,
25
25
  };
26
+ case 'set_follow':
27
+ return {
28
+ type: 'set_follow',
29
+ subaccount: inner.subaccount,
30
+ is_following: inner.is_following,
31
+ };
32
+ case 'followers':
33
+ return {
34
+ type: 'followers',
35
+ subaccount: inner.subaccount,
36
+ cursor: inner.cursor,
37
+ limit: inner.limit,
38
+ };
39
+ case 'following':
40
+ return {
41
+ type: 'following',
42
+ subaccount: inner.subaccount,
43
+ cursor: inner.cursor,
44
+ limit: inner.limit,
45
+ };
26
46
  default: {
27
47
  throw new Error(
28
48
  `canonicalizeMobileInner: unhandled inner payload type: ${JSON.stringify(inner)}`,
@@ -10,4 +10,7 @@ export const MOBILE_EIP712_METHOD_BY_TYPE: Record<
10
10
  set_username: 'mobile:execute_set_username',
11
11
  set_private_mode: 'mobile:execute_set_private_mode',
12
12
  register_expo_token: 'mobile:execute_register_expo_token',
13
+ set_follow: 'mobile:execute_set_follow',
14
+ followers: 'mobile:query_followers',
15
+ following: 'mobile:query_following',
13
16
  };