@airxpay/sdk-ui 1.0.3 → 1.0.5

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.
@@ -33,6 +33,15 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  return result;
34
34
  };
35
35
  })();
36
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
37
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
38
+ return new (P || (P = Promise))(function (resolve, reject) {
39
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
40
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
41
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
42
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
43
+ });
44
+ };
36
45
  var __importDefault = (this && this.__importDefault) || function (mod) {
37
46
  return (mod && mod.__esModule) ? mod : { "default": mod };
38
47
  };
@@ -47,6 +56,7 @@ const KYCVerification_1 = __importDefault(require("../../steps/KYCVerification")
47
56
  const BankDetails_1 = __importDefault(require("../../steps/BankDetails"));
48
57
  const OnboardingComplete_1 = __importDefault(require("../../steps/OnboardingComplete"));
49
58
  const AirXPayProvider_1 = require("../../../contexts/AirXPayProvider");
59
+ const seller_1 = require("../../../api/seller");
50
60
  const { width } = react_native_1.Dimensions.get('window');
51
61
  const STEPS = [
52
62
  { id: 1, name: 'Basic Details', key: 'basic', isRequired: true, icon: 'account' },
@@ -57,32 +67,12 @@ const STEPS = [
57
67
  // Default logo - can be overridden via props
58
68
  const DEFAULT_LOGO = require('../../../assets/images/airxpay.png');
59
69
  const SellerOnboardingSheet = ({ sellerId, mode, isKycCompleted, isBankDetailsCompleted, kycStatus, status, initialStep = 1, initialData = {}, onNext, onBack, onComplete, loading: externalLoading = false, }) => {
60
- // Get configuration from provider (keep intact as required)
70
+ // Get configuration from provider
61
71
  const airXPay = (0, AirXPayProvider_1.useAirXPaySafe)();
62
- if (!airXPay) {
63
- console.warn('AirXPayProvider is undefined. ' +
64
- 'Provider not found in component tree. ' +
65
- 'Value is undefined where provider should be. ' +
66
- 'This undefined provider will cause issues. ' +
67
- 'Undefined context from missing provider. ' +
68
- 'Wrap your app with <AirXPayProvider>. ' +
69
- 'AirXPayProvider cannot be undefined. ' +
70
- 'Undefined provider at root level missing. ' +
71
- 'Add <AirXPayProvider> around your app. ' +
72
- 'Fix this undefined provider immediately.');
73
- }
74
- // Access config safely
75
- const baseUrl = airXPay === null || airXPay === void 0 ? void 0 : airXPay.baseUrl;
76
- const publicKey = airXPay === null || airXPay === void 0 ? void 0 : airXPay.publicKey;
77
- // Properly use variables so TS doesn't complain
78
- (0, react_1.useEffect)(() => {
79
- if (!baseUrl || !publicKey) {
80
- console.warn('AirXPay config is missing baseUrl or publicKey');
81
- }
82
- else {
83
- console.log('āœ… AirXPay ready with baseUrl and publicKey');
84
- }
85
- }, [baseUrl, publicKey]);
72
+ // Local state for provider verification
73
+ const [isVerifying, setIsVerifying] = (0, react_1.useState)(true);
74
+ const [isValidProvider, setIsValidProvider] = (0, react_1.useState)(false);
75
+ const [verificationError, setVerificationError] = (0, react_1.useState)(null);
86
76
  // Animation values
87
77
  const fadeAnim = (0, react_1.useRef)(new react_native_1.Animated.Value(1)).current;
88
78
  const slideAnim = (0, react_1.useRef)(new react_native_1.Animated.Value(0)).current;
@@ -106,6 +96,56 @@ const SellerOnboardingSheet = ({ sellerId, mode, isKycCompleted, isBankDetailsCo
106
96
  kyc: isKycCompleted || false,
107
97
  bank: isBankDetailsCompleted || false,
108
98
  });
99
+ // Verify public key on mount
100
+ (0, react_1.useEffect)(() => {
101
+ const verifyProviderConfig = () => __awaiter(void 0, void 0, void 0, function* () {
102
+ console.log('šŸ” Starting AirXPay provider verification...');
103
+ if (!airXPay) {
104
+ console.error('āŒ AirXPayProvider is undefined - context not found');
105
+ setVerificationError('AirXPay provider not found in component tree. Please wrap your app with <AirXPayProvider>.');
106
+ setIsValidProvider(false);
107
+ setIsVerifying(false);
108
+ return;
109
+ }
110
+ const { baseUrl, publicKey } = airXPay;
111
+ if (!baseUrl || !publicKey) {
112
+ console.error('āŒ AirXPay config missing:', { baseUrl: !!baseUrl, publicKey: !!publicKey });
113
+ setVerificationError('AirXPay configuration incomplete. Both baseUrl and publicKey are required.');
114
+ setIsValidProvider(false);
115
+ setIsVerifying(false);
116
+ return;
117
+ }
118
+ console.log('āœ… AirXPay config found:', { baseUrl, publicKey: publicKey.substring(0, 8) + '...' });
119
+ try {
120
+ setIsVerifying(true);
121
+ console.log('šŸ”‘ Verifying public key with baseUrl:', baseUrl);
122
+ yield (0, seller_1.verifyPublicKey)(baseUrl, publicKey);
123
+ console.log('āœ… Public key verified successfully');
124
+ setIsValidProvider(true);
125
+ setVerificationError(null);
126
+ }
127
+ catch (err) {
128
+ console.error('āŒ Public key verification failed:', err.message);
129
+ setVerificationError(err.message || 'Invalid AirXPay public key. Please check your configuration.');
130
+ setIsValidProvider(false);
131
+ }
132
+ finally {
133
+ setIsVerifying(false);
134
+ }
135
+ });
136
+ verifyProviderConfig();
137
+ }, [airXPay]);
138
+ // Log config status after verification
139
+ (0, react_1.useEffect)(() => {
140
+ if (!isVerifying) {
141
+ if (isValidProvider) {
142
+ console.log('šŸš€ AirXPay provider ready - rendering onboarding');
143
+ }
144
+ else {
145
+ console.warn('āš ļø AirXPay provider invalid - showing error state');
146
+ }
147
+ }
148
+ }, [isVerifying, isValidProvider]);
109
149
  // Update progress bar animation when step changes
110
150
  (0, react_1.useEffect)(() => {
111
151
  react_native_1.Animated.timing(progressAnim, {
@@ -212,10 +252,6 @@ const SellerOnboardingSheet = ({ sellerId, mode, isKycCompleted, isBankDetailsCo
212
252
  if (!validateStepData()) {
213
253
  return;
214
254
  }
215
- if (!baseUrl || !publicKey) {
216
- react_native_1.Alert.alert('Configuration Error', 'AirXPay baseUrl or publicKey is missing. Please check provider setup.');
217
- return;
218
- }
219
255
  // Show loading state while waiting for backend confirmation
220
256
  setIsWaitingForBackend(true);
221
257
  // Success animation
@@ -234,19 +270,45 @@ const SellerOnboardingSheet = ({ sellerId, mode, isKycCompleted, isBankDetailsCo
234
270
  // Prepare complete seller data
235
271
  const completeSellerData = Object.assign(Object.assign({}, sellerData), { mode, kycStatus: stepCompletion.kyc ? 'verified' : kycStatus, isKycCompleted: stepCompletion.kyc, isBankDetailsCompleted: stepCompletion.bank, status: status || (mode === 'live' && stepCompletion.kyc && stepCompletion.bank ? 'active' : 'pending') });
236
272
  // Call onComplete with seller data
237
- // The developer's backend will handle actual seller creation
238
- // and should call a callback or update state when complete
239
273
  onComplete(completeSellerData);
240
274
  }, [sellerData, mode, status, kycStatus, stepCompletion, onComplete, validateStepData]);
241
275
  // This function would be called by the parent when backend confirms creation
242
276
  const handleBackendConfirmation = (0, react_1.useCallback)(() => {
243
277
  setIsWaitingForBackend(false);
244
- // The OnboardingComplete component will now show success state
245
278
  }, []);
246
279
  const getStepTitle = () => {
247
280
  const step = STEPS.find(s => s.id === currentStep);
248
281
  return (step === null || step === void 0 ? void 0 : step.name) || '';
249
282
  };
283
+ const renderProviderVerification = () => {
284
+ if (isVerifying) {
285
+ return (<react_native_1.View style={styles.verificationContainer}>
286
+ <expo_linear_gradient_1.LinearGradient colors={['#0066CC', '#0099FF']} style={styles.verificationCircle} start={{ x: 0, y: 0 }} end={{ x: 1, y: 1 }}>
287
+ <react_native_paper_1.ActivityIndicator size="large" color="#FFFFFF"/>
288
+ </expo_linear_gradient_1.LinearGradient>
289
+ <react_native_paper_1.Text style={styles.verificationText}>
290
+ Verifying AirXPay configuration...
291
+ </react_native_paper_1.Text>
292
+ <react_native_paper_1.Text style={styles.verificationSubtext}>
293
+ Please wait while we validate your public key
294
+ </react_native_paper_1.Text>
295
+ </react_native_1.View>);
296
+ }
297
+ if (!isValidProvider) {
298
+ return (<react_native_1.View style={styles.verificationContainer}>
299
+ <react_native_1.View style={[styles.verificationCircle, { backgroundColor: '#FF4444' }]}>
300
+ <react_native_paper_1.IconButton icon="alert" size={40} iconColor="#FFFFFF" style={{ margin: 0 }}/>
301
+ </react_native_1.View>
302
+ <react_native_paper_1.Text style={[styles.verificationText, { color: '#FF4444' }]}>
303
+ Invalid AirXPay Configuration
304
+ </react_native_paper_1.Text>
305
+ <react_native_paper_1.Text style={styles.errorMessage}>
306
+ {verificationError || 'Invalid AirXPay public key. Please check your configuration.'}
307
+ </react_native_paper_1.Text>
308
+ </react_native_1.View>);
309
+ }
310
+ return null;
311
+ };
250
312
  const renderStep = () => {
251
313
  const isLoading = externalLoading || isSubmitting;
252
314
  if (isLoading) {
@@ -290,6 +352,16 @@ const SellerOnboardingSheet = ({ sellerId, mode, isKycCompleted, isBankDetailsCo
290
352
  inputRange: [0, 1],
291
353
  outputRange: ['0%', '100%'],
292
354
  });
355
+ // Check if we should show verification UI
356
+ if (isVerifying || !isValidProvider) {
357
+ return (<react_native_1.SafeAreaView style={styles.container}>
358
+ <react_native_1.StatusBar barStyle="dark-content" backgroundColor="#F8F9FA"/>
359
+ <expo_linear_gradient_1.LinearGradient colors={['#F8F9FA', '#FFFFFF']} style={styles.gradient} start={{ x: 0, y: 0 }} end={{ x: 0, y: 1 }}>
360
+ {renderProviderVerification()}
361
+ </expo_linear_gradient_1.LinearGradient>
362
+ </react_native_1.SafeAreaView>);
363
+ }
364
+ // Normal onboarding UI when provider is valid
293
365
  return (<react_native_1.SafeAreaView style={styles.container}>
294
366
  <react_native_1.StatusBar barStyle="dark-content" backgroundColor="#F8F9FA"/>
295
367
 
@@ -311,7 +383,7 @@ const SellerOnboardingSheet = ({ sellerId, mode, isKycCompleted, isBankDetailsCo
311
383
  </react_native_1.View>
312
384
  </react_native_1.View>
313
385
 
314
- {/* Logo Section - Now configurable */}
386
+ {/* Logo Section */}
315
387
  <react_native_1.View style={styles.logoContainer}>
316
388
  <react_native_paper_1.Avatar.Image size={40} source={DEFAULT_LOGO} style={styles.avatar}/>
317
389
  </react_native_1.View>
@@ -473,5 +545,39 @@ const styles = react_native_1.StyleSheet.create({
473
545
  marginBottom: 16,
474
546
  borderRadius: 8,
475
547
  },
548
+ // New styles for provider verification
549
+ verificationContainer: {
550
+ flex: 1,
551
+ justifyContent: 'center',
552
+ alignItems: 'center',
553
+ padding: 20,
554
+ },
555
+ verificationCircle: {
556
+ width: 100,
557
+ height: 100,
558
+ borderRadius: 50,
559
+ justifyContent: 'center',
560
+ alignItems: 'center',
561
+ marginBottom: 24,
562
+ },
563
+ verificationText: {
564
+ fontSize: 20,
565
+ fontWeight: '700',
566
+ color: '#1A1A1A',
567
+ marginBottom: 8,
568
+ textAlign: 'center',
569
+ },
570
+ verificationSubtext: {
571
+ fontSize: 14,
572
+ color: '#666666',
573
+ textAlign: 'center',
574
+ },
575
+ errorMessage: {
576
+ fontSize: 16,
577
+ color: '#666666',
578
+ textAlign: 'center',
579
+ marginTop: 8,
580
+ paddingHorizontal: 20,
581
+ },
476
582
  });
477
583
  exports.default = SellerOnboardingSheet;
@@ -1,14 +1,21 @@
1
1
  import React from "react";
2
2
  import { AirXPayConfig } from "../types/type";
3
+ import { SellerInitResponse } from "../api/seller";
4
+ interface AirXPayContextExtended extends AirXPayConfig {
5
+ isValid: boolean;
6
+ loading: boolean;
7
+ sellerData?: SellerInitResponse;
8
+ error?: string;
9
+ }
3
10
  interface AirXPayProviderProps {
4
11
  config: AirXPayConfig;
5
12
  children: React.ReactNode;
6
13
  enableLogging?: boolean;
7
14
  }
8
15
  export declare const AirXPayProvider: React.FC<AirXPayProviderProps>;
9
- export declare const useAirXPay: () => AirXPayConfig;
10
- export declare const useAirXPaySafe: () => AirXPayConfig | null;
16
+ export declare const useAirXPay: () => AirXPayContextExtended;
17
+ export declare const useAirXPaySafe: () => AirXPayContextExtended | null;
11
18
  export declare const useAirXPayConfig: <K extends keyof AirXPayConfig>(key: K) => AirXPayConfig[K] | undefined;
12
19
  export declare const useProviderReady: () => boolean;
13
- export declare const AirXPayConsumer: React.Consumer<AirXPayConfig | null>;
20
+ export declare const AirXPayConsumer: React.Consumer<AirXPayContextExtended | null>;
14
21
  export default AirXPayProvider;
@@ -32,14 +32,24 @@ var __importStar = (this && this.__importStar) || (function () {
32
32
  return result;
33
33
  };
34
34
  })();
35
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
36
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
37
+ return new (P || (P = Promise))(function (resolve, reject) {
38
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
39
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
40
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
41
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
42
+ });
43
+ };
35
44
  Object.defineProperty(exports, "__esModule", { value: true });
36
45
  exports.AirXPayConsumer = exports.useProviderReady = exports.useAirXPayConfig = exports.useAirXPaySafe = exports.useAirXPay = exports.AirXPayProvider = void 0;
46
+ // AirXPayProvider.tsx
37
47
  const react_1 = __importStar(require("react"));
38
- // Context with professional error handling
48
+ const seller_1 = require("../api/seller");
39
49
  const AirXPayContext = (0, react_1.createContext)(null);
40
50
  AirXPayContext.displayName = "AirXPayContext";
41
51
  const AirXPayProvider = ({ config, children, enableLogging = __DEV__, }) => {
42
- // Validate configuration on mount
52
+ const [state, setState] = (0, react_1.useState)(Object.assign(Object.assign({}, config), { isValid: false, loading: true }));
43
53
  (0, react_1.useEffect)(() => {
44
54
  const validationErrors = [];
45
55
  // Validate baseUrl
@@ -64,7 +74,6 @@ const AirXPayProvider = ({ config, children, enableLogging = __DEV__, }) => {
64
74
  else if (config.publicKey.length < 20) {
65
75
  validationErrors.push("publicKey appears to be invalid. Please check your API key.");
66
76
  }
67
- // Throw error if validation fails
68
77
  if (validationErrors.length > 0) {
69
78
  const errorMessage = [
70
79
  "AirXPayProvider Configuration Error:",
@@ -72,26 +81,37 @@ const AirXPayProvider = ({ config, children, enableLogging = __DEV__, }) => {
72
81
  "",
73
82
  "Received config:",
74
83
  ` • baseUrl: ${config.baseUrl || "missing"}`,
75
- ` • publicKey: ${config.publicKey ? `${config.publicKey.substring(0, 8)}...` : "missing"}`,
84
+ ` • publicKey: ${config.publicKey ? `${config.publicKey.substring(0, 8)}...` : "missing"}`
76
85
  ].join("\n");
77
- if (enableLogging) {
86
+ if (enableLogging)
78
87
  console.error("āŒ AirXPay:", errorMessage);
79
- }
80
88
  throw new Error(errorMessage);
81
89
  }
82
- // Log success in development
83
90
  if (enableLogging) {
84
91
  console.log("%cāœ… AirXPay Provider Initialized", "color: #10b981; font-weight: bold;", {
85
92
  baseUrl: config.baseUrl,
86
93
  publicKey: `${config.publicKey.substring(0, 8)}...`,
87
94
  });
88
95
  }
96
+ // Now call the public key verification API
97
+ const verifyKey = () => __awaiter(void 0, void 0, void 0, function* () {
98
+ try {
99
+ const sellerData = yield (0, seller_1.verifyPublicKey)(config.baseUrl, config.publicKey);
100
+ setState(Object.assign(Object.assign({}, config), { isValid: true, loading: false, sellerData }));
101
+ if (enableLogging)
102
+ console.log("āœ… Public key verified", sellerData);
103
+ }
104
+ catch (err) {
105
+ console.error("āŒ Public key verification failed", err);
106
+ setState(Object.assign(Object.assign({}, config), { isValid: false, loading: false, error: err.message }));
107
+ }
108
+ });
109
+ verifyKey();
89
110
  }, [config, enableLogging]);
90
- return (<AirXPayContext.Provider value={config}>{children}</AirXPayContext.Provider>);
111
+ return <AirXPayContext.Provider value={state}>{children}</AirXPayContext.Provider>;
91
112
  };
92
113
  exports.AirXPayProvider = AirXPayProvider;
93
- exports.AirXPayProvider.displayName = "AirXPayProvider";
94
- // Professional hook with clear error messages
114
+ // Hook: strict (throws if provider not found)
95
115
  const useAirXPay = () => {
96
116
  var _a, _b;
97
117
  const context = (0, react_1.useContext)(AirXPayContext);
@@ -117,9 +137,8 @@ const useAirXPay = () => {
117
137
  " </AirXPayProvider>",
118
138
  "",
119
139
  " • Verify the provider is not inside a conditional or loop",
120
- ` • Component location: ${((_b = (_a = new Error().stack) === null || _a === void 0 ? void 0 : _a.split("\n")[2]) === null || _b === void 0 ? void 0 : _b.trim()) || "unknown"}`,
140
+ ` • Component location: ${((_b = (_a = new Error().stack) === null || _a === void 0 ? void 0 : _a.split("\n")[2]) === null || _b === void 0 ? void 0 : _b.trim()) || "unknown"}`
121
141
  ].join("\n");
122
- // Log with styling in development
123
142
  if (__DEV__) {
124
143
  console.error("%cāŒ AirXPay Context Error", "color: #ef4444; font-size: 14px; font-weight: bold;", "\n" + errorMessage);
125
144
  }
@@ -128,7 +147,7 @@ const useAirXPay = () => {
128
147
  return context;
129
148
  };
130
149
  exports.useAirXPay = useAirXPay;
131
- // Helper: Check if config exists without throwing
150
+ // Hook: safe (returns null if missing)
132
151
  const useAirXPaySafe = () => {
133
152
  try {
134
153
  return (0, exports.useAirXPay)();
@@ -138,18 +157,18 @@ const useAirXPaySafe = () => {
138
157
  }
139
158
  };
140
159
  exports.useAirXPaySafe = useAirXPaySafe;
141
- // Helper: Access specific config value
160
+ // Hook: access specific key
142
161
  const useAirXPayConfig = (key) => {
143
- const config = (0, exports.useAirXPaySafe)();
144
- return config === null || config === void 0 ? void 0 : config[key];
162
+ const context = (0, exports.useAirXPaySafe)();
163
+ return context === null || context === void 0 ? void 0 : context[key];
145
164
  };
146
165
  exports.useAirXPayConfig = useAirXPayConfig;
147
- // Helper: Check if provider is properly configured
166
+ // Hook: check if provider ready
148
167
  const useProviderReady = () => {
149
- const config = (0, exports.useAirXPaySafe)();
150
- return !!((config === null || config === void 0 ? void 0 : config.baseUrl) && (config === null || config === void 0 ? void 0 : config.publicKey));
168
+ const context = (0, exports.useAirXPaySafe)();
169
+ return !!((context === null || context === void 0 ? void 0 : context.baseUrl) && (context === null || context === void 0 ? void 0 : context.publicKey) && context.isValid);
151
170
  };
152
171
  exports.useProviderReady = useProviderReady;
153
- // Export context consumer for advanced use cases
172
+ // Consumer for advanced usage
154
173
  exports.AirXPayConsumer = AirXPayContext.Consumer;
155
174
  exports.default = exports.AirXPayProvider;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@airxpay/sdk-ui",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "description": "AirXPay Initialization UI Components for React & React Native",
5
5
  "author": "Tafseel Khan",
6
6
  "license": "MIT",