Skip to content
Merged

Prod #173

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
21 changes: 21 additions & 0 deletions ios/SmallcaseGateway.m
Original file line number Diff line number Diff line change
Expand Up @@ -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]]) {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -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": [
Expand Down
2 changes: 1 addition & 1 deletion react-native-smallcase-gateway.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -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
13 changes: 9 additions & 4 deletions smart_investing_react_native/app/screens/SmtScreen.tsx
Original file line number Diff line number Diff line change
@@ -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<
Expand Down Expand Up @@ -70,6 +71,12 @@ const SmtScreen = () => {
backIconOpacity: bo,
};

const smallplugSub = SCGatewayEventManager.subscribeToSmallplugEvents(
event => {
console.log('[SmallPlug Event]:', event);
},
);

try {
const result = await launchSmallPlug(
targetEndpoint,
Expand All @@ -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'}
Expand Down
57 changes: 57 additions & 0 deletions src/SCGatewayEventEmitter.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
1 change: 1 addition & 0 deletions types/constants.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
10 changes: 10 additions & 0 deletions types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ export interface LoansEvent {
timestamp: number;
}

export interface SmallplugAnalyticsEvent {
eventName: string;
data: Record<string, any>;
timestamp: number;
}

export interface GatewayEventSubscription {
remove(): void;
}
Expand All @@ -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;
}

Expand Down Expand Up @@ -61,6 +69,7 @@ declare const _default: {
TRANSACTION_TYPE: {
connect: string;
sipSetup: string;
imrSetup: string;
fetchFunds: string;
transaction: string;
holdingsImport: string;
Expand All @@ -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;
};
Expand Down
Loading