
Research
Supply Chain Attack on Axios Pulls Malicious Dependency from npm
A supply chain attack on Axios introduced a malicious dependency, plain-crypto-js@4.2.1, published minutes earlier and absent from the project’s GitHub releases.
@tonclient/lib-react-native-jsi
Advanced tools
JSI-based implementation of a bridge to mobile React Native platform including static libraries for iOS and Android.
yarn add @tonclient/lib-react-native-jsi
Requirements: Xcode 12.5
cd ios && pod install && cd ..
On iOS, the library is installed automatically. However, currently it is not possible to autoinstall more than one JSI library. In order to use lib-react-native-jsi and react-native-reanimated simultaneously, you need to enable DONT_AUTOINSTALL_* flags in Podfile and register JSI bindings in jsExecutorFactoryForBridge method:
Podfile
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['OTHER_CPLUSPLUSFLAGS'] = '-DDONT_AUTOINSTALL_REANIMATED -DDONT_AUTOINSTALL_TONCLIENTJSI'
end
end
end
Note: Don't forget to run
pod installafter doing that.
Then, rename AppDelegate.m to AppDelegate.mm in order to compile this file as Objective-C++.
Note: It's important to do it with Xcode, so that the project references are updated accordingly.
AppDelegate.mm
#import "AppDelegate.h"
...
+#import <React/RCTCxxBridgeDelegate.h>
+#import <RNReanimated/REAInitializer.h>
+#import <lib-react-native-jsi/TONJSIExecutorInitializer.h>
+#if __has_include(<reacthermes/HermesExecutorFactory.h>)
+#import <reacthermes/HermesExecutorFactory.h>
+typedef HermesExecutorFactory ExecutorFactory;
+#elif __has_include(<React/HermesExecutorFactory.h>)
+#import <React/HermesExecutorFactory.h>
+typedef HermesExecutorFactory ExecutorFactory;
+#else
+#import <React/JSCExecutorFactory.h>
+typedef JSCExecutorFactory ExecutorFactory;
+#endif
+#if __has_include(<React/RCTJSIExecutorRuntimeInstaller.h>)
+#import <React/RCTJSIExecutorRuntimeInstaller.h>
+#endif
...
+@interface AppDelegate() <RCTCxxBridgeDelegate>
+
+@end
@implementation AppDelegate
...
+- (std::unique_ptr<facebook::react::JSExecutorFactory>)jsExecutorFactoryForBridge:(RCTBridge *)bridge
+{
+ const auto installer = tonlabs::TONJSIExecutorRuntimeInstaller(bridge, reanimated::REAJSIExecutorRuntimeInstaller(bridge, NULL));
+
+#if __has_include(<React/RCTJSIExecutorRuntimeInstaller.h>)
+ // installs globals such as console, nativePerformanceNow, etc.
+ return std::make_unique<ExecutorFactory>(RCTJSIExecutorRuntimeInstaller(installer));
+#else
+ return std::make_unique<ExecutorFactory>(installer);
+#endif
+}
@end
Note: Make sure that your project uses C++14 or higher. You can change C++ Language Dialect in the Build Settings of your project.
Requirements: Android NDK 21.3.6528147
android/build.gradle
buildscript {
// ...
dependencies {
- classpath('com.android.tools.build:gradle:3.5.3')
+ classpath('com.android.tools.build:gradle:4.1.0')
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
android/app/build.gradle
android {
applicationVariants.all { variant ->
// ...
}
+ configurations {
+ all*.exclude module: 'fbjni-java-only'
+ }
+
+ packagingOptions {
+ pickFirst 'lib/*/libfbjni.so'
+ pickFirst 'lib/*/libc++_shared.so'
+ }
}
android/gradle.properties
# Version of flipper SDK to use with React Native
-FLIPPER_VERSION=0.75.1
+FLIPPER_VERSION=0.93.0
android/app/src/main/java/.../MainApplication.java
+import com.facebook.react.bridge.JSIModulePackage;
+import com.tonlabs.tonclientjsi.TonClientJSIModulePackage;
public class MainApplication extends Application implements ReactApplication {
private final ReactNativeHost mReactNativeHost =
new ReactNativeHost(this) {
...
@Override
protected String getJSMainModuleName() {
return "index";
}
+ @Override
+ protected JSIModulePackage getJSIModulePackage() {
+ return new TonClientJSIModulePackage();
+ }
};
If you wish to use lib-react-native-jsi and react-native-reanimated simultaneously, you need to initialize all JSI libraries in getJSIModules method of a custom JSIModulePackage instance:
+import com.facebook.react.bridge.JavaScriptContextHolder;
+import com.facebook.react.bridge.JSIModuleSpec;
+import com.facebook.react.bridge.JSIModulePackage;
+import com.facebook.react.bridge.ReactApplicationContext;
+import com.swmansion.reanimated.ReanimatedJSIModulePackage;
+import com.tonlabs.tonclientjsi.TonClientJSIModulePackage;
+import java.util.Arrays;
public class MainApplication extends Application implements ReactApplication {
private final ReactNativeHost mReactNativeHost =
new ReactNativeHost(this) {
...
@Override
protected String getJSMainModuleName() {
return "index";
}
+ @Override
+ protected JSIModulePackage getJSIModulePackage() {
+ return new JSIModulePackage() {
+ @Override
+ public List<JSIModuleSpec> getJSIModules(final ReactApplicationContext reactApplicationContext, final JavaScriptContextHolder jsContext) {
+ new ReanimatedJSIModulePackage().getJSIModules(reactApplicationContext, jsContext);
+ new TonClientJSIModulePackage().getJSIModules(reactApplicationContext, jsContext);
+ return Arrays.<JSIModuleSpec>asList();
+ }
+ };
+ }
};
android/app/src/main/AndroidManifest.xml
<manifest>
<application>
+ <provider
+ android:name="com.facebook.react.modules.blob.BlobProvider"
+ android:authorities="@string/blob_provider_authority"
+ android:exported="false"
+ />
</application>
</manifest>
android/app/src/main/res/values/strings.xml
<resources>
...
+ <string name="blob_provider_authority">your.app.package.blobs</string>
</resources>
index.tsx
import { TonClient } from '@tonclient/core';
import { libReactNativeJsi } from 'lib-react-native-jsi';
// Application initialization
TonClient.useBinaryLibrary(libReactNativeJsi);
const client = new TonClient();
const keys = await client.crypto.generate_random_sign_keys();
setResponseParamsHandler(
handler: (
requestId: number,
params: any,
responseType: number,
finished: boolean
) => void
): void
Sets the response handler for sendRequestParams.
createContext(configJson: string): Promise<string>
Calls tc_create_context from TON SDK.
destroyContext(context: number): void
Calls tc_destroy_context from TON SDK.
sendRequestParams(
context: number,
requestId: number,
functionName: string,
functionParams: any
): void
Calls tc_request_ptr from TON SDK.
In React Native app, you can load any resource as JS Blob (binary large object) using fetch function and blob method:
const url = '...'; // path to a local file or a remote resource
const response = await fetch(url);
const blob = await response.blob();
Then you can create an object URL for the provided blob:
const objectURL = URL.createObjectURL(blob);
Note: On Android, it is necessary to register
BlobProvideras a ContentProvider in order to create object URLs for blobs (see details). On iOS, there is no additional configuration required.
Finally, you can pass the object URL directly as source prop of React Native <Image /> component:
<Image source={{ uri: objectURL }} />
Note: There is a problem with accessing blobs greater than 64 KB on Android (see this issue) on React Native 0.64.2 and earlier. Please use React Native 0.65.0+ or alternatively build older version of React Native from sources with the fix from this pull request.
It is also possible to pass blob object URL directly as source prop of <Pdf /> component from react-native-pdf:
<Pdf source={{ uri: objectURL }} />
Note: The above requires this pull request which has not been merged yet.
Note: It is advisable to keep the reference to the Blob object as long as its object URL is used with other components. Otherwise, the JavaScript garbage collector may collect the JS Blob object and consequently deallocate the memory associated with this blob (both on Android and iOS). This will lead to a crash due to bad memory access when the component tries to access blob data again, for example during UI interaction or re-render.
After you're done with the object URL, don't forget to revoke it:
URL.revokeObjectURL(objectURL);
Note: Currently, the React Native implementation does nothing, but this function is still a part of URL API.
This library provides two ways of transferring large binary payloads between React Native and TON SDK:
You can pass each request param individually either as a string or a blob to lib.sendRequestParams method and consequently to any of TON Client JS bindings. All JS Blobs in the request params will be resolved and converted to base64-encoded strings and then JSON-serialized on a worker thread to avoid UI freezes before calling tc_request_ptr function from TON SDK.
By default, if there is any JS Blob in the request params, then all strings in the response params will also be converted to JS Blobs. Otherwise, all strings will be returned as regular JS strings.
You can override this behaviour by passing additional parameter response_binary_type in the request params with either of following values:
base64 – all string response params will be returned as original strings returned from TON SDK
blob – all string response params will decoded from base64 and returned as raw binary JS Blobs
In the following example, the generated bytes are returned as a blob. Without response_binary_type parameter, the random payload would be returned as base64-encoded string, because there are no blobs in the request params.
const { bytes } = await client.crypto.generate_random_bytes({
length: 1024,
response_binary_type: 'blob',
}); // returns bytes as blob
In the example below, we calculate the hash of the provided blob and force the response binary type to string. Without response_binary_type parameter, the hash would be returned as a blob.
const { hash } = await client.crypto.sha512({
data: decrypted,
response_binary_type: 'base64',
}); // returns hash as string
First, install the dependencies in lib-react-native-jsi directory:
cd packages/lib-react-native-jsi
yarn install
The library comes with example apps for different versions of React Native. Before running each example app, it is necessary to install its dependencies using yarn install as well as its CocoaPods dependencies using pod install in ios directory.
cd example63
yarn install
cd ios
pod install
cd ..
Then you can build and run the example app on Android or iOS with the following commands:
yarn react-native start
yarn react-native run-android
yarn react-native run-ios
Please remember to set appropriate version of React Native in lib-react-native-jsi when developing example63, example64 and example65 apps using the following commands:
cd lib-react-native-jsi
yarn add react-native@0.63.4
yarn add react-native@0.64.0
yarn add react-native@0.65.1
For testing purposes, use tests-lib-react-native-jsi tests runner.
First pack the dependent libraries into *.tgz archives:
cd packages/core
npm i
npx tsc
npm pack
cd ../tests
npm i
npx tsc
npm pack
cd ../lib-react-native-jsi
yarn install
npm pack
Then, install the dependencies from *.tgz archives:
cd ../tests-react-native-jsi
npm add file:../core/tonclient-core-1.28.1.tgz
npm add file:../tests/tonclient-tests-1.28.1.tgz
npm add file:../lib-react-native-jsi/tonclient-lib-react-native-jsi-1.28.1.tgz
npm i
cd ios
pod install
cd ..
Note: Please update the version in the filenames appropriately.
Finally, you can launch the tests runner with the following commands:
node run ios
node run android
FAQs
TON Client React Native JSI Module
The npm package @tonclient/lib-react-native-jsi receives a total of 6 weekly downloads. As such, @tonclient/lib-react-native-jsi popularity was classified as not popular.
We found that @tonclient/lib-react-native-jsi demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
A supply chain attack on Axios introduced a malicious dependency, plain-crypto-js@4.2.1, published minutes earlier and absent from the project’s GitHub releases.

Research
Malicious versions of the Telnyx Python SDK on PyPI delivered credential-stealing malware via a multi-stage supply chain attack.

Security News
TeamPCP is partnering with ransomware group Vect to turn open source supply chain attacks on tools like Trivy and LiteLLM into large-scale ransomware operations.