diff --git a/CHANGELOG.md b/CHANGELOG.md
index fc2644d3..41170cb2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,58 @@
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.7.2](https://github.com/smallcase/react-native-smallcase-gateway/compare/v7.7.1...v7.7.2) (2026-09-23)
+
+### Improvements
+
+* update Android Gateway SDK to 6.1.4 and Loans SDK to 5.4.0
+* update iOS Gateway SDK to 7.2.2 and Loans SDK to 7.5.0
+
+### [7.7.1](https://github.com/smallcase/react-native-smallcase-gateway/compare/v7.7.0...v7.7.1) (2026-09-20)
+
+
+### Features
+
+* expose webview-as-a-service ([648f235](https://github.com/smallcase/react-native-smallcase-gateway/commit/648f2359715094ce88f680e3ba18fc2c7cfbae4c))
+
+## [7.7.0](https://github.com/smallcase/react-native-smallcase-gateway/compare/v7.6.2...v7.7.0) (2026-08-27)
+
+
+### Features
+
+* add Loans KYC permission usage descriptions ([e384009](https://github.com/smallcase/react-native-smallcase-gateway/commit/e384009584353f89528e07bbf7ee28ce7e2eba2d))
+
+### [7.6.2](https://github.com/smallcase/react-native-smallcase-gateway/compare/v7.6.1...v7.6.2) (2026-09-02)
+
+### [7.6.1](https://github.com/smallcase/react-native-smallcase-gateway/compare/v7.6.0...v7.6.1) (2026-08-17)
+
+### Improvements
+
+* **android:** update Loans SDK to 5.3.1
+
+## [7.6.0](https://github.com/smallcase/react-native-smallcase-gateway/compare/v7.5.0...v7.6.0) (2026-07-31)
+
+
+### Improvements
+
+* **android:** update Loans SDK to 5.3.0
+
+### Bug Fixes
+
+* **android:** keep SCGateway classes for R8 ([e99d428](https://github.com/smallcase/react-native-smallcase-gateway/commit/e99d4284368827051a46a68f12e2dba75852ac3e))
+
+## [7.5.0](https://npmjs.com/package/react-native-smallcase-gateway/v/7.5.0?activeTab=versions) (2026-07-10)
+
+Dev Improvements
+
+* Bumped Loans native SDK to the dark-theme internal release (Android 5.1.4-92, iOS 7.1.2-44) and dropped a stale ProGuard workaround while keeping R8 full mode on.
+
+Features
+
+* Added a `colorScheme` (`dark` / `light` / `system`) option to `ScLoanInfo`, letting partner apps control the LAS web UI theme instead of always defaulting to light.
+
+### [7.4.4](https://github.com/smallcase/react-native-smallcase-gateway/compare/v7.4.3...v7.4.4) (2026-06-11)
+
### [7.4.3](https://github.com/smallcase/react-native-smallcase-gateway/compare/v7.4.0...v7.4.3) (2026-06-09)
### [7.4.2](https://github.com/smallcase/react-native-smallcase-gateway/compare/v7.4.0...v7.4.2) (2026-05-25)
diff --git a/README.md b/README.md
index 80a9d484..72c2b6bb 100644
--- a/README.md
+++ b/README.md
@@ -28,6 +28,17 @@ platform :ios, '11.0'
then run
`cd ios; pod update`
+Apps using Loans KYC must also add these usage descriptions to the iOS app's `Info.plist`:
+
+```xml
+NSCameraUsageDescription
+Camera access is required to capture your selfie during KYC.
+NSMicrophoneUsageDescription
+Microphone access is required for audio during video KYC.
+NSLocationWhenInUseUsageDescription
+Location access is required to verify your location during KYC.
+```
+
## android setup
Add these lines to your project level `build.gradle`
@@ -37,12 +48,8 @@ allprojects {
repositories {
// .. you other repositories
maven {
- url "http://artifactory.smallcase.com/artifactory/gradle-dev-local"
- credentials {
- username "react_native_user"
- password "reactNativeUser123"
- }
- }
+ url "https://artifactory.smallcase.com/artifactory/SCGateway"
+ }
}
}
```
@@ -100,8 +107,22 @@ const res = await SmallcaseGateway.triggerTransaction(transactionId);
// start lead generation flow
SmallcaseGateway.triggerLeadGen({ email: "test@gmail.com" });
+
+// launch a standalone WebView; setup/init are not required
+await SmallcaseGateway.launchScWebView("https://www.smallcase.com");
```
+## Native SDK debug mode
+
+The native Gateway and Loans SDK versions this package depends on are pinned in `native-sdk.json`, once for `release` (default) and once for `debug`. Debug builds of the native SDKs enable WebView inspection and debug logging, and are published to smallcase's internal registries only.
+
+To consume the debug builds:
+
+- Android: add `SmallcaseGateway_sdkMode=debug` to the host app's `android/gradle.properties`, then sync. Artifactory access to `SCGateway-internal` is required.
+- iOS: add `source 'git@github.com:smallcase/cocoapodspec-internal.git'` and `source 'https://cdn.cocoapods.org/'` to the host app's `Podfile`, then run `SMALLCASE_SDK_MODE=debug pod install`. Run a plain `pod install` to switch back.
+
+The build fails with an explicit error if debug mode is selected but `native-sdk.json` has no debug pin for an SDK.
+
## Debug / Contribution
Make sure you have react native dev environment set up
diff --git a/android/build.gradle b/android/build.gradle
index 68bb5f72..4e34b7ee 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -146,11 +146,25 @@ repositories {
def kotlin_version = getExtOrDefault('kotlinVersion')
+// Native SDK pins live in native-sdk.json. Set SmallcaseGateway_sdkMode=debug in the
+// host app's gradle.properties to consume debug builds of the native SDKs.
+def sdkMode = getExtOrDefault('sdkMode') ?: 'release'
+def nativeSdks = new groovy.json.JsonSlurper().parse(file("$projectDir/../native-sdk.json"))
+if (!nativeSdks.containsKey(sdkMode)) {
+ throw new GradleException("${project.name}: unknown SmallcaseGateway_sdkMode '${sdkMode}', expected one of ${nativeSdks.keySet()}")
+}
+def androidSdks = nativeSdks[sdkMode].android
+androidSdks.each { sdk, coordinate ->
+ if (!coordinate) {
+ throw new GradleException("${project.name}: no ${sdk} SDK pinned for mode '${sdkMode}' in native-sdk.json")
+ }
+}
+
dependencies {
//noinspection GradleDynamicVersion
implementation 'com.facebook.react:react-native:+' // From node_modules
- implementation 'com.smallcase.gateway:sdk:6.1.1'
- implementation 'com.smallcase.loans:sdk-sourav-native-dark-theme-cb54bf9:5.1.4-92-release'
+ implementation androidSdks.gateway
+ implementation androidSdks.loans
implementation "androidx.core:core-ktx:1.3.1"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}
diff --git a/android/src/main/java/com/reactnativesmallcasegateway/SmallcaseGatewayModule.kt b/android/src/main/java/com/reactnativesmallcasegateway/SmallcaseGatewayModule.kt
index c36f9a6e..d9629576 100644
--- a/android/src/main/java/com/reactnativesmallcasegateway/SmallcaseGatewayModule.kt
+++ b/android/src/main/java/com/reactnativesmallcasegateway/SmallcaseGatewayModule.kt
@@ -1,5 +1,6 @@
package com.reactnativesmallcasegateway
+import android.net.Uri
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import com.facebook.react.bridge.*
@@ -163,6 +164,28 @@ class SmallcaseGatewayModule(reactContext: ReactApplicationContext) : ReactConte
}
}
+ @ReactMethod
+ fun launchScWebView(url: String, promise: Promise) {
+ val activity = reactApplicationContext.currentActivity ?: run {
+ promise.reject("no_activity", "No active Android activity")
+ return
+ }
+ val uri = Uri.parse(url)
+ if (uri.scheme?.lowercase() !in setOf("http", "https") || uri.host.isNullOrBlank()) {
+ promise.reject("invalid_url", "A valid absolute HTTP(S) URL is required")
+ return
+ }
+
+ activity.runOnUiThread {
+ try {
+ SmallcaseGatewaySdk.launchScWebView(activity, url)
+ promise.resolve(true)
+ } catch (error: Exception) {
+ promise.reject("launch_failed", error)
+ }
+ }
+ }
+
@ReactMethod
fun launchSmallplug(targetEndpoint: String, params: String, promise: Promise) {
@@ -562,4 +585,3 @@ class SmallcaseGatewayModule(reactContext: ReactApplicationContext) : ReactConte
}
}
-
diff --git a/ios/SmallcaseGateway.m b/ios/SmallcaseGateway.m
index fa04027c..46c60e4e 100644
--- a/ios/SmallcaseGateway.m
+++ b/ios/SmallcaseGateway.m
@@ -360,6 +360,27 @@ @interface RCT_EXTERN_MODULE(SmallcaseGateway, NSObject)
}
//MARK: smallplug
+RCT_REMAP_METHOD(launchScWebView,
+ urlString:(NSString *)urlString
+ launchScWebViewWithResolver:(RCTPromiseResolveBlock)resolve
+ rejecter:(RCTPromiseRejectBlock)reject) {
+ NSURL *url = [NSURL URLWithString:urlString];
+ NSString *scheme = url.scheme.lowercaseString;
+ if (url == nil || url.host.length == 0 ||
+ !([scheme isEqualToString:@"http"] || [scheme isEqualToString:@"https"])) {
+ reject(@"invalid_url", @"A valid absolute HTTP(S) URL is required", nil);
+ return;
+ }
+
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [SCGateway.shared
+ launchScWebViewWithPresentingController:[[[UIApplication sharedApplication] keyWindow] rootViewController]
+ url:url
+ completion:^(__unused id response, __unused NSError *error) {}];
+ resolve(@(YES));
+ });
+}
+
RCT_REMAP_METHOD(launchSmallplug,
targetEndpoint:(NSString *)targetEndpoint
params:(NSString *)params
@@ -809,4 +830,3 @@ - (NSError *)scLoanErrorToDict:(ScLoanError *)error {
}
@end
-
diff --git a/native-sdk.json b/native-sdk.json
new file mode 100644
index 00000000..03f441c9
--- /dev/null
+++ b/native-sdk.json
@@ -0,0 +1,22 @@
+{
+ "release": {
+ "android": {
+ "gateway": "com.smallcase.gateway:sdk:6.1.4",
+ "loans": "com.smallcase.loans:sdk:5.4.0"
+ },
+ "ios": {
+ "gateway": { "name": "SCGateway", "version": "7.2.2" },
+ "loans": { "name": "SCLoans", "version": "7.5.0" }
+ }
+ },
+ "debug": {
+ "android": {
+ "gateway": null,
+ "loans": null
+ },
+ "ios": {
+ "gateway": null,
+ "loans": null
+ }
+ }
+}
diff --git a/package.json b/package.json
index 26045bb4..069a09ff 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "react-native-smallcase-gateway",
"title": "React Native Smallcase Gateway",
- "version": "7.4.3",
+ "version": "7.7.2",
"description": "smallcase gateway bindings for react native",
"main": "src/index.js",
"files": [
@@ -12,6 +12,7 @@
"cpp",
"types",
"react-native-smallcase-gateway.podspec",
+ "native-sdk.json",
"!lib/typescript/example",
"!lib/typescript/smart_investing_react_native",
"!android/build",
diff --git a/react-native-smallcase-gateway.podspec b/react-native-smallcase-gateway.podspec
index 686d423d..1a61ec5c 100644
--- a/react-native-smallcase-gateway.podspec
+++ b/react-native-smallcase-gateway.podspec
@@ -1,6 +1,18 @@
require "json"
package = JSON.parse(File.read(File.join(__dir__, "package.json")))
+
+# Native SDK pins live in native-sdk.json. Run `SMALLCASE_SDK_MODE=debug pod install`
+# in the host app to consume debug builds of the native SDKs.
+native_sdks = JSON.parse(File.read(File.join(__dir__, "native-sdk.json")))
+sdk_mode = ENV.fetch("SMALLCASE_SDK_MODE", "release")
+unless native_sdks.key?(sdk_mode)
+ raise "react-native-smallcase-gateway: unknown SMALLCASE_SDK_MODE '#{sdk_mode}', expected one of #{native_sdks.keys}"
+end
+ios_sdks = native_sdks[sdk_mode]["ios"]
+ios_sdks.each do |sdk, pod|
+ raise "react-native-smallcase-gateway: no #{sdk} SDK pinned for mode '#{sdk_mode}' in native-sdk.json" if pod.nil?
+end
folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32'
Pod::Spec.new do |s|
@@ -34,8 +46,6 @@ Pod::Spec.new do |s|
s.dependency "ReactCommon/turbomodule/core"
end
- s.dependency 'SCGateway', '7.2.0'
- # INTERNAL TEST PIN: dark-theme branch build (mirrors the android/build.gradle pin).
- # Revert to: s.dependency 'SCLoans', '7.2.0'
- s.dependency 'SCLoans-sourav-native-dark-theme-37c97d9', '7.1.2-45-release'
+ s.dependency ios_sdks["gateway"]["name"], ios_sdks["gateway"]["version"]
+ s.dependency ios_sdks["loans"]["name"], ios_sdks["loans"]["version"]
end
diff --git a/smart_investing_react_native/android/app/proguard-rules.pro b/smart_investing_react_native/android/app/proguard-rules.pro
index 5dccbcd3..5924e582 100644
--- a/smart_investing_react_native/android/app/proguard-rules.pro
+++ b/smart_investing_react_native/android/app/proguard-rules.pro
@@ -12,6 +12,8 @@
# SCGateway proguard rules — keeping it here, same as loans.
-keep class com.smallcase.gateway.** { *; }
+-keep class com.example.** { *; }
+
# Retrofit + R8 full mode (AGP 8 default): generic signatures are stripped for
# any type that is not kept, so ConfigService.getBrokerConfigs(): Call
# degrades to a raw Call and Retrofit rejects it
diff --git a/smart_investing_react_native/android/gradle.properties b/smart_investing_react_native/android/gradle.properties
index 9767fbf1..6657b545 100644
--- a/smart_investing_react_native/android/gradle.properties
+++ b/smart_investing_react_native/android/gradle.properties
@@ -42,6 +42,3 @@ hermesEnabled=true
artifactory_contextUrl=https\://artifactory.smallcase.com/artifactory
artifactory_password=reactNativeUser123
artifactory_user=react_native_user
-
-# R8 full mode enabled — verified safe against loans SDK consumer-rules.pro
-android.enableR8.fullMode=true
\ No newline at end of file
diff --git a/smart_investing_react_native/app/screens/SmtScreen.tsx b/smart_investing_react_native/app/screens/SmtScreen.tsx
index f2998d68..87d17507 100644
--- a/smart_investing_react_native/app/screens/SmtScreen.tsx
+++ b/smart_investing_react_native/app/screens/SmtScreen.tsx
@@ -1,9 +1,14 @@
import React from 'react';
-import {Button, TextInput, View} from 'react-native';
+import {Button, ScrollView, TextInput} from 'react-native';
import {launchSmallPlug} from '../apis/Functions';
-import {SCGatewayEventManager} from 'react-native-smallcase-gateway';
+import SmallcaseGateway, {
+ SCGatewayEventManager,
+} from 'react-native-smallcase-gateway';
const SmtScreen = () => {
+ const [webViewUrl, onChangeWebViewUrl] = React.useState(
+ 'https://www.smallcase.com',
+ );
const [targetEndpoint, onChangeTargetEndpoint] = React.useState<
string | null
>(null);
@@ -21,7 +26,7 @@ const SmtScreen = () => {
string | null
>(null);
return (
-
+
{
@@ -99,7 +104,24 @@ const SmtScreen = () => {
title={'SmallPlug'}
accessibilityLabel="Learn more about this purple button"
/>
-
+
+