@ -0,0 +1,5 @@ |
|||
# Security Policy |
|||
|
|||
## Reporting a Vulnerability |
|||
|
|||
bluewallet at bluewallet dot io |
@ -1,19 +0,0 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<module external.linked.project.id="BlueWallet" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" type="JAVA_MODULE" version="4"> |
|||
<component name="FacetManager"> |
|||
<facet type="java-gradle" name="Java-Gradle"> |
|||
<configuration> |
|||
<option name="BUILD_FOLDER_PATH" value="$MODULE_DIR$/build" /> |
|||
<option name="BUILDABLE" value="false" /> |
|||
</configuration> |
|||
</facet> |
|||
</component> |
|||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="true"> |
|||
<exclude-output /> |
|||
<content url="file://$MODULE_DIR$"> |
|||
<excludeFolder url="file://$MODULE_DIR$/.gradle" /> |
|||
</content> |
|||
<orderEntry type="inheritedJdk" /> |
|||
<orderEntry type="sourceFolder" forTests="false" /> |
|||
</component> |
|||
</module> |
@ -1,16 +0,0 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<module external.system.id="GRADLE" type="JAVA_MODULE" version="4"> |
|||
<component name="FacetManager"> |
|||
<facet type="android-gradle" name="Android-Gradle"> |
|||
<configuration> |
|||
<option name="GRADLE_PROJECT_PATH" value=":" /> |
|||
</configuration> |
|||
</facet> |
|||
</component> |
|||
<component name="NewModuleRootManager" inherit-compiler-output="true"> |
|||
<exclude-output /> |
|||
<content url="file://$MODULE_DIR$" /> |
|||
<orderEntry type="jdk" jdkName="1.8" jdkType="JavaSDK" /> |
|||
<orderEntry type="sourceFolder" forTests="false" /> |
|||
</component> |
|||
</module> |
@ -1,192 +0,0 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<module external.linked.project.id=":app" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" type="JAVA_MODULE" version="4"> |
|||
<component name="FacetManager"> |
|||
<facet type="android-gradle" name="Android-Gradle"> |
|||
<configuration> |
|||
<option name="GRADLE_PROJECT_PATH" value=":app" /> |
|||
</configuration> |
|||
</facet> |
|||
<facet type="android" name="Android"> |
|||
<configuration> |
|||
<option name="SELECTED_BUILD_VARIANT" value="debug" /> |
|||
<option name="ASSEMBLE_TASK_NAME" value="assembleDebug" /> |
|||
<option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" /> |
|||
<afterSyncTasks> |
|||
<task>generateDebugSources</task> |
|||
</afterSyncTasks> |
|||
<option name="ALLOW_USER_CONFIGURATION" value="false" /> |
|||
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" /> |
|||
<option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" /> |
|||
<option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/src/main/res;file://$MODULE_DIR$/build/generated/res/rs/debug;file://$MODULE_DIR$/build/generated/res/resValues/debug" /> |
|||
<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" /> |
|||
</configuration> |
|||
</facet> |
|||
</component> |
|||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7"> |
|||
<output url="file://$MODULE_DIR$/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes" /> |
|||
<output-test url="file://$MODULE_DIR$/build/intermediates/javac/debugUnitTest/compileDebugUnitTestJavaWithJavac/classes" /> |
|||
<exclude-output /> |
|||
<content url="file://$MODULE_DIR$"> |
|||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/debug" isTestSource="false" generated="true" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/build/generated/aidl_source_output_dir/debug/compileDebugAidl/out" isTestSource="false" generated="true" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/build/generated/renderscript_source_output_dir/debug/compileDebugRenderscript/out" isTestSource="false" generated="true" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/react/debug" type="java-resource" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/debug" type="java-resource" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/androidTest/debug" isTestSource="true" generated="true" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/build/generated/aidl_source_output_dir/debugAndroidTest/compileDebugAndroidTestAidl/out" isTestSource="true" generated="true" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/androidTest/debug" isTestSource="true" generated="true" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/build/generated/renderscript_source_output_dir/debugAndroidTest/compileDebugAndroidTestRenderscript/out" isTestSource="true" generated="true" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/androidTest/debug" type="java-test-resource" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/androidTest/debug" type="java-test-resource" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/test/debug" isTestSource="true" generated="true" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/src/debug/resources" type="java-resource" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/src/debug/assets" type="java-resource" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/src/debug/aidl" isTestSource="false" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/src/debug/java" isTestSource="false" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/src/debug/shaders" isTestSource="false" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/res" type="java-test-resource" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/resources" type="java-test-resource" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/assets" type="java-test-resource" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/aidl" isTestSource="true" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/java" isTestSource="true" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/rs" isTestSource="true" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/shaders" isTestSource="true" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/res" type="java-test-resource" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/resources" type="java-test-resource" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/assets" type="java-test-resource" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/aidl" isTestSource="true" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/java" isTestSource="true" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/rs" isTestSource="true" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/shaders" isTestSource="true" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/src/main/res" type="java-resource" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/src/main/assets" type="java-resource" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/src/main/aidl" isTestSource="false" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/src/main/shaders" isTestSource="false" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/shaders" isTestSource="true" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/src/test/res" type="java-test-resource" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/src/test/assets" type="java-test-resource" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/src/test/aidl" isTestSource="true" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/src/test/rs" isTestSource="true" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/src/test/shaders" isTestSource="true" /> |
|||
<excludeFolder url="file://$MODULE_DIR$/build/generated/not_namespaced_r_class_sources" /> |
|||
<excludeFolder url="file://$MODULE_DIR$/build/generated/source/r" /> |
|||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/annotation_processor_list" /> |
|||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/apk_list" /> |
|||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/blame" /> |
|||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/bundle_manifest" /> |
|||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/check_manifest_result" /> |
|||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/compatible_screen_manifest" /> |
|||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex" /> |
|||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/external_libs_dex" /> |
|||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" /> |
|||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/instant_app_manifest" /> |
|||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/instant_run_merged_manifests" /> |
|||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/javac" /> |
|||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/jniLibs" /> |
|||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/legacy_multidex_aapt_derived_proguard_rules" /> |
|||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/legacy_multidex_main_dex_list" /> |
|||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/lint_jar" /> |
|||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/merged_assets" /> |
|||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/merged_manifests" /> |
|||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/metadata_feature_manifest" /> |
|||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/prebuild" /> |
|||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/processed_res" /> |
|||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" /> |
|||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" /> |
|||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/shader_assets" /> |
|||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/shaders" /> |
|||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/signing_config" /> |
|||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" /> |
|||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/transforms" /> |
|||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/validate_signing_config" /> |
|||
<excludeFolder url="file://$MODULE_DIR$/build/outputs" /> |
|||
<excludeFolder url="file://$MODULE_DIR$/build/tmp" /> |
|||
</content> |
|||
<orderEntry type="jdk" jdkName="Android API 27 Platform" jdkType="Android SDK" /> |
|||
<orderEntry type="sourceFolder" forTests="false" /> |
|||
<orderEntry type="library" name="Gradle: com.squareup.okhttp3:okhttp-urlconnection:3.12.1@jar" level="project" /> |
|||
<orderEntry type="library" name="Gradle: com.facebook.fresco:fresco:1.10.0@aar" level="project" /> |
|||
<orderEntry type="library" name="Gradle: com.android.support:support-fragment:28.0.0@aar" level="project" /> |
|||
<orderEntry type="library" name="Gradle: com.android.support:localbroadcastmanager:28.0.0@aar" level="project" /> |
|||
<orderEntry type="library" name="Gradle: com.facebook.fresco:fbcore:1.10.0@aar" level="project" /> |
|||
<orderEntry type="library" name="Gradle: com.android.support:animated-vector-drawable:28.0.0@aar" level="project" /> |
|||
<orderEntry type="library" name="Gradle: com.facebook.fresco:drawee:1.10.0@aar" level="project" /> |
|||
<orderEntry type="library" name="Gradle: android.arch.lifecycle:viewmodel:1.1.1@aar" level="project" /> |
|||
<orderEntry type="library" name="Gradle: com.squareup.okhttp3:okhttp:3.12.1@jar" level="project" /> |
|||
<orderEntry type="library" name="Gradle: com.android.support:loader:28.0.0@aar" level="project" /> |
|||
<orderEntry type="library" name="Gradle: android.arch.core:runtime:1.1.1@aar" level="project" /> |
|||
<orderEntry type="library" name="Gradle: android.arch.lifecycle:livedata-core:1.1.1@aar" level="project" /> |
|||
<orderEntry type="library" name="Gradle: com.android.support:cursoradapter:28.0.0@aar" level="project" /> |
|||
<orderEntry type="library" name="Gradle: android.arch.lifecycle:runtime:1.1.1@aar" level="project" /> |
|||
<orderEntry type="library" name="Gradle: com.android.support:support-compat:28.0.0@aar" level="project" /> |
|||
<orderEntry type="library" name="Gradle: com.facebook.fresco:imagepipeline-base:1.10.0@aar" level="project" /> |
|||
<orderEntry type="library" name="Gradle: com.google.zxing:core:3.3.3@jar" level="project" /> |
|||
<orderEntry type="library" name="Gradle: javax.inject:javax.inject:1@jar" level="project" /> |
|||
<orderEntry type="library" name="Gradle: com.facebook.soloader:soloader:0.6.0@aar" level="project" /> |
|||
<orderEntry type="library" name="Gradle: com.google.code.findbugs:jsr305:3.0.2@jar" level="project" /> |
|||
<orderEntry type="library" name="Gradle: com.android.support:support-vector-drawable:28.0.0@aar" level="project" /> |
|||
<orderEntry type="library" name="Gradle: com.android.support:support-core-utils:28.0.0@aar" level="project" /> |
|||
<orderEntry type="library" name="Gradle: com.android.support:support-annotations:28.0.0@jar" level="project" /> |
|||
<orderEntry type="library" name="Gradle: com.android.support:interpolator:28.0.0@aar" level="project" /> |
|||
<orderEntry type="library" name="Gradle: android.arch.lifecycle:livedata:1.1.1@aar" level="project" /> |
|||
<orderEntry type="library" name="Gradle: com.android.support:drawerlayout:28.0.0@aar" level="project" /> |
|||
<orderEntry type="library" name="Gradle: com.android.support:documentfile:28.0.0@aar" level="project" /> |
|||
<orderEntry type="library" name="Gradle: com.android.support:slidingpanelayout:28.0.0@aar" level="project" /> |
|||
<orderEntry type="library" name="Gradle: com.parse.bolts:bolts-tasks:1.4.0@jar" level="project" /> |
|||
<orderEntry type="library" name="Gradle: com.android.support:appcompat-v7:28.0.0@aar" level="project" /> |
|||
<orderEntry type="library" scope="TEST" name="Gradle: com.android.support:multidex-instrumentation:1.0.2@aar" level="project" /> |
|||
<orderEntry type="library" name="Gradle: com.android.support:collections:28.0.0@jar" level="project" /> |
|||
<orderEntry type="library" name="Gradle: com.android.support:support-core-ui:28.0.0@aar" level="project" /> |
|||
<orderEntry type="library" name="Gradle: com.facebook.fresco:imagepipeline-okhttp3:1.10.0@aar" level="project" /> |
|||
<orderEntry type="library" name="Gradle: com.android.support:asynclayoutinflater:28.0.0@aar" level="project" /> |
|||
<orderEntry type="library" name="Gradle: com.android.support:print:28.0.0@aar" level="project" /> |
|||
<orderEntry type="library" name="Gradle: android.arch.core:common:1.1.1@jar" level="project" /> |
|||
<orderEntry type="library" name="Gradle: com.android.support:versionedparcelable:28.0.0@aar" level="project" /> |
|||
<orderEntry type="library" name="Gradle: com.facebook.infer.annotation:infer-annotation:0.11.2@jar" level="project" /> |
|||
<orderEntry type="library" name="Gradle: com.facebook.fresco:imagepipeline:1.10.0@aar" level="project" /> |
|||
<orderEntry type="library" name="Gradle: com.android.support:viewpager:28.0.0@aar" level="project" /> |
|||
<orderEntry type="library" name="Gradle: com.facebook.react:react-native:0.59.6@aar" level="project" /> |
|||
<orderEntry type="library" name="Gradle: android.arch.lifecycle:common:1.1.1@jar" level="project" /> |
|||
<orderEntry type="library" name="Gradle: com.android.support:coordinatorlayout:28.0.0@aar" level="project" /> |
|||
<orderEntry type="library" name="Gradle: com.android.support:customview:28.0.0@aar" level="project" /> |
|||
<orderEntry type="library" name="Gradle: com.android.support:swiperefreshlayout:28.0.0@aar" level="project" /> |
|||
<orderEntry type="library" name="Gradle: com.android.support:multidex:1.0.3@aar" level="project" /> |
|||
<orderEntry type="library" name="Gradle: com.squareup.okio:okio:1.15.0@jar" level="project" /> |
|||
<orderEntry type="library" name="Gradle: com.koushikdutta.async:androidasync:2.1.6@jar" level="project" /> |
|||
<orderEntry type="module" module-name="react-native-device-info" /> |
|||
<orderEntry type="module" module-name="react-native-google-analytics-bridge" /> |
|||
<orderEntry type="module" module-name="react-native-obscure" /> |
|||
<orderEntry type="module" module-name="react-native-camera" /> |
|||
<orderEntry type="module" module-name="react-native-webview" /> |
|||
<orderEntry type="module" module-name="@react-native-community_slider" /> |
|||
<orderEntry type="module" module-name="react-native-sentry" /> |
|||
<orderEntry type="module" module-name="react-native-linear-gradient" /> |
|||
<orderEntry type="module" module-name="react-native-image-picker" /> |
|||
<orderEntry type="module" module-name="react-native-vector-icons" /> |
|||
<orderEntry type="module" module-name="react-native-haptic-feedback" /> |
|||
<orderEntry type="module" module-name="@react-native-community_async-storage" /> |
|||
<orderEntry type="module" module-name="react-native-prompt-android" /> |
|||
<orderEntry type="module" module-name="react-native-gesture-handler" /> |
|||
<orderEntry type="module" module-name="react-native-randombytes" /> |
|||
<orderEntry type="module" module-name="react-native-svg" /> |
|||
<orderEntry type="module" module-name="@remobile_react-native-qrcode-local-image" /> |
|||
<orderEntry type="module" module-name="react-native-fs" /> |
|||
<orderEntry type="module" module-name="react-native-tcp" /> |
|||
<orderEntry type="library" name="Gradle: android-android-27" level="project" /> |
|||
</component> |
|||
</module> |
@ -0,0 +1,8 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" |
|||
xmlns:tools="http://schemas.android.com/tools"> |
|||
|
|||
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/> |
|||
|
|||
<application android:usesCleartextTraffic="true" tools:targetApi="28" tools:ignore="GoogleAppIndexingWarning" /> |
|||
</manifest> |
@ -0,0 +1,3 @@ |
|||
{ |
|||
"app_secret": "7a010505-cccc-4e40-aa6b-fbbe0624c8d9" |
|||
} |
@ -1,28 +1,15 @@ |
|||
package io.bluewallet.bluewallet; |
|||
|
|||
import com.facebook.react.ReactActivity; |
|||
import com.facebook.react.ReactActivityDelegate; |
|||
import com.facebook.react.ReactRootView; |
|||
import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView; |
|||
|
|||
public class MainActivity extends ReactActivity { |
|||
|
|||
/** |
|||
/** |
|||
* Returns the name of the main component registered from JavaScript. |
|||
* This is used to schedule rendering of the component. |
|||
*/ |
|||
@Override |
|||
protected String getMainComponentName() { |
|||
return "BlueWallet"; // this one too
|
|||
return "BlueWallet"; |
|||
} |
|||
|
|||
@Override |
|||
protected ReactActivityDelegate createReactActivityDelegate() { |
|||
return new ReactActivityDelegate(this, getMainComponentName()) { |
|||
@Override |
|||
protected ReactRootView createRootView() { |
|||
return new RNGestureHandlerEnabledRootView(MainActivity.this); |
|||
} |
|||
}; |
|||
} |
|||
} |
|||
|
@ -1,3 +1,5 @@ |
|||
<resources> |
|||
<string name="app_name">BlueWallet</string> |
|||
<string name="appCenterCrashes_whenToSendCrashes" moduleConfig="true" translatable="false">ASK_JAVASCRIPT</string> |
|||
<string name="appCenterAnalytics_whenToEnableAnalytics" moduleConfig="true" translatable="false">ALWAYS_SEND</string> |
|||
</resources> |
|||
|
@ -1 +0,0 @@ |
|||
./gradlew assembleRelease |
@ -1,8 +0,0 @@ |
|||
keystore( |
|||
name = "debug", |
|||
properties = "debug.keystore.properties", |
|||
store = "debug.keystore", |
|||
visibility = [ |
|||
"PUBLIC", |
|||
], |
|||
) |
@ -1,4 +0,0 @@ |
|||
key.store=debug.keystore |
|||
key.alias=androiddebugkey |
|||
key.store.password=android |
|||
key.alias.password=android |
@ -1,10 +0,0 @@ |
|||
v3.5.0 |
|||
------ |
|||
|
|||
ADD: Create LND invoice |
|||
ADD: Ability to show wallet XPUB in options |
|||
ADD: translations for german (DE) |
|||
ADD: Set receive amount & label |
|||
ADD: Added more Fiat currencies |
|||
ADD: help text in lighning settings |
|||
ADD: CZ locale |
@ -1,9 +0,0 @@ |
|||
v3.5.5 |
|||
------ |
|||
|
|||
ADD: pay zero-amount (tip) invoices |
|||
ADD: lightning withdrawal through zigzag |
|||
ADD: Thai translation |
|||
ADD: Dutch translation |
|||
ADD: Added Singapore Dollars |
|||
ADD: Added AUD, VEF, and ZAR fiats. |
@ -1 +0,0 @@ |
|||
Initial Android release |
@ -1 +0,0 @@ |
|||
Bug fixes and performance improvements |
@ -1 +0,0 @@ |
|||
Bug fixes and performance improvements |
@ -1 +0,0 @@ |
|||
Bug fixes and performance improvements |
@ -1,39 +0,0 @@ |
|||
Store, send and receive bitcoin with the wallet focus on security and simplicity. |
|||
|
|||
On BlueWallet you own you private keys. |
|||
|
|||
You can instantly transact with anyone in the world and transform the financial system right from your pocket. |
|||
|
|||
Create for free unlimited number of wallets or access your existing one on your Android device. It's simple and fast. |
|||
|
|||
_____ |
|||
|
|||
Here's what you get: |
|||
|
|||
1 - Security by design |
|||
|
|||
Open Source |
|||
MIT licensed, you can build it and run it on your own! Made with ReactNative |
|||
|
|||
Plausible deniability |
|||
Password which decrypts fake wallets if you are forced to disclose your access |
|||
|
|||
Full encryption |
|||
You can protect and encrypt your wallet by defining a password |
|||
|
|||
SegWit & HD wallets |
|||
SegWit supported and HD wallets enable |
|||
|
|||
2 - Focused on your experience |
|||
|
|||
Be in control |
|||
Private keys never leave your device. You control your private keys |
|||
|
|||
Flexible fees |
|||
Starting from 1 Satoshi. Defined by you, the user |
|||
|
|||
Replace-By-Fee |
|||
(RBF) Speed-up your transactions by increasing the fee (BIP125) |
|||
|
|||
Sentinel wallets new |
|||
Watch-only wallets allow you to keep an eye on your cold storage without touching the hardware. |
Before Width: | Height: | Size: 87 KiB |
Before Width: | Height: | Size: 4.1 KiB |
@ -1 +0,0 @@ |
|||
A Bitcoin & Lightning wallet for android. Easy to use and secure |
@ -1 +0,0 @@ |
|||
BlueWallet - Bitcoin & Lightning Wallet |
@ -1,5 +0,0 @@ |
|||
defaults.url=https://sentry.io/ |
|||
defaults.org=bluewallet |
|||
defaults.project=bluewallet |
|||
auth.token=0ee298bd4d3743819f710a5ed555f5429e4ffe64acbb41ac933f2745b0c163da |
|||
cli.executable=node_modules/@sentry/cli/bin/sentry-cli |
@ -1,41 +1,3 @@ |
|||
rootProject.name = 'BlueWallet' |
|||
include ':@react-native-community_async-storage' |
|||
project(':@react-native-community_async-storage').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-community/async-storage/android') |
|||
include ':@react-native-community_slider' |
|||
project(':@react-native-community_slider').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-community/slider/android') |
|||
include ':react-native-obscure' |
|||
project(':react-native-obscure').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-obscure/android') |
|||
include ':react-native-tcp' |
|||
project(':react-native-tcp').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-tcp/android') |
|||
include ':@remobile_react-native-qrcode-local-image' |
|||
project(':@remobile_react-native-qrcode-local-image').projectDir = new File(rootProject.projectDir, '../node_modules/@remobile/react-native-qrcode-local-image/android') |
|||
include ':react-native-image-picker' |
|||
project(':react-native-image-picker').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-image-picker/android') |
|||
include ':react-native-webview' |
|||
project(':react-native-webview').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-webview/android') |
|||
include ':react-native-svg' |
|||
project(':react-native-svg').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-svg/android') |
|||
include ':react-native-vector-icons' |
|||
project(':react-native-vector-icons').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-vector-icons/android') |
|||
include ':react-native-sentry' |
|||
project(':react-native-sentry').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-sentry/android') |
|||
include ':react-native-randombytes' |
|||
project(':react-native-randombytes').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-randombytes/android') |
|||
include ':react-native-prompt-android' |
|||
project(':react-native-prompt-android').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-prompt-android/android') |
|||
include ':react-native-linear-gradient' |
|||
project(':react-native-linear-gradient').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-linear-gradient/android') |
|||
include ':react-native-haptic-feedback' |
|||
project(':react-native-haptic-feedback').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-haptic-feedback/android') |
|||
include ':react-native-google-analytics-bridge' |
|||
project(':react-native-google-analytics-bridge').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-google-analytics-bridge/android') |
|||
include ':react-native-gesture-handler' |
|||
project(':react-native-gesture-handler').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-gesture-handler/android') |
|||
include ':react-native-fs' |
|||
project(':react-native-fs').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-fs/android') |
|||
include ':react-native-device-info' |
|||
project(':react-native-device-info').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-device-info/android') |
|||
include ':react-native-camera' |
|||
project(':react-native-camera').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-camera/android') |
|||
|
|||
apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) |
|||
include ':app' |
|||
|
@ -1 +0,0 @@ |
|||
fastlane supply --json_key ~/Documents/bluewalletsecure/api-8414470778596272879-665287-df921afdf533.json --package_name io.bluewallet.bluewallet --apk ~/Documents/BlueWallet/android/app/build/outputs/apk/release/app-release.apk |
@ -0,0 +1,332 @@ |
|||
import { HDSegwitBech32Wallet, SegwitBech32Wallet } from './'; |
|||
const bitcoin = require('bitcoinjs5'); |
|||
const BlueElectrum = require('../BlueElectrum'); |
|||
const reverse = require('buffer-reverse'); |
|||
const BigNumber = require('bignumber.js'); |
|||
|
|||
/** |
|||
* Represents transaction of a BIP84 wallet. |
|||
* Helpers for RBF, CPFP etc. |
|||
*/ |
|||
export class HDSegwitBech32Transaction { |
|||
/** |
|||
* @param txhex {string|null} Object is initialized with txhex |
|||
* @param txid {string|null} If txhex not present - txid whould be present |
|||
* @param wallet {HDSegwitBech32Wallet|null} If set - a wallet object to which transacton belongs |
|||
*/ |
|||
constructor(txhex, txid, wallet) { |
|||
if (!txhex && !txid) throw new Error('Bad arguments'); |
|||
this._txhex = txhex; |
|||
this._txid = txid; |
|||
|
|||
if (wallet) { |
|||
if (wallet.type === HDSegwitBech32Wallet.type) { |
|||
/** @type {HDSegwitBech32Wallet} */ |
|||
this._wallet = wallet; |
|||
} else { |
|||
throw new Error('Only HD Bech32 wallets supported'); |
|||
} |
|||
} |
|||
|
|||
if (this._txhex) this._txDecoded = bitcoin.Transaction.fromHex(this._txhex); |
|||
this._remoteTx = null; |
|||
} |
|||
|
|||
/** |
|||
* If only txid present - we fetch hex |
|||
* |
|||
* @returns {Promise<void>} |
|||
* @private |
|||
*/ |
|||
async _fetchTxhexAndDecode() { |
|||
let hexes = await BlueElectrum.multiGetTransactionByTxid([this._txid], 10, false); |
|||
this._txhex = hexes[this._txid]; |
|||
if (!this._txhex) throw new Error("Transaction can't be found in mempool"); |
|||
this._txDecoded = bitcoin.Transaction.fromHex(this._txhex); |
|||
} |
|||
|
|||
/** |
|||
* Returns max used sequence for this transaction. Next RBF transaction |
|||
* should have this sequence + 1 |
|||
* |
|||
* @returns {Promise<number>} |
|||
*/ |
|||
async getMaxUsedSequence() { |
|||
if (!this._txDecoded) await this._fetchTxhexAndDecode(); |
|||
|
|||
let max = 0; |
|||
for (let inp of this._txDecoded.ins) { |
|||
max = Math.max(inp.sequence, max); |
|||
} |
|||
|
|||
return max; |
|||
} |
|||
|
|||
/** |
|||
* Basic check that Sequence num for this TX is replaceable |
|||
* |
|||
* @returns {Promise<boolean>} |
|||
*/ |
|||
async isSequenceReplaceable() { |
|||
return (await this.getMaxUsedSequence()) < bitcoin.Transaction.DEFAULT_SEQUENCE; |
|||
} |
|||
|
|||
/** |
|||
* If internal extended tx data not set - this is a method |
|||
* to fetch and set this data from electrum. Its different data from |
|||
* decoded hex - it contains confirmations etc. |
|||
* |
|||
* @returns {Promise<void>} |
|||
* @private |
|||
*/ |
|||
async _fetchRemoteTx() { |
|||
let result = await BlueElectrum.multiGetTransactionByTxid([this._txid || this._txDecoded.getId()]); |
|||
this._remoteTx = Object.values(result)[0]; |
|||
} |
|||
|
|||
/** |
|||
* Fetches from electrum actual confirmations number for this tx |
|||
* |
|||
* @returns {Promise<Number>} |
|||
*/ |
|||
async getRemoteConfirmationsNum() { |
|||
if (!this._remoteTx) await this._fetchRemoteTx(); |
|||
return this._remoteTx.confirmations || 0; // stupid undefined
|
|||
} |
|||
|
|||
/** |
|||
* Checks that tx belongs to a wallet and also |
|||
* tx value is < 0, which means its a spending transaction |
|||
* definately initiated by us, can be RBF'ed. |
|||
* |
|||
* @returns {Promise<boolean>} |
|||
*/ |
|||
async isOurTransaction() { |
|||
if (!this._wallet) throw new Error('Wallet required for this method'); |
|||
let found = false; |
|||
for (let tx of this._wallet.getTransactions()) { |
|||
if (tx.txid === (this._txid || this._txDecoded.getId())) { |
|||
// its our transaction, and its spending transaction, which means we initiated it
|
|||
if (tx.value < 0) found = true; |
|||
} |
|||
} |
|||
return found; |
|||
} |
|||
|
|||
/** |
|||
* Checks that tx belongs to a wallet and also |
|||
* tx value is > 0, which means its a receiving transaction and thus |
|||
* can be CPFP'ed. |
|||
* |
|||
* @returns {Promise<boolean>} |
|||
*/ |
|||
async isToUsTransaction() { |
|||
if (!this._wallet) throw new Error('Wallet required for this method'); |
|||
let found = false; |
|||
for (let tx of this._wallet.getTransactions()) { |
|||
if (tx.txid === (this._txid || this._txDecoded.getId())) { |
|||
if (tx.value > 0) found = true; |
|||
} |
|||
} |
|||
return found; |
|||
} |
|||
|
|||
/** |
|||
* Returns all the info about current transaction which is needed to do a replacement TX |
|||
* * fee - current tx fee |
|||
* * utxos - UTXOs current tx consumes |
|||
* * changeAmount - amount of satoshis that sent to change address (or addresses) we control |
|||
* * feeRate - sat/byte for current tx |
|||
* * targets - destination(s) of funds (outputs we do not control) |
|||
* * unconfirmedUtxos - UTXOs created by this transaction (only the ones we control) |
|||
* |
|||
* @returns {Promise<{fee: number, utxos: Array, unconfirmedUtxos: Array, changeAmount: number, feeRate: number, targets: Array}>} |
|||
*/ |
|||
async getInfo() { |
|||
if (!this._wallet) throw new Error('Wallet required for this method'); |
|||
if (!this._remoteTx) await this._fetchRemoteTx(); |
|||
if (!this._txDecoded) await this._fetchTxhexAndDecode(); |
|||
|
|||
let prevInputs = []; |
|||
for (let inp of this._txDecoded.ins) { |
|||
let reversedHash = Buffer.from(reverse(inp.hash)); |
|||
reversedHash = reversedHash.toString('hex'); |
|||
prevInputs.push(reversedHash); |
|||
} |
|||
|
|||
let prevTransactions = await BlueElectrum.multiGetTransactionByTxid(prevInputs); |
|||
|
|||
// fetched, now lets count how much satoshis went in
|
|||
let wentIn = 0; |
|||
let utxos = []; |
|||
for (let inp of this._txDecoded.ins) { |
|||
let reversedHash = Buffer.from(reverse(inp.hash)); |
|||
reversedHash = reversedHash.toString('hex'); |
|||
if (prevTransactions[reversedHash] && prevTransactions[reversedHash].vout && prevTransactions[reversedHash].vout[inp.index]) { |
|||
let value = prevTransactions[reversedHash].vout[inp.index].value; |
|||
value = new BigNumber(value).multipliedBy(100000000).toNumber(); |
|||
wentIn += value; |
|||
let address = SegwitBech32Wallet.witnessToAddress(inp.witness[inp.witness.length - 1]); |
|||
utxos.push({ vout: inp.index, value: value, txId: reversedHash, address: address }); |
|||
} |
|||
} |
|||
|
|||
// counting how much went into actual outputs
|
|||
|
|||
let wasSpent = 0; |
|||
for (let outp of this._txDecoded.outs) { |
|||
wasSpent += +outp.value; |
|||
} |
|||
|
|||
let fee = wentIn - wasSpent; |
|||
let feeRate = Math.floor(fee / (this._txhex.length / 2)); |
|||
if (feeRate === 0) feeRate = 1; |
|||
|
|||
// lets take a look at change
|
|||
let changeAmount = 0; |
|||
let targets = []; |
|||
for (let outp of this._remoteTx.vout) { |
|||
let address = outp.scriptPubKey.addresses[0]; |
|||
let value = new BigNumber(outp.value).multipliedBy(100000000).toNumber(); |
|||
if (this._wallet.weOwnAddress(address)) { |
|||
changeAmount += value; |
|||
} else { |
|||
// this is target
|
|||
targets.push({ value: value, address: address }); |
|||
} |
|||
} |
|||
|
|||
// lets find outputs we own that current transaction creates. can be used in CPFP
|
|||
let unconfirmedUtxos = []; |
|||
for (let outp of this._remoteTx.vout) { |
|||
let address = outp.scriptPubKey.addresses[0]; |
|||
let value = new BigNumber(outp.value).multipliedBy(100000000).toNumber(); |
|||
if (this._wallet.weOwnAddress(address)) { |
|||
unconfirmedUtxos.push({ |
|||
vout: outp.n, |
|||
value: value, |
|||
txId: this._txid || this._txDecoded.getId(), |
|||
address: address, |
|||
}); |
|||
} |
|||
} |
|||
|
|||
return { fee, feeRate, targets, changeAmount, utxos, unconfirmedUtxos }; |
|||
} |
|||
|
|||
/** |
|||
* Checks if all outputs belong to us, that |
|||
* means we already canceled this tx and we can only bump fees |
|||
* |
|||
* @returns {Promise<boolean>} |
|||
*/ |
|||
async canCancelTx() { |
|||
if (!this._wallet) throw new Error('Wallet required for this method'); |
|||
if (!this._txDecoded) await this._fetchTxhexAndDecode(); |
|||
|
|||
// if theres at least one output we dont own - we can cancel this transaction!
|
|||
for (let outp of this._txDecoded.outs) { |
|||
if (!this._wallet.weOwnAddress(SegwitBech32Wallet.scriptPubKeyToAddress(outp.script))) return true; |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
/** |
|||
* Creates an RBF transaction that can replace previous one and basically cancel it (rewrite |
|||
* output to the one our wallet controls). Note, this cannot add more utxo in RBF transaction if |
|||
* newFeerate is too high |
|||
* |
|||
* @param newFeerate {number} Sat/byte. Should be greater than previous tx feerate |
|||
* @returns {Promise<{outputs: Array, tx: Transaction, inputs: Array, fee: Number}>} |
|||
*/ |
|||
async createRBFcancelTx(newFeerate) { |
|||
if (!this._wallet) throw new Error('Wallet required for this method'); |
|||
if (!this._remoteTx) await this._fetchRemoteTx(); |
|||
|
|||
let { feeRate, utxos } = await this.getInfo(); |
|||
|
|||
if (newFeerate <= feeRate) throw new Error('New feerate should be bigger than the old one'); |
|||
let myAddress = await this._wallet.getChangeAddressAsync(); |
|||
|
|||
return this._wallet.createTransaction( |
|||
utxos, |
|||
[{ address: myAddress }], |
|||
newFeerate, |
|||
/* meaningless in this context */ myAddress, |
|||
(await this.getMaxUsedSequence()) + 1, |
|||
); |
|||
} |
|||
|
|||
/** |
|||
* Creates an RBF transaction that can bumps fee of previous one. Note, this cannot add more utxo in RBF |
|||
* transaction if newFeerate is too high |
|||
* |
|||
* @param newFeerate {number} Sat/byte |
|||
* @returns {Promise<{outputs: Array, tx: Transaction, inputs: Array, fee: Number}>} |
|||
*/ |
|||
async createRBFbumpFee(newFeerate) { |
|||
if (!this._wallet) throw new Error('Wallet required for this method'); |
|||
if (!this._remoteTx) await this._fetchRemoteTx(); |
|||
|
|||
let { feeRate, targets, changeAmount, utxos } = await this.getInfo(); |
|||
|
|||
if (newFeerate <= feeRate) throw new Error('New feerate should be bigger than the old one'); |
|||
let myAddress = await this._wallet.getChangeAddressAsync(); |
|||
|
|||
if (changeAmount === 0) delete targets[0].value; |
|||
// looks like this was sendMAX transaction (because there was no change), so we cant reuse amount in this
|
|||
// target since fee wont change. removing the amount so `createTransaction` will sendMAX correctly with new feeRate
|
|||
|
|||
if (targets.length === 0) { |
|||
// looks like this was cancelled tx with single change output, so it wasnt included in `this.getInfo()` targets
|
|||
// so we add output paying ourselves:
|
|||
targets.push({ address: this._wallet._getInternalAddressByIndex(this._wallet.next_free_change_address_index) }); |
|||
// not checking emptiness on purpose: it could unpredictably generate too far address because of unconfirmed tx.
|
|||
} |
|||
|
|||
return this._wallet.createTransaction(utxos, targets, newFeerate, myAddress, (await this.getMaxUsedSequence()) + 1); |
|||
} |
|||
|
|||
/** |
|||
* Creates a CPFP transaction that can bumps fee of previous one (spends created but not confirmed outputs |
|||
* that belong to us). Note, this cannot add more utxo in CPFP transaction if newFeerate is too high |
|||
* |
|||
* @param newFeerate {number} sat/byte |
|||
* @returns {Promise<{outputs: Array, tx: Transaction, inputs: Array, fee: Number}>} |
|||
*/ |
|||
async createCPFPbumpFee(newFeerate) { |
|||
if (!this._wallet) throw new Error('Wallet required for this method'); |
|||
if (!this._remoteTx) await this._fetchRemoteTx(); |
|||
|
|||
let { feeRate, fee: oldFee, unconfirmedUtxos } = await this.getInfo(); |
|||
|
|||
if (newFeerate <= feeRate) throw new Error('New feerate should be bigger than the old one'); |
|||
let myAddress = await this._wallet.getChangeAddressAsync(); |
|||
|
|||
// calculating feerate for CPFP tx so that average between current and CPFP tx will equal newFeerate.
|
|||
// this works well if both txs are +/- equal size in bytes
|
|||
const targetFeeRate = 2 * newFeerate - feeRate; |
|||
|
|||
let add = 0; |
|||
while (add <= 128) { |
|||
var { tx, inputs, outputs, fee } = this._wallet.createTransaction( |
|||
unconfirmedUtxos, |
|||
[{ address: myAddress }], |
|||
targetFeeRate + add, |
|||
myAddress, |
|||
HDSegwitBech32Wallet.defaultRBFSequence, |
|||
); |
|||
let combinedFeeRate = (oldFee + fee) / (this._txhex.length / 2 + tx.toHex().length / 2); // avg
|
|||
if (Math.round(combinedFeeRate) < newFeerate) { |
|||
add *= 2; |
|||
if (!add) add = 2; |
|||
} else { |
|||
// reached target feerate
|
|||
break; |
|||
} |
|||
} |
|||
|
|||
return { tx, inputs, outputs, fee }; |
|||
} |
|||
} |
After Width: | Height: | Size: 548 B |
After Width: | Height: | Size: 669 B |
After Width: | Height: | Size: 818 B |
@ -0,0 +1,8 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "https://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
|||
<plist version="1.0"> |
|||
<dict> |
|||
<key>AppSecret</key> |
|||
<string>e83710b1-61c2-497b-b0f7-c3b6ab79f2d8</string> |
|||
</dict> |
|||
</plist> |
@ -0,0 +1,4 @@ |
|||
//
|
|||
// Use this file to import your target's public headers that you would like to expose to Swift.
|
|||
//
|
|||
|
@ -0,0 +1,5 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
|||
<plist version="1.0"> |
|||
<dict/> |
|||
</plist> |
@ -0,0 +1,5 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
|||
<plist version="1.0"> |
|||
<dict/> |
|||
</plist> |
@ -0,0 +1,56 @@ |
|||
// |
|||
// ComplicationController.swift |
|||
// T WatchKit Extension |
|||
// |
|||
// Created by Marcos Rodriguez on 8/24/19. |
|||
// Copyright © 2019 Marcos Rodriguez. All rights reserved. |
|||
// |
|||
|
|||
import ClockKit |
|||
|
|||
|
|||
class ComplicationController: NSObject, CLKComplicationDataSource { |
|||
|
|||
// MARK: - Timeline Configuration |
|||
|
|||
func getSupportedTimeTravelDirections(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTimeTravelDirections) -> Void) { |
|||
handler([.forward, .backward]) |
|||
} |
|||
|
|||
func getTimelineStartDate(for complication: CLKComplication, withHandler handler: @escaping (Date?) -> Void) { |
|||
handler(nil) |
|||
} |
|||
|
|||
func getTimelineEndDate(for complication: CLKComplication, withHandler handler: @escaping (Date?) -> Void) { |
|||
handler(nil) |
|||
} |
|||
|
|||
func getPrivacyBehavior(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationPrivacyBehavior) -> Void) { |
|||
handler(.showOnLockScreen) |
|||
} |
|||
|
|||
// MARK: - Timeline Population |
|||
|
|||
func getCurrentTimelineEntry(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTimelineEntry?) -> Void) { |
|||
// Call the handler with the current timeline entry |
|||
handler(nil) |
|||
} |
|||
|
|||
func getTimelineEntries(for complication: CLKComplication, before date: Date, limit: Int, withHandler handler: @escaping ([CLKComplicationTimelineEntry]?) -> Void) { |
|||
// Call the handler with the timeline entries prior to the given date |
|||
handler(nil) |
|||
} |
|||
|
|||
func getTimelineEntries(for complication: CLKComplication, after date: Date, limit: Int, withHandler handler: @escaping ([CLKComplicationTimelineEntry]?) -> Void) { |
|||
// Call the handler with the timeline entries after to the given date |
|||
handler(nil) |
|||
} |
|||
|
|||
// MARK: - Placeholder Templates |
|||
|
|||
func getLocalizableSampleTemplate(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTemplate?) -> Void) { |
|||
// This method will be called once per supported complication, and the results will be cached |
|||
handler(nil) |
|||
} |
|||
|
|||
} |
@ -0,0 +1,32 @@ |
|||
{ |
|||
"images" : [ |
|||
{ |
|||
"idiom" : "watch", |
|||
"screen-width" : "<=145", |
|||
"filename" : "circular38mm@2x.png", |
|||
"scale" : "2x" |
|||
}, |
|||
{ |
|||
"screen-width" : ">161", |
|||
"scale" : "2x", |
|||
"idiom" : "watch", |
|||
"filename" : "circular40mm@2x.png" |
|||
}, |
|||
{ |
|||
"scale" : "2x", |
|||
"idiom" : "watch", |
|||
"filename" : "circular42mm@2x.png", |
|||
"screen-width" : ">145" |
|||
}, |
|||
{ |
|||
"filename" : "circular44mm@2x.png", |
|||
"scale" : "2x", |
|||
"idiom" : "watch", |
|||
"screen-width" : ">183" |
|||
} |
|||
], |
|||
"info" : { |
|||
"version" : 1, |
|||
"author" : "xcode" |
|||
} |
|||
} |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.4 KiB |
@ -0,0 +1,48 @@ |
|||
{ |
|||
"info" : { |
|||
"version" : 1, |
|||
"author" : "xcode" |
|||
}, |
|||
"assets" : [ |
|||
{ |
|||
"idiom" : "watch", |
|||
"role" : "circular", |
|||
"filename" : "Circular.imageset" |
|||
}, |
|||
{ |
|||
"idiom" : "watch", |
|||
"filename" : "Modular.imageset", |
|||
"role" : "modular" |
|||
}, |
|||
{ |
|||
"idiom" : "watch", |
|||
"filename" : "Utilitarian.imageset", |
|||
"role" : "utilitarian" |
|||
}, |
|||
{ |
|||
"idiom" : "watch", |
|||
"role" : "extra-large", |
|||
"filename" : "Extra Large.imageset" |
|||
}, |
|||
{ |
|||
"role" : "graphic-corner", |
|||
"idiom" : "watch", |
|||
"filename" : "Graphic Corner.imageset" |
|||
}, |
|||
{ |
|||
"filename" : "Graphic Circular.imageset", |
|||
"role" : "graphic-circular", |
|||
"idiom" : "watch" |
|||
}, |
|||
{ |
|||
"idiom" : "watch", |
|||
"filename" : "Graphic Bezel.imageset", |
|||
"role" : "graphic-bezel" |
|||
}, |
|||
{ |
|||
"idiom" : "watch", |
|||
"role" : "graphic-large-rectangular", |
|||
"filename" : "Graphic Large Rectangular.imageset" |
|||
} |
|||
] |
|||
} |
@ -0,0 +1,32 @@ |
|||
{ |
|||
"images" : [ |
|||
{ |
|||
"filename" : "extra-large38mm@2x.png", |
|||
"screen-width" : "<=145", |
|||
"idiom" : "watch", |
|||
"scale" : "2x" |
|||
}, |
|||
{ |
|||
"screen-width" : ">161", |
|||
"filename" : "extra-large40mm@2x.png", |
|||
"idiom" : "watch", |
|||
"scale" : "2x" |
|||
}, |
|||
{ |
|||
"screen-width" : ">145", |
|||
"idiom" : "watch", |
|||
"filename" : "extra-large42mm@2x.png", |
|||
"scale" : "2x" |
|||
}, |
|||
{ |
|||
"idiom" : "watch", |
|||
"scale" : "2x", |
|||
"screen-width" : ">183", |
|||
"filename" : "extra-large44mm@2x.png" |
|||
} |
|||
], |
|||
"info" : { |
|||
"version" : 1, |
|||
"author" : "xcode" |
|||
} |
|||
} |
After Width: | Height: | Size: 7.5 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 12 KiB |
@ -0,0 +1,30 @@ |
|||
{ |
|||
"images" : [ |
|||
{ |
|||
"idiom" : "watch", |
|||
"scale" : "2x", |
|||
"screen-width" : "<=145" |
|||
}, |
|||
{ |
|||
"idiom" : "watch", |
|||
"filename" : "graphic-bezel40mm@2x.png", |
|||
"screen-width" : ">161", |
|||
"scale" : "2x" |
|||
}, |
|||
{ |
|||
"idiom" : "watch", |
|||
"scale" : "2x", |
|||
"screen-width" : ">145" |
|||
}, |
|||
{ |
|||
"idiom" : "watch", |
|||
"filename" : "graphic-bezel44mm@2x.png", |
|||
"screen-width" : ">183", |
|||
"scale" : "2x" |
|||
} |
|||
], |
|||
"info" : { |
|||
"version" : 1, |
|||
"author" : "xcode" |
|||
} |
|||
} |
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 3.9 KiB |
@ -0,0 +1,30 @@ |
|||
{ |
|||
"images" : [ |
|||
{ |
|||
"idiom" : "watch", |
|||
"scale" : "2x", |
|||
"screen-width" : "<=145" |
|||
}, |
|||
{ |
|||
"idiom" : "watch", |
|||
"filename" : "graphic-circular40mm@2x.png", |
|||
"screen-width" : ">161", |
|||
"scale" : "2x" |
|||
}, |
|||
{ |
|||
"idiom" : "watch", |
|||
"scale" : "2x", |
|||
"screen-width" : ">145" |
|||
}, |
|||
{ |
|||
"idiom" : "watch", |
|||
"filename" : "graphic-circular44mm@2x.png", |
|||
"screen-width" : ">183", |
|||
"scale" : "2x" |
|||
} |
|||
], |
|||
"info" : { |
|||
"version" : 1, |
|||
"author" : "xcode" |
|||
} |
|||
} |
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 3.9 KiB |
@ -0,0 +1,30 @@ |
|||
{ |
|||
"images" : [ |
|||
{ |
|||
"idiom" : "watch", |
|||
"scale" : "2x", |
|||
"screen-width" : "<=145" |
|||
}, |
|||
{ |
|||
"idiom" : "watch", |
|||
"filename" : "graphic-corner40mm@2x.png", |
|||
"screen-width" : ">161", |
|||
"scale" : "2x" |
|||
}, |
|||
{ |
|||
"idiom" : "watch", |
|||
"scale" : "2x", |
|||
"screen-width" : ">145" |
|||
}, |
|||
{ |
|||
"idiom" : "watch", |
|||
"filename" : "graphic-corner44mm@2x.png", |
|||
"screen-width" : ">183", |
|||
"scale" : "2x" |
|||
} |
|||
], |
|||
"info" : { |
|||
"version" : 1, |
|||
"author" : "xcode" |
|||
} |
|||
} |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 1.6 KiB |
@ -0,0 +1,28 @@ |
|||
{ |
|||
"images" : [ |
|||
{ |
|||
"idiom" : "watch", |
|||
"scale" : "2x", |
|||
"screen-width" : "<=145" |
|||
}, |
|||
{ |
|||
"idiom" : "watch", |
|||
"scale" : "2x", |
|||
"screen-width" : ">161" |
|||
}, |
|||
{ |
|||
"idiom" : "watch", |
|||
"scale" : "2x", |
|||
"screen-width" : ">145" |
|||
}, |
|||
{ |
|||
"idiom" : "watch", |
|||
"scale" : "2x", |
|||
"screen-width" : ">183" |
|||
} |
|||
], |
|||
"info" : { |
|||
"version" : 1, |
|||
"author" : "xcode" |
|||
} |
|||
} |
@ -0,0 +1,32 @@ |
|||
{ |
|||
"info" : { |
|||
"version" : 1, |
|||
"author" : "xcode" |
|||
}, |
|||
"images" : [ |
|||
{ |
|||
"screen-width" : "<=145", |
|||
"scale" : "2x", |
|||
"idiom" : "watch", |
|||
"filename" : "modular38mm@2x.png" |
|||
}, |
|||
{ |
|||
"screen-width" : ">161", |
|||
"scale" : "2x", |
|||
"filename" : "modular40mm@2x.png", |
|||
"idiom" : "watch" |
|||
}, |
|||
{ |
|||
"scale" : "2x", |
|||
"idiom" : "watch", |
|||
"filename" : "modular42mm@2x.png", |
|||
"screen-width" : ">145" |
|||
}, |
|||
{ |
|||
"filename" : "modular44mm@2x.png", |
|||
"screen-width" : ">183", |
|||
"idiom" : "watch", |
|||
"scale" : "2x" |
|||
} |
|||
] |
|||
} |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 2.4 KiB |
@ -0,0 +1,32 @@ |
|||
{ |
|||
"info" : { |
|||
"version" : 1, |
|||
"author" : "xcode" |
|||
}, |
|||
"images" : [ |
|||
{ |
|||
"scale" : "2x", |
|||
"filename" : "utility38mm@2x.png", |
|||
"screen-width" : "<=145", |
|||
"idiom" : "watch" |
|||
}, |
|||
{ |
|||
"idiom" : "watch", |
|||
"scale" : "2x", |
|||
"screen-width" : ">161", |
|||
"filename" : "utility40mm@2x.png" |
|||
}, |
|||
{ |
|||
"scale" : "2x", |
|||
"idiom" : "watch", |
|||
"filename" : "utility42mm@2x.png", |
|||
"screen-width" : ">145" |
|||
}, |
|||
{ |
|||
"idiom" : "watch", |
|||
"screen-width" : ">183", |
|||
"filename" : "utility44mm@2x.png", |
|||
"scale" : "2x" |
|||
} |
|||
] |
|||
} |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 2.0 KiB |