zopassport 0.1.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 (110) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +407 -0
  3. package/app/.env.example +15 -0
  4. package/app/README.md +28 -0
  5. package/app/package.json +24 -0
  6. package/app/reanimated-mock.js +102 -0
  7. package/app/reanimated-mock.jsx +97 -0
  8. package/app/src/App.tsx +331 -0
  9. package/app/src/components/FounderBadge.tsx +26 -0
  10. package/app/src/components/OTPInput.tsx +149 -0
  11. package/app/src/components/PhoneInput.tsx +109 -0
  12. package/app/src/components/ZoAuth.tsx +320 -0
  13. package/app/src/components/ZoAvatar.tsx +87 -0
  14. package/app/src/components/ZoLanding.tsx +231 -0
  15. package/app/src/components/ZoOnboarding.tsx +524 -0
  16. package/app/src/components/ZoPassportCard.tsx +183 -0
  17. package/app/src/components/ZoProgressRing.tsx +57 -0
  18. package/app/src/components/index.ts +16 -0
  19. package/app/src/components/wallet/MovingShine.tsx +43 -0
  20. package/app/src/components/wallet/TransactionItem.tsx +84 -0
  21. package/app/src/components/wallet/TransactionList.tsx +65 -0
  22. package/app/src/components/wallet/WalletCard.tsx +152 -0
  23. package/app/src/components/wallet/WalletScreen.tsx +190 -0
  24. package/app/src/components/wallet/ZoToken.tsx +69 -0
  25. package/app/src/components/wallet/index.ts +8 -0
  26. package/app/src/components/wallet/styles/index.ts +4 -0
  27. package/app/src/components/wallet/styles/walletStyles.ts +210 -0
  28. package/app/src/sdk/ZoPassportSDK.ts +277 -0
  29. package/app/src/sdk/lib/api/auth.ts +223 -0
  30. package/app/src/sdk/lib/api/avatar.ts +155 -0
  31. package/app/src/sdk/lib/api/client.ts +135 -0
  32. package/app/src/sdk/lib/api/index.ts +8 -0
  33. package/app/src/sdk/lib/api/profile.ts +80 -0
  34. package/app/src/sdk/lib/api/wallet.ts +59 -0
  35. package/app/src/sdk/lib/types/auth.ts +78 -0
  36. package/app/src/sdk/lib/types/avatar.ts +22 -0
  37. package/app/src/sdk/lib/types/index.ts +8 -0
  38. package/app/src/sdk/lib/types/profile.ts +18 -0
  39. package/app/src/sdk/lib/types/wallet.ts +103 -0
  40. package/app/src/sdk/lib/types.ts +205 -0
  41. package/app/src/sdk/lib/utils/index.ts +6 -0
  42. package/app/src/sdk/lib/utils/phone.ts +71 -0
  43. package/app/src/sdk/lib/utils/storage.ts +116 -0
  44. package/app/src/sdk/lib/utils/wallet.ts +73 -0
  45. package/app/src/sdk/types.ts +205 -0
  46. package/app/src/styles.css +154 -0
  47. package/app/svg-mock.js +125 -0
  48. package/app/svg-mock.jsx +120 -0
  49. package/app/vite.config.ts +70 -0
  50. package/assets/ASSETS_MANIFEST.md +124 -0
  51. package/assets/bae.png +0 -0
  52. package/assets/bro.png +0 -0
  53. package/assets/cultural-stickers/Business.png +0 -0
  54. package/assets/cultural-stickers/Default (2).jpg +0 -0
  55. package/assets/cultural-stickers/Design.png +0 -0
  56. package/assets/cultural-stickers/FollowYourHeart.png +0 -0
  57. package/assets/cultural-stickers/Food.png +0 -0
  58. package/assets/cultural-stickers/Game.png +0 -0
  59. package/assets/cultural-stickers/Health&Fitness.png +0 -0
  60. package/assets/cultural-stickers/Home&Lifestyle.png +0 -0
  61. package/assets/cultural-stickers/Law.png +0 -0
  62. package/assets/cultural-stickers/Literature&Stories.png +0 -0
  63. package/assets/cultural-stickers/Music&Entertainment.png +0 -0
  64. package/assets/cultural-stickers/Nature&Wildlife.png +0 -0
  65. package/assets/cultural-stickers/Photography.png +0 -0
  66. package/assets/cultural-stickers/Science&Technology.png +0 -0
  67. package/assets/cultural-stickers/Spiritual.png +0 -0
  68. package/assets/cultural-stickers/Sport.png +0 -0
  69. package/assets/cultural-stickers/Stories&Journal.png +0 -0
  70. package/assets/cultural-stickers/Television&Cinema.png +0 -0
  71. package/assets/cultural-stickers/Travel&Adventure.png +0 -0
  72. package/assets/cultural-stickers/z.jpg (1).jpg +0 -0
  73. package/assets/figma-assets/landing-zo-logo.png +0 -0
  74. package/assets/images/rank1.jpeg +0 -0
  75. package/assets/index.ts +76 -0
  76. package/assets/lotties/loader.json +1216 -0
  77. package/assets/lotties/spinner.json +1 -0
  78. package/assets/videos/loading-screen-background.mp4 +0 -0
  79. package/assets/videos/opening-disks.mp4 +0 -0
  80. package/assets/wallet/constants.ts +38 -0
  81. package/assets/zo-coin.gif +0 -0
  82. package/assets/zo-fallback.png +0 -0
  83. package/dist/assets/index.d.mts +136 -0
  84. package/dist/assets/index.d.ts +136 -0
  85. package/dist/assets/index.js +133 -0
  86. package/dist/assets/index.js.map +1 -0
  87. package/dist/assets/index.mjs +100 -0
  88. package/dist/assets/index.mjs.map +1 -0
  89. package/dist/index.d.mts +789 -0
  90. package/dist/index.d.ts +789 -0
  91. package/dist/index.js +1118 -0
  92. package/dist/index.js.map +1 -0
  93. package/dist/index.mjs +1060 -0
  94. package/dist/index.mjs.map +1 -0
  95. package/dist/react-native.d.mts +537 -0
  96. package/dist/react-native.d.ts +537 -0
  97. package/dist/react-native.js +1617 -0
  98. package/dist/react-native.js.map +1 -0
  99. package/dist/react-native.mjs +1588 -0
  100. package/dist/react-native.mjs.map +1 -0
  101. package/dist/react.d.mts +824 -0
  102. package/dist/react.d.ts +824 -0
  103. package/dist/react.js +3856 -0
  104. package/dist/react.js.map +1 -0
  105. package/dist/react.mjs +3801 -0
  106. package/dist/react.mjs.map +1 -0
  107. package/package.json +112 -0
  108. package/scripts/init.js +196 -0
  109. package/scripts/postinstall.js +174 -0
  110. package/scripts/verify-build.js +121 -0
@@ -0,0 +1,1617 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/react-native.tsx
31
+ var react_native_exports = {};
32
+ __export(react_native_exports, {
33
+ AsyncStorageAdapter: () => AsyncStorageAdapter,
34
+ MemoryStorageAdapter: () => MemoryStorageAdapter,
35
+ MovingShine: () => MovingShine,
36
+ STORAGE_KEYS: () => STORAGE_KEYS,
37
+ TransactionItem: () => TransactionItem,
38
+ TransactionList: () => TransactionList,
39
+ WalletCard: () => WalletCard,
40
+ WalletScreen: () => WalletScreen,
41
+ ZoPassportSDK: () => ZoPassportSDK,
42
+ ZoToken: () => ZoToken,
43
+ ZoTokenVideo: () => ZoTokenVideo
44
+ });
45
+ module.exports = __toCommonJS(react_native_exports);
46
+
47
+ // src/components/wallet/WalletScreen.tsx
48
+ var import_react5 = require("react");
49
+ var import_react_native7 = require("react-native");
50
+ var import_react_native_reanimated3 = __toESM(require("react-native-reanimated"));
51
+
52
+ // src/components/wallet/WalletCard.tsx
53
+ var import_react2 = require("react");
54
+ var import_react_native4 = require("react-native");
55
+ var import_react_native_reanimated2 = __toESM(require("react-native-reanimated"));
56
+
57
+ // src/components/wallet/MovingShine.tsx
58
+ var import_react = require("react");
59
+ var import_react_native2 = require("react-native");
60
+ var import_react_native_reanimated = __toESM(require("react-native-reanimated"));
61
+
62
+ // assets/wallet/constants.ts
63
+ var WALLET_ASSETS = {
64
+ walletBackground: "https://proxy.cdn.zo.xyz/gallery/media/images/2e1fe74c-673c-4acd-a5aa-4ac13027dfb2_20250706072110.png",
65
+ walletCover: "https://proxy.cdn.zo.xyz/gallery/media/images/aeb1d508-c511-46a9-b4f8-260ea8825c6a_20250706072152.png",
66
+ shine: "https://proxy.cdn.zo.xyz/gallery/media/images/2a117a82-e399-4278-8eac-0d5b9209d150_20250706073538.png"
67
+ };
68
+ var WALLET_COLORS = {
69
+ background: "#111111",
70
+ cardBackground: "#222222",
71
+ cardInner: "rgba(255, 255, 255, 0.24)",
72
+ cardContent: "#111111",
73
+ cardBorder: "rgba(255, 255, 255, 0.16)",
74
+ textWhite: "#FFFFFF",
75
+ textGray: "rgba(255, 255, 255, 0.44)",
76
+ zoGreen: "#00C853",
77
+ shadowDark: "rgba(25, 25, 25, 1)"
78
+ };
79
+ var WALLET_DIMENSIONS = {
80
+ cardAspectRatio: 312 / 200,
81
+ coverAspectRatio: 312 / 120,
82
+ cardBorderRadius: 16,
83
+ innerBorderRadius: 12,
84
+ avatarSize: 32,
85
+ tokenSize: 16,
86
+ tokenVideoSize: 24
87
+ };
88
+ var ANIMATIONS = {
89
+ shineDuration: 1500,
90
+ cardTransition: 300,
91
+ fadeInDuration: 500
92
+ };
93
+
94
+ // src/components/wallet/styles/walletStyles.ts
95
+ var import_react_native = require("react-native");
96
+ var walletStyles = import_react_native.StyleSheet.create({
97
+ // Layout
98
+ flex: {
99
+ flex: 1
100
+ },
101
+ screen: {
102
+ flex: 1,
103
+ backgroundColor: WALLET_COLORS.background
104
+ },
105
+ container: {
106
+ flexDirection: "column-reverse"
107
+ },
108
+ // Header
109
+ header: {
110
+ width: "100%",
111
+ flexDirection: "row",
112
+ paddingVertical: 16,
113
+ paddingHorizontal: 24,
114
+ alignItems: "flex-start"
115
+ },
116
+ titleContainer: {
117
+ ...import_react_native.StyleSheet.absoluteFillObject,
118
+ alignItems: "center",
119
+ justifyContent: "center"
120
+ },
121
+ // Wallet Card
122
+ cardPressContainer: {
123
+ padding: 24,
124
+ paddingBottom: 0,
125
+ paddingTop: 8
126
+ },
127
+ card: {
128
+ aspectRatio: WALLET_DIMENSIONS.cardAspectRatio,
129
+ width: "100%",
130
+ borderRadius: WALLET_DIMENSIONS.cardBorderRadius,
131
+ backgroundColor: WALLET_COLORS.cardBackground
132
+ },
133
+ cardContainer: {
134
+ margin: 24,
135
+ flex: 1,
136
+ alignSelf: "stretch",
137
+ backgroundColor: WALLET_COLORS.cardInner,
138
+ borderRadius: WALLET_DIMENSIONS.innerBorderRadius,
139
+ paddingBottom: 4
140
+ },
141
+ cardContent: {
142
+ flex: 1,
143
+ padding: 16,
144
+ backgroundColor: WALLET_COLORS.cardContent,
145
+ borderRadius: WALLET_DIMENSIONS.innerBorderRadius,
146
+ borderWidth: 1,
147
+ borderColor: WALLET_COLORS.cardBorder
148
+ },
149
+ cardShadow: {
150
+ width: "80%",
151
+ height: 24,
152
+ backgroundColor: WALLET_COLORS.shadowDark,
153
+ position: "absolute",
154
+ top: "45%",
155
+ left: "10%",
156
+ shadowColor: "black",
157
+ shadowOffset: { width: 0, height: -10 },
158
+ shadowOpacity: 0.75,
159
+ shadowRadius: 16,
160
+ elevation: 5
161
+ },
162
+ // Balance
163
+ balanceRow: {
164
+ flexDirection: "row",
165
+ alignItems: "center",
166
+ justifyContent: "space-between"
167
+ },
168
+ balanceWrapper: {
169
+ flexDirection: "row",
170
+ alignItems: "baseline",
171
+ gap: 4
172
+ },
173
+ // User Info
174
+ avatarInfo: {
175
+ flexDirection: "row",
176
+ gap: 8
177
+ },
178
+ // Card Cover
179
+ cardCover: {
180
+ aspectRatio: WALLET_DIMENSIONS.coverAspectRatio,
181
+ width: "100%",
182
+ position: "absolute",
183
+ bottom: 0,
184
+ left: 0,
185
+ right: 0,
186
+ borderBottomLeftRadius: WALLET_DIMENSIONS.innerBorderRadius,
187
+ borderBottomRightRadius: WALLET_DIMENSIONS.innerBorderRadius,
188
+ overflow: "hidden"
189
+ },
190
+ cardCoverTextContainer: {
191
+ position: "absolute",
192
+ bottom: 0,
193
+ left: 0,
194
+ right: 0,
195
+ top: 0,
196
+ justifyContent: "center",
197
+ alignItems: "center"
198
+ },
199
+ // Shine Effect
200
+ shineContainer: {
201
+ ...import_react_native.StyleSheet.absoluteFillObject,
202
+ overflow: "hidden"
203
+ },
204
+ shineEffect: {
205
+ position: "absolute",
206
+ width: 150,
207
+ left: -60,
208
+ top: -140,
209
+ bottom: 0
210
+ },
211
+ // Text Styles
212
+ whiteText: {
213
+ color: WALLET_COLORS.textWhite
214
+ },
215
+ grayText: {
216
+ color: WALLET_COLORS.textGray
217
+ },
218
+ // Token
219
+ tokenVideo: {
220
+ width: WALLET_DIMENSIONS.tokenVideoSize,
221
+ height: WALLET_DIMENSIONS.tokenVideoSize,
222
+ borderRadius: WALLET_DIMENSIONS.tokenVideoSize,
223
+ overflow: "hidden"
224
+ },
225
+ token: {
226
+ width: WALLET_DIMENSIONS.tokenSize,
227
+ height: WALLET_DIMENSIONS.tokenSize
228
+ },
229
+ tokenContainer: {
230
+ flexDirection: "row",
231
+ gap: 4,
232
+ alignItems: "center",
233
+ justifyContent: "center"
234
+ },
235
+ textShadow: {
236
+ shadowRadius: 8,
237
+ shadowOpacity: 1
238
+ },
239
+ // Transactions
240
+ txnContent: {
241
+ alignSelf: "stretch",
242
+ paddingHorizontal: 24,
243
+ gap: 32,
244
+ paddingBottom: 24,
245
+ paddingTop: 40
246
+ },
247
+ txnRow: {
248
+ minHeight: 40,
249
+ flexDirection: "row",
250
+ gap: 12,
251
+ justifyContent: "space-between",
252
+ alignItems: "center"
253
+ },
254
+ iconBgTilted: {
255
+ transform: [{ rotate: "-45deg" }],
256
+ width: 40,
257
+ height: 40,
258
+ borderRadius: 20,
259
+ backgroundColor: "#202020",
260
+ alignItems: "center",
261
+ justifyContent: "center"
262
+ },
263
+ // States
264
+ loader: {
265
+ flex: 1,
266
+ alignItems: "center",
267
+ justifyContent: "center",
268
+ marginTop: 240
269
+ },
270
+ openBg: {
271
+ ...import_react_native.StyleSheet.absoluteFillObject,
272
+ backgroundColor: WALLET_COLORS.background,
273
+ opacity: 0.8
274
+ },
275
+ zoDescriptionContainer: {
276
+ position: "absolute",
277
+ bottom: 140
278
+ },
279
+ description: {
280
+ paddingHorizontal: 24,
281
+ color: WALLET_COLORS.textWhite
282
+ },
283
+ // Spacing
284
+ bar: {
285
+ height: 56
286
+ }
287
+ });
288
+
289
+ // src/components/wallet/MovingShine.tsx
290
+ var import_jsx_runtime = require("react/jsx-runtime");
291
+ var MovingShine = (0, import_react.memo)(
292
+ ({ duration = ANIMATIONS.shineDuration }) => {
293
+ const tx = (0, import_react_native_reanimated.useSharedValue)(-100);
294
+ const animatedStyle = (0, import_react_native_reanimated.useAnimatedStyle)(() => ({
295
+ transform: [{ rotate: "30deg" }, { translateX: tx.value }]
296
+ }));
297
+ (0, import_react.useEffect)(() => {
298
+ tx.value = (0, import_react_native_reanimated.withRepeat)((0, import_react_native_reanimated.withTiming)(420, { duration }), -1, false);
299
+ }, [duration]);
300
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native_reanimated.default.View, { style: [styles.shineEffect, animatedStyle], children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
301
+ import_react_native2.Image,
302
+ {
303
+ source: { uri: WALLET_ASSETS.shine },
304
+ style: import_react_native2.StyleSheet.absoluteFillObject,
305
+ resizeMode: "cover"
306
+ }
307
+ ) });
308
+ }
309
+ );
310
+ MovingShine.displayName = "MovingShine";
311
+ var styles = import_react_native2.StyleSheet.create({
312
+ shineEffect: walletStyles.shineEffect
313
+ });
314
+
315
+ // src/components/wallet/ZoToken.tsx
316
+ var import_react_native3 = require("react-native");
317
+ var import_jsx_runtime2 = require("react/jsx-runtime");
318
+ var ZO_COIN_GIF = "/zo-coin.gif";
319
+ var ZoToken = ({ size = 16, style, source = ZO_COIN_GIF }) => {
320
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native3.View, { style: [{ width: size, height: size }, style], children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
321
+ import_react_native3.Image,
322
+ {
323
+ source: { uri: source },
324
+ style: {
325
+ width: size,
326
+ height: size,
327
+ borderRadius: size / 2
328
+ },
329
+ resizeMode: "cover"
330
+ }
331
+ ) });
332
+ };
333
+ var ZoTokenVideo = ({ size = 24, style, source = ZO_COIN_GIF }) => {
334
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
335
+ import_react_native3.View,
336
+ {
337
+ style: [
338
+ {
339
+ width: size,
340
+ height: size,
341
+ borderRadius: size / 2,
342
+ overflow: "hidden"
343
+ },
344
+ style
345
+ ],
346
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
347
+ import_react_native3.Image,
348
+ {
349
+ source: { uri: source },
350
+ style: {
351
+ width: size,
352
+ height: size
353
+ },
354
+ resizeMode: "cover"
355
+ }
356
+ )
357
+ }
358
+ );
359
+ };
360
+ var styles2 = import_react_native3.StyleSheet.create({
361
+ container: {
362
+ alignItems: "center",
363
+ justifyContent: "center"
364
+ }
365
+ });
366
+
367
+ // src/lib/utils/wallet.ts
368
+ var formatBalance = (balance) => {
369
+ if (balance === 0) return "0";
370
+ const formatted = balance.toLocaleString("en-US", {
371
+ minimumFractionDigits: 0,
372
+ maximumFractionDigits: 2
373
+ });
374
+ return formatted;
375
+ };
376
+ var formatWalletAddress = (address) => {
377
+ if (!address || address.length < 8) return address;
378
+ return `${address.slice(0, 4)}...${address.slice(-4)}`;
379
+ };
380
+ var formatNickname = (nickname) => {
381
+ if (!nickname) return "";
382
+ return nickname.startsWith("@") ? nickname : `@${nickname}`;
383
+ };
384
+ var getTransactionColor = (action) => {
385
+ return action === "spend" ? "#FF4444" : "#00C853";
386
+ };
387
+
388
+ // src/components/wallet/WalletCard.tsx
389
+ var import_jsx_runtime3 = require("react/jsx-runtime");
390
+ var WalletCard = (0, import_react2.memo)(
391
+ ({ balance, user, isOpen = false, onToggle, isLoading }) => {
392
+ const bgY = (0, import_react_native_reanimated2.useSharedValue)(0);
393
+ const cardY = (0, import_react_native_reanimated2.useSharedValue)(0);
394
+ const animatedBackgroundStyle = (0, import_react_native_reanimated2.useAnimatedStyle)(() => ({
395
+ transform: [{ translateY: bgY.value }]
396
+ }));
397
+ const animatedCardStyle = (0, import_react_native_reanimated2.useAnimatedStyle)(() => ({
398
+ transform: [{ translateY: cardY.value }]
399
+ }));
400
+ (0, import_react2.useEffect)(() => {
401
+ bgY.value = (0, import_react_native_reanimated2.withTiming)(isOpen ? 200 : 0, { duration: ANIMATIONS.cardTransition });
402
+ cardY.value = (0, import_react_native_reanimated2.withTiming)(isOpen ? -150 : 0, { duration: ANIMATIONS.cardTransition });
403
+ }, [isOpen]);
404
+ const displayName = user.nickname ? formatNickname(user.nickname) : user.first_name || "You";
405
+ const walletText = `${displayName}'s wallet`;
406
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
407
+ import_react_native4.Pressable,
408
+ {
409
+ style: styles3.cardPressContainer,
410
+ onPress: onToggle,
411
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native_reanimated2.default.View, { style: [styles3.card, animatedBackgroundStyle], children: [
412
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
413
+ import_react_native4.Image,
414
+ {
415
+ source: { uri: WALLET_ASSETS.walletBackground },
416
+ style: import_react_native4.StyleSheet.absoluteFillObject,
417
+ resizeMode: "contain"
418
+ }
419
+ ),
420
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
421
+ import_react_native_reanimated2.default.View,
422
+ {
423
+ style: styles3.cardShadow,
424
+ entering: import_react_native_reanimated2.FadeIn.duration(ANIMATIONS.fadeInDuration)
425
+ }
426
+ ),
427
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native_reanimated2.default.View, { style: [styles3.cardContainer, animatedCardStyle], children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native4.View, { style: styles3.cardContent, children: [
428
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native4.View, { style: styles3.balanceRow, children: [
429
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native4.View, { style: styles3.balanceWrapper, children: [
430
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native4.Text, { style: [styles3.whiteText, styles3.balanceAmount], children: formatBalance(balance) }),
431
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native4.Text, { style: [styles3.grayText, styles3.currency], children: "$Zo" })
432
+ ] }),
433
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ZoTokenVideo, { size: 24 })
434
+ ] }),
435
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native4.View, { style: styles3.flex }),
436
+ user && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native4.View, { style: styles3.avatarInfo, children: [
437
+ user.avatar?.image && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
438
+ import_react_native4.Image,
439
+ {
440
+ source: { uri: user.avatar.image },
441
+ style: styles3.avatar
442
+ }
443
+ ),
444
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native4.View, { style: styles3.flex, children: [
445
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native4.Text, { style: [styles3.whiteText, styles3.userName], children: displayName }),
446
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native4.Text, { style: [styles3.grayText, styles3.walletAddress], children: formatWalletAddress(user.wallet_address || "") })
447
+ ] })
448
+ ] }),
449
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native4.View, { style: styles3.shineContainer, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(MovingShine, {}) })
450
+ ] }) }),
451
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native4.View, { style: styles3.cardCover, children: [
452
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
453
+ import_react_native4.Image,
454
+ {
455
+ source: { uri: WALLET_ASSETS.walletCover },
456
+ style: import_react_native4.StyleSheet.absoluteFillObject,
457
+ resizeMode: "cover"
458
+ }
459
+ ),
460
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native4.View, { style: styles3.cardCoverTextContainer, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native4.Text, { style: [styles3.grayText, styles3.cardCoverText], children: walletText }) })
461
+ ] })
462
+ ] })
463
+ }
464
+ );
465
+ }
466
+ );
467
+ WalletCard.displayName = "WalletCard";
468
+ var styles3 = import_react_native4.StyleSheet.create({
469
+ ...walletStyles,
470
+ balanceAmount: {
471
+ fontSize: 24,
472
+ fontWeight: "700"
473
+ },
474
+ currency: {
475
+ fontSize: 12
476
+ },
477
+ userName: {
478
+ fontSize: 16,
479
+ fontWeight: "600"
480
+ },
481
+ walletAddress: {
482
+ fontSize: 12
483
+ },
484
+ avatar: {
485
+ width: 32,
486
+ height: 32,
487
+ borderRadius: 16
488
+ },
489
+ cardCoverText: {
490
+ fontSize: 16,
491
+ fontWeight: "600"
492
+ }
493
+ });
494
+
495
+ // src/components/wallet/TransactionList.tsx
496
+ var import_react4 = require("react");
497
+ var import_react_native6 = require("react-native");
498
+
499
+ // src/components/wallet/TransactionItem.tsx
500
+ var import_react3 = require("react");
501
+ var import_react_native5 = require("react-native");
502
+ var import_moment = __toESM(require("moment"));
503
+ var import_jsx_runtime4 = require("react/jsx-runtime");
504
+ var StatusIcon = (0, import_react3.memo)(() => {
505
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native5.View, { style: styles4.iconBgTilted, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native5.Text, { style: styles4.iconText, children: "\u2190" }) });
506
+ });
507
+ StatusIcon.displayName = "StatusIcon";
508
+ var TransactionItem = (0, import_react3.memo)(
509
+ ({ transaction, showDate = true }) => {
510
+ const color = getTransactionColor(transaction.action);
511
+ const formattedAmount = formatBalance(transaction.amount);
512
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native5.View, { style: styles4.txnRow, children: [
513
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(StatusIcon, {}),
514
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native5.View, { style: styles4.flex, children: [
515
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native5.Text, { style: styles4.description, children: transaction.description }),
516
+ showDate && transaction.claimed_at && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native5.Text, { style: styles4.date, children: (0, import_moment.default)(transaction.claimed_at).format("DD MMM hh:mm A") })
517
+ ] }),
518
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native5.View, { style: styles4.tokenContainer, children: [
519
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
520
+ import_react_native5.Text,
521
+ {
522
+ style: [
523
+ styles4.textShadow,
524
+ {
525
+ shadowColor: color,
526
+ color,
527
+ fontWeight: "600",
528
+ fontSize: 16
529
+ }
530
+ ],
531
+ children: [
532
+ "+ ",
533
+ formattedAmount
534
+ ]
535
+ }
536
+ ),
537
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ZoToken, { size: 16 })
538
+ ] })
539
+ ] });
540
+ }
541
+ );
542
+ TransactionItem.displayName = "TransactionItem";
543
+ var styles4 = import_react_native5.StyleSheet.create({
544
+ txnRow: walletStyles.txnRow,
545
+ iconBgTilted: walletStyles.iconBgTilted,
546
+ tokenContainer: walletStyles.tokenContainer,
547
+ textShadow: walletStyles.textShadow,
548
+ flex: {
549
+ flex: 1
550
+ },
551
+ iconText: {
552
+ color: "rgba(255, 255, 255, 0.6)",
553
+ fontSize: 16
554
+ },
555
+ description: {
556
+ color: "#FFFFFF",
557
+ fontSize: 16,
558
+ fontWeight: "500"
559
+ },
560
+ date: {
561
+ color: "rgba(255, 255, 255, 0.44)",
562
+ fontSize: 12,
563
+ marginTop: 2
564
+ }
565
+ });
566
+
567
+ // src/components/wallet/TransactionList.tsx
568
+ var import_jsx_runtime5 = require("react/jsx-runtime");
569
+ var TransactionList = (0, import_react4.memo)(
570
+ ({ transactions, isLoading, onEndReached }) => {
571
+ if (isLoading && !transactions?.length) {
572
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native6.View, { style: styles5.loader, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native6.ActivityIndicator, { size: "large", color: "#00C853" }) });
573
+ }
574
+ if (!transactions?.length) {
575
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native6.View, { style: styles5.emptyState, children: [
576
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native6.Text, { style: styles5.emptyText, children: "No transactions yet" }),
577
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native6.Text, { style: styles5.emptySubtext, children: "Complete quests to earn $Zo tokens" })
578
+ ] });
579
+ }
580
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native6.View, { style: styles5.txnContent, children: transactions.map((transaction, index) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(TransactionItem, { transaction }, transaction.id || index)) });
581
+ }
582
+ );
583
+ TransactionList.displayName = "TransactionList";
584
+ var styles5 = import_react_native6.StyleSheet.create({
585
+ txnContent: walletStyles.txnContent,
586
+ loader: {
587
+ padding: 40,
588
+ alignItems: "center",
589
+ justifyContent: "center"
590
+ },
591
+ emptyState: {
592
+ padding: 40,
593
+ alignItems: "center",
594
+ justifyContent: "center"
595
+ },
596
+ emptyText: {
597
+ color: "#FFFFFF",
598
+ fontSize: 18,
599
+ fontWeight: "600",
600
+ marginBottom: 8
601
+ },
602
+ emptySubtext: {
603
+ color: "rgba(255, 255, 255, 0.44)",
604
+ fontSize: 14,
605
+ textAlign: "center"
606
+ }
607
+ });
608
+
609
+ // src/components/wallet/WalletScreen.tsx
610
+ var import_jsx_runtime6 = require("react/jsx-runtime");
611
+ var WalletScreen = (0, import_react5.memo)(({
612
+ user,
613
+ balance,
614
+ transactions,
615
+ isLoading: isLoadingProp = false,
616
+ onBack
617
+ }) => {
618
+ const [isOpen, setIsOpen] = (0, import_react5.useState)(false);
619
+ const [isTitleVisible, setIsTitleVisible] = (0, import_react5.useState)(false);
620
+ const isLoading = isLoadingProp;
621
+ const toggleView = (0, import_react5.useCallback)(() => {
622
+ setIsOpen((prev) => !prev);
623
+ }, []);
624
+ const handleScroll = (0, import_react5.useCallback)((event) => {
625
+ const scrollY = event.nativeEvent.contentOffset.y;
626
+ setIsTitleVisible(scrollY > 200);
627
+ }, []);
628
+ const backdrop = (0, import_react5.useMemo)(
629
+ () => isOpen ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_native7.Pressable, { onPress: toggleView, style: styles6.openBg, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_native7.View, {}) }) : null,
630
+ [isOpen, toggleView]
631
+ );
632
+ const description = (0, import_react5.useMemo)(
633
+ () => isOpen ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_native_reanimated3.default.View, { entering: import_react_native_reanimated3.FadeIn, exiting: import_react_native_reanimated3.FadeOut, style: styles6.zoDescriptionContainer, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_native7.Text, { style: styles6.description, children: "Get Zo World coins as airdrop by completing quests, stay & trips." }) }) : null,
634
+ [isOpen]
635
+ );
636
+ const walletText = `${user.nickname || user.first_name}'s wallet`;
637
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_react_native7.View, { style: styles6.screen, children: [
638
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_react_native7.View, { style: styles6.header, children: [
639
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_native7.Pressable, { onPress: onBack, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_native7.Text, { style: styles6.backButton, children: "\u2190" }) }),
640
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_native_reanimated3.default.View, { pointerEvents: "none", style: styles6.titleContainer, children: isTitleVisible && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_native_reanimated3.default.View, { entering: import_react_native_reanimated3.FadeInUp, exiting: import_react_native_reanimated3.FadeOutUp, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_native7.Text, { style: [styles6.whiteText, styles6.headerTitle], children: walletText }) }) })
641
+ ] }),
642
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
643
+ import_react_native7.ScrollView,
644
+ {
645
+ contentContainerStyle: styles6.container,
646
+ onScroll: handleScroll,
647
+ scrollEventThrottle: 16,
648
+ showsVerticalScrollIndicator: false,
649
+ children: isLoading ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_native_reanimated3.default.View, { entering: import_react_native_reanimated3.FadeIn, exiting: import_react_native_reanimated3.FadeOut, style: styles6.loader, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_native7.ActivityIndicator, { size: "large", color: "#00C853" }) }, "loader") : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_react_native_reanimated3.default.View, { entering: import_react_native_reanimated3.FadeInDown, style: styles6.container, children: [
650
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_native7.SafeAreaView, {}),
651
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(TransactionList, { transactions, isLoading: false }),
652
+ backdrop,
653
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
654
+ WalletCard,
655
+ {
656
+ balance,
657
+ user,
658
+ isOpen,
659
+ onToggle: toggleView,
660
+ isLoading
661
+ }
662
+ ),
663
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_native7.View, { style: styles6.bar }),
664
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_native7.SafeAreaView, {})
665
+ ] })
666
+ }
667
+ ),
668
+ description
669
+ ] });
670
+ });
671
+ WalletScreen.displayName = "WalletScreen";
672
+ var styles6 = import_react_native7.StyleSheet.create({
673
+ ...walletStyles,
674
+ backButton: {
675
+ color: "#FFFFFF",
676
+ fontSize: 24,
677
+ fontWeight: "600"
678
+ },
679
+ headerTitle: {
680
+ fontSize: 18,
681
+ fontWeight: "600"
682
+ }
683
+ });
684
+
685
+ // src/lib/api/client.ts
686
+ var import_axios = __toESM(require("axios"));
687
+
688
+ // src/lib/utils/logger.ts
689
+ var LOG_LEVELS = {
690
+ debug: 0,
691
+ info: 1,
692
+ warn: 2,
693
+ error: 3,
694
+ none: 4
695
+ };
696
+ var Logger = class {
697
+ constructor() {
698
+ this.config = {
699
+ enabled: false,
700
+ level: "warn",
701
+ prefix: "[ZoPassport]"
702
+ };
703
+ }
704
+ /**
705
+ * Configure the logger
706
+ * @param options - Logger configuration
707
+ */
708
+ configure(options) {
709
+ this.config = { ...this.config, ...options };
710
+ }
711
+ /**
712
+ * Enable debug logging
713
+ */
714
+ enable() {
715
+ this.config.enabled = true;
716
+ }
717
+ /**
718
+ * Disable all logging
719
+ */
720
+ disable() {
721
+ this.config.enabled = false;
722
+ }
723
+ /**
724
+ * Set log level
725
+ */
726
+ setLevel(level) {
727
+ this.config.level = level;
728
+ }
729
+ shouldLog(level) {
730
+ if (!this.config.enabled) return false;
731
+ return LOG_LEVELS[level] >= LOG_LEVELS[this.config.level];
732
+ }
733
+ debug(...args) {
734
+ if (this.shouldLog("debug")) {
735
+ console.log(this.config.prefix, ...args);
736
+ }
737
+ }
738
+ info(...args) {
739
+ if (this.shouldLog("info")) {
740
+ console.info(this.config.prefix, ...args);
741
+ }
742
+ }
743
+ warn(...args) {
744
+ if (this.shouldLog("warn")) {
745
+ console.warn(this.config.prefix, ...args);
746
+ }
747
+ }
748
+ error(...args) {
749
+ if (this.shouldLog("error")) {
750
+ console.error(this.config.prefix, ...args);
751
+ }
752
+ }
753
+ };
754
+ var logger = new Logger();
755
+
756
+ // src/lib/utils/storage.ts
757
+ var STORAGE_KEYS = {
758
+ ACCESS_TOKEN: "zo_access_token",
759
+ REFRESH_TOKEN: "zo_refresh_token",
760
+ TOKEN_EXPIRY: "zo_token_expiry",
761
+ REFRESH_EXPIRY: "zo_refresh_expiry",
762
+ USER: "zo_user",
763
+ CLIENT_DEVICE_ID: "zo_device_id",
764
+ CLIENT_DEVICE_SECRET: "zo_device_secret",
765
+ AVATAR_URL: "zo_avatar_url",
766
+ NICKNAME: "zo_nickname",
767
+ CITY: "zo_city",
768
+ BODY_TYPE: "zo_body_type"
769
+ };
770
+ var LocalStorageAdapter = class {
771
+ async getItem(key) {
772
+ if (typeof window === "undefined") return null;
773
+ try {
774
+ return localStorage.getItem(key);
775
+ } catch (error) {
776
+ logger.warn(`LocalStorage.getItem failed for key "${key}":`, error);
777
+ return null;
778
+ }
779
+ }
780
+ async setItem(key, value) {
781
+ if (typeof window === "undefined") return;
782
+ try {
783
+ localStorage.setItem(key, value);
784
+ } catch (error) {
785
+ logger.warn(`LocalStorage.setItem failed for key "${key}":`, error);
786
+ }
787
+ }
788
+ async removeItem(key) {
789
+ if (typeof window === "undefined") return;
790
+ try {
791
+ localStorage.removeItem(key);
792
+ } catch (error) {
793
+ logger.warn(`LocalStorage.removeItem failed for key "${key}":`, error);
794
+ }
795
+ }
796
+ };
797
+ var AsyncStorageAdapter = class {
798
+ constructor(asyncStorage) {
799
+ this.storage = asyncStorage;
800
+ }
801
+ async getItem(key) {
802
+ try {
803
+ return await this.storage.getItem(key);
804
+ } catch (error) {
805
+ logger.warn(`AsyncStorage.getItem failed for key "${key}":`, error);
806
+ return null;
807
+ }
808
+ }
809
+ async setItem(key, value) {
810
+ try {
811
+ await this.storage.setItem(key, value);
812
+ } catch (error) {
813
+ logger.warn(`AsyncStorage.setItem failed for key "${key}":`, error);
814
+ }
815
+ }
816
+ async removeItem(key) {
817
+ try {
818
+ await this.storage.removeItem(key);
819
+ } catch (error) {
820
+ logger.warn(`AsyncStorage.removeItem failed for key "${key}":`, error);
821
+ }
822
+ }
823
+ };
824
+ var MemoryStorageAdapter = class {
825
+ constructor() {
826
+ this.store = /* @__PURE__ */ new Map();
827
+ }
828
+ async getItem(key) {
829
+ return this.store.get(key) || null;
830
+ }
831
+ async setItem(key, value) {
832
+ this.store.set(key, value);
833
+ }
834
+ async removeItem(key) {
835
+ this.store.delete(key);
836
+ }
837
+ /** Clear all stored data (useful for testing) */
838
+ clear() {
839
+ this.store.clear();
840
+ }
841
+ };
842
+
843
+ // src/lib/api/client.ts
844
+ function generateDeviceCredentials() {
845
+ const deviceId = `web-${Date.now()}-${Math.random().toString(36).substring(7)}`;
846
+ const deviceSecret = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
847
+ return { deviceId, deviceSecret };
848
+ }
849
+ var ZoApiClient = class {
850
+ constructor(config) {
851
+ this.config = config;
852
+ this.storage = config.storageAdapter || new LocalStorageAdapter();
853
+ this.client = import_axios.default.create({
854
+ baseURL: config.baseUrl || "https://api.io.zo.xyz",
855
+ timeout: config.timeout || 1e4,
856
+ headers: {
857
+ "Content-Type": "application/json",
858
+ "Accept": "application/json"
859
+ }
860
+ });
861
+ this.setupInterceptors();
862
+ }
863
+ async setupInterceptors() {
864
+ this.client.interceptors.request.use(async (config) => {
865
+ config.headers["client-key"] = this.config.clientKey;
866
+ const credentials = await this.getOrCreateDeviceCredentials();
867
+ config.headers["client-device-id"] = credentials.deviceId;
868
+ config.headers["client-device-secret"] = credentials.deviceSecret;
869
+ const token = await this.storage.getItem(STORAGE_KEYS.ACCESS_TOKEN);
870
+ if (token) {
871
+ config.headers["Authorization"] = `Bearer ${token}`;
872
+ }
873
+ return config;
874
+ });
875
+ this.client.interceptors.response.use(
876
+ (response) => response,
877
+ async (error) => {
878
+ const originalRequest = error.config;
879
+ if (error.response?.status === 401 && !originalRequest._retry) {
880
+ originalRequest._retry = true;
881
+ const refreshToken = await this.storage.getItem(STORAGE_KEYS.REFRESH_TOKEN);
882
+ if (refreshToken) {
883
+ try {
884
+ const response = await this.client.post("/api/v1/auth/token/refresh/", {
885
+ refresh_token: refreshToken
886
+ });
887
+ if (response.data?.access) {
888
+ await this.storage.setItem(STORAGE_KEYS.ACCESS_TOKEN, response.data.access);
889
+ if (response.data.refresh) {
890
+ await this.storage.setItem(STORAGE_KEYS.REFRESH_TOKEN, response.data.refresh);
891
+ }
892
+ originalRequest.headers["Authorization"] = `Bearer ${response.data.access}`;
893
+ return this.client(originalRequest);
894
+ }
895
+ } catch (refreshError) {
896
+ await this.storage.removeItem(STORAGE_KEYS.ACCESS_TOKEN);
897
+ await this.storage.removeItem(STORAGE_KEYS.REFRESH_TOKEN);
898
+ }
899
+ }
900
+ }
901
+ return Promise.reject(error);
902
+ }
903
+ );
904
+ }
905
+ async getOrCreateDeviceCredentials() {
906
+ const storedId = await this.storage.getItem(STORAGE_KEYS.CLIENT_DEVICE_ID);
907
+ const storedSecret = await this.storage.getItem(STORAGE_KEYS.CLIENT_DEVICE_SECRET);
908
+ if (storedId && storedSecret) {
909
+ return { deviceId: storedId, deviceSecret: storedSecret };
910
+ }
911
+ const credentials = generateDeviceCredentials();
912
+ await this.storage.setItem(STORAGE_KEYS.CLIENT_DEVICE_ID, credentials.deviceId);
913
+ await this.storage.setItem(STORAGE_KEYS.CLIENT_DEVICE_SECRET, credentials.deviceSecret);
914
+ return credentials;
915
+ }
916
+ get axiosInstance() {
917
+ return this.client;
918
+ }
919
+ getStorage() {
920
+ return this.storage;
921
+ }
922
+ };
923
+
924
+ // src/lib/api/auth.ts
925
+ var ZoAuth = class {
926
+ constructor(client) {
927
+ this.client = client;
928
+ }
929
+ /**
930
+ * Send OTP to phone number
931
+ * Step 1 of ZO phone authentication
932
+ */
933
+ async sendOTP(countryCode, phoneNumber) {
934
+ try {
935
+ const payload = {
936
+ mobile_country_code: countryCode,
937
+ mobile_number: phoneNumber,
938
+ message_channel: ""
939
+ // Empty string as per ZO API spec
940
+ };
941
+ const response = await this.client.axiosInstance.post(
942
+ "/api/v1/auth/login/mobile/otp/",
943
+ payload
944
+ );
945
+ if (response.status >= 200 && response.status < 300) {
946
+ return {
947
+ success: true,
948
+ message: response.data?.message || "OTP sent successfully"
949
+ };
950
+ }
951
+ return {
952
+ success: false,
953
+ message: response.data?.message || `Unexpected status: ${response.status}`
954
+ };
955
+ } catch (error) {
956
+ const errorData = error.response?.data;
957
+ const errorMessage = errorData?.detail || errorData?.message || errorData?.error || error.message || "Failed to send OTP";
958
+ return {
959
+ success: false,
960
+ message: errorMessage
961
+ };
962
+ }
963
+ }
964
+ /**
965
+ * Verify OTP and authenticate user
966
+ * Step 2 of ZO phone authentication
967
+ * Returns full auth response with tokens and user profile
968
+ */
969
+ async verifyOTP(countryCode, phoneNumber, otp) {
970
+ try {
971
+ const payload = {
972
+ mobile_country_code: countryCode,
973
+ mobile_number: phoneNumber,
974
+ otp
975
+ };
976
+ const response = await this.client.axiosInstance.post(
977
+ "/api/v1/auth/login/mobile/",
978
+ payload
979
+ );
980
+ let responseData;
981
+ if (typeof response.data === "string") {
982
+ try {
983
+ responseData = JSON.parse(response.data);
984
+ } catch {
985
+ return {
986
+ success: false,
987
+ error: "Invalid response format from authentication service"
988
+ };
989
+ }
990
+ } else {
991
+ responseData = response.data;
992
+ }
993
+ if (!responseData || !responseData.user || !responseData.access_token) {
994
+ return {
995
+ success: false,
996
+ error: "Invalid response structure from authentication service"
997
+ };
998
+ }
999
+ return {
1000
+ success: true,
1001
+ data: responseData
1002
+ };
1003
+ } catch (error) {
1004
+ const errorMessage = this.extractErrorMessage(error);
1005
+ return {
1006
+ success: false,
1007
+ error: errorMessage
1008
+ };
1009
+ }
1010
+ }
1011
+ /**
1012
+ * Refresh access token using refresh token
1013
+ */
1014
+ async refreshAccessToken(refreshToken) {
1015
+ try {
1016
+ const response = await this.client.axiosInstance.post("/api/v1/auth/token/refresh/", {
1017
+ refresh_token: refreshToken
1018
+ });
1019
+ return {
1020
+ success: true,
1021
+ tokens: response.data
1022
+ };
1023
+ } catch (error) {
1024
+ return {
1025
+ success: false,
1026
+ error: "Failed to refresh authentication"
1027
+ };
1028
+ }
1029
+ }
1030
+ /**
1031
+ * Check if user is authenticated
1032
+ */
1033
+ async checkLoginStatus(accessToken) {
1034
+ try {
1035
+ const response = await this.client.axiosInstance.get("/api/v1/auth/login/check/", {
1036
+ headers: {
1037
+ Authorization: `Bearer ${accessToken}`
1038
+ }
1039
+ });
1040
+ return {
1041
+ success: true,
1042
+ isAuthenticated: response.data.authenticated === true
1043
+ };
1044
+ } catch {
1045
+ return {
1046
+ success: false,
1047
+ isAuthenticated: false
1048
+ };
1049
+ }
1050
+ }
1051
+ /**
1052
+ * Extract error message from various ZO API error formats
1053
+ */
1054
+ extractErrorMessage(error) {
1055
+ const errorData = error.response?.data;
1056
+ if (errorData) {
1057
+ if (errorData.errors && Array.isArray(errorData.errors)) {
1058
+ return errorData.errors[0] || "Invalid OTP";
1059
+ }
1060
+ if (errorData.detail) return errorData.detail;
1061
+ if (errorData.message) return errorData.message;
1062
+ if (errorData.error) return errorData.error;
1063
+ }
1064
+ return "Authentication failed";
1065
+ }
1066
+ };
1067
+
1068
+ // src/lib/api/profile.ts
1069
+ var ZoProfile = class {
1070
+ constructor(client) {
1071
+ this.client = client;
1072
+ }
1073
+ /**
1074
+ * Get user profile
1075
+ */
1076
+ async getProfile(accessToken) {
1077
+ try {
1078
+ const response = await this.client.axiosInstance.get(
1079
+ "/api/v1/profile/me/",
1080
+ {
1081
+ headers: {
1082
+ Authorization: `Bearer ${accessToken}`
1083
+ }
1084
+ }
1085
+ );
1086
+ return {
1087
+ success: true,
1088
+ profile: response.data
1089
+ };
1090
+ } catch (error) {
1091
+ const errorData = error.response?.data;
1092
+ return {
1093
+ success: false,
1094
+ error: errorData?.detail || errorData?.message || "Failed to fetch profile"
1095
+ };
1096
+ }
1097
+ }
1098
+ /**
1099
+ * Update user profile (partial updates supported)
1100
+ */
1101
+ async updateProfile(accessToken, updates) {
1102
+ try {
1103
+ const response = await this.client.axiosInstance.post(
1104
+ "/api/v1/profile/me/",
1105
+ updates,
1106
+ {
1107
+ headers: {
1108
+ Authorization: `Bearer ${accessToken}`
1109
+ }
1110
+ }
1111
+ );
1112
+ return {
1113
+ success: true,
1114
+ profile: response.data
1115
+ };
1116
+ } catch (error) {
1117
+ const errorData = error.response?.data;
1118
+ return {
1119
+ success: false,
1120
+ error: errorData?.detail || errorData?.message || "Failed to update profile"
1121
+ };
1122
+ }
1123
+ }
1124
+ };
1125
+
1126
+ // src/lib/api/avatar.ts
1127
+ var ZoAvatar = class {
1128
+ constructor(client) {
1129
+ this.client = client;
1130
+ }
1131
+ /**
1132
+ * Generate avatar for user
1133
+ */
1134
+ async generateAvatar(accessToken, bodyType) {
1135
+ try {
1136
+ const payload = {
1137
+ body_type: bodyType
1138
+ };
1139
+ const response = await this.client.axiosInstance.post(
1140
+ "/api/v1/avatar/generate/",
1141
+ payload,
1142
+ {
1143
+ headers: {
1144
+ Authorization: `Bearer ${accessToken}`
1145
+ }
1146
+ }
1147
+ );
1148
+ return {
1149
+ success: true,
1150
+ task_id: response.data.task_id,
1151
+ status: response.data.status
1152
+ };
1153
+ } catch (error) {
1154
+ const errorData = error.response?.data;
1155
+ return {
1156
+ success: false,
1157
+ error: errorData?.detail || errorData?.message || "Failed to generate avatar"
1158
+ };
1159
+ }
1160
+ }
1161
+ /**
1162
+ * Check avatar generation status
1163
+ */
1164
+ async getAvatarStatus(accessToken, taskId) {
1165
+ try {
1166
+ const response = await this.client.axiosInstance.get(
1167
+ `/api/v1/avatar/status/${taskId}/`,
1168
+ {
1169
+ headers: {
1170
+ Authorization: `Bearer ${accessToken}`
1171
+ }
1172
+ }
1173
+ );
1174
+ return {
1175
+ success: true,
1176
+ status: response.data.status,
1177
+ avatarUrl: response.data.result?.avatar_url
1178
+ };
1179
+ } catch (error) {
1180
+ const errorData = error.response?.data;
1181
+ return {
1182
+ success: false,
1183
+ error: errorData?.detail || errorData?.message || "Failed to get avatar status"
1184
+ };
1185
+ }
1186
+ }
1187
+ /**
1188
+ * Poll avatar status until completion
1189
+ */
1190
+ async pollAvatarStatus(accessToken, taskId, options = {}) {
1191
+ const {
1192
+ onProgress,
1193
+ onComplete,
1194
+ onError,
1195
+ maxAttempts = 30,
1196
+ interval = 2e3
1197
+ } = options;
1198
+ let attempts = 0;
1199
+ const poll = async () => {
1200
+ attempts++;
1201
+ if (attempts > maxAttempts) {
1202
+ const timeoutError = "Avatar generation timed out";
1203
+ onError?.(timeoutError);
1204
+ return;
1205
+ }
1206
+ const result = await this.getAvatarStatus(accessToken, taskId);
1207
+ if (!result.success) {
1208
+ onError?.(result.error || "Unknown error");
1209
+ return;
1210
+ }
1211
+ onProgress?.(result.status || "unknown");
1212
+ if (result.status === "completed" && result.avatarUrl) {
1213
+ onComplete?.(result.avatarUrl);
1214
+ return;
1215
+ }
1216
+ if (result.status === "failed") {
1217
+ onError?.("Avatar generation failed");
1218
+ return;
1219
+ }
1220
+ setTimeout(poll, interval);
1221
+ };
1222
+ poll();
1223
+ }
1224
+ };
1225
+
1226
+ // src/lib/api/wallet.ts
1227
+ var ZO_TOKEN_CONFIG = {
1228
+ base: {
1229
+ rpc: "https://mainnet.base.org",
1230
+ contractAddress: "0x111142c7ecaf39797b7865b82034269962142069",
1231
+ // $Zo token on Base
1232
+ decimals: 18
1233
+ },
1234
+ avalanche: {
1235
+ rpc: "https://api.avax.network/ext/bc/C/rpc",
1236
+ contractAddress: "0x111142c7ecaf39797b7865b82034269962142069",
1237
+ // $Zo token on Avalanche (update if different)
1238
+ decimals: 18
1239
+ }
1240
+ };
1241
+ var ERC20_BALANCE_ABI = "0x70a08231";
1242
+ var ZoWallet = class {
1243
+ constructor(client) {
1244
+ this.cachedBalance = 0;
1245
+ this.userWalletAddress = null;
1246
+ this.network = "base";
1247
+ this.client = client;
1248
+ }
1249
+ /**
1250
+ * Set the user's wallet address for on-chain queries
1251
+ */
1252
+ setWalletAddress(address, network = "base") {
1253
+ this.userWalletAddress = address;
1254
+ this.network = network;
1255
+ logger.debug(`Wallet address set: ${address} on ${network}`);
1256
+ }
1257
+ /**
1258
+ * Get wallet balance - tries on-chain first, then API fallback
1259
+ * @returns Wallet balance amount
1260
+ */
1261
+ async getBalance() {
1262
+ if (this.userWalletAddress) {
1263
+ try {
1264
+ const onChainBalance = await this.getOnChainBalance();
1265
+ if (onChainBalance !== null) {
1266
+ this.cachedBalance = onChainBalance;
1267
+ return onChainBalance;
1268
+ }
1269
+ } catch (error) {
1270
+ logger.warn("On-chain balance check failed, falling back to API:", error);
1271
+ }
1272
+ }
1273
+ const apiBalance = await this.getBalanceFromAPI();
1274
+ if (apiBalance !== null) {
1275
+ return apiBalance;
1276
+ }
1277
+ logger.debug("Returning cached/default balance:", this.cachedBalance);
1278
+ return this.cachedBalance;
1279
+ }
1280
+ /**
1281
+ * Fetch balance directly from blockchain via JSON-RPC
1282
+ */
1283
+ async getOnChainBalance() {
1284
+ if (!this.userWalletAddress) {
1285
+ logger.warn("No wallet address set for on-chain query");
1286
+ return null;
1287
+ }
1288
+ const config = ZO_TOKEN_CONFIG[this.network];
1289
+ try {
1290
+ const paddedAddress = this.userWalletAddress.toLowerCase().replace("0x", "").padStart(64, "0");
1291
+ const data = ERC20_BALANCE_ABI + paddedAddress;
1292
+ const response = await fetch(config.rpc, {
1293
+ method: "POST",
1294
+ headers: { "Content-Type": "application/json" },
1295
+ body: JSON.stringify({
1296
+ jsonrpc: "2.0",
1297
+ id: 1,
1298
+ method: "eth_call",
1299
+ params: [
1300
+ {
1301
+ to: config.contractAddress,
1302
+ data
1303
+ },
1304
+ "latest"
1305
+ ]
1306
+ })
1307
+ });
1308
+ const result = await response.json();
1309
+ if (result.error) {
1310
+ logger.warn("RPC error:", result.error);
1311
+ return null;
1312
+ }
1313
+ const rawBalance = BigInt(result.result || "0x0");
1314
+ const balance = Number(rawBalance) / Math.pow(10, config.decimals);
1315
+ logger.debug(`On-chain balance fetched: ${balance} $Zo`);
1316
+ return balance;
1317
+ } catch (error) {
1318
+ logger.warn("Failed to fetch on-chain balance:", error);
1319
+ return null;
1320
+ }
1321
+ }
1322
+ /**
1323
+ * Fetch balance from Zo API endpoints (tries multiple endpoints with fallback)
1324
+ */
1325
+ async getBalanceFromAPI() {
1326
+ const endpoints = [
1327
+ "/api/v1/web3/token/airdrops/summary",
1328
+ "/api/v1/wallet/balance",
1329
+ "/api/v1/profile/wallet"
1330
+ ];
1331
+ const errors = [];
1332
+ for (const endpoint of endpoints) {
1333
+ try {
1334
+ const response = await this.client.axiosInstance.get(endpoint);
1335
+ const balance = response.data?.data?.total_amount ?? response.data?.balance ?? response.data?.total_amount;
1336
+ if (typeof balance === "number") {
1337
+ logger.debug(`Balance fetched from API ${endpoint}:`, balance);
1338
+ this.cachedBalance = balance;
1339
+ return balance;
1340
+ }
1341
+ } catch (error) {
1342
+ if (error?.response?.status !== 404) {
1343
+ errors.push({
1344
+ endpoint,
1345
+ status: error?.response?.status,
1346
+ message: error?.message || "Unknown error"
1347
+ });
1348
+ }
1349
+ }
1350
+ }
1351
+ if (errors.length > 0) {
1352
+ logger.warn("All balance API endpoints failed:", errors);
1353
+ }
1354
+ return null;
1355
+ }
1356
+ /**
1357
+ * Get transaction history
1358
+ * @param page - Optional page number for pagination
1359
+ * @returns Array of transactions
1360
+ */
1361
+ async getTransactions(page) {
1362
+ const endpoints = [
1363
+ page ? `/api/v1/profile/completion-grants/claims?page=${page}` : "/api/v1/profile/completion-grants/claims",
1364
+ page ? `/api/v1/wallet/transactions?page=${page}` : "/api/v1/wallet/transactions"
1365
+ ];
1366
+ const errors = [];
1367
+ for (const url of endpoints) {
1368
+ try {
1369
+ const response = await this.client.axiosInstance.get(url);
1370
+ const data = response.data?.data || response.data;
1371
+ return {
1372
+ transactions: data?.results ?? data?.transactions ?? [],
1373
+ next: data?.next,
1374
+ previous: data?.previous,
1375
+ count: data?.count ?? 0
1376
+ };
1377
+ } catch (error) {
1378
+ if (error?.response?.status !== 404) {
1379
+ errors.push({
1380
+ endpoint: url,
1381
+ status: error?.response?.status,
1382
+ message: error?.message || "Unknown error"
1383
+ });
1384
+ }
1385
+ }
1386
+ }
1387
+ if (errors.length > 0) {
1388
+ logger.warn("All transaction API endpoints failed:", errors);
1389
+ }
1390
+ return {
1391
+ transactions: [],
1392
+ next: void 0,
1393
+ previous: void 0,
1394
+ count: 0
1395
+ };
1396
+ }
1397
+ };
1398
+
1399
+ // src/ZoPassportSDK.ts
1400
+ var ZoPassportSDK = class {
1401
+ constructor(config) {
1402
+ this.refreshTimer = null;
1403
+ this._user = null;
1404
+ this._isAuthenticated = false;
1405
+ if (config.debug) {
1406
+ logger.enable();
1407
+ logger.setLevel("debug");
1408
+ }
1409
+ this.storage = config.storageAdapter || new LocalStorageAdapter();
1410
+ this.client = new ZoApiClient({
1411
+ ...config,
1412
+ storageAdapter: this.storage
1413
+ });
1414
+ this.auth = new ZoAuth(this.client);
1415
+ this.profile = new ZoProfile(this.client);
1416
+ this.avatar = new ZoAvatar(this.client);
1417
+ this.wallet = new ZoWallet(this.client);
1418
+ if (config.autoRefresh !== false) {
1419
+ this.startAutoRefresh(config.refreshInterval || 6e4);
1420
+ }
1421
+ this._readyPromise = this.loadSession();
1422
+ logger.debug("SDK initialized with config:", {
1423
+ baseUrl: config.baseUrl,
1424
+ autoRefresh: config.autoRefresh !== false
1425
+ });
1426
+ }
1427
+ /**
1428
+ * Wait for the SDK to be ready (session loaded from storage)
1429
+ * Use this if you need to check isAuthenticated immediately after construction
1430
+ */
1431
+ async ready() {
1432
+ return this._readyPromise;
1433
+ }
1434
+ // =====================
1435
+ // Session Management
1436
+ // =====================
1437
+ async loadSession() {
1438
+ try {
1439
+ const userJson = await this.storage.getItem(STORAGE_KEYS.USER);
1440
+ const accessToken = await this.storage.getItem(STORAGE_KEYS.ACCESS_TOKEN);
1441
+ if (userJson && accessToken) {
1442
+ this._user = JSON.parse(userJson);
1443
+ this._isAuthenticated = true;
1444
+ }
1445
+ } catch (error) {
1446
+ logger.warn("Failed to load session:", error);
1447
+ }
1448
+ }
1449
+ async saveSession(authResponse) {
1450
+ await this.storage.setItem(STORAGE_KEYS.ACCESS_TOKEN, authResponse.access_token);
1451
+ await this.storage.setItem(STORAGE_KEYS.REFRESH_TOKEN, authResponse.refresh_token);
1452
+ await this.storage.setItem(STORAGE_KEYS.TOKEN_EXPIRY, authResponse.access_token_expiry);
1453
+ await this.storage.setItem(STORAGE_KEYS.REFRESH_EXPIRY, authResponse.refresh_token_expiry);
1454
+ await this.storage.setItem(STORAGE_KEYS.USER, JSON.stringify(authResponse.user));
1455
+ await this.storage.setItem(STORAGE_KEYS.CLIENT_DEVICE_ID, authResponse.device_id || "");
1456
+ await this.storage.setItem(STORAGE_KEYS.CLIENT_DEVICE_SECRET, authResponse.device_secret || "");
1457
+ this._user = authResponse.user;
1458
+ this._isAuthenticated = true;
1459
+ }
1460
+ async clearSession() {
1461
+ await this.storage.removeItem(STORAGE_KEYS.ACCESS_TOKEN);
1462
+ await this.storage.removeItem(STORAGE_KEYS.REFRESH_TOKEN);
1463
+ await this.storage.removeItem(STORAGE_KEYS.TOKEN_EXPIRY);
1464
+ await this.storage.removeItem(STORAGE_KEYS.REFRESH_EXPIRY);
1465
+ await this.storage.removeItem(STORAGE_KEYS.USER);
1466
+ await this.storage.removeItem(STORAGE_KEYS.CLIENT_DEVICE_ID);
1467
+ await this.storage.removeItem(STORAGE_KEYS.CLIENT_DEVICE_SECRET);
1468
+ this._user = null;
1469
+ this._isAuthenticated = false;
1470
+ }
1471
+ // =====================
1472
+ // Auto Token Refresh
1473
+ // =====================
1474
+ startAutoRefresh(interval) {
1475
+ this.refreshTimer = setInterval(async () => {
1476
+ await this.refreshTokenIfNeeded();
1477
+ }, interval);
1478
+ }
1479
+ stopAutoRefresh() {
1480
+ if (this.refreshTimer) {
1481
+ clearInterval(this.refreshTimer);
1482
+ this.refreshTimer = null;
1483
+ }
1484
+ }
1485
+ async refreshTokenIfNeeded() {
1486
+ const tokenExpiry = await this.storage.getItem(STORAGE_KEYS.TOKEN_EXPIRY);
1487
+ const refreshToken = await this.storage.getItem(STORAGE_KEYS.REFRESH_TOKEN);
1488
+ if (!tokenExpiry || !refreshToken) return;
1489
+ const expiryDate = new Date(tokenExpiry);
1490
+ const now = /* @__PURE__ */ new Date();
1491
+ const twoMinutes = 2 * 60 * 1e3;
1492
+ if (expiryDate.getTime() - now.getTime() < twoMinutes) {
1493
+ const result = await this.auth.refreshAccessToken(refreshToken);
1494
+ if (result.success && result.tokens) {
1495
+ await this.storage.setItem(STORAGE_KEYS.ACCESS_TOKEN, result.tokens.access);
1496
+ await this.storage.setItem(STORAGE_KEYS.REFRESH_TOKEN, result.tokens.refresh);
1497
+ await this.storage.setItem(STORAGE_KEYS.TOKEN_EXPIRY, result.tokens.access_expiry);
1498
+ await this.storage.setItem(STORAGE_KEYS.REFRESH_EXPIRY, result.tokens.refresh_expiry);
1499
+ }
1500
+ }
1501
+ }
1502
+ // =====================
1503
+ // Public API
1504
+ // =====================
1505
+ get user() {
1506
+ return this._user;
1507
+ }
1508
+ get isAuthenticated() {
1509
+ return this._isAuthenticated;
1510
+ }
1511
+ /**
1512
+ * Complete phone authentication flow
1513
+ */
1514
+ async loginWithPhone(countryCode, phoneNumber, otp) {
1515
+ const result = await this.auth.verifyOTP(countryCode, phoneNumber, otp);
1516
+ if (result.success && result.data) {
1517
+ await this.saveSession(result.data);
1518
+ if (result.data.user?.wallet_address) {
1519
+ this.wallet.setWalletAddress(result.data.user.wallet_address, "base");
1520
+ }
1521
+ return { success: true, user: result.data.user };
1522
+ }
1523
+ return { success: false, error: result.error };
1524
+ }
1525
+ /**
1526
+ * Logout and clear session
1527
+ */
1528
+ async logout() {
1529
+ await this.clearSession();
1530
+ this.stopAutoRefresh();
1531
+ }
1532
+ /**
1533
+ * Get current user profile
1534
+ */
1535
+ async getProfile() {
1536
+ const accessToken = await this.storage.getItem(STORAGE_KEYS.ACCESS_TOKEN);
1537
+ if (!accessToken) return null;
1538
+ const result = await this.profile.getProfile(accessToken);
1539
+ if (result.success && result.profile) {
1540
+ this._user = result.profile;
1541
+ await this.storage.setItem(STORAGE_KEYS.USER, JSON.stringify(result.profile));
1542
+ if (result.profile.wallet_address) {
1543
+ this.wallet.setWalletAddress(result.profile.wallet_address, "base");
1544
+ }
1545
+ return result.profile;
1546
+ }
1547
+ return null;
1548
+ }
1549
+ /**
1550
+ * Update user profile
1551
+ */
1552
+ async updateProfile(updates) {
1553
+ const accessToken = await this.storage.getItem(STORAGE_KEYS.ACCESS_TOKEN);
1554
+ if (!accessToken) return { success: false, error: "Not authenticated" };
1555
+ const result = await this.profile.updateProfile(accessToken, updates);
1556
+ if (result.success && result.profile) {
1557
+ this._user = result.profile;
1558
+ await this.storage.setItem(STORAGE_KEYS.USER, JSON.stringify(result.profile));
1559
+ return { success: true, profile: result.profile };
1560
+ }
1561
+ return { success: false, error: result.error };
1562
+ }
1563
+ /**
1564
+ * Generate avatar
1565
+ */
1566
+ async generateAvatar(bodyType) {
1567
+ const accessToken = await this.storage.getItem(STORAGE_KEYS.ACCESS_TOKEN);
1568
+ if (!accessToken) return { success: false, error: "Not authenticated" };
1569
+ const startResult = await this.avatar.generateAvatar(accessToken, bodyType);
1570
+ if (!startResult.success || !startResult.task_id) {
1571
+ return { success: false, error: startResult.error };
1572
+ }
1573
+ return new Promise((resolve) => {
1574
+ this.avatar.pollAvatarStatus(accessToken, startResult.task_id, {
1575
+ onComplete: (avatarUrl) => {
1576
+ resolve({ success: true, avatarUrl });
1577
+ },
1578
+ onError: (error) => {
1579
+ resolve({ success: false, error });
1580
+ }
1581
+ });
1582
+ });
1583
+ }
1584
+ /**
1585
+ * Get wallet balance
1586
+ */
1587
+ async getWalletBalance() {
1588
+ return this.wallet.getBalance();
1589
+ }
1590
+ /**
1591
+ * Get wallet transactions
1592
+ */
1593
+ async getWalletTransactions(page) {
1594
+ return this.wallet.getTransactions(page);
1595
+ }
1596
+ /**
1597
+ * Cleanup
1598
+ */
1599
+ destroy() {
1600
+ this.stopAutoRefresh();
1601
+ }
1602
+ };
1603
+ // Annotate the CommonJS export names for ESM import in node:
1604
+ 0 && (module.exports = {
1605
+ AsyncStorageAdapter,
1606
+ MemoryStorageAdapter,
1607
+ MovingShine,
1608
+ STORAGE_KEYS,
1609
+ TransactionItem,
1610
+ TransactionList,
1611
+ WalletCard,
1612
+ WalletScreen,
1613
+ ZoPassportSDK,
1614
+ ZoToken,
1615
+ ZoTokenVideo
1616
+ });
1617
+ //# sourceMappingURL=react-native.js.map