├── .gitattributes ├── ios ├── .gitignore ├── RNCardano.xcworkspace │ ├── xcshareddata │ │ └── IDEWorkspaceChecks.plist │ └── contents.xcworkspacedata ├── RNCWallet.h ├── RNCHdWallet.h ├── RNCPasswordProtect.h ├── RNCBaseReactModule.h ├── RNCRandomAddressChecker.h ├── RNCBaseReactModule.m ├── RNCConvert.h ├── rust │ └── build.sh ├── NSData+FastHex.h ├── RNCSafeOperation.h ├── RNCConvert.m ├── NSData+FastHex.m ├── RNCSafeOperation.m ├── RNCPasswordProtect.m ├── RNCRandomAddressChecker.m ├── RNCHdWallet.m ├── RNCWallet.m └── RNCardano.xcodeproj │ └── project.pbxproj ├── rust ├── .gitignore ├── headers.sh ├── src │ ├── constants.rs │ ├── lib.rs │ ├── common.rs │ ├── ios.rs │ └── android.rs ├── Cargo.toml ├── include │ └── rust_native_cardano.h └── Cargo.lock ├── android ├── .gitignore ├── src │ └── main │ │ ├── AndroidManifest.xml │ │ └── kotlin │ │ └── io │ │ └── crossroad │ │ └── rncardano │ │ ├── CardanoPackage.kt │ │ ├── PasswordProtect.kt │ │ ├── RandomAddressChecker.kt │ │ ├── Result.kt │ │ ├── Native.kt │ │ ├── HdWallet.kt │ │ ├── Convert.kt │ │ └── Wallet.kt ├── proguard-rules.pro └── build.gradle ├── react-native.config.js ├── index.js ├── package.json ├── .gitignore ├── RNCardano.podspec ├── README.md ├── index.d.ts └── LICENSE /.gitattributes: -------------------------------------------------------------------------------- 1 | *.pbxproj -text -------------------------------------------------------------------------------- /ios/.gitignore: -------------------------------------------------------------------------------- 1 | /rust/*.a 2 | /rust/*.h 3 | -------------------------------------------------------------------------------- /rust/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /NDK 3 | /.cargo 4 | -------------------------------------------------------------------------------- /android/.gitignore: -------------------------------------------------------------------------------- 1 | /.cargo 2 | /gradle 3 | /gradlew* 4 | -------------------------------------------------------------------------------- /rust/headers.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | cbindgen . -o include/rust_native_cardano.h -l C -------------------------------------------------------------------------------- /android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /react-native.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | dependency: { 3 | platforms: { 4 | ios: { 5 | sharedLibraries: ["libresolv"], 6 | }, 7 | }, 8 | }, 9 | }; 10 | -------------------------------------------------------------------------------- /ios/RNCardano.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /rust/src/constants.rs: -------------------------------------------------------------------------------- 1 | pub const MAX_OUTPUT_SIZE: usize = 4096; 2 | 3 | pub const SEED_SIZE: usize = 32; 4 | pub const XPRV_SIZE: usize = 96; 5 | pub const XPUB_SIZE: usize = 64; 6 | pub const SIGNATURE_SIZE: usize = 64; 7 | 8 | pub const SALT_SIZE : usize = 32; 9 | pub const NONCE_SIZE : usize = 12; 10 | pub const TAG_SIZE : usize = 16; -------------------------------------------------------------------------------- /ios/RNCardano.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 2 | import { NativeModules } from 'react-native'; 3 | 4 | const { CardanoWallet, CardanoHdWallet, CardanoPasswordProtect, CardanoRandomAddressChecker } = NativeModules; 5 | 6 | export { 7 | CardanoWallet as Wallet, 8 | CardanoHdWallet as HdWallet, 9 | CardanoRandomAddressChecker as RandomAddressChecker, 10 | CardanoPasswordProtect as PasswordProtect 11 | }; 12 | -------------------------------------------------------------------------------- /rust/src/lib.rs: -------------------------------------------------------------------------------- 1 | extern crate wallet_wasm; 2 | extern crate cardano; 3 | 4 | mod common; 5 | mod constants; 6 | 7 | #[cfg(target_os="android")] 8 | extern crate jni; 9 | #[cfg(target_os="android")] 10 | mod android; 11 | #[cfg(target_os="android")] 12 | pub use self::android::*; 13 | 14 | #[cfg(target_os="ios")] 15 | mod ios; 16 | #[cfg(target_os="ios")] 17 | pub use self::ios::*; -------------------------------------------------------------------------------- /ios/RNCWallet.h: -------------------------------------------------------------------------------- 1 | // 2 | // Wallet.h 3 | // RNCardano 4 | // 5 | // Created by Yehor Popovych on 10/21/18. 6 | // Copyright © 2018 Crossroad Labs s.r.o. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "RNCBaseReactModule.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface RNCWallet : RNCBaseReactModule 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /ios/RNCHdWallet.h: -------------------------------------------------------------------------------- 1 | // 2 | // HdWallet.h 3 | // RNCardano 4 | // 5 | // Created by Yehor Popovych on 10/21/18. 6 | // Copyright © 2018 Crossroad Labs s.r.o. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "RNCBaseReactModule.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface RNCHdWallet : RNCBaseReactModule 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /ios/RNCPasswordProtect.h: -------------------------------------------------------------------------------- 1 | // 2 | // RNCPasswordProtect.h 3 | // RNCardano 4 | // 5 | // Created by Yehor Popovych on 10/22/18. 6 | // Copyright © 2018 Crossroad Labs s.r.o. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "RNCBaseReactModule.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface RNCPasswordProtect : RNCBaseReactModule 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /ios/RNCBaseReactModule.h: -------------------------------------------------------------------------------- 1 | // 2 | // RNCBaseReactModule.h 3 | // RNCardano 4 | // 5 | // Created by Yehor Popovych on 10/23/18. 6 | // Copyright © 2018 Crossroad Labs s.r.o. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface RNCBaseReactModule : NSObject 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /ios/RNCRandomAddressChecker.h: -------------------------------------------------------------------------------- 1 | // 2 | // RNCRandomAddressChecker.h 3 | // RNCardano 4 | // 5 | // Created by Yehor Popovych on 10/22/18. 6 | // Copyright © 2018 Crossroad Labs s.r.o. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "RNCBaseReactModule.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface RNCRandomAddressChecker : RNCBaseReactModule 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /ios/RNCBaseReactModule.m: -------------------------------------------------------------------------------- 1 | // 2 | // RNCBaseReactModule.m 3 | // RNCardano 4 | // 5 | // Created by Yehor Popovych on 10/23/18. 6 | // Copyright © 2018 Crossroad Labs s.r.o. All rights reserved. 7 | // 8 | 9 | #import "RNCBaseReactModule.h" 10 | #import 11 | 12 | 13 | @implementation RNCBaseReactModule 14 | 15 | + (void)load { 16 | init_cardano(); 17 | } 18 | 19 | // Can't be called 20 | + (NSString *)moduleName { 21 | return @"RNCBaseReactModule"; 22 | } 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-cardano", 3 | "version": "0.2.4", 4 | "description": "React Native bingings to the rust-cardano", 5 | "main": "index.js", 6 | "types": "index.d.ts", 7 | "scripts": { 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "keywords": [ 11 | "react-native", 12 | "Cardano", 13 | "Wallet" 14 | ], 15 | "author": "Crossroad Labs ", 16 | "license": "Apache-2.0", 17 | "peerDependencies": { 18 | "react-native": "^0.60.0" 19 | }, 20 | "devDependencies": { 21 | "react-native": "^0.60.0" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # OSX 3 | # 4 | .DS_Store 5 | 6 | # node.js 7 | # 8 | node_modules/ 9 | npm-debug.log 10 | yarn-error.log 11 | 12 | 13 | # Xcode 14 | # 15 | build/ 16 | *.pbxuser 17 | !default.pbxuser 18 | *.mode1v3 19 | !default.mode1v3 20 | *.mode2v3 21 | !default.mode2v3 22 | *.perspectivev3 23 | !default.perspectivev3 24 | xcuserdata 25 | *.xccheckout 26 | *.moved-aside 27 | DerivedData 28 | *.hmap 29 | *.ipa 30 | *.xcuserstate 31 | project.xcworkspace 32 | 33 | 34 | # Android/IntelliJ 35 | # 36 | build/ 37 | .idea 38 | .gradle 39 | local.properties 40 | *.iml 41 | 42 | # BUCK 43 | buck-out/ 44 | \.buckd/ 45 | *.keystore 46 | -------------------------------------------------------------------------------- /rust/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rust_native_cardano" 3 | version = "0.1.0" 4 | authors = ["vincent.hanquez@iohk.io"] 5 | license = "MIT" 6 | description = "Exporting to wasm the cardano wallet" 7 | keywords = [ "Cardano", "Wallet", "React Native" ] 8 | 9 | [build-dependencies] 10 | 11 | [dependencies] 12 | wallet-wasm = { git = "https://github.com/input-output-hk/js-cardano-wasm.git" } 13 | cardano = { git = "https://github.com/input-output-hk/js-cardano-wasm.git" } 14 | 15 | [target.'cfg(target_os="android")'.dependencies] 16 | jni = "0.10.2" 17 | 18 | [lib] 19 | crate-type = ["staticlib", "cdylib"] 20 | 21 | [profile.release] 22 | debug = false 23 | opt-level = 's' 24 | lto = false 25 | -------------------------------------------------------------------------------- /android/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/arellomobile/Library/Android/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /android/src/main/kotlin/io/crossroad/rncardano/CardanoPackage.kt: -------------------------------------------------------------------------------- 1 | package io.crossroad.rncardano 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 | 8 | class CardanoPackage : ReactPackage { 9 | override fun createNativeModules(reactContext: ReactApplicationContext): List { 10 | return listOf( 11 | HdWallet(reactContext), 12 | Wallet(reactContext), 13 | PasswordProtect(reactContext), 14 | RandomAddressChecker(reactContext) 15 | ) 16 | } 17 | 18 | override fun createViewManagers(reactContext: ReactApplicationContext): List> { 19 | return emptyList() 20 | } 21 | } -------------------------------------------------------------------------------- /rust/src/common.rs: -------------------------------------------------------------------------------- 1 | use std::panic; 2 | use cardano::util::{base58, hex}; 3 | 4 | pub fn handle_exception R + panic::UnwindSafe, R>(func: F) -> Result { 5 | match panic::catch_unwind(func) { 6 | Ok(res) => Ok(res), 7 | Err(err) => { 8 | if let Some(string) = err.downcast_ref::() { 9 | return Err(string.clone()); 10 | } else if let Some(string) = err.downcast_ref::<&'static str>() { 11 | return Err(string.to_string()); 12 | } 13 | return Err(format!("Error: {:?}", err)); 14 | } 15 | } 16 | } 17 | 18 | pub fn hide_exceptions() { 19 | panic::set_hook(Box::new(|_| {})); 20 | } 21 | 22 | pub fn convert_address_base58(addr: &str) -> String { 23 | let decoded = base58::decode(&addr).expect("Couldn't decode base58"); 24 | format!("\"{}\"", hex::encode(&decoded)) 25 | } -------------------------------------------------------------------------------- /ios/RNCConvert.h: -------------------------------------------------------------------------------- 1 | // 2 | // RNCConvert.h 3 | // RNCardano 4 | // 5 | // Created by Yehor Popovych on 10/21/18. 6 | // Copyright © 2018 Crossroad Labs s.r.o. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface RNCConvert : NSObject 14 | 15 | + (NSData *)dataFromEncodedString:(NSString *)string; 16 | + (NSString *)encodedStringFromData:(NSData *)data; 17 | 18 | + (NSDictionary *)dictionaryFromJsonData:(NSData *)data error:(NSError **)error; 19 | + (NSData *)jsonDataFromDictionary:(NSDictionary *)dictionary error:(NSError **)error; 20 | 21 | + (NSDictionary *)dictionaryResponseFromJsonData:(NSData *)data error:(NSError **)error; 22 | + (NSArray *)arrayResponseFromJsonData:(NSData *)data error:(NSError **)error; 23 | + (NSNumber *)numberResponseFromJsonData:(NSData *)data error:(NSError **)error; 24 | 25 | + (NSData *)UTF8BytesFromString:(NSString *)string; 26 | 27 | + (NSData *)dataFromByteArray:(NSArray *)array; 28 | 29 | @end 30 | 31 | NS_ASSUME_NONNULL_END 32 | -------------------------------------------------------------------------------- /RNCardano.podspec: -------------------------------------------------------------------------------- 1 | 2 | Pod::Spec.new do |s| 3 | package = JSON.parse(File.read(File.join(File.dirname(__FILE__), 'package.json'))) 4 | 5 | s.name = "RNCardano" 6 | s.version = package['version'] 7 | s.summary = package['description'] 8 | 9 | s.homepage = "https://github.com/Emurgo/react-native-cardano" 10 | s.license = package['license'] 11 | s.author = { "Crossroad Labs" => "info@crossroad.io" } 12 | s.source = { :git => "https://github.com/Emurgo/react-native-cardano.git", :tag => "#{s.version}" } 13 | 14 | s.source_files = 'ios/**/*.{h,m,swift,sh}' 15 | s.exclude_files = 'android/' 16 | s.requires_arc = true 17 | 18 | s.ios.deployment_target = '10.0' 19 | s.tvos.deployment_target = '10.0' 20 | 21 | s.script_phase = { 22 | :name => 'Build Rust Binary', 23 | :script => 'bash ${PODS_TARGET_SRCROOT}/ios/rust/build.sh', 24 | :execution_position => :before_compile 25 | } 26 | 27 | s.pod_target_xcconfig = { 28 | 'HEADER_SEARCH_PATHS' => '$(CONFIGURATION_BUILD_DIR)', 29 | 'OTHER_LIBTOOLFLAGS' => '"-lrust_native_cardano"', 30 | "ENABLE_BITCODE" => "NO" 31 | } 32 | 33 | s.libraries = 'resolv' 34 | 35 | s.dependency "React" 36 | end 37 | -------------------------------------------------------------------------------- /ios/rust/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # build-rust.sh 4 | # RNCardano 5 | # 6 | # Created by Yehor Popovych on 10/21/18. 7 | # Copyright © 2018 Crossroad Labs s.r.o. All rights reserved. 8 | 9 | set -e 10 | 11 | HAS_CARGO_IN_PATH=`which cargo; echo $?` 12 | 13 | # when cocoapods is used PODS_TARGET_SRCROOT=path(podspec) 14 | if [ "$HAS_CARGO_IN_PATH" -ne "0" ]; then 15 | PATH="${HOME}/.cargo/bin:${PATH}" 16 | fi 17 | 18 | if [ -z "${PODS_TARGET_SRCROOT}" ]; then 19 | ROOT_DIR="${SRCROOT}/../rust" 20 | else 21 | ROOT_DIR="${PODS_TARGET_SRCROOT}/rust" 22 | fi 23 | 24 | if [[ -n "${DEVELOPER_SDK_DIR:-}" ]]; then 25 | # Assume we're in Xcode, which means we're probably cross-compiling. 26 | # In this case, we need to add an extra library search path for build scripts and proc-macros, 27 | # which run on the host instead of the target. 28 | # (macOS Big Sur does not have linkable libraries in /usr/lib/.) 29 | export LIBRARY_PATH="${DEVELOPER_SDK_DIR}/MacOSX.sdk/usr/lib:${LIBRARY_PATH:-}" 30 | fi 31 | 32 | OUTPUT_DIR=`echo "${CONFIGURATION}" | tr '[:upper:]' '[:lower:]'` 33 | 34 | cd "${ROOT_DIR}" 35 | 36 | cargo lipo --xcode-integ 37 | 38 | mkdir -p "${CONFIGURATION_BUILD_DIR}" 39 | 40 | cp -f "${ROOT_DIR}"/target/universal/"${OUTPUT_DIR}"/*.a "${CONFIGURATION_BUILD_DIR}"/ 41 | cp -f "${ROOT_DIR}"/include/*.h "${CONFIGURATION_BUILD_DIR}"/ 42 | 43 | exit 0 44 | -------------------------------------------------------------------------------- /android/src/main/kotlin/io/crossroad/rncardano/PasswordProtect.kt: -------------------------------------------------------------------------------- 1 | package io.crossroad.rncardano 2 | 3 | import com.facebook.react.bridge.* 4 | 5 | class PasswordProtect(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) { 6 | override fun getName() = "CardanoPasswordProtect" 7 | 8 | @ReactMethod 9 | fun encryptWithPassword( 10 | password: String, salt: String, nonce: String, 11 | data: String, promise: Promise 12 | ) { 13 | try { 14 | Native.passwordProtectEncryptWithPassword( 15 | Convert.bytes(password), 16 | Convert.bytes(salt), 17 | Convert.bytes(nonce), 18 | Convert.bytes(data) 19 | ) 20 | .map { Convert.string(it) } 21 | .pour(promise) 22 | } catch (err: Throwable) { 23 | promise.reject(err) 24 | } 25 | } 26 | 27 | @ReactMethod 28 | fun decryptWithPassword(password: String, data: String, promise: Promise) { 29 | try { 30 | Native.passwordProtectDecryptWithPassword( 31 | Convert.bytes(password), Convert.bytes(data) 32 | ) 33 | .map { Convert.string(it) } 34 | .pour(promise) 35 | } catch (err: Throwable) { 36 | promise.reject(err) 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /android/src/main/kotlin/io/crossroad/rncardano/RandomAddressChecker.kt: -------------------------------------------------------------------------------- 1 | package io.crossroad.rncardano 2 | 3 | import com.facebook.react.bridge.* 4 | import org.json.JSONObject 5 | 6 | class RandomAddressChecker(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) { 7 | override fun getName() = "CardanoRandomAddressChecker" 8 | 9 | @ReactMethod 10 | fun newChecker(pkey: String, promise: Promise) { 11 | try { 12 | Native.randomAddressCheckerNewChecker("\"$pkey\"") 13 | .map { Convert.result(it) } 14 | .pour(promise) 15 | } catch (err: Throwable) { 16 | promise.reject(err) 17 | } 18 | } 19 | 20 | @ReactMethod 21 | fun newCheckerFromMnemonics(mnemonics: String, promise: Promise) { 22 | try { 23 | Native.randomAddressCheckerNewCheckerFromMnemonics("\"$mnemonics\"") 24 | .map { Convert.result(it) } 25 | .pour(promise) 26 | } catch (err: Throwable) { 27 | promise.reject(err) 28 | } 29 | } 30 | 31 | @ReactMethod 32 | fun checkAddresses(checker: ReadableMap, addresses: ReadableArray, promise: Promise) { 33 | try { 34 | val params = JSONObject() 35 | params.put("checker", Convert.json(checker)) 36 | params.put("addresses", Convert.json(addresses)) 37 | Native.randomAddressCheckerCheckAddresses(params) 38 | .map { Convert.arrayResult(it) } 39 | .pour(promise) 40 | } catch (err: Throwable) { 41 | promise.reject(err) 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /android/src/main/kotlin/io/crossroad/rncardano/Result.kt: -------------------------------------------------------------------------------- 1 | package io.crossroad.rncardano 2 | 3 | import com.facebook.react.bridge.Promise 4 | 5 | class Result(val value: T?, val error: String?) { 6 | companion object { 7 | fun ok(value: T): Result { 8 | return Result(value, null) 9 | } 10 | 11 | fun err(err: String): Result { 12 | return Result(null, err) 13 | } 14 | } 15 | 16 | fun map(mapper: (value: T) -> T2): Result { 17 | return if (this.value != null) { 18 | try { Result.ok(mapper(this.value)) } 19 | catch (err: Throwable) { Result.err(err.toString()) } 20 | } else { 21 | Result(null, this.error) 22 | } 23 | } 24 | 25 | fun mapNull(mapper: (value: T?) -> T2?): Result { 26 | return if (this.error == null) { 27 | try { Result(mapper(this.value), null) } 28 | catch (err: Throwable) { Result.err(err.toString()) } 29 | } else { 30 | Result.err(this.error) 31 | } 32 | } 33 | 34 | fun isOk(): Boolean { 35 | return this.error == null 36 | } 37 | 38 | fun isErr(): Boolean { 39 | return this.error != null 40 | } 41 | 42 | fun mapErr(mapper: (err: String) -> String): Result { 43 | return if (this.error != null) { 44 | Result.err(mapper(this.error)) 45 | } else { 46 | this 47 | } 48 | } 49 | 50 | fun pour(promise: Promise) { 51 | if (this.error != null) { 52 | promise.reject("0", this.error) 53 | } else { 54 | promise.resolve(this.value) 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /ios/NSData+FastHex.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSData+FastHex.h 3 | // Pods 4 | // 5 | // Created by Jonathon Mah on 2015-05-13. 6 | // 7 | // 8 | 9 | #import 10 | 11 | 12 | #if !__has_feature(nullability) 13 | #define NS_ASSUME_NONNULL_BEGIN 14 | #define NS_ASSUME_NONNULL_END 15 | #define nullable 16 | #define nonnull 17 | #endif 18 | 19 | 20 | NS_ASSUME_NONNULL_BEGIN 21 | 22 | @interface NSData (FastHex) 23 | 24 | /** Returns an NSData instance constructed from the hex characters of the passed string. 25 | * A convenience method for \p -initWithHexString:ignoreOtherCharacters: with the value 26 | * YES for \p ignoreOtherCharacters . */ 27 | + (instancetype)dataWithHexString:(NSString *)hexString; 28 | 29 | /** Initializes the NSData instance with data from the hex characters of the passed string. 30 | * 31 | * \param hexString A string containing ASCII hexadecimal characters (uppercase and lowercase accepted). 32 | * \param ignoreOtherCharacters If YES, skips non-hexadecimal characters, and trailing characters. 33 | * If NO, non-hexadecimal or trailing characters will abort parsing and this method will return nil. 34 | * 35 | * \return the initialized data instance, or nil if \p ignoreOtherCharacters is NO and \p hexString 36 | * contains a non-hex or trailing character. If \p hexString is the empty string, returns an empty 37 | * (non-nil) NSData instance. */ 38 | - (nullable instancetype)initWithHexString:(NSString *)hexString ignoreOtherCharacters:(BOOL)ignoreOtherCharacters; 39 | 40 | /** Returns a string of the receiver's data bytes as uppercase hexadecimal characters. */ 41 | - (NSString *)hexStringRepresentation; 42 | 43 | /** Returns a string of the receiver's data bytes as uppercase or lowercase hexadecimal characters. 44 | * 45 | * \param uppercase YES to use uppercase letters A-F; NO for lowercase a-f 46 | */ 47 | - (NSString *)hexStringRepresentationUppercase:(BOOL)uppercase; 48 | 49 | @end 50 | 51 | NS_ASSUME_NONNULL_END 52 | -------------------------------------------------------------------------------- /android/src/main/kotlin/io/crossroad/rncardano/Native.kt: -------------------------------------------------------------------------------- 1 | package io.crossroad.rncardano 2 | 3 | import org.json.JSONObject 4 | 5 | object Native { 6 | init { 7 | System.loadLibrary("rust_native_cardano") 8 | this.initLibrary() 9 | } 10 | 11 | private external fun initLibrary() 12 | 13 | // HDWallet 14 | external fun hdWalletFromEnhancedEntropy( 15 | entropy: ByteArray, password: ByteArray 16 | ): Result 17 | external fun hdWalletFromSeed(seed: ByteArray): Result 18 | external fun hdWalletToPublic(pkey: ByteArray): Result 19 | external fun hdWalletDerivePrivate(pkey: ByteArray, index: Int): Result 20 | external fun hdWalletDerivePublic(pubKey: ByteArray, index: Int): Result 21 | external fun hdWalletSign(pkey: ByteArray, data: ByteArray): Result 22 | 23 | // Wallet 24 | external fun walletFromMasterKey(pkey: ByteArray): Result 25 | external fun walletFromDaedalusMnemonic(mnemonics: String): Result 26 | external fun walletNewAccount(params: JSONObject): Result 27 | external fun walletGenerateAddresses(params: JSONObject, alen: Int): Result 28 | external fun walletCheckAddress(address: String): Result 29 | external fun walletSpend(params: JSONObject, ilen: Int, olen: Int): Result 30 | external fun walletMove(params: JSONObject, ilen: Int): Result 31 | 32 | // RandomAddressChecker 33 | external fun randomAddressCheckerNewChecker(pkey: String): Result 34 | external fun randomAddressCheckerNewCheckerFromMnemonics(mnemonics: String): Result 35 | external fun randomAddressCheckerCheckAddresses(params: JSONObject): Result 36 | 37 | // PasswordProtect 38 | external fun passwordProtectEncryptWithPassword( 39 | password: ByteArray, salt: ByteArray, nonce: ByteArray, data: ByteArray 40 | ): Result 41 | external fun passwordProtectDecryptWithPassword( 42 | password: ByteArray, data: ByteArray 43 | ): Result 44 | } -------------------------------------------------------------------------------- /ios/RNCSafeOperation.h: -------------------------------------------------------------------------------- 1 | // 2 | // RNCSafeOperation.h 3 | // RNCardano 4 | // 5 | // Created by Yehor Popovych on 10/22/18. 6 | // Copyright © 2018 Crossroad Labs s.r.o. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | #define CHECK_NON_NULL_OR_CERROR(var, error, name) if (var == NULL) {\ 15 | error = copy_string([[NSString stringWithFormat:@"Empty parameter: \"%s\"", name] UTF8String]);\ 16 | return nil;\ 17 | } 18 | 19 | #define CHECK_HAS_LENGTH_OR_CERROR(var, error, name) if (var == NULL || [var length] <= 0) {\ 20 | error = copy_string([[NSString stringWithFormat:@"Empty parameter: \"%s\"", name] UTF8String]);\ 21 | return nil;\ 22 | } 23 | 24 | @interface NSError (Rust) 25 | 26 | + (NSError *)rustError:(NSString *)description; 27 | 28 | @end 29 | 30 | @interface RNCBaseSafeOperation : NSObject 31 | 32 | - (Out)exec:(In)param error:(NSError **)error; 33 | 34 | - (void)exec:(In)param andResolve:(RCTPromiseResolveBlock)resolve orReject:(RCTPromiseRejectBlock)reject; 35 | 36 | @end 37 | 38 | @interface RNCSafeOperation : RNCBaseSafeOperation 39 | 40 | + (RNCBaseSafeOperation *)new:(Out(^)(In param, NSError** error))cb; 41 | 42 | - (RNCSafeOperation *)initWithCallback:(Out(^)(In param, NSError** error))cb; 43 | 44 | @end 45 | 46 | @interface RNCCSafeOperation : RNCSafeOperation 47 | 48 | + (RNCBaseSafeOperation *)new:(Out(^)(In param, char** error))cb; 49 | 50 | - (RNCCSafeOperation *)initWithCallback:(Out(^)(In param, char** error))cb; 51 | 52 | @end 53 | 54 | @interface RNCSafeOperationCombined : RNCBaseSafeOperation 55 | 56 | + (RNCBaseSafeOperation* )combine:(RNCBaseSafeOperation *)op1 57 | with:(RNCBaseSafeOperation *)op2; 58 | 59 | - (RNCSafeOperationCombined *)init:(RNCBaseSafeOperation *)op1 60 | and:(RNCBaseSafeOperation *)op2; 61 | 62 | @end 63 | 64 | NS_ASSUME_NONNULL_END 65 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext { 3 | kotlin_version = '1.3.10' 4 | gradle_version = '3.3.1' 5 | } 6 | 7 | repositories { 8 | google() 9 | maven { url 'https://plugins.gradle.org/m2/' } 10 | jcenter() 11 | } 12 | 13 | dependencies { 14 | classpath "com.android.tools.build:gradle:$gradle_version" 15 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 16 | } 17 | } 18 | 19 | apply plugin: 'com.android.library' 20 | apply plugin: 'kotlin-android' 21 | apply plugin: 'org.mozilla.rust-android-gradle.rust-android' 22 | 23 | android { 24 | compileSdkVersion 28 25 | buildToolsVersion "28.0.3" 26 | 27 | defaultConfig { 28 | minSdkVersion 21 29 | targetSdkVersion 27 30 | versionCode 1 31 | versionName "1.0" 32 | } 33 | lintOptions { 34 | abortOnError true 35 | } 36 | buildTypes { 37 | release { 38 | minifyEnabled false 39 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 40 | } 41 | } 42 | sourceSets { 43 | main.java.srcDirs += 'src/main/kotlin' 44 | } 45 | } 46 | 47 | cargo { 48 | profile = 'release' 49 | module = '../rust' 50 | libname = 'rust_native_cardano' 51 | targets = ['arm', 'arm64', 'x86', 'x86_64'] 52 | } 53 | 54 | repositories { 55 | google() 56 | maven { 57 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm 58 | url "$rootDir/../node_modules/react-native/android" 59 | } 60 | jcenter() 61 | } 62 | 63 | dependencies { 64 | implementation 'com.facebook.react:react-native:+' 65 | implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" 66 | } 67 | 68 | afterEvaluate { 69 | // The `cargoBuild` task isn't available until after evaluation. 70 | android.libraryVariants.all { variant -> 71 | def productFlavor = "" 72 | variant.productFlavors.each { 73 | productFlavor += "${it.name.capitalize()}" 74 | } 75 | def buildType = "${variant.buildType.name.capitalize()}" 76 | tasks["generate${productFlavor}${buildType}Assets"].dependsOn(tasks["cargoBuild"]) 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /ios/RNCConvert.m: -------------------------------------------------------------------------------- 1 | // 2 | // RNCConvert.m 3 | // RNCardano 4 | // 5 | // Created by Yehor Popovych on 10/21/18. 6 | // Copyright © 2018 Crossroad Labs s.r.o. All rights reserved. 7 | // 8 | 9 | #import "RNCConvert.h" 10 | #import "NSData+FastHex.h" 11 | #import "RNCSafeOperation.h" 12 | 13 | @interface RNCConvert (/* Private */) 14 | 15 | + (id)responseFromJsonData:(NSData *)data error:(NSError **)error; 16 | 17 | @end 18 | 19 | @implementation RNCConvert 20 | 21 | + (NSData *)dataFromEncodedString:(NSString *)string { 22 | return [NSData dataWithHexString:string]; 23 | } 24 | 25 | + (NSString *)encodedStringFromData:(NSData *)data { 26 | return [data hexStringRepresentationUppercase:YES]; 27 | } 28 | 29 | + (NSDictionary *)dictionaryFromJsonData:(NSData *)data error:(NSError **)error { 30 | return [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:error]; 31 | } 32 | 33 | + (NSData *)UTF8BytesFromString:(NSString *)string { 34 | return [string dataUsingEncoding:NSUTF8StringEncoding]; 35 | } 36 | 37 | + (NSData *)jsonDataFromDictionary:(NSDictionary *)dictionary error:(NSError **)error { 38 | return [NSJSONSerialization dataWithJSONObject:dictionary options:kNilOptions error:error]; 39 | } 40 | 41 | + (NSDictionary *)dictionaryResponseFromJsonData:(NSData *)data error:(NSError **)error { 42 | return [self responseFromJsonData:data error:error]; 43 | } 44 | 45 | + (NSArray *)arrayResponseFromJsonData:(NSData *)data error:(NSError **)error { 46 | return [self responseFromJsonData:data error:error]; 47 | } 48 | 49 | + (NSNumber *)numberResponseFromJsonData:(NSData *)data error:(NSError **)error { 50 | return [self responseFromJsonData:data error:error]; 51 | } 52 | 53 | + (NSData *)dataFromByteArray:(NSArray *)array { 54 | NSMutableData* data = [NSMutableData dataWithLength:[array count]]; 55 | unsigned char* bytes = [data mutableBytes]; 56 | for (NSUInteger index = 0; index < [array count]; index++) { 57 | bytes[index] = [[array objectAtIndex:index] unsignedCharValue]; 58 | } 59 | return data; 60 | } 61 | 62 | + (id)responseFromJsonData:(NSData *)data error:(NSError **)error { 63 | NSDictionary* dict = [self dictionaryFromJsonData:data error:error]; 64 | if (*error != nil) { 65 | return nil; 66 | } 67 | if ([[dict objectForKey:@"failed"] boolValue]) { 68 | *error = [NSError rustError: 69 | [NSString stringWithFormat:@"Error in: %@, message: %@", 70 | [dict objectForKey:@"loc"], [dict objectForKey: @"msg"] 71 | ]]; 72 | return nil; 73 | } 74 | return [dict objectForKey:@"result"]; 75 | } 76 | 77 | @end 78 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # react-native-cardano 3 | 4 | ## Getting started 5 | 6 | You must include this module manually in your `package.json`, e.g.: 7 | 8 | ``` 9 | "dependencies": { 10 | ... 11 | "react-native-cardano": "https://github.com/Emurgo/react-native-cardano.git" 12 | } 13 | ``` 14 | 15 | ### Installing Rust 16 | 17 | `$ curl https://sh.rustup.rs -sSf | sh` 18 | 19 | Follow instructions. Restart Terminal application after installation (PATH should be updated) 20 | 21 | #### Install Rust targets and tools for iOS 22 | 23 | 1. Install build targets: `$ rustup target add aarch64-apple-ios armv7-apple-ios armv7s-apple-ios x86_64-apple-ios i386-apple-ios` 24 | 2. Install `cargo-lipo` for building: `$ cargo install cargo-lipo` 25 | 26 | #### Install Rust targets for Android 27 | 28 | `$ rustup target add aarch64-linux-android armv7-linux-androideabi i686-linux-android x86_64-linux-android` 29 | 30 | Android NDK should be installed for Android. Check that `local.properties` file in `android` folder has `ndk.dir` property and it's path is correct. 31 | 32 | ### Mostly automatic installation 33 | 34 | `$ react-native link react-native-cardano` 35 | 36 | ### Manual installation 37 | 38 | #### iOS 39 | 40 | 1. In XCode, in the project navigator, right click `Libraries` ➜ `Add Files to [your project's name]` 41 | 2. Go to `node_modules` ➜ `react-native-cardano` and add `RNCardano.xcodeproj` 42 | 3. In XCode, in the project navigator, select your project. Add `libRNCardano.a` to your project's `Build Phases` ➜ `Link Binary With Libraries` 43 | 4. Run your project (`Cmd+R`) 44 | 45 | #### Android 46 | 47 | 1. Open up `android/app/src/main/java/[...]/MainActivity.java` 48 | - Add `import io.crossroad.rnardano.CardanoPackage;` to the imports at the top of the file 49 | - Add `new CardanoPackage()` to the list returned by the `getPackages()` method 50 | 2. Append the following lines to `android/settings.gradle`: 51 | ``` 52 | include ':react-native-cardano' 53 | project(':react-native-cardano').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-cardano/android') 54 | ``` 55 | 3. Insert the following lines inside the dependencies block in `android/app/build.gradle`: 56 | ``` 57 | compile project(':react-native-cardano') 58 | ``` 59 | 60 | 61 | ## Usage 62 | ```javascript 63 | import { Wallet, HdWallet, RandomAddressChecker, PasswordProtect } from 'react-native-cardano'; 64 | 65 | Wallet 66 | .checkAddress( 67 | "DdzFFzCqrhtCUjHyzgvgigwA5soBgDxpc8WfnG1RGhrsRrWMV8uKdpgVfCXGgNuXhdN4qxPMvRUtbUnWhPzxSdxJrWzPqACZeh6scCH5" 68 | ) 69 | .then(isValid => console.log(isValid)); // Should print "true" 70 | ``` 71 | 72 | You can check all exported functions [there](index.d.ts). 73 | -------------------------------------------------------------------------------- /android/src/main/kotlin/io/crossroad/rncardano/HdWallet.kt: -------------------------------------------------------------------------------- 1 | package io.crossroad.rncardano 2 | 3 | import com.facebook.react.bridge.ReactApplicationContext 4 | import com.facebook.react.bridge.ReactContextBaseJavaModule 5 | import com.facebook.react.bridge.ReactMethod 6 | import com.facebook.react.bridge.Promise 7 | 8 | class HdWallet(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) { 9 | override fun getName() = "CardanoHdWallet" 10 | 11 | @ReactMethod 12 | fun fromEnhancedEntropy(entropy: String, password: String, promise: Promise) { 13 | try { 14 | Native.hdWalletFromEnhancedEntropy(Convert.bytes(entropy), Convert.bytes(password)) 15 | .map { Convert.string(it) } 16 | .pour(promise) 17 | } catch (err: Throwable) { 18 | promise.reject(err) 19 | } 20 | 21 | } 22 | 23 | @ReactMethod 24 | fun fromSeed(seed: String, promise: Promise) { 25 | try { 26 | Native.hdWalletFromSeed(Convert.bytes(seed)) 27 | .map { Convert.string(it) } 28 | .pour(promise) 29 | } catch (err: Throwable) { 30 | promise.reject(err) 31 | } 32 | } 33 | 34 | @ReactMethod 35 | fun toPublic(xprv: String, promise: Promise) { 36 | try { 37 | Native.hdWalletToPublic(Convert.bytes(xprv)) 38 | .map { Convert.string(it) } 39 | .pour(promise) 40 | } catch (err: Throwable) { 41 | promise.reject(err) 42 | } 43 | } 44 | 45 | @ReactMethod 46 | fun derivePrivate(xprv: String, index: Int, promise: Promise) { 47 | try { 48 | Native.hdWalletDerivePrivate(Convert.bytes(xprv), index) 49 | .map { Convert.string(it) } 50 | .pour(promise) 51 | } catch (err: Throwable) { 52 | promise.reject(err) 53 | } 54 | } 55 | 56 | @ReactMethod 57 | fun derivePublic(xpub: String, index: Int, promise: Promise) { 58 | try { 59 | Native.hdWalletDerivePublic(Convert.bytes(xpub), index) 60 | .map { Convert.string(it) } 61 | .pour(promise) 62 | } catch (err: Throwable) { 63 | promise.reject(err) 64 | } 65 | } 66 | 67 | @ReactMethod 68 | fun sign(xprv: String, data: String, promise: Promise) { 69 | try { 70 | Native.hdWalletSign(Convert.bytes(xprv), Convert.bytes(data)) 71 | .map { Convert.string(it) } 72 | .pour(promise) 73 | } catch (err: Throwable) { 74 | promise.reject(err) 75 | } 76 | } 77 | } -------------------------------------------------------------------------------- /ios/NSData+FastHex.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSData+FastHex.m 3 | // Pods 4 | // 5 | // Created by Jonathon Mah on 2015-05-13. 6 | // 7 | // 8 | 9 | #import "NSData+FastHex.h" 10 | 11 | 12 | @implementation NSData (FastHex) 13 | 14 | static const uint8_t invalidNibble = 128; 15 | 16 | static uint8_t nibbleFromChar(unichar c) { 17 | if (c >= '0' && c <= '9') { 18 | return c - '0'; 19 | } else if (c >= 'A' && c <= 'F') { 20 | return 10 + c - 'A'; 21 | } else if (c >= 'a' && c <= 'f') { 22 | return 10 + c - 'a'; 23 | } else { 24 | return invalidNibble; 25 | } 26 | } 27 | 28 | + (instancetype)dataWithHexString:(NSString *)hexString 29 | { return [[self alloc] initWithHexString:hexString ignoreOtherCharacters:YES]; } 30 | 31 | - (nullable instancetype)initWithHexString:(NSString *)hexString ignoreOtherCharacters:(BOOL)ignoreOtherCharacters 32 | { 33 | if (!hexString) 34 | return nil; 35 | 36 | const NSUInteger charLength = hexString.length; 37 | const NSUInteger maxByteLength = charLength / 2; 38 | uint8_t *const bytes = malloc(maxByteLength); 39 | uint8_t *bytePtr = bytes; 40 | 41 | CFStringInlineBuffer inlineBuffer; 42 | CFStringInitInlineBuffer((CFStringRef)hexString, &inlineBuffer, CFRangeMake(0, charLength)); 43 | 44 | // Each byte is made up of two hex characters; store the outstanding half-byte until we read the second 45 | uint8_t hiNibble = invalidNibble; 46 | for (CFIndex i = 0; i < charLength; ++i) { 47 | uint8_t nextNibble = nibbleFromChar(CFStringGetCharacterFromInlineBuffer(&inlineBuffer, i)); 48 | 49 | if (nextNibble == invalidNibble && !ignoreOtherCharacters) { 50 | free(bytes); 51 | return nil; 52 | } else if (hiNibble == invalidNibble) { 53 | hiNibble = nextNibble; 54 | } else if (nextNibble != invalidNibble) { 55 | // Have next full byte 56 | *bytePtr++ = (hiNibble << 4) | nextNibble; 57 | hiNibble = invalidNibble; 58 | } 59 | } 60 | 61 | if (hiNibble != invalidNibble && !ignoreOtherCharacters) { // trailing hex character 62 | free(bytes); 63 | return nil; 64 | } 65 | 66 | return [self initWithBytesNoCopy:bytes length:(bytePtr - bytes) freeWhenDone:YES]; 67 | } 68 | 69 | - (NSString *)hexStringRepresentation 70 | { return [self hexStringRepresentationUppercase:YES]; } 71 | 72 | - (NSString *)hexStringRepresentationUppercase:(BOOL)uppercase 73 | { 74 | const char *hexTable = uppercase ? "0123456789ABCDEF" : "0123456789abcdef"; 75 | 76 | const NSUInteger byteLength = self.length; 77 | const NSUInteger charLength = byteLength * 2; 78 | char *const hexChars = malloc(charLength * sizeof(*hexChars)); 79 | __block char *charPtr = hexChars; 80 | 81 | [self enumerateByteRangesUsingBlock:^(const void *bytes, NSRange byteRange, BOOL *stop) { 82 | const uint8_t *bytePtr = bytes; 83 | for (NSUInteger count = 0; count < byteRange.length; ++count) { 84 | const uint8_t byte = *bytePtr++; 85 | *charPtr++ = hexTable[(byte >> 4) & 0xF]; 86 | *charPtr++ = hexTable[byte & 0xF]; 87 | } 88 | }]; 89 | 90 | return [[NSString alloc] initWithBytesNoCopy:hexChars length:charLength encoding:NSASCIIStringEncoding freeWhenDone:YES]; 91 | } 92 | 93 | @end 94 | -------------------------------------------------------------------------------- /ios/RNCSafeOperation.m: -------------------------------------------------------------------------------- 1 | // 2 | // RNCSafeOperation.m 3 | // RNCardano 4 | // 5 | // Created by Yehor Popovych on 10/22/18. 6 | // Copyright © 2018 Crossroad Labs s.r.o. All rights reserved. 7 | // 8 | 9 | #import "RNCSafeOperation.h" 10 | #import 11 | 12 | @implementation RNCBaseSafeOperation 13 | 14 | - (void)exec:(id)param andResolve:(RCTPromiseResolveBlock)resolve orReject:(RCTPromiseRejectBlock)reject { 15 | NSError* error = nil; 16 | id result = [self exec:param error:&error]; 17 | if (error != nil) { 18 | reject([NSString stringWithFormat:@"%li", (long)[error code]], 19 | [error localizedDescription], 20 | error); 21 | } else { 22 | resolve(result); 23 | } 24 | } 25 | 26 | - (id)exec:(id)param error:(NSError **)error { 27 | NSAssert(true, @"Reload"); 28 | return nil; 29 | } 30 | 31 | @end 32 | 33 | @interface RNCSafeOperation (/* Private */) 34 | 35 | @property (copy) Out (^callback)(In param, NSError** error); 36 | 37 | @end 38 | 39 | @implementation RNCSafeOperation 40 | 41 | + (RNCBaseSafeOperation *)new:(_Nullable id (^)(_Nullable id param, NSError** error))cb { 42 | return [[RNCSafeOperation alloc] initWithCallback: cb]; 43 | } 44 | 45 | - (RNCSafeOperation *)initWithCallback:(_Nullable id(^)(_Nullable id param, NSError** error))cb { 46 | if (self = [super init]) { 47 | self.callback = cb; 48 | } 49 | return self; 50 | } 51 | 52 | - (id)exec:(id)param error:(NSError **)error { 53 | return self.callback(param, error); 54 | } 55 | 56 | @end 57 | 58 | @implementation RNCCSafeOperation 59 | 60 | + (RNCBaseSafeOperation *)new:(_Nullable id(^)(_Nullable id param, char** error))cb { 61 | return [[RNCCSafeOperation alloc] initWithCallback:cb]; 62 | } 63 | 64 | - (RNCCSafeOperation *)initWithCallback:(_Nullable id(^)(_Nullable id param, char** error))cb { 65 | return [super initWithCallback:^_Nullable id(_Nullable id param, NSError **error) { 66 | char* cError = NULL; 67 | id result = cb(param, &cError); 68 | if (cError != NULL) { 69 | *error = [NSError rustError:[NSString stringWithUTF8String: cError]]; 70 | dealloc_string(cError); 71 | } 72 | return result; 73 | }]; 74 | } 75 | 76 | @end 77 | 78 | @interface RNCSafeOperationCombined (/* Private */) 79 | 80 | @property (strong) RNCSafeOperation* op1; 81 | @property (strong) RNCSafeOperation* op2; 82 | 83 | @end 84 | 85 | @implementation RNCSafeOperationCombined 86 | 87 | + (RNCBaseSafeOperation* )combine:(RNCSafeOperation *)op1 with:(RNCSafeOperation *)op2 { 88 | return [[self alloc] init:op1 and: op2]; 89 | } 90 | 91 | - (RNCSafeOperationCombined* )init:(RNCSafeOperation *)op1 and:(RNCSafeOperation *)op2 { 92 | if (self = [super init]) { 93 | self.op1 = op1; 94 | self.op2 = op2; 95 | } 96 | return self; 97 | } 98 | 99 | - (id)exec:(id)param error:(NSError **)error { 100 | id result = [self.op1 exec:param error:error]; 101 | if (*error == nil) { 102 | result = [self.op2 exec:result error:error]; 103 | } 104 | return result; 105 | } 106 | 107 | @end 108 | 109 | @implementation NSError (Rust) 110 | 111 | + (NSError *)rustError:(NSString *)description { 112 | return [NSError errorWithDomain:@"RNCardano.Rust" 113 | code: 0 114 | userInfo: @{NSLocalizedDescriptionKey: description}]; 115 | } 116 | 117 | @end 118 | 119 | 120 | -------------------------------------------------------------------------------- /index.d.ts: -------------------------------------------------------------------------------- 1 | declare namespace RNCardano { 2 | export type HexString = string; 3 | 4 | export namespace HdWallet { 5 | export type XPrv = HexString; 6 | export type XPub = HexString; 7 | 8 | // Generate an eXtended private key from the given entropy and the given password. 9 | export function fromEnhancedEntropy(entropy: HexString, password: HexString): Promise; 10 | 11 | // Create a private key from the given seed. 12 | export function fromSeed(seed: HexString): Promise; 13 | 14 | // Get a public key for the private one. 15 | export function toPublic(xprv: XPrv): Promise; 16 | 17 | // Create a derived private key with an index. 18 | export function derivePrivate(xprv: XPrv, index: number): Promise; 19 | 20 | // Create a derived public key with an index. 21 | export function derivePublic(xpub: XPub, index: number): Promise; 22 | 23 | // Sign the given message with the private key. 24 | export function sign(xprv: XPrv, msg: HexString): Promise; 25 | } 26 | 27 | export namespace Wallet { 28 | export type WalletObj = { 29 | root_cached_key: HdWallet.XPrv; 30 | derivation_scheme: string; 31 | selection_policy: string; 32 | config: { protocol_magic: number }; 33 | }; 34 | export type DaedalusWalletObj = WalletObj; 35 | export type AccountObj = { 36 | root_cached_key: HdWallet.XPrv; 37 | derivation_scheme: string; 38 | }; 39 | export type Address = string; //base58 40 | export type AddressType = "Internal" | "External"; 41 | export type SpendInputObj = { 42 | ptr: { id: string; index: number }; 43 | value: OutputObj; 44 | addressing: { account: number; change: number; index: number }; 45 | }; 46 | export type MoveInputObj = { 47 | ptr: { id: string; index: number }; 48 | value: string; 49 | addressing: [number, number]; 50 | } 51 | export type OutputObj = { address: string; value: string }; 52 | export type TransactionObj = { 53 | cbor_encoded_tx: HexString; 54 | change_used: boolean; 55 | fee: string; 56 | }; 57 | 58 | // Create a wallet object from the given seed. 59 | export function fromMasterKey(xprv: HdWallet.XPrv): Promise; 60 | 61 | // Create a daedalus wallet object from the given seed. 62 | export function fromDaedalusMnemonic(mnemonics: string): Promise; 63 | 64 | // Create an account, for public key derivation (using bip44 model). 65 | export function newAccount(wallet: WalletObj, account: number): Promise; 66 | 67 | // Generate addresses for the given wallet. 68 | export function generateAddresses( 69 | account: AccountObj, type: AddressType, indices: Array, protocolMagic: number 70 | ): Promise>; 71 | 72 | // Check if the given base58 string is a valid Cardano Extended Address. 73 | export function checkAddress(address: Address): Promise; 74 | 75 | // Generate a ready to send, signed, transaction. 76 | export function spend( 77 | wallet: WalletObj, inputs: Array, outputs: Array, change_addr: Address 78 | ): Promise; 79 | 80 | // Move all UTxO to a single address. 81 | export function move( 82 | wallet: DaedalusWalletObj, inputs: Array, output: Address 83 | ): Promise; 84 | } 85 | 86 | export namespace RandomAddressChecker { 87 | export type AddressCheckerObj = object; 88 | 89 | // Create a random address checker, this will allow validating. 90 | export function newChecker(xprv: HdWallet.XPrv): Promise; 91 | 92 | // Create a random address checker from daedalus mnemonics. 93 | export function newCheckerFromMnemonics(mnemonics: string): Promise; 94 | 95 | // Check if the given addresses are valid. 96 | export function checkAddresses( 97 | checker: AddressCheckerObj, addresses: Array 98 | ): Promise>; 99 | } 100 | 101 | export namespace PasswordProtect { 102 | // Encrypt the given data with the password, salt and nonce. 103 | export function encryptWithPassword( 104 | password: HexString, salt: HexString, nonce: HexString, data: HexString 105 | ): Promise; 106 | 107 | // Decrypt the given data with the password. 108 | export function decryptWithPassword(password: HexString, data: HexString): Promise; 109 | } 110 | } 111 | export = RNCardano; -------------------------------------------------------------------------------- /android/src/main/kotlin/io/crossroad/rncardano/Convert.kt: -------------------------------------------------------------------------------- 1 | package io.crossroad.rncardano 2 | 3 | import com.facebook.common.util.Hex 4 | import com.facebook.react.bridge.* 5 | import org.json.JSONArray 6 | import org.json.JSONObject 7 | 8 | object Convert { 9 | fun bytes(encodedString: String): ByteArray { 10 | return Hex.decodeHex(encodedString) 11 | } 12 | 13 | fun string(bytes: ByteArray): String { 14 | return Hex.encodeHex(bytes, false) 15 | } 16 | 17 | fun array(json: JSONArray): WritableArray { 18 | val array = Arguments.createArray() 19 | for (i in 0 until json.length()) { 20 | val obj = json[i] 21 | when (obj) { 22 | is Int -> array.pushInt(obj) 23 | is Boolean -> array.pushBoolean(obj) 24 | is Long -> array.pushDouble(obj.toDouble()) 25 | is Float -> array.pushDouble(obj.toDouble()) 26 | is Double -> array.pushDouble(obj.toDouble()) 27 | is String -> array.pushString(obj) 28 | is JSONArray -> array.pushArray(this.array(obj)) 29 | JSONObject.NULL -> array.pushNull() 30 | is JSONObject -> array.pushMap(this.map(obj)) 31 | } 32 | } 33 | return array 34 | } 35 | 36 | fun map(json: JSONObject): WritableMap { 37 | val map = Arguments.createMap() 38 | for (key in json.keys()) { 39 | val obj = json[key] 40 | when (obj) { 41 | is Int -> map.putInt(key, obj) 42 | is Boolean -> map.putBoolean(key, obj) 43 | is Long -> map.putDouble(key, obj.toDouble()) 44 | is Float -> map.putDouble(key, obj.toDouble()) 45 | is Double -> map.putDouble(key, obj.toDouble()) 46 | is String -> map.putString(key, obj) 47 | is JSONArray -> map.putArray(key, this.array(obj)) 48 | JSONObject.NULL -> map.putNull(key) 49 | is JSONObject -> map.putMap(key, this.map(obj)) 50 | } 51 | } 52 | return map 53 | } 54 | 55 | fun json(array: ReadableArray): JSONArray { 56 | val json = JSONArray() 57 | for (i in 0 until array.size()) { 58 | when (array.getType(i)) { 59 | ReadableType.Array -> json.put(this.json(array.getArray(i)!!)) 60 | ReadableType.Map -> json.put(this.json(array.getMap(i)!!)) 61 | ReadableType.Boolean -> json.put(array.getBoolean(i)) 62 | ReadableType.Null, null -> json.put(JSONObject.NULL) 63 | ReadableType.Number -> json.put(array.getDouble(i)) 64 | ReadableType.String -> json.put(array.getString(i)) 65 | } 66 | } 67 | return json 68 | } 69 | 70 | fun json(map: ReadableMap): JSONObject { 71 | val json = JSONObject() 72 | val iterator = map.keySetIterator() 73 | var key: String? = if (iterator.hasNextKey()) { iterator.nextKey() } else { null } 74 | while (key != null) { 75 | when (map.getType(key)) { 76 | ReadableType.Array -> json.put(key, this.json(map.getArray(key)!!)) 77 | ReadableType.Map -> json.put(key, this.json(map.getMap(key)!!)) 78 | ReadableType.Boolean -> json.put(key, map.getBoolean(key)) 79 | ReadableType.Null, null -> json.put(key, JSONObject.NULL) 80 | ReadableType.Number -> json.put(key, map.getDouble(key)) 81 | ReadableType.String -> json.put(key, map.getString(key)) 82 | } 83 | key = if (iterator.hasNextKey()) { iterator.nextKey() } else { null } 84 | } 85 | return json 86 | } 87 | 88 | fun bytes(array: ReadableArray): ByteArray { 89 | return ByteArray(array.size()) { array.getInt(it).toByte() } 90 | } 91 | 92 | 93 | @Throws 94 | private fun checkError(json: JSONObject) { 95 | if(json.getBoolean("failed")) { 96 | throw Throwable( 97 | "Error in: " + json.getString("loc") + 98 | ", message: " + json.getString("msg") 99 | ) 100 | } 101 | } 102 | 103 | fun result(json: JSONObject): WritableMap { 104 | this.checkError(json) 105 | return this.map(json.getJSONObject("result")) 106 | } 107 | 108 | fun arrayResult(json: JSONObject): WritableArray { 109 | this.checkError(json) 110 | return this.array(json.getJSONArray("result")) 111 | } 112 | 113 | fun boolResult(json: JSONObject): Boolean { 114 | this.checkError(json) 115 | return json.getBoolean("result") 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /android/src/main/kotlin/io/crossroad/rncardano/Wallet.kt: -------------------------------------------------------------------------------- 1 | package io.crossroad.rncardano 2 | 3 | import com.facebook.react.bridge.* 4 | import org.json.JSONObject 5 | 6 | class Wallet(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) { 7 | override fun getName() = "CardanoWallet" 8 | 9 | @ReactMethod 10 | fun fromMasterKey(pkey: String, promise: Promise) { 11 | try { 12 | Native.walletFromMasterKey(Convert.bytes(pkey)) 13 | .map { Convert.result(it) } 14 | .pour(promise) 15 | } catch (err: Throwable) { 16 | promise.reject(err) 17 | } 18 | } 19 | 20 | @ReactMethod 21 | fun fromDaedalusMnemonic(mnemonics: String, promise: Promise) { 22 | try { 23 | Native.walletFromDaedalusMnemonic("\"$mnemonics\"") 24 | .map { Convert.result(it) } 25 | .pour(promise) 26 | } catch (err: Throwable) { 27 | promise.reject(err) 28 | } 29 | } 30 | 31 | @ReactMethod 32 | fun newAccount(wallet: ReadableMap, accountIndex: Int, promise: Promise) { 33 | try { 34 | val params = JSONObject() 35 | params.put("wallet", Convert.json(wallet)) 36 | params.put("account", accountIndex) 37 | Native.walletNewAccount(params) 38 | .map { Convert.result(it) } 39 | .pour(promise) 40 | } catch (err: Throwable) { 41 | promise.reject(err) 42 | } 43 | } 44 | 45 | @ReactMethod 46 | fun generateAddresses( 47 | account: ReadableMap, type: String, indicies: ReadableArray, protocolMagic: Int, promise: Promise 48 | ) { 49 | try { 50 | val params = JSONObject() 51 | params.put("account", Convert.json(account)) 52 | params.put("address_type", type) 53 | params.put("indices", Convert.json(indicies)) 54 | params.put("protocol_magic", protocolMagic) 55 | Native.walletGenerateAddresses(params, indicies.size()) 56 | .map { Convert.arrayResult(it) } 57 | .pour(promise) 58 | } catch (err: Throwable) { 59 | promise.reject(err) 60 | } 61 | } 62 | 63 | @ReactMethod 64 | fun checkAddress(address: String, promise: Promise) { 65 | try { 66 | Native.walletCheckAddress(address) 67 | .map { 68 | try { Convert.boolResult(it) } 69 | catch (_: Throwable) { false } 70 | } 71 | .pour(promise) 72 | } catch (err: Throwable) { 73 | promise.reject(err) 74 | } 75 | } 76 | 77 | @ReactMethod 78 | fun spend( 79 | wallet: ReadableMap, inputs: ReadableArray, 80 | outputs: ReadableArray, changeAddress: String, promise: Promise 81 | ) { 82 | try { 83 | val params = JSONObject() 84 | params.put("wallet", Convert.json(wallet)) 85 | params.put("inputs", Convert.json(inputs)) 86 | params.put("outputs", Convert.json(outputs)) 87 | params.put("change_addr", changeAddress) 88 | Native.walletSpend(params, inputs.size(), outputs.size()) 89 | .map { Convert.result(it) } 90 | .map { obj -> 91 | obj.putString( 92 | "cbor_encoded_tx", 93 | Convert.string(Convert.bytes(obj.getArray("cbor_encoded_tx")!!)) 94 | ) 95 | obj 96 | } 97 | .pour(promise) 98 | } catch (err: Throwable) { 99 | promise.reject(err) 100 | } 101 | } 102 | 103 | @ReactMethod 104 | fun move( 105 | wallet: ReadableMap, inputs: ReadableArray, 106 | output: String, promise: Promise 107 | ) { 108 | try { 109 | val params = JSONObject() 110 | params.put("wallet", Convert.json(wallet)) 111 | params.put("inputs", Convert.json(inputs)) 112 | params.put("output", output) 113 | Native.walletMove(params, inputs.size()) 114 | .map { Convert.result(it) } 115 | .map { obj -> 116 | obj.putString( 117 | "cbor_encoded_tx", 118 | Convert.string(Convert.bytes(obj.getArray("cbor_encoded_tx")!!)) 119 | ) 120 | obj 121 | } 122 | .pour(promise) 123 | } catch (err: Throwable) { 124 | promise.reject(err) 125 | } 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /rust/include/rust_native_cardano.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define MAX_OUTPUT_SIZE 4096 6 | 7 | #define NONCE_SIZE 12 8 | 9 | #define SALT_SIZE 32 10 | 11 | #define SEED_SIZE 32 12 | 13 | #define SIGNATURE_SIZE 64 14 | 15 | #define TAG_SIZE 16 16 | 17 | #define XPRV_SIZE 96 18 | 19 | #define XPUB_SIZE 64 20 | 21 | char *copy_string(const char *cstr); 22 | 23 | void dealloc_string(char *ptr); 24 | 25 | int32_t decrypt_with_password_safe(const unsigned char *password_ptr, 26 | uintptr_t password_sz, 27 | const unsigned char *data_ptr, 28 | uintptr_t data_sz, 29 | unsigned char *output_ptr, 30 | char **error); 31 | 32 | int32_t encrypt_with_password_safe(const unsigned char *password_ptr, 33 | uintptr_t password_sz, 34 | const unsigned char *salt_ptr, 35 | const unsigned char *nonce_ptr, 36 | const unsigned char *data_ptr, 37 | uintptr_t data_sz, 38 | unsigned char *output_ptr, 39 | char **error); 40 | 41 | void init_cardano(void); 42 | 43 | int32_t random_address_check_safe(const unsigned char *input_ptr, 44 | uintptr_t input_sz, 45 | unsigned char *output_ptr, 46 | char **error); 47 | 48 | int32_t random_address_checker_from_mnemonics_safe(const unsigned char *input_ptr, 49 | uintptr_t input_sz, 50 | unsigned char *output_ptr, 51 | char **error); 52 | 53 | int32_t random_address_checker_new_safe(const unsigned char *input_ptr, 54 | uintptr_t input_sz, 55 | unsigned char *output_ptr, 56 | char **error); 57 | 58 | void wallet_derive_private_safe(const unsigned char *xprv_ptr, 59 | uint32_t index, 60 | unsigned char *out, 61 | char **error); 62 | 63 | bool wallet_derive_public_safe(const unsigned char *xpub_ptr, 64 | uint32_t index, 65 | unsigned char *out, 66 | char **error); 67 | 68 | uintptr_t wallet_from_enhanced_entropy_safe(const unsigned char *entropy_ptr, 69 | uintptr_t entropy_size, 70 | const unsigned char *password_ptr, 71 | uintptr_t password_size, 72 | unsigned char *out, 73 | char **error); 74 | 75 | void wallet_from_seed_safe(const unsigned char *seed_ptr, unsigned char *out, char **error); 76 | 77 | void wallet_sign_safe(const unsigned char *xprv_ptr, 78 | const unsigned char *msg_ptr, 79 | uintptr_t msg_sz, 80 | unsigned char *out, 81 | char **error); 82 | 83 | void wallet_to_public_safe(const unsigned char *xprv_ptr, unsigned char *out, char **error); 84 | 85 | int32_t xwallet_account_safe(const unsigned char *input_ptr, 86 | uintptr_t input_sz, 87 | unsigned char *output_ptr, 88 | char **error); 89 | 90 | int32_t xwallet_addresses_safe(const unsigned char *input_ptr, 91 | uintptr_t input_sz, 92 | unsigned char *output_ptr, 93 | char **error); 94 | 95 | int32_t xwallet_checkaddress_safe(const unsigned char *input_ptr, 96 | uintptr_t input_sz, 97 | unsigned char *output_ptr, 98 | char **error); 99 | 100 | int32_t xwallet_create_daedalus_mnemonic_safe(const unsigned char *input_ptr, 101 | uintptr_t input_sz, 102 | unsigned char *output_ptr, 103 | char **error); 104 | 105 | int32_t xwallet_from_master_key_safe(const unsigned char *input_ptr, 106 | unsigned char *output_ptr, 107 | char **error); 108 | 109 | int32_t xwallet_move_safe(const unsigned char *input_ptr, 110 | uintptr_t input_sz, 111 | unsigned char *output_ptr, 112 | char **error); 113 | 114 | int32_t xwallet_spend_safe(const unsigned char *input_ptr, 115 | uintptr_t input_sz, 116 | unsigned char *output_ptr, 117 | char **error); 118 | -------------------------------------------------------------------------------- /ios/RNCPasswordProtect.m: -------------------------------------------------------------------------------- 1 | // 2 | // RNCPasswordProtect.m 3 | // RNCardano 4 | // 5 | // Created by Yehor Popovych on 10/22/18. 6 | // Copyright © 2018 Crossroad Labs s.r.o. All rights reserved. 7 | // 8 | 9 | #import "RNCPasswordProtect.h" 10 | #import 11 | #import "RNCConvert.h" 12 | #import "RNCSafeOperation.h" 13 | 14 | @implementation RNCPasswordProtect 15 | 16 | RCT_EXPORT_MODULE(CardanoPasswordProtect) 17 | 18 | RCT_EXPORT_METHOD(encryptWithPassword:(nonnull NSString *)password 19 | andSalt:(nonnull NSString *)salt 20 | andNonce:(nonnull NSString *)nonce 21 | andData:(nonnull NSString *)data 22 | resolver:(RCTPromiseResolveBlock)resolve 23 | rejecter:(RCTPromiseRejectBlock)reject) { 24 | 25 | RNCBaseSafeOperation* op = [RNCCSafeOperation new:^NSString*(NSDictionary* params, char **error) { 26 | NSData* nonce = params[@"nonce"]; 27 | NSData* salt = params[@"salt"]; 28 | NSData* data = params[@"data"]; 29 | NSData* password = params[@"password"]; 30 | 31 | CHECK_HAS_LENGTH_OR_CERROR(password, *error, "password"); 32 | CHECK_HAS_LENGTH_OR_CERROR(data, *error, "data"); 33 | 34 | if ([salt length] != SALT_SIZE) { 35 | *error = copy_string([[NSString stringWithFormat:@"Wrong salt len %lu should be %d", (unsigned long)[salt length], SALT_SIZE] UTF8String]); 36 | return nil; 37 | } 38 | if ([nonce length] != NONCE_SIZE) { 39 | *error = copy_string([[NSString stringWithFormat:@"Wrong nonce len %lu should be %d", (unsigned long)[nonce length], NONCE_SIZE] UTF8String]); 40 | return nil; 41 | } 42 | 43 | NSUInteger result_size = [data length] + TAG_SIZE + NONCE_SIZE + SALT_SIZE; 44 | 45 | NSMutableData* output = [NSMutableData dataWithLength:result_size]; 46 | 47 | int32_t rsz = encrypt_with_password_safe([password bytes], 48 | [password length], 49 | [salt bytes], 50 | [nonce bytes], 51 | [data bytes], 52 | [data length], 53 | [output mutableBytes], 54 | error); 55 | if (*error != NULL) { 56 | return nil; 57 | } 58 | if (rsz == result_size) { 59 | return [RNCConvert encodedStringFromData:output]; 60 | } else { 61 | *error = copy_string([[NSString stringWithFormat:@"Wrong converted data len %d should be %lu", rsz, (unsigned long)result_size] UTF8String]); 62 | return nil; 63 | } 64 | }]; 65 | 66 | NSMutableDictionary* params = [NSMutableDictionary new]; 67 | [params setObject:[RNCConvert dataFromEncodedString:password] forKey:@"password"]; 68 | [params setObject:[RNCConvert dataFromEncodedString:salt] forKey:@"salt"]; 69 | [params setObject:[RNCConvert dataFromEncodedString:nonce] forKey:@"nonce"]; 70 | [params setObject:[RNCConvert dataFromEncodedString:data] forKey:@"data"]; 71 | 72 | [op exec:params andResolve:resolve orReject:reject]; 73 | } 74 | 75 | RCT_EXPORT_METHOD(decryptWithPassword:(nonnull NSString *)password 76 | data:(nonnull NSString *)data 77 | resolver:(RCTPromiseResolveBlock)resolve 78 | rejecter:(RCTPromiseRejectBlock)reject) { 79 | 80 | RNCBaseSafeOperation* op = [RNCCSafeOperation new:^NSString*(NSDictionary* params, char **error) { 81 | NSData* data = params[@"data"]; 82 | NSData* password = params[@"password"]; 83 | 84 | CHECK_HAS_LENGTH_OR_CERROR(password, *error, "password"); 85 | 86 | if ([data length] <= TAG_SIZE + NONCE_SIZE + SALT_SIZE) { 87 | *error = copy_string([[NSString stringWithFormat:@"Wrong data len %lu should be at least %d", (unsigned long)[data length], TAG_SIZE + NONCE_SIZE + SALT_SIZE + 1] UTF8String]); 88 | } 89 | 90 | NSUInteger result_size = [data length] - TAG_SIZE - NONCE_SIZE - SALT_SIZE; 91 | 92 | NSMutableData* output = [NSMutableData dataWithLength:result_size]; 93 | 94 | int32_t rsz = decrypt_with_password_safe([password bytes], 95 | [password length], 96 | [data bytes], 97 | [data length], 98 | [output mutableBytes], 99 | error); 100 | if (*error != NULL) { 101 | return nil; 102 | } 103 | if (rsz <= 0) { 104 | *error = copy_string("Decryption failed. Check your password."); 105 | return nil; 106 | } else if (rsz == result_size) { 107 | return [RNCConvert encodedStringFromData:output]; 108 | } else { 109 | *error = copy_string([[NSString stringWithFormat:@"Wrong converted data len %d should be %lu", rsz, (unsigned long)result_size] UTF8String]); 110 | return nil; 111 | } 112 | }]; 113 | 114 | NSMutableDictionary* params = [NSMutableDictionary new]; 115 | [params setObject:[RNCConvert dataFromEncodedString:password] forKey:@"password"]; 116 | [params setObject:[RNCConvert dataFromEncodedString:data] forKey:@"data"]; 117 | 118 | [op exec:params andResolve:resolve orReject:reject]; 119 | } 120 | 121 | @end 122 | -------------------------------------------------------------------------------- /ios/RNCRandomAddressChecker.m: -------------------------------------------------------------------------------- 1 | // 2 | // RNCRandomAddressChecker.m 3 | // RNCardano 4 | // 5 | // Created by Yehor Popovych on 10/22/18. 6 | // Copyright © 2018 Crossroad Labs s.r.o. All rights reserved. 7 | // 8 | 9 | #import "RNCRandomAddressChecker.h" 10 | #import 11 | #import "RNCConvert.h" 12 | #import "RNCSafeOperation.h" 13 | 14 | 15 | @implementation RNCRandomAddressChecker 16 | 17 | RCT_EXPORT_MODULE(CardanoRandomAddressChecker) 18 | 19 | RCT_EXPORT_METHOD(newChecker:(nonnull NSString *)pkey 20 | resolver:(RCTPromiseResolveBlock)resolve 21 | rejecter:(RCTPromiseRejectBlock)reject) { 22 | RNCBaseSafeOperation *op1 = [RNCCSafeOperation new:^NSDictionary*(NSString* pkey, char **error) { 23 | CHECK_HAS_LENGTH_OR_CERROR(pkey, *error, "pkey"); 24 | NSData* input = [RNCConvert UTF8BytesFromString:[NSString stringWithFormat:@"\"%@\"", pkey]]; 25 | NSMutableData* output = [NSMutableData dataWithLength:MAX_OUTPUT_SIZE]; 26 | int32_t rsz = random_address_checker_new_safe([input bytes], 27 | [input length], 28 | [output mutableBytes], 29 | error); 30 | return @{@"size": [NSNumber numberWithInteger:rsz], @"output": output}; 31 | }]; 32 | 33 | RNCBaseSafeOperation *op2 = [RNCSafeOperation new:^NSDictionary*(NSDictionary* params, NSError ** error) { 34 | NSInteger rsz = [params[@"size"] integerValue]; 35 | if (rsz > 0) { 36 | return [RNCConvert dictionaryResponseFromJsonData:[params[@"output"] subdataWithRange:NSMakeRange(0, rsz)] error:error]; 37 | } else { 38 | *error = [NSError rustError:[NSString stringWithFormat: @"Wrong response size: %li", (long)rsz]]; 39 | } 40 | return nil; 41 | }]; 42 | 43 | [[RNCSafeOperationCombined combine:op1 with:op2] exec:pkey andResolve:resolve orReject:reject]; 44 | } 45 | 46 | RCT_EXPORT_METHOD(newCheckerFromMnemonics:(nonnull NSString *)mnemonics 47 | resolver:(RCTPromiseResolveBlock)resolve 48 | rejecter:(RCTPromiseRejectBlock)reject) { 49 | RNCBaseSafeOperation *op1 = [RNCCSafeOperation new:^NSDictionary*(NSString* mnemonics, char **error) { 50 | CHECK_HAS_LENGTH_OR_CERROR(mnemonics, *error, "mnemonics"); 51 | NSData* input = [RNCConvert UTF8BytesFromString:[NSString stringWithFormat:@"\"%@\"", mnemonics]]; 52 | NSMutableData* output = [NSMutableData dataWithLength:MAX_OUTPUT_SIZE]; 53 | int32_t rsz = random_address_checker_from_mnemonics_safe([input bytes], 54 | [input length], 55 | [output mutableBytes], 56 | error); 57 | return @{@"size": [NSNumber numberWithInteger:rsz], @"output": output}; 58 | }]; 59 | 60 | RNCBaseSafeOperation *op2 = [RNCSafeOperation new:^NSDictionary*(NSDictionary* params, NSError ** error) { 61 | NSInteger rsz = [params[@"size"] integerValue]; 62 | if (rsz > 0) { 63 | return [RNCConvert dictionaryResponseFromJsonData:[params[@"output"] subdataWithRange:NSMakeRange(0, rsz)] error:error]; 64 | } else { 65 | *error = [NSError rustError:[NSString stringWithFormat: @"Wrong response size: %li", (long)rsz]]; 66 | } 67 | return nil; 68 | }]; 69 | 70 | [[RNCSafeOperationCombined combine:op1 with:op2] exec:mnemonics andResolve:resolve orReject:reject]; 71 | } 72 | 73 | RCT_EXPORT_METHOD(checkAddresses:(nonnull NSDictionary *)checker 74 | addresses:(nonnull NSArray *)addresses 75 | resolver:(RCTPromiseResolveBlock)resolve 76 | rejecter:(RCTPromiseRejectBlock)reject) { 77 | 78 | RNCBaseSafeOperation* op1 = [RNCSafeOperation new:^NSData*(NSDictionary* params, NSError ** error) { 79 | return [RNCConvert jsonDataFromDictionary:params error:error]; 80 | }]; 81 | 82 | RNCBaseSafeOperation* op2 = [RNCCSafeOperation new:^NSDictionary*(NSData* input, char **error) { 83 | CHECK_HAS_LENGTH_OR_CERROR(input, *error, "addresses"); 84 | NSUInteger OUTPUT_SIZE = MAX([input length], MAX_OUTPUT_SIZE); 85 | NSMutableData* output = [NSMutableData dataWithLength:OUTPUT_SIZE]; 86 | int32_t rsz = random_address_check_safe([input bytes], 87 | [input length], 88 | [output mutableBytes], 89 | error); 90 | return @{@"size": [NSNumber numberWithInteger:rsz], @"output": output}; 91 | }]; 92 | 93 | RNCBaseSafeOperation *op3 = [RNCSafeOperation new:^NSArray*(NSDictionary* params, NSError **error) { 94 | NSInteger rsz = [params[@"size"] integerValue]; 95 | if (rsz > 0) { 96 | return [RNCConvert arrayResponseFromJsonData:[params[@"output"] subdataWithRange:NSMakeRange(0, rsz)] error:error]; 97 | } else { 98 | *error = [NSError rustError:[NSString stringWithFormat: @"Wrong response size: %li", (long)rsz]]; 99 | } 100 | return nil; 101 | }]; 102 | 103 | NSMutableDictionary* params = [NSMutableDictionary new]; 104 | [params setObject:checker forKey:@"checker"]; 105 | [params setObject:addresses forKey:@"addresses"]; 106 | 107 | [[RNCSafeOperationCombined combine:[RNCSafeOperationCombined combine:op1 with:op2] with:op3] exec:params andResolve:resolve orReject:reject]; 108 | } 109 | 110 | @end 111 | -------------------------------------------------------------------------------- /rust/src/ios.rs: -------------------------------------------------------------------------------- 1 | use common::*; 2 | use wallet_wasm::*; 3 | 4 | use std::os::raw::{c_uchar, c_char}; 5 | use std::ffi::{ CString, CStr }; 6 | use std::panic; 7 | use std::usize; 8 | use std::str; 9 | use std::slice; 10 | 11 | pub use constants::*; 12 | 13 | fn handle_error R + panic::UnwindSafe, R>(error: *mut*mut c_char, err_val: R, func: F) -> R { 14 | match handle_exception(func) { 15 | Ok(val) => val, 16 | Err(err) => { 17 | unsafe { 18 | *error = CString::new(err).unwrap().into_raw(); 19 | } 20 | err_val 21 | } 22 | } 23 | } 24 | 25 | #[no_mangle] 26 | pub unsafe extern "C" fn copy_string(cstr: *const c_char) -> *mut c_char { 27 | let vec = CStr::from_ptr(cstr).to_bytes_with_nul().to_vec(); 28 | CString::from_vec_unchecked(vec).into_raw() 29 | } 30 | 31 | #[no_mangle] 32 | pub extern "C" fn dealloc_string(ptr: *mut c_char) { 33 | dealloc_str(ptr); 34 | } 35 | 36 | #[no_mangle] 37 | pub extern "C" fn init_cardano() { 38 | hide_exceptions(); 39 | } 40 | 41 | #[no_mangle] 42 | pub extern "C" fn wallet_from_enhanced_entropy_safe( 43 | entropy_ptr: *const c_uchar, entropy_size: usize, 44 | password_ptr: *const c_uchar, password_size: usize, 45 | out: *mut c_uchar, 46 | error: *mut*mut c_char 47 | ) -> usize { 48 | handle_error(error, usize::MAX, || { 49 | wallet_from_enhanced_entropy(entropy_ptr, entropy_size, password_ptr, password_size, out) 50 | }) 51 | } 52 | 53 | #[no_mangle] 54 | pub extern "C" fn wallet_from_seed_safe(seed_ptr: *const c_uchar, out: *mut c_uchar, error: *mut*mut c_char) { 55 | handle_error(error, (), || { 56 | wallet_from_seed(seed_ptr, out) 57 | }) 58 | } 59 | 60 | #[no_mangle] 61 | pub extern "C" fn wallet_to_public_safe(xprv_ptr: *const c_uchar, out: *mut c_uchar, error: *mut*mut c_char) { 62 | handle_error(error, (), || { 63 | wallet_to_public(xprv_ptr, out) 64 | }) 65 | } 66 | 67 | #[no_mangle] 68 | pub extern "C" fn wallet_derive_private_safe( 69 | xprv_ptr: *const c_uchar, index: u32, out: *mut c_uchar, error: *mut*mut c_char 70 | ) { 71 | handle_error(error, (), || { 72 | wallet_derive_private(xprv_ptr, index, out) 73 | }) 74 | } 75 | 76 | #[no_mangle] 77 | pub extern "C" fn wallet_derive_public_safe( 78 | xpub_ptr: *const c_uchar, index: u32, out: *mut c_uchar, error: *mut*mut c_char 79 | ) -> bool { 80 | handle_error(error, false, || { 81 | wallet_derive_public(xpub_ptr, index, out) 82 | }) 83 | } 84 | 85 | #[no_mangle] 86 | pub extern "C" fn wallet_sign_safe( 87 | xprv_ptr: *const c_uchar, msg_ptr: *const c_uchar, 88 | msg_sz: usize, out: *mut c_uchar, error: *mut*mut c_char 89 | ) { 90 | handle_error(error, (), || { 91 | wallet_sign(xprv_ptr, msg_ptr, msg_sz, out) 92 | }) 93 | } 94 | 95 | #[no_mangle] 96 | pub extern "C" fn xwallet_from_master_key_safe( 97 | input_ptr: *const c_uchar, output_ptr: *mut c_uchar, error: *mut*mut c_char 98 | ) -> i32 { 99 | handle_error(error, -1, || { 100 | xwallet_from_master_key(input_ptr, output_ptr) 101 | }) 102 | } 103 | 104 | #[no_mangle] 105 | pub extern "C" fn xwallet_create_daedalus_mnemonic_safe( 106 | input_ptr: *const c_uchar, input_sz: usize, 107 | output_ptr: *mut c_uchar, error: *mut*mut c_char 108 | ) -> i32 { 109 | handle_error(error, -1, || { 110 | xwallet_create_daedalus_mnemonic(input_ptr, input_sz, output_ptr) 111 | }) 112 | } 113 | 114 | #[no_mangle] 115 | pub extern "C" fn xwallet_account_safe( 116 | input_ptr: *const c_uchar, input_sz: usize, 117 | output_ptr: *mut c_uchar, error: *mut*mut c_char 118 | ) -> i32 { 119 | handle_error(error, -1, || { 120 | xwallet_account(input_ptr, input_sz, output_ptr) 121 | }) 122 | } 123 | 124 | #[no_mangle] 125 | pub extern "C" fn xwallet_addresses_safe( 126 | input_ptr: *const c_uchar, input_sz: usize, 127 | output_ptr: *mut c_uchar, error: *mut*mut c_char) -> i32 { 128 | handle_error(error, -1, || { 129 | xwallet_addresses(input_ptr, input_sz, output_ptr) 130 | }) 131 | } 132 | 133 | #[no_mangle] 134 | pub extern "C" fn xwallet_checkaddress_safe( 135 | input_ptr: *const c_uchar, input_sz: usize, 136 | output_ptr: *mut c_uchar, error: *mut*mut c_char 137 | ) -> i32 { 138 | handle_error(error, -1, || { 139 | let addr_str = unsafe { 140 | str::from_utf8_unchecked(slice::from_raw_parts(input_ptr, input_sz)) 141 | }; 142 | let fixed_addr = convert_address_base58(addr_str); 143 | let addr: &[u8] = fixed_addr.as_bytes(); 144 | 145 | xwallet_checkaddress(addr.as_ptr(), addr.len(), output_ptr) 146 | }) 147 | } 148 | 149 | #[no_mangle] 150 | pub extern "C" fn xwallet_spend_safe( 151 | input_ptr: *const c_uchar, input_sz: usize, 152 | output_ptr: *mut c_uchar, error: *mut*mut c_char 153 | ) -> i32 { 154 | handle_error(error, -1, || { 155 | xwallet_spend(input_ptr, input_sz, output_ptr) 156 | }) 157 | } 158 | 159 | #[no_mangle] 160 | pub extern "C" fn xwallet_move_safe( 161 | input_ptr: *const c_uchar, input_sz: usize, 162 | output_ptr: *mut c_uchar, error: *mut*mut c_char 163 | ) -> i32 { 164 | handle_error(error, -1, || { 165 | xwallet_move(input_ptr, input_sz, output_ptr) 166 | }) 167 | } 168 | 169 | #[no_mangle] 170 | pub extern "C" fn random_address_checker_new_safe( 171 | input_ptr: *const c_uchar, input_sz: usize, 172 | output_ptr: *mut c_uchar, error: *mut*mut c_char 173 | ) -> i32 { 174 | handle_error(error, -1, || { 175 | random_address_checker_new(input_ptr, input_sz, output_ptr) 176 | }) 177 | } 178 | 179 | #[no_mangle] 180 | pub extern "C" fn random_address_checker_from_mnemonics_safe( 181 | input_ptr: *const c_uchar, input_sz: usize, 182 | output_ptr: *mut c_uchar, error: *mut*mut c_char 183 | ) -> i32 { 184 | handle_error(error, -1, || { 185 | random_address_checker_from_mnemonics(input_ptr, input_sz, output_ptr) 186 | }) 187 | } 188 | 189 | #[no_mangle] 190 | pub extern "C" fn random_address_check_safe( 191 | input_ptr: *const c_uchar, input_sz: usize, 192 | output_ptr: *mut c_uchar, error: *mut*mut c_char 193 | ) -> i32 { 194 | handle_error(error, -1, || { 195 | random_address_check(input_ptr, input_sz, output_ptr) 196 | }) 197 | } 198 | 199 | #[no_mangle] 200 | pub extern "C" fn encrypt_with_password_safe( 201 | password_ptr: *const c_uchar, password_sz: usize, 202 | salt_ptr: *const c_uchar, // expect 32 bytes 203 | nonce_ptr: *const c_uchar, // expect 12 bytes 204 | data_ptr: *const c_uchar, data_sz: usize, 205 | output_ptr: *mut c_uchar, error: *mut*mut c_char 206 | ) -> i32 { 207 | handle_error(error, -1, || { 208 | encrypt_with_password(password_ptr, password_sz, salt_ptr, nonce_ptr, data_ptr, data_sz, output_ptr) 209 | }) 210 | } 211 | 212 | #[no_mangle] 213 | pub extern "C" fn decrypt_with_password_safe( 214 | password_ptr: *const c_uchar, password_sz: usize, 215 | data_ptr: *const c_uchar, data_sz: usize, 216 | output_ptr: *mut c_uchar, error: *mut*mut c_char 217 | ) -> i32 { 218 | handle_error(error, -1, || { 219 | decrypt_with_password(password_ptr, password_sz, data_ptr, data_sz, output_ptr) 220 | }) 221 | } -------------------------------------------------------------------------------- /ios/RNCHdWallet.m: -------------------------------------------------------------------------------- 1 | // 2 | // HdWallet.m 3 | // RNCardano 4 | // 5 | // Created by Yehor Popovych on 10/21/18. 6 | // Copyright © 2018 Crossroad Labs s.r.o. All rights reserved. 7 | // 8 | 9 | #import "RNCHdWallet.h" 10 | #import "RNCConvert.h" 11 | #import 12 | #import "RNCSafeOperation.h" 13 | 14 | @implementation RNCHdWallet 15 | 16 | RCT_EXPORT_MODULE(CardanoHdWallet) 17 | 18 | RCT_EXPORT_METHOD(fromEnhancedEntropy:(nonnull NSString *)entropy 19 | withPassword:(nonnull NSString *)password 20 | resolver:(RCTPromiseResolveBlock)resolve 21 | rejecter:(RCTPromiseRejectBlock)reject) { 22 | 23 | RNCBaseSafeOperation *op = [RNCCSafeOperation new:^NSString*(NSDictionary* params, char ** error) { 24 | NSData* entropy = params[@"entropy"]; 25 | NSData* password = params[@"password"]; 26 | CHECK_HAS_LENGTH_OR_CERROR(entropy, *error, "entropy"); 27 | CHECK_NON_NULL_OR_CERROR(password, *error, "password"); 28 | 29 | NSMutableData* output = [NSMutableData dataWithLength:XPRV_SIZE]; 30 | uintptr_t res = wallet_from_enhanced_entropy_safe([entropy bytes], [entropy length], 31 | [password bytes], [password length], 32 | [output mutableBytes], error); 33 | if (*error != NULL) { 34 | return nil; 35 | } 36 | if (res != 0) { 37 | *error = copy_string([[NSString stringWithFormat:@"Wrong response %lu should be 0", res] UTF8String]); 38 | return nil; 39 | } 40 | return [RNCConvert encodedStringFromData:output]; 41 | }]; 42 | 43 | NSMutableDictionary* params = [NSMutableDictionary new]; 44 | [params setObject:[RNCConvert dataFromEncodedString:entropy] forKey:@"entropy"]; 45 | [params setObject:[RNCConvert dataFromEncodedString:password] forKey:@"password"]; 46 | 47 | [op exec:params andResolve:resolve orReject:reject]; 48 | } 49 | 50 | RCT_EXPORT_METHOD(fromSeed:(nonnull NSString *)seed 51 | resolver:(RCTPromiseResolveBlock)resolve 52 | rejecter:(RCTPromiseRejectBlock)reject) { 53 | 54 | RNCBaseSafeOperation *op = [RNCCSafeOperation new:^NSString*(NSData* seed, char ** error) { 55 | if ([seed length] != SEED_SIZE) { 56 | *error = copy_string([[NSString stringWithFormat:@"Wrong seed len %lu should be %d", (unsigned long)[seed length], SEED_SIZE] UTF8String]); 57 | return nil; 58 | } 59 | NSMutableData* output = [NSMutableData dataWithLength:XPRV_SIZE]; 60 | 61 | wallet_from_seed_safe([seed bytes], [output mutableBytes], error); 62 | 63 | return [RNCConvert encodedStringFromData:output]; 64 | }]; 65 | 66 | [op exec:[RNCConvert dataFromEncodedString:seed] andResolve:resolve orReject:reject]; 67 | } 68 | 69 | RCT_EXPORT_METHOD(toPublic:(nonnull NSString *)xprv 70 | resolver:(RCTPromiseResolveBlock)resolve 71 | rejecter:(RCTPromiseRejectBlock)reject) { 72 | 73 | RNCBaseSafeOperation *op = [RNCCSafeOperation new:^NSString*(NSData* xprv, char ** error) { 74 | if ([xprv length] != XPRV_SIZE) { 75 | *error = copy_string([[NSString stringWithFormat:@"Wrong XPrv len %lu should be %d", (unsigned long)[xprv length], XPRV_SIZE] UTF8String]); 76 | return nil; 77 | } 78 | NSMutableData* output = [NSMutableData dataWithLength:XPUB_SIZE]; 79 | 80 | wallet_to_public_safe([xprv bytes], [output mutableBytes], error); 81 | 82 | return [RNCConvert encodedStringFromData:output]; 83 | }]; 84 | 85 | [op exec:[RNCConvert dataFromEncodedString:xprv] andResolve:resolve orReject:reject]; 86 | } 87 | 88 | RCT_EXPORT_METHOD(derivePrivate:(nonnull NSString *)xprv 89 | withIndex:(nonnull NSNumber *)index 90 | resolver:(RCTPromiseResolveBlock)resolve 91 | rejecter:(RCTPromiseRejectBlock)reject) { 92 | 93 | RNCBaseSafeOperation *op = [RNCCSafeOperation new:^NSString*(NSDictionary* params, char ** error) { 94 | NSData* xprv = params[@"xprv"]; 95 | CHECK_NON_NULL_OR_CERROR(params[@"index"], *error, "index"); 96 | uint32_t index = [params[@"index"] unsignedIntValue]; 97 | if ([xprv length] != XPRV_SIZE) { 98 | *error = copy_string([[NSString stringWithFormat:@"Wrong XPrv len %lu should be %d", (unsigned long)[xprv length], XPRV_SIZE] UTF8String]); 99 | return nil; 100 | } 101 | NSMutableData* output = [NSMutableData dataWithLength:XPRV_SIZE]; 102 | 103 | wallet_derive_private_safe([xprv bytes], index, [output mutableBytes], error); 104 | 105 | return [RNCConvert encodedStringFromData:output]; 106 | }]; 107 | 108 | NSMutableDictionary* params = [NSMutableDictionary new]; 109 | [params setObject:[RNCConvert dataFromEncodedString:xprv] forKey:@"xprv"]; 110 | [params setObject:index forKey:@"index"]; 111 | 112 | [op exec:params andResolve:resolve orReject:reject]; 113 | } 114 | 115 | RCT_EXPORT_METHOD(derivePublic:(nonnull NSString *)xpub 116 | withIndex:(nonnull NSNumber *)index 117 | resolver:(RCTPromiseResolveBlock)resolve 118 | rejecter:(RCTPromiseRejectBlock)reject) { 119 | 120 | RNCBaseSafeOperation *op = [RNCCSafeOperation new:^NSString*(NSDictionary* params, char ** error) { 121 | NSData* xpub = params[@"xpub"]; 122 | CHECK_NON_NULL_OR_CERROR(params[@"index"], *error, "index"); 123 | uint32_t index = [params[@"index"] unsignedIntValue]; 124 | 125 | if ([xpub length] != XPUB_SIZE) { 126 | *error = copy_string([[NSString stringWithFormat:@"Wrong XPub len %lu should be %d", (unsigned long)[xpub length], XPUB_SIZE] UTF8String]); 127 | return nil; 128 | } 129 | 130 | if (index >= 0x80000000) { 131 | *error = copy_string("Cannot do public derivation with hard index"); 132 | return nil; 133 | } 134 | 135 | NSMutableData* output = [NSMutableData dataWithLength:XPUB_SIZE]; 136 | 137 | bool res = wallet_derive_public_safe([xpub bytes], index, [output mutableBytes], error); 138 | 139 | if (*error != NULL) { 140 | return nil; 141 | } 142 | 143 | if (!res) { 144 | *error = copy_string("Can't derive public key"); 145 | } 146 | 147 | return [RNCConvert encodedStringFromData:output]; 148 | }]; 149 | 150 | NSMutableDictionary* params = [NSMutableDictionary new]; 151 | [params setObject:[RNCConvert dataFromEncodedString:xpub] forKey:@"xpub"]; 152 | [params setObject:index forKey:@"index"]; 153 | 154 | [op exec:params andResolve:resolve orReject:reject]; 155 | } 156 | 157 | RCT_EXPORT_METHOD(sign:(nonnull NSString *)xprv 158 | data:(nonnull NSString *)data 159 | resolver:(RCTPromiseResolveBlock)resolve 160 | rejecter:(RCTPromiseRejectBlock)reject) { 161 | 162 | RNCBaseSafeOperation *op = [RNCCSafeOperation new:^NSString*(NSDictionary* params, char ** error) { 163 | NSData* xprv = params[@"xprv"]; 164 | NSData* data = params[@"data"]; 165 | CHECK_HAS_LENGTH_OR_CERROR(data, *error, "data"); 166 | 167 | if ([xprv length] != XPRV_SIZE) { 168 | *error = copy_string([[NSString stringWithFormat:@"Wrong XPrv len %lu should be %d", (unsigned long)[xprv length], XPRV_SIZE] UTF8String]); 169 | return nil; 170 | } 171 | 172 | NSMutableData* output = [NSMutableData dataWithLength:SIGNATURE_SIZE]; 173 | 174 | wallet_sign_safe([xprv bytes], [data bytes], [data length], [output mutableBytes], error); 175 | 176 | return [RNCConvert encodedStringFromData:output]; 177 | }]; 178 | 179 | NSMutableDictionary* params = [NSMutableDictionary new]; 180 | [params setObject:[RNCConvert dataFromEncodedString:xprv] forKey:@"xprv"]; 181 | [params setObject:[RNCConvert dataFromEncodedString:data] forKey:@"data"]; 182 | 183 | [op exec:params andResolve:resolve orReject:reject]; 184 | } 185 | 186 | @end 187 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /ios/RNCWallet.m: -------------------------------------------------------------------------------- 1 | // 2 | // Wallet.m 3 | // RNCardano 4 | // 5 | // Created by Yehor Popovych on 10/21/18. 6 | // Copyright © 2018 Crossroad Labs s.r.o. All rights reserved. 7 | // 8 | 9 | #import "RNCWallet.h" 10 | #import 11 | #import "RNCConvert.h" 12 | #import "RNCSafeOperation.h" 13 | 14 | @implementation RNCWallet 15 | 16 | RCT_EXPORT_MODULE(CardanoWallet) 17 | 18 | RCT_EXPORT_METHOD(fromMasterKey:(nonnull NSString *)pkey 19 | resolver:(RCTPromiseResolveBlock)resolve 20 | rejecter:(RCTPromiseRejectBlock)reject) { 21 | 22 | RNCBaseSafeOperation *op1 = [RNCCSafeOperation new:^NSDictionary*(NSData* pkey, char **error) { 23 | CHECK_HAS_LENGTH_OR_CERROR(pkey, *error, "pkey"); 24 | NSMutableData* output = [NSMutableData dataWithLength:MAX_OUTPUT_SIZE]; 25 | int32_t rsz = xwallet_from_master_key_safe([pkey bytes], 26 | [output mutableBytes], 27 | error); 28 | return @{@"size": [NSNumber numberWithInteger:rsz], @"output": output}; 29 | }]; 30 | 31 | RNCBaseSafeOperation *op2 = [RNCSafeOperation new:^NSDictionary*(NSDictionary* params, NSError ** error) { 32 | NSInteger rsz = [params[@"size"] integerValue]; 33 | if (rsz > 0) { 34 | return [RNCConvert dictionaryResponseFromJsonData:[params[@"output"] subdataWithRange:NSMakeRange(0, rsz)] error:error]; 35 | } else { 36 | *error = [NSError rustError:[NSString stringWithFormat: @"Wrong response size: %li", (long)rsz]]; 37 | } 38 | return nil; 39 | }]; 40 | 41 | [[RNCSafeOperationCombined combine:op1 with:op2] exec:[RNCConvert dataFromEncodedString:pkey] andResolve:resolve orReject:reject]; 42 | } 43 | 44 | RCT_EXPORT_METHOD(fromDaedalusMnemonic:(nonnull NSString *)mnemonics 45 | resolver:(RCTPromiseResolveBlock)resolve 46 | rejecter:(RCTPromiseRejectBlock)reject) { 47 | RNCBaseSafeOperation* op1 = [RNCCSafeOperation new:^NSDictionary*(NSString* mnemonics, char **error) { 48 | CHECK_HAS_LENGTH_OR_CERROR(mnemonics, *error, "mnemonics"); 49 | NSData* input = [RNCConvert UTF8BytesFromString:[NSString stringWithFormat:@"\"%@\"", mnemonics]]; 50 | NSMutableData* output = [NSMutableData dataWithLength:MAX_OUTPUT_SIZE]; 51 | int32_t rsz = xwallet_create_daedalus_mnemonic_safe([input bytes], 52 | [input length], 53 | [output mutableBytes], 54 | error); 55 | return @{@"size": [NSNumber numberWithInteger:rsz], @"output": output}; 56 | }]; 57 | 58 | RNCBaseSafeOperation *op2 = [RNCSafeOperation new:^NSDictionary*(NSDictionary* params, NSError **error) { 59 | NSInteger rsz = [params[@"size"] integerValue]; 60 | if (rsz > 0) { 61 | return [RNCConvert dictionaryResponseFromJsonData:[params[@"output"] subdataWithRange:NSMakeRange(0, rsz)] error:error]; 62 | } else { 63 | *error = [NSError rustError:[NSString stringWithFormat: @"Wrong response size: %li", (long)rsz]]; 64 | } 65 | return nil; 66 | }]; 67 | 68 | [[RNCSafeOperationCombined combine:op1 with:op2] exec:mnemonics andResolve:resolve orReject:reject]; 69 | } 70 | 71 | RCT_EXPORT_METHOD(newAccount:(nonnull NSDictionary *)wallet 72 | withIndex:(nonnull NSNumber *)index 73 | resolver:(RCTPromiseResolveBlock)resolve 74 | rejecter:(RCTPromiseRejectBlock)reject) { 75 | 76 | RNCBaseSafeOperation* op1 = [RNCSafeOperation new:^NSData*(NSDictionary* params, NSError ** error) { 77 | return [RNCConvert jsonDataFromDictionary:params error:error]; 78 | }]; 79 | 80 | RNCBaseSafeOperation* op2 = [RNCCSafeOperation new:^NSDictionary*(NSData* input, char **error) { 81 | NSMutableData* output = [NSMutableData dataWithLength:MAX_OUTPUT_SIZE]; 82 | int32_t rsz = xwallet_account_safe([input bytes], 83 | [input length], 84 | [output mutableBytes], 85 | error); 86 | return @{@"size": [NSNumber numberWithInteger:rsz], @"output": output}; 87 | }]; 88 | 89 | RNCBaseSafeOperation *op3 = [RNCSafeOperation new:^NSDictionary*(NSDictionary* params, NSError **error) { 90 | NSInteger rsz = [params[@"size"] integerValue]; 91 | if (rsz > 0) { 92 | return [RNCConvert dictionaryResponseFromJsonData:[params[@"output"] subdataWithRange:NSMakeRange(0, rsz)] error:error]; 93 | } else { 94 | *error = [NSError rustError:[NSString stringWithFormat: @"Wrong response size: %li", (long)rsz]]; 95 | } 96 | return nil; 97 | }]; 98 | 99 | NSMutableDictionary* params = [NSMutableDictionary new]; 100 | [params setObject:wallet forKey:@"wallet"]; 101 | [params setObject:index forKey:@"account"]; 102 | 103 | [[RNCSafeOperationCombined combine:[RNCSafeOperationCombined combine:op1 with:op2] with:op3] exec:params andResolve:resolve orReject:reject]; 104 | } 105 | 106 | RCT_EXPORT_METHOD(generateAddresses:(nonnull NSDictionary *)account 107 | withType:(nonnull NSString*) type 108 | forIndices:(nonnull NSArray *)indices 109 | withMagic:(nonnull NSNumber*)magic 110 | resolver:(RCTPromiseResolveBlock)resolve 111 | rejecter:(RCTPromiseRejectBlock)reject) { 112 | 113 | RNCBaseSafeOperation* op1 = [RNCSafeOperation new:^NSDictionary*(NSDictionary* params, NSError ** error) { 114 | return @{@"data": [RNCConvert jsonDataFromDictionary:params error:error], 115 | @"alen": [NSNumber numberWithUnsignedInteger:[params[@"indices"] count]]}; 116 | }]; 117 | 118 | RNCBaseSafeOperation* op2 = [RNCCSafeOperation new:^NSDictionary*(NSDictionary* params, char **error) { 119 | NSData* input = params[@"data"]; 120 | CHECK_NON_NULL_OR_CERROR(params[@"alen"], *error, "indicies"); 121 | NSUInteger alen = [params[@"alen"] unsignedIntegerValue]; 122 | NSUInteger maxSize = alen * 131 + 2; // (128 + 3 for meta) per addr + 2 for meta 123 | NSMutableData* output = [NSMutableData dataWithLength:maxSize]; 124 | int32_t rsz = xwallet_addresses_safe([input bytes], 125 | [input length], 126 | [output mutableBytes], 127 | error); 128 | return @{@"size": [NSNumber numberWithInteger:rsz], @"output": output}; 129 | }]; 130 | 131 | RNCBaseSafeOperation *op3 = [RNCSafeOperation new:^NSArray*(NSDictionary* param, NSError **error) { 132 | NSInteger rsz = [param[@"size"] integerValue]; 133 | if (rsz > 0) { 134 | return [RNCConvert arrayResponseFromJsonData:[param[@"output"] subdataWithRange:NSMakeRange(0, rsz)] error:error]; 135 | } else { 136 | *error = [NSError rustError:[NSString stringWithFormat: @"Wrong response size: %li", (long)rsz]]; 137 | } 138 | return nil; 139 | }]; 140 | 141 | NSMutableDictionary* params = [NSMutableDictionary new]; 142 | [params setObject:account forKey:@"account"]; 143 | [params setObject:type forKey:@"address_type"]; 144 | [params setObject:indices forKey:@"indices"]; 145 | [params setObject:magic forKey:@"protocol_magic"]; 146 | 147 | [[RNCSafeOperationCombined combine:[RNCSafeOperationCombined combine:op1 with:op2] with:op3] exec:params andResolve:resolve orReject:reject]; 148 | } 149 | 150 | 151 | RCT_EXPORT_METHOD(checkAddress:(nonnull NSString *)address 152 | resolver:(RCTPromiseResolveBlock)resolve 153 | rejecter:(RCTPromiseRejectBlock)reject) { 154 | 155 | RNCBaseSafeOperation* op1 = [RNCCSafeOperation new:^NSDictionary*(NSString* address, char **error) { 156 | CHECK_HAS_LENGTH_OR_CERROR(address, *error, "address"); 157 | NSData* input = [RNCConvert UTF8BytesFromString:address]; 158 | NSMutableData* output = [NSMutableData dataWithLength:MAX_OUTPUT_SIZE]; 159 | int32_t rsz = xwallet_checkaddress_safe([input bytes], 160 | [input length], 161 | [output mutableBytes], 162 | error); 163 | return @{@"size": [NSNumber numberWithInteger:rsz], @"output": output}; 164 | }]; 165 | 166 | RNCBaseSafeOperation *op2 = [RNCSafeOperation new:^NSNumber*(NSDictionary* params, NSError **error) { 167 | NSInteger rsz = [params[@"size"] integerValue]; 168 | if (rsz > 0) { 169 | NSNumber* res = [RNCConvert numberResponseFromJsonData:[params[@"output"] subdataWithRange:NSMakeRange(0, rsz)] error:error]; 170 | if (*error != nil) { 171 | *error = nil; 172 | return [NSNumber numberWithBool:NO]; 173 | } 174 | return res; 175 | } else { 176 | *error = [NSError rustError:[NSString stringWithFormat: @"Wrong response size: %li", (long)rsz]]; 177 | } 178 | return nil; 179 | }]; 180 | 181 | [[RNCSafeOperationCombined combine:op1 with:op2] exec:address andResolve:resolve orReject:reject]; 182 | } 183 | 184 | RCT_EXPORT_METHOD(spend:(nonnull NSDictionary *)wallet 185 | withInputs:(nonnull NSArray*)inputs 186 | andOutputs:(nonnull NSArray*)outputs 187 | andChangeAddress:(nonnull NSString*)change 188 | resolver:(RCTPromiseResolveBlock)resolve 189 | rejecter:(RCTPromiseRejectBlock)reject) { 190 | 191 | RNCBaseSafeOperation* op1 = [RNCSafeOperation new:^NSDictionary*(NSDictionary* params, NSError ** error) { 192 | return @{@"data": [RNCConvert jsonDataFromDictionary:params error:error], 193 | @"ilen": [NSNumber numberWithUnsignedInteger:[params[@"inputs"] count]], 194 | @"olen": [NSNumber numberWithUnsignedInteger:[params[@"outputs"] count]]}; 195 | }]; 196 | 197 | RNCBaseSafeOperation* op2 = [RNCCSafeOperation new:^NSDictionary*(NSDictionary* params, char **error) { 198 | NSData* input = params[@"data"]; 199 | CHECK_NON_NULL_OR_CERROR(params[@"ilen"], *error, "inputs"); 200 | CHECK_NON_NULL_OR_CERROR(params[@"olen"], *error, "outputs"); 201 | NSUInteger ilen = [params[@"ilen"] unsignedIntegerValue]; 202 | NSUInteger olen = [params[@"olen"] unsignedIntegerValue]; 203 | NSUInteger OUTPUT_SIZE = (ilen + olen + 1) * 65536 + 1024; // 64kb per address + metadata 204 | NSMutableData* output = [NSMutableData dataWithLength:OUTPUT_SIZE]; 205 | int32_t rsz = xwallet_spend_safe([input bytes], 206 | [input length], 207 | [output mutableBytes], 208 | error); 209 | return @{@"size": [NSNumber numberWithInteger:rsz], @"output": output}; 210 | }]; 211 | 212 | RNCBaseSafeOperation *op3 = [RNCSafeOperation new:^NSDictionary*(NSDictionary* params, NSError **error) { 213 | NSInteger rsz = [params[@"size"] integerValue]; 214 | if (rsz > 0) { 215 | NSDictionary* res = [RNCConvert dictionaryResponseFromJsonData:[params[@"output"] subdataWithRange:NSMakeRange(0, rsz)] error:error]; 216 | if (*error == nil) { 217 | NSMutableDictionary* fixed = [res mutableCopy]; 218 | fixed[@"cbor_encoded_tx"] = [RNCConvert encodedStringFromData:[RNCConvert dataFromByteArray:res[@"cbor_encoded_tx"]]]; 219 | return fixed; 220 | } 221 | return res; 222 | } else { 223 | *error = [NSError rustError:[NSString stringWithFormat: @"Wrong response size: %li", (long)rsz]]; 224 | } 225 | return nil; 226 | }]; 227 | 228 | NSMutableDictionary* params = [NSMutableDictionary new]; 229 | [params setObject:wallet forKey:@"wallet"]; 230 | [params setObject:inputs forKey:@"inputs"]; 231 | [params setObject:outputs forKey:@"outputs"]; 232 | [params setObject:change forKey:@"change_addr"]; 233 | 234 | [[RNCSafeOperationCombined combine:[RNCSafeOperationCombined combine:op1 with:op2] with:op3] exec:params andResolve:resolve orReject:reject]; 235 | } 236 | 237 | RCT_EXPORT_METHOD(move:(nonnull NSDictionary *)wallet 238 | withInputs:(nonnull NSArray*)inputs 239 | andOutput:(nonnull NSString*)output 240 | resolver:(RCTPromiseResolveBlock)resolve 241 | rejecter:(RCTPromiseRejectBlock)reject) { 242 | 243 | RNCBaseSafeOperation* op1 = [RNCSafeOperation new:^NSDictionary*(NSDictionary* params, NSError ** error) { 244 | return @{@"data": [RNCConvert jsonDataFromDictionary:params error:error], 245 | @"ilen": [NSNumber numberWithUnsignedInteger:[params[@"inputs"] count]]}; 246 | }]; 247 | 248 | RNCBaseSafeOperation* op2 = [RNCCSafeOperation new:^NSDictionary*(NSDictionary* params, char **error) { 249 | NSData* input = params[@"data"]; 250 | CHECK_NON_NULL_OR_CERROR(params[@"ilen"], *error, "inputs"); 251 | NSUInteger ilen = [params[@"ilen"] unsignedIntegerValue]; 252 | NSUInteger OUTPUT_SIZE = (ilen + 1) * 65536 + 1024; 253 | NSMutableData* output = [NSMutableData dataWithLength:OUTPUT_SIZE]; 254 | int32_t rsz = xwallet_move_safe([input bytes], 255 | [input length], 256 | [output mutableBytes], 257 | error); 258 | return @{@"size": [NSNumber numberWithInteger:rsz], @"output": output}; 259 | }]; 260 | 261 | RNCBaseSafeOperation *op3 = [RNCSafeOperation new:^NSDictionary*(NSDictionary* params, NSError **error) { 262 | NSInteger rsz = [params[@"size"] integerValue]; 263 | if (rsz > 0) { 264 | NSDictionary* res = [RNCConvert dictionaryResponseFromJsonData:[params[@"output"] subdataWithRange:NSMakeRange(0, rsz)] error:error]; 265 | if (*error == nil) { 266 | NSMutableDictionary* fixed = [res mutableCopy]; 267 | fixed[@"cbor_encoded_tx"] = [RNCConvert encodedStringFromData:[RNCConvert dataFromByteArray:res[@"cbor_encoded_tx"]]]; 268 | return fixed; 269 | } 270 | return res; 271 | } else { 272 | *error = [NSError rustError:[NSString stringWithFormat: @"Wrong response size: %li", (long)rsz]]; 273 | } 274 | return nil; 275 | }]; 276 | 277 | NSMutableDictionary* params = [NSMutableDictionary new]; 278 | [params setObject:wallet forKey:@"wallet"]; 279 | [params setObject:inputs forKey:@"inputs"]; 280 | [params setObject:output forKey:@"output"]; 281 | 282 | [[RNCSafeOperationCombined combine:[RNCSafeOperationCombined combine:op1 with:op2] with:op3] exec:params andResolve:resolve orReject:reject]; 283 | } 284 | 285 | @end 286 | -------------------------------------------------------------------------------- /rust/src/android.rs: -------------------------------------------------------------------------------- 1 | use wallet_wasm::*; 2 | use common::*; 3 | use constants::*; 4 | 5 | use std::str; 6 | use std::cmp; 7 | 8 | // This is the interface to the JVM that we'll 9 | // call the majority of our methods on. 10 | use jni::JNIEnv; 11 | 12 | // These objects are what you should use as arguments to your native function. 13 | // They carry extra lifetime information to prevent them escaping this context 14 | // and getting used after being GC'd. 15 | use jni::objects::{JObject, JString}; 16 | 17 | // This is just a pointer. We'll be returning it from our function. 18 | // We can't return one of the objects with lifetime information because the 19 | // lifetime checker won't let us. 20 | use jni::sys::{jbyteArray, jobject, jint}; 21 | 22 | fn json_string_to_object<'a>(env: &'a JNIEnv, data: &[u8]) -> JObject<'a> { 23 | let class = env.find_class("org/json/JSONObject").unwrap(); 24 | let string = str::from_utf8(data).unwrap(); 25 | let json = *env.new_string(string).expect("Couldn't create java string!"); 26 | env.new_object(class, "(Ljava/lang/String;)V", &[json.into()]).unwrap() 27 | } 28 | 29 | fn json_object_to_string(env: &JNIEnv, obj: JObject) -> String { 30 | let jstr = env.call_method(obj, "toString", "()Ljava/lang/String;", &[]).unwrap().l().unwrap(); 31 | env.get_string(jstr.into()).expect("Couldn't get java string!").into() 32 | } 33 | 34 | fn return_result<'a>(env: &'a JNIEnv, res: Result, String>) -> jobject { 35 | let class = env.find_class("io/crossroad/rncardano/Result").unwrap(); 36 | static METHOD: &str = "(Ljava/lang/Object;Ljava/lang/String;)V"; 37 | match res { 38 | Ok(res) => env.new_object(class, METHOD, &[res.into(), JObject::null().into()]).unwrap().into_inner(), 39 | Err(error) => { 40 | let jstr = *env.new_string(error).expect("Couldn't create java string!"); 41 | env.new_object(class, METHOD, &[JObject::null().into(), jstr.into()]).unwrap().into_inner() 42 | } 43 | } 44 | } 45 | 46 | #[allow(non_snake_case)] 47 | #[no_mangle] 48 | pub extern fn Java_io_crossroad_rncardano_Native_initLibrary(_env: JNIEnv, _: JObject) { 49 | hide_exceptions(); 50 | } 51 | 52 | #[allow(non_snake_case)] 53 | #[no_mangle] 54 | pub extern fn Java_io_crossroad_rncardano_Native_hdWalletFromEnhancedEntropy( 55 | env: JNIEnv, _: JObject, entropy: jbyteArray, password: jbyteArray 56 | ) -> jobject { 57 | return_result(&env, handle_exception(|| { 58 | let input = env.convert_byte_array(entropy).unwrap(); 59 | let pwd = env.convert_byte_array(password).unwrap(); 60 | let mut output = [0 as u8; XPRV_SIZE]; 61 | 62 | let res = wallet_from_enhanced_entropy(input.as_ptr(), input.len(), pwd.as_ptr(), pwd.len(), output.as_mut_ptr()); 63 | 64 | if res != 0 { panic!("Rust method error. Check entropy size.") } 65 | 66 | JObject::from(env.byte_array_from_slice(&output).unwrap()) 67 | }) 68 | ) 69 | } 70 | 71 | 72 | #[allow(non_snake_case)] 73 | #[no_mangle] 74 | pub extern fn Java_io_crossroad_rncardano_Native_hdWalletFromSeed( 75 | env: JNIEnv, _: JObject, seed: jbyteArray 76 | ) -> jobject { 77 | return_result(&env, handle_exception(|| { 78 | let input = env.convert_byte_array(seed).unwrap(); 79 | 80 | if input.len() != SEED_SIZE { 81 | panic!("Wrong seed len {} should be {}", input.len(), SEED_SIZE); 82 | } 83 | 84 | let mut output = [0 as u8; XPRV_SIZE]; 85 | 86 | wallet_from_seed(input.as_ptr(), output.as_mut_ptr()); 87 | 88 | JObject::from(env.byte_array_from_slice(&output).unwrap()) 89 | }) 90 | ) 91 | } 92 | 93 | #[allow(non_snake_case)] 94 | #[no_mangle] 95 | pub extern fn Java_io_crossroad_rncardano_Native_hdWalletToPublic( 96 | env: JNIEnv, _: JObject, pkey: jbyteArray 97 | ) -> jobject { 98 | return_result(&env, handle_exception(|| { 99 | let input = env.convert_byte_array(pkey).unwrap(); 100 | 101 | if input.len() != XPRV_SIZE { 102 | panic!("Wrong XPrv len {} should be {}", input.len(), XPRV_SIZE); 103 | } 104 | 105 | let mut output = [0 as u8; XPUB_SIZE]; 106 | 107 | wallet_to_public(input.as_ptr(), output.as_mut_ptr()); 108 | 109 | JObject::from(env.byte_array_from_slice(&output).unwrap()) 110 | }) 111 | ) 112 | } 113 | 114 | #[allow(non_snake_case)] 115 | #[no_mangle] 116 | pub extern fn Java_io_crossroad_rncardano_Native_hdWalletDerivePrivate( 117 | env: JNIEnv, _: JObject, pkey: jbyteArray, index: jint 118 | ) -> jobject { 119 | return_result(&env, handle_exception(|| { 120 | let input = env.convert_byte_array(pkey).unwrap(); 121 | 122 | if input.len() != XPRV_SIZE { 123 | panic!("Wrong XPrv len {} should be {}", input.len(), XPRV_SIZE); 124 | } 125 | 126 | let mut output = [0 as u8; XPRV_SIZE]; 127 | 128 | wallet_derive_private(input.as_ptr(), index as u32, output.as_mut_ptr()); 129 | 130 | JObject::from(env.byte_array_from_slice(&output).unwrap()) 131 | }) 132 | ) 133 | } 134 | 135 | #[allow(non_snake_case)] 136 | #[no_mangle] 137 | pub extern fn Java_io_crossroad_rncardano_Native_hdWalletDerivePublic( 138 | env: JNIEnv, _: JObject, pubKey: jbyteArray, index: jint 139 | ) -> jobject { 140 | return_result(&env, handle_exception(|| { 141 | let input = env.convert_byte_array(pubKey).unwrap(); 142 | 143 | if input.len() != XPUB_SIZE { 144 | panic!("Wrong XPub len {} should be {}", input.len(), XPUB_SIZE); 145 | } 146 | 147 | if (index as u32) >= 0x80000000 { 148 | panic!("Cannot do public derivation with hard index"); 149 | } 150 | 151 | let mut output = [0 as u8; XPUB_SIZE]; 152 | 153 | let res = wallet_derive_public(input.as_ptr(), index as u32, output.as_mut_ptr()); 154 | 155 | if !res { 156 | panic!("Can't derive public key"); 157 | } 158 | 159 | JObject::from(env.byte_array_from_slice(&output).unwrap()) 160 | }) 161 | ) 162 | } 163 | 164 | #[allow(non_snake_case)] 165 | #[no_mangle] 166 | pub extern fn Java_io_crossroad_rncardano_Native_hdWalletSign( 167 | env: JNIEnv, _: JObject, pkey: jbyteArray, data: jbyteArray 168 | ) -> jobject { 169 | return_result(&env, handle_exception(|| { 170 | let xprv = env.convert_byte_array(pkey).unwrap(); 171 | 172 | if xprv.len() != XPRV_SIZE { 173 | panic!("Wrong XPrv len {} should be {}", xprv.len(), XPRV_SIZE); 174 | } 175 | 176 | let input = env.convert_byte_array(data).unwrap(); 177 | let mut output = [0 as u8; SIGNATURE_SIZE]; 178 | 179 | wallet_sign(xprv.as_ptr(), input.as_ptr(), input.len(), output.as_mut_ptr()); 180 | 181 | JObject::from(env.byte_array_from_slice(&output).unwrap()) 182 | }) 183 | ) 184 | } 185 | 186 | #[allow(non_snake_case)] 187 | #[no_mangle] 188 | pub extern fn Java_io_crossroad_rncardano_Native_walletFromMasterKey( 189 | env: JNIEnv, _: JObject, bytes: jbyteArray 190 | ) -> jobject { 191 | return_result(&env, handle_exception(|| { 192 | let input = env.convert_byte_array(bytes).unwrap(); 193 | let mut output = [0 as u8; MAX_OUTPUT_SIZE]; 194 | 195 | let rsz = xwallet_from_master_key(input.as_ptr(), output.as_mut_ptr()); 196 | 197 | if rsz <= 0 { panic!("Response {} <= 0", rsz); } 198 | 199 | json_string_to_object(&env, &output[0..(rsz as usize)]) 200 | })) 201 | } 202 | 203 | #[allow(non_snake_case)] 204 | #[no_mangle] 205 | pub extern fn Java_io_crossroad_rncardano_Native_walletFromDaedalusMnemonic( 206 | env: JNIEnv, _: JObject, mnemonics: JString 207 | ) -> jobject { 208 | return_result(&env, handle_exception(|| { 209 | let mstr: String = env.get_string(mnemonics).expect("Couldn't get java string!").into(); 210 | let input: &[u8] = mstr.as_bytes(); 211 | let mut output = [0 as u8; MAX_OUTPUT_SIZE]; 212 | 213 | let rsz = xwallet_create_daedalus_mnemonic(input.as_ptr(), input.len(), output.as_mut_ptr()); 214 | 215 | if rsz <= 0 { panic!("Response {} <= 0", rsz); } 216 | 217 | json_string_to_object(&env, &output[0..(rsz as usize)]) 218 | })) 219 | } 220 | 221 | #[allow(non_snake_case)] 222 | #[no_mangle] 223 | pub extern fn Java_io_crossroad_rncardano_Native_walletNewAccount( 224 | env: JNIEnv, _: JObject, params: JObject 225 | ) -> jobject { 226 | return_result(&env, handle_exception(|| { 227 | let string = json_object_to_string(&env, params); 228 | let input = string.as_bytes(); 229 | let mut output = [0 as u8; MAX_OUTPUT_SIZE]; 230 | 231 | let rsz = xwallet_account(input.as_ptr(), input.len(), output.as_mut_ptr()); 232 | 233 | if rsz <= 0 { panic!("Response {} <= 0", rsz); } 234 | 235 | json_string_to_object(&env, &output[0..(rsz as usize)]) 236 | })) 237 | } 238 | 239 | #[allow(non_snake_case)] 240 | #[no_mangle] 241 | pub extern fn Java_io_crossroad_rncardano_Native_walletGenerateAddresses( 242 | env: JNIEnv, _: JObject, params: JObject, alen: jint 243 | ) -> jobject { 244 | return_result(&env, handle_exception(|| { 245 | let string = json_object_to_string(&env, params); 246 | let input = string.as_bytes(); 247 | 248 | let output_max = 131 * (alen as usize) + 2; // (128 + 3 for meta) per addr + 2 249 | let mut output: Vec = Vec::new(); 250 | output.resize(output_max, 0); 251 | 252 | let rsz = xwallet_addresses(input.as_ptr(), input.len(), output.as_mut_ptr()); 253 | 254 | if rsz <= 0 { panic!("Response {} <= 0", rsz); } 255 | 256 | json_string_to_object(&env, &output[0..(rsz as usize)]) 257 | })) 258 | } 259 | 260 | #[allow(non_snake_case)] 261 | #[no_mangle] 262 | pub extern fn Java_io_crossroad_rncardano_Native_walletCheckAddress( 263 | env: JNIEnv, _: JObject, address: JString 264 | ) -> jobject { 265 | return_result(&env, handle_exception(|| { 266 | let addr_str: String = env.get_string(address).expect("Couldn't get java string!").into(); 267 | let fixed_addr = convert_address_base58(&addr_str); 268 | let addr: &[u8] = fixed_addr.as_bytes(); 269 | 270 | let mut output = [0 as u8; MAX_OUTPUT_SIZE]; 271 | 272 | let rsz = xwallet_checkaddress(addr.as_ptr(), addr.len(), output.as_mut_ptr()); 273 | 274 | if rsz <= 0 { panic!("Response {} <= 0", rsz); } 275 | 276 | json_string_to_object(&env, &output[0..(rsz as usize)]) 277 | })) 278 | } 279 | 280 | #[allow(non_snake_case)] 281 | #[no_mangle] 282 | pub extern fn Java_io_crossroad_rncardano_Native_walletSpend( 283 | env: JNIEnv, _: JObject, params: JObject, ilen: jint, olen: jint 284 | ) -> jobject { 285 | return_result(&env, handle_exception(|| { 286 | let string = json_object_to_string(&env, params); 287 | let input = string.as_bytes(); 288 | 289 | let OUTPUT_SIZE = ((ilen as usize) + (olen as usize) + 1) * 65536 + 1024; 290 | let mut output: Vec = Vec::new(); 291 | output.resize(OUTPUT_SIZE, 0); 292 | 293 | let rsz = xwallet_spend(input.as_ptr(), input.len(), output.as_mut_ptr()); 294 | 295 | if rsz <= 0 { panic!("Response {} <= 0", rsz); } 296 | 297 | json_string_to_object(&env, &output[0..(rsz as usize)]) 298 | })) 299 | } 300 | 301 | #[allow(non_snake_case)] 302 | #[no_mangle] 303 | pub extern fn Java_io_crossroad_rncardano_Native_walletMove( 304 | env: JNIEnv, _: JObject, params: JObject, ilen: jint 305 | ) -> jobject { 306 | return_result(&env, handle_exception(|| { 307 | let string = json_object_to_string(&env, params); 308 | let input = string.as_bytes(); 309 | 310 | let OUTPUT_SIZE = ((ilen as usize) + 1) * 65536 + 1024; 311 | let mut output: Vec = Vec::new(); 312 | output.resize(OUTPUT_SIZE, 0); 313 | 314 | let rsz = xwallet_move(input.as_ptr(), input.len(), output.as_mut_ptr()); 315 | 316 | if rsz <= 0 { panic!("Response {} <= 0", rsz); } 317 | 318 | json_string_to_object(&env, &output[0..(rsz as usize)]) 319 | })) 320 | } 321 | 322 | #[allow(non_snake_case)] 323 | #[no_mangle] 324 | pub extern fn Java_io_crossroad_rncardano_Native_randomAddressCheckerNewChecker( 325 | env: JNIEnv, _: JObject, pkey: JString 326 | ) -> jobject { 327 | return_result(&env, handle_exception(|| { 328 | let string: String = env.get_string(pkey).expect("Couldn't get java string!").into(); 329 | let input: &[u8] = string.as_bytes(); 330 | let mut output = [0 as u8; MAX_OUTPUT_SIZE]; 331 | 332 | let rsz = random_address_checker_new(input.as_ptr(), input.len(), output.as_mut_ptr()); 333 | 334 | if rsz <= 0 { panic!("Response {} <= 0", rsz); } 335 | 336 | json_string_to_object(&env, &output[0..(rsz as usize)]) 337 | })) 338 | } 339 | 340 | #[allow(non_snake_case)] 341 | #[no_mangle] 342 | pub extern fn Java_io_crossroad_rncardano_Native_randomAddressCheckerNewCheckerFromMnemonics( 343 | env: JNIEnv, _: JObject, mnemonics: JString 344 | ) -> jobject { 345 | return_result(&env, handle_exception(|| { 346 | let string: String = env.get_string(mnemonics).expect("Couldn't get java string!").into(); 347 | let input: &[u8] = string.as_bytes(); 348 | let mut output = [0 as u8; MAX_OUTPUT_SIZE]; 349 | 350 | let rsz = random_address_checker_from_mnemonics(input.as_ptr(), input.len(), output.as_mut_ptr()); 351 | 352 | if rsz <= 0 { panic!("Response {} <= 0", rsz); } 353 | 354 | json_string_to_object(&env, &output[0..(rsz as usize)]) 355 | })) 356 | } 357 | 358 | #[allow(non_snake_case)] 359 | #[no_mangle] 360 | pub extern fn Java_io_crossroad_rncardano_Native_randomAddressCheckerCheckAddresses( 361 | env: JNIEnv, _: JObject, params: JObject 362 | ) -> jobject { 363 | return_result(&env, handle_exception(|| { 364 | let string = json_object_to_string(&env, params); 365 | let input = string.as_bytes(); 366 | 367 | let OUTPUT_SIZE = cmp::max(input.len(), MAX_OUTPUT_SIZE); 368 | let mut output: Vec = Vec::new(); 369 | output.resize(OUTPUT_SIZE, 0); 370 | 371 | let rsz = random_address_check(input.as_ptr(), input.len(), output.as_mut_ptr()); 372 | 373 | if rsz <= 0 { panic!("Response {} <= 0", rsz); } 374 | 375 | json_string_to_object(&env, &output[0..(rsz as usize)]) 376 | })) 377 | } 378 | 379 | #[allow(non_snake_case)] 380 | #[no_mangle] 381 | pub extern fn Java_io_crossroad_rncardano_Native_passwordProtectEncryptWithPassword( 382 | env: JNIEnv, _: JObject, password: jbyteArray, salt: jbyteArray, nonce: jbyteArray, data: jbyteArray 383 | ) -> jobject { 384 | return_result(&env, handle_exception(|| { 385 | let nsalt = env.convert_byte_array(salt).unwrap(); 386 | let nnonce = env.convert_byte_array(nonce).unwrap(); 387 | 388 | if nsalt.len() != SALT_SIZE { panic!("Wrong salt len {} should be {}", nsalt.len(), SALT_SIZE); } 389 | if nnonce.len() != NONCE_SIZE { panic!("Wrong nonce len {} should be {}", nnonce.len(), NONCE_SIZE) } 390 | 391 | let ndata = env.convert_byte_array(data).unwrap(); 392 | let pwd = env.convert_byte_array(password).unwrap(); 393 | 394 | if pwd.len() == 0 { panic!("Password can't be empty"); } 395 | 396 | let result_size = ndata.len() + TAG_SIZE + NONCE_SIZE + SALT_SIZE; 397 | 398 | let mut output: Vec = Vec::new(); 399 | output.resize(result_size, 0); 400 | 401 | let rsz = encrypt_with_password( 402 | pwd.as_ptr(), pwd.len(), nsalt.as_ptr(), nnonce.as_ptr(), ndata.as_ptr(), ndata.len(), 403 | output.as_mut_ptr() 404 | ) as usize; 405 | 406 | if rsz != result_size { panic!("Size mismatch {} should be {}", rsz, result_size) } 407 | 408 | JObject::from(env.byte_array_from_slice(output.as_slice()).unwrap()) 409 | })) 410 | } 411 | 412 | #[allow(non_snake_case)] 413 | #[no_mangle] 414 | pub extern fn Java_io_crossroad_rncardano_Native_passwordProtectDecryptWithPassword( 415 | env: JNIEnv, _: JObject, password: jbyteArray, data: jbyteArray 416 | ) -> jobject { 417 | return_result(&env, handle_exception(|| { 418 | let ndata = env.convert_byte_array(data).unwrap(); 419 | 420 | if ndata.len() <= TAG_SIZE + NONCE_SIZE + SALT_SIZE { 421 | panic!("Wrong data len {} should be at least {}", ndata.len(), TAG_SIZE + NONCE_SIZE + SALT_SIZE + 1); 422 | } 423 | 424 | let pwd = env.convert_byte_array(password).unwrap(); 425 | 426 | if pwd.len() == 0 { panic!("Password can't be empty"); } 427 | 428 | let result_size = ndata.len() - TAG_SIZE - NONCE_SIZE - SALT_SIZE; 429 | 430 | let mut output: Vec = Vec::new(); 431 | output.resize(result_size, 0); 432 | 433 | let rsz = decrypt_with_password( 434 | pwd.as_ptr(), pwd.len(), ndata.as_ptr(), ndata.len(), 435 | output.as_mut_ptr() 436 | ); 437 | 438 | if rsz <= 0 { panic!("Decryption failed. Check your password.") } 439 | if rsz as usize != result_size { panic!("Size mismatch {} should be {}", rsz, result_size) } 440 | 441 | JObject::from(env.byte_array_from_slice(output.as_slice()).unwrap()) 442 | })) 443 | } 444 | -------------------------------------------------------------------------------- /rust/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "ascii" 5 | version = "0.7.1" 6 | source = "registry+https://github.com/rust-lang/crates.io-index" 7 | 8 | [[package]] 9 | name = "backtrace" 10 | version = "0.3.9" 11 | source = "registry+https://github.com/rust-lang/crates.io-index" 12 | dependencies = [ 13 | "backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", 14 | "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 15 | "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", 16 | "rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", 17 | "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 18 | ] 19 | 20 | [[package]] 21 | name = "backtrace-sys" 22 | version = "0.1.24" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | dependencies = [ 25 | "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", 26 | "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", 27 | ] 28 | 29 | [[package]] 30 | name = "byteorder" 31 | version = "1.2.6" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | 34 | [[package]] 35 | name = "cardano" 36 | version = "0.1.1" 37 | source = "git+https://github.com/input-output-hk/js-cardano-wasm.git#863f712baf631d352097370b645d91033194c11d" 38 | dependencies = [ 39 | "cbor_event 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", 40 | "chain-core 0.1.0 (git+https://github.com/input-output-hk/js-cardano-wasm.git)", 41 | "cryptoxide 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 42 | "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", 43 | "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", 44 | ] 45 | 46 | [[package]] 47 | name = "cbor_event" 48 | version = "2.1.3" 49 | source = "registry+https://github.com/rust-lang/crates.io-index" 50 | 51 | [[package]] 52 | name = "cc" 53 | version = "1.0.25" 54 | source = "registry+https://github.com/rust-lang/crates.io-index" 55 | 56 | [[package]] 57 | name = "cesu8" 58 | version = "1.1.0" 59 | source = "registry+https://github.com/rust-lang/crates.io-index" 60 | 61 | [[package]] 62 | name = "cfg-if" 63 | version = "0.1.5" 64 | source = "registry+https://github.com/rust-lang/crates.io-index" 65 | 66 | [[package]] 67 | name = "chain-core" 68 | version = "0.1.0" 69 | source = "git+https://github.com/input-output-hk/js-cardano-wasm.git#863f712baf631d352097370b645d91033194c11d" 70 | dependencies = [ 71 | "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 72 | ] 73 | 74 | [[package]] 75 | name = "combine" 76 | version = "3.6.1" 77 | source = "registry+https://github.com/rust-lang/crates.io-index" 78 | dependencies = [ 79 | "ascii 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", 80 | "byteorder 1.2.6 (registry+https://github.com/rust-lang/crates.io-index)", 81 | "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", 82 | "memchr 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 83 | "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 84 | ] 85 | 86 | [[package]] 87 | name = "cryptoxide" 88 | version = "0.1.0" 89 | source = "registry+https://github.com/rust-lang/crates.io-index" 90 | 91 | [[package]] 92 | name = "either" 93 | version = "1.5.0" 94 | source = "registry+https://github.com/rust-lang/crates.io-index" 95 | 96 | [[package]] 97 | name = "error-chain" 98 | version = "0.12.0" 99 | source = "registry+https://github.com/rust-lang/crates.io-index" 100 | dependencies = [ 101 | "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", 102 | ] 103 | 104 | [[package]] 105 | name = "itoa" 106 | version = "0.4.3" 107 | source = "registry+https://github.com/rust-lang/crates.io-index" 108 | 109 | [[package]] 110 | name = "jni" 111 | version = "0.10.2" 112 | source = "registry+https://github.com/rust-lang/crates.io-index" 113 | dependencies = [ 114 | "cesu8 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 115 | "combine 3.6.1 (registry+https://github.com/rust-lang/crates.io-index)", 116 | "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", 117 | "jni-sys 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 118 | "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", 119 | "walkdir 2.2.5 (registry+https://github.com/rust-lang/crates.io-index)", 120 | ] 121 | 122 | [[package]] 123 | name = "jni-sys" 124 | version = "0.3.0" 125 | source = "registry+https://github.com/rust-lang/crates.io-index" 126 | 127 | [[package]] 128 | name = "libc" 129 | version = "0.2.43" 130 | source = "registry+https://github.com/rust-lang/crates.io-index" 131 | 132 | [[package]] 133 | name = "log" 134 | version = "0.4.5" 135 | source = "registry+https://github.com/rust-lang/crates.io-index" 136 | dependencies = [ 137 | "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 138 | ] 139 | 140 | [[package]] 141 | name = "memchr" 142 | version = "2.1.0" 143 | source = "registry+https://github.com/rust-lang/crates.io-index" 144 | dependencies = [ 145 | "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 146 | "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", 147 | "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 148 | ] 149 | 150 | [[package]] 151 | name = "proc-macro2" 152 | version = "0.4.20" 153 | source = "registry+https://github.com/rust-lang/crates.io-index" 154 | dependencies = [ 155 | "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 156 | ] 157 | 158 | [[package]] 159 | name = "quote" 160 | version = "0.6.8" 161 | source = "registry+https://github.com/rust-lang/crates.io-index" 162 | dependencies = [ 163 | "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", 164 | ] 165 | 166 | [[package]] 167 | name = "rust_native_cardano" 168 | version = "0.1.0" 169 | dependencies = [ 170 | "cardano 0.1.1 (git+https://github.com/input-output-hk/js-cardano-wasm.git)", 171 | "jni 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", 172 | "wallet-wasm 0.1.0 (git+https://github.com/input-output-hk/js-cardano-wasm.git)", 173 | ] 174 | 175 | [[package]] 176 | name = "rustc-demangle" 177 | version = "0.1.9" 178 | source = "registry+https://github.com/rust-lang/crates.io-index" 179 | 180 | [[package]] 181 | name = "ryu" 182 | version = "0.2.6" 183 | source = "registry+https://github.com/rust-lang/crates.io-index" 184 | 185 | [[package]] 186 | name = "same-file" 187 | version = "1.0.3" 188 | source = "registry+https://github.com/rust-lang/crates.io-index" 189 | dependencies = [ 190 | "winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 191 | ] 192 | 193 | [[package]] 194 | name = "serde" 195 | version = "1.0.80" 196 | source = "registry+https://github.com/rust-lang/crates.io-index" 197 | 198 | [[package]] 199 | name = "serde_derive" 200 | version = "1.0.80" 201 | source = "registry+https://github.com/rust-lang/crates.io-index" 202 | dependencies = [ 203 | "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", 204 | "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", 205 | "syn 0.15.12 (registry+https://github.com/rust-lang/crates.io-index)", 206 | ] 207 | 208 | [[package]] 209 | name = "serde_json" 210 | version = "1.0.32" 211 | source = "registry+https://github.com/rust-lang/crates.io-index" 212 | dependencies = [ 213 | "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", 214 | "ryu 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", 215 | "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", 216 | ] 217 | 218 | [[package]] 219 | name = "syn" 220 | version = "0.15.12" 221 | source = "registry+https://github.com/rust-lang/crates.io-index" 222 | dependencies = [ 223 | "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", 224 | "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", 225 | "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 226 | ] 227 | 228 | [[package]] 229 | name = "unicode-xid" 230 | version = "0.1.0" 231 | source = "registry+https://github.com/rust-lang/crates.io-index" 232 | 233 | [[package]] 234 | name = "unreachable" 235 | version = "1.0.0" 236 | source = "registry+https://github.com/rust-lang/crates.io-index" 237 | dependencies = [ 238 | "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 239 | ] 240 | 241 | [[package]] 242 | name = "version_check" 243 | version = "0.1.5" 244 | source = "registry+https://github.com/rust-lang/crates.io-index" 245 | 246 | [[package]] 247 | name = "void" 248 | version = "1.0.2" 249 | source = "registry+https://github.com/rust-lang/crates.io-index" 250 | 251 | [[package]] 252 | name = "walkdir" 253 | version = "2.2.5" 254 | source = "registry+https://github.com/rust-lang/crates.io-index" 255 | dependencies = [ 256 | "same-file 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", 257 | "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 258 | "winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 259 | ] 260 | 261 | [[package]] 262 | name = "wallet-wasm" 263 | version = "0.1.0" 264 | source = "git+https://github.com/input-output-hk/js-cardano-wasm.git#863f712baf631d352097370b645d91033194c11d" 265 | dependencies = [ 266 | "cardano 0.1.1 (git+https://github.com/input-output-hk/js-cardano-wasm.git)", 267 | "cbor_event 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", 268 | "cryptoxide 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 269 | "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", 270 | "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", 271 | "serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", 272 | ] 273 | 274 | [[package]] 275 | name = "winapi" 276 | version = "0.3.6" 277 | source = "registry+https://github.com/rust-lang/crates.io-index" 278 | dependencies = [ 279 | "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 280 | "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 281 | ] 282 | 283 | [[package]] 284 | name = "winapi-i686-pc-windows-gnu" 285 | version = "0.4.0" 286 | source = "registry+https://github.com/rust-lang/crates.io-index" 287 | 288 | [[package]] 289 | name = "winapi-util" 290 | version = "0.1.1" 291 | source = "registry+https://github.com/rust-lang/crates.io-index" 292 | dependencies = [ 293 | "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 294 | ] 295 | 296 | [[package]] 297 | name = "winapi-x86_64-pc-windows-gnu" 298 | version = "0.4.0" 299 | source = "registry+https://github.com/rust-lang/crates.io-index" 300 | 301 | [metadata] 302 | "checksum ascii 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ae7d751998c189c1d4468cf0a39bb2eae052a9c58d50ebb3b9591ee3813ad50" 303 | "checksum backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "89a47830402e9981c5c41223151efcced65a0510c13097c769cede7efb34782a" 304 | "checksum backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c66d56ac8dabd07f6aacdaf633f4b8262f5b3601a810a0dcddffd5c22c69daa0" 305 | "checksum byteorder 1.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "90492c5858dd7d2e78691cfb89f90d273a2800fc11d98f60786e5d87e2f83781" 306 | "checksum cardano 0.1.1 (git+https://github.com/input-output-hk/js-cardano-wasm.git)" = "" 307 | "checksum cbor_event 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2b6cda8a789815488ee290d106bc97dba47785dae73d63576fc42c126912a451" 308 | "checksum cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "f159dfd43363c4d08055a07703eb7a3406b0dac4d0584d96965a3262db3c9d16" 309 | "checksum cesu8 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" 310 | "checksum cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0c4e7bb64a8ebb0d856483e1e682ea3422f883c5f5615a90d51a2c82fe87fdd3" 311 | "checksum chain-core 0.1.0 (git+https://github.com/input-output-hk/js-cardano-wasm.git)" = "" 312 | "checksum combine 3.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fc1d011beeed29187b8db2ac3925c8dd4d3e87db463dc9d2d2833985388fc5bc" 313 | "checksum cryptoxide 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc9be687df90da186ed5c6ada0b6b4d69f5ad914071870bc5d41277377d30427" 314 | "checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" 315 | "checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" 316 | "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" 317 | "checksum jni 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1ecfa3b81afc64d9a6539c4eece96ac9a93c551c713a313800dade8e33d7b5c1" 318 | "checksum jni-sys 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" 319 | "checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d" 320 | "checksum log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fcce5fa49cc693c312001daf1d13411c4a5283796bac1084299ea3e567113f" 321 | "checksum memchr 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4b3629fe9fdbff6daa6c33b90f7c08355c1aca05a3d01fa8063b822fcf185f3b" 322 | "checksum proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)" = "3d7b7eaaa90b4a90a932a9ea6666c95a389e424eff347f0f793979289429feee" 323 | "checksum quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dd636425967c33af890042c483632d33fa7a18f19ad1d7ea72e8998c6ef8dea5" 324 | "checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395" 325 | "checksum ryu 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7153dd96dade874ab973e098cb62fcdbb89a03682e46b144fd09550998d4a4a7" 326 | "checksum same-file 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "10f7794e2fda7f594866840e95f5c5962e886e228e68b6505885811a94dd728c" 327 | "checksum serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)" = "15c141fc7027dd265a47c090bf864cf62b42c4d228bbcf4e51a0c9e2b0d3f7ef" 328 | "checksum serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)" = "225de307c6302bec3898c51ca302fc94a7a1697ef0845fcee6448f33c032249c" 329 | "checksum serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)" = "43344e7ce05d0d8280c5940cabb4964bea626aa58b1ec0e8c73fa2a8512a38ce" 330 | "checksum syn 0.15.12 (registry+https://github.com/rust-lang/crates.io-index)" = "34ab9797e47d24cb76b8dc4d24ff36807018c7cc549c4cba050b068be0c586b0" 331 | "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" 332 | "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" 333 | "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" 334 | "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" 335 | "checksum walkdir 2.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "af464bc7be7b785c7ac72e266a6b67c4c9070155606f51655a650a6686204e35" 336 | "checksum wallet-wasm 0.1.0 (git+https://github.com/input-output-hk/js-cardano-wasm.git)" = "" 337 | "checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" 338 | "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 339 | "checksum winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "afc5508759c5bf4285e61feb862b6083c8480aec864fa17a81fdec6f69b461ab" 340 | "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 341 | -------------------------------------------------------------------------------- /ios/RNCardano.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 92AD5E64217E679F0081DB38 /* RNCRandomAddressChecker.m in Sources */ = {isa = PBXBuildFile; fileRef = 92AD5E63217E679F0081DB38 /* RNCRandomAddressChecker.m */; }; 11 | 92AD5E67217E6CE90081DB38 /* RNCPasswordProtect.m in Sources */ = {isa = PBXBuildFile; fileRef = 92AD5E66217E6CE90081DB38 /* RNCPasswordProtect.m */; }; 12 | 92AD5E6D217E92500081DB38 /* RNCBaseReactModule.m in Sources */ = {isa = PBXBuildFile; fileRef = 92AD5E6C217E92500081DB38 /* RNCBaseReactModule.m */; }; 13 | 92C85A18217CC1F9007703DA /* RNCWallet.m in Sources */ = {isa = PBXBuildFile; fileRef = 92C85A17217CC1F9007703DA /* RNCWallet.m */; }; 14 | 92C85A1B217CC34B007703DA /* RNCHdWallet.m in Sources */ = {isa = PBXBuildFile; fileRef = 92C85A1A217CC34B007703DA /* RNCHdWallet.m */; }; 15 | 92C85A64217CD247007703DA /* RNCConvert.m in Sources */ = {isa = PBXBuildFile; fileRef = 92C85A63217CD247007703DA /* RNCConvert.m */; }; 16 | 92C85A8F217D0111007703DA /* NSData+FastHex.m in Sources */ = {isa = PBXBuildFile; fileRef = 92C85A8D217D0111007703DA /* NSData+FastHex.m */; }; 17 | 92C85A92217D3A29007703DA /* RNCSafeOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 92C85A91217D3A29007703DA /* RNCSafeOperation.m */; }; 18 | /* End PBXBuildFile section */ 19 | 20 | /* Begin PBXCopyFilesBuildPhase section */ 21 | 58B511D91A9E6C8500147676 /* CopyFiles */ = { 22 | isa = PBXCopyFilesBuildPhase; 23 | buildActionMask = 2147483647; 24 | dstPath = "include/$(PRODUCT_NAME)"; 25 | dstSubfolderSpec = 16; 26 | files = ( 27 | ); 28 | runOnlyForDeploymentPostprocessing = 0; 29 | }; 30 | /* End PBXCopyFilesBuildPhase section */ 31 | 32 | /* Begin PBXFileReference section */ 33 | 134814201AA4EA6300B7C361 /* libRNCardano.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNCardano.a; sourceTree = BUILT_PRODUCTS_DIR; }; 34 | 92AD5E62217E679F0081DB38 /* RNCRandomAddressChecker.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNCRandomAddressChecker.h; sourceTree = ""; }; 35 | 92AD5E63217E679F0081DB38 /* RNCRandomAddressChecker.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNCRandomAddressChecker.m; sourceTree = ""; }; 36 | 92AD5E65217E6CE90081DB38 /* RNCPasswordProtect.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNCPasswordProtect.h; sourceTree = ""; }; 37 | 92AD5E66217E6CE90081DB38 /* RNCPasswordProtect.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNCPasswordProtect.m; sourceTree = ""; }; 38 | 92AD5E6B217E92500081DB38 /* RNCBaseReactModule.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNCBaseReactModule.h; sourceTree = ""; }; 39 | 92AD5E6C217E92500081DB38 /* RNCBaseReactModule.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNCBaseReactModule.m; sourceTree = ""; }; 40 | 92C85974217CB381007703DA /* RNCardano.podspec */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = RNCardano.podspec; sourceTree = ""; }; 41 | 92C85A16217CC1F9007703DA /* RNCWallet.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNCWallet.h; sourceTree = ""; }; 42 | 92C85A17217CC1F9007703DA /* RNCWallet.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNCWallet.m; sourceTree = ""; }; 43 | 92C85A19217CC34B007703DA /* RNCHdWallet.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNCHdWallet.h; sourceTree = ""; }; 44 | 92C85A1A217CC34B007703DA /* RNCHdWallet.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNCHdWallet.m; sourceTree = ""; }; 45 | 92C85A62217CD247007703DA /* RNCConvert.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNCConvert.h; sourceTree = ""; }; 46 | 92C85A63217CD247007703DA /* RNCConvert.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNCConvert.m; sourceTree = ""; }; 47 | 92C85A8C217CF140007703DA /* rust */ = {isa = PBXFileReference; lastKnownFileType = folder; path = rust; sourceTree = ""; }; 48 | 92C85A8D217D0111007703DA /* NSData+FastHex.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSData+FastHex.m"; sourceTree = ""; }; 49 | 92C85A8E217D0111007703DA /* NSData+FastHex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSData+FastHex.h"; sourceTree = ""; }; 50 | 92C85A90217D3A29007703DA /* RNCSafeOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNCSafeOperation.h; sourceTree = ""; }; 51 | 92C85A91217D3A29007703DA /* RNCSafeOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNCSafeOperation.m; sourceTree = ""; }; 52 | /* End PBXFileReference section */ 53 | 54 | /* Begin PBXFrameworksBuildPhase section */ 55 | 58B511D81A9E6C8500147676 /* Frameworks */ = { 56 | isa = PBXFrameworksBuildPhase; 57 | buildActionMask = 2147483647; 58 | files = ( 59 | ); 60 | runOnlyForDeploymentPostprocessing = 0; 61 | }; 62 | /* End PBXFrameworksBuildPhase section */ 63 | 64 | /* Begin PBXGroup section */ 65 | 134814211AA4EA7D00B7C361 /* Products */ = { 66 | isa = PBXGroup; 67 | children = ( 68 | 134814201AA4EA6300B7C361 /* libRNCardano.a */, 69 | ); 70 | name = Products; 71 | sourceTree = ""; 72 | }; 73 | 58B511D21A9E6C8500147676 = { 74 | isa = PBXGroup; 75 | children = ( 76 | 92AD5E68217E7B4B0081DB38 /* Utils */, 77 | 92AD5E65217E6CE90081DB38 /* RNCPasswordProtect.h */, 78 | 92AD5E66217E6CE90081DB38 /* RNCPasswordProtect.m */, 79 | 92AD5E62217E679F0081DB38 /* RNCRandomAddressChecker.h */, 80 | 92AD5E63217E679F0081DB38 /* RNCRandomAddressChecker.m */, 81 | 92C85A19217CC34B007703DA /* RNCHdWallet.h */, 82 | 92C85A1A217CC34B007703DA /* RNCHdWallet.m */, 83 | 92C85A16217CC1F9007703DA /* RNCWallet.h */, 84 | 92C85A17217CC1F9007703DA /* RNCWallet.m */, 85 | 92C85A8C217CF140007703DA /* rust */, 86 | 134814211AA4EA7D00B7C361 /* Products */, 87 | ); 88 | sourceTree = ""; 89 | }; 90 | 92AD5E68217E7B4B0081DB38 /* Utils */ = { 91 | isa = PBXGroup; 92 | children = ( 93 | 92C85974217CB381007703DA /* RNCardano.podspec */, 94 | 92C85A62217CD247007703DA /* RNCConvert.h */, 95 | 92C85A63217CD247007703DA /* RNCConvert.m */, 96 | 92C85A90217D3A29007703DA /* RNCSafeOperation.h */, 97 | 92C85A91217D3A29007703DA /* RNCSafeOperation.m */, 98 | 92AD5E6B217E92500081DB38 /* RNCBaseReactModule.h */, 99 | 92AD5E6C217E92500081DB38 /* RNCBaseReactModule.m */, 100 | 92C85A8E217D0111007703DA /* NSData+FastHex.h */, 101 | 92C85A8D217D0111007703DA /* NSData+FastHex.m */, 102 | ); 103 | name = Utils; 104 | sourceTree = ""; 105 | }; 106 | /* End PBXGroup section */ 107 | 108 | /* Begin PBXNativeTarget section */ 109 | 58B511DA1A9E6C8500147676 /* RNCardano */ = { 110 | isa = PBXNativeTarget; 111 | buildConfigurationList = 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RNCardano" */; 112 | buildPhases = ( 113 | 92C85A5E217CC9FE007703DA /* ShellScript */, 114 | 58B511D71A9E6C8500147676 /* Sources */, 115 | 58B511D81A9E6C8500147676 /* Frameworks */, 116 | 58B511D91A9E6C8500147676 /* CopyFiles */, 117 | ); 118 | buildRules = ( 119 | ); 120 | dependencies = ( 121 | ); 122 | name = RNCardano; 123 | productName = RCTDataManager; 124 | productReference = 134814201AA4EA6300B7C361 /* libRNCardano.a */; 125 | productType = "com.apple.product-type.library.static"; 126 | }; 127 | /* End PBXNativeTarget section */ 128 | 129 | /* Begin PBXProject section */ 130 | 58B511D31A9E6C8500147676 /* Project object */ = { 131 | isa = PBXProject; 132 | attributes = { 133 | CLASSPREFIX = RNC; 134 | LastUpgradeCheck = 1000; 135 | ORGANIZATIONNAME = "Crossroad Labs s.r.o"; 136 | TargetAttributes = { 137 | 58B511DA1A9E6C8500147676 = { 138 | CreatedOnToolsVersion = 6.1.1; 139 | }; 140 | }; 141 | }; 142 | buildConfigurationList = 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RNCardano" */; 143 | compatibilityVersion = "Xcode 3.2"; 144 | developmentRegion = English; 145 | hasScannedForEncodings = 0; 146 | knownRegions = ( 147 | en, 148 | ); 149 | mainGroup = 58B511D21A9E6C8500147676; 150 | productRefGroup = 58B511D21A9E6C8500147676; 151 | projectDirPath = ""; 152 | projectRoot = ""; 153 | targets = ( 154 | 58B511DA1A9E6C8500147676 /* RNCardano */, 155 | ); 156 | }; 157 | /* End PBXProject section */ 158 | 159 | /* Begin PBXShellScriptBuildPhase section */ 160 | 92C85A5E217CC9FE007703DA /* ShellScript */ = { 161 | isa = PBXShellScriptBuildPhase; 162 | buildActionMask = 2147483647; 163 | files = ( 164 | ); 165 | inputFileListPaths = ( 166 | ); 167 | inputPaths = ( 168 | ); 169 | outputFileListPaths = ( 170 | ); 171 | outputPaths = ( 172 | ); 173 | runOnlyForDeploymentPostprocessing = 0; 174 | shellPath = /bin/sh; 175 | shellScript = "bash \"${SRCROOT}\"/rust/build.sh\n"; 176 | }; 177 | /* End PBXShellScriptBuildPhase section */ 178 | 179 | /* Begin PBXSourcesBuildPhase section */ 180 | 58B511D71A9E6C8500147676 /* Sources */ = { 181 | isa = PBXSourcesBuildPhase; 182 | buildActionMask = 2147483647; 183 | files = ( 184 | 92AD5E67217E6CE90081DB38 /* RNCPasswordProtect.m in Sources */, 185 | 92C85A8F217D0111007703DA /* NSData+FastHex.m in Sources */, 186 | 92C85A1B217CC34B007703DA /* RNCHdWallet.m in Sources */, 187 | 92AD5E6D217E92500081DB38 /* RNCBaseReactModule.m in Sources */, 188 | 92C85A92217D3A29007703DA /* RNCSafeOperation.m in Sources */, 189 | 92AD5E64217E679F0081DB38 /* RNCRandomAddressChecker.m in Sources */, 190 | 92C85A64217CD247007703DA /* RNCConvert.m in Sources */, 191 | 92C85A18217CC1F9007703DA /* RNCWallet.m in Sources */, 192 | ); 193 | runOnlyForDeploymentPostprocessing = 0; 194 | }; 195 | /* End PBXSourcesBuildPhase section */ 196 | 197 | /* Begin XCBuildConfiguration section */ 198 | 58B511ED1A9E6C8500147676 /* Debug */ = { 199 | isa = XCBuildConfiguration; 200 | buildSettings = { 201 | ALWAYS_SEARCH_USER_PATHS = NO; 202 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 203 | CLANG_CXX_LIBRARY = "libc++"; 204 | CLANG_ENABLE_MODULES = YES; 205 | CLANG_ENABLE_OBJC_ARC = YES; 206 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 207 | CLANG_WARN_BOOL_CONVERSION = YES; 208 | CLANG_WARN_COMMA = YES; 209 | CLANG_WARN_CONSTANT_CONVERSION = YES; 210 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 211 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 212 | CLANG_WARN_EMPTY_BODY = YES; 213 | CLANG_WARN_ENUM_CONVERSION = YES; 214 | CLANG_WARN_INFINITE_RECURSION = YES; 215 | CLANG_WARN_INT_CONVERSION = YES; 216 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 217 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 218 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 219 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 220 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 221 | CLANG_WARN_STRICT_PROTOTYPES = YES; 222 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 223 | CLANG_WARN_UNREACHABLE_CODE = YES; 224 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 225 | COPY_PHASE_STRIP = NO; 226 | ENABLE_STRICT_OBJC_MSGSEND = YES; 227 | ENABLE_TESTABILITY = YES; 228 | GCC_C_LANGUAGE_STANDARD = gnu99; 229 | GCC_DYNAMIC_NO_PIC = NO; 230 | GCC_NO_COMMON_BLOCKS = YES; 231 | GCC_OPTIMIZATION_LEVEL = 0; 232 | GCC_PREPROCESSOR_DEFINITIONS = ( 233 | "DEBUG=1", 234 | "$(inherited)", 235 | ); 236 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 237 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 238 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 239 | GCC_WARN_UNDECLARED_SELECTOR = YES; 240 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 241 | GCC_WARN_UNUSED_FUNCTION = YES; 242 | GCC_WARN_UNUSED_VARIABLE = YES; 243 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 244 | MTL_ENABLE_DEBUG_INFO = YES; 245 | ONLY_ACTIVE_ARCH = YES; 246 | SDKROOT = iphoneos; 247 | }; 248 | name = Debug; 249 | }; 250 | 58B511EE1A9E6C8500147676 /* Release */ = { 251 | isa = XCBuildConfiguration; 252 | buildSettings = { 253 | ALWAYS_SEARCH_USER_PATHS = NO; 254 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 255 | CLANG_CXX_LIBRARY = "libc++"; 256 | CLANG_ENABLE_MODULES = YES; 257 | CLANG_ENABLE_OBJC_ARC = YES; 258 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 259 | CLANG_WARN_BOOL_CONVERSION = YES; 260 | CLANG_WARN_COMMA = YES; 261 | CLANG_WARN_CONSTANT_CONVERSION = YES; 262 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 263 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 264 | CLANG_WARN_EMPTY_BODY = YES; 265 | CLANG_WARN_ENUM_CONVERSION = YES; 266 | CLANG_WARN_INFINITE_RECURSION = YES; 267 | CLANG_WARN_INT_CONVERSION = YES; 268 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 269 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 270 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 271 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 272 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 273 | CLANG_WARN_STRICT_PROTOTYPES = YES; 274 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 275 | CLANG_WARN_UNREACHABLE_CODE = YES; 276 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 277 | COPY_PHASE_STRIP = YES; 278 | ENABLE_NS_ASSERTIONS = NO; 279 | ENABLE_STRICT_OBJC_MSGSEND = YES; 280 | GCC_C_LANGUAGE_STANDARD = gnu99; 281 | GCC_NO_COMMON_BLOCKS = YES; 282 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 283 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 284 | GCC_WARN_UNDECLARED_SELECTOR = YES; 285 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 286 | GCC_WARN_UNUSED_FUNCTION = YES; 287 | GCC_WARN_UNUSED_VARIABLE = YES; 288 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 289 | MTL_ENABLE_DEBUG_INFO = NO; 290 | SDKROOT = iphoneos; 291 | VALIDATE_PRODUCT = YES; 292 | }; 293 | name = Release; 294 | }; 295 | 58B511F01A9E6C8500147676 /* Debug */ = { 296 | isa = XCBuildConfiguration; 297 | buildSettings = { 298 | HEADER_SEARCH_PATHS = ( 299 | "$(inherited)", 300 | "$(SRCROOT)/../../../React/**", 301 | "$(SRCROOT)/../../react-native/React/**", 302 | "$(PROJECT_DIR)/rust", 303 | ); 304 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 305 | LIBRARY_SEARCH_PATHS = ( 306 | "$(inherited)", 307 | "$(PROJECT_DIR)/rust", 308 | ); 309 | OTHER_LDFLAGS = ( 310 | "$(inherited)", 311 | "-ObjC", 312 | ); 313 | OTHER_LIBTOOLFLAGS = "-lrust_native_cardano"; 314 | PRODUCT_NAME = RNCardano; 315 | SKIP_INSTALL = YES; 316 | TVOS_DEPLOYMENT_TARGET = 10.0; 317 | }; 318 | name = Debug; 319 | }; 320 | 58B511F11A9E6C8500147676 /* Release */ = { 321 | isa = XCBuildConfiguration; 322 | buildSettings = { 323 | HEADER_SEARCH_PATHS = ( 324 | "$(inherited)", 325 | "$(SRCROOT)/../../../React/**", 326 | "$(SRCROOT)/../../react-native/React/**", 327 | "$(PROJECT_DIR)/rust", 328 | ); 329 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 330 | LIBRARY_SEARCH_PATHS = ( 331 | "$(inherited)", 332 | "$(PROJECT_DIR)/rust", 333 | ); 334 | OTHER_LDFLAGS = ( 335 | "$(inherited)", 336 | "-ObjC", 337 | ); 338 | OTHER_LIBTOOLFLAGS = "-lrust_native_cardano"; 339 | PRODUCT_NAME = RNCardano; 340 | SKIP_INSTALL = YES; 341 | TVOS_DEPLOYMENT_TARGET = 10.0; 342 | }; 343 | name = Release; 344 | }; 345 | /* End XCBuildConfiguration section */ 346 | 347 | /* Begin XCConfigurationList section */ 348 | 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RNCardano" */ = { 349 | isa = XCConfigurationList; 350 | buildConfigurations = ( 351 | 58B511ED1A9E6C8500147676 /* Debug */, 352 | 58B511EE1A9E6C8500147676 /* Release */, 353 | ); 354 | defaultConfigurationIsVisible = 0; 355 | defaultConfigurationName = Release; 356 | }; 357 | 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RNCardano" */ = { 358 | isa = XCConfigurationList; 359 | buildConfigurations = ( 360 | 58B511F01A9E6C8500147676 /* Debug */, 361 | 58B511F11A9E6C8500147676 /* Release */, 362 | ); 363 | defaultConfigurationIsVisible = 0; 364 | defaultConfigurationName = Release; 365 | }; 366 | /* End XCConfigurationList section */ 367 | }; 368 | rootObject = 58B511D31A9E6C8500147676 /* Project object */; 369 | } 370 | --------------------------------------------------------------------------------