react-native-fpay 0.1.1 → 0.2.2

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.
@@ -1,17 +1,133 @@
1
1
  "use strict";
2
2
 
3
- // ─────────────────────────────────────────────
3
+ // ─────────────────────────────────────────────────────────────────────────────
4
4
  // FountainPayProvider
5
- // The ONLY thing the host app mounts.
6
- // Wraps children and mounts the invisible shell.
7
- // ─────────────────────────────────────────────
8
- import React from 'react';
5
+ //
6
+ // Mount once at the root of your app and pass your API key here.
7
+ // Every component can then call useFountainPay() (no arguments) and get
8
+ // the SAME instance — no re-initialization, no prop drilling.
9
+ //
10
+ // Usage:
11
+ // <FountainPayProvider apiKey="fp_live_...">
12
+ // <YourApp />
13
+ // </FountainPayProvider>
14
+ // ─────────────────────────────────────────────────────────────────────────────
15
+ import React, { createContext, useContext, useMemo, useRef } from 'react';
9
16
  import { FPShell } from "./ui/modals/FPShell.js";
10
- import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
17
+ import { FPEngine } from "./engine/FPEngine.js";
18
+ import { initClient } from "./core/api/client.js";
19
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
20
+ // ── Context ───────────────────────────────────────────────────────────────────
21
+
22
+ const FountainPayContext = /*#__PURE__*/createContext(null);
23
+
24
+ // ── Hook — the only thing components import ───────────────────────────────────
25
+
26
+ /**
27
+ * Returns the shared FountainPay instance created by the nearest
28
+ * <FountainPayProvider>. No API key needed here — it was given to the provider.
29
+ *
30
+ * Call from any component:
31
+ * const pay = useFountainPay();
32
+ * await pay.initializeSDK(user, callbacks); // call once after login
33
+ * pay.send(500, 'NGN'); // call anywhere, anytime
34
+ */
35
+ export function useFountainPay() {
36
+ const instance = useContext(FountainPayContext);
37
+ if (!instance) {
38
+ throw new Error('[FountainPay] useFountainPay() must be called inside <FountainPayProvider>.\n' + 'Make sure you have wrapped your app root with <FountainPayProvider apiKey="...">.');
39
+ }
40
+ return instance;
41
+ }
42
+
43
+ // ── Provider ──────────────────────────────────────────────────────────────────
44
+
11
45
  export function FountainPayProvider({
46
+ apiKey,
47
+ options,
12
48
  children
13
49
  }) {
14
- return /*#__PURE__*/_jsxs(_Fragment, {
50
+ // Boot the HTTP client as soon as the provider mounts —
51
+ // this means generateAccountNumber works even before initializeSDK
52
+ const clientBooted = useRef(false);
53
+ if (!clientBooted.current) {
54
+ initClient(apiKey, {
55
+ baseUrl: options?.baseUrl,
56
+ environment: options?.environment
57
+ });
58
+ clientBooted.current = true;
59
+ console.log('[FountainPay] Provider mounted. HTTP client ready.');
60
+ }
61
+
62
+ // Build the instance once per provider lifetime.
63
+ // All components that call useFountainPay() share this exact object.
64
+ const instance = useMemo(() => {
65
+ console.log('[FountainPay] Creating shared FPInstance for apiKey:', apiKey.slice(0, 8) + '...');
66
+ return {
67
+ /**
68
+ * Call once after the user logs in.
69
+ * Starts BLE advertising, proximity broadcast, and the payment listener.
70
+ */
71
+ async initializeSDK(user, callbacks) {
72
+ console.log('[FountainPay] initializeSDK() called for user:', user.accountName);
73
+ try {
74
+ await FPEngine.initialize(apiKey, user, options ?? {}, callbacks ?? {});
75
+ console.log('[FountainPay] initializeSDK() complete. SDK is ready.');
76
+ } catch (err) {
77
+ console.error('[FountainPay] initializeSDK() FAILED:', err);
78
+ throw err;
79
+ }
80
+ },
81
+ /** Open the Send Money bottom sheet. */
82
+ send(amount, currency) {
83
+ console.log('[FountainPay] send() called:', amount, currency);
84
+ if (!FPEngine.isReady()) {
85
+ console.warn('[FountainPay] send() called before initializeSDK() — call initializeSDK first.');
86
+ }
87
+ FPEngine.showSend(amount, currency);
88
+ },
89
+ /** Open the Receive Money bottom sheet. */
90
+ receive(amount, currency = 'NGN') {
91
+ console.log('[FountainPay] receive() called:', amount, currency);
92
+ if (!FPEngine.isReady()) {
93
+ console.warn('[FountainPay] receive() called before initializeSDK().');
94
+ }
95
+ FPEngine.showReceive(amount, currency);
96
+ },
97
+ /** Generate a virtual account number (no UI shown). */
98
+ async generateAccountNumber(request) {
99
+ console.log('[FountainPay] generateAccountNumber() called:', request.accountName);
100
+ return FPEngine.generateAccount(request);
101
+ },
102
+ /**
103
+ * Activate the incoming Bluetooth payment request listener.
104
+ * When a nearby device sends a payment request, the Accept/Decline
105
+ * modal will appear automatically.
106
+ */
107
+ listen() {
108
+ console.log('[FountainPay] listen() called — activating BT payment listener.');
109
+ if (!FPEngine.isReady()) {
110
+ console.warn('[FountainPay] listen() called before initializeSDK().');
111
+ }
112
+ FPEngine.startListening();
113
+ },
114
+ /** Stop all background services. Call on logout. */
115
+ async destroy() {
116
+ console.log('[FountainPay] destroy() called — stopping all services.');
117
+ await FPEngine.destroy();
118
+ console.log('[FountainPay] All services stopped.');
119
+ },
120
+ get isReady() {
121
+ return FPEngine.isReady();
122
+ },
123
+ get currentUser() {
124
+ return FPEngine.getUser();
125
+ }
126
+ };
127
+ // Re-create instance only if the apiKey changes (which should never happen at runtime)
128
+ }, [apiKey]);
129
+ return /*#__PURE__*/_jsxs(FountainPayContext.Provider, {
130
+ value: instance,
15
131
  children: [children, /*#__PURE__*/_jsx(FPShell, {})]
16
132
  });
17
133
  }
@@ -1 +1 @@
1
- {"version":3,"names":["React","FPShell","jsx","_jsx","Fragment","_Fragment","jsxs","_jsxs","FountainPayProvider","children"],"sourceRoot":"../../src","sources":["FountainPayProvider.tsx"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA,OAAOA,KAAK,MAA0B,OAAO;AAC7C,SAASC,OAAO,QAAQ,wBAAqB;AAAC,SAAAC,GAAA,IAAAC,IAAA,EAAAC,QAAA,IAAAC,SAAA,EAAAC,IAAA,IAAAC,KAAA;AAM9C,OAAO,SAASC,mBAAmBA,CAAC;EAAEC;AAAgB,CAAC,EAAE;EACvD,oBACEF,KAAA,CAAAF,SAAA;IAAAI,QAAA,GACGA,QAAQ,eAETN,IAAA,CAACF,OAAO,IAAE,CAAC;EAAA,CACX,CAAC;AAEP","ignoreList":[]}
1
+ {"version":3,"names":["React","createContext","useContext","useMemo","useRef","FPShell","FPEngine","initClient","jsx","_jsx","jsxs","_jsxs","FountainPayContext","useFountainPay","instance","Error","FountainPayProvider","apiKey","options","children","clientBooted","current","baseUrl","environment","console","log","slice","initializeSDK","user","callbacks","accountName","initialize","err","error","send","amount","currency","isReady","warn","showSend","receive","showReceive","generateAccountNumber","request","generateAccount","listen","startListening","destroy","currentUser","getUser","Provider","value"],"sourceRoot":"../../src","sources":["FountainPayProvider.tsx"],"mappings":"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","ignoreList":[]}
@@ -1,82 +1,6 @@
1
1
  "use strict";
2
2
 
3
- // ─────────────────────────────────────────────────────────────
4
- // useFountainPay — The ONLY hook the host app ever uses.
5
- //
6
- // Usage:
7
- // const pay = useFountainPay('your-api-key');
8
- // await pay.initializeSDK(userInfo, callbacks);
9
- // pay.send(500, 'NGN');
10
- // pay.receive(200, 'NGN');
11
- // const acct = await pay.generateAccountNumber({ accountName: 'John' });
12
- // pay.listen();
13
- // pay.destroy();
14
- // ─────────────────────────────────────────────────────────────
15
- import { useMemo } from 'react';
16
- import { FPEngine } from "./engine/FPEngine.js";
17
- import { initClient } from "./core/api/client.js";
18
- export function useFountainPay(apiKey, options) {
19
- // Initialize HTTP client immediately so API calls can be made
20
- // even before initializeSDK (e.g. generateAccountNumber for onboarding)
21
- useMemo(() => {
22
- initClient(apiKey, {
23
- baseUrl: options?.baseUrl,
24
- environment: options?.environment
25
- });
26
- }, [apiKey]);
27
- const instance = useMemo(() => ({
28
- /**
29
- * Call this once after the user logs in.
30
- * Starts proximity broadcasting, BLE peripheral, and BT listener.
31
- */
32
- async initializeSDK(user, callbacks) {
33
- await FPEngine.initialize(apiKey, user, options ?? {}, callbacks ?? {});
34
- },
35
- /**
36
- * Open the Send Money sheet.
37
- * @param amount Major denomination (e.g. 500 for NGN 500)
38
- * @param currency e.g. 'NGN', 'USD'
39
- */
40
- send(amount, currency) {
41
- FPEngine.showSend(amount, currency);
42
- },
43
- /**
44
- * Open the Receive Money sheet.
45
- * @param amount Expected amount (optional)
46
- * @param currency e.g. 'NGN'
47
- */
48
- receive(amount, currency = 'NGN') {
49
- FPEngine.showReceive(amount, currency);
50
- },
51
- /**
52
- * Generate a virtual account number.
53
- * No UI is shown — returns the account directly.
54
- */
55
- async generateAccountNumber(request) {
56
- return FPEngine.generateAccount(request);
57
- },
58
- /**
59
- * Start listening for incoming Bluetooth payment requests.
60
- * When one arrives, the SDK auto-shows the Accept/Decline modal.
61
- * The result fires onPaymentReceived / onPaymentDeclined callbacks
62
- * that were passed into initializeSDK.
63
- */
64
- listen() {
65
- FPEngine.startListening();
66
- },
67
- /**
68
- * Stop all background services. Call on logout.
69
- */
70
- destroy() {
71
- FPEngine.destroy();
72
- },
73
- get isReady() {
74
- return FPEngine.isReady();
75
- },
76
- get currentUser() {
77
- return FPEngine.getUser();
78
- }
79
- }), [apiKey]);
80
- return instance;
81
- }
3
+ // useFountainPay re-exported from FountainPayProvider.
4
+ // The hook lives in FountainPayProvider.tsx now.
5
+ export { useFountainPay } from "./FountainPayProvider.js";
82
6
  //# sourceMappingURL=useFountainPay.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["useMemo","FPEngine","initClient","useFountainPay","apiKey","options","baseUrl","environment","instance","initializeSDK","user","callbacks","initialize","send","amount","currency","showSend","receive","showReceive","generateAccountNumber","request","generateAccount","listen","startListening","destroy","isReady","currentUser","getUser"],"sourceRoot":"../../src","sources":["useFountainPay.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASA,OAAO,QAAQ,OAAO;AAC/B,SAASC,QAAQ,QAAQ,sBAAmB;AAC5C,SAASC,UAAU,QAAQ,sBAAmB;AAW9C,OAAO,SAASC,cAAcA,CAACC,MAAc,EAAEC,OAAsB,EAAc;EACjF;EACA;EACAL,OAAO,CAAC,MAAM;IACZE,UAAU,CAACE,MAAM,EAAE;MAAEE,OAAO,EAAED,OAAO,EAAEC,OAAO;MAAEC,WAAW,EAAEF,OAAO,EAAEE;IAAY,CAAC,CAAC;EACtF,CAAC,EAAE,CAACH,MAAM,CAAC,CAAC;EAEZ,MAAMI,QAAQ,GAAGR,OAAO,CAAa,OAAO;IAC1C;AACJ;AACA;AACA;IACI,MAAMS,aAAaA,CAACC,IAAgB,EAAEC,SAAuB,EAAiB;MAC5E,MAAMV,QAAQ,CAACW,UAAU,CAACR,MAAM,EAAEM,IAAI,EAAEL,OAAO,IAAI,CAAC,CAAC,EAAEM,SAAS,IAAI,CAAC,CAAC,CAAC;IACzE,CAAC;IAED;AACJ;AACA;AACA;AACA;IACIE,IAAIA,CAACC,MAAc,EAAEC,QAAoB,EAAQ;MAC/Cd,QAAQ,CAACe,QAAQ,CAACF,MAAM,EAAEC,QAAQ,CAAC;IACrC,CAAC;IAED;AACJ;AACA;AACA;AACA;IACIE,OAAOA,CAACH,MAAe,EAAEC,QAAoB,GAAG,KAAK,EAAQ;MAC3Dd,QAAQ,CAACiB,WAAW,CAACJ,MAAM,EAAEC,QAAQ,CAAC;IACxC,CAAC;IAED;AACJ;AACA;AACA;IACI,MAAMI,qBAAqBA,CAACC,OAAiC,EAA6B;MACxF,OAAOnB,QAAQ,CAACoB,eAAe,CAACD,OAAO,CAAC;IAC1C,CAAC;IAED;AACJ;AACA;AACA;AACA;AACA;IACIE,MAAMA,CAAA,EAAS;MACbrB,QAAQ,CAACsB,cAAc,CAAC,CAAC;IAC3B,CAAC;IAED;AACJ;AACA;IACIC,OAAOA,CAAA,EAAS;MACdvB,QAAQ,CAACuB,OAAO,CAAC,CAAC;IACpB,CAAC;IAED,IAAIC,OAAOA,CAAA,EAAY;MACrB,OAAOxB,QAAQ,CAACwB,OAAO,CAAC,CAAC;IAC3B,CAAC;IAED,IAAIC,WAAWA,CAAA,EAAsB;MACnC,OAAOzB,QAAQ,CAAC0B,OAAO,CAAC,CAAC;IAC3B;EACF,CAAC,CAAC,EAAE,CAACvB,MAAM,CAAC,CAAC;EAEb,OAAOI,QAAQ;AACjB","ignoreList":[]}
1
+ {"version":3,"names":["useFountainPay"],"sourceRoot":"../../src","sources":["useFountainPay.ts"],"mappings":";;AAAA;AACA;AACA,SAASA,cAAc,QAAQ,0BAAuB","ignoreList":[]}
@@ -1,7 +1,20 @@
1
1
  import { type ReactNode } from 'react';
2
- interface Props {
2
+ import type { FPInstance, FPSDKOptions } from './core/types';
3
+ /**
4
+ * Returns the shared FountainPay instance created by the nearest
5
+ * <FountainPayProvider>. No API key needed here — it was given to the provider.
6
+ *
7
+ * Call from any component:
8
+ * const pay = useFountainPay();
9
+ * await pay.initializeSDK(user, callbacks); // call once after login
10
+ * pay.send(500, 'NGN'); // call anywhere, anytime
11
+ */
12
+ export declare function useFountainPay(): FPInstance;
13
+ interface ProviderProps {
14
+ apiKey: string;
15
+ options?: FPSDKOptions;
3
16
  children: ReactNode;
4
17
  }
5
- export declare function FountainPayProvider({ children }: Props): import("react/jsx-runtime").JSX.Element;
18
+ export declare function FountainPayProvider({ apiKey, options, children }: ProviderProps): import("react/jsx-runtime").JSX.Element;
6
19
  export {};
7
20
  //# sourceMappingURL=FountainPayProvider.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"FountainPayProvider.d.ts","sourceRoot":"","sources":["../../../src/FountainPayProvider.tsx"],"names":[],"mappings":"AAKA,OAAc,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAG9C,UAAU,KAAK;IACb,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,wBAAgB,mBAAmB,CAAC,EAAE,QAAQ,EAAE,EAAE,KAAK,2CAQtD"}
1
+ {"version":3,"file":"FountainPayProvider.d.ts","sourceRoot":"","sources":["../../../src/FountainPayProvider.tsx"],"names":[],"mappings":"AAYA,OAAc,EACZ,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAIf,OAAO,KAAK,EACV,UAAU,EAEV,YAAY,EAKb,MAAM,cAAc,CAAC;AAQtB;;;;;;;;GAQG;AACH,wBAAgB,cAAc,IAAI,UAAU,CAS3C;AAID,UAAU,aAAa;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,wBAAgB,mBAAmB,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,aAAa,2CA6F/E"}
@@ -1,3 +1,2 @@
1
- import type { FPInstance, FPSDKOptions } from './core/types';
2
- export declare function useFountainPay(apiKey: string, options?: FPSDKOptions): FPInstance;
1
+ export { useFountainPay } from './FountainPayProvider';
3
2
  //# sourceMappingURL=useFountainPay.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useFountainPay.d.ts","sourceRoot":"","sources":["../../../src/useFountainPay.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EACV,UAAU,EAEV,YAAY,EAKb,MAAM,cAAc,CAAC;AAEtB,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,UAAU,CAqEjF"}
1
+ {"version":3,"file":"useFountainPay.d.ts","sourceRoot":"","sources":["../../../src/useFountainPay.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-fpay",
3
- "version": "0.1.1",
3
+ "version": "0.2.2",
4
4
  "description": "Fountain Pay react-native sdk library",
5
5
  "main": "./lib/module/index.js",
6
6
  "module": "./lib/module/index.js",
@@ -1,21 +1,156 @@
1
- // ─────────────────────────────────────────────
1
+ // ─────────────────────────────────────────────────────────────────────────────
2
2
  // FountainPayProvider
3
- // The ONLY thing the host app mounts.
4
- // Wraps children and mounts the invisible shell.
5
- // ─────────────────────────────────────────────
6
- import React, { type ReactNode } from 'react';
3
+ //
4
+ // Mount once at the root of your app and pass your API key here.
5
+ // Every component can then call useFountainPay() (no arguments) and get
6
+ // the SAME instance no re-initialization, no prop drilling.
7
+ //
8
+ // Usage:
9
+ // <FountainPayProvider apiKey="fp_live_...">
10
+ // <YourApp />
11
+ // </FountainPayProvider>
12
+ // ─────────────────────────────────────────────────────────────────────────────
13
+ import React, {
14
+ type ReactNode, createContext, useContext, useMemo, useRef,
15
+ } from 'react';
7
16
  import { FPShell } from './ui/modals/FPShell';
17
+ import { FPEngine } from './engine/FPEngine';
18
+ import { initClient } from './core/api/client';
19
+ import type {
20
+ FPInstance,
21
+ FPUserInfo,
22
+ FPSDKOptions,
23
+ FPCallbacks,
24
+ FPCurrency,
25
+ FPGenerateAccountRequest,
26
+ FPVirtualAccount,
27
+ } from './core/types';
8
28
 
9
- interface Props {
29
+ // ── Context ───────────────────────────────────────────────────────────────────
30
+
31
+ const FountainPayContext = createContext<FPInstance | null>(null);
32
+
33
+ // ── Hook — the only thing components import ───────────────────────────────────
34
+
35
+ /**
36
+ * Returns the shared FountainPay instance created by the nearest
37
+ * <FountainPayProvider>. No API key needed here — it was given to the provider.
38
+ *
39
+ * Call from any component:
40
+ * const pay = useFountainPay();
41
+ * await pay.initializeSDK(user, callbacks); // call once after login
42
+ * pay.send(500, 'NGN'); // call anywhere, anytime
43
+ */
44
+ export function useFountainPay(): FPInstance {
45
+ const instance = useContext(FountainPayContext);
46
+ if (!instance) {
47
+ throw new Error(
48
+ '[FountainPay] useFountainPay() must be called inside <FountainPayProvider>.\n' +
49
+ 'Make sure you have wrapped your app root with <FountainPayProvider apiKey="...">.'
50
+ );
51
+ }
52
+ return instance;
53
+ }
54
+
55
+ // ── Provider ──────────────────────────────────────────────────────────────────
56
+
57
+ interface ProviderProps {
58
+ apiKey: string;
59
+ options?: FPSDKOptions;
10
60
  children: ReactNode;
11
61
  }
12
62
 
13
- export function FountainPayProvider({ children }: Props) {
63
+ export function FountainPayProvider({ apiKey, options, children }: ProviderProps) {
64
+ // Boot the HTTP client as soon as the provider mounts —
65
+ // this means generateAccountNumber works even before initializeSDK
66
+ const clientBooted = useRef(false);
67
+ if (!clientBooted.current) {
68
+ initClient(apiKey, { baseUrl: options?.baseUrl, environment: options?.environment });
69
+ clientBooted.current = true;
70
+ console.log('[FountainPay] Provider mounted. HTTP client ready.');
71
+ }
72
+
73
+ // Build the instance once per provider lifetime.
74
+ // All components that call useFountainPay() share this exact object.
75
+ const instance = useMemo<FPInstance>(() => {
76
+ console.log('[FountainPay] Creating shared FPInstance for apiKey:', apiKey.slice(0, 8) + '...');
77
+
78
+ return {
79
+ /**
80
+ * Call once after the user logs in.
81
+ * Starts BLE advertising, proximity broadcast, and the payment listener.
82
+ */
83
+ async initializeSDK(user: FPUserInfo, callbacks?: FPCallbacks): Promise<void> {
84
+ console.log('[FountainPay] initializeSDK() called for user:', user.accountName);
85
+ try {
86
+ await FPEngine.initialize(apiKey, user, options ?? {}, callbacks ?? {});
87
+ console.log('[FountainPay] initializeSDK() complete. SDK is ready.');
88
+ } catch (err) {
89
+ console.error('[FountainPay] initializeSDK() FAILED:', err);
90
+ throw err;
91
+ }
92
+ },
93
+
94
+ /** Open the Send Money bottom sheet. */
95
+ send(amount: number, currency: FPCurrency): void {
96
+ console.log('[FountainPay] send() called:', amount, currency);
97
+ if (!FPEngine.isReady()) {
98
+ console.warn('[FountainPay] send() called before initializeSDK() — call initializeSDK first.');
99
+ }
100
+ FPEngine.showSend(amount, currency);
101
+ },
102
+
103
+ /** Open the Receive Money bottom sheet. */
104
+ receive(amount?: number, currency: FPCurrency = 'NGN'): void {
105
+ console.log('[FountainPay] receive() called:', amount, currency);
106
+ if (!FPEngine.isReady()) {
107
+ console.warn('[FountainPay] receive() called before initializeSDK().');
108
+ }
109
+ FPEngine.showReceive(amount, currency);
110
+ },
111
+
112
+ /** Generate a virtual account number (no UI shown). */
113
+ async generateAccountNumber(request: FPGenerateAccountRequest): Promise<FPVirtualAccount> {
114
+ console.log('[FountainPay] generateAccountNumber() called:', request.accountName);
115
+ return FPEngine.generateAccount(request);
116
+ },
117
+
118
+ /**
119
+ * Activate the incoming Bluetooth payment request listener.
120
+ * When a nearby device sends a payment request, the Accept/Decline
121
+ * modal will appear automatically.
122
+ */
123
+ listen(): void {
124
+ console.log('[FountainPay] listen() called — activating BT payment listener.');
125
+ if (!FPEngine.isReady()) {
126
+ console.warn('[FountainPay] listen() called before initializeSDK().');
127
+ }
128
+ FPEngine.startListening();
129
+ },
130
+
131
+ /** Stop all background services. Call on logout. */
132
+ async destroy(): Promise<void> {
133
+ console.log('[FountainPay] destroy() called — stopping all services.');
134
+ await FPEngine.destroy();
135
+ console.log('[FountainPay] All services stopped.');
136
+ },
137
+
138
+ get isReady(): boolean {
139
+ return FPEngine.isReady();
140
+ },
141
+
142
+ get currentUser(): FPUserInfo | null {
143
+ return FPEngine.getUser();
144
+ },
145
+ };
146
+ // Re-create instance only if the apiKey changes (which should never happen at runtime)
147
+ }, [apiKey]);
148
+
14
149
  return (
15
- <>
150
+ <FountainPayContext.Provider value={instance}>
16
151
  {children}
17
- {/* FPShell is invisible until pay.send() or pay.receive() is called */}
152
+ {/* FPShell is invisible until pay.send() or pay.receive() fires */}
18
153
  <FPShell />
19
- </>
154
+ </FountainPayContext.Provider>
20
155
  );
21
156
  }
@@ -1,95 +1,3 @@
1
- // ─────────────────────────────────────────────────────────────
2
- // useFountainPay — The ONLY hook the host app ever uses.
3
- //
4
- // Usage:
5
- // const pay = useFountainPay('your-api-key');
6
- // await pay.initializeSDK(userInfo, callbacks);
7
- // pay.send(500, 'NGN');
8
- // pay.receive(200, 'NGN');
9
- // const acct = await pay.generateAccountNumber({ accountName: 'John' });
10
- // pay.listen();
11
- // pay.destroy();
12
- // ─────────────────────────────────────────────────────────────
13
- import { useMemo } from 'react';
14
- import { FPEngine } from './engine/FPEngine';
15
- import { initClient } from './core/api/client';
16
- import type {
17
- FPInstance,
18
- FPUserInfo,
19
- FPSDKOptions,
20
- FPCallbacks,
21
- FPCurrency,
22
- FPGenerateAccountRequest,
23
- FPVirtualAccount,
24
- } from './core/types';
25
-
26
- export function useFountainPay(apiKey: string, options?: FPSDKOptions): FPInstance {
27
- // Initialize HTTP client immediately so API calls can be made
28
- // even before initializeSDK (e.g. generateAccountNumber for onboarding)
29
- useMemo(() => {
30
- initClient(apiKey, { baseUrl: options?.baseUrl, environment: options?.environment });
31
- }, [apiKey]);
32
-
33
- const instance = useMemo<FPInstance>(() => ({
34
- /**
35
- * Call this once after the user logs in.
36
- * Starts proximity broadcasting, BLE peripheral, and BT listener.
37
- */
38
- async initializeSDK(user: FPUserInfo, callbacks?: FPCallbacks): Promise<void> {
39
- await FPEngine.initialize(apiKey, user, options ?? {}, callbacks ?? {});
40
- },
41
-
42
- /**
43
- * Open the Send Money sheet.
44
- * @param amount Major denomination (e.g. 500 for NGN 500)
45
- * @param currency e.g. 'NGN', 'USD'
46
- */
47
- send(amount: number, currency: FPCurrency): void {
48
- FPEngine.showSend(amount, currency);
49
- },
50
-
51
- /**
52
- * Open the Receive Money sheet.
53
- * @param amount Expected amount (optional)
54
- * @param currency e.g. 'NGN'
55
- */
56
- receive(amount?: number, currency: FPCurrency = 'NGN'): void {
57
- FPEngine.showReceive(amount, currency);
58
- },
59
-
60
- /**
61
- * Generate a virtual account number.
62
- * No UI is shown — returns the account directly.
63
- */
64
- async generateAccountNumber(request: FPGenerateAccountRequest): Promise<FPVirtualAccount> {
65
- return FPEngine.generateAccount(request);
66
- },
67
-
68
- /**
69
- * Start listening for incoming Bluetooth payment requests.
70
- * When one arrives, the SDK auto-shows the Accept/Decline modal.
71
- * The result fires onPaymentReceived / onPaymentDeclined callbacks
72
- * that were passed into initializeSDK.
73
- */
74
- listen(): void {
75
- FPEngine.startListening();
76
- },
77
-
78
- /**
79
- * Stop all background services. Call on logout.
80
- */
81
- destroy(): void {
82
- FPEngine.destroy();
83
- },
84
-
85
- get isReady(): boolean {
86
- return FPEngine.isReady();
87
- },
88
-
89
- get currentUser(): FPUserInfo | null {
90
- return FPEngine.getUser();
91
- },
92
- }), [apiKey]);
93
-
94
- return instance;
95
- }
1
+ // useFountainPay re-exported from FountainPayProvider.
2
+ // The hook lives in FountainPayProvider.tsx now.
3
+ export { useFountainPay } from './FountainPayProvider';