{
10 |
11 |
12 | protected GuardedAsyncTask() {
13 | }
14 |
15 | @Override
16 | protected final Void doInBackground(Params... params) {
17 | try {
18 | doInBackgroundGuarded(params);
19 | } catch (RuntimeException e) {
20 | e.printStackTrace();
21 | }
22 | return null;
23 | }
24 |
25 | protected abstract void doInBackgroundGuarded(Params... params);
26 | }
27 |
--------------------------------------------------------------------------------
/ios/local-podspec/react-native-navigation.podspec.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-native-navigation",
3 | "version": "1.1.493",
4 | "summary": "React Native Navigation - truly native navigation for iOS and Android",
5 | "homepage": "https://github.com/wix/react-native-navigation",
6 | "license": {
7 | "type": "MIT",
8 | "file": "LICENSE"
9 | },
10 | "authors": {
11 | "Tal Kol": "talkol@gmail.com"
12 | },
13 | "source": {
14 | "git": "https://github.com/wix/react-native-navigation.git",
15 | "tag": "v1.1.493"
16 | },
17 | "platforms": {
18 | "ios": "8.0"
19 | },
20 | "source_files": [
21 | "ios/**/*.{h,m}"
22 | ],
23 | "requires_arc": true,
24 | "dependencies": {
25 | "React": [
26 |
27 | ]
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/android/app/src/main/java/com/renrenbit/rrwallet/service/statistics/UmengAnalyticsAgent.java:
--------------------------------------------------------------------------------
1 | package com.renrenbit.rrwallet.service.statistics;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 |
6 | import com.umeng.analytics.MobclickAgent;
7 |
8 | /**
9 | * Created by jackQ on 2018/8/11.
10 | */
11 |
12 | public class UmengAnalyticsAgent {
13 | public static void init(Context context) {
14 | MobclickAgent.setScenarioType(context, MobclickAgent.EScenarioType.E_UM_NORMAL);
15 | }
16 |
17 | public static void onResume(Activity activity) {
18 | MobclickAgent.onResume(activity);
19 | }
20 |
21 |
22 | public static void onPause(Activity activity) {
23 | MobclickAgent.onPause(activity);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/android/app/src/main/java/com/renrenbit/rrwallet/service/wallet/btc/net/FormalEnv.java:
--------------------------------------------------------------------------------
1 | package com.renrenbit.rrwallet.service.wallet.btc.net;
2 |
3 | import com.renrenbit.rrwallet.service.wallet.CoinType;
4 |
5 | import org.bitcoinj.core.NetworkParameters;
6 | import org.bitcoinj.params.MainNetParams;
7 |
8 |
9 | /**
10 | * Created by jackQ on 2018/7/7.
11 | */
12 |
13 | public class FormalEnv implements BtcEnv {
14 |
15 | @Override
16 | public NetworkParameters getNetParams() {
17 | return MainNetParams.get();
18 | }
19 |
20 | @Override
21 | public String getPath() {
22 | return CoinType.btc.getPath();
23 | }
24 |
25 | @Override
26 | public CoinType getCoinType() {
27 | return CoinType.btc;
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/android/app/src/main/java/com/renrenbit/rrwallet/service/wallet/btc/net/TestEnv.java:
--------------------------------------------------------------------------------
1 | package com.renrenbit.rrwallet.service.wallet.btc.net;
2 |
3 | import com.renrenbit.rrwallet.service.wallet.CoinType;
4 |
5 | import org.bitcoinj.core.NetworkParameters;
6 | import org.bitcoinj.params.TestNet3Params;
7 |
8 | /**
9 | * Created by jackQ on 2018/7/7.
10 | */
11 |
12 | public class TestEnv implements BtcEnv {
13 |
14 | @Override
15 | public NetworkParameters getNetParams() {
16 | return TestNet3Params.get();
17 | }
18 |
19 | @Override
20 | public String getPath() {
21 | return CoinType.btcTest.getPath();
22 | }
23 |
24 | @Override
25 | public CoinType getCoinType() {
26 | return CoinType.btcTest;
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/src/module/i18n/translations/en.js:
--------------------------------------------------------------------------------
1 | const common = require("./common/en.json");
2 | const mine = require("./mine/en.json");
3 | const qunfabao = require("./qunfabao/en.json");
4 | const wallet = require("./wallet/en.json");
5 |
6 | const _ = require("lodash");
7 |
8 | const bizs = {
9 | common,
10 | mine,
11 | qunfabao,
12 | wallet,
13 | };
14 |
15 | const en = Object.assign(
16 | {},
17 | ..._.reduce(
18 | bizs,
19 | (r, value, key) => {
20 | const biz = _.reduce(
21 | value,
22 | (subResult, subValue, subKey) => {
23 | subResult[`${key}-${subKey}`] = subValue;
24 | return subResult;
25 | },
26 | {}
27 | );
28 | r.push(biz);
29 | return r;
30 | },
31 | []
32 | )
33 | );
34 |
35 | module.exports = en;
36 |
--------------------------------------------------------------------------------
/src/module/i18n/translations/zh.js:
--------------------------------------------------------------------------------
1 | const common = require("./common/zh.json");
2 | const mine = require("./mine/zh.json");
3 | const qunfabao = require("./qunfabao/zh.json");
4 | const wallet = require("./wallet/zh.json");
5 |
6 | const _ = require("lodash");
7 |
8 | const bizs = {
9 | common,
10 | mine,
11 | qunfabao,
12 | wallet,
13 | };
14 |
15 | const zh = Object.assign(
16 | {},
17 | ..._.reduce(
18 | bizs,
19 | (r, value, key) => {
20 | const biz = _.reduce(
21 | value,
22 | (subResult, subValue, subKey) => {
23 | subResult[`${key}-${subKey}`] = subValue;
24 | return subResult;
25 | },
26 | {}
27 | );
28 | r.push(biz);
29 | return r;
30 | },
31 | []
32 | )
33 | );
34 |
35 | module.exports = zh;
36 |
--------------------------------------------------------------------------------
/android/app/src/main/java/com/blankj/utilcode/constant/MemoryConstants.java:
--------------------------------------------------------------------------------
1 | package com.blankj.utilcode.constant;
2 |
3 | import android.support.annotation.IntDef;
4 |
5 | import java.lang.annotation.Retention;
6 | import java.lang.annotation.RetentionPolicy;
7 |
8 | /**
9 | *
10 | * author: Blankj
11 | * blog : http://blankj.com
12 | * time : 2017/03/13
13 | * desc : constants of memory
14 | *
15 | */
16 | public final class MemoryConstants {
17 |
18 | public static final int BYTE = 1;
19 | public static final int KB = 1024;
20 | public static final int MB = 1048576;
21 | public static final int GB = 1073741824;
22 |
23 | @IntDef({BYTE, KB, MB, GB})
24 | @Retention(RetentionPolicy.SOURCE)
25 | public @interface Unit {
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/ios/rrwallet/RNBridgeModule/RRRNAnalysis.m:
--------------------------------------------------------------------------------
1 | //
2 | // RRRNAnalysis.m
3 | // rrwallet
4 | //
5 | // Created by muhuai on 2018/11/19.
6 | // Copyright © 2018 Facebook. All rights reserved.
7 | //
8 |
9 | #import "RRRNAnalysis.h"
10 | #import
11 |
12 | @implementation RRRNAnalysis
13 | RCT_EXPORT_MODULE();
14 |
15 | RCT_REMAP_METHOD(event, event:(NSString *)event attributes:(NSDictionary *)attributes) {
16 | if (attributes.count == 0) {
17 | [MobClick event:event];
18 | } else {
19 | [MobClick event:event attributes:attributes];
20 | }
21 | }
22 |
23 | RCT_REMAP_METHOD(counter, event:(NSString *)event attributes:(NSDictionary *)attributes counter:(NSString *)counter) {
24 | [MobClick event:event attributes:attributes counter:counter.intValue];
25 | }
26 |
27 | @end
28 |
--------------------------------------------------------------------------------
/android/app/src/main/java/com/renrenbit/rrwallet/network/ICommonApi.kt:
--------------------------------------------------------------------------------
1 | package com.renrenbit.rrwallet.network
2 |
3 | import retrofit2.Call
4 | import retrofit2.http.*
5 | import retrofit2.http.POST
6 |
7 |
8 |
9 | /**
10 | * Created by jackQ on 2018/6/1.
11 | */
12 | interface ICommonApi {
13 | @GET
14 | fun get(@Url relativePath: String, @HeaderMap headers: Map): Call
15 |
16 | @POST
17 | @FormUrlEncoded
18 | fun post(@Url relativePath: String,
19 | @FieldMap(encoded = true) fields: Map,
20 | @HeaderMap headers: Map): Call
21 |
22 |
23 | @POST
24 | fun post(@Url relativePath: String,
25 | @Body data: String,
26 | @HeaderMap headers: Map): Call
27 |
28 |
29 | }
--------------------------------------------------------------------------------
/src/util/Storage.js:
--------------------------------------------------------------------------------
1 | import Storage from "react-native-storage";
2 | import { AsyncStorage } from "react-native";
3 |
4 | const storage = new Storage({
5 | // 最大容量,默认值1000条数据循环存储
6 | size: 1000,
7 |
8 | // 存储引擎:对于rn使用asyncstorage,对于web使用window.localstorage
9 | // 如果不指定则数据只会保存在内存中,重启后即丢失
10 | storageBackend: AsyncStorage,
11 |
12 | // 数据过期时间,默认一整天(1000 * 3600 * 24 毫秒),设为null则永不过期
13 | defaultExpires: null,
14 |
15 | // 读写时在内存中缓存数据。默认启用。
16 | enableCache: true,
17 | });
18 |
19 | // 缓存key
20 | // !!!!注意,key中不要用_下划线字符,否则在key-id的存储形式下有问题
21 | const STORAGE_KEY = {
22 | CONTACT_LIST: "contactList", // 联系人列表
23 | APP_INFO: "appinfo", // app信息
24 | };
25 |
26 | // api 使用参见https://github.com/sunnylqm/react-native-storage/blob/master/README-CHN.md
27 | //
28 | export default storage;
29 | export { STORAGE_KEY };
30 |
--------------------------------------------------------------------------------
/src/module/app/DetectionRisk.ios.js:
--------------------------------------------------------------------------------
1 | import { NativeModules, Alert } from "react-native";
2 | import AppInfo from "./AppInfo";
3 | import { BUNDLE_ID_PRO_IOS, BUNDLE_ID_DEV, BUNDLE_ID_INHOUSE_IOS } from "../../config/const";
4 |
5 | const RRRNDevice = NativeModules.RRRNDevice;
6 |
7 | const vaildBundleId = () => {
8 | if (__DEV__) {
9 | return true;
10 | }
11 | return [BUNDLE_ID_PRO_IOS, BUNDLE_ID_INHOUSE_IOS, BUNDLE_ID_DEV].indexOf(AppInfo.bundleId) != -1;
12 | };
13 |
14 | const detectionRisk = () => {
15 | if (!vaildBundleId()) {
16 | Alert.alert("警告", "发现二次签名");
17 | return true;
18 | }
19 | const isJailbreak = RRRNDevice.OO0o0OO00O00oOO0o0;
20 | if (isJailbreak) {
21 | Alert.alert("警告", "安装包已损坏请重新安装");
22 | return true;
23 | }
24 | return false;
25 | };
26 |
27 | export default detectionRisk;
28 |
--------------------------------------------------------------------------------
/android/app/src/main/java/com/blankj/utilcode/constant/TimeConstants.java:
--------------------------------------------------------------------------------
1 | package com.blankj.utilcode.constant;
2 |
3 | import android.support.annotation.IntDef;
4 |
5 | import java.lang.annotation.Retention;
6 | import java.lang.annotation.RetentionPolicy;
7 |
8 | /**
9 | *
10 | * author: Blankj
11 | * blog : http://blankj.com
12 | * time : 2017/03/13
13 | * desc : constants of time
14 | *
15 | */
16 | public final class TimeConstants {
17 |
18 | public static final int MSEC = 1;
19 | public static final int SEC = 1000;
20 | public static final int MIN = 60000;
21 | public static final int HOUR = 3600000;
22 | public static final int DAY = 86400000;
23 |
24 | @IntDef({MSEC, SEC, MIN, HOUR, DAY})
25 | @Retention(RetentionPolicy.SOURCE)
26 | public @interface Unit {
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/component/common/Footer.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from "react";
2 | import { StyleSheet, View } from "react-native";
3 | import device from "../../util/device";
4 |
5 | export default class Footer extends Component {
6 | render() {
7 | return (
8 |
9 | {this.props.children}
10 | {device.isIPhoneX && }
11 |
12 | );
13 | }
14 | }
15 |
16 | const styles = StyleSheet.create({
17 | footer: {
18 | width: "100%",
19 | backgroundColor: "#FFFFFF",
20 | },
21 | container: {
22 | paddingHorizontal: 0,
23 | flexDirection: "row",
24 | justifyContent: "space-between",
25 | },
26 | bottom: {
27 | height: device.iPhoneXSafeArea.bottom,
28 | },
29 | });
30 |
--------------------------------------------------------------------------------
/src/util/UIAdapter.js:
--------------------------------------------------------------------------------
1 | import { Dimensions, Platform } from "react-native";
2 |
3 | const { width, height, scale } = Dimensions.get("screen");
4 |
5 | const manualPadding = (x3, x2 = x3, ax3 = x3, ax2 = x2) => {
6 | let r;
7 | switch (scale) {
8 | case 3:
9 | r = Platform.select({ ios: x3, android: ax3 });
10 | break;
11 | case 2:
12 | default:
13 | r = Platform.select({ ios: x2, android: ax2 });
14 | }
15 | return Math.ceil(r);
16 | };
17 |
18 | const padding = length => {
19 | return manualPadding(length, length * 0.8);
20 | };
21 |
22 | const fontSize = size => {
23 | let r = size;
24 | switch (scale) {
25 | case 2:
26 | r = size * 0.8;
27 | break;
28 | case 3:
29 | default:
30 | r = size;
31 | }
32 | return Math.ceil(r);
33 | };
34 |
35 | export { manualPadding, padding, fontSize };
36 |
--------------------------------------------------------------------------------
/android/app/src/main/java/com/renrenbit/rrwallet/network/NetworkClient.kt:
--------------------------------------------------------------------------------
1 | package com.renrenbit.rrwallet.network
2 |
3 | import org.json.JSONObject
4 |
5 | /**
6 | * Created by jackQ on 2018/6/1.
7 | */
8 | interface NetworkClient {
9 | fun get(url: String, headers: MutableMap?): String?
10 |
11 | fun getAsync(url: String, headers: MutableMap?, callback: Callback)
12 |
13 | fun post(url: String, headers: MutableMap?, params: MutableMap?): JSONObject?
14 |
15 | fun postAsync(url: String, headers: MutableMap?, params: MutableMap?, callback: Callback)
16 |
17 | fun post(url: String, headers: MutableMap?, data: String?): String?
18 |
19 | fun postAsync(url: String, headers: MutableMap?, data: String?, callback: Callback)
20 | }
--------------------------------------------------------------------------------
/ios/rrwallet/Service/Wallet/ethers/ethers/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | $(CURRENT_PROJECT_VERSION)
21 | NSPrincipalClass
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/android/app/src/main/java/com/renrenbit/rrwallet/utils/WeakHandler.java:
--------------------------------------------------------------------------------
1 | package com.renrenbit.rrwallet.utils;
2 |
3 | import android.os.Handler;
4 | import android.os.Looper;
5 | import android.os.Message;
6 |
7 | import java.lang.ref.WeakReference;
8 |
9 | public class WeakHandler extends Handler {
10 |
11 | public interface IHandler {
12 | public void handleMsg(Message msg);
13 | }
14 |
15 | WeakReference mRef;
16 |
17 | public WeakHandler(IHandler handler) {
18 | mRef = new WeakReference(handler);
19 | }
20 |
21 | public WeakHandler(Looper looper, IHandler handler) {
22 | super(looper);
23 | mRef = new WeakReference(handler);
24 | }
25 |
26 | @Override
27 | public void handleMessage(Message msg) {
28 | IHandler handler = mRef.get();
29 | if (handler != null && msg != null)
30 | handler.handleMsg(msg);
31 | }
32 | }
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "es6": true,
4 | "node": true,
5 | "react-native/react-native": true
6 | },
7 | "parser": "babel-eslint",
8 | "extends": "eslint:recommended",
9 | "globals": {
10 | "Atomics": "readonly",
11 | "SharedArrayBuffer": "readonly"
12 | },
13 | "parserOptions": {
14 | "ecmaFeatures": {
15 | "jsx": true,
16 | "legacyDecorators": true
17 | },
18 | "ecmaVersion": 2018,
19 | "sourceType": "module"
20 | },
21 | "plugins": [
22 | "react",
23 | "react-native"
24 | ],
25 | "rules": {
26 | "no-unused-vars": "off",
27 | "no-console": "off",
28 | "no-useless-escape": "off",
29 | "no-empty": ["error", { "allowEmptyCatch": true }],
30 | "no-extra-boolean-cast": "off",
31 | "no-control-regex": "off",
32 | "getter-return": "off"
33 | }
34 | }
--------------------------------------------------------------------------------
/ios/rrwallet/Service/Network/DFSecurityPolicy.m:
--------------------------------------------------------------------------------
1 | //
2 | // DFSecurityPolicy.m
3 | // rrwallet
4 | //
5 | // Created by muhuai on 2018/7/24.
6 | // Copyright © 2018 Facebook. All rights reserved.
7 | //
8 |
9 | #import "DFSecurityPolicy.h"
10 | @interface DFSecurityPolicy()
11 |
12 | @property (nonatomic, strong) AFSecurityPolicy *innerPolicy;
13 | @end
14 | @implementation DFSecurityPolicy
15 |
16 | - (instancetype)init {
17 | self = [super init];
18 | _innerPolicy = [AFSecurityPolicy defaultPolicy];
19 | return self;
20 | }
21 |
22 | - (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust
23 | forDomain:(nullable NSString *)domain {
24 | if ([domain containsString:@"gateway.d.cash"] || [domain containsString:@"gateway.bitrenren.com"]) {
25 | return [super evaluateServerTrust:serverTrust forDomain:domain];
26 | } else {
27 | return [self.innerPolicy evaluateServerTrust:serverTrust forDomain:domain];
28 | }
29 | }
30 | @end
31 |
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["module:metro-react-native-babel-preset"],
3 | "plugins": [
4 | "@babel/plugin-transform-flow-strip-types",
5 | ["@babel/plugin-proposal-decorators", { "legacy": true}],
6 | ["@babel/plugin-proposal-class-properties", { "loose": true}],
7 | ["transform-inline-environment-variables", { "include": [ "RN_JS_VERSION", "RN_ENV", "RN_CID" ] }],
8 | ["module-resolver", {
9 | "root": ["./src"],
10 | "extensions": [".js"],
11 | "alias": {
12 | "@img": "./resources/img",
13 | "@CC": "./src/component/common",
14 | "@i18n": "./src/module/i18n/i18n",
15 | "@theme": "./src/util/Theme",
16 | "@util": "./src/util",
17 | "@page": "./src/page",
18 | "@module": "./src/module",
19 | "underscore": "lodash"
20 | }
21 | }]
22 | ],
23 | "env": {
24 | "production": {
25 | "plugins": ["transform-remove-console"]
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/util/ImageUtil.js:
--------------------------------------------------------------------------------
1 | import { CameraRoll, PermissionsAndroid, Platform } from "react-native";
2 | import _ from "lodash";
3 |
4 | const ERROR_MESSAGE_SAVE_IMAGE = "图片保存失败,请检查相册读取权限,或者手动截图保存";
5 | async function saveToCameraRoll(uri) {
6 | if (!_.isString(uri) || uri.length <= 0) {
7 | throw new Error(ERROR_MESSAGE_SAVE_IMAGE);
8 | }
9 | if (Platform.OS === "android") {
10 | try {
11 | const granted = await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE);
12 | if (granted !== PermissionsAndroid.RESULTS.GRANTED) {
13 | throw new Error(ERROR_MESSAGE_SAVE_IMAGE);
14 | }
15 | } catch (err) {
16 | throw new Error(ERROR_MESSAGE_SAVE_IMAGE);
17 | }
18 | }
19 | try {
20 | await CameraRoll.saveToCameraRoll(uri);
21 | } catch (error) {
22 | throw new Error(ERROR_MESSAGE_SAVE_IMAGE);
23 | }
24 | }
25 |
26 | const ImageUtil = {
27 | saveToCameraRoll,
28 | };
29 |
30 | export default ImageUtil;
31 |
--------------------------------------------------------------------------------
/resources/iconfont/iconfont.js:
--------------------------------------------------------------------------------
1 | const cheerio = require('cheerio')
2 | const fs = require('fs')
3 | const path = require('path');
4 | const pwd = process.cwd();
5 |
6 | const json = {}
7 | const html = fs.readFileSync( path.resolve(pwd,'resources/iconfont/demo_unicode.html')).toString()
8 | const $ = cheerio.load(html)
9 |
10 | var lis = $('.icon_lists.clear').children().each((i, el) => {
11 | let name = $(el).children('.name').text()
12 | let t = name.lastIndexOf('_')
13 | if (t > 0) {
14 | name = name.substr(0, t)
15 | }
16 |
17 | let code = $(el).children('.code').text()
18 | if (code.length <= 3) {
19 | console.warn()
20 | return
21 | }
22 | code = parseInt("0x" + code.substring(3, code.length - 1))
23 |
24 |
25 | json[name] = code
26 | });
27 |
28 | try{
29 | fs.writeFileSync( path.resolve(pwd ,'resources/iconfont/iconfont.json'), JSON.stringify(json), 'utf8');
30 | }catch(e){
31 | console.log('生成iconfont映射文件失败', e);
32 | }
33 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | RRWallet是一款On-Chain数字货币钱包, 支持多个币种, 可同时运行在iOS, Android上.
2 |
3 |
4 |
5 | ## 主要特点⚡️
6 |
7 | * 支持BTC, USDT, ETH, BCH, BSV, ETC等多个币种
8 | * 支持BTC和USDT多签
9 | * 智能合约批量发送交易
10 | * 助记词加密存储在本地
11 | * 使用React Native开发, 一套代码同时支持iOS, Android
12 | * 门限签名(即将支持)
13 |
14 |
15 |
16 | ## 本地运行🚀
17 |
18 | 确保已经安装了Node.js, iOS 和 Android开发环境
19 |
20 | 1.安装依赖
21 |
22 | ```shell
23 | npm ci #前端依赖
24 | cd ios #以下为iOS依赖, 如不需要可以跳过
25 | pod install
26 | ```
27 |
28 | 2.启动服务
29 |
30 | ```shell
31 | npm start
32 | ```
33 |
34 | 3.打开Xcode或者Android Studio 运行即可
35 |
36 |
37 |
38 | ## 编译Release😈
39 | ### iOS
40 |
41 | ```shell
42 | #确保Xcode中的证书有效
43 | npm run build-ios
44 | ```
45 |
46 | ### Android
47 |
48 | ```shell
49 | #需要替换掉build.gradle中的Keystore以及对应的密码
50 | npm run build-android
51 | ```
52 |
53 |
54 |
55 | ## 社区
56 |
57 | 欢迎到社区里与我们讨论任何技术问题
58 |
59 | [RenrenBit Developer Group(Telegram)](http://t.me/renrenbit_developer)
60 |
61 | ## License
62 |
63 | MIT License
64 |
65 | Copyright (c) 2020 RenrenBit
66 |
67 |
--------------------------------------------------------------------------------
/src/module/i18n/script/excel2json.js:
--------------------------------------------------------------------------------
1 | const xlsx = require("xlsx");
2 | const fs = require("fs");
3 | const mkdirp = require("mkdirp");
4 |
5 | const TRANSLATIONS_PATH = "../translations";
6 | const EXCEL_PATH = "../excel/renrenbit.xlsx";
7 |
8 | const workbook = xlsx.readFile(EXCEL_PATH);
9 |
10 | for (const biz in workbook.Sheets) {
11 | const worksheet = workbook.Sheets[biz];
12 | const columns = xlsx.utils.sheet_to_json(worksheet);
13 | const { zh, en } = formatJSON(columns);
14 | const bizPath = `${TRANSLATIONS_PATH}/${biz}`;
15 | mkdirp.sync(bizPath);
16 | // fs.writeFileSync(`${bizPath}/zh.json`, JSON.stringify(zh, null, 2))
17 | fs.writeFileSync(`${bizPath}/en.json`, JSON.stringify(en, null, 2));
18 | }
19 |
20 | function formatJSON(columns) {
21 | const zh = {};
22 | const en = {};
23 | columns.forEach(column => {
24 | if (column.zh) {
25 | zh[column.name] = column.zh;
26 | }
27 | if (column.en) {
28 | en[column.name] = column.en;
29 | }
30 | });
31 | return { zh, en };
32 | }
33 |
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
19 |
20 | android.useDeprecatedNdk=true
21 |
22 | android.enableAapt2=false
23 | org.gradle.jvmargs=-Xmx1536M
--------------------------------------------------------------------------------
/src/module/launch/splash.js:
--------------------------------------------------------------------------------
1 | import { NativeModules } from "react-native";
2 | import { SPLASH_SCENE_LOCK, SPLASH_SCENE_TAB } from "../../config/const";
3 | import DeviceSecurity from "../security/DeviceSecurity";
4 | import RNLanguages from "react-native-languages";
5 |
6 | const RRRNSplash = NativeModules.RRRNSplash;
7 | class Splash {
8 | get isFirstLaunch() {
9 | return RRRNSplash.isFirstLaunch && RNLanguages.language.indexOf("zh") === 0;
10 | }
11 | constructor() {
12 | setTimeout(() => {
13 | this.dismiss();
14 | }, 8 * 1000); //八秒后强制dimiss, 防止业务层没人调用卡在闪屏
15 | }
16 | /**
17 | *
18 | * @param {SPLASH_SCENE_TAB|SPLASH_SCENE_LOCK|SPLASH_SCENE_GUIDE} scene
19 | * @memberof Splash
20 | */
21 | dismissIfNeed = scene => {
22 | if (scene == SPLASH_SCENE_TAB && (DeviceSecurity.isUnlocking || this.isFirstLaunch)) {
23 | return;
24 | }
25 | this.dismiss();
26 | };
27 | dismiss = () => {
28 | RRRNSplash && RRRNSplash.dismiss && RRRNSplash.dismiss();
29 | };
30 | }
31 |
32 | export default new Splash();
33 |
--------------------------------------------------------------------------------
/ios/rrwallet/Category/NSDictionary+MFCategory.h:
--------------------------------------------------------------------------------
1 | //
2 | // NSDictionary+MFCategory.h
3 | // rrwallet
4 | //
5 | // Created by muhuai on 06/02/2017.
6 | // Copyright © 2017 MH. All rights reserved.
7 | //
8 |
9 | #import
10 | @interface NSDictionary(MFCategory)
11 |
12 | - (id)mf_objectForKey:(id)aKey ofClass:(Class)aClass defaultObj:(id)defaultObj;
13 |
14 | - (NSInteger)mf_integerValueForKey:(NSString *)key;
15 | - (NSInteger)mf_integerValueForKey:(NSString *)key defaultValue:(NSInteger)defaultValue;
16 |
17 | - (BOOL)mf_boolValueForKey:(NSString *)key;
18 |
19 | - (NSString *)mf_stringValueForKey:(NSString *)key defaultValue:(NSString *)defaultValue;
20 | - (NSString *)mf_stringValueForKey:(NSString *)key;
21 |
22 | - (NSArray *)mf_arrayValueForKey:(NSString *)key defaultValue:(NSArray *)defaultValue;
23 | - (NSArray *)mf_arrayValueForKey:(NSString *)key;
24 |
25 | - (NSDictionary *)mf_dictionaryValueForKey:(NSString *)key defalutValue:(NSDictionary *)defaultValue;
26 | - (NSDictionary *)mf_dictionaryValueForKey:(NSString *)key;
27 |
28 | @end
29 |
--------------------------------------------------------------------------------
/android/app/src/main/java/com/renrenbit/rrwallet/network/cookie/GuardedResultAsyncTask.java:
--------------------------------------------------------------------------------
1 | package com.renrenbit.rrwallet.network.cookie;
2 |
3 | import android.os.AsyncTask;
4 |
5 | /**
6 | * Created by jackQ on 2018/6/2.
7 | */
8 |
9 | abstract class GuardedResultAsyncTask
10 | extends AsyncTask {
11 |
12 | protected GuardedResultAsyncTask() {
13 |
14 | }
15 |
16 | @Override
17 | protected final Result doInBackground(Void... params) {
18 | try {
19 | return doInBackgroundGuarded();
20 | } catch (RuntimeException e) {
21 | e.printStackTrace();
22 | throw e;
23 | }
24 | }
25 |
26 | @Override
27 | protected final void onPostExecute(Result result) {
28 | try {
29 | onPostExecuteGuarded(result);
30 | } catch (RuntimeException e) {
31 | e.printStackTrace();
32 | }
33 | }
34 |
35 | protected abstract Result doInBackgroundGuarded();
36 |
37 | protected abstract void onPostExecuteGuarded(Result result);
38 | }
39 |
--------------------------------------------------------------------------------
/ios/rrwallet/Category/RCTStatusBarManager+Swizzle.m:
--------------------------------------------------------------------------------
1 | //
2 | // RCTStatusBarManager+Swizzle.m
3 | // rrwallet
4 | //
5 | // Created by muhuai on 2018/8/4.
6 | // Copyright © 2018 Facebook. All rights reserved.
7 | //
8 |
9 | #import "RCTStatusBarManager+Swizzle.h"
10 | #import
11 |
12 | @implementation RCTStatusBarManager (Swizzle)
13 |
14 | + (void)load {
15 | static dispatch_once_t onceToken;
16 | dispatch_once(&onceToken, ^{
17 | RCTSwapInstanceMethods([RCTStatusBarManager class], @selector(setStyle:animated:), @selector(df_setStyle:animated:));
18 | RCTSwapInstanceMethods([RCTStatusBarManager class], @selector(setHidden:withAnimation:), @selector(df_setHidden:withAnimation:));
19 | });
20 | }
21 |
22 | - (void)df_setStyle:(UIStatusBarStyle)statusBarStyle animated:(BOOL)animated {
23 | [RCTSharedApplication() setStatusBarStyle:statusBarStyle animated:animated];
24 | }
25 |
26 | - (void)df_setHidden:(BOOL)hidden withAnimation:(UIStatusBarAnimation)animation {
27 | [RCTSharedApplication() setStatusBarHidden:hidden withAnimation:animation];
28 | }
29 | @end
30 |
--------------------------------------------------------------------------------
/ios/rrwallet/Service/BlockChain/Bitcoin/RRBTCutxo.h:
--------------------------------------------------------------------------------
1 | //
2 | // RRBTCTransactionOutput.h
3 | // rrwallet
4 | //
5 | // Created by muhuai on 2018/11/27.
6 | // Copyright © 2018 Facebook. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 |
12 | NS_ASSUME_NONNULL_BEGIN
13 |
14 | @interface RRBTCutxo : NSObject
15 |
16 | @property (nonatomic, copy) NSString *address;
17 | @property (nonatomic, copy) NSString *path;
18 | @property (nonatomic, copy) NSString *txid;
19 | @property (nonatomic, copy) NSString *rawSigHash;
20 | @property (nonatomic) NSInteger vout;
21 | @property (nonatomic, copy) NSString *scriptPubKey;
22 | @property (nonatomic) float amount;
23 | @property (nonatomic) NSInteger satoshis;
24 | @property (nonatomic) NSInteger height;
25 | @property (nonatomic) NSInteger confirmations;
26 | @property (nonatomic) NSInteger sigHashType;
27 |
28 | @property (nonatomic, strong, readonly) BTCScript *script;
29 |
30 | - (instancetype)initWithDictionary:(NSDictionary *)dictionary;
31 |
32 | @end
33 |
34 | NS_ASSUME_NONNULL_END
35 |
--------------------------------------------------------------------------------
/ios/rrwallet/Service/Wallet/DFWallet.m:
--------------------------------------------------------------------------------
1 |
2 | //
3 | // DFWallet.m
4 | // rrwallet
5 | //
6 | // Created by muhuai on 2018/2/28.
7 | // Copyright © 2018年 Facebook. All rights reserved.
8 | //
9 |
10 | #import "DFWallet.h"
11 | #import
12 | #import
13 | #import "DFETHWallet.h"
14 |
15 | @interface DFWallet()
16 |
17 | @property (nonatomic, strong, readwrite) DFEthereumRPCProvider *rpc;
18 |
19 | @end
20 |
21 | @implementation DFWallet
22 |
23 | + (instancetype)sharedInstance {
24 | static DFWallet *wallet;
25 | static dispatch_once_t onceToken;
26 | dispatch_once(&onceToken, ^{
27 | wallet = [[DFWallet alloc] init];
28 | });
29 |
30 | return wallet;
31 | }
32 |
33 | - (instancetype)init {
34 | self = [super init];
35 | if (self) {
36 |
37 | _env = DFWalletEnvRelease;
38 |
39 | #if WALLET_ENV_DEBUG
40 | _env = DFWalletEnvDebug;
41 | #endif
42 |
43 | #if DEBUG
44 | _env = DFWalletEnvDebug;
45 | #endif
46 |
47 |
48 | _rpc = [[DFEthereumRPCProvider alloc] initWithEnv:_env];
49 | }
50 | return self;
51 | }
52 | @end
53 |
--------------------------------------------------------------------------------
/android/app/src/main/java/com/renrenbit/rrwallet/service/push/ActivityHookService.java:
--------------------------------------------------------------------------------
1 | package com.renrenbit.rrwallet.service.push;
2 |
3 | import android.app.Activity;
4 | import android.os.Bundle;
5 |
6 | import com.renrenbit.rrwallet.service.statistics.UmengAnalyticsAgent;
7 | import com.umeng.message.PushAgent;
8 |
9 | /**
10 | * Created by jackQ on 2018/6/18.
11 | */
12 |
13 | class ActivityHookService {
14 | void onActivityCreated(Activity activity, Bundle savedInstanceState) {
15 | PushAgent.getInstance(activity).onAppStart();
16 | }
17 |
18 | void onActivityStarted(Activity activity) {
19 |
20 | }
21 |
22 | void onActivityResumed(Activity activity) {
23 | UmengAnalyticsAgent.onResume(activity);
24 | }
25 |
26 | void onActivityPaused(Activity activity) {
27 | UmengAnalyticsAgent.onPause(activity);
28 | }
29 |
30 | void onActivityStopped(Activity activity) {
31 |
32 | }
33 |
34 | void onActivitySaveInstanceState(Activity activity, Bundle outState) {
35 |
36 | }
37 |
38 | void onActivityDestroyed(Activity activity) {
39 |
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/module/contact/index.js:
--------------------------------------------------------------------------------
1 | import Network from "../common/network";
2 | import storage, { STORAGE_KEY } from "../../util/Storage";
3 |
4 | // 使用storage 的key-id方式来保存联系人数据
5 | export default {
6 | async getContactList(uuid, page) {
7 | let contactList = [];
8 |
9 | try {
10 | contactList = await storage.getAllDataForKey(STORAGE_KEY.CONTACT_LIST);
11 | } catch (e) {
12 | console.log("获取联系人列表失败", e);
13 | }
14 |
15 | return contactList;
16 | },
17 |
18 | // 保存,判断是新增还是修改
19 | async save(param) {
20 | console.log("保存联系人入参+===>", param);
21 | if (param.id === null || param.id === undefined) {
22 | param.id = Date.now();
23 | }
24 |
25 | console.log("保存联系人====>", param);
26 |
27 | await storage.save({
28 | key: STORAGE_KEY.CONTACT_LIST,
29 | id: param.id,
30 | data: param,
31 | });
32 | },
33 |
34 | async deleteAll() {
35 | storage.clearMapForKey(STORAGE_KEY.CONTACT_LIST);
36 | },
37 |
38 | async delete(contactId) {
39 | storage.remove({
40 | key: STORAGE_KEY.CONTACT_LIST,
41 | id: contactId,
42 | });
43 | },
44 | };
45 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 RenrenBit
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/android/app/src/main/java/com/renrenbit/rrwallet/utils/Md5.java:
--------------------------------------------------------------------------------
1 | package com.renrenbit.rrwallet.utils;
2 |
3 | import android.text.TextUtils;
4 |
5 | import java.security.MessageDigest;
6 | import java.security.NoSuchAlgorithmException;
7 |
8 | /**
9 | * Created by jackQ on 2018/6/12.
10 | */
11 |
12 | public class Md5 {
13 | public static String md5(String str) {
14 | if (TextUtils.isEmpty(str)) {
15 | return "";
16 | }
17 | MessageDigest md5 = null;
18 | try {
19 | md5 = MessageDigest.getInstance("MD5");
20 | byte[] bytes = md5.digest(str.getBytes());
21 | StringBuilder result = new StringBuilder();
22 | for (byte b : bytes) {
23 | String temp = Integer.toHexString(b & 0xff);
24 | if (temp.length() == 1) {
25 | temp = "0" + temp;
26 | }
27 | result.append(temp);
28 | }
29 | return result.toString();
30 | } catch (NoSuchAlgorithmException e) {
31 | e.printStackTrace();
32 | }
33 | return "";
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/component/common/Dialog.js:
--------------------------------------------------------------------------------
1 | import { AlertIOS, AlertAndroid, Alert, Platform } from "react-native";
2 | // import DialogAndroid from 'react-native-dialogs'
3 | import prompt from "react-native-prompt-android";
4 |
5 | class Dialog {
6 | alert = Alert.alert;
7 |
8 | prompt = (title, message, buttons, type, defaultValue) => {
9 | if (Platform.OS == "ios") {
10 | AlertIOS.prompt(title, message, buttons, type, defaultValue);
11 | } else if (Platform.OS == "android") {
12 | prompt(title, message, buttons, {
13 | type: type,
14 | cancelable: false,
15 | defaultValue: defaultValue,
16 | });
17 | // prompt(title, message, buttons, {
18 | // type: type,
19 | // defaultValue: defaultValue,
20 | // })
21 | // DialogAndroid.prompt(title, message, {
22 | // positiveText: 'OK',
23 | // negativeText: 'Cancel',
24 | // keyboardType: 'password',
25 | // defaultValue: defaultValue
26 | // }).then(result => {
27 | // console.log(result)
28 | // })
29 | }
30 | };
31 | }
32 |
33 | export default new Dialog();
34 |
--------------------------------------------------------------------------------
/src/module/wallet/account/Account.js:
--------------------------------------------------------------------------------
1 | import { computed } from "mobx";
2 | import _ from "lodash";
3 |
4 | class Account {
5 | id;
6 | /**
7 | *
8 | * @type { String }
9 | * @memberof MultiChainAccount
10 | */
11 | name;
12 | type;
13 | @computed get totalAsset() {
14 | throw new Error("not implemented totalAsset");
15 | }
16 | @computed get floatingAsset() {
17 | throw new Error("not implemented floatingAsset");
18 | }
19 |
20 | /**
21 | * 更新account相关业务数据, AccountStore会轮询该方法
22 | *
23 | * @memberof Account
24 | */
25 | update = async () => {
26 | throw new Error("not implemented update");
27 | };
28 |
29 | /**
30 | * 定时轮询
31 | *
32 | * @memberof Account
33 | */
34 | pollingUpdateTask = () => {
35 | this.update().finally(() => {
36 | setTimeout(this.pollingUpdateTask, _.random(60, 80) * 1000);
37 | });
38 | };
39 | constructor(obj = {}) {
40 | this.id = obj.id;
41 | this.name = obj.name;
42 | this.type = obj.type;
43 | setTimeout(() => {
44 | this.pollingUpdateTask();
45 | }, 0);
46 | }
47 | }
48 |
49 | export default Account;
50 |
--------------------------------------------------------------------------------
/android/app/src/main/java/com/renrenbit/rrwallet/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.renrenbit.rrwallet;
2 |
3 | import android.graphics.Color;
4 | import android.os.Bundle;
5 | import android.support.annotation.Nullable;
6 | import android.view.View;
7 | import android.view.WindowManager;
8 |
9 | import com.renrenbit.rrwallet.react.module.RRRNSplash;
10 | import com.reactnativenavigation.controllers.SplashActivity;
11 |
12 | public class MainActivity extends SplashActivity {
13 |
14 | @Override
15 | protected void onCreate(@Nullable Bundle savedInstanceState) {
16 | super.onCreate(savedInstanceState);
17 | getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
18 | getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
19 | getWindow().setStatusBarColor(Color.TRANSPARENT);
20 | }
21 |
22 | @Override
23 | public View createSplashLayout() {
24 | if (BuildConfig.DEBUG) {
25 | return super.createSplashLayout();
26 | }
27 | return RRRNSplash.getSplashLayout(this);
28 | }
29 | }
--------------------------------------------------------------------------------
/android/app/src/main/java/com/renrenbit/rrwallet/service/wallet/WalletCreatorFactory.java:
--------------------------------------------------------------------------------
1 | package com.renrenbit.rrwallet.service.wallet;
2 |
3 | import com.renrenbit.rrwallet.service.wallet.btc.BtcWalletCreator;
4 | import com.renrenbit.rrwallet.service.wallet.ether.EthWalletCreator;
5 |
6 | import java.util.Map;
7 | import java.util.concurrent.ConcurrentHashMap;
8 |
9 | /**
10 | * Created by jackQ on 2018/6/16.
11 | */
12 |
13 | public class WalletCreatorFactory {
14 | private static Map sMap;
15 |
16 | public static IWalletCreator getCreator(CoinType type) {
17 | if (sMap == null) {
18 | synchronized (WalletCreatorFactory.class) {
19 | if (sMap == null) {
20 | sMap = new ConcurrentHashMap<>();
21 | initMap();
22 | }
23 | }
24 | }
25 | return sMap.get(type);
26 | }
27 |
28 | private static void initMap() {
29 | sMap.put(CoinType.eth, new EthWalletCreator());
30 | sMap.put(CoinType.btc, new BtcWalletCreator());
31 | sMap.put(CoinType.btcTest, new BtcWalletCreator());
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/android/app/src/main/java/com/renrenbit/rrwallet/network/RetrofitResponseAdapter.java:
--------------------------------------------------------------------------------
1 | package com.renrenbit.rrwallet.network;
2 |
3 | import retrofit2.Call;
4 | import retrofit2.Response;
5 |
6 | /**
7 | * Created by jackQ on 2018/6/2.
8 | */
9 |
10 | @SuppressWarnings("unchecked")
11 | public class RetrofitResponseAdapter implements retrofit2.Callback {
12 |
13 | private final Callback mCallback;
14 |
15 | public RetrofitResponseAdapter(Callback callback) {
16 | mCallback = callback;
17 | }
18 |
19 | @Override
20 | public void onResponse(Call call, Response response) {
21 | try {
22 | if (response.isSuccessful()) {
23 | mCallback.onResponse(response.body());
24 | } else {
25 | String errorResp = response.errorBody() != null ? response.errorBody().string() : "";
26 | mCallback.onResponse(errorResp);
27 | }
28 | } catch (Throwable e) {
29 | mCallback.onFailure(e);
30 | }
31 | }
32 |
33 | @Override
34 | public void onFailure(Call call, Throwable t) {
35 | mCallback.onFailure(t);
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/android/app/src/main/java/com/renrenbit/rrwallet/react/module/webview/MessageEvent.java:
--------------------------------------------------------------------------------
1 | package com.renrenbit.rrwallet.react.module.webview;
2 |
3 | import com.facebook.react.bridge.Arguments;
4 | import com.facebook.react.bridge.WritableMap;
5 | import com.facebook.react.uimanager.events.Event;
6 | import com.facebook.react.uimanager.events.RCTEventEmitter;
7 |
8 | public class MessageEvent extends Event {
9 |
10 | public static final String EVENT_NAME = "messageEvent";
11 |
12 | private final String message;
13 |
14 | public MessageEvent(int viewId, String message) {
15 | super(viewId);
16 |
17 | this.message = message;
18 | }
19 |
20 | @Override
21 | public String getEventName() {
22 | return EVENT_NAME;
23 | }
24 |
25 | @Override
26 | public void dispatch(RCTEventEmitter rctEventEmitter) {
27 | rctEventEmitter.receiveEvent(getViewTag(), getEventName(), serializeEventData());
28 | }
29 |
30 | private WritableMap serializeEventData() {
31 | WritableMap eventData = Arguments.createMap();
32 | eventData.putString("message", this.message);
33 |
34 | return eventData;
35 | }
36 |
37 | }
--------------------------------------------------------------------------------
/ios/rrwallet/Service/BlockChain/Bitcoin/RRBTCutxo.m:
--------------------------------------------------------------------------------
1 | //
2 | // RRBTCTransactionOutput.m
3 | // rrwallet
4 | //
5 | // Created by muhuai on 2018/11/27.
6 | // Copyright © 2018 Facebook. All rights reserved.
7 | //
8 |
9 | #import "RRBTCutxo.h"
10 |
11 | @interface RRBTCutxo()
12 |
13 | @property (nonatomic, strong, readwrite) BTCScript *script;
14 |
15 | @end
16 | @implementation RRBTCutxo
17 |
18 | - (instancetype)initWithDictionary:(NSDictionary *)dictionary {
19 | self = [super init];
20 | if (self) {
21 | self.address = dictionary[@"address"];
22 | self.path = dictionary[@"path"];
23 | self.satoshis = [dictionary[@"satoshis"] longLongValue];
24 | self.amount = [dictionary[@"amount"] floatValue];
25 | self.scriptPubKey = dictionary[@"scriptPubKey"];
26 | self.vout = [dictionary[@"vout"] intValue];
27 | self.confirmations = [dictionary[@"confirmations"] integerValue];
28 | self.txid = dictionary[@"txid"];
29 | self.rawSigHash = dictionary[@"rawSigHash"];
30 | self.sigHashType = [dictionary[@"sigHashType"] integerValue];
31 |
32 | self.script = [[BTCScript alloc] initWithData:BTCDataFromHex(self.scriptPubKey)];
33 | }
34 |
35 | return self;
36 | }
37 | @end
38 |
--------------------------------------------------------------------------------
/ios/rrwallet/Service/Wallet/ethers/ethers/ethers.h:
--------------------------------------------------------------------------------
1 | //
2 | // ethers.h
3 | // ethers
4 | //
5 | // Created by Richard Moore on 2017-01-19.
6 | // Copyright © 2017 Ethers. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | //! Project version number for ethers.
12 | FOUNDATION_EXPORT double ethersVersionNumber;
13 |
14 | //! Project version string for ethers.
15 | FOUNDATION_EXPORT const unsigned char ethersVersionString[];
16 |
17 | #import
18 | #import
19 | #import
20 | #import
21 | #import
22 | #import
23 | #import
24 | #import
25 |
26 | #import
27 | //#import
28 | #import
29 | #import
30 | #import
31 |
32 | #import
33 | //#import
34 | #import
35 | #import
36 |
37 | #import
38 | #import
39 | #import
40 | #import
41 |
--------------------------------------------------------------------------------
/android/app/src/main/java/com/renrenbit/rrwallet/service/wallet/CoinType.java:
--------------------------------------------------------------------------------
1 | package com.renrenbit.rrwallet.service.wallet;
2 |
3 | import com.renrenbit.rrwallet.service.wallet.db.entry.Account;
4 |
5 | /**
6 | * Created by jackQ on 2018/6/16.
7 | */
8 |
9 | public enum CoinType {
10 | eth("m/44'/60'/0'/0/0", Account.ETHER),
11 | btc("m/44'/0'/0'/0/0", Account.BTC),
12 | btcTest("m/44'/1'/0'/0/0", Account.BTC_TEST);
13 |
14 | private final String mPath;
15 | private final int mAccountType;
16 |
17 |
18 | CoinType(String path, int accountType) {
19 | this.mPath = path;
20 | this.mAccountType = accountType;
21 | }
22 |
23 | public static CoinType of(int type) {
24 | switch (type) {
25 | case Account.ETHER:
26 | return eth;
27 | case Account.BTC:
28 | return btc;
29 | case Account.BTC_TEST:
30 | return btcTest;
31 | }
32 | throw new IllegalArgumentException("not support coin type : " + type);
33 | }
34 |
35 | public String getPath() {
36 | return mPath;
37 | }
38 |
39 | public int getAccountType() {
40 | return mAccountType;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/ios/rrwallet/Service/Wallet/DFETHWallet.h:
--------------------------------------------------------------------------------
1 | //
2 | // DFAccount.h
3 | // rrwallet
4 | //
5 | // Created by muhuai on 2018/2/28.
6 | // Copyright © 2018年 Facebook. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 | #import "DFBaseWallet.h"
12 | #import "DFWalletDefine.h"
13 |
14 | @interface DFETHWallet : DFBaseWallet
15 |
16 | @property (nonatomic, strong, readonly) NSString *address;
17 | @property (nonatomic, strong, readonly) NSString *mnemonicPhrase;
18 |
19 | - (instancetype)initRandom;
20 |
21 | - (instancetype)initWithPhrase:(NSString *)phrase;
22 |
23 | - (instancetype)initWithPrivateKey:(NSString *)privateKey;
24 |
25 | + (void)decryptWithKeyStore:(NSString *)keystore password:(NSString *)pwd completion:(void (^)(DFETHWallet *))completion;
26 |
27 | - (BOOL)isVaildPassword:(NSString *)pwd;
28 |
29 | - (void)updatePassword:(NSString *)pwd orig:(NSString *)orig error:(NSError **)error;
30 |
31 | - (void)lock;
32 |
33 | - (NSData *)sign:(Transaction *)transcation password:(NSString *)pwd;
34 |
35 | - (NSData *)toData;
36 |
37 | - (void)getKeyStore:(NSString *)pwd callback:(void (^)(NSString *json))callback;
38 |
39 | - (NSString *)getPrivateKey:(NSString *)pwd;
40 |
41 | @end
42 |
--------------------------------------------------------------------------------
/ios/rrwallet/Service/Network/DFUserAgent.m:
--------------------------------------------------------------------------------
1 | //
2 | // DFUserAgent.m
3 | // rrwallet
4 | //
5 | // Created by muhuai on 2018/3/5.
6 | // Copyright © 2018年 Facebook. All rights reserved.
7 | //
8 |
9 | #import "DFUserAgent.h"
10 | #import
11 |
12 | @implementation DFUserAgent
13 | static NSString *s_origAgent;
14 | + (void)registerUserAgent {
15 | NSString *ua = [self customUserAgent];
16 |
17 | NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:ua, @"UserAgent", ua, @"User-Agent", ua, @"User_Agent", nil];
18 | [[NSUserDefaults standardUserDefaults] registerDefaults:dictionary];
19 | }
20 |
21 | + (NSString *)customUserAgent {
22 |
23 | static dispatch_once_t onceToken;
24 | dispatch_once(&onceToken, ^{
25 | UIWebView *webView = [[UIWebView alloc] init];
26 | s_origAgent = [webView stringByEvaluatingJavaScriptFromString:@"navigator.userAgent"];
27 | });
28 | NSString *ua = [s_origAgent copy];
29 | NSBundle *bundle = [NSBundle bundleForClass:[self class]];
30 |
31 | NSString *marketingVersionNumber = [bundle objectForInfoDictionaryKey:@"CFBundleShortVersionString"];
32 |
33 | ua = [ua stringByAppendingFormat:@" RRWallet/%@", marketingVersionNumber];
34 | return ua;
35 | }
36 |
37 | @end
38 |
--------------------------------------------------------------------------------
/android/app/src/main/java/com/renrenbit/rrwallet/service/wallet/SecureRandomUtils.java:
--------------------------------------------------------------------------------
1 | package com.renrenbit.rrwallet.service.wallet;
2 |
3 | import org.web3j.crypto.LinuxSecureRandom;
4 |
5 | import java.security.SecureRandom;
6 |
7 | /**
8 | * Created by jackQ on 2018/6/4.
9 | */
10 |
11 | public class SecureRandomUtils {
12 | private static final SecureRandom SECURE_RANDOM;
13 | // Taken from BitcoinJ implementation
14 | // https://github.com/bitcoinj/bitcoinj/blob/3cb1f6c6c589f84fe6e1fb56bf26d94cccc85429/core/src/main/java/org/bitcoinj/core/Utils.java#L573
15 | private static int isAndroid = -1;
16 |
17 | static {
18 | if (isAndroidRuntime()) {
19 | new LinuxSecureRandom();
20 | }
21 | SECURE_RANDOM = new SecureRandom();
22 | }
23 |
24 | private SecureRandomUtils() {
25 | }
26 |
27 | public static SecureRandom secureRandom() {
28 | return SECURE_RANDOM;
29 | }
30 |
31 | static boolean isAndroidRuntime() {
32 | if (isAndroid == -1) {
33 | final String runtime = System.getProperty("java.runtime.name");
34 | isAndroid = (runtime != null && runtime.equals("Android Runtime")) ? 1 : 0;
35 | }
36 | return isAndroid == 1;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
20 |
23 |
24 |
--------------------------------------------------------------------------------
/ios/rrwallet/Service/BlockChain/DFBaseWallet.h:
--------------------------------------------------------------------------------
1 | //
2 | // DFWallet.h
3 | // rrwallet
4 | //
5 | // Created by muhuai on 2018/4/2.
6 | // Copyright © 2018年 Facebook. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | typedef NS_ENUM(NSUInteger, DFWalletType) {
12 | DFWalletTypeEthereum = 1,
13 | DFWalletTypeBitcoin = 2
14 | };
15 |
16 | typedef enum : NSUInteger {
17 | DFWalletSourceMnemonic,
18 | DFWalletSourcePrivateKey,
19 | DFWalletSourceKeyStore,
20 | } DFWalletSource;
21 |
22 |
23 | @interface DFBaseWallet: NSObject
24 | @property (nonatomic, strong) NSString *walletID;
25 | @property (nonatomic, assign) DFWalletType type;
26 | @property (nonatomic, assign) DFWalletSource source;
27 |
28 | - (instancetype)initWithDictionary:(NSDictionary *)dict;
29 |
30 | + (instancetype)walletWithID:(NSString *)walletID;
31 |
32 | + (instancetype)walletWithID:(NSString *)walletID source:(DFWalletSource)source;
33 |
34 | - (NSDictionary *)toDictionary;
35 |
36 | - (NSString *)mnemonicWithPassword:(NSString *)pwd;
37 |
38 | - (BOOL)unlock:(NSString *)pwd;
39 |
40 | - (void)lock;
41 |
42 | - (void)saveSeed:(NSData *)seed password:(NSString *)pwd;
43 |
44 | - (NSData *)seedWithPassword:(NSString *)pwd;
45 |
46 | - (void)dropSeedWithPassword:(NSString *)pwd;
47 | @end
48 |
--------------------------------------------------------------------------------
/src/component/common/GrowingTextInput.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from "react";
2 | import { TextInput } from "react-native";
3 | import { observer } from "mobx-react";
4 | import { observable, computed } from "mobx";
5 |
6 | const TEXTINPUT_INITIAL_HEIGHT = -1;
7 | @observer
8 | class GrowingTextInput extends Component {
9 | @observable height = TEXTINPUT_INITIAL_HEIGHT;
10 | @computed get style() {
11 | const outer = this.props.style;
12 | return [outer, this.height === TEXTINPUT_INITIAL_HEIGHT && { height: this.height }];
13 | }
14 | handleInputRef = ref => (this.input = ref);
15 | _onContentSizeChange = e => {
16 | const contentSize = e.nativeEvent.contentSize;
17 | this.height = contentSize.height;
18 |
19 | const outer = this.props.onContentSizeChange;
20 | if (outer) {
21 | outer(e);
22 | }
23 | };
24 | focus = () => {
25 | this.input && this.input.focus();
26 | };
27 | blur = () => {
28 | this.input && this.input.blur();
29 | };
30 | render() {
31 | return (
32 |
39 | );
40 | }
41 | }
42 |
43 | export default GrowingTextInput;
44 |
--------------------------------------------------------------------------------
/ios/rrwallet/LaunchScreen.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/module/wallet/wallet/ETHRPCProvider.js:
--------------------------------------------------------------------------------
1 | import network from "../../common/network";
2 | import { NETWORK_ENV_TESTNET } from "../../../config/const";
3 | import { BigNumber } from "bignumber.js";
4 | import ethereum, { unitMap } from "../../../util/ethereum";
5 |
6 | class ETHRPCProvider {
7 | /**
8 | *节点推荐gasPrice
9 | *
10 | * @memberof ETHRPCProvider
11 | */
12 | gasPrice = 15;
13 |
14 | constructor() {
15 | // this.fetchGasPrice()
16 | // setInterval(this.fetchGasPrice, 10 * 60 * 1000)
17 | }
18 |
19 | fetchGasPrice = async () => {
20 | const weiGasPrice = await network.jsonrpc(network.ETHRpcUrl, "eth_gasPrice", []);
21 | this.gasPrice = new BigNumber(weiGasPrice).div(unitMap.Gwei).toNumber();
22 | };
23 |
24 | ethGetTransactionCount = async (address, tag = "latest") => {
25 | return new BigNumber(
26 | await network.jsonrpc(network.ETHRpcUrl, "eth_getTransactionCount", [address, tag]),
27 | 16
28 | ).toNumber();
29 | };
30 | ethCall = async (obj, tag = "latest") => {
31 | return await network.jsonrpc(network.ETHRpcUrl, "eth_call", [obj, tag]);
32 | };
33 | ethGetTransactionReceipt = async txhash => {
34 | return await network.jsonrpc(network.ETHRpcUrl, "eth_getTransactionReceipt", [txhash]);
35 | };
36 | }
37 |
38 | export default new ETHRPCProvider();
39 |
--------------------------------------------------------------------------------
/ios/rrwallet/Service/BlockChain/Ethereum/DFEthereumRPCProvider.h:
--------------------------------------------------------------------------------
1 | //
2 | // DFEthereumJsonPRCClient.h
3 | // rrwallet
4 | //
5 | // Created by muhuai on 2018/3/1.
6 | // Copyright © 2018年 Facebook. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "DFWalletDefine.h"
11 | @class DFContractTransaction;
12 |
13 | typedef void (^DFEthereumJsonRPCCompletion)(NSDictionary *result, NSError *error);
14 |
15 | typedef enum : unsigned char {
16 | DFEthereumTypeHomestead = 0x01,
17 | DFEthereumTypeMorden = 0x02,
18 | DFEthereumTypeRopsten = 0x03,
19 | DFEthereumTypeRinkeby = 0x04
20 | } DFEthereumType;
21 |
22 | @interface DFEthereumRPCProvider : NSObject
23 |
24 | @property (nonatomic, assign, readonly) DFWalletEnv env;
25 |
26 | - (instancetype)initWithURL:(NSString *)url;
27 |
28 | - (instancetype)initWithEnv:(DFWalletEnv)env;
29 |
30 | - (void)getTransactionCount:(NSString *)address completion:(void (^)(NSInteger count, NSError *error))completion;
31 |
32 | - (void)sendContractTransaction:(DFContractTransaction *)transcation
33 | walletID:(NSString *)walletID
34 | broadcast:(BOOL)broadcast
35 | password:(NSString *)password
36 | completion:(void (^)(NSString *txHash, NSInteger nonce, NSError *error))completion;
37 | @end
38 |
--------------------------------------------------------------------------------
/src/component/common/FlatListLoadMoreView.js:
--------------------------------------------------------------------------------
1 | import React, { Component, PureComponent } from "react";
2 | import { StyleSheet, View, ActivityIndicator, Text } from "react-native";
3 | import PropTypes from "prop-types";
4 | import theme from "../../util/Theme";
5 | import i18n from "../../module/i18n/i18n";
6 |
7 | class FlatListLoadMoreView extends PureComponent {
8 | static propTypes = {
9 | status: PropTypes.oneOf(["empty", "loading", "nomore"]),
10 | text: PropTypes.string,
11 | };
12 |
13 | static defaultProps = {
14 | status: "empty",
15 | text: `- ${i18n.t("common-end-line")} -`,
16 | };
17 |
18 | render() {
19 | if (this.props.status === "empty") {
20 | return ;
21 | }
22 | return (
23 |
24 | {this.props.status === "loading" ? (
25 |
26 | ) : (
27 | {this.props.text}
28 | )}
29 |
30 | );
31 | }
32 | }
33 |
34 | const styles = StyleSheet.create({
35 | container: {
36 | flex: 1,
37 | height: 62,
38 | alignItems: "center",
39 | justifyContent: "center",
40 | },
41 | text: {
42 | fontSize: 12,
43 | color: theme.textColor.mainTitle,
44 | },
45 | });
46 | export default FlatListLoadMoreView;
47 |
--------------------------------------------------------------------------------
/android/app/src/main/java/com/renrenbit/rrwallet/react/module/webview/ShouldOverrideUrlLoadingEvent.java:
--------------------------------------------------------------------------------
1 | package com.renrenbit.rrwallet.react.module.webview;
2 |
3 | import com.facebook.react.bridge.Arguments;
4 | import com.facebook.react.bridge.WritableMap;
5 | import com.facebook.react.uimanager.events.Event;
6 | import com.facebook.react.uimanager.events.RCTEventEmitter;
7 |
8 | public class ShouldOverrideUrlLoadingEvent extends Event {
9 |
10 | public static final String EVENT_NAME = "shouldOverrideUrlLoading";
11 |
12 | private final String mUrl;
13 | private final int mNavigationType;
14 |
15 | public ShouldOverrideUrlLoadingEvent(int viewId, long timestampMs, String url, int navigationType) {
16 | super(viewId);
17 |
18 | mUrl = url;
19 | mNavigationType = navigationType;
20 | }
21 |
22 | @Override
23 | public String getEventName() {
24 | return EVENT_NAME;
25 | }
26 |
27 | @Override
28 | public void dispatch(RCTEventEmitter rctEventEmitter) {
29 | rctEventEmitter.receiveEvent(getViewTag(), getEventName(), serializeEventData());
30 | }
31 |
32 | private WritableMap serializeEventData() {
33 | WritableMap eventData = Arguments.createMap();
34 | eventData.putString("url", mUrl);
35 | eventData.putInt("navigationType", mNavigationType);
36 |
37 | return eventData;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/android/app/src/main/java/com/renrenbit/rrwallet/react/module/WalletNativePackage.java:
--------------------------------------------------------------------------------
1 | package com.renrenbit.rrwallet.react.module;
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 | import java.util.Arrays;
9 | import java.util.Collections;
10 | import java.util.List;
11 |
12 | /**
13 | * Created by jackQ on 2018/5/31.
14 | */
15 |
16 | public class WalletNativePackage implements ReactPackage {
17 |
18 | @Override
19 | public List createNativeModules(ReactApplicationContext reactContext) {
20 | return Arrays.asList(
21 | new RRRNNetworkModule(reactContext),
22 | new RRRNDeviceModule(reactContext),
23 | new RRRNEthereumModule(reactContext),
24 | new NotificationModule(reactContext),
25 | new RRRNBitcoinModule(reactContext),
26 | new RRRNQRDecoderModule(reactContext),
27 | new RRRNAnalysisModule(reactContext),
28 | new RRRNSplash(reactContext)
29 | );
30 | }
31 |
32 | @Override
33 | public List createViewManagers(ReactApplicationContext reactContext) {
34 | return Collections.emptyList();
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/ios/rrwallet/Service/BlockChain/Ethereum/DFContractTransaction.h:
--------------------------------------------------------------------------------
1 | //
2 | // DFContractTransaction.h
3 | // rrwallet
4 | //
5 | // Created by muhuai on 2018/8/19.
6 | // Copyright © 2018 Facebook. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 |
12 | @interface DFContractTransaction : NSObject
13 |
14 | @property (nonatomic, assign) NSInteger retryCount;
15 | @property (nonatomic, assign) NSInteger nonce;
16 |
17 | @property (nonatomic, strong, readonly) NSString *from;
18 | @property (nonatomic, strong, readonly) NSString *contract;
19 | @property (nonatomic, strong, readonly) NSString *amount;
20 | @property (nonatomic, strong, readonly) NSString *data;
21 | @property (nonatomic, strong, readonly) NSString *gasLimit;
22 | @property (nonatomic, strong, readonly) NSString *gasPrice;
23 | @property (nonatomic, assign, readonly) NSInteger chainID;
24 |
25 | - (instancetype)initWithFrom:(NSString *)from
26 | contract:(NSString *)contract
27 | amount:(NSString *)amount
28 | data:(NSString *)data
29 | gasLimit:(NSString *)gasLimit
30 | gasPrice:(NSString *)gasPrice
31 | nonce:(NSInteger)nonce
32 | chainID:(NSInteger)chain;
33 |
34 | - (Transaction *)origTransaction;
35 |
36 | @end
37 |
--------------------------------------------------------------------------------
/ios/rrwallet/RNBridgeModule/RRRNQRDecoder.m:
--------------------------------------------------------------------------------
1 | //
2 | // DFRNQRDecoder.m
3 | // rrwallet
4 | //
5 | // Created by 杨然 on 2018/10/31.
6 | // Copyright © 2018 Facebook. All rights reserved.
7 | //
8 |
9 | #import "RRRNQRDecoder.h"
10 | #import
11 | #import
12 |
13 | @implementation RRRNQRDecoder
14 |
15 | RCT_EXPORT_MODULE();
16 |
17 | RCT_REMAP_METHOD(decode, decode:(NSString *)path WithResolver:(RCTPromiseResolveBlock)resolve
18 | rejecter:(RCTPromiseRejectBlock)reject) {
19 | UIImage *pickImage = [[UIImage alloc] initWithContentsOfFile:[path stringByReplacingOccurrencesOfString:@"file://" withString:@""]];
20 | NSData *imageData = UIImagePNGRepresentation(pickImage);
21 | CIImage *ciImage = [CIImage imageWithData:imageData];
22 | CIContext *context = [CIContext contextWithOptions:@{kCIContextUseSoftwareRenderer : @(YES)}]; // 软件渲染
23 | CIDetector *detector = [CIDetector detectorOfType: CIDetectorTypeQRCode context:context options: @{CIDetectorAccuracy : CIDetectorAccuracyLow}];
24 |
25 | NSArray *feature = [detector featuresInImage:ciImage];
26 | if (feature.count) {
27 | resolve(((CIQRCodeFeature *)feature[0]).messageString);
28 | } else {
29 | reject(@"-100", @"未识别到二维码", [NSError errorWithDomain:NSURLErrorDomain code:-100 userInfo:@{NSLocalizedDescriptionKey: @"未识别到二维码"}]);
30 | }
31 | }
32 |
33 | @end
34 |
--------------------------------------------------------------------------------
/android/app/src/main/java/com/renrenbit/rrwallet/service/push/MessageHandler.java:
--------------------------------------------------------------------------------
1 | package com.renrenbit.rrwallet.service.push;
2 |
3 | import android.app.Notification;
4 | import android.content.Context;
5 |
6 | import com.umeng.message.UmengMessageHandler;
7 | import com.umeng.message.entity.UMessage;
8 |
9 | /**
10 | * Created by jackQ on 2018/6/18.
11 | */
12 |
13 | public class MessageHandler extends UmengMessageHandler {
14 |
15 | /**
16 | * 通知的回调方法
17 | *
18 | * @param context
19 | * @param msg
20 | */
21 | @Override
22 | public void dealWithNotificationMessage(Context context, UMessage msg) {
23 | //调用super则会走通知展示流程,不调用super则不展示通知
24 | super.dealWithNotificationMessage(context, msg);
25 | }
26 |
27 | @Override
28 | public void dealWithCustomMessage(Context context, UMessage uMessage) {
29 | PushEvent event = new PushEvent(uMessage.extra, uMessage.custom, uMessage.title, uMessage.text);
30 | PushManager.inst().handleMessage(context, event);
31 | }
32 |
33 | @Override
34 | public Notification getNotification(Context context, UMessage uMessage) {
35 | PushEvent event = new PushEvent(uMessage.extra, uMessage.custom, uMessage.title, uMessage.text);
36 | PushManager.inst().onReceiveMessage(context, event);
37 | return super.getNotification(context, uMessage);
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/ios/rrwallet/Service/Splash/RRSplashViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // RRSplashViewController.m
3 | // rrwallet
4 | //
5 | // Created by muhuai on 2018/12/19.
6 | // Copyright © 2018 Facebook. All rights reserved.
7 | //
8 |
9 | #import "RRSplashViewController.h"
10 |
11 | @interface RRSplashViewController ()
12 |
13 | @property (nonatomic, strong) UIImageView *logo;
14 | @property (nonatomic, assign) BOOL isFirstLaunch;
15 |
16 | @end
17 |
18 | @implementation RRSplashViewController
19 |
20 | - (instancetype)initWithFirstLaunch:(BOOL)isFirstLaunch {
21 | self = [super init];
22 | if (self) {
23 | self.isFirstLaunch = isFirstLaunch;
24 | }
25 | return self;
26 | }
27 |
28 | - (void)viewDidLoad {
29 | [super viewDidLoad];
30 |
31 | CGSize window = self.view.frame.size;
32 |
33 | self.view.backgroundColor = [UIColor colorWithRed:255.f / 255 green:255.f / 255 blue:255.f / 255 alpha:1.f];
34 |
35 | if (self.isFirstLaunch) {
36 | } else {
37 | self.logo = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"splash_logo"]];
38 | self.logo.frame = CGRectMake((window.width - self.logo.frame.size.width) / 2, (window.height - self.logo.frame.size.height) / 2 - 100, self.logo.frame.size.width, self.logo.frame.size.height);
39 |
40 | [self.view addSubview:self.logo];
41 | }
42 | }
43 |
44 | - (UIStatusBarStyle)preferredStatusBarStyle{
45 | return UIStatusBarStyleLightContent;
46 | }
47 | @end
48 |
--------------------------------------------------------------------------------
/src/util/Version.js:
--------------------------------------------------------------------------------
1 | import _ from "lodash";
2 |
3 | function isMatchedVersion(version, semver = "*") {
4 | if (!_.isString(version) || !_.isString(semver)) {
5 | return false;
6 | }
7 |
8 | semver = semver.split(" ").join("");
9 |
10 | if (semver === "*") {
11 | return true;
12 | }
13 |
14 | if (!/^(>=|>|<=|<|=)?\d\.\d\.\d$/.test(semver)) {
15 | return false;
16 | }
17 |
18 | const [target, operator = "="] = semver.split(/^(>=|>|<=|<|=)/).reverse();
19 | const versions = version.split(".").map(el => parseInt(el));
20 | const targets = target.split(".").map(el => parseInt(el));
21 |
22 | if (operator === "=") {
23 | return version === target;
24 | }
25 |
26 | for (let i = 0; i < targets.length; i++) {
27 | if (compare(versions[i], targets[i], operator)) {
28 | if (i == targets.length - 1) {
29 | return true;
30 | }
31 | continue;
32 | }
33 | return false;
34 | }
35 |
36 | return false;
37 | }
38 |
39 | function compare(a, b, operator) {
40 | switch (operator) {
41 | case ">":
42 | return a - b > 0 ? true : false;
43 | case ">=":
44 | return a - b >= +0 ? true : false;
45 | case "<":
46 | return a - b < 0 ? true : false;
47 | case "<=":
48 | return a - b <= +0 ? true : false;
49 | case "=":
50 | return a - b === 0 ? true : false;
51 | }
52 | }
53 |
54 | export default {
55 | isMatchedVersion,
56 | };
57 |
--------------------------------------------------------------------------------
/ios/rrwallet/Service/Wallet/ethers/ethers/ThirdParty/trezor-crypto/curves.c:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2016 Jochen Hoenicke
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining
5 | * a copy of this software and associated documentation files (the "Software"),
6 | * to deal in the Software without restriction, including without limitation
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 | * and/or sell copies of the Software, and to permit persons to whom the
9 | * Software is furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included
12 | * in all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
18 | * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 | * OTHER DEALINGS IN THE SOFTWARE.
21 | */
22 |
23 | const char SECP256K1_NAME[] = "secp256k1";
24 | const char NIST256P1_NAME[] = "nist256p1";
25 | const char ED25519_NAME[] = "ed25519";
26 | const char CURVE25519_NAME[] = "curve25519";
27 |
--------------------------------------------------------------------------------
/ios/rrwallet/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "20x20",
5 | "idiom" : "iphone",
6 | "filename" : "40X40.png",
7 | "scale" : "2x"
8 | },
9 | {
10 | "size" : "20x20",
11 | "idiom" : "iphone",
12 | "filename" : "60X60.png",
13 | "scale" : "3x"
14 | },
15 | {
16 | "size" : "29x29",
17 | "idiom" : "iphone",
18 | "filename" : "58X58.png",
19 | "scale" : "2x"
20 | },
21 | {
22 | "size" : "29x29",
23 | "idiom" : "iphone",
24 | "filename" : "87X87.png",
25 | "scale" : "3x"
26 | },
27 | {
28 | "size" : "40x40",
29 | "idiom" : "iphone",
30 | "filename" : "80X80.png",
31 | "scale" : "2x"
32 | },
33 | {
34 | "size" : "40x40",
35 | "idiom" : "iphone",
36 | "filename" : "120X120.png",
37 | "scale" : "3x"
38 | },
39 | {
40 | "size" : "60x60",
41 | "idiom" : "iphone",
42 | "filename" : "120X120-1.png",
43 | "scale" : "2x"
44 | },
45 | {
46 | "size" : "60x60",
47 | "idiom" : "iphone",
48 | "filename" : "180x180.png",
49 | "scale" : "3x"
50 | },
51 | {
52 | "size" : "1024x1024",
53 | "idiom" : "ios-marketing",
54 | "filename" : "1024X1024.png",
55 | "scale" : "1x"
56 | }
57 | ],
58 | "info" : {
59 | "version" : 1,
60 | "author" : "xcode"
61 | }
62 | }
--------------------------------------------------------------------------------
/ios/rrwallet/Service/Wallet/ethers/ethers/ThirdParty/trezor-crypto/curves.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2016 Jochen Hoenicke
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining
5 | * a copy of this software and associated documentation files (the "Software"),
6 | * to deal in the Software without restriction, including without limitation
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 | * and/or sell copies of the Software, and to permit persons to whom the
9 | * Software is furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included
12 | * in all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
18 | * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 | * OTHER DEALINGS IN THE SOFTWARE.
21 | */
22 |
23 | #ifndef __CURVES_H__
24 | #define __CURVES_H__
25 |
26 | extern const char SECP256K1_NAME[];
27 | extern const char NIST256P1_NAME[];
28 | extern const char ED25519_NAME[];
29 | extern const char CURVE25519_NAME[];
30 |
31 | #endif
32 |
--------------------------------------------------------------------------------
/src/component/common/EmptyView.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from "react";
2 | import { View, Text, StyleSheet, Image, ViewPropTypes } from "react-native";
3 | import PropTypes from "prop-types";
4 | import i18n from "../../module/i18n/i18n";
5 | import theme from "../../util/Theme";
6 |
7 | export default class EmptyView extends Component {
8 | static propTypes = {
9 | containerStyle: ViewPropTypes.style,
10 | imageSource: PropTypes.number,
11 | title: PropTypes.string,
12 | };
13 |
14 | constructor(props) {
15 | super(props);
16 |
17 | const { imageSource = require("@img/mine/empty_data.png"), title = i18n.common("empty-data") } = props;
18 | this.state = {
19 | imageSource,
20 | title,
21 | };
22 | }
23 |
24 | render() {
25 | return (
26 |
27 |
28 | {!!this.state.title && {this.state.title}}
29 |
30 | );
31 | }
32 | }
33 |
34 | const styles = StyleSheet.create({
35 | container: {
36 | width: "100%",
37 | height: "100%",
38 | alignItems: "center",
39 | paddingTop: 160,
40 | backgroundColor: theme.backgroundColor,
41 | },
42 | text: {
43 | marginTop: 22,
44 | fontSize: 14,
45 | paddingLeft: 16,
46 | paddingRight: 16,
47 | lineHeight: 18,
48 | color: theme.textColor.mainTitle,
49 | textAlign: "center",
50 | },
51 | });
52 |
--------------------------------------------------------------------------------
/android/app/src/main/java/com/renrenbit/rrwallet/network/cookie/CookieManager.java:
--------------------------------------------------------------------------------
1 | package com.renrenbit.rrwallet.network.cookie;
2 |
3 | import com.blankj.utilcode.util.Utils;
4 |
5 | import java.io.IOException;
6 | import java.net.URI;
7 | import java.util.List;
8 | import java.util.Map;
9 |
10 | import okhttp3.JavaNetCookieJar;
11 |
12 | /**
13 | * Created by jackQ on 2018/6/2.
14 | */
15 |
16 | public class CookieManager {
17 |
18 | private static CookieManager sInstance;
19 | private final CookieHandler mHandler;
20 | private final JavaNetCookieJar mCookieJar;
21 |
22 | private CookieManager() {
23 | mHandler = new CookieHandler(Utils.getApp());
24 | mCookieJar = new JavaNetCookieJar(mHandler);
25 | }
26 |
27 | public static CookieManager inst() {
28 | if (sInstance == null) {
29 | synchronized (CookieManager.class) {
30 | if (sInstance == null) {
31 | sInstance = new CookieManager();
32 | }
33 | }
34 | }
35 | return sInstance;
36 | }
37 |
38 | public JavaNetCookieJar getCookieJar() {
39 | return mCookieJar;
40 | }
41 |
42 | public Map> get(URI uri, Map> headers)
43 | throws IOException {
44 | return mHandler.get(uri, headers);
45 | }
46 |
47 | public void set(URI uri, Map> headers) throws IOException {
48 | mHandler.put(uri, headers);
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/android/app/src/main/java/com/renrenbit/rrwallet/react/module/RRRNQRDecoderModule.java:
--------------------------------------------------------------------------------
1 | package com.renrenbit.rrwallet.react.module;
2 |
3 | import com.renrenbit.rrwallet.utils.Constants;
4 | import com.renrenbit.rrwallet.utils.QRDecoder;
5 | import com.facebook.react.bridge.Promise;
6 | import com.facebook.react.bridge.ReactApplicationContext;
7 | import com.facebook.react.bridge.ReactContextBaseJavaModule;
8 | import com.facebook.react.bridge.ReactMethod;
9 | import com.facebook.react.module.annotations.ReactModule;
10 |
11 | import java.util.concurrent.ExecutionException;
12 |
13 |
14 | @ReactModule(name = Constants.REACT_MODULE_NAME_DFRN_QRDECODER)
15 | public class RRRNQRDecoderModule extends ReactContextBaseJavaModule {
16 | private final ReactApplicationContext mReaftContext;
17 | @Override
18 | public String getName() {
19 | return Constants.REACT_MODULE_NAME_DFRN_QRDECODER;
20 | }
21 |
22 | RRRNQRDecoderModule(ReactApplicationContext reactContext) {
23 | super(reactContext);
24 | mReaftContext = reactContext;
25 | }
26 |
27 | @ReactMethod
28 | public void decode(String path, Promise promise) throws ExecutionException, InterruptedException {
29 | QRDecoder decoder = new QRDecoder();
30 | QRDecoder.DecodeResult result = decoder.loadImageFromURL(path,mReaftContext);
31 | if (result.data != null) {
32 | promise.resolve(result.data);
33 | } else {
34 | promise.reject(result.errMsg);
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/ios/rrwallet/Service/Wallet/ethers/ethers/ThirdParty/trezor-crypto/secp256k1.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2013-2014 Tomas Dzetkulic
3 | * Copyright (c) 2013-2014 Pavol Rusnak
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining
6 | * a copy of this software and associated documentation files (the "Software"),
7 | * to deal in the Software without restriction, including without limitation
8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 | * and/or sell copies of the Software, and to permit persons to whom the
10 | * Software is furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included
13 | * in all copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
19 | * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21 | * OTHER DEALINGS IN THE SOFTWARE.
22 | */
23 |
24 | #ifndef __SECP256K1_H__
25 | #define __SECP256K1_H__
26 |
27 | #include
28 |
29 | #include "ecdsa.h"
30 | #include "bip32.h"
31 |
32 | extern const ecdsa_curve secp256k1;
33 | extern const curve_info secp256k1_info;
34 |
35 | #endif
36 |
--------------------------------------------------------------------------------