Merge branch 'master' into widgetfix1

This commit is contained in:
marcosrdz 2020-11-10 11:53:40 -05:00
commit 52fa81c30b
25 changed files with 1004 additions and 511 deletions

View File

@ -91,6 +91,7 @@ jobs:
api-level: 29
target: google_apis
avd-name: Pixel_API_29_AOSP
emulator-options: -no-window -gpu swiftshader_indirect -no-snapshot -noaudio -no-boot-anim -camera-back none -camera-front none
script: npm run e2e:release-test || npm run e2e:release-test || npm run e2e:release-test
env:
TRAVIS: 1

View File

@ -784,6 +784,7 @@ export const BlueListItem = React.memo(props => {
topDivider={props.topDivider !== undefined ? props.topDivider : false}
testID={props.testID}
onPress={props.onPress}
disabled={props.disabled}
>
{props.leftAvatar && <Avatar>{props.leftAvatar}</Avatar>}
{props.leftIcon && <Avatar icon={props.leftIcon} />}

View File

@ -136,7 +136,7 @@ android {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1
versionName "5.6.4"
versionName "5.6.5"
multiDexEnabled true
missingDimensionStrategy 'react-native-camera', 'general'
testBuildType System.getProperty('testBuildType', 'debug') // This will later be used to control the test apk build type

View File

@ -26,6 +26,21 @@
6D641F2425525054003792DF /* WalletInformationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D641F2225525053003792DF /* WalletInformationView.swift */; };
6D641F3525526311003792DF /* SendReceiveButtons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D641F3425526311003792DF /* SendReceiveButtons.swift */; };
6D641F3625526311003792DF /* SendReceiveButtons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D641F3425526311003792DF /* SendReceiveButtons.swift */; };
6D6CA4B9255872E3009312A5 /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D333B3A252FE1A3004D72DF /* WidgetKit.framework */; };
6D6CA4BA255872E3009312A5 /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D333B3C252FE1A3004D72DF /* SwiftUI.framework */; };
6D6CA4BD255872E3009312A5 /* PriceWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D6CA4BC255872E3009312A5 /* PriceWidget.swift */; };
6D6CA4C3255872E7009312A5 /* PriceWidgetExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 6D6CA4B8255872E3009312A5 /* PriceWidgetExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
6D6CA4D725587397009312A5 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D9A2E08254BA348007B5B82 /* Assets.xcassets */; };
6D6CA4E0255873BC009312A5 /* UserDefaultsGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DA7047D254E24D5005FE5E2 /* UserDefaultsGroup.swift */; };
6D6CA5152558EBA4009312A5 /* WidgetAPI+Electrum.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D6CA5142558EBA3009312A5 /* WidgetAPI+Electrum.swift */; };
6D6CA5162558EBA4009312A5 /* WidgetAPI+Electrum.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D6CA5142558EBA3009312A5 /* WidgetAPI+Electrum.swift */; };
6D6CA5282558EC52009312A5 /* PriceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D6CA5272558EC52009312A5 /* PriceView.swift */; };
6D6CA5292558EC52009312A5 /* PriceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D6CA5272558EC52009312A5 /* PriceView.swift */; };
6D6CA5322558ED4D009312A5 /* Colors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DEB4C3A254FBF4800E9F9AA /* Colors.swift */; };
6D6CA5332558ED54009312A5 /* Models.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DEB4BFA254FBA0E00E9F9AA /* Models.swift */; };
6D6CA53C2558F316009312A5 /* WidgetAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D9A2E6A254BAB1B007B5B82 /* WidgetAPI.swift */; };
6D6CA5452558F365009312A5 /* WidgetDataStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D9A2E6B254BAB1B007B5B82 /* WidgetDataStore.swift */; };
6D6CA54E2558F497009312A5 /* WidgetAPI+Electrum.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D6CA5142558EBA3009312A5 /* WidgetAPI+Electrum.swift */; };
6D99465F2555A660000E52E8 /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D333B3A252FE1A3004D72DF /* WidgetKit.framework */; };
6D9946602555A660000E52E8 /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D333B3C252FE1A3004D72DF /* SwiftUI.framework */; };
6D9946632555A660000E52E8 /* MarketWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D9946622555A660000E52E8 /* MarketWidget.swift */; };
@ -95,6 +110,13 @@
remoteGlobalIDString = 3271B0A8236E2E0700DA766F;
remoteInfo = TodayExtension;
};
6D6CA4C1255872E7009312A5 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 6D6CA4B7255872E3009312A5;
remoteInfo = PriceWidgetExtension;
};
6D9946442555A583000E52E8 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */;
@ -147,6 +169,7 @@
dstSubfolderSpec = 13;
files = (
6D9946692555A661000E52E8 /* MarketWidgetExtension.appex in Embed App Extensions */,
6D6CA4C3255872E7009312A5 /* PriceWidgetExtension.appex in Embed App Extensions */,
6D9A2E0D254BA348007B5B82 /* WalletInformationAndMarketWidgetExtension.appex in Embed App Extensions */,
6DEB4AB8254FB59E00E9F9AA /* WalletInformationWidgetExtension.appex in Embed App Extensions */,
3271B0B5236E2E0700DA766F /* BlueWallet - Bitcoin Price.appex in Embed App Extensions */,
@ -272,6 +295,12 @@
6D641F17255226DA003792DF /* MarketView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarketView.swift; sourceTree = "<group>"; };
6D641F2225525053003792DF /* WalletInformationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WalletInformationView.swift; sourceTree = "<group>"; };
6D641F3425526311003792DF /* SendReceiveButtons.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SendReceiveButtons.swift; sourceTree = "<group>"; };
6D6CA4B8255872E3009312A5 /* PriceWidgetExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = PriceWidgetExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
6D6CA4BC255872E3009312A5 /* PriceWidget.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PriceWidget.swift; sourceTree = "<group>"; };
6D6CA4C0255872E7009312A5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
6D6CA5142558EBA3009312A5 /* WidgetAPI+Electrum.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "WidgetAPI+Electrum.swift"; sourceTree = "<group>"; };
6D6CA5272558EC52009312A5 /* PriceView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PriceView.swift; sourceTree = "<group>"; };
6D6CA6192558F6AB009312A5 /* PriceWidgetExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = PriceWidgetExtension.entitlements; sourceTree = "<group>"; };
6D99465E2555A660000E52E8 /* MarketWidgetExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = MarketWidgetExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
6D9946622555A660000E52E8 /* MarketWidget.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarketWidget.swift; sourceTree = "<group>"; };
6D9946662555A661000E52E8 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
@ -383,6 +412,15 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
6D6CA4B5255872E3009312A5 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
6D6CA4BA255872E3009312A5 /* SwiftUI.framework in Frameworks */,
6D6CA4B9255872E3009312A5 /* WidgetKit.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
6D99465B2555A660000E52E8 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
@ -518,6 +556,15 @@
name = Resources;
sourceTree = "<group>";
};
6D6CA4BB255872E3009312A5 /* PriceWidget */ = {
isa = PBXGroup;
children = (
6D6CA4BC255872E3009312A5 /* PriceWidget.swift */,
6D6CA4C0255872E7009312A5 /* Info.plist */,
);
path = PriceWidget;
sourceTree = "<group>";
};
6D9946612555A660000E52E8 /* MarketWidget */ = {
isa = PBXGroup;
children = (
@ -551,6 +598,7 @@
children = (
6DEB4BC1254FB98300E9F9AA /* Shared */,
6D9946612555A660000E52E8 /* MarketWidget */,
6D6CA4BB255872E3009312A5 /* PriceWidget */,
6D9A2E05254BA347007B5B82 /* WalletInformationAndMarketWidget */,
6DEB4AB0254FB59C00E9F9AA /* WalletInformationWidget */,
);
@ -563,6 +611,7 @@
children = (
6DEB4DD82552260200E9F9AA /* Views */,
6D9A2E6A254BAB1B007B5B82 /* WidgetAPI.swift */,
6D6CA5142558EBA3009312A5 /* WidgetAPI+Electrum.swift */,
6D9A2E6B254BAB1B007B5B82 /* WidgetDataStore.swift */,
6DA7047D254E24D5005FE5E2 /* UserDefaultsGroup.swift */,
6D9A2E08254BA348007B5B82 /* Assets.xcassets */,
@ -578,6 +627,7 @@
6D641F17255226DA003792DF /* MarketView.swift */,
6D641F2225525053003792DF /* WalletInformationView.swift */,
6D641F3425526311003792DF /* SendReceiveButtons.swift */,
6D6CA5272558EC52009312A5 /* PriceView.swift */,
);
path = Views;
sourceTree = "<group>";
@ -585,6 +635,7 @@
83CBB9F61A601CBA00E9B192 = {
isa = PBXGroup;
children = (
6D6CA6192558F6AB009312A5 /* PriceWidgetExtension.entitlements */,
6D9947152555AB9E000E52E8 /* MarketWidgetExtension.entitlements */,
6DEB4ACE254FB5D800E9F9AA /* WalletInformationWidgetExtension.entitlements */,
13B07FAE1A68108700A75B9A /* BlueWallet */,
@ -614,6 +665,7 @@
6D9A2E02254BA347007B5B82 /* WalletInformationAndMarketWidgetExtension.appex */,
6DEB4AAD254FB59B00E9F9AA /* WalletInformationWidgetExtension.appex */,
6D99465E2555A660000E52E8 /* MarketWidgetExtension.appex */,
6D6CA4B8255872E3009312A5 /* PriceWidgetExtension.appex */,
);
name = Products;
sourceTree = "<group>";
@ -736,6 +788,7 @@
6DEB4AB7254FB59E00E9F9AA /* PBXTargetDependency */,
6D9946452555A583000E52E8 /* PBXTargetDependency */,
6D9946682555A661000E52E8 /* PBXTargetDependency */,
6D6CA4C2255872E7009312A5 /* PBXTargetDependency */,
);
name = BlueWallet;
productName = "Hello World";
@ -759,6 +812,23 @@
productReference = 3271B0A9236E2E0700DA766F /* BlueWallet - Bitcoin Price.appex */;
productType = "com.apple.product-type.app-extension";
};
6D6CA4B7255872E3009312A5 /* PriceWidgetExtension */ = {
isa = PBXNativeTarget;
buildConfigurationList = 6D6CA4C6255872E7009312A5 /* Build configuration list for PBXNativeTarget "PriceWidgetExtension" */;
buildPhases = (
6D6CA4B4255872E3009312A5 /* Sources */,
6D6CA4B5255872E3009312A5 /* Frameworks */,
6D6CA4B6255872E3009312A5 /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = PriceWidgetExtension;
productName = PriceWidgetExtension;
productReference = 6D6CA4B8255872E3009312A5 /* PriceWidgetExtension.appex */;
productType = "com.apple.product-type.app-extension";
};
6D99465D2555A660000E52E8 /* MarketWidgetExtension */ = {
isa = PBXNativeTarget;
buildConfigurationList = 6D99466A2555A661000E52E8 /* Build configuration list for PBXNativeTarget "MarketWidgetExtension" */;
@ -875,6 +945,9 @@
CreatedOnToolsVersion = 11.2;
LastSwiftMigration = 1130;
};
6D6CA4B7255872E3009312A5 = {
CreatedOnToolsVersion = 12.1;
};
6D99465D2555A660000E52E8 = {
CreatedOnToolsVersion = 12.1;
};
@ -948,6 +1021,7 @@
6D99465D2555A660000E52E8 /* MarketWidgetExtension */,
6DEB4AAC254FB59B00E9F9AA /* WalletInformationWidgetExtension */,
6D9A2E01254BA347007B5B82 /* WalletInformationAndMarketWidgetExtension */,
6D6CA4B7255872E3009312A5 /* PriceWidgetExtension */,
);
};
/* End PBXProject section */
@ -970,6 +1044,14 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
6D6CA4B6255872E3009312A5 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
6D6CA4D725587397009312A5 /* Assets.xcassets in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
6D99465C2555A660000E52E8 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
@ -1170,6 +1252,20 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
6D6CA4B4255872E3009312A5 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
6D6CA5452558F365009312A5 /* WidgetDataStore.swift in Sources */,
6D6CA4E0255873BC009312A5 /* UserDefaultsGroup.swift in Sources */,
6D6CA5322558ED4D009312A5 /* Colors.swift in Sources */,
6D6CA4BD255872E3009312A5 /* PriceWidget.swift in Sources */,
6D6CA5292558EC52009312A5 /* PriceView.swift in Sources */,
6D6CA53C2558F316009312A5 /* WidgetAPI.swift in Sources */,
6D6CA5332558ED54009312A5 /* Models.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
6D99465A2555A660000E52E8 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
@ -1183,6 +1279,7 @@
6D99467B2555A68A000E52E8 /* MarketView.swift in Sources */,
6D9946872555A695000E52E8 /* UserDefaultsGroup.swift in Sources */,
6D9946632555A660000E52E8 /* MarketWidget.swift in Sources */,
6D6CA5152558EBA4009312A5 /* WidgetAPI+Electrum.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -1193,12 +1290,14 @@
6D641F2325525054003792DF /* WalletInformationView.swift in Sources */,
6D9A2E6D254BAB1B007B5B82 /* WidgetAPI.swift in Sources */,
6DEB4C3B254FBF4800E9F9AA /* Colors.swift in Sources */,
6D6CA5282558EC52009312A5 /* PriceView.swift in Sources */,
6D9A2E6F254BAB1B007B5B82 /* WidgetDataStore.swift in Sources */,
6DA7047E254E24D5005FE5E2 /* UserDefaultsGroup.swift in Sources */,
6D9A2E07254BA347007B5B82 /* WalletInformationAndMarketWidget.swift in Sources */,
6D641F3525526311003792DF /* SendReceiveButtons.swift in Sources */,
6DEB4BFB254FBA0E00E9F9AA /* Models.swift in Sources */,
6D641F18255226DA003792DF /* MarketView.swift in Sources */,
6D6CA5162558EBA4009312A5 /* WidgetAPI+Electrum.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -1215,6 +1314,7 @@
6D641F3625526311003792DF /* SendReceiveButtons.swift in Sources */,
6DEB4BFC254FBA0E00E9F9AA /* Models.swift in Sources */,
6D641F19255226DA003792DF /* MarketView.swift in Sources */,
6D6CA54E2558F497009312A5 /* WidgetAPI+Electrum.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -1249,6 +1349,11 @@
target = 3271B0A8236E2E0700DA766F /* TodayExtension */;
targetProxy = 3271B0B3236E2E0700DA766F /* PBXContainerItemProxy */;
};
6D6CA4C2255872E7009312A5 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 6D6CA4B7255872E3009312A5 /* PriceWidgetExtension */;
targetProxy = 6D6CA4C1255872E7009312A5 /* PBXContainerItemProxy */;
};
6D9946452555A583000E52E8 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 6D99465D2555A660000E52E8 /* MarketWidgetExtension */;
@ -1375,7 +1480,7 @@
"$(inherited)",
"$(PROJECT_DIR)",
);
MARKETING_VERSION = 5.6.4;
MARKETING_VERSION = 5.6.5;
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",
@ -1415,7 +1520,7 @@
"$(inherited)",
"$(PROJECT_DIR)",
);
MARKETING_VERSION = 5.6.4;
MARKETING_VERSION = 5.6.5;
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",
@ -1454,6 +1559,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 5.6.5;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.TodayExtension;
@ -1492,6 +1598,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 5.6.5;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.TodayExtension;
PRODUCT_NAME = "BlueWallet - Bitcoin Price";
@ -1504,6 +1611,85 @@
};
name = Release;
};
6D6CA4C4255872E7009312A5 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_ENTITLEMENTS = PriceWidgetExtension.entitlements;
CODE_SIGN_IDENTITY = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 290;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = A7W54YZ4WU;
GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = "$(SRCROOT)/WalletInformationWidget/Widgets/PriceWidget/Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 14.1;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 5.6.5;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.PriceWidget;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = PriceWidget;
SKIP_INSTALL = YES;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
6D6CA4C5255872E7009312A5 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_ENTITLEMENTS = PriceWidgetExtension.entitlements;
CODE_SIGN_IDENTITY = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 290;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = A7W54YZ4WU;
GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = "$(SRCROOT)/WalletInformationWidget/Widgets/PriceWidget/Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 14.1;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 5.6.5;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.PriceWidget;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = PriceWidget;
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-O";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
6D99466B2555A661000E52E8 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 367FA8CEB35BC9431019D98A /* Pods-MarketWidgetExtension.debug.xcconfig */;
@ -1531,7 +1717,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 5.6.4;
MARKETING_VERSION = 5.6.5;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.MarketWidget;
@ -1573,7 +1759,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 5.6.4;
MARKETING_VERSION = 5.6.5;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.MarketWidget;
PRODUCT_NAME = "$(TARGET_NAME)";
@ -1613,7 +1799,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 5.6.4;
MARKETING_VERSION = 5.6.5;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.WalletInformationAndMarketWidget;
@ -1657,7 +1843,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 5.6.4;
MARKETING_VERSION = 5.6.5;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.WalletInformationAndMarketWidget;
PRODUCT_NAME = "$(TARGET_NAME)";
@ -1698,7 +1884,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 5.6.4;
MARKETING_VERSION = 5.6.5;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.WalletInformationWidget;
@ -1740,7 +1926,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 5.6.4;
MARKETING_VERSION = 5.6.5;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.WalletInformationWidget;
PRODUCT_NAME = "$(TARGET_NAME)";
@ -1880,6 +2066,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 5.6.5;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.watch.extension;
@ -1918,6 +2105,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 5.6.5;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.watch.extension;
PRODUCT_NAME = "${TARGET_NAME}";
@ -1950,6 +2138,7 @@
GCC_C_LANGUAGE_STANDARD = gnu11;
IBSC_MODULE = BlueWalletWatch_Extension;
INFOPLIST_FILE = BlueWalletWatch/Info.plist;
MARKETING_VERSION = 5.6.5;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.watch;
@ -1984,6 +2173,7 @@
GCC_C_LANGUAGE_STANDARD = gnu11;
IBSC_MODULE = BlueWalletWatch_Extension;
INFOPLIST_FILE = BlueWalletWatch/Info.plist;
MARKETING_VERSION = 5.6.5;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.watch;
PRODUCT_NAME = "$(TARGET_NAME)";
@ -2019,6 +2209,15 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
6D6CA4C6255872E7009312A5 /* Build configuration list for PBXNativeTarget "PriceWidgetExtension" */ = {
isa = XCConfigurationList;
buildConfigurations = (
6D6CA4C4255872E7009312A5 /* Debug */,
6D6CA4C5255872E7009312A5 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
6D99466A2555A661000E52E8 /* Build configuration list for PBXNativeTarget "MarketWidgetExtension" */ = {
isa = XCConfigurationList;
buildConfigurations = (

View File

@ -17,7 +17,7 @@
<key>CFBundlePackageType</key>
<string>XPC!</string>
<key>CFBundleShortVersionString</key>
<string>5.6.4</string>
<string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key>
<string>239</string>
<key>CLKComplicationPrincipalClass</key>

View File

@ -17,7 +17,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>5.6.4</string>
<string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key>
<string>239</string>
<key>UISupportedInterfaceOrientations</key>

View File

@ -373,8 +373,8 @@ PODS:
- React
- RNRate (1.2.4):
- React
- RNReactNativeHapticFeedback (1.10.0):
- React
- RNReactNativeHapticFeedback (1.11.0):
- React-Core
- RNReanimated (1.13.1):
- React
- RNScreens (2.11.0):
@ -390,7 +390,7 @@ PODS:
- React
- RNVectorIcons (6.6.0):
- React
- RNWatch (1.0.2):
- RNWatch (1.0.3):
- React
- Sentry (5.2.2):
- Sentry/Core (= 5.2.2)
@ -731,7 +731,7 @@ SPEC CHECKSUMS:
RNLocalize: 4071198b59b461f3b74eebc5fee8c50f13e39e79
RNQuickAction: 6d404a869dc872cde841ad3147416a670d13fa93
RNRate: 2b31dad120cd1b78e33c6034808561c386a3dddf
RNReactNativeHapticFeedback: 22c5ecf474428766c6b148f96f2ff6155cd7225e
RNReactNativeHapticFeedback: 653a8c126a0f5e88ce15ffe280b3ff37e1fbb285
RNReanimated: dd8c286ab5dd4ba36d3a7fef8bff7e08711b5476
RNScreens: 0e91da98ab26d5d04c7b59a9b6bd694124caf88c
RNSecureKeyStore: f1ad870e53806453039f650720d2845c678d89c8
@ -739,7 +739,7 @@ SPEC CHECKSUMS:
RNShare: 7a7277f3c313652422d9de072ac50714dff5e8a4
RNSVG: ce9d996113475209013317e48b05c21ee988d42e
RNVectorIcons: 0bb4def82230be1333ddaeee9fcba45f0b288ed4
RNWatch: d56d00be49131ee454bb5a4a574f18506c8949e4
RNWatch: e4c5d19506c94506860032fb68aedd5991beb985
Sentry: 8fa58a051237554f22507fb483b9a1de0171a2dc
SwiftSocket: c8d482e867ae4d3eb4c769e9382e123c1f1f833b
ToolTipMenu: 4d89d95ddffd7539230bdbe02ee51bbde362e37e

View File

@ -0,0 +1,10 @@
<?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>
<key>com.apple.security.application-groups</key>
<array>
<string>group.io.bluewallet.bluewallet</string>
</array>
</dict>
</plist>

View File

@ -17,7 +17,7 @@
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>5.6.4</string>
<string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSExtension</key>

View File

@ -0,0 +1,29 @@
<?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>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
<string>PriceWidget</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSExtension</key>
<dict>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.widgetkit-extension</string>
</dict>
</dict>
</plist>

View File

@ -0,0 +1,97 @@
//
// PriceWidget.swift
// PriceWidget
//
// Created by Marcos Rodriguez on 11/8/20.
// Copyright © 2020 BlueWallet. All rights reserved.
//
import WidgetKit
import SwiftUI
var marketData: [MarketDataTimeline: MarketData?] = [ .Current: nil, .Previous: nil]
struct Provider: TimelineProvider {
func placeholder(in context: Context) -> SimpleEntry {
SimpleEntry(date: Date(), currentMarketData: nil)
}
func getSnapshot(in context: Context, completion: @escaping (SimpleEntry) -> ()) {
let entry: SimpleEntry
if (context.isPreview) {
entry = SimpleEntry(date: Date(), currentMarketData: MarketData(nextBlock: "", sats: "", price: "$10,000", rate: 10000, dateString: "2019-09-18T17:27:00+00:00"))
} else {
entry = SimpleEntry(date: Date(), currentMarketData: emptyMarketData)
}
completion(entry)
}
func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
var entries: [SimpleEntry] = []
if WidgetAPI.getUserPreferredCurrency() != WidgetAPI.getLastSelectedCurrency() {
marketData[.Current] = nil
marketData[.Previous] = nil
WidgetAPI.saveNewSelectedCurrency()
}
var entryMarketData = marketData[.Current] ?? emptyMarketData
WidgetAPI.fetchPrice(currency: WidgetAPI.getUserPreferredCurrency()) { (data, error) in
if let data = data, let formattedRate = data.formattedRate {
let currentMarketData = MarketData(nextBlock: "", sats: "", price: formattedRate, rate: data.rateDouble, dateString: data.lastUpdate)
if let cachedMarketData = marketData[.Current], currentMarketData.dateString != cachedMarketData?.dateString {
marketData[.Previous] = marketData[.Current]
marketData[.Current] = currentMarketData
entryMarketData = currentMarketData
entries.append(SimpleEntry(date:Date(), currentMarketData: entryMarketData))
} else {
entries.append(SimpleEntry(date:Date(), currentMarketData: currentMarketData))
}
}
let timeline = Timeline(entries: entries, policy: .atEnd)
completion(timeline)
}
}
}
struct SimpleEntry: TimelineEntry {
let date: Date
let currentMarketData: MarketData?
var previousMarketData: MarketData? {
return marketData[.Previous] as? MarketData
}
}
struct PriceWidgetEntryView : View {
var entry: Provider.Entry
var priceView: some View {
PriceView(currentMarketData: entry.currentMarketData, previousMarketData: marketData[.Previous] ?? emptyMarketData).padding()
}
var body: some View {
priceView.background(Color.widgetBackground)
}
}
@main
struct PriceWidget: Widget {
let kind: String = "PriceWidget"
var body: some WidgetConfiguration {
StaticConfiguration(kind: kind, provider: Provider()) { entry in
PriceWidgetEntryView(entry: entry)
}
.configurationDisplayName("Price")
.description("View the current price of Bitcoin.").supportedFamilies([.systemSmall])
}
}
struct PriceWidget_Previews: PreviewProvider {
static var previews: some View {
PriceWidgetEntryView(entry: SimpleEntry(date: Date(), currentMarketData: MarketData(nextBlock: "", sats: "", price: "$10,000", rate: 10000, dateString: "2019-09-18T17:27:00+00:00")))
.previewContext(WidgetPreviewContext(family: .systemSmall))
}
}

View File

@ -8,7 +8,7 @@
import Foundation
struct MarketData {
struct MarketData:Codable {
var nextBlock: String
var sats: String
var price: String
@ -16,6 +16,19 @@ struct MarketData {
var formattedNextBlock: String {
return nextBlock == "..." ? "..." : #"\#(nextBlock) sat/b"#
}
var dateString: String = ""
var formattedDate: String? {
let isoDateFormatter = ISO8601DateFormatter()
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale.current
dateFormatter.timeStyle = .short
if let date = isoDateFormatter.date(from: dateString) {
return dateFormatter.string(from: date)
}
return nil
}
}
struct WalletData {
@ -30,3 +43,8 @@ struct WalletData {
let emptyMarketData = MarketData(nextBlock: "...", sats: "...", price: "...", rate: 0)
let emptyWalletData = WalletData(balance: 0, latestTransactionTime: Int(Date().timeIntervalSince1970))
enum MarketDataTimeline: String {
case Previous = "previous"
case Current = "current"
}

View File

@ -0,0 +1,48 @@
//
// PriceView.swift
// BlueWallet
//
// Created by Marcos Rodriguez on 11/8/20.
// Copyright © 2020 BlueWallet. All rights reserved.
//
import SwiftUI
import WidgetKit
struct PriceView: View {
var currentMarketData: MarketData? = emptyMarketData
var previousMarketData: MarketData? = emptyMarketData
var body: some View {
VStack(alignment: .trailing, spacing: /*@START_MENU_TOKEN@*/nil/*@END_MENU_TOKEN@*/, content: {
Text("Last Updated").font(Font.system(size: 11, weight: .regular, design: .default)).foregroundColor(.textColorLightGray)
HStack(alignment: .lastTextBaseline, spacing: /*@START_MENU_TOKEN@*/nil/*@END_MENU_TOKEN@*/, content: {
Text(currentMarketData?.formattedDate ?? "").lineLimit(1).foregroundColor(.textColor).font(Font.system(size:13, weight: .regular, design: .default)).minimumScaleFactor(0.01).transition(.opacity)
})
Spacer()
VStack(alignment: .trailing, spacing: 16, content: {
HStack(alignment: .lastTextBaseline, spacing: /*@START_MENU_TOKEN@*/nil/*@END_MENU_TOKEN@*/, content: {
Text(currentMarketData?.price ?? "").lineLimit(1).foregroundColor(.textColor).font(Font.system(size:28, weight: .bold, design: .default)).minimumScaleFactor(0.01).transition(.opacity)
})
if let previousMarketDataPrice = previousMarketData?.price, let currentMarketDataRate = currentMarketData?.rate, let previousMarketDataRate = previousMarketData?.rate, previousMarketDataRate > 0, currentMarketDataRate != previousMarketDataRate {
HStack(alignment: .lastTextBaseline, spacing: /*@START_MENU_TOKEN@*/nil/*@END_MENU_TOKEN@*/, content: {
Image(systemName: currentMarketDataRate > previousMarketDataRate ? "arrow.up" : "arrow.down")
Text("from").lineLimit(1).foregroundColor(.textColor).font(Font.system(size:13, weight: .regular, design: .default)).minimumScaleFactor(0.01)
Text(previousMarketDataPrice).lineLimit(1).foregroundColor(.textColor).font(Font.system(size:13, weight: .regular, design: .default)).minimumScaleFactor(0.01)
}).transition(.slide)
}
})
}).frame(minWidth: 0,
maxWidth: .infinity,
minHeight: 0,
maxHeight: .infinity,
alignment: .trailing)
}
}
struct PriceView_Previews: PreviewProvider {
static var previews: some View {
PriceView().previewContext(WidgetPreviewContext(family: .systemSmall))
}
}

View File

@ -0,0 +1,83 @@
//
// WidgetAPI+Electrum.swift
// BlueWallet
//
// Created by Marcos Rodriguez on 11/8/20.
// Copyright © 2020 BlueWallet. All rights reserved.
//
import SwiftSocket
struct APIError: LocalizedError {
var errorDescription: String = "Failed to fetch Electrum data..."
}
extension WidgetAPI {
static func fetchNextBlockFee(completion: @escaping ((MarketData?, Error?) -> Void), userElectrumSettings: UserDefaultsElectrumSettings = UserDefaultsGroup.getElectrumSettings()) {
guard let host = userElectrumSettings.host, let _ = userElectrumSettings.sslPort, let port = userElectrumSettings.port else {
print("No valid UserDefaultsElectrumSettings found");
return
}
DispatchQueue.global(qos: .background).async {
let client = TCPClient(address: host, port: port)
let send = "{\"id\": 1, \"method\": \"blockchain.estimatefee\", \"params\": [1]}\n"
switch client.connect(timeout: 1) {
case .success:
switch client.send(string: send) {
case .success:
guard let data = client.read(1024*10, timeout: 1) else {
client.close()
completion(nil, APIError())
return
}
if let response = String(bytes: data, encoding: .utf8), let nextBlockResponse = response.components(separatedBy: #"result":"#).last?.components(separatedBy: ",").first, let nextBlockResponseDouble = Double(nextBlockResponse.trimmingCharacters(in: .whitespacesAndNewlines)) {
print("Successfully obtained response from Electrum sever")
print(userElectrumSettings)
client.close()
completion(MarketData(nextBlock: String(format: "%.0f", (nextBlockResponseDouble / 1024) * 100000000), sats: "0", price: "0", rate: 0), nil)
}
case .failure(let error):
print(error)
client.close()
completion(nil, APIError())
}
case .failure(let error):
print(error)
client.close()
if userElectrumSettings.host == DefaultElectrumPeers.last?.host {
completion(nil, APIError())
} else if let currentIndex = DefaultElectrumPeers.firstIndex(where: {$0.host == userElectrumSettings.host}) {
fetchNextBlockFee(completion: completion, userElectrumSettings: DefaultElectrumPeers[DefaultElectrumPeers.index(after: currentIndex)])
} else {
if let first = DefaultElectrumPeers.first {
fetchNextBlockFee(completion: completion, userElectrumSettings: first)
}
}
}
}
}
static func fetchMarketData(currency: String, completion: @escaping ((MarketData?, Error?) -> Void)) {
var marketDataEntry = MarketData(nextBlock: "...", sats: "...", price: "...", rate: 0)
WidgetAPI.fetchPrice(currency: currency, completion: { (result, error) in
if let result = result {
marketDataEntry.rate = result.rateDouble
marketDataEntry.price = result.formattedRate ?? "!"
}
WidgetAPI.fetchNextBlockFee { (marketData, error) in
if let nextBlock = marketData?.nextBlock {
marketDataEntry.nextBlock = nextBlock
} else {
marketDataEntry.nextBlock = "!"
}
if let rateDouble = result?.rateDouble {
marketDataEntry.sats = numberFormatter.string(from: NSNumber(value: Double(10 / rateDouble) * 10000000)) ?? "!"
}
completion(marketDataEntry, nil)
}
})
}
}

View File

@ -7,11 +7,7 @@
//
import Foundation
import SwiftSocket
struct APIError: LocalizedError {
var errorDescription: String = "Failed to fetch Electrum data..."
}
var numberFormatter: NumberFormatter {
let formatter = NumberFormatter()
@ -24,76 +20,6 @@ var numberFormatter: NumberFormatter {
class WidgetAPI {
static func fetchNextBlockFee(completion: @escaping ((MarketData?, Error?) -> Void), userElectrumSettings: UserDefaultsElectrumSettings = UserDefaultsGroup.getElectrumSettings()) {
guard let host = userElectrumSettings.host, let _ = userElectrumSettings.sslPort, let port = userElectrumSettings.port else {
print("No valid UserDefaultsElectrumSettings found");
return
}
DispatchQueue.global(qos: .background).async {
let client = TCPClient(address: host, port: port)
let send = "{\"id\": 1, \"method\": \"blockchain.estimatefee\", \"params\": [1]}\n"
switch client.connect(timeout: 1) {
case .success:
switch client.send(string: send) {
case .success:
guard let data = client.read(1024*10, timeout: 1) else {
client.close()
completion(nil, APIError())
return
}
let characterSet = Set("0123456789.")
if let response = String(bytes: data, encoding: .utf8), let nextBlockResponse = response.components(separatedBy: #"result":"#).last?.components(separatedBy: ",").first, let nextBlockResponseDouble = Double(nextBlockResponse.filter({characterSet.contains($0)}).trimmingCharacters(in: .whitespacesAndNewlines)) {
print("Successfully obtained response from Electrum sever")
print(userElectrumSettings)
let marketData = MarketData(nextBlock: String(format: "%.0f", (nextBlockResponseDouble / 1024) * 100000000), sats: "0", price: "0", rate: 0)
client.close()
completion(marketData, nil)
} else {
client.close()
completion(nil, APIError())
}
case .failure(let error):
print(error)
client.close()
completion(nil, APIError())
}
case .failure(let error):
print(error)
client.close()
if userElectrumSettings.host == DefaultElectrumPeers.last?.host {
completion(nil, APIError())
} else if let currentIndex = DefaultElectrumPeers.firstIndex(where: {$0.host == userElectrumSettings.host}) {
fetchNextBlockFee(completion: completion, userElectrumSettings: DefaultElectrumPeers[DefaultElectrumPeers.index(after: currentIndex)])
} else {
if let first = DefaultElectrumPeers.first {
fetchNextBlockFee(completion: completion, userElectrumSettings: first)
}
}
}
}
}
static func fetchMarketData(currency: String, completion: @escaping ((MarketData?, Error?) -> Void)) {
var marketDataEntry = MarketData(nextBlock: "...", sats: "...", price: "...", rate: 0)
WidgetAPI.fetchPrice(currency: currency, completion: { (result, error) in
if let result = result {
marketDataEntry.rate = result.rateDouble
marketDataEntry.price = result.formattedRate ?? "!"
}
WidgetAPI.fetchNextBlockFee { (marketData, error) in
if let nextBlock = marketData?.nextBlock {
marketDataEntry.nextBlock = nextBlock
} else {
marketDataEntry.nextBlock = "!"
}
if let rateDouble = result?.rateDouble {
marketDataEntry.sats = numberFormatter.string(from: NSNumber(value: Double(10 / rateDouble) * 10000000)) ?? "!"
}
completion(marketDataEntry, nil)
}
})
}
static func fetchPrice(currency: String, completion: @escaping ((WidgetDataStore?, Error?) -> Void)) {
guard let url = URL(string: "https://api.coindesk.com/v1/bpi/currentPrice/\(currency).json") else {return}
@ -105,11 +31,12 @@ class WidgetAPI {
completion(nil, error)
return }
guard let bpi = json?["bpi"] as? Dictionary<String, Any>, let preferredCurrency = bpi[currency] as? Dictionary<String, Any>, let rateString = preferredCurrency["rate"] as? String, let rateDouble = preferredCurrency["rate_float"] as? Double else {
guard let bpi = json?["bpi"] as? Dictionary<String, Any>, let preferredCurrency = bpi[currency] as? Dictionary<String, Any>, let rateString = preferredCurrency["rate"] as? String, let rateDouble = preferredCurrency["rate_float"] as? Double, let time = json?["time"] as? Dictionary<String, Any>, let lastUpdatedString = time["updatedISO"] as? String
else {
print(error?.localizedDescription ?? "Response Error")
completion(nil, error)
return }
let latestRateDataStore = WidgetDataStore(rate: rateString, lastUpdate: "", rateDouble: rateDouble)
let latestRateDataStore = WidgetDataStore(rate: rateString, lastUpdate: lastUpdatedString, rateDouble: rateDouble)
completion(latestRateDataStore, nil)
}.resume()
}

View File

@ -1,6 +1,6 @@
Een Bitcoin portomonnee die u de mogelijkheid geeft om Bitcoin te bewaren, versturen, ontvangen en kopen met focus op beveiliging en eenvoud.
On BlueWallet, a bitcoin wallet you own your private keys. A Bitcoin wallet made by Bitcoin users for the community.
Op BlueWallet, een bitcoin wallet, bezit u uw eigen privésleutels. Een Bitcoin wallet gemaakt door Bitcoin-gebruikers voor de gemeenschap.
U kan naar iedereen in de wereld direct transacties versturen en het financiële systeem veranderen vanuit uw broekzak.
@ -16,11 +16,11 @@ Dit is wat u krijgt:
Open Source
MIT gelicenseerd, u kunt het zelf bouwen en gebruiken. Gemaakt met ReactNative
Plausible deniability
Plausibele ontkenning
Wachtwoord dat nep bitcoin portomonnees ontsleuten voor als u gedwongen wordt uw toegang vrij te geven
Volledige versleuteling
On top of the iOS multi-layer encryption, we encrypt everything with added passwords
Naast de meerlaagse versleuteling van iOS, versleutelen we alles met toegevoegde wachtwoorden
Full node
Verbind uw Bitcoin full node via Electrum
@ -35,13 +35,13 @@ Privé sleutels verlaten nooit uw apparaat.
U beheert uw privé sleutels
Aanpasbare vergoedingen
Starting from 1 Satoshi. Defined by you, the user
Begin met 1 satoshi. Gedefinieerd door jou, de gebruiker
Replace-By-Fee
(RBF) Versnel uw transactie door de vergoeding te verhogen (BIP125)
Watch-only wallets
Watch-only wallets allow you to keep an eye on your cold storage without touching the hardware.
Alleen lezen wallets
Alleen lezen wallets zodat u uw cold storage in de gaten kunt houden zonder de hardware aan te raken.
Lightning Network
Lightning-portomonnee zonder configuratie. Oneerlijk goedkoop en snelle transacties met de ultieme Bitcoin ervaring.

View File

@ -436,7 +436,7 @@
"please_write_down_mnemonics": "Please write down this mnemonic phrase on paper. Don't worry, you can write it down later.",
"i_wrote_it_down": "Ok, I wrote it down",
"type_your_mnemonics": "Insert a seed to import your existing vault key",
"this_is_cosigners_xpub": "This is cosigner's xpub, ready to be imported in other wallet. It is safe to share it.",
"this_is_cosigners_xpub": "This is the cosigner's xpub, ready to be imported into another wallet. It is safe to share it.",
"wallet_key_created": "Your vault key was created. Take a moment to safely backup your mnemonic seed",
"are_you_sure_seed_will_be_lost": "Are you sure? Your mnemonic seed will be lost if you dont have a backup",
"forget_this_seed": "Forget this seed and use xpub instead",

View File

@ -8,16 +8,24 @@
"of": "{number} van {total}",
"ok": "Oké",
"storage_is_encrypted": "Uw opslag is versleuteld. Wachtwoord is vereist om het te ontcijferen",
"yes": "Ja"
"allow": "Toestaan",
"dont_allow": "Niet toestaan",
"yes": "Ja",
"no": "Nee",
"save": "Opslaan",
"seed": "Seed",
"wallet_key": "Wallet key",
"invalid_animated_qr_code_fragment" : "Ongeldig geanimeerde QRCode, probeer het opnieuw",
"file_saved": "Bestand ({filePath}) is opgeslagen in uw gedownloade bestanden."
},
"azteco": {
"codeIs": "De code van uw tegoedbon is",
"errorBeforeRefeem": "Before redeeming you must first add a Bitcoin wallet.",
"errorBeforeRefeem": "Voor het inlossen moet u eerst Bitcoin wallet toevoegen.",
"errorSomething": "Er ging is verkeerd. Is deze tegoedbon nog geldig?",
"redeem": "Redeem to wallet",
"redeemButton": "Redeem",
"redeem": "Inlossen naar wallet.",
"redeemButton": "Inlossen",
"success": "Succes",
"title": "Redeem Azte.co voucher"
"title": "Los uw Atze.co voucher in"
},
"entropy": {
"save": "Opslaan",
@ -25,352 +33,417 @@
"undo": "Herstellen"
},
"errors": {
"broadcast": "Broadcast failed",
"broadcast": "Broadcast mislukt",
"error": "Fout",
"network": "Netwerkfout"
},
"hodl": {
"are_you_sure_you_want_to_logout": "Are you sure you want to logout from HodlHodl?",
"are_you_sure_you_want_to_logout": "Weet u zeker dat u wilt uitloggen van HodlHodl?",
"cont_address_escrow": "Escrow",
"cont_address_to": "To",
"cont_address_to": "Naar",
"cont_buying": "kopen",
"cont_cancel": "Cancel contract",
"cont_cancel_q": "Are you sure you want to cancel this contract?",
"cont_cancel_y": "Yes, cancel contract",
"cont_chat": "Open chat with counterparty",
"cont_how": "How to pay",
"cont_no": "You don't have any contracts in progress",
"cont_paid": "Mark contract as Paid",
"cont_paid_e": "Do this only if you sent funds to the seller via agreed payment method",
"cont_paid_q": "Are you sure you want to mark this contract as paid?",
"cont_cancel": "Annuleer contract",
"cont_cancel_q": "Weet u zeker dat u dit contract wil annuleren?",
"cont_cancel_y": "Ja, annuleer dit contract",
"cont_chat": "Open chat met tegenpartij",
"cont_how": "Hoe te betalen",
"cont_no": "U heeft geen lopende contracten",
"cont_paid": "Markeer contract als betaald",
"cont_paid_e": "Doe dit alleen als u geld naar de verkoper heeft gestuurd via de overeengekomen betalingsmethode",
"cont_paid_q": "Weet u zeker dat u dit contract als betaald wilt markeren?",
"cont_selling": "verkopen",
"cont_st_completed": "All done!",
"cont_st_in_progress_buyer": "Coins are in escrow, please pay seller",
"cont_st_paid_enought": "Bitcoins are in escrow! Please pay seller\nvia agreed payment method",
"cont_st_paid_waiting": "Waiting for seller to release coins from escrow",
"cont_st_waiting": "Waiting for seller to deposit bitcoins to escrow...",
"cont_title": "My contracts",
"filter_any": "Any",
"filter_buying": "Buying",
"filter_country_global": "Global offers",
"filter_country_near": "Near me",
"cont_st_completed": "Klaar!",
"cont_st_in_progress_buyer": "Coins zijn in escrow, contacteer de verkoper",
"cont_st_paid_enought": "Bitcoin zijn in escrow! Contacteer de verkoper\nvia overeengekomen betalingsmethode",
"cont_st_paid_waiting": "Wachten op verkoper om coins vrij te geven uit escrow",
"cont_st_waiting": "Wachten op verkoper om coins te storten in escrow..",
"cont_title": "Mijn contracten",
"filter_any": "ieder",
"filter_buying": "Kopen",
"filter_country_global": "Wereldwijd aanbod",
"filter_country_near": "Dicht bij mij",
"filter_currency": "Valuta",
"filter_detail": "Detail",
"filter_filters": "Filters",
"filter_iambuying": "I'm buying bitcoin",
"filter_iamselling": "I'm selling bitcoin",
"filter_method": "Payment method",
"filter_search": "Search",
"filter_selling": "Selling",
"filter_iambuying": "Ik koop bitcoin",
"filter_iamselling": "Ik verkoop bitcoin",
"filter_method": "Betalingsmethode",
"filter_search": "Zoeken",
"filter_selling": "Verkopen",
"item_minmax": "Min/Max",
"item_nooffers": "No offers. Try to change \"Near me\" to Global offers!",
"item_rating": "{rating} trades",
"item_rating_no": "No rating",
"item_nooffers": "Geen aanbod. Probeer \"Dicht bij mij\" te veranderen naar wereldwijd aanbod!",
"item_rating": "{rating} transacties",
"item_rating_no": "Geen beoordeling",
"login": "Inloggen",
"mycont": "My contracts",
"offer_accept": "Accept offer",
"offer_account_finish": "Looks like you didn't finish setting up account on HodlHodl, would you like to finish setup now?",
"offer_choosemethod": "Choose payment method",
"mycont": "Mijn contracten",
"offer_accept": "Bod accepteren",
"offer_account_finish": "Het lijkt er op dat u nog niet klaar bent met uw account op HodlHodl, wilt u hiermee verder gaan?",
"offer_choosemethod": "Kies betalingsmethode",
"offer_confirmations": "bevestigingen",
"offer_minmax": "min / max",
"offer_minutes": "min",
"offer_promt_fiat": "How much {currency} do you want to buy?",
"offer_promt_fiat": "Hoeveel {currency} wilt u kopen?",
"offer_promt_fiat_e": "Bijvoorbeeld 100",
"offer_window": "window",
"p2p": "A p2p exchange"
"offer_window": "raam",
"p2p": "Een p2p exchange"
},
"lnd": {
"errorInvoiceExpired": "Invoice expired",
"errorInvoiceExpired": "Factuur verlopen",
"exchange": "Exchange",
"expired": "Verlopen",
"expiredLow": "verlopen",
"expiresIn": "Verloopt: {time}",
"payButton": "Pay",
"placeholder": "Invoice",
"potentialFee": "Potential fee: {fee}",
"payButton": "Betalen",
"placeholder": "Factuur",
"potentialFee": "Mogelijke fee: {fee}",
"refill": "Bijvullen",
"refill_card": "Refill with bank card",
"refill_create": "In order to proceed, please create a Bitcoin wallet to refill with.",
"refill_external": "Aanvullen met exterene portemonnee",
"refill_card": "Bijvullen met bankpas",
"refill_create": "Om verder te gaan, moet u een Bitcoin wallet maken om mee te vullen.",
"refill_external": "Aanvullen met externe wallet",
"refill_lnd_balance": "Vul Lightning-portemonneesaldo bij",
"sameWalletAsInvoiceError": "U kunt geen factuur betalen met dezelfde portemonnee die is gebruikt om de factuur te maken.",
"title": "fondsen beheren"
},
"lndViewInvoice": {
"additional_info": "Additional Information",
"for": "For:",
"has_been_paid": "This invoice has been paid for",
"additional_info": "Extra informatie",
"for": "Voor:",
"has_been_paid": "Deze factuur is betaald",
"open_direct_channel": "Open een rechtstreeks kanaal met deze node:",
"please_pay": "Please pay",
"preimage": "Preimage",
"please_pay": "Betaal alstublieft",
"preimage": "Préimage",
"sats": "sats",
"wasnt_paid_and_expired": "This invoice was not paid for and has expired"
"wasnt_paid_and_expired": "Deze factuur is niet betaald en is verlopen"
},
"plausibledeniability": {
"create_fake_storage": "Nep versleutelde opslag aanmaken",
"create_fake_storage": "Creëer versleutelde opslag",
"create_password": "Wachtwoord aanmaken",
"create_password_explanation": "Wachtwoord voor nep-opslag hoort niet overeen te komen met wachtwoord voor uw hoofdopslag",
"help": "Onder bepaalde omstandigheden kunt u worden gedwongen om uw wachtwoord te onthullen. Om uw munten veilig te houden, kan BlueWallet nog een versleutelde opslag aanmaken, met een ander wachtwoord. Onder druk kunt u dit wachtwoord bekendmaken aan de derde partij. Indien ingevoerd in BlueWallet, zal het nieuwe nep'-opslagruimte worden ontgrendeld. Dit lijkt legitiem voor de derde partij, maar zal uw hoofdopslag met munten niet bekend maken aan de derde partij",
"help": "Onder bepaalde omstandigheden kunt u worden gedwongen om uw wachtwoord te onthullen. Om uw munten veilig te houden, kan BlueWallet nog een versleutelde opslag aanmaken, met een ander wachtwoord. Onder druk kunt u dit wachtwoord bekendmaken aan de derde partij. Indien ingevoerd in BlueWallet, zal het nieuwe nep'-opslagruimte worden ontgrendeld. Dit lijkt legitiem voor de derde partij, maar zal uw hoofdopslag met munten niet bekend maken aan de derde partij.",
"help2": "De nieuwe opslag zal volledig functioneel zijn en u kunt er een minimum aantal munten opslaan zodat het geloofwaardig lijkt.",
"password_should_not_match": "Wachtwoord voor nep-opslag hoort niet overeen te komen met wachtwoord voor uw hoofdopslag",
"password_should_not_match": "Wachtwoord is momenteel in gebruik. Probeer een ander wachtwoord.",
"passwords_do_not_match": "Wachtwoorden komen niet overeen, probeer het opnieuw",
"retype_password": "Herhaal wachtwoord",
"success": "Succes",
"title": "Plausibele ontkenning"
},
"pleasebackup": {
"ask": "Have you saved your wallet's backup phrase? This backup phrase is required to access your funds in case you lose this device. Without the backup phrase, your funds will be permanently lost.",
"ask_no": "No, I have not",
"ask_yes": "Yes, I have",
"ask": "Heeft u uw back-up zin opgeslagen? Deze back-up zin is nodig om toegang te krijgen tot uw gelden wanneer u dit apparaat verliest. Zonder de back-up zin zijn je gelden voor altijd verloren.",
"ask_no": "Nee, dat heb ik niet",
"ask_yes": "Ja, dat heb ik.",
"ok": "Oké, ik heb het opgeschreven!",
"ok_lnd": "Oké, ik heb het bewaard.",
"text": "Please take a moment to write down this mnemonic phrase on a piece of paper. It's your backup you can use to restore the wallet on other device.",
"text_lnd": "Please take a moment to save this LNDHub authentication. It's your backup you can use to restore the wallet on other device.",
"title": "Uw portomonnee is aangemaakt..."
"text": "Neem alstublieft een moment om deze mnemonic phrase op papier te schrijven. Het is uw back-up die u kunt gebruiken om uw wallet te herstellen op een ander apparaat.",
"text_lnd": "Neem alstublieft een moment om deze LNDHub authenticatie op te slaan. Het is uw back-up die u kunt gebruiken om uw wallet te herstellen op een ander apparaat.",
"title": "Uw wallet is aangemaakt..."
},
"receive": {
"details_create": "Create",
"details_create": "Maken",
"details_label": "Omschrijving",
"details_setAmount": "Ontvang met bedrag",
"details_share": "delen",
"header": "Ontvang"
},
"send": {
"broadcastButton": "BROADCAST",
"broadcastError": "error",
"broadcastNone": "Input transaction hash",
"broadcastPending": "pending",
"broadcastSuccess": "success",
"broadcastButton": "UITZENDEN",
"broadcastError": "fout",
"broadcastNone": "Voer transactie-hash in",
"broadcastPending": "in afwachting",
"broadcastSuccess": "succes",
"confirm_header": "Bevestig",
"confirm_sendNow": "Nu verzenden",
"create_amount": "Bedrag",
"create_broadcast": "Uitzenden",
"create_copy": "Copy and broadcast later",
"create_copy": "Kopieer en verzend lader",
"create_details": "Details",
"create_fee": "Vergoeding",
"create_fee": "Fee",
"create_memo": "Memo",
"create_satoshi_per_byte": "Satoshi per byte",
"create_this_is_hex": "Dit is de transactie-hex, ondertekend en klaar om op het netwerk te worden uitgezonden.",
"create_this_is_hex": "Dit is uw transactie-hex, ondertekend en klaar om op het netwerk te worden uitgezonden.",
"create_to": "Naar",
"create_tx_size": "TX grootte",
"create_verify": "Verify on coinb.in",
"details_add_rec_add": "Add Recipient",
"details_add_rec_rem": "Remove Recipient",
"create_verify": "Verifieer op coinb.in",
"details_add_rec_add": "Voeg ontvanger toe",
"details_add_rec_rem": "Verwijder ontvanger",
"details_address": "adres",
"details_address_field_is_not_valid": "Adresveld is niet geldig",
"details_adv_fee_bump": "Allow Fee Bump",
"details_adv_full": "Use Full Balance",
"details_adv_full_remove": "Your other recipients will be removed from this transaction.",
"details_adv_full_sure": "Weet u zeker dat u het volledige saldo van uw portomonnee wilt gebruiken voor deze transactie?",
"details_address_field_is_not_valid": "Adres is niet geldig",
"details_adv_fee_bump": "Sta Fee Bumb toe",
"details_adv_full": "Gebruik volledige saldo",
"details_adv_full_remove": "Uw andere ontvangers worden verwijderd van deze transactie.",
"details_adv_full_sure": "Weet u zeker dat u het volledige saldo van uw wallet wilt gebruiken voor deze transactie?",
"details_adv_import": "Importeer transactie",
"details_amount_field_is_not_valid": "Bedrag veld is niet geldig",
"details_create": "Aanmaken",
"details_amount_field_is_not_valid": "Bedrag is niet geldig",
"details_create": "Maak factuur aan",
"details_error_decode": "Fout: Niet in staat om Bitcoin adres te decoderen",
"details_fee_field_is_not_valid": "Tarief is niet geldig",
"details_next": "Volgende",
"details_no_maximum": "The selected wallet does not support automatic maximum balance calculation. Are you sure to want to select this wallet?",
"details_no_multiple": "The selected wallet does not support sending Bitcoin to multiple recipients. Are you sure to want to select this wallet?",
"details_no_signed_tx": "The selected file does not contain a transaction that can be imported.",
"details_no_maximum": "De geselecteerde wallet ondersteunt geen automatische berekening van het maximale saldo. Weet u zeker dat u deze wallet wilt selecteren?",
"details_no_multiple": "De geselecteerde wallet ondersteunt het verzenden van Bitcoin naar meerdere ontvangers niet. Weet u zeker dat u deze wallet wilt selecteren?",
"details_no_signed_tx": "Het geselecteerde bestand bevat geen transactie die kan worden geïmporteerd.",
"details_note_placeholder": "notitie voor mezelf",
"details_scan": "Scan",
"details_total_exceeds_balance": "Het verzendingsbedrag overschrijdt het beschikbare saldo.",
"details_wallet_before_tx": "Before creating a transaction, you must first add a Bitcoin wallet.",
"details_wallet_selection": "Wallet Selection",
"dynamic_init": "Initializing",
"details_wallet_before_tx": "Voor het maken van een transactie moet u eerst een Bitcoin wallet toevoegen.",
"details_wallet_selection": "Wallet keuze",
"dynamic_init": "Initialiseren",
"dynamic_next": "Volgende",
"dynamic_prev": "Vorige",
"dynamic_start": "Start",
"dynamic_stop": "Stop",
"fee_10m": "10m",
"fee_1d": "1d",
"fee_3h": "3h",
"fee_3h": "3u",
"fee_custom": "Custom",
"fee_fast": "Fast",
"fee_fast": "Snel",
"fee_medium": "Medium",
"fee_replace_min": "The total fee rate (satoshi per byte) you want to pay should be higher than {min} sat/byte",
"fee_satbyte": "in sat/byte",
"fee_slow": "Slow",
"fee_replace_min": "De totale fee rate (satoshi per byte) die u wilt betalen moet hoger zijn dan {min} sat/byte",
"fee_satbyte": "In sat/byte",
"fee_slow": "Langzaam",
"header": "Verstuur",
"input_clear": "Clear",
"input_clear": "Leegmaken",
"input_done": "Klaar",
"input_paste": "Plak",
"input_total": "Totaal:",
"permission_camera_message": "We hebben toestemming nodig om uw camera te gebruiken",
"permission_camera_title": "Permission to use camera",
"open_settings": "Open Settings",
"permission_camera_title": "Toestemming om camera te gebruiken",
"open_settings": "Open instellingen",
"permission_storage_later": "Vraag mij later",
"permission_storage_message": "BlueWallet needs your permission to access your storage to save this transaction.",
"permission_storage_title": "BlueWallet Storage Access Permission",
"permission_storage_message": "BlueWallet heeft u toestemming nodig om toegang te krijgen tot uw opslag om deze transactie op te slaan.",
"permission_storage_title": "BlueWallet opslag toegang toestemming",
"psbt_clipboard": "Gekopieerd naar Plakbord",
"psbt_this_is_psbt": "This is a partially signed bitcoin transaction (PSBT). Please finish signing it with your hardware wallet.",
"psbt_tx_export": "Export to file",
"psbt_tx_open": "Open Signed Transaction",
"psbt_tx_scan": "Scan Signed Transaction",
"qr_error_no_qrcode": "The selected image does not contain a QR Code.",
"qr_error_no_wallet": "The selected file does not contain a wallet that can be imported.",
"psbt_this_is_psbt": "Dit is een gedeeltelijk ondertekende bitcoin-transactie (PSBT). Voltooi het door te ondertekenen met uw hardware wallet. ",
"psbt_tx_export": "Exporteer naar bestand",
"psbt_tx_open": "Open ondertekende transactie",
"psbt_tx_scan": "Scan ondertekende transactie",
"qr_error_no_qrcode": "De geselecteerde afbeelding bevat geen QR-code.",
"qr_error_no_wallet": "Het geselecteerde bestand bevat geen wallet die geïmporteerd kan worden.",
"success_done": "Klaar",
"txSaved": "The transaction file ({filePath}) has been saved in your Downloads folder ."
"txSaved": "Het transactiebestand ({filePath}) is opgeslagen in uw map Downloads.",
"problem_with_psbt": "Probleem met PSBT"
},
"settings": {
"about": "Over",
"about_awesome": "Gebouwt met de geweldige",
"about_backup": "Maak altijd een backup van uw sleutels!",
"about_free": "BlueWallet is a free and open source project. Crafted by Bitcoin users.",
"about_release_notes": "Release notes",
"about_review": "Leave us a review",
"about_selftest": "Run self test",
"about_free": "BlueWallet is een gratis en open-source project. Gemaakt door Bitcoin gebruikers.",
"about_release_notes": "Release-opmerkingen",
"about_review": "Laat een review achter",
"about_selftest": "Voer een zelftest uit",
"about_sm_github": "GitHub",
"about_sm_telegram": "Telegram chat",
"about_sm_twitter": "Volg ons op Twitter",
"advanced_options": "Geavanceerde opties",
"currency": "Valuta",
"currency_source": "Prijzen verstrekt bij CoinDesk",
"default_desc": "When disabled, BlueWallet will immediately open the selected wallet at launch.",
"default_info": "Default info",
"default_desc": "Indien uitgeschakeld zal BlueWallet meteen de geselecteerde wallet openen bij het opstarten.",
"default_info": "Standaard info",
"default_title": "Bij opstarten",
"default_wallets": "Bekijk alle portomonnees",
"default_wallets": "Bekijk alle wallets",
"electrum_connected": "Verbonden",
"electrum_connected_not": "Niet verbonden",
"electrum_error_connect": "Can't connect to provided Electrum server",
"electrum_host": "host, for example {example}",
"electrum_error_connect": "Kan niet verbinden met aangeleverde Electrum server",
"electrum_host": "host, bijvoorbeeld {example}",
"electrum_port": "TCP-poort, gebruikelijk {example}",
"electrum_port_ssl": "SSL-poort, gebruikelijk {example}",
"electrum_saved": "Your changes have been saved successfully. Restart may be required for changes to take effect.",
"electrum_saved": "Uw veranderingen zijn succesvol opgeslagen. Opnieuw opstarten kan nodig zijn om de wijzigingen door te voeren.",
"electrum_settings": "Electrum instellingen",
"electrum_settings_explain": "Laat leeg om standaardinstelling te gebruiken",
"electrum_status": "Status",
"encrypt_decrypt": "Versleutel opslag",
"encrypt_decrypt_q": "Are you sure you want to decrypt your storage? This will allow your wallets to be accessed without a password.",
"encrypt_decrypt_q": "Weet u zeker dat u uw opslag wilt ontsleutelen? Hierdoor kunnen uw wallets zonder wachtwoord worden geopend.",
"encrypt_del_uninstall": "Wis als BlueWallet is verwijderd",
"encrypt_enc_and_pass": "Encrypted en wachtwoord beveiligd",
"encrypt_enc_and_pass": "Versleuteld en wachtwoord beveiligd",
"encrypt_title": "Beveiliging",
"encrypt_tstorage": "opslag",
"encrypt_use": "Gebruik {type}",
"encrypt_use_expl": "{type} will be used to confirm your identity prior to making a transaction, unlocking, exporting or deleting a wallet. {type} will not be used to unlock an encrypted storage.",
"encrypt_use_expl": "{type} wordt gebruikt om uw identiteit te bevestigen voordat u een transactie uitvoert, een wallet ontgrendelt, exporteert of verwijdert. {type} wordt niet gebruikt om een versleutelde opslag te ontgrendelen.",
"general": "Algemeen",
"general_adv_mode": "Enable advanced mode",
"general_adv_mode_e": "When enabled, you will see advanced options such as different wallet types, the ability to specify the LNDHub instance you wish to connect to and custom entropy during wallet creation.",
"general_continuity": "Continuity",
"general_continuity_e": "When enabled, you will be able to view selected wallets, and transactions, using your other Apple iCloud connected devices.",
"groundcontrol_explanation": "GroundControl is a free opensource push notifications server for bitcoin wallets. You can install your own GroundControl server and put its URL here to not rely on BlueWallet's infrastructure. Leave blank to use default",
"general_adv_mode_e": "Indien ingeschakeld ziet u geavanceerde opties zoals verschillende wallettypes, de mogelijkheid om de LNDHub-instantie te specificeren waarmee u verbinding wilt maken en aangepaste entropie tijdens het aanmaken van een wallet.",
"general_continuity": "Continuïteit",
"general_continuity_e": "Indien ingeschakeld, kunt u geselecteerde wallets en transacties bekijken met uw andere Apple iCloud-apparaten.",
"groundcontrol_explanation": "GroundControl is een gratis opensource-server voor pushmeldingen voor bitcoin-wallets. U kunt uw eigen GroundControl-server installeren en de URL hier plaatsen om niet te vertrouwen op de infrastructuur van BlueWallet. Laat leeg om standaard te gebruiken",
"header": "instellingen",
"language": "Taal",
"language_restart": "When selecting a new language, restarting BlueWallet may be required for the change to take effect.",
"language_restart": "Bij het selecteren van een nieuwe taal kan het nodig zijn om BlueWallet opnieuw op te starten om de wijziging door te voeren.",
"lightning_error_lndhub_uri": "Ongeldige LndHub URI",
"lightning_saved": "Uw wijzigingen zijn succesvol opgeslagen",
"lightning_settings": "Lightning instellingen",
"lightning_settings_explain": "Om verbinding te maken met uw eigen LND-knooppunt installeert u LndHub en zet u de URL hier in de instellingen. Laat dit leeg om de standaard lndHub (lndhub.io) te gebruiken.",
"lightning_settings_explain": "Om verbinding te maken met uw eigen LND-node installeert u LndHub en plaatst u de URL hier in de instellingen. Laat dit leeg om de standaard lndHub (lndhub.io) te gebruiken.",
"network": "Netwerk",
"network_broadcast": "Broadcast transaction",
"network_broadcast": "Verzend transactie",
"network_electrum": "Electrum server",
"not_a_valid_uri": "Ongeldige URI",
"notifications": "Meldingen",
"password": "Wachtwoord",
"password_explain": "Maak een wachtwoord aan dat u wilt gebruiken om de opslag te versleutelen",
"passwords_do_not_match": "Wachtwoorden komen niet overeen",
"plausible_deniability": "Plausibele ontkenning...",
"push_notifications": "Push meldingen",
"retype_password": "Geef nogmaals het wachtwoord",
"plausible_deniability": "Plausibele ontkenning",
"privacy": "Privacy",
"privacy_read_clipboard": "Lees klembord",
"privacy_read_clipboard_alert": "BlueWallet geeft snelkoppelingen weer voor het afhandelen van een factuur of adres op uw klembord.",
"privacy_system_settings": "Systeeminstellingen",
"privacy_quickactions": "Wallet snelkoppelingen",
"privacy_quickactions_explanation": "Houd het BlueWallet-app-pictogram op uw startscherm ingedrukt om snel het saldo van uw wallet te bekijken.",
"privacy_clipboard_explanation": "Bied snelkoppelingen aan als een adres of factuur op uw klembord staat.",
"push_notifications": "Push notificaties",
"retype_password": "Geef nogmaals het wachtwoord op",
"save": "Opslaan",
"saved": "Opgeslagen"
},
"transactions": {
"cancel_explain": "We will replace this transaction with the one that pays you and has higher fees. This effectively cancels transaction. This is called RBF - Replace By Fee.",
"cancel_no": "This transaction is not replaceable",
"cancel_explain": "We zullen deze transactie vervangen door degene die u betaalt en hogere fees heeft. Dit annuleert effectief de transactie. Dit heet RBF - Replace By Fee.",
"cancel_no": "Deze transactie is niet vervangbaar",
"cancel_title": "Annuleer deze transcatie (RBF)",
"cpfp_create": "Create",
"cpfp_exp": "We will create another transaction that spends your unconfirmed transaction. The total fee will be higher than the original transaction fee, so it should be mined faster. This is called CPFP - Child Pays For Parent.",
"cpfp_no_bump": "This transaction is not bumpable",
"cpfp_title": "Bump fee (CPFP)",
"details_block": "Block Height",
"cpfp_create": "Creëer",
"cpfp_exp": "We zullen een andere transactie creëren die uw niet-bevestigde transactie besteedt. De totale vergoeding is hoger dan de oorspronkelijke transactiekosten, dus deze moet sneller worden gemined. Dit heet CPFP - Child Pays For Parent.",
"cpfp_no_bump": "Deze transactie is niet bumpable",
"cpfp_title": "Bumb fee (CPFP)",
"details_balance_hide": "Verberg saldo",
"details_balance_show": "Toon saldo",
"details_block": "Blokhoogte",
"details_copy": "Kopiëren",
"details_from": "Invoer",
"details_inputs": "Inputs",
"details_outputs": "Outputs",
"details_received": "Received",
"details_show_in_block_explorer": "Weergeven in blokverkenner",
"details_received": "Ontvangen",
"details_show_in_block_explorer": "Weergeven in block explorer",
"details_title": "Transacties",
"details_to": "Uitvoer",
"details_transaction_details": "Transactie details",
"enable_hw": "This wallet is not being used in conjunction with a hardwarde wallet. Would you like to enable hardware wallet use?",
"enable_hw": "Deze wallet wordt niet gebruikt in combinatie met een hardware wallet. Wilt u het gebruik van een hardware wallet inschakelen?",
"list_conf": "conf: {number}",
"list_title": "transacties",
"rbf_explain": "We will replace this transaction with the one with a higher fee, so it should be mined faster. This is called RBF - Replace By Fee.",
"rbf_title": "Bump fee (RBF)",
"status_bump": "Bump Fee",
"rbf_explain": "We zullen deze transactie vervangen door degene met een hogere fee, dus het zou sneller moeten worden gemined. Dit heet RBF - Replace By Fee.",
"rbf_title": "Bumb fee (RBF)",
"status_bump": "Bumb fee",
"status_cancel": "Annuleer transactie",
"transactions_count": "transactions count"
"transactions_count": "transactieteller"
},
"wallets": {
"add_bitcoin_explain": "Simple and powerful Bitcoin wallet",
"add_bitcoin_explain": "Eenvoudige en krachtige Bitcoin-wallet",
"add_bitcoin": "Bitcoin",
"add_create": "Aanmaken",
"add_entropy_generated": "{gen} bytes of generated entropy",
"add_entropy_provide": "Provide entropy via dice rolls",
"add_entropy_remain": "{gen} bytes of generated entropy. Remaining {rem} bytes will be obtained from the System random number generator.",
"add_import_wallet": "Portemonnee importeren",
"add_entropy_generated": "{gen} bytes gegenereerde entropie",
"add_entropy_provide": "Zorg voor entropie via dobbelstenen",
"add_entropy_remain": "{gen} bytes gegenereerde entropie. Resterende {rem} bytes zullen worden verkregen uit het systeem voor willekeurige getallen.",
"add_import_wallet": "Wallet importeren",
"import_file": "Importeer bestand",
"add_lightning": "Lightning",
"add_lightning_explain": "For spending with instant transactions",
"add_lightning_explain": "Voor uitgaven met directe transacties",
"add_lndhub": "Verbind met uw LNDHub",
"add_lndhub_error": "The provided node address is not valid LNDHub node.",
"add_lndhub_error": "Het opgegeven node-adres is geen geldige LNDHub-node.",
"add_lndhub_placeholder": "uw node adres",
"add_or": "of",
"add_title": "portemonnee toevoegen",
"add_title": "wallet toevoegen",
"add_wallet_name": "naam",
"add_wallet_type": "type",
"details_address": "Adres",
"details_advanced": "Geavenceerd",
"details_are_you_sure": "Weet u het zeker?",
"details_connected_to": "Verbonden met",
"details_del_wb": "Wallet Balance",
"details_del_wb_err": "The provided balance amount does not match this wallet's balance. Please, try again",
"details_del_wb_q": "This wallet has a balance. Before proceeding, please be aware that you will not be able to recover the funds without this wallet's seed phrase. In order to avoid accidental removal this wallet, please enter your wallet's balance of {balance} satoshis.",
"details_del_wb": "Wallet saldo",
"details_del_wb_err": "Het opgegeven saldo komt niet overeen met het saldo van deze wallet. Probeer het a.u.b. opnieuw",
"details_del_wb_q": "Deze wallet heeft een saldo. Voordat u verder gaat, moet u er rekening mee houden dat u het geld niet kunt terugkrijgen zonder de seed phrase van deze wallet. Om te voorkomen dat deze wallet per ongeluk wordt verwijderd, moet u het saldo van {balance} satoshis in uw wallet invoeren.",
"details_delete": "Verwijderen",
"details_delete_wallet": "Verwijder portomonne",
"details_display": "display in wallets list",
"details_delete_wallet": "Verwijder wallet",
"details_display": "toon in wallet lijst",
"details_export_backup": "Exporteren / back-up maken",
"details_marketplace": "Marktplaats",
"details_master_fingerprint": "Master fingerprint",
"details_master_fingerprint": "Master vingerafdruk",
"details_no_cancel": "Nee, annuleren",
"details_save": "Opslaan",
"details_show_xpub": "Toon portemonnee XPUB",
"details_title": "Portemonnee",
"details_show_xpub": "Toon wallet XPUB",
"details_title": "Wallet",
"details_type": "Type",
"details_use_with_hardware_wallet": "Gebruik met hardware wallet",
"details_wallet_updated": "Wallet updated",
"details_yes_delete": "Yes, delete",
"export_title": "portemonnee exporteren",
"details_wallet_updated": "Wallet bijgewerkt",
"details_yes_delete": "Ja, verwijder",
"export_title": "wallet exporteren",
"import_do_import": "Importeren",
"import_error": "Importeren mislukt. Zorg ervoor dat de verstrekte gegevens geldig zijn.",
"import_explanation": "Write here your mnemonic, private key, WIF, or anything you've got. BlueWallet will do its best to guess the correct format and import your wallet",
"import_explanation": "Schrijf hier je mnemonic phrase, private key, WIF of wat je maar hebt. BlueWallet zal zijn best doen om het juiste formaat te raden en uw wallet te importeren",
"import_imported": "Geïmporteerd",
"import_scan_qr": "of QR-code scannen?",
"import_scan_qr": "QR-code scannen of importeren?",
"import_success": "Succes",
"looks_like_bip38": "Dit lijkt op een met een wachtwoord beveiligde private key (BIP38)",
"enter_bip38_password": "Voer wachtwoord in om te ontgrendelen",
"import_title": "importeren",
"list_create_a_button": "Voeg nu toe",
"list_create_a_wallet": "Portemonnee aanmaken",
"list_create_a_wallet1": "It's free and you can create",
"list_create_a_wallet2": "zoveel als u wilt",
"list_create_a_wallet": "Wallet aanmaken",
"list_create_a_wallet_text": "Het is gratis en u kunt \ner zoveel maken als u wilt",
"list_empty_txs1": "Uw transacties verschijnen hier",
"list_empty_txs1_lightning": "Lightning wallet should be used for your daily transactions. Fees are unfairly cheap and speed is blazing fast.",
"list_empty_txs2": "Start with your wallet",
"list_empty_txs2_lightning": "\nTo start using it tap on \"manage funds\" and topup your balance.",
"list_header": "A wallet represents a pair of keys, one private and one you can share to receive coins.",
"list_import_error": "An error was encountered when attempting to import this wallet.",
"list_import_problem": "There was a problem importing this wallet",
"list_empty_txs1_lightning": "Lightning-wallet moet worden gebruikt voor uw dagelijkse transacties. De fees zijn oneerlijk goedkoop en het is razendsnel.",
"list_empty_txs2": "Begin met uw wallet",
"list_empty_txs2_lightning": "\nOm het te gebruiken, tikt u op \"beheer fondsen\" en laadt u uw saldo op.",
"list_header": "Een wallet vertegenwoordigt een paar keys, een private en een die u kunt delen om coins te ontvangen.",
"list_import_error": "Er is een fout opgetreden bij het importeren van deze wallet.",
"list_import_problem": "Er is een probleem opgetreden bij het importeren van deze wallet",
"list_latest_transaction": "laatste transactie",
"list_long_choose": "Kies foto",
"list_long_clipboard": "Copy from Clipboard",
"list_long_clipboard": "Kopiëren van klembord",
"list_long_scan": "Scan QR-code",
"take_photo": "Maak foto",
"list_tap_here_to_buy": "Koop Bitcoin",
"list_title": "portemonnees",
"list_title": "wallets",
"list_tryagain": "Probeer opnieuw",
"reorder_title": "Portemonnees opnieuw ordenen",
"select_no_bitcoin": "Er is momenteel geen Bitcoin portomonnee beschikbaar",
"select_no_bitcoin_exp": "A Bitcoin wallet is required to refill Lightning wallets. Please, create or import one.",
"select_wallet": "Selecteer portemonnee",
"reorder_title": "Wallets opnieuw ordenen",
"select_no_bitcoin": "Er is momenteel geen Bitcoin-wallet beschikbaar",
"select_no_bitcoin_exp": "Een Bitcoin-wallet is vereist om Lightning-wallets opnieuw te vullen. Maak of importeer er een.",
"select_wallet": "Selecteer wallet",
"xpub_copiedToClipboard": "Gekopieerd naar het klembord.",
"xpub_title": "portemonnee XPUB"
"xpub_title": "wallet XPUB"
},
"multisig": {
"multisig_vault": "Kluis",
"multisig_vault_explain": "Beste beveiliging voor grote bedragen",
"provide_signature": "Geef een handtekening",
"vault_key": "Kluisnummer {number}",
"required_keys_out_of_total": "Vereiste sleutels uit het totaal",
"fee": "Fee: {number}",
"fee_btc": "{number} BTC",
"confirm": "Bevestig",
"header": "Verzenden",
"share": "Delen",
"how_many_signatures_can_bluewallet_make": "hoeveel handtekeningen kan BlueWallet maken",
"scan_or_import_file": "Scan of importeer bestand",
"export_coordination_setup": "export coördinatie setup",
"cosign_this_transaction": "Deze transactie medeondertekenen?",
"lets_start": "Laten we beginnen",
"create": "Maken",
"provide_key": "Geef de key op",
"native_segwit_title": "Beste oefening",
"wrapped_segwit_title": "Beste compatibiliteit",
"legacy_title": "Legacy",
"co_sign_transaction": "Onderteken QR-airgapped transactie",
"what_is_vault": "Een kluis is een",
"what_is_vault_numberOfWallets": "{m}-van-{n} multisig",
"what_is_vault_wallet": "wallet",
"vault_advanced_customize": "Kluis-instellingen...",
"needs": "Behoeften",
"what_is_vault_description_number_of_vault_keys": "{m} kluissleutels",
"what_is_vault_description_to_spend": "te besteden en een 3e die u \nals back-up kunt gebruiken.",
"quorum": "{m} van {n} quorum",
"quorum_header": "Quorum",
"of": "van",
"wallet_type": "Wallettype",
"view_key": "bekijk",
"invalid_mnemonics": "Deze mnemonic phrase lijkt niet te kloppen",
"invalid_cosigner": "Geen geldige mede-ondertekenaar gegevens",
"invalid_cosigner_format": "Onjuiste mede-ondertekenaar: dit is geen mede-ondertekenaar voor het {format} formaat",
"create_new_key": "Maak een nieuwe",
"scan_or_open_file": "Scan of open bestand",
"i_have_mnemonics": "Ik heb een seed voor deze key...",
"please_write_down_mnemonics": "Schrijf dit mnemonic phrase op papier. Maak je geen zorgen, je kunt het later opschrijven.",
"i_wrote_it_down": "Ok, ik heb het opgeschreven",
"type_your_mnemonics": "Voeg een seed in om uw bestaande kluissleutel te importeren",
"this_is_cosigners_xpub": "Dit is de xpub van mede-ondertekenaar, klaar om in een andere wallet te worden geïmporteerd. Het is veilig om het te delen.",
"wallet_key_created": "Uw kluissleutel is gemaakt. Neem even de tijd om een veilige back-up van uw mnemonic seed te maken",
"are_you_sure_seed_will_be_lost": "Weet u het zeker? Uw mnemonic seed zal verloren gaan als u geen back-up heeft",
"forget_this_seed": "Vergeet deze seed en gebruik xpub",
"invalid_fingerprint": "Vingerafdruk voor dit seed komt niet overeen met de vingerafdruk van deze mede-ondertekenaar",
"view_edit_cosigners": "Bekijk/bewerk mede-ondertekenaars",
"this_cosigner_is_already_imported": "Deze mede-ondertekenaar is al geïmporteerd",
"export_signed_psbt": "Ondertekende PSBT exporteren",
"view_edit_cosigners_title": "Bewerk mede-ontertekenaars"
}
}

47
package-lock.json generated
View File

@ -1,6 +1,6 @@
{
"name": "bluewallet",
"version": "5.6.4",
"version": "5.6.5",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@ -6957,9 +6957,9 @@
}
},
"amplitude-js": {
"version": "7.2.2",
"resolved": "https://registry.npmjs.org/amplitude-js/-/amplitude-js-7.2.2.tgz",
"integrity": "sha512-Y1/kw/NaxMdqwBnkbjPywpjPbSmuVuszFLQ9tw56P6YraljvbMC93afHQvLC/3zG5SImDnykbg/8HxrWFDhsLg==",
"version": "7.3.0",
"resolved": "https://registry.npmjs.org/amplitude-js/-/amplitude-js-7.3.0.tgz",
"integrity": "sha512-FI3ziFNfV4kqpLYHLo6t+E7cbZZ1n8VRCNt214Z1CuDbEzPcc/TenmkCwPoYJA5FQibamqZL9qiKtdMTZhSsUg==",
"requires": {
"@amplitude/ua-parser-js": "0.7.24",
"blueimp-md5": "^2.10.0",
@ -9288,9 +9288,9 @@
"dev": true
},
"detox": {
"version": "17.9.0",
"resolved": "https://registry.npmjs.org/detox/-/detox-17.9.0.tgz",
"integrity": "sha512-1dyzO4Bz8e2RieRLX2WiS+3VBAd5KxCtKU4fPEFXKoSZROc1ToAl6OZWv+2ALzAMaSd6pZeeQPO1M4GTEeGaiQ==",
"version": "17.10.2",
"resolved": "https://registry.npmjs.org/detox/-/detox-17.10.2.tgz",
"integrity": "sha512-gKJgtdJfNk4ZHobd0S93F5i0LH9WthYPZ41fsa+8uA1bEnLKknGTBV3iG+YdHXGRRa7ZkAh0A2SAuwnl0z6P+Q==",
"requires": {
"bunyan": "^1.8.12",
"bunyan-debug-stream": "^1.1.0",
@ -9331,9 +9331,9 @@
}
},
"cliui": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.3.tgz",
"integrity": "sha512-Gj3QHTkVMPKqwP3f7B4KPkBZRMR9r4rfi5bXFpg1a+Svvj8l7q5CnkBkVQzfxT5DFSsGk2+PascOgL0JYkL2kw==",
"version": "7.0.4",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
"integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
"requires": {
"string-width": "^4.2.0",
"strip-ansi": "^6.0.0",
@ -9358,11 +9358,6 @@
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
},
"escalade": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw=="
},
"find-up": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
@ -9461,9 +9456,9 @@
}
},
"yargs-parser": {
"version": "20.2.3",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.3.tgz",
"integrity": "sha512-emOFRT9WVHw03QSvN5qor9QQT9+sw5vwxfYweivSMHTcAXPefwVae2FjO7JJjj8hCE4CzPOPeFM83VwT29HCww=="
"version": "20.2.4",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz",
"integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA=="
}
}
},
@ -18940,9 +18935,9 @@
"from": "git+https://github.com/marcosrdz/react-native-handoff.git"
},
"react-native-haptic-feedback": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/react-native-haptic-feedback/-/react-native-haptic-feedback-1.10.0.tgz",
"integrity": "sha512-2aEXYTLrQq2N3phaGJ23V0x6qsIz4j1vhTck9A7geTfW7J54mOfk1Pr4Y1WEMMKptFA9p78kZHBb31IIE+g37w=="
"version": "1.11.0",
"resolved": "https://registry.npmjs.org/react-native-haptic-feedback/-/react-native-haptic-feedback-1.11.0.tgz",
"integrity": "sha512-KTIy7lExwMtB6pOpCARyUzFj5EzYTh+A1GN/FB5Eb0LrW5C6hbb1kdj9K2/RHyZC+wyAJD1M823ZaDCU6n6cLA=="
},
"react-native-image-picker": {
"version": "2.3.4",
@ -19226,9 +19221,9 @@
}
},
"react-native-watch-connectivity": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/react-native-watch-connectivity/-/react-native-watch-connectivity-1.0.2.tgz",
"integrity": "sha512-uNx6Zhx++LpRRyQddukBcMyMtWnleP97OME9HEkW91rEuwTviBK12+1sn/YGBgGLrmdEULAoPO91w619w2Efbw==",
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/react-native-watch-connectivity/-/react-native-watch-connectivity-1.0.3.tgz",
"integrity": "sha512-YITROIsVJw2mw5bm2Xr0waob16EdWJKpIO1B7AJWEpoWwSRu6bS/x1Z0QOhIFDWhRJFNvTQwnnflCq6PjflXNQ==",
"requires": {
"lodash.sortby": "^4.7.0"
}
@ -19250,8 +19245,8 @@
}
},
"react-native-widget-center": {
"version": "git+https://github.com/BlueWallet/react-native-widget-center.git#6f6306bdba950262b09c0089de906f3e128fae53",
"from": "git+https://github.com/BlueWallet/react-native-widget-center.git#v0.0.4"
"version": "git+https://github.com/BlueWallet/react-native-widget-center.git#e2e9a9038b76d096bf929a87105a97a0a7095001",
"from": "git+https://github.com/BlueWallet/react-native-widget-center.git#e2e9a9038b76d096bf929a87105a97a0a7095001"
},
"react-refresh": {
"version": "0.4.3",

View File

@ -1,6 +1,6 @@
{
"name": "bluewallet",
"version": "5.6.4",
"version": "5.6.5",
"license": "MIT",
"devDependencies": {
"@babel/core": "^7.10.4",
@ -77,7 +77,7 @@
"@react-navigation/stack": "5.9.3",
"@remobile/react-native-qrcode-local-image": "git+https://github.com/BlueWallet/react-native-qrcode-local-image.git",
"@sentry/react-native": "1.9.0",
"amplitude-js": "7.2.2",
"amplitude-js": "7.3.0",
"assert": "1.5.0",
"base-x": "3.0.8",
"bc-bech32": "file:blue_modules/bc-bech32",
@ -94,7 +94,7 @@
"coinselect": "3.1.12",
"crypto-js": "3.1.9-1",
"dayjs": "1.9.1",
"detox": "17.9.0",
"detox": "17.10.2",
"ecurve": "1.0.6",
"electrum-client": "git+https://github.com/BlueWallet/rn-electrum-client.git#f9a827e724a5a2e578fdfdb483f83793af55b030",
"electrum-mnemonic": "2.0.0",
@ -127,7 +127,7 @@
"react-native-fs": "2.16.6",
"react-native-gesture-handler": "1.8.0",
"react-native-handoff": "git+https://github.com/marcosrdz/react-native-handoff.git",
"react-native-haptic-feedback": "1.10.0",
"react-native-haptic-feedback": "1.11.0",
"react-native-image-picker": "2.3.4",
"react-native-inappbrowser-reborn": "git+https://github.com/BlueWallet/react-native-inappbrowser.git#fa2d8e1763e46dd12a7e53081e97a0f908049103",
"react-native-level-fs": "3.0.1",
@ -155,9 +155,9 @@
"react-native-tcp-socket": "3.7.1",
"react-native-tooltip": "git+https://github.com/BlueWallet/react-native-tooltip.git#d369e7ece09e4dec73873f1cfeac83e9d35294a6",
"react-native-vector-icons": "6.6.0",
"react-native-watch-connectivity": "1.0.2",
"react-native-watch-connectivity": "1.0.3",
"react-native-webview": "10.9.2",
"react-native-widget-center": "git+https://github.com/BlueWallet/react-native-widget-center.git#v0.0.4",
"react-native-widget-center": "git+https://github.com/BlueWallet/react-native-widget-center.git#e2e9a9038b76d096bf929a87105a97a0a7095001",
"react-test-render": "1.1.2",
"readable-stream": "3.6.0",
"realm": "6.1.4",

View File

@ -14,8 +14,9 @@ import {
StyleSheet,
Dimensions,
Platform,
ScrollView,
Text,
LayoutAnimation,
FlatList,
} from 'react-native';
import { Icon } from 'react-native-elements';
import AsyncStorage from '@react-native-community/async-storage';
@ -64,7 +65,6 @@ const styles = StyleSheet.create({
backgroundColor: BlueCurrentTheme.colors.elevated,
},
scrollViewContent: {
flexWrap: 'wrap',
flexDirection: 'row',
},
modalContent: {
@ -212,6 +212,7 @@ const styles = StyleSheet.create({
export default class SendDetails extends Component {
static contextType = BlueStorageContext;
state = { isLoading: true };
scrollView = React.createRef();
constructor(props, context) {
super(props);
@ -254,7 +255,7 @@ export default class SendDetails extends Component {
feeUnit: fromWallet.getPreferredBalanceUnit(),
amountUnit: fromWallet.preferredBalanceUnit, // default for whole screen
renderWalletSelectionButtonHidden: false,
width: Dimensions.get('window').width - 320,
width: Dimensions.get('window').width,
};
}
}
@ -450,15 +451,8 @@ export default class SendDetails extends Component {
}
}
if (error) {
if (index === 0) {
this.scrollView.scrollTo();
} else if (index === this.state.addresses.length - 1) {
this.scrollView.scrollToEnd();
} else {
const page = Math.round(this.state.width * (this.state.addresses.length - 2));
this.scrollView.scrollTo({ x: page, y: 0, animated: true });
}
this.setState({ isLoading: false, recipientsScrollIndex: index });
this.scrollView.current.scrollToIndex({ index });
this.setState({ isLoading: false });
alert(error);
ReactNativeHapticFeedback.trigger('notificationError', { ignoreAndroidSystemSettings: false });
return;
@ -696,7 +690,8 @@ export default class SendDetails extends Component {
const feeSatoshi = new BigNumber(element.amount).multipliedBy(100000000);
return element.address.length > 0 && feeSatoshi > 0;
}) || this.state.addresses[0];
this.setState({ addresses: [firstTransaction], recipientsScrollIndex: 0 }, () => changeWallet());
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
this.setState({ addresses: [firstTransaction] }, () => changeWallet());
},
style: 'default',
},
@ -718,7 +713,8 @@ export default class SendDetails extends Component {
return element.amount === BitcoinUnit.MAX;
}) || this.state.addresses[0];
firstTransaction.amount = 0;
this.setState({ addresses: [firstTransaction], recipientsScrollIndex: 0 }, () => changeWallet());
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
this.setState({ addresses: [firstTransaction] }, () => changeWallet());
},
style: 'default',
},
@ -965,14 +961,15 @@ export default class SendDetails extends Component {
handleAddRecipient = () => {
const { addresses } = this.state;
addresses.push(new BitcoinTransaction());
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut, () => this.scrollView.current.scrollToEnd());
this.setState(
{
addresses,
isAdvancedTransactionOptionsVisible: false,
},
() => {
this.scrollView.scrollToEnd();
if (this.state.addresses.length > 1) this.scrollView.flashScrollIndicators();
this.scrollView.current.scrollToEnd();
if (this.state.addresses.length > 1) this.scrollView.current.flashScrollIndicators();
// after adding recipient it automatically scrolls to the last one
this.setState({ recipientsScrollIndex: this.state.addresses.length - 1 });
},
@ -982,13 +979,14 @@ export default class SendDetails extends Component {
handleRemoveRecipient = () => {
const { addresses } = this.state;
addresses.splice(this.state.recipientsScrollIndex, 1);
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
this.setState(
{
addresses,
isAdvancedTransactionOptionsVisible: false,
},
() => {
if (this.state.addresses.length > 1) this.scrollView.flashScrollIndicators();
if (this.state.addresses.length > 1) this.scrollView.current.flashScrollIndicators();
// after deletion it automatically scrolls to the last one
this.setState({ recipientsScrollIndex: this.state.addresses.length - 1 });
},
@ -1081,6 +1079,16 @@ export default class SendDetails extends Component {
this.setState({ isTransactionReplaceable: value });
};
scrollViewCurrentIndex = () => {
Keyboard.dismiss();
const offset = this.scrollView.current.contentOffset;
if (offset) {
const page = Math.round(offset.x / Dimensions.get('window').width);
return page;
}
return 0;
};
renderCreateButton = () => {
return (
<View style={styles.createButton}>
@ -1122,110 +1130,84 @@ export default class SendDetails extends Component {
);
};
handlePageChange = e => {
Keyboard.dismiss();
const offset = e.nativeEvent.contentOffset;
if (offset) {
const page = Math.round(offset.x / this.state.width);
if (this.state.recipientsScrollIndex !== page) {
this.setState({ recipientsScrollIndex: page });
}
}
};
renderBitcoinTransactionInfoFields = ({ item, index }) => {
return (
<View style={{ width: this.state.width }}>
<BlueBitcoinAmount
isLoading={this.state.isLoading}
amount={item.amount ? item.amount.toString() : null}
onAmountUnitChange={unit => {
const units = this.state.units;
units[index] = unit;
scrollViewCurrentIndex = () => {
Keyboard.dismiss();
const offset = this.scrollView.contentOffset;
if (offset) {
const page = Math.round(offset.x / this.state.width);
return page;
}
return 0;
};
const addresses = this.state.addresses;
const item = addresses[index];
renderBitcoinTransactionInfoFields = () => {
const rows = [];
switch (unit) {
case BitcoinUnit.SATS:
item.amountSats = parseInt(item.amount);
break;
case BitcoinUnit.BTC:
item.amountSats = currency.btcToSatoshi(item.amount);
break;
case BitcoinUnit.LOCAL_CURRENCY:
// also accounting for cached fiat->sat conversion to avoid rounding error
item.amountSats =
BlueBitcoinAmount.getCachedSatoshis(item.amount) || currency.btcToSatoshi(currency.fiatToBTC(item.amount));
break;
}
for (const [index, item] of this.state.addresses.entries()) {
rows.push(
<View key={index} style={{ width: this.state.width }}>
<BlueBitcoinAmount
isLoading={this.state.isLoading}
amount={item.amount ? item.amount.toString() : null}
onAmountUnitChange={unit => {
const units = this.state.units;
units[index] = unit;
const addresses = this.state.addresses;
const item = addresses[index];
switch (unit) {
case BitcoinUnit.SATS:
item.amountSats = parseInt(item.amount);
break;
case BitcoinUnit.BTC:
item.amountSats = currency.btcToSatoshi(item.amount);
break;
case BitcoinUnit.LOCAL_CURRENCY:
// also accounting for cached fiat->sat conversion to avoid rounding error
item.amountSats =
BlueBitcoinAmount.getCachedSatoshis(item.amount) || currency.btcToSatoshi(currency.fiatToBTC(item.amount));
break;
}
addresses[index] = item;
this.setState({ units, addresses });
}}
onChangeText={text => {
item.amount = text;
switch (this.state.units[index] || this.state.amountUnit) {
case BitcoinUnit.BTC:
item.amountSats = currency.btcToSatoshi(item.amount);
break;
case BitcoinUnit.LOCAL_CURRENCY:
item.amountSats = currency.btcToSatoshi(currency.fiatToBTC(item.amount));
break;
default:
case BitcoinUnit.SATS:
item.amountSats = parseInt(text);
break;
}
const addresses = this.state.addresses;
addresses[index] = item;
this.setState({ addresses }, this.reCalcTx);
}}
unit={this.state.units[index] || this.state.amountUnit}
inputAccessoryViewID={this.state.fromWallet.allowSendMax() ? BlueUseAllFundsButton.InputAccessoryViewID : null}
/>
<BlueAddressInput
onChangeText={async text => {
text = text.trim();
const transactions = this.state.addresses;
const { address, amount, memo, payjoinUrl } = DeeplinkSchemaMatch.decodeBitcoinUri(text);
item.address = address || text;
item.amount = amount || item.amount;
transactions[index] = item;
this.setState({
addresses: transactions,
memo: memo || this.state.memo,
isLoading: false,
payjoinUrl,
});
this.reCalcTx();
}}
onBarScanned={this.processAddressData}
address={item.address}
isLoading={this.state.isLoading}
inputAccessoryViewID={BlueDismissKeyboardInputAccessory.InputAccessoryViewID}
launchedBy={this.props.route.name}
/>
{this.state.addresses.length > 1 && (
<BlueText style={styles.of}>{loc.formatString(loc._.of, { number: index + 1, total: this.state.addresses.length })}</BlueText>
)}
</View>,
);
}
return rows;
addresses[index] = item;
this.setState({ units, addresses });
}}
onChangeText={text => {
item.amount = text;
switch (this.state.units[index] || this.state.amountUnit) {
case BitcoinUnit.BTC:
item.amountSats = currency.btcToSatoshi(item.amount);
break;
case BitcoinUnit.LOCAL_CURRENCY:
item.amountSats = currency.btcToSatoshi(currency.fiatToBTC(item.amount));
break;
default:
case BitcoinUnit.SATS:
item.amountSats = parseInt(text);
break;
}
const addresses = this.state.addresses;
addresses[index] = item;
this.setState({ addresses }, this.reCalcTx);
}}
unit={this.state.units[index] || this.state.amountUnit}
inputAccessoryViewID={this.state.fromWallet.allowSendMax() ? BlueUseAllFundsButton.InputAccessoryViewID : null}
/>
<BlueAddressInput
onChangeText={async text => {
text = text.trim();
const transactions = this.state.addresses;
const { address, amount, memo, payjoinUrl } = DeeplinkSchemaMatch.decodeBitcoinUri(text);
item.address = address || text;
item.amount = amount || item.amount;
transactions[index] = item;
this.setState({
addresses: transactions,
memo: memo || this.state.memo,
isLoading: false,
payjoinUrl,
});
this.reCalcTx();
}}
onBarScanned={this.processAddressData}
address={item.address}
isLoading={this.state.isLoading}
inputAccessoryViewID={BlueDismissKeyboardInputAccessory.InputAccessoryViewID}
launchedBy={this.props.route.name}
/>
{this.state.addresses.length > 1 && (
<BlueText style={styles.of}>{loc.formatString(loc._.of, { number: index + 1, total: this.state.addresses.length })}</BlueText>
)}
</View>
);
};
onUseAllPressed = () => {
@ -1238,13 +1220,13 @@ export default class SendDetails extends Component {
text: loc._.ok,
onPress: async () => {
Keyboard.dismiss();
const recipient = this.state.addresses[this.state.recipientsScrollIndex];
const recipient = this.state.addresses[this.scrollViewCurrentIndex()];
recipient.amount = BitcoinUnit.MAX;
recipient.amountSats = BitcoinUnit.MAX;
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
this.setState({
addresses: [recipient],
units: [BitcoinUnit.BTC],
recipientsScrollIndex: 0,
isAdvancedTransactionOptionsVisible: false,
});
},
@ -1271,6 +1253,8 @@ export default class SendDetails extends Component {
this.setState({ width: e.nativeEvent.layout.width });
};
keyExtractor = (_item, index) => `${index}`;
render() {
if (this.state.isLoading || typeof this.state.fromWallet === 'undefined') {
return (
@ -1286,20 +1270,20 @@ export default class SendDetails extends Component {
<StatusBar barStyle="light-content" />
<View>
<KeyboardAvoidingView behavior="position">
<ScrollView
pagingEnabled
horizontal
contentContainerStyle={styles.scrollViewContent}
ref={ref => (this.scrollView = ref)}
<FlatList
keyboardShouldPersistTaps="always"
onContentSizeChange={() => this.scrollView.scrollToEnd()}
onLayout={() => this.scrollView.scrollToEnd()}
onMomentumScrollEnd={this.handlePageChange}
scrollEnabled={this.state.addresses.length > 1}
extraData={this.state.addresses}
data={this.state.addresses}
renderItem={this.renderBitcoinTransactionInfoFields}
keyExtractor={this.keyExtractor}
ref={this.scrollView}
horizontal
pagingEnabled
onMomentumScrollBegin={Keyboard.dismiss}
scrollIndicatorInsets={{ top: 0, left: 8, bottom: 0, right: 8 }}
>
{this.renderBitcoinTransactionInfoFields()}
</ScrollView>
contentContainerStyle={styles.scrollViewContent}
/>
<View hide={!this.state.showMemoRow} style={styles.memo}>
<TextInput
onChangeText={text => this.setState({ memo: text })}

View File

@ -12,7 +12,6 @@ import {
Text,
TouchableOpacity,
View,
ScrollView,
} from 'react-native';
import {
BlueButton,
@ -88,10 +87,10 @@ const WalletsAddMultisigStep2 = () => {
color: colors.foregroundColor,
},
modalContentShort: {
backgroundColor: colors.elevated,
backgroundColor: colors.modal,
},
modalContent: {
backgroundColor: colors.elevated,
backgroundColor: colors.modal,
},
textFiat: {
color: colors.alternativeTextColor,
@ -126,6 +125,9 @@ const WalletsAddMultisigStep2 = () => {
wordText: {
color: colors.labelText,
},
headerText: {
color: colors.foregroundColor,
},
});
const onCreate = async () => {
@ -566,17 +568,18 @@ const WalletsAddMultisigStep2 = () => {
>
<KeyboardAvoidingView behavior={Platform.OS === 'ios' ? 'position' : null}>
<View style={[styles.modalContent, stylesHook.modalContent, styles.alignItemsCenter]}>
<Text style={[styles.headerText]}>{loc.multisig.this_is_cosigners_xpub}</Text>
<Text style={[styles.headerText, stylesHook.textDestination]}>{loc.multisig.this_is_cosigners_xpub}</Text>
<BlueSpacing20 />
<QRCode
value={cosignerXpub}
size={250}
color="#000000"
logoBackgroundColor={colors.brandingColor}
backgroundColor="#FFFFFF"
ecl="H"
/>
<View style={styles.qrCodeContainer}>
<QRCode
value={cosignerXpub}
size={260}
color="#000000"
logoBackgroundColor={colors.brandingColor}
backgroundColor="#FFFFFF"
ecl="H"
/>
</View>
<BlueSpacing20 />
<View style={styles.squareButtonWrapper}>
{isLoading ? (
@ -599,30 +602,24 @@ const WalletsAddMultisigStep2 = () => {
);
return (
<ScrollView contentContainerStyle={[styles.root, stylesHook.root]}>
<View style={[styles.root, stylesHook.root]}>
<StatusBar barStyle="light-content" />
<BlueSpacing20 />
<View style={[styles.root, stylesHook.root, styles.mainBlock]}>
<StatusBar barStyle="light-content" />
<FlatList data={data.current} renderItem={_renderKeyItem} keyExtractor={(_item, index) => `${index}`} />
<FlatList data={data.current} renderItem={_renderKeyItem} keyExtractor={(_item, index) => `${index}`} />
{renderMnemonicsModal()}
{renderMnemonicsModal()}
{renderProvideMnemonicsModal()}
{renderProvideMnemonicsModal()}
{renderCosignersXpubModal()}
</View>
{renderCosignersXpubModal()}
{footer}
</ScrollView>
</View>
);
};
const styles = StyleSheet.create({
root: {
flex: 1,
marginTop: -8,
flexDirection: 'column',
height: '100%',
marginHorizontal: 20,
},
mainBlock: {
height: '100%',
@ -664,7 +661,7 @@ const styles = StyleSheet.create({
paddingHorizontal: 16,
marginBottom: 8,
},
buttonContainer: {
buttonContainer: {
flexDirection: 'row',
marginVertical: 24,
alignItems: 'center',
@ -732,6 +729,7 @@ const styles = StyleSheet.create({
header2Text: { color: '#9AA0AA', fontSize: 14, paddingBottom: 20 },
alignItemsCenter: { alignItems: 'center' },
squareButtonWrapper: { height: 50, width: 250 },
qrCodeContainer: { borderWidth: 6, borderRadius: 8, borderColor: '#FFFFFF' },
});
WalletsAddMultisigStep2.navigationOptions = () => ({

View File

@ -3,6 +3,9 @@ vim ios/BlueWalletWatch/Info.plist
vim "ios/BlueWalletWatch Extension/Info.plist"
vim "ios/TodayExtension/Info.plist"
vim ios/BlueWallet.xcodeproj/project.pbxproj
vim ios/WalletInformationWidget/Widgets/MarketWidget/Info.plist
vim ios/WalletInformationWidget/Widgets/WalletInformationAndMarketWidget/Info.plist
vim ios/WalletInformationWidget/Info.plist
vim android/app/build.gradle
vim package.json
vim package-lock.json

View File

@ -6,12 +6,6 @@ import { MultisigCosigner } from '../../class/multisig-cosigner';
const bitcoin = require('bitcoinjs-lib');
const Base43 = require('../../blue_modules/base43');
const mnemonicsCobo =
'fossil glove maze chest logic shadow document describe awake card bunker lottery sunset athlete giant among logic capable happy sword ridge beef warfare fire';
const mnemonicsColdcard =
'inhale flip hundred clock onion wool upgrade unable cigar cricket move federal drum firm excuse adapt parade flag rice assume acid inch park cool';
const fp1cobo = 'D37EAD88';
const Zpub1 = 'Zpub74ijpfhERJNjhCKXRspTdLJV5eoEmSRZdHqDvp9kVtdVEyiXk7pXxRbfZzQvsDFpfDHEHVtVpx4Dz9DGUWGn2Xk5zG5u45QTMsYS2vjohNQ';
@ -30,6 +24,15 @@ const electumJson =
'{"x2/": {"xpub": "Zpub75mAE8EjyxSzoyPmGnd5E6MyD7ALGNndruWv52xpzimZQKukwvEfXTHqmH8nbbc6ccP5t2aM3mws3pKYSnKpKMMytdbNEZFUxKzztYFM8Pn", "hw_type": "coldcard", "ckcc_xfp": 64392470, "label": "Coldcard", "derivation": "m/48\'/1\'/0\'/1\'", "type": "hardware"}, "x1/": {"xpub": "Zpub74ijpfhERJNjhCKXRspTdLJV5eoEmSRZdHqDvp9kVtdVEyiXk7pXxRbfZzQvsDFpfDHEHVtVpx4Dz9DGUWGn2Xk5zG5u45QTMsYS2vjohNQ", "hw_type": "coldcard", "ckcc_xfp": 2293071571, "label": "Coldcard", "derivation": "m/48\'/1\'/0\'/1\'", "type": "hardware"}, "wallet_type": "2of2", "use_encryption": false, "seed_version": 17}';
describe('multisig-wallet (p2sh)', () => {
if (!process.env.MNEMONICS_COBO) {
console.error('process.env.MNEMONICS_COBO not set, skipped');
return;
}
if (!process.env.MNEMONICS_COLDCARD) {
console.error('process.env.MNEMONICS_COLDCARD not set, skipped');
return;
}
it('basic operations work', async () => {
const w = new MultisigHDWallet();
w.setSecret(txtFileFormatMultisigLegacy);
@ -174,7 +177,7 @@ describe('multisig-wallet (p2sh)', () => {
'xpub69SfFhG5eA9cqxHKM6b1HhXMpDzipUPDBNMBrjNgWWbbzKqnqwx2mvMyB5bRgmLAi7cBgr8euuz4Lvz3maWxpfUmdM71dyQuvq68mTAG4Cp',
fp1cobo,
);
w.addCosigner(mnemonicsColdcard);
w.addCosigner(process.env.MNEMONICS_COLDCARD);
w.setDerivationPath(path);
w.setM(2);
@ -250,8 +253,8 @@ describe('multisig-wallet (p2sh)', () => {
];
const w = new MultisigHDWallet();
w.addCosigner(mnemonicsCobo);
w.addCosigner(mnemonicsColdcard);
w.addCosigner(process.env.MNEMONICS_COBO);
w.addCosigner(process.env.MNEMONICS_COLDCARD);
w.setDerivationPath(path);
w.setM(2);
@ -299,6 +302,15 @@ describe('multisig-wallet (p2sh)', () => {
});
describe('multisig-wallet (wrapped segwit)', () => {
if (!process.env.MNEMONICS_COBO) {
console.error('process.env.MNEMONICS_COBO not set, skipped');
return;
}
if (!process.env.MNEMONICS_COLDCARD) {
console.error('process.env.MNEMONICS_COLDCARD not set, skipped');
return;
}
it('basic operations work', async () => {
const w = new MultisigHDWallet();
w.setSecret(txtFileFormatMultisigWrappedSegwit);
@ -415,12 +427,12 @@ describe('multisig-wallet (wrapped segwit)', () => {
const w = new MultisigHDWallet();
w.addCosigner(Ypub1, fp1cobo);
w.addCosigner(mnemonicsColdcard);
w.addCosigner(process.env.MNEMONICS_COLDCARD);
w.setDerivationPath(path);
w.setM(2);
assert.strictEqual(
w.convertXpubToMultisignatureXpub(MultisigHDWallet.seedToXpub(mnemonicsColdcard, path)),
w.convertXpubToMultisignatureXpub(MultisigHDWallet.seedToXpub(process.env.MNEMONICS_COLDCARD, path)),
'Ypub6kvtvTZpqGuWtQfg9bL5xe4vDWtwsirR8LzDvsY3vgXvyncW1NGXCUJ9Ps7CiizSSLV6NnnXSYyVDnxCu26QChWzWLg5YCAHam6cYjGtzRz',
);
assert.strictEqual(w.getCosignerForFingerprint(fp1cobo), w.getCosigner(1));
@ -490,12 +502,12 @@ describe('multisig-wallet (wrapped segwit)', () => {
const w = new MultisigHDWallet();
w.addCosigner(Ypub1, fp1cobo);
w.addCosigner(mnemonicsColdcard);
w.addCosigner(process.env.MNEMONICS_COLDCARD);
w.setDerivationPath(path);
w.setM(2);
assert.strictEqual(
w.convertXpubToMultisignatureXpub(MultisigHDWallet.seedToXpub(mnemonicsColdcard, path)),
w.convertXpubToMultisignatureXpub(MultisigHDWallet.seedToXpub(process.env.MNEMONICS_COLDCARD, path)),
'Ypub6kvtvTZpqGuWtQfg9bL5xe4vDWtwsirR8LzDvsY3vgXvyncW1NGXCUJ9Ps7CiizSSLV6NnnXSYyVDnxCu26QChWzWLg5YCAHam6cYjGtzRz',
);
assert.strictEqual(w.getCosignerForFingerprint(fp1cobo), w.getCosigner(1));
@ -543,6 +555,15 @@ describe('multisig-wallet (wrapped segwit)', () => {
});
describe('multisig-wallet (native segwit)', () => {
if (!process.env.MNEMONICS_COBO) {
console.error('process.env.MNEMONICS_COBO not set, skipped');
return;
}
if (!process.env.MNEMONICS_COLDCARD) {
console.error('process.env.MNEMONICS_COLDCARD not set, skipped');
return;
}
it('can sort buffers', async () => {
let sorted;
sorted = MultisigHDWallet.sortBuffers([Buffer.from('10', 'hex'), Buffer.from('0011', 'hex')]);
@ -636,7 +657,7 @@ describe('multisig-wallet (native segwit)', () => {
"m/48'/0'/0'/2'/1/3",
);
assert.strictEqual(
MultisigHDWallet.seedToXpub(mnemonicsColdcard, path),
MultisigHDWallet.seedToXpub(process.env.MNEMONICS_COLDCARD, path),
'xpub6FCYVZAU7dofgor9fQaqyqqA9NqBAn83iQpoayuWrwBPfwiPgCXGCD7dvAG93M5MZs5VWVP7FErGA5UeiALqaPt7KV67fL9WX9bqXTyeWxb',
);
assert.strictEqual(
@ -652,8 +673,8 @@ describe('multisig-wallet (native segwit)', () => {
assert.throws(() => w.addCosigner(Zpub1, fp1cobo, 'ROFLBOATS')); // invalid path
assert.throws(() => w.addCosigner(Zpub1, fp1cobo)); // duplicates are not allowed
assert.throws(() => w.addCosigner(Zpub2, fp2coldcard)); // duplicates are not allowed
assert.throws(() => w.addCosigner(mnemonicsCobo)); // duplicates are not allowed
assert.throws(() => w.addCosigner(mnemonicsColdcard)); // duplicates are not allowed
assert.throws(() => w.addCosigner(process.env.MNEMONICS_COBO)); // duplicates are not allowed
assert.throws(() => w.addCosigner(process.env.MNEMONICS_COLDCARD)); // duplicates are not allowed
assert.strictEqual(w.getM(), 2);
assert.strictEqual(w.getN(), 2);
@ -674,7 +695,7 @@ describe('multisig-wallet (native segwit)', () => {
w = new MultisigHDWallet();
w.addCosigner(Zpub1, fp1cobo);
w.addCosigner(mnemonicsColdcard);
w.addCosigner(process.env.MNEMONICS_COLDCARD);
w.setDerivationPath(path);
w.setM(2);
assert.strictEqual(w._getExternalAddressByIndex(0), 'bc1qxzrzh4caw7e3genwtldtxntzj0ktfl7mhf2lh4fj8h7hnkvtvc4salvp85');
@ -686,9 +707,9 @@ describe('multisig-wallet (native segwit)', () => {
assert.strictEqual(w.getN(), 2);
assert.strictEqual(w.getDerivationPath(), path);
assert.strictEqual(w.getCosigner(1), Zpub1);
assert.strictEqual(w.getCosigner(2), mnemonicsColdcard);
assert.strictEqual(w.getCosigner(2), process.env.MNEMONICS_COLDCARD);
assert.strictEqual(w.getCosignerForFingerprint(fp1cobo), Zpub1);
assert.strictEqual(w.getCosignerForFingerprint(fp2coldcard), mnemonicsColdcard);
assert.strictEqual(w.getCosignerForFingerprint(fp2coldcard), process.env.MNEMONICS_COLDCARD);
assert.strictEqual(w.howManySignaturesCanWeMake(), 1);
});
@ -841,8 +862,8 @@ describe('multisig-wallet (native segwit)', () => {
const path = "m/48'/0'/0'/2'";
const w = new MultisigHDWallet();
w.addCosigner(mnemonicsCobo, false, path);
w.addCosigner(mnemonicsColdcard, false, path);
w.addCosigner(process.env.MNEMONICS_COBO, false, path);
w.addCosigner(process.env.MNEMONICS_COLDCARD, false, path);
w.setDerivationPath(path);
w.setM(2);
@ -899,7 +920,7 @@ describe('multisig-wallet (native segwit)', () => {
const w = new MultisigHDWallet();
w.addCosigner(Zpub1, fp1cobo);
w.addCosigner(mnemonicsColdcard, false, path);
w.addCosigner(process.env.MNEMONICS_COLDCARD, false, path);
w.setDerivationPath(path);
w.setM(2);
@ -987,7 +1008,7 @@ describe('multisig-wallet (native segwit)', () => {
const walletWithFirstKey = new MultisigHDWallet();
walletWithFirstKey.addCosigner(Zpub1, fp1cobo);
walletWithFirstKey.addCosigner(mnemonicsColdcard, false, path);
walletWithFirstKey.addCosigner(process.env.MNEMONICS_COLDCARD, false, path);
walletWithFirstKey.setDerivationPath(path);
walletWithFirstKey.setM(2);
@ -1000,7 +1021,7 @@ describe('multisig-wallet (native segwit)', () => {
assert.strictEqual(walletWithFirstKey.calculateHowManySignaturesWeHaveFromPsbt(psbt), 1); // didnt change
const walletWithSecondKey = new MultisigHDWallet();
walletWithSecondKey.addCosigner(mnemonicsCobo);
walletWithSecondKey.addCosigner(process.env.MNEMONICS_COBO);
walletWithSecondKey.addCosigner(Zpub2, fp2coldcard);
walletWithSecondKey.setDerivationPath(path);
walletWithSecondKey.setM(2);
@ -1018,7 +1039,7 @@ describe('multisig-wallet (native segwit)', () => {
const w = new MultisigHDWallet();
w.addCosigner(Zpub1, fp1cobo);
w.addCosigner(mnemonicsColdcard, false, path);
w.addCosigner(process.env.MNEMONICS_COLDCARD, false, path);
w.setDerivationPath(path);
w.setM(2);
@ -1310,11 +1331,11 @@ describe('multisig-wallet (native segwit)', () => {
assert.strictEqual(w.getM(), 0);
assert.strictEqual(w.getN(), 0);
w.setSecret(mnemonicsCobo);
w.setSecret(process.env.MNEMONICS_COBO);
assert.strictEqual(w.getM(), 0);
assert.strictEqual(w.getN(), 0);
w.setSecret(MultisigHDWallet.seedToXpub(mnemonicsColdcard, "m/48'/0'/0'/1'"));
w.setSecret(MultisigHDWallet.seedToXpub(process.env.MNEMONICS_COLDCARD, "m/48'/0'/0'/1'"));
assert.strictEqual(w.getM(), 0);
assert.strictEqual(w.getN(), 0);
});
@ -1476,20 +1497,20 @@ describe('multisig-wallet (native segwit)', () => {
const w = new MultisigHDWallet();
w.addCosigner(Zpub1, fp1cobo);
w.addCosigner(mnemonicsColdcard);
w.addCosigner(process.env.MNEMONICS_COLDCARD);
w.setDerivationPath(path);
w.setM(2);
assert.strictEqual(w._getExternalAddressByIndex(0), 'bc1qxzrzh4caw7e3genwtldtxntzj0ktfl7mhf2lh4fj8h7hnkvtvc4salvp85');
assert.strictEqual(w.getCosigner(1), Zpub1);
assert.strictEqual(w.getCosigner(2), mnemonicsColdcard);
assert.strictEqual(w.getCosigner(2), process.env.MNEMONICS_COLDCARD);
assert.strictEqual(w.getFingerprint(1), fp1cobo);
assert.strictEqual(w.getFingerprint(2), fp2coldcard);
assert.strictEqual(w.getCustomDerivationPathForCosigner(1), path);
assert.strictEqual(w.getCustomDerivationPathForCosigner(2), path);
assert.strictEqual(w.getCosignerForFingerprint(fp1cobo), Zpub1);
assert.strictEqual(w.getCosignerForFingerprint(fp2coldcard), mnemonicsColdcard);
assert.strictEqual(w.getCosignerForFingerprint(fp2coldcard), process.env.MNEMONICS_COLDCARD);
assert.strictEqual(w.howManySignaturesCanWeMake(), 1);
w.replaceCosigner(fp2coldcard, Zpub2, fp2coldcard, path); // <-------------------
@ -1498,9 +1519,9 @@ describe('multisig-wallet (native segwit)', () => {
assert.strictEqual(w.getFingerprint(2), fp2coldcard);
assert.strictEqual(w.getCustomDerivationPathForCosigner(2), path);
w.replaceCosigner(fp2coldcard, mnemonicsColdcard); // <---------------------------
w.replaceCosigner(fp2coldcard, process.env.MNEMONICS_COLDCARD); // <---------------------------
assert.strictEqual(w.getCosigner(2), mnemonicsColdcard);
assert.strictEqual(w.getCosigner(2), process.env.MNEMONICS_COLDCARD);
assert.strictEqual(w.getFingerprint(2), fp2coldcard);
assert.strictEqual(w.getCustomDerivationPathForCosigner(2), path);
@ -1511,7 +1532,7 @@ describe('multisig-wallet (native segwit)', () => {
assert.strictEqual(w.getN(), 1);
assert.strictEqual(w.getM(), 2);
w.addCosigner(mnemonicsColdcard);
w.addCosigner(process.env.MNEMONICS_COLDCARD);
assert.strictEqual(w.getN(), 2);
w.deleteCosigner(fp2coldcard);
assert.ok(!w.getCosigner(2));

View File

@ -3,13 +3,9 @@ import { HDSegwitBech32Wallet } from '../../class';
import PayjoinTransaction from '../../class/payjoin-transaction';
import { PayjoinClient } from 'payjoin-client';
const bitcoin = require('bitcoinjs-lib');
const assert = require('assert');
jest.useFakeTimers();
const w = new HDSegwitBech32Wallet();
w.setSecret(
'inhale flip hundred clock onion wool upgrade unable cigar cricket move federal drum firm excuse adapt parade flag rice assume acid inch park cool',
);
const utxos = [
{
height: 666,
@ -24,10 +20,14 @@ const utxos = [
},
];
const assert = require('assert');
describe('PayjoinTransaction', () => {
it('throws if smth is wrong with pj transaction', async () => {
if (!process.env.MNEMONICS_COLDCARD) {
console.error('process.env.MNEMONICS_COLDCARD not set, skipped');
return;
}
const w = new HDSegwitBech32Wallet();
w.setSecret(process.env.MNEMONICS_COLDCARD);
const { tx: txOrig, psbt: psbtOrig } = w.createTransaction(
utxos,
[{ address: 'bc1qyvdzueznsh0rsyfqzdtj9ce7nlx4rlg2v93lcl', value: 10000 }],
@ -69,6 +69,12 @@ describe('PayjoinTransaction', () => {
});
it('works', async () => {
if (!process.env.MNEMONICS_COLDCARD) {
console.error('process.env.MNEMONICS_COLDCARD not set, skipped');
return;
}
const w = new HDSegwitBech32Wallet();
w.setSecret(process.env.MNEMONICS_COLDCARD);
// bitcoin:bc1qy0ydthpa35m37pvwl5tu76j0srcmcwtmaur3aw?amount=0.0001&pj=https://btc.donate.kukks.org/BTC/pj
const { tx: txOrigin, psbt: psbtOrigin } = w.createTransaction(
utxos,