diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d3f1309..1da47e81 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +### [7.3.5](https://github.com/smallcase/react-native-smallcase-gateway/compare/v7.3.4...v7.3.5) (2026-03-29) + + +### Features + +* add IMR_SETUP transaction type and bump SCGateway pod to 7.1.6 ([d411416](https://github.com/smallcase/react-native-smallcase-gateway/commit/d41141669da49d79988d43b9e476ed0eb07ae00c)) + ### [7.3.4](https://github.com/smallcase/react-native-smallcase-gateway/compare/v7.3.3...v7.3.4) (2026-03-23) ### [7.3.3](https://github.com/smallcase/react-native-smallcase-gateway/compare/v7.3.2...v7.3.3) (2026-03-23) diff --git a/android/build.gradle b/android/build.gradle index 8c6c2fdd..7f881a44 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -149,7 +149,7 @@ def kotlin_version = getExtOrDefault('kotlinVersion') dependencies { //noinspection GradleDynamicVersion implementation 'com.facebook.react:react-native:+' // From node_modules - implementation 'com.smallcase.gateway:sdk:6.0.5' + implementation 'com.smallcase.gateway:sdk:6.0.6' implementation 'com.smallcase.loans:sdk:5.1.1' implementation "androidx.core:core-ktx:1.3.1" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" diff --git a/ios/SmallcaseGateway.m b/ios/SmallcaseGateway.m index 69ee3937..7e3a75b3 100644 --- a/ios/SmallcaseGateway.m +++ b/ios/SmallcaseGateway.m @@ -290,6 +290,27 @@ @interface RCT_EXTERN_MODULE(SmallcaseGateway, NSObject) return; } + //MARK: intent - imr setup + if([response isKindOfClass: [ObjcTransactionIntentIMRSetup class]]) { + ObjcTransactionIntentIMRSetup *trxResponse = response; + [responseDict setValue:@"IMR_SETUP" forKey:@"transaction"]; + + NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; + [dict setValue: trxResponse.authToken forKey:@"smallcaseAuthToken"]; + [dict setValue: trxResponse.transactionId forKey:@"transactionId"]; + [dict setValue: trxResponse.imrAction forKey:@"imrAction"]; + [dict setValue: trxResponse.frequency forKey:@"frequency"]; + [dict setValue: trxResponse.iscid forKey:@"iscid"]; + [dict setValue: trxResponse.scheduledDate forKey:@"scheduledDate"]; + [dict setValue: trxResponse.triggerDate forKey:@"triggerDate"]; + [dict setValue: trxResponse.scid forKey:@"scid"]; + [dict setValue: trxResponse.signup forKey:@"signup"]; + [dict setValue: trxResponse.imrActive ? @"YES" : @"NO" forKey:@"imrActive"]; + + [responseDict setValue:dict forKey:@"data"]; + resolve(responseDict); + return; + } //MARK: intent - authorize holdings if([response isKindOfClass: [ObjcTransactionIntentAuthoriseHoldings class]]) { diff --git a/package.json b/package.json index 62ea534f..df264a5a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "react-native-smallcase-gateway", "title": "React Native Smallcase Gateway", - "version": "7.3.4", + "version": "7.3.5", "description": "smallcase gateway bindings for react native", "main": "src/index.js", "files": [ diff --git a/react-native-smallcase-gateway.podspec b/react-native-smallcase-gateway.podspec index 72143205..e76e092a 100644 --- a/react-native-smallcase-gateway.podspec +++ b/react-native-smallcase-gateway.podspec @@ -34,6 +34,6 @@ Pod::Spec.new do |s| s.dependency "ReactCommon/turbomodule/core" end - s.dependency 'SCGateway', '7.1.5' + s.dependency 'SCGateway', '7.1.7' s.dependency 'SCLoans', '7.1.1' end diff --git a/smart_investing_react_native/app/screens/SmtScreen.tsx b/smart_investing_react_native/app/screens/SmtScreen.tsx index dee1fe83..f2998d68 100644 --- a/smart_investing_react_native/app/screens/SmtScreen.tsx +++ b/smart_investing_react_native/app/screens/SmtScreen.tsx @@ -1,6 +1,7 @@ import React from 'react'; import {Button, TextInput, View} from 'react-native'; import {launchSmallPlug} from '../apis/Functions'; +import {SCGatewayEventManager} from 'react-native-smallcase-gateway'; const SmtScreen = () => { const [targetEndpoint, onChangeTargetEndpoint] = React.useState< @@ -70,6 +71,12 @@ const SmtScreen = () => { backIconOpacity: bo, }; + const smallplugSub = SCGatewayEventManager.subscribeToSmallplugEvents( + event => { + console.log('[SmallPlug Event]:', event); + }, + ); + try { const result = await launchSmallPlug( targetEndpoint, @@ -79,16 +86,14 @@ const SmtScreen = () => { console.log('✅ Smallplug Success:', result); if (result?.data?.userInfo) { console.log(' User Info:', result.data.userInfo); - // You can use the userInfo object here, for example, show an alert - // alert(`Success! User phone: ${result.data.userInfo.phoneNumber}`); } } catch (error: any) { console.error(' Smallplug Error:', error); if (error?.data?.userInfo) { console.log(' User Info from error:', error.data.userInfo); - // You can use the userInfo object here - // alert(`Failure! User phone: ${error.data.userInfo.phoneNumber}`); } + } finally { + SCGatewayEventManager.unsubscribeFromSmallplugEvents(smallplugSub); } }} title={'SmallPlug'} diff --git a/src/SCGatewayEventEmitter.js b/src/SCGatewayEventEmitter.js index 7bcfcf74..31effa08 100644 --- a/src/SCGatewayEventEmitter.js +++ b/src/SCGatewayEventEmitter.js @@ -18,6 +18,7 @@ export const SCGatewayEventTypes = { SUPER_PROPERTIES_UPDATED: 'scgateway_super_properties_updated', USER_RESET: 'scgateway_user_reset', USER_IDENTIFY: 'scgateway_user_identify', + SMALLPLUG_ANALYTICS_EVENT: 'smallplug_analytics_event', }; const SCGatewayNotificationEvent = 'scg_notification'; @@ -104,6 +105,62 @@ class SCGatewayEvents { return subscription; } + /** + * Subscribe to SmallPlug / DM analytics events streamed during a launchSmallplug session. + * Events have shape: { eventName: string, data: object, timestamp: number } + * @param {(event: {eventName: string, data: any, timestamp: number}) => void} callback + * @returns {GatewayEventSubscription} + */ + subscribeToSmallplugEvents(callback) { + if (!this.isInitialized) { + console.warn('[SCGatewayEvents] Event emitter not initialized'); + return null; + } + + if (typeof callback !== 'function') { + console.warn( + '[SCGatewayEvents] Invalid callback provided for SmallPlug subscription' + ); + return null; + } + + const subscription = this.eventEmitter.addListener( + SCGatewayNotificationEvent, + (jsonString) => { + if (!jsonString) return; + let parsed; + try { + parsed = JSON.parse(jsonString); + } catch (e) { + return; + } + if (parsed.type !== 'smallplug_analytics_event') return; + const { eventName, data } = parsed.data ?? {}; + callback({ + eventName, + data, + timestamp: parsed.timestamp ?? Date.now(), + }); + } + ); + + this.subscriptions.push(subscription); + return subscription; + } + + /** + * Unsubscribe from SmallPlug analytics events + * @param {GatewayEventSubscription} subscription - Subscription returned from subscribeToSmallplugEvents + */ + unsubscribeFromSmallplugEvents(subscription) { + if (subscription && typeof subscription.remove === 'function') { + subscription.remove(); + this.subscriptions = this.subscriptions.filter( + (sub) => sub !== subscription + ); + } + } + /** * Unsubscribe from Gateway Events * @param {GatewayEventSubscription} subscription - Subscription returned from subscribeToGatewayEvents diff --git a/src/constants.js b/src/constants.js index 4e7e1860..3aa284a6 100644 --- a/src/constants.js +++ b/src/constants.js @@ -7,6 +7,7 @@ export const ENV = { export const TRANSACTION_TYPE = { connect: 'CONNECT', sipSetup: 'SIP_SETUP', + imrSetup: 'IMR_SETUP', fetchFunds: 'FETCH_FUNDS', transaction: 'TRANSACTION', holdingsImport: 'HOLDINGS_IMPORT', diff --git a/types/constants.d.ts b/types/constants.d.ts index 32111aff..6d4147b5 100644 --- a/types/constants.d.ts +++ b/types/constants.d.ts @@ -6,6 +6,7 @@ export namespace ENV { export namespace TRANSACTION_TYPE { const connect: string; const sipSetup: string; + const imrSetup: string; const fetchFunds: string; const transaction: string; const holdingsImport: string; diff --git a/types/index.d.ts b/types/index.d.ts index 66417fb5..548d96b1 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -12,6 +12,12 @@ export interface LoansEvent { timestamp: number; } +export interface SmallplugAnalyticsEvent { + eventName: string; + data: Record; + timestamp: number; +} + export interface GatewayEventSubscription { remove(): void; } @@ -22,6 +28,8 @@ export interface LoansEventSubscription { interface SCGatewayEventManagerInterface { subscribeToGatewayEvents(callback: ((event: GatewayEvent) => void)): GatewayEventSubscription | null; + subscribeToSmallplugEvents(callback: ((event: SmallplugAnalyticsEvent) => void)): GatewayEventSubscription | null; + unsubscribeFromSmallplugEvents(subscription: GatewayEventSubscription): void; unsubscribeFromGatewayEvents(subscription: GatewayEventSubscription): void; } @@ -61,6 +69,7 @@ declare const _default: { TRANSACTION_TYPE: { connect: string; sipSetup: string; + imrSetup: string; fetchFunds: string; transaction: string; holdingsImport: string; @@ -86,6 +95,7 @@ declare const _default: { SCLoansEventManager: SCLoansEventManagerInterface; subscribeToGatewayEvents: (callback: (event: GatewayEvent) => void) => GatewayEventSubscription | null; unsubscribeFromGatewayEvents: (subscription: GatewayEventSubscription) => void; + subscribeToSmallplugEvents: (callback: (event: SmallplugAnalyticsEvent) => void) => GatewayEventSubscription | null; subscribeToLoansEvent: (callback: (event: LoansEvent) => void) => LoansEventSubscription | null; unsubscribeFromLoansEvent: (subscription: LoansEventSubscription) => void; };