From 1966f9b8840d740a30db60855aca0d546e58d462 Mon Sep 17 00:00:00 2001 From: deepaksmallcase Date: Mon, 28 Sep 2026 23:53:14 +0530 Subject: [PATCH 1/3] feat: add native SDK debug mode switch Move the native Gateway and Loans SDK pins into native-sdk.json with release and debug entries. Host apps opt into debug builds of the native SDKs with SmallcaseGateway_sdkMode=debug (Android) or SMALLCASE_SDK_MODE=debug pod install (iOS); release stays the default. Co-Authored-By: Claude Opus 5.5 --- README.md | 11 ++++++ android/build.gradle | 20 ++++++++-- native-sdk.json | 22 +++++++++++ package.json | 1 + react-native-smallcase-gateway.podspec | 20 +++++++--- src/__tests__/nativeSdkConfig.test.js | 54 ++++++++++++++++++++++++++ 6 files changed, 118 insertions(+), 10 deletions(-) create mode 100644 native-sdk.json create mode 100644 src/__tests__/nativeSdkConfig.test.js diff --git a/README.md b/README.md index df11f8f0..cc696fc4 100644 --- a/README.md +++ b/README.md @@ -129,6 +129,17 @@ This is opt-in and fully backward compatible — existing calls to `triggerTrans **Using incognito for a different (e.g. linked/family) account:** `incognito: true` on its own does not switch which smallcase account the SDK is acting as — it only changes how that call's browser session behaves. To connect or transact on behalf of a different smallcase account than the one currently authenticated, call `SmallcaseGateway.init(sdkToken)` again with that account's own token before calling `triggerTransaction` — the same way you would for any account switch, incognito or not. +## 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 553b3db9..4e34b7ee 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -146,13 +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 - // INTERNAL TEST PIN: feat/incognito-mode branch build. - // Revert to: implementation 'com.smallcase.gateway:sdk:6.1.1' - implementation 'com.smallcase.gateway:sdk-feat-incognito-mode-c1b21c9:6.1.2-3193-release' - 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/native-sdk.json b/native-sdk.json new file mode 100644 index 00000000..8ed8c2bb --- /dev/null +++ b/native-sdk.json @@ -0,0 +1,22 @@ +{ + "release": { + "android": { + "gateway": "com.smallcase.gateway:sdk-feat-incognito-mode-c1b21c9:6.1.2-3193-release", + "loans": "com.smallcase.loans:sdk-sourav-native-dark-theme-cb54bf9:5.1.4-92-release" + }, + "ios": { + "gateway": { "name": "SCGateway-feat-incognito-mode-2d15c7b", "version": "7.2.0-28-release" }, + "loans": { "name": "SCLoans-sourav-native-dark-theme-37c97d9", "version": "7.1.2-45-release" } + } + }, + "debug": { + "android": { + "gateway": null, + "loans": null + }, + "ios": { + "gateway": null, + "loans": null + } + } +} diff --git a/package.json b/package.json index 26045bb4..b694305e 100644 --- a/package.json +++ b/package.json @@ -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 2e0a2543..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,10 +46,6 @@ Pod::Spec.new do |s| s.dependency "ReactCommon/turbomodule/core" end - # INTERNAL TEST PIN: feat/incognito-mode branch build. - # Revert to: s.dependency 'SCGateway', '7.2.0' - s.dependency 'SCGateway-feat-incognito-mode-2d15c7b', '7.2.0-28-release' - # 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/src/__tests__/nativeSdkConfig.test.js b/src/__tests__/nativeSdkConfig.test.js new file mode 100644 index 00000000..98048ab2 --- /dev/null +++ b/src/__tests__/nativeSdkConfig.test.js @@ -0,0 +1,54 @@ +const nativeSdks = require('../../native-sdk.json'); +const packageJson = require('../../package.json'); + +const SDKS = ['gateway', 'loans']; +const MAVEN_COORDINATE = /^[\w.-]+:[\w.-]+:[\w.-]+$/; + +const isValidAndroidPin = (pin) => + typeof pin === 'string' && MAVEN_COORDINATE.test(pin); + +const isValidIosPin = (pin) => + pin !== null && + typeof pin === 'object' && + typeof pin.name === 'string' && + pin.name.length > 0 && + typeof pin.version === 'string' && + pin.version.length > 0; + +describe('native-sdk.json', () => { + test('is shipped in the npm package', () => { + expect(packageJson.files).toContain('native-sdk.json'); + }); + + test('defines release and debug modes', () => { + expect(Object.keys(nativeSdks).sort()).toEqual(['debug', 'release']); + }); + + test.each(Object.keys(nativeSdks))( + '%s mode lists every SDK for both platforms', + (mode) => { + expect(Object.keys(nativeSdks[mode].android).sort()).toEqual(SDKS); + expect(Object.keys(nativeSdks[mode].ios).sort()).toEqual(SDKS); + } + ); + + test('release mode pins every SDK', () => { + SDKS.forEach((sdk) => { + expect(isValidAndroidPin(nativeSdks.release.android[sdk])).toBe(true); + expect(isValidIosPin(nativeSdks.release.ios[sdk])).toBe(true); + }); + }); + + test('debug mode pins are well formed when set', () => { + SDKS.forEach((sdk) => { + const androidPin = nativeSdks.debug.android[sdk]; + const iosPin = nativeSdks.debug.ios[sdk]; + if (androidPin !== null) { + expect(isValidAndroidPin(androidPin)).toBe(true); + } + if (iosPin !== null) { + expect(isValidIosPin(iosPin)).toBe(true); + } + }); + }); +}); From 69e2dff65cf0bf630149f69575deefeed1be44b6 Mon Sep 17 00:00:00 2001 From: deepaksmallcase Date: Wed, 30 Sep 2026 14:59:37 +0530 Subject: [PATCH 2/3] test: remove native-sdk.json config shape test Co-Authored-By: Claude Opus 5.5 --- src/__tests__/nativeSdkConfig.test.js | 54 --------------------------- 1 file changed, 54 deletions(-) delete mode 100644 src/__tests__/nativeSdkConfig.test.js diff --git a/src/__tests__/nativeSdkConfig.test.js b/src/__tests__/nativeSdkConfig.test.js deleted file mode 100644 index 98048ab2..00000000 --- a/src/__tests__/nativeSdkConfig.test.js +++ /dev/null @@ -1,54 +0,0 @@ -const nativeSdks = require('../../native-sdk.json'); -const packageJson = require('../../package.json'); - -const SDKS = ['gateway', 'loans']; -const MAVEN_COORDINATE = /^[\w.-]+:[\w.-]+:[\w.-]+$/; - -const isValidAndroidPin = (pin) => - typeof pin === 'string' && MAVEN_COORDINATE.test(pin); - -const isValidIosPin = (pin) => - pin !== null && - typeof pin === 'object' && - typeof pin.name === 'string' && - pin.name.length > 0 && - typeof pin.version === 'string' && - pin.version.length > 0; - -describe('native-sdk.json', () => { - test('is shipped in the npm package', () => { - expect(packageJson.files).toContain('native-sdk.json'); - }); - - test('defines release and debug modes', () => { - expect(Object.keys(nativeSdks).sort()).toEqual(['debug', 'release']); - }); - - test.each(Object.keys(nativeSdks))( - '%s mode lists every SDK for both platforms', - (mode) => { - expect(Object.keys(nativeSdks[mode].android).sort()).toEqual(SDKS); - expect(Object.keys(nativeSdks[mode].ios).sort()).toEqual(SDKS); - } - ); - - test('release mode pins every SDK', () => { - SDKS.forEach((sdk) => { - expect(isValidAndroidPin(nativeSdks.release.android[sdk])).toBe(true); - expect(isValidIosPin(nativeSdks.release.ios[sdk])).toBe(true); - }); - }); - - test('debug mode pins are well formed when set', () => { - SDKS.forEach((sdk) => { - const androidPin = nativeSdks.debug.android[sdk]; - const iosPin = nativeSdks.debug.ios[sdk]; - if (androidPin !== null) { - expect(isValidAndroidPin(androidPin)).toBe(true); - } - if (iosPin !== null) { - expect(isValidIosPin(iosPin)).toBe(true); - } - }); - }); -}); From 7a427b377032203e87186daf3fafc517a5247499 Mon Sep 17 00:00:00 2001 From: deepaksmallcase Date: Wed, 30 Sep 2026 15:08:36 +0530 Subject: [PATCH 3/3] style: format native-sdk.json with prettier Co-Authored-By: Claude Opus 5.5 --- native-sdk.json | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/native-sdk.json b/native-sdk.json index 8ed8c2bb..3a509ebb 100644 --- a/native-sdk.json +++ b/native-sdk.json @@ -5,8 +5,14 @@ "loans": "com.smallcase.loans:sdk-sourav-native-dark-theme-cb54bf9:5.1.4-92-release" }, "ios": { - "gateway": { "name": "SCGateway-feat-incognito-mode-2d15c7b", "version": "7.2.0-28-release" }, - "loans": { "name": "SCLoans-sourav-native-dark-theme-37c97d9", "version": "7.1.2-45-release" } + "gateway": { + "name": "SCGateway-feat-incognito-mode-2d15c7b", + "version": "7.2.0-28-release" + }, + "loans": { + "name": "SCLoans-sourav-native-dark-theme-37c97d9", + "version": "7.1.2-45-release" + } } }, "debug": {