react-native-zano 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/README.md +56 -0
- package/android/build.gradle +40 -0
- package/android/src/main/java/app/edge/rnzano/RnZanoModule.java +51 -0
- package/android/src/main/java/app/edge/rnzano/RnZanoPackage.java +21 -0
- package/ios/ZanoModule.h +4 -0
- package/ios/ZanoModule.mm +86 -0
- package/ios/ZanoModule.xcframework/Info.plist +44 -0
- package/ios/ZanoModule.xcframework/ios-arm64/libzano-module.a +0 -0
- package/ios/ZanoModule.xcframework/ios-arm64_x86_64-simulator/libzano-module.a +0 -0
- package/ios/react-native-zano.xcodeproj/project.pbxproj +1 -0
- package/lib/scripts/update-sources.d.ts +1 -0
- package/lib/scripts/update-sources.js +308 -0
- package/lib/scripts/utils/android-tools.d.ts +1 -0
- package/lib/scripts/utils/android-tools.js +25 -0
- package/lib/scripts/utils/common.d.ts +19 -0
- package/lib/scripts/utils/common.js +74 -0
- package/lib/src/CppBridge.d.ts +69 -0
- package/lib/src/CppBridge.js +328 -0
- package/lib/src/index.d.ts +4 -0
- package/lib/src/index.js +28 -0
- package/lib/src/types.d.ts +234 -0
- package/lib/src/types.js +23 -0
- package/package.json +55 -0
- package/react-native-zano.podspec +27 -0
- package/src/zano-wrapper/zano-methods.hpp +15 -0
package/CHANGELOG.md
ADDED
package/README.md
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# react-native-zano
|
|
2
|
+
|
|
3
|
+
This library packages Zano C++ client for use on React Native.
|
|
4
|
+
|
|
5
|
+
Supported platforms:
|
|
6
|
+
|
|
7
|
+
- Android
|
|
8
|
+
- iOS
|
|
9
|
+
|
|
10
|
+
## Usage
|
|
11
|
+
|
|
12
|
+
First, add this library to your React Native app using NPM or Yarn, and run `pod install` as necessary to integrate it with your app's native code.
|
|
13
|
+
|
|
14
|
+
Here is a simple usage example:
|
|
15
|
+
|
|
16
|
+
```js
|
|
17
|
+
import { makeZano } from 'react-native-zano'
|
|
18
|
+
|
|
19
|
+
const zano = makeZano()
|
|
20
|
+
const version = await zano.getVersion()
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
We have types too, if you need those:
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
import type { CppBridge } from 'react-native-zano'
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
All methods available in Zano's `plain_wallet_api` are available here. In addition, there are convenience methods that provide higher-level abstractions by combining multiple raw asynchronous API calls and handling common error cases:
|
|
30
|
+
|
|
31
|
+
- getSeedPhraseInfo - Returns information about a seed phrase
|
|
32
|
+
- generateSeedPhrase - Creates a new seed phrase
|
|
33
|
+
- startWallet - Opens an existing wallet or creates a new one if it doesn't exist
|
|
34
|
+
- stopWallet - Safely closes a wallet
|
|
35
|
+
- removeWallet - Deletes a wallet from the system
|
|
36
|
+
- walletStatus - Gets the current status of a wallet
|
|
37
|
+
- getBalances - Retrieves the balance information for a wallet
|
|
38
|
+
- getTransactions - Fetches recent transactions for a wallet
|
|
39
|
+
- whitelistAssets - Add assetIds to wallet's local whitelist
|
|
40
|
+
- transfer - Sends funds to another wallet
|
|
41
|
+
|
|
42
|
+
## Developing
|
|
43
|
+
|
|
44
|
+
This library relies on a large amount of native C++ code from other repos. To integrate this code, you must run the following script before publishing this library to NPM:
|
|
45
|
+
|
|
46
|
+
```sh
|
|
47
|
+
npm run update-sources
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
This script does the following tasks:
|
|
51
|
+
|
|
52
|
+
- Download third-party source code.
|
|
53
|
+
- Compile shared libraries for Android.
|
|
54
|
+
- Compile an iOS universal static library and put it into an XCFramework.
|
|
55
|
+
|
|
56
|
+
The `update-sources` script is also the place to make edits when upgrading any of the third-party dependencies. The react-native-zano repo doesn't include these third-party C++ sources, since they are enormous.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
buildscript {
|
|
2
|
+
repositories {
|
|
3
|
+
mavenCentral()
|
|
4
|
+
google()
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
dependencies {
|
|
8
|
+
classpath 'com.android.tools.build:gradle:7.3.1'
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
apply plugin: 'com.android.library'
|
|
13
|
+
|
|
14
|
+
def safeExtGet(prop, fallback) {
|
|
15
|
+
rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
android {
|
|
19
|
+
compileSdkVersion safeExtGet('compileSdkVersion', 32)
|
|
20
|
+
defaultConfig {
|
|
21
|
+
minSdkVersion safeExtGet('minSdkVersion', 23)
|
|
22
|
+
targetSdkVersion safeExtGet('targetSdkVersion', 32)
|
|
23
|
+
}
|
|
24
|
+
lintOptions {
|
|
25
|
+
abortOnError false
|
|
26
|
+
}
|
|
27
|
+
namespace 'app.edge.rnzano'
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
repositories {
|
|
31
|
+
maven {
|
|
32
|
+
url('../node_modules/react-native/android')
|
|
33
|
+
}
|
|
34
|
+
google()
|
|
35
|
+
mavenCentral()
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
dependencies {
|
|
39
|
+
implementation 'com.facebook.react:react-native:+'
|
|
40
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
package app.edge.rnzano;
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.ReadableArray;
|
|
4
|
+
import com.facebook.react.bridge.Promise;
|
|
5
|
+
import com.facebook.react.bridge.ReactApplicationContext;
|
|
6
|
+
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
|
7
|
+
import com.facebook.react.bridge.ReactMethod;
|
|
8
|
+
import java.util.HashMap;
|
|
9
|
+
import java.util.Map;
|
|
10
|
+
|
|
11
|
+
public class RnZanoModule extends ReactContextBaseJavaModule {
|
|
12
|
+
private native String callZanoJNI(String method, String[] arguments);
|
|
13
|
+
|
|
14
|
+
private native String[] getMethodNames();
|
|
15
|
+
|
|
16
|
+
static {
|
|
17
|
+
System.loadLibrary("rnzano");
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
public RnZanoModule(ReactApplicationContext reactContext) {
|
|
21
|
+
super(reactContext);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
@Override
|
|
25
|
+
public Map<String, Object> getConstants() {
|
|
26
|
+
final Map<String, Object> constants = new HashMap<>();
|
|
27
|
+
constants.put("methodNames", getMethodNames());
|
|
28
|
+
constants.put("documentDirectory", getReactApplicationContext().getFilesDir().getAbsolutePath());
|
|
29
|
+
return constants;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
@Override
|
|
33
|
+
public String getName() {
|
|
34
|
+
return "ZanoModule";
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
@ReactMethod
|
|
38
|
+
public void callZano(String method, ReadableArray arguments, Promise promise) {
|
|
39
|
+
// Re-package the arguments:
|
|
40
|
+
String[] strings = new String[arguments.size()];
|
|
41
|
+
for (int i = 0; i < arguments.size(); ++i) {
|
|
42
|
+
strings[i] = arguments.getString(i);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
try {
|
|
46
|
+
promise.resolve(callZanoJNI(method, strings));
|
|
47
|
+
} catch (Exception e) {
|
|
48
|
+
promise.reject("ZanoError", e);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
package app.edge.rnzano;
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.ReactPackage;
|
|
4
|
+
import com.facebook.react.bridge.NativeModule;
|
|
5
|
+
import com.facebook.react.bridge.ReactApplicationContext;
|
|
6
|
+
import com.facebook.react.uimanager.ViewManager;
|
|
7
|
+
import java.util.Arrays;
|
|
8
|
+
import java.util.Collections;
|
|
9
|
+
import java.util.List;
|
|
10
|
+
|
|
11
|
+
public class RnZanoPackage implements ReactPackage {
|
|
12
|
+
@Override
|
|
13
|
+
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
|
|
14
|
+
return Arrays.<NativeModule>asList(new RnZanoModule(reactContext));
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
@Override
|
|
18
|
+
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
|
|
19
|
+
return Collections.emptyList();
|
|
20
|
+
}
|
|
21
|
+
}
|
package/ios/ZanoModule.h
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
#import "ZanoModule.h"
|
|
2
|
+
#include "zano-methods.hpp"
|
|
3
|
+
|
|
4
|
+
@implementation ZanoModule
|
|
5
|
+
|
|
6
|
+
RCT_EXPORT_MODULE();
|
|
7
|
+
|
|
8
|
+
+ (BOOL)requiresMainQueueSetup { return NO; }
|
|
9
|
+
|
|
10
|
+
RCT_REMAP_METHOD(
|
|
11
|
+
callZano,
|
|
12
|
+
callZanoMethod:(NSString *)method
|
|
13
|
+
arguments:(NSArray *)arguments
|
|
14
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
15
|
+
rejecter:(RCTPromiseRejectBlock)reject
|
|
16
|
+
) {
|
|
17
|
+
const std::string methodString = [method UTF8String];
|
|
18
|
+
|
|
19
|
+
// Re-package the arguments:
|
|
20
|
+
NSUInteger length = [arguments count];
|
|
21
|
+
std::vector<const std::string> strings;
|
|
22
|
+
strings.reserve(length);
|
|
23
|
+
for (NSUInteger i = 0; i < length; ++i) {
|
|
24
|
+
NSString *string = [arguments objectAtIndex:i];
|
|
25
|
+
strings.push_back([string UTF8String]);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Find the named method:
|
|
29
|
+
for (int i = 0; i < zanoMethodCount; ++i) {
|
|
30
|
+
if (zanoMethods[i].name != methodString) continue;
|
|
31
|
+
|
|
32
|
+
// Validate the argument count:
|
|
33
|
+
if (zanoMethods[i].argc != strings.size()) {
|
|
34
|
+
reject(@"Error", @"zano incorrect C++ argument count", nil);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Call the method, with error handling:
|
|
39
|
+
try {
|
|
40
|
+
const std::string out = zanoMethods[i].method(strings);
|
|
41
|
+
resolve(
|
|
42
|
+
[NSString stringWithCString:out.c_str() encoding:NSUTF8StringEncoding]
|
|
43
|
+
);
|
|
44
|
+
} catch (std::exception e) {
|
|
45
|
+
reject(
|
|
46
|
+
@"Error",
|
|
47
|
+
[NSString stringWithCString:e.what() encoding:NSUTF8StringEncoding],
|
|
48
|
+
nil
|
|
49
|
+
);
|
|
50
|
+
} catch (...) {
|
|
51
|
+
reject(@"Error", @"zano threw a C++ exception", nil);
|
|
52
|
+
}
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
reject(
|
|
57
|
+
@"TypeError",
|
|
58
|
+
[NSString stringWithFormat:@"No zano C++ method %@", method],
|
|
59
|
+
nil
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
- (NSDictionary *)constantsToExport
|
|
64
|
+
{
|
|
65
|
+
NSMutableArray *out = [NSMutableArray arrayWithCapacity:zanoMethodCount];
|
|
66
|
+
for (int i = 0; i < zanoMethodCount; ++i) {
|
|
67
|
+
NSString *name = [NSString stringWithCString:zanoMethods[i].name
|
|
68
|
+
encoding:NSUTF8StringEncoding];
|
|
69
|
+
out[i] = name;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
NSFileManager *fileManager = [NSFileManager defaultManager];
|
|
73
|
+
NSURL *docsDir = [fileManager URLForDirectory:NSDocumentDirectory
|
|
74
|
+
inDomain:NSUserDomainMask
|
|
75
|
+
appropriateForURL:nil
|
|
76
|
+
create:YES
|
|
77
|
+
error:nil];
|
|
78
|
+
NSString *docsPath = [docsDir path];
|
|
79
|
+
|
|
80
|
+
return @{
|
|
81
|
+
@"methodNames": out,
|
|
82
|
+
@"documentDirectory": docsPath
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
@end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
3
|
+
<plist version="1.0">
|
|
4
|
+
<dict>
|
|
5
|
+
<key>AvailableLibraries</key>
|
|
6
|
+
<array>
|
|
7
|
+
<dict>
|
|
8
|
+
<key>BinaryPath</key>
|
|
9
|
+
<string>libzano-module.a</string>
|
|
10
|
+
<key>LibraryIdentifier</key>
|
|
11
|
+
<string>ios-arm64</string>
|
|
12
|
+
<key>LibraryPath</key>
|
|
13
|
+
<string>libzano-module.a</string>
|
|
14
|
+
<key>SupportedArchitectures</key>
|
|
15
|
+
<array>
|
|
16
|
+
<string>arm64</string>
|
|
17
|
+
</array>
|
|
18
|
+
<key>SupportedPlatform</key>
|
|
19
|
+
<string>ios</string>
|
|
20
|
+
</dict>
|
|
21
|
+
<dict>
|
|
22
|
+
<key>BinaryPath</key>
|
|
23
|
+
<string>libzano-module.a</string>
|
|
24
|
+
<key>LibraryIdentifier</key>
|
|
25
|
+
<string>ios-arm64_x86_64-simulator</string>
|
|
26
|
+
<key>LibraryPath</key>
|
|
27
|
+
<string>libzano-module.a</string>
|
|
28
|
+
<key>SupportedArchitectures</key>
|
|
29
|
+
<array>
|
|
30
|
+
<string>arm64</string>
|
|
31
|
+
<string>x86_64</string>
|
|
32
|
+
</array>
|
|
33
|
+
<key>SupportedPlatform</key>
|
|
34
|
+
<string>ios</string>
|
|
35
|
+
<key>SupportedPlatformVariant</key>
|
|
36
|
+
<string>simulator</string>
|
|
37
|
+
</dict>
|
|
38
|
+
</array>
|
|
39
|
+
<key>CFBundlePackageType</key>
|
|
40
|
+
<string>XFWK</string>
|
|
41
|
+
<key>XCFrameworkFormatVersion</key>
|
|
42
|
+
<string>1.0</string>
|
|
43
|
+
</dict>
|
|
44
|
+
</plist>
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
// Placeholder so react-native autolinking can find us.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const srcPath: string;
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Run this script as `node -r sucrase/register ./scripts/update-sources.ts`
|
|
3
|
+
//
|
|
4
|
+
// It will:
|
|
5
|
+
// - Download third-party source code.
|
|
6
|
+
// - Assemble Android shared libraries for each platform.
|
|
7
|
+
// - Assemble an iOS universal static xcframework.
|
|
8
|
+
//
|
|
9
|
+
// Here is where each puzzle piece comes from:
|
|
10
|
+
//
|
|
11
|
+
// | | Zano | OpenSSL | Boost |
|
|
12
|
+
// |---------|-------|-------------------|-------------------|
|
|
13
|
+
// | Android | CMake | zano_native_lib | Boost-for-Android |
|
|
14
|
+
// | iOS | CMake | OpenSSL-Universal | zano_native_lib |
|
|
15
|
+
//
|
|
16
|
+
// For both iOS and Android, we build Zano by invoking CMake directly.
|
|
17
|
+
// The zano_native_lib build scripts aren't really useful,
|
|
18
|
+
// since the aren't geared towards React Native auto-linking.
|
|
19
|
+
// Calling CMake ourselves isn't that hard.
|
|
20
|
+
//
|
|
21
|
+
// On Android, the zano_native_lib OpenSSL libraries in are fine,
|
|
22
|
+
// but we have to use Boost-for-Android to get the right STL version.
|
|
23
|
+
//
|
|
24
|
+
// On iOS, the boost libraries are fine,
|
|
25
|
+
// but their OpenSSL is just a re-packaged copy OpenSSL-Universal,
|
|
26
|
+
// so it's simpler to pull that in from CocoaPods directly.
|
|
27
|
+
//
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
exports.srcPath = void 0;
|
|
30
|
+
const promises_1 = require("fs/promises");
|
|
31
|
+
const os_1 = require("os");
|
|
32
|
+
const path_1 = require("path");
|
|
33
|
+
const android_tools_1 = require("./utils/android-tools");
|
|
34
|
+
const common_1 = require("./utils/common");
|
|
35
|
+
exports.srcPath = (0, path_1.join)(__dirname, '../src');
|
|
36
|
+
async function main() {
|
|
37
|
+
await (0, promises_1.mkdir)(common_1.tmpPath, { recursive: true });
|
|
38
|
+
await downloadSources();
|
|
39
|
+
// Android:
|
|
40
|
+
await buildAndroidBoost();
|
|
41
|
+
for (const platform of androidPlatforms) {
|
|
42
|
+
await buildAndroidZano(platform);
|
|
43
|
+
}
|
|
44
|
+
// iOS:
|
|
45
|
+
for (const platform of iosPlatforms) {
|
|
46
|
+
await buildIosZano(platform);
|
|
47
|
+
}
|
|
48
|
+
await packageIosZano();
|
|
49
|
+
}
|
|
50
|
+
async function downloadSources() {
|
|
51
|
+
await (0, common_1.getRepo)('zano_native_lib', 'https://github.com/hyle-team/zano_native_lib.git', '391a965d1d609f917cc97908b9d354a7f54e0258');
|
|
52
|
+
await (0, common_1.getRepo)('Boost-for-Android', 'https://github.com/moritz-wundke/Boost-for-Android.git', '51924ec5533a4fefb5edf99feaeded794c06a4fb');
|
|
53
|
+
}
|
|
54
|
+
// Compiler options:
|
|
55
|
+
const includePaths = ['zano_native_lib/Zano/src/wallet'];
|
|
56
|
+
// Source list (from src/):
|
|
57
|
+
const sources = ['zano-wrapper/zano-methods.cpp'];
|
|
58
|
+
// .a files from Zano:
|
|
59
|
+
const zanoLibs = ['common', 'crypto', 'currency_core', 'wallet', 'z'];
|
|
60
|
+
// .a files from boost:
|
|
61
|
+
const boostLibs = [
|
|
62
|
+
'atomic',
|
|
63
|
+
'chrono',
|
|
64
|
+
'date_time',
|
|
65
|
+
'filesystem',
|
|
66
|
+
'program_options',
|
|
67
|
+
'regex',
|
|
68
|
+
'serialization',
|
|
69
|
+
'system',
|
|
70
|
+
'thread',
|
|
71
|
+
'timer'
|
|
72
|
+
];
|
|
73
|
+
const androidPlatforms = [
|
|
74
|
+
{ arch: 'arm64-v8a', triple: 'aarch64-linux-android33' },
|
|
75
|
+
{ arch: 'armeabi-v7a', triple: 'armv7a-linux-androideabi23' },
|
|
76
|
+
{ arch: 'x86', triple: 'i686-linux-android23' },
|
|
77
|
+
{ arch: 'x86_64', triple: 'x86_64-linux-android23' }
|
|
78
|
+
];
|
|
79
|
+
// Phones and simulators we need to support:
|
|
80
|
+
const iosPlatforms = [
|
|
81
|
+
{ sdk: 'iphoneos', arch: 'arm64', cmakePlatform: 'OS64' },
|
|
82
|
+
{ sdk: 'iphonesimulator', arch: 'arm64', cmakePlatform: 'SIMULATORARM64' },
|
|
83
|
+
{ sdk: 'iphonesimulator', arch: 'x86_64', cmakePlatform: 'SIMULATOR64' }
|
|
84
|
+
// Zano does not support these:
|
|
85
|
+
// { sdk: 'iphoneos', arch: 'armv7' },
|
|
86
|
+
// { sdk: 'iphoneos', arch: 'armv7s' },
|
|
87
|
+
];
|
|
88
|
+
const iosSdkTriples = {
|
|
89
|
+
iphoneos: '%arch%-apple-ios9.0',
|
|
90
|
+
iphonesimulator: '%arch%-apple-ios9.0-simulator'
|
|
91
|
+
};
|
|
92
|
+
/**
|
|
93
|
+
* We compile our own Boost for Android,
|
|
94
|
+
* because the Zano one is linking with the static STL library,
|
|
95
|
+
* but we need to link with the shared STL library.
|
|
96
|
+
*/
|
|
97
|
+
async function buildAndroidBoost() {
|
|
98
|
+
const boostExists = await (0, common_1.fileExists)((0, path_1.join)(common_1.tmpPath, 'Boost-for-Android/build/out/arm64-v8a/lib/libboost_atomic.a'));
|
|
99
|
+
if (boostExists)
|
|
100
|
+
return;
|
|
101
|
+
const ndkPath = await (0, android_tools_1.getNdkPath)();
|
|
102
|
+
await (0, common_1.loudExec)('./build-android.sh', [
|
|
103
|
+
`--arch=${androidPlatforms.map(platform => platform.arch).join(',')}`,
|
|
104
|
+
'--boost=1.84.0',
|
|
105
|
+
`--with-libraries=${boostLibs.join(',')}`,
|
|
106
|
+
'--layout=system',
|
|
107
|
+
ndkPath
|
|
108
|
+
], { cwd: (0, path_1.join)(common_1.tmpPath, 'Boost-for-Android') });
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Invokes CMake to build Zano,
|
|
112
|
+
* followed by clang++ to build the shared library.
|
|
113
|
+
*/
|
|
114
|
+
async function buildAndroidZano(platform) {
|
|
115
|
+
const { arch, triple } = platform;
|
|
116
|
+
const ndkPath = await (0, android_tools_1.getNdkPath)();
|
|
117
|
+
const working = (0, path_1.join)(common_1.tmpPath, `android-${arch}`);
|
|
118
|
+
const boostPath = (0, path_1.join)(common_1.tmpPath, 'Boost-for-Android/build/out/', arch);
|
|
119
|
+
const sslPath = (0, path_1.join)(common_1.tmpPath, 'zano_native_lib/_libs_android/openssl');
|
|
120
|
+
const zanoLibPath = (0, path_1.join)(common_1.tmpPath, `android-${arch}/${arch}/lib/`);
|
|
121
|
+
// Build Zano itself:
|
|
122
|
+
await (0, common_1.loudExec)('cmake', [
|
|
123
|
+
// Source directory:
|
|
124
|
+
`-S${(0, path_1.join)(common_1.tmpPath, 'zano_native_lib/Zano')}`,
|
|
125
|
+
// Build directory:
|
|
126
|
+
`-B${(0, path_1.join)(working, 'cmake')}`,
|
|
127
|
+
// Build options:
|
|
128
|
+
`-DBoost_INCLUDE_DIRS=${(0, path_1.join)(boostPath, 'include')}`,
|
|
129
|
+
`-DBoost_LIBRARY_DIRS=${(0, path_1.join)(boostPath, 'lib')}`,
|
|
130
|
+
`-DBoost_VERSION="1.84.0"`,
|
|
131
|
+
`-DCMAKE_ANDROID_ARCH_ABI=${arch}`,
|
|
132
|
+
`-DCMAKE_ANDROID_NDK=${ndkPath}`,
|
|
133
|
+
`-DCMAKE_ANDROID_STL_TYPE=c++_shared`,
|
|
134
|
+
`-DCMAKE_BUILD_TYPE=Release`,
|
|
135
|
+
`-DCMAKE_INSTALL_PREFIX=${working}`,
|
|
136
|
+
`-DCMAKE_SYSTEM_NAME=Android`,
|
|
137
|
+
`-DCMAKE_SYSTEM_VERSION=23`,
|
|
138
|
+
`-DDISABLE_TOR=TRUE`,
|
|
139
|
+
`-DOPENSSL_CRYPTO_LIBRARY=${(0, path_1.join)(sslPath, arch, 'lib/libcrypto.a')}`,
|
|
140
|
+
`-DOPENSSL_INCLUDE_DIR=${(0, path_1.join)(sslPath, 'include')}`,
|
|
141
|
+
`-DOPENSSL_SSL_LIBRARY=${(0, path_1.join)(sslPath, arch, 'lib/libssl.a')}`
|
|
142
|
+
]);
|
|
143
|
+
await (0, common_1.loudExec)('cmake', [
|
|
144
|
+
'--build',
|
|
145
|
+
(0, path_1.join)(working, 'cmake'),
|
|
146
|
+
'--config',
|
|
147
|
+
'Release',
|
|
148
|
+
'--target',
|
|
149
|
+
'install',
|
|
150
|
+
'--',
|
|
151
|
+
`-j${(0, os_1.cpus)().length}`
|
|
152
|
+
]);
|
|
153
|
+
// Build the library:
|
|
154
|
+
const cxxPath = (0, path_1.join)(ndkPath, `toolchains/llvm/prebuilt/darwin-x86_64/bin/${triple}-clang++`);
|
|
155
|
+
const outPath = (0, path_1.join)(common_1.tmpPath, '../android/src/main/jniLibs/', arch);
|
|
156
|
+
await (0, promises_1.mkdir)(outPath, { recursive: true });
|
|
157
|
+
const jniSources = [...sources, 'jni/jni.cpp'];
|
|
158
|
+
const sslLibs = ['crypto', 'ssl'];
|
|
159
|
+
console.log(`Linking librnzano.so for Android ${arch}`);
|
|
160
|
+
await (0, common_1.loudExec)(cxxPath, [
|
|
161
|
+
'-shared',
|
|
162
|
+
'-fPIC',
|
|
163
|
+
`-o${(0, path_1.join)(outPath, 'librnzano.so')}`,
|
|
164
|
+
...includePaths.map(path => `-I${(0, path_1.join)(common_1.tmpPath, path)}`),
|
|
165
|
+
...jniSources.map(source => (0, path_1.join)(exports.srcPath, source)),
|
|
166
|
+
...boostLibs.map(name => (0, path_1.join)(boostPath, `/lib/libboost_${name}.a`)),
|
|
167
|
+
...sslLibs.map(name => (0, path_1.join)(sslPath, `${arch}/lib/lib${name}.a`)),
|
|
168
|
+
...zanoLibs.map(name => (0, path_1.join)(zanoLibPath, `lib${name}.a`)),
|
|
169
|
+
'-llog',
|
|
170
|
+
`-Wl,--version-script=${(0, path_1.join)(exports.srcPath, 'jni/exports.map')}`,
|
|
171
|
+
'-Wl,--no-undefined'
|
|
172
|
+
]);
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Invokes CMake to build Zano, then breaks open the resulting .a files
|
|
176
|
+
* and re-assembles them into one giant .a file.
|
|
177
|
+
*/
|
|
178
|
+
async function buildIosZano(platform) {
|
|
179
|
+
const { sdk, arch, cmakePlatform } = platform;
|
|
180
|
+
const working = (0, path_1.join)(common_1.tmpPath, `${sdk}-${arch}`);
|
|
181
|
+
await (0, promises_1.mkdir)(working, { recursive: true });
|
|
182
|
+
// Find platform tools:
|
|
183
|
+
const ar = await (0, common_1.quietExec)('xcrun', ['--sdk', sdk, '--find', 'ar']);
|
|
184
|
+
const cc = await (0, common_1.quietExec)('xcrun', ['--sdk', sdk, '--find', 'clang']);
|
|
185
|
+
const cxx = await (0, common_1.quietExec)('xcrun', ['--sdk', sdk, '--find', 'clang++']);
|
|
186
|
+
const sdkFlags = [
|
|
187
|
+
'-arch',
|
|
188
|
+
arch,
|
|
189
|
+
'-target',
|
|
190
|
+
iosSdkTriples[sdk].replace('%arch%', arch),
|
|
191
|
+
'-isysroot',
|
|
192
|
+
await (0, common_1.quietExec)('xcrun', ['--sdk', sdk, '--show-sdk-path'])
|
|
193
|
+
];
|
|
194
|
+
const cflags = [
|
|
195
|
+
...includePaths.map(path => `-I${(0, path_1.join)(common_1.tmpPath, path)}`),
|
|
196
|
+
'-miphoneos-version-min=9.0',
|
|
197
|
+
'-O2',
|
|
198
|
+
'-Werror=partial-availability'
|
|
199
|
+
];
|
|
200
|
+
const cxxflags = [...cflags, '-std=c++11'];
|
|
201
|
+
// Compile our sources:
|
|
202
|
+
const objects = [];
|
|
203
|
+
for (const source of sources) {
|
|
204
|
+
console.log(`Compiling ${source} for ${sdk}-${arch}...`);
|
|
205
|
+
// Figure out the object file name:
|
|
206
|
+
const object = (0, path_1.join)(working, source.replace(/^.*\//, '').replace(/\.c$|\.cc$|\.cpp$/, '.o'));
|
|
207
|
+
objects.push(object);
|
|
208
|
+
const useCxx = /\.cpp$|\.cc$/.test(source);
|
|
209
|
+
await (0, common_1.loudExec)(useCxx ? cxx : cc, [
|
|
210
|
+
'-c',
|
|
211
|
+
...(useCxx ? cxxflags : cflags),
|
|
212
|
+
...sdkFlags,
|
|
213
|
+
`-o${object}`,
|
|
214
|
+
(0, path_1.join)(exports.srcPath, source)
|
|
215
|
+
]);
|
|
216
|
+
}
|
|
217
|
+
// Build Zano itself:
|
|
218
|
+
const boostPath = (0, path_1.join)(common_1.tmpPath, `zano_native_lib/_libs_ios/boost`);
|
|
219
|
+
const sslPath = (0, path_1.join)(common_1.tmpPath, `zano_native_lib/_libs_ios/OpenSSL/${sdk}`);
|
|
220
|
+
const iosToolchain = (0, path_1.join)(common_1.tmpPath, 'zano_native_lib/ios-cmake/ios.toolchain.cmake');
|
|
221
|
+
await (0, common_1.loudExec)('cmake', [
|
|
222
|
+
// Source directory:
|
|
223
|
+
`-S${(0, path_1.join)(common_1.tmpPath, 'zano_native_lib/Zano')}`,
|
|
224
|
+
// Build directory:
|
|
225
|
+
`-B${(0, path_1.join)(working, 'cmake')}`,
|
|
226
|
+
// Build options:
|
|
227
|
+
`-DBoost_INCLUDE_DIRS=${(0, path_1.join)(boostPath, 'include')}`,
|
|
228
|
+
`-DBoost_LIBRARY_DIRS=${(0, path_1.join)(boostPath, `stage/${sdk}/${arch}`)}`,
|
|
229
|
+
`-DBoost_VERSION="1.84.0"`,
|
|
230
|
+
`-DCMAKE_BUILD_TYPE=Release`,
|
|
231
|
+
`-DCMAKE_INSTALL_PREFIX=${working}`,
|
|
232
|
+
`-DCMAKE_SYSTEM_NAME=iOS`,
|
|
233
|
+
`-DCMAKE_TOOLCHAIN_FILE=${iosToolchain}`,
|
|
234
|
+
`-DCMAKE_XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH=NO`,
|
|
235
|
+
`-DDISABLE_TOR=TRUE`,
|
|
236
|
+
`-DOPENSSL_CRYPTO_LIBRARY=${(0, path_1.join)(sslPath, 'lib/libcrypto.a')}`,
|
|
237
|
+
`-DOPENSSL_INCLUDE_DIR=${(0, path_1.join)(sslPath, 'include')}`,
|
|
238
|
+
`-DOPENSSL_SSL_LIBRARY=${(0, path_1.join)(sslPath, 'lib/libssl.a')}`,
|
|
239
|
+
`-DPLATFORM=${cmakePlatform}`,
|
|
240
|
+
`-GXcode`
|
|
241
|
+
]);
|
|
242
|
+
await (0, common_1.loudExec)('cmake', [
|
|
243
|
+
'--build',
|
|
244
|
+
(0, path_1.join)(working, 'cmake'),
|
|
245
|
+
'--config',
|
|
246
|
+
'Release',
|
|
247
|
+
'--target',
|
|
248
|
+
'install'
|
|
249
|
+
]);
|
|
250
|
+
// Explode Zano archives and gather the objects:
|
|
251
|
+
async function unpackLib(libPath, name) {
|
|
252
|
+
console.log(`Unpacking lib${name}.a`);
|
|
253
|
+
const outPath = (0, path_1.join)(working, `unpack/${name}`);
|
|
254
|
+
await (0, promises_1.rm)(outPath, { recursive: true, force: true });
|
|
255
|
+
await (0, promises_1.mkdir)(outPath, { recursive: true });
|
|
256
|
+
await (0, common_1.loudExec)('ar', ['-x', libPath], { cwd: outPath });
|
|
257
|
+
// Add object files to the list:
|
|
258
|
+
for (const file of await (0, promises_1.readdir)(outPath)) {
|
|
259
|
+
if (file.endsWith('.o'))
|
|
260
|
+
objects.push((0, path_1.join)(outPath, file));
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
for (const lib of zanoLibs) {
|
|
264
|
+
await unpackLib((0, path_1.join)(working, `lib/lib${lib}.a`), lib);
|
|
265
|
+
}
|
|
266
|
+
for (const lib of boostLibs) {
|
|
267
|
+
await unpackLib((0, path_1.join)(common_1.tmpPath, `zano_native_lib/_libs_ios/boost/stage/${sdk}/${arch}/libboost_${lib}.a`), `boost_${lib}`);
|
|
268
|
+
}
|
|
269
|
+
// Generate a static library:
|
|
270
|
+
console.log(`Building static library for ${sdk}-${arch}...`);
|
|
271
|
+
const library = (0, path_1.join)(working, `libzano-module.a`);
|
|
272
|
+
await (0, promises_1.rm)(library, { force: true });
|
|
273
|
+
await (0, common_1.loudExec)(ar, ['rcs', library, ...objects]);
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Creates a unified xcframework file out of the per-platform
|
|
277
|
+
* static libraries that `buildIosZano` creates.
|
|
278
|
+
*/
|
|
279
|
+
async function packageIosZano() {
|
|
280
|
+
const sdks = new Set(iosPlatforms.map(row => row.sdk));
|
|
281
|
+
// Merge the platforms into a fat library:
|
|
282
|
+
const merged = [];
|
|
283
|
+
for (const sdk of sdks) {
|
|
284
|
+
console.log(`Merging libraries for ${sdk}...`);
|
|
285
|
+
const outPath = (0, path_1.join)(common_1.tmpPath, `${sdk}-lipo`);
|
|
286
|
+
await (0, promises_1.mkdir)(outPath, { recursive: true });
|
|
287
|
+
const output = (0, path_1.join)(outPath, 'libzano-module.a');
|
|
288
|
+
await (0, common_1.loudExec)('lipo', [
|
|
289
|
+
'-create',
|
|
290
|
+
'-output',
|
|
291
|
+
output,
|
|
292
|
+
...iosPlatforms
|
|
293
|
+
.filter(platform => platform.sdk === sdk)
|
|
294
|
+
.map(({ sdk, arch }) => (0, path_1.join)(common_1.tmpPath, `${sdk}-${arch}`, `libzano-module.a`))
|
|
295
|
+
]);
|
|
296
|
+
merged.push('-library', output);
|
|
297
|
+
}
|
|
298
|
+
// Bundle those into an XCFramework:
|
|
299
|
+
console.log('Creating XCFramework...');
|
|
300
|
+
await (0, promises_1.rm)('ios/ZanoModule.xcframework', { recursive: true, force: true });
|
|
301
|
+
await (0, common_1.loudExec)('xcodebuild', [
|
|
302
|
+
'-create-xcframework',
|
|
303
|
+
...merged,
|
|
304
|
+
'-output',
|
|
305
|
+
(0, path_1.join)(__dirname, '../ios/ZanoModule.xcframework')
|
|
306
|
+
]);
|
|
307
|
+
}
|
|
308
|
+
main().catch(error => console.log(error));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function getNdkPath(): Promise<string>;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getNdkPath = void 0;
|
|
4
|
+
const path_1 = require("path");
|
|
5
|
+
const common_1 = require("./common");
|
|
6
|
+
// Matches the Edge app NDK version
|
|
7
|
+
// The Zano build used '27.2.12479018', so we could try upgrading.
|
|
8
|
+
const NDK_VERSION = '26.1.10909125';
|
|
9
|
+
async function getNdkPath() {
|
|
10
|
+
const { ANDROID_HOME } = process.env;
|
|
11
|
+
if (ANDROID_HOME == null) {
|
|
12
|
+
throw new Error('ANDROID_HOME is not set in the environment.');
|
|
13
|
+
}
|
|
14
|
+
// Find the NDK:
|
|
15
|
+
const ndkPath = (0, path_1.join)(ANDROID_HOME, 'ndk', NDK_VERSION);
|
|
16
|
+
const hasNdk = await (0, common_1.fileExists)(ndkPath);
|
|
17
|
+
// Install the NDK if we need it:
|
|
18
|
+
if (!hasNdk) {
|
|
19
|
+
console.log(`Installing NDK ${NDK_VERSION}...`);
|
|
20
|
+
const sdkManagerPath = (0, path_1.join)(ANDROID_HOME, 'cmdline-tools/latest/bin/sdkmanager');
|
|
21
|
+
await (0, common_1.loudExec)(sdkManagerPath, [`"ndk;${NDK_VERSION}"`]);
|
|
22
|
+
}
|
|
23
|
+
return ndkPath;
|
|
24
|
+
}
|
|
25
|
+
exports.getNdkPath = getNdkPath;
|