Marcos Rodriguez
5 years ago
137 changed files with 8712 additions and 3492 deletions
@ -0,0 +1,97 @@ |
|||
import React, { Component } from 'react'; |
|||
import { View, Image, TouchableOpacity } from 'react-native'; |
|||
import { Icon } from 'react-native-elements'; |
|||
import Biometric from './class/biometrics'; |
|||
import PropTypes from 'prop-types'; |
|||
import { SafeAreaView } from 'react-navigation'; |
|||
/** @type {AppStorage} */ |
|||
|
|||
const BlueApp = require('./BlueApp'); |
|||
|
|||
export default class UnlockWith extends Component { |
|||
state = { biometricType: false, isStorageEncrypted: false, isAuthenticating: false }; |
|||
|
|||
async componentDidMount() { |
|||
let biometricType = false; |
|||
if (await Biometric.isBiometricUseCapableAndEnabled()) { |
|||
biometricType = await Biometric.biometricType(); |
|||
} |
|||
const isStorageEncrypted = await BlueApp.storageIsEncrypted(); |
|||
this.setState({ biometricType, isStorageEncrypted }, async () => { |
|||
if (!biometricType || isStorageEncrypted) { |
|||
this.unlockWithKey(); |
|||
} else if (typeof biometricType === 'string') this.unlockWithBiometrics(); |
|||
}); |
|||
} |
|||
|
|||
successfullyAuthenticated = () => { |
|||
this.props.onSuccessfullyAuthenticated(); |
|||
}; |
|||
|
|||
unlockWithBiometrics = async () => { |
|||
if (await BlueApp.storageIsEncrypted()) { |
|||
this.unlockWithKey(); |
|||
} |
|||
this.setState({ isAuthenticating: true }, async () => { |
|||
if (await Biometric.unlockWithBiometrics()) { |
|||
await BlueApp.startAndDecrypt(); |
|||
return this.props.onSuccessfullyAuthenticated(); |
|||
} |
|||
this.setState({ isAuthenticating: false }); |
|||
}); |
|||
}; |
|||
|
|||
unlockWithKey = () => { |
|||
this.setState({ isAuthenticating: true }, async () => { |
|||
await BlueApp.startAndDecrypt(); |
|||
this.props.onSuccessfullyAuthenticated(); |
|||
}); |
|||
}; |
|||
|
|||
render() { |
|||
if (!this.state.biometricType && !this.state.isStorageEncrypted) { |
|||
return <View />; |
|||
} |
|||
return ( |
|||
<SafeAreaView style={{ flex: 1 }}> |
|||
<View style={{ flex: 2, justifyContent: 'space-between', alignItems: 'center' }}> |
|||
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> |
|||
<Image source={require('./img/qr-code.png')} style={{ width: 120, height: 120 }} /> |
|||
</View> |
|||
<View style={{ flex: 0.2, justifyContent: 'flex-end', marginBottom: 58 }}> |
|||
<View style={{ justifyContent: 'center', flexDirection: 'row' }}> |
|||
{this.state.biometricType === Biometric.TouchID && !this.state.isStorageEncrypted && ( |
|||
<> |
|||
<TouchableOpacity disabled={this.state.isAuthenticating} onPress={this.unlockWithBiometrics}> |
|||
<Image source={require('./img/fingerprint.png')} style={{ width: 64, height: 64 }} /> |
|||
</TouchableOpacity> |
|||
</> |
|||
)} |
|||
{this.state.biometricType === Biometric.FaceID && !this.state.isStorageEncrypted && ( |
|||
<> |
|||
<TouchableOpacity disabled={this.state.isAuthenticating} onPress={this.unlockWithBiometrics}> |
|||
<Image source={require('./img/faceid.png')} style={{ width: 64, height: 64 }} /> |
|||
</TouchableOpacity> |
|||
</> |
|||
)} |
|||
{this.state.biometricType !== false && this.state.isStorageEncrypted && ( |
|||
<View style={{ backgroundColor: 'gray', width: 0.5, height: 20, marginHorizontal: 16 }} /> |
|||
)} |
|||
{this.state.isStorageEncrypted && ( |
|||
<> |
|||
<TouchableOpacity disabled={this.state.isAuthenticating} onPress={this.unlockWithKey}> |
|||
<Icon name="key" size={64} type="font-awesome" /> |
|||
</TouchableOpacity> |
|||
</> |
|||
)} |
|||
</View> |
|||
</View> |
|||
</View> |
|||
</SafeAreaView> |
|||
); |
|||
} |
|||
} |
|||
|
|||
UnlockWith.propTypes = { |
|||
onSuccessfullyAuthenticated: PropTypes.func, |
|||
}; |
@ -0,0 +1,12 @@ |
|||
export default class WatchConnectivity { |
|||
isAppInstalled = false; |
|||
static shared = new WatchConnectivity(); |
|||
wallets; |
|||
fetchTransactionsFunction = () => {}; |
|||
|
|||
getIsWatchAppInstalled() {} |
|||
|
|||
async handleLightningInvoiceCreateRequest(_walletIndex, _amount, _description) {} |
|||
|
|||
async sendWalletsToWatch() {} |
|||
} |
@ -0,0 +1,17 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<projectDescription> |
|||
<name>BlueWallet</name> |
|||
<comment>Project android created by Buildship.</comment> |
|||
<projects> |
|||
</projects> |
|||
<buildSpec> |
|||
<buildCommand> |
|||
<name>org.eclipse.buildship.core.gradleprojectbuilder</name> |
|||
<arguments> |
|||
</arguments> |
|||
</buildCommand> |
|||
</buildSpec> |
|||
<natures> |
|||
<nature>org.eclipse.buildship.core.gradleprojectnature</nature> |
|||
</natures> |
|||
</projectDescription> |
@ -0,0 +1,6 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<classpath> |
|||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8/"/> |
|||
<classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer"/> |
|||
<classpathentry kind="output" path="bin/default"/> |
|||
</classpath> |
@ -0,0 +1,23 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<projectDescription> |
|||
<name>app</name> |
|||
<comment>Project app created by Buildship.</comment> |
|||
<projects> |
|||
</projects> |
|||
<buildSpec> |
|||
<buildCommand> |
|||
<name>org.eclipse.jdt.core.javabuilder</name> |
|||
<arguments> |
|||
</arguments> |
|||
</buildCommand> |
|||
<buildCommand> |
|||
<name>org.eclipse.buildship.core.gradleprojectbuilder</name> |
|||
<arguments> |
|||
</arguments> |
|||
</buildCommand> |
|||
</buildSpec> |
|||
<natures> |
|||
<nature>org.eclipse.jdt.core.javanature</nature> |
|||
<nature>org.eclipse.buildship.core.gradleprojectnature</nature> |
|||
</natures> |
|||
</projectDescription> |
@ -0,0 +1,2 @@ |
|||
connection.project.dir=.. |
|||
eclipse.preferences.version=1 |
After Width: | Height: | Size: 514 B |
@ -0,0 +1,5 @@ |
|||
defaults.url=https://sentry.io/ |
|||
defaults.org=bluewallet |
|||
defaults.project=bluewallet |
|||
auth.token=8020b31b54e94e7b86b4a69f60869f3d5a1320f44efe4f22bb9fa27e0b371448 |
|||
cli.executable=node_modules/@sentry/cli/bin/sentry-cli |
@ -0,0 +1,45 @@ |
|||
const https = require('https'); |
|||
|
|||
const auth = 'Basic ' + Buffer.from(process.env.GITHUB).toString('base64'); |
|||
|
|||
const branch = require('child_process') |
|||
.execSync('git ls-remote --heads origin | grep $(git rev-parse HEAD) | cut -d / -f 3') |
|||
.toString() |
|||
.trim(); |
|||
|
|||
const req = https.request( |
|||
{ |
|||
hostname: 'api.github.com', |
|||
port: 443, |
|||
path: '/repos/BlueWallet/BlueWallet/pulls', |
|||
method: 'GET', |
|||
headers: { 'User-Agent': 'BlueWallet bot', Authorization: auth }, |
|||
}, |
|||
resp => { |
|||
let data = ''; |
|||
|
|||
resp.on('data', chunk => { |
|||
data += chunk; |
|||
}); |
|||
|
|||
resp.on('end', () => { |
|||
try { |
|||
const prs = JSON.parse(data); |
|||
for (let pr of prs) { |
|||
if (branch === pr.head.ref) { |
|||
console.log(pr.number); |
|||
} |
|||
} |
|||
} catch (err) { |
|||
console.log(err); |
|||
console.log('got json: ', data); |
|||
} |
|||
}); |
|||
}, |
|||
); |
|||
|
|||
req.on('error', e => { |
|||
console.error(e); |
|||
}); |
|||
|
|||
req.end(); |
@ -0,0 +1,20 @@ |
|||
#!/usr/bin/env bash |
|||
|
|||
echo Uploading to Appetize and publishing link to Github... |
|||
echo -n "Branch " |
|||
git ls-remote --heads origin | grep $(git rev-parse HEAD) | cut -d / -f 3 |
|||
echo -n "Branch 2 " |
|||
git log -n 1 --pretty=%d HEAD | awk '{print $2}' | sed 's/origin\///' | sed 's/)//' |
|||
|
|||
FILENAME="$APPCENTER_OUTPUT_DIRECTORY/app-release.apk" |
|||
|
|||
if [ -f $FILENAME ]; then |
|||
APTZ=`curl "https://$APPETIZE@api.appetize.io/v1/apps" -F "file=@$FILENAME" -F "platform=android"` |
|||
echo Apptezize response: |
|||
echo $APTZ |
|||
APPURL=`node -e "let e = JSON.parse('$APTZ'); console.log(e.publicURL);"` |
|||
echo App url: $APPURL |
|||
PR=`node appcenter-post-build-get-pr-number.js` |
|||
echo PR: $PR |
|||
curl -X POST --data "{\"body\":\"This was a triumph. I'm making a note here: HUGE SUCCESS.\n\n [android] $APPURL\"}" -u "$GITHUB" "https://api.github.com/repos/BlueWallet/BlueWallet/issues/$PR/comments" |
|||
fi |
@ -0,0 +1,60 @@ |
|||
import Biometrics from 'react-native-biometrics'; |
|||
const BlueApp = require('../BlueApp'); |
|||
|
|||
export default class Biometric { |
|||
static STORAGEKEY = 'Biometrics'; |
|||
static FaceID = Biometrics.FaceID; |
|||
static TouchID = Biometrics.TouchID; |
|||
|
|||
static async isDeviceBiometricCapable() { |
|||
const isDeviceBiometricCapable = await Biometric.biometricType(); |
|||
if (typeof isDeviceBiometricCapable === 'string') { |
|||
return isDeviceBiometricCapable; |
|||
} |
|||
Biometric.setBiometricUseEnabled(false); |
|||
return false; |
|||
} |
|||
|
|||
static async biometricType() { |
|||
try { |
|||
const isSensorAvailable = await Biometrics.isSensorAvailable(); |
|||
return isSensorAvailable; |
|||
} catch (e) { |
|||
console.log(e); |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
static async isBiometricUseEnabled() { |
|||
try { |
|||
const enabledBiometrics = await BlueApp.getItem(Biometric.STORAGEKEY); |
|||
return !!enabledBiometrics; |
|||
} catch (_e) { |
|||
await BlueApp.setItem(Biometric.STORAGEKEY, ''); |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
static async isBiometricUseCapableAndEnabled() { |
|||
const isBiometricUseEnabled = await Biometric.isBiometricUseEnabled(); |
|||
const isDeviceBiometricCapable = await Biometric.isDeviceBiometricCapable(); |
|||
return isBiometricUseEnabled && isDeviceBiometricCapable; |
|||
} |
|||
|
|||
static async setBiometricUseEnabled(value) { |
|||
await BlueApp.setItem(Biometric.STORAGEKEY, value === true ? '1' : ''); |
|||
} |
|||
|
|||
static async unlockWithBiometrics() { |
|||
const isDeviceBiometricCapable = await Biometric.isDeviceBiometricCapable(); |
|||
if (isDeviceBiometricCapable) { |
|||
try { |
|||
await Biometrics.simplePrompt('Please confirm your identity.'); |
|||
return true; |
|||
} catch (_e) { |
|||
return false; |
|||
} |
|||
} |
|||
return false; |
|||
} |
|||
} |
@ -0,0 +1,45 @@ |
|||
import AsyncStorage from '@react-native-community/async-storage'; |
|||
const BlueApp = require('../BlueApp'); |
|||
|
|||
export default class OnAppLaunch { |
|||
static STORAGE_KEY = 'ONAPP_LAUNCH_SELECTED_DEFAULT_WALLET_KEY'; |
|||
|
|||
static async isViewAllWalletsEnabled() { |
|||
try { |
|||
const selectedDefaultWallet = await AsyncStorage.getItem(OnAppLaunch.STORAGE_KEY); |
|||
return selectedDefaultWallet === '' || selectedDefaultWallet === null; |
|||
} catch (_e) { |
|||
return true; |
|||
} |
|||
} |
|||
|
|||
static async setViewAllWalletsEnabled(value) { |
|||
if (!value) { |
|||
const selectedDefaultWallet = await OnAppLaunch.getSelectedDefaultWallet(); |
|||
if (!selectedDefaultWallet) { |
|||
const firstWallet = BlueApp.getWallets()[0]; |
|||
await OnAppLaunch.setSelectedDefaultWallet(firstWallet.getID()); |
|||
} |
|||
} else { |
|||
await AsyncStorage.setItem(OnAppLaunch.STORAGE_KEY, ''); |
|||
} |
|||
} |
|||
|
|||
static async getSelectedDefaultWallet() { |
|||
let selectedWallet = false; |
|||
try { |
|||
const selectedWalletID = JSON.parse(await AsyncStorage.getItem(OnAppLaunch.STORAGE_KEY)); |
|||
selectedWallet = BlueApp.getWallets().find(wallet => wallet.getID() === selectedWalletID); |
|||
if (!selectedWallet) { |
|||
await AsyncStorage.setItem(OnAppLaunch.STORAGE_KEY, ''); |
|||
} |
|||
} catch (_e) { |
|||
return false; |
|||
} |
|||
return selectedWallet; |
|||
} |
|||
|
|||
static async setSelectedDefaultWallet(value) { |
|||
await AsyncStorage.setItem(OnAppLaunch.STORAGE_KEY, JSON.stringify(value)); |
|||
} |
|||
} |
@ -0,0 +1,46 @@ |
|||
import QuickActions from 'react-native-quick-actions'; |
|||
import { Platform } from 'react-native'; |
|||
|
|||
export default class DeviceQuickActions { |
|||
static shared = new DeviceQuickActions(); |
|||
wallets; |
|||
|
|||
static setWallets(wallets) { |
|||
DeviceQuickActions.shared.wallets = wallets; |
|||
} |
|||
|
|||
static removeAllWallets() { |
|||
DeviceQuickActions.shared.wallets = undefined; |
|||
} |
|||
|
|||
static setQuickActions() { |
|||
if (DeviceQuickActions.shared.wallets === undefined) { |
|||
return; |
|||
} |
|||
QuickActions.isSupported((error, supported) => { |
|||
if (supported && error === null) { |
|||
let shortcutItems = []; |
|||
const loc = require('../loc/'); |
|||
for (const wallet of DeviceQuickActions.shared.wallets) { |
|||
shortcutItems.push({ |
|||
type: 'Wallets', // Required
|
|||
title: wallet.getLabel(), // Optional, if empty, `type` will be used instead
|
|||
subtitle: |
|||
wallet.hideBalance || wallet.getBalance() <= 0 |
|||
? '' |
|||
: loc.formatBalance(Number(wallet.getBalance()), wallet.getPreferredBalanceUnit(), true), |
|||
userInfo: { |
|||
url: `bluewallet://wallet/${wallet.getID()}`, // Provide any custom data like deep linking URL
|
|||
}, |
|||
icon: Platform.select({ android: 'quickactions', ios: 'bookmark' }), |
|||
}); |
|||
} |
|||
QuickActions.setShortcutItems(shortcutItems); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
static clearShortcutItems() { |
|||
QuickActions.clearShortcutItems(); |
|||
} |
|||
} |
@ -1,6 +1,7 @@ |
|||
vim ios/BlueWallet/Info.plist |
|||
vim ios/BlueWalletWatch/Info.plist |
|||
vim "ios/BlueWalletWatch Extension/Info.plist" |
|||
vim "ios/TodayExtension/Info.plist" |
|||
vim android/app/build.gradle |
|||
vim package.json |
|||
vim package-lock.json |
|||
|
After Width: | Height: | Size: 8.6 KiB |
After Width: | Height: | Size: 34 KiB |
@ -0,0 +1,8 @@ |
|||
<?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>PreviewsEnabled</key> |
|||
<false/> |
|||
</dict> |
|||
</plist> |
@ -1,5 +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/> |
|||
<dict> |
|||
<key>com.apple.security.application-groups</key> |
|||
<array> |
|||
<string>group.io.bluewallet.bluewallet</string> |
|||
</array> |
|||
</dict> |
|||
</plist> |
|||
|
@ -0,0 +1,125 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="15505" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="M4Y-Lb-cyx"> |
|||
<device id="retina6_1" orientation="portrait" appearance="light"/> |
|||
<dependencies> |
|||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15509"/> |
|||
<capability name="Safe area layout guides" minToolsVersion="9.0"/> |
|||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> |
|||
</dependencies> |
|||
<scenes> |
|||
<!--Today View Controller--> |
|||
<scene sceneID="cwh-vc-ff4"> |
|||
<objects> |
|||
<viewController id="M4Y-Lb-cyx" customClass="TodayViewController" customModule="BlueWallet___Bitcoin_Price" customModuleProvider="target" sceneMemberID="viewController"> |
|||
<view key="view" contentMode="scaleToFill" simulatedAppContext="notificationCenter" id="S3S-Oj-5AN"> |
|||
<rect key="frame" x="0.0" y="0.0" width="320" height="100"/> |
|||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> |
|||
<subviews> |
|||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Bitcoin Price" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="aaf-Pc-Y9i"> |
|||
<rect key="frame" x="16" y="8" width="288" height="21"/> |
|||
<constraints> |
|||
<constraint firstAttribute="height" constant="21" id="fON-Nf-oBQ"/> |
|||
</constraints> |
|||
<fontDescription key="fontDescription" style="UICTFontTextStyleHeadline"/> |
|||
<nil key="textColor"/> |
|||
<nil key="highlightedColor"/> |
|||
</label> |
|||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" verticalHuggingPriority="251" text="..." textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="bcB-MD-aJf"> |
|||
<rect key="frame" x="104" y="73" width="200" height="15"/> |
|||
<fontDescription key="fontDescription" style="UICTFontTextStyleCaption1"/> |
|||
<nil key="textColor"/> |
|||
<nil key="highlightedColor"/> |
|||
</label> |
|||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Last Updated:" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="vU4-uK-6ow"> |
|||
<rect key="frame" x="16" y="73" width="80" height="15"/> |
|||
<fontDescription key="fontDescription" style="UICTFontTextStyleCaption1"/> |
|||
<nil key="textColor"/> |
|||
<nil key="highlightedColor"/> |
|||
</label> |
|||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="USD" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="lkL-gv-1a1"> |
|||
<rect key="frame" x="16" y="40" width="35" height="33"/> |
|||
<constraints> |
|||
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="35" id="4Nq-zK-gi3"/> |
|||
</constraints> |
|||
<fontDescription key="fontDescription" type="system" pointSize="17"/> |
|||
<nil key="textColor"/> |
|||
<nil key="highlightedColor"/> |
|||
</label> |
|||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" verticalHuggingPriority="251" text="..." textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="bEQ-e6-Puo"> |
|||
<rect key="frame" x="59" y="46.5" width="14" height="20.5"/> |
|||
<fontDescription key="fontDescription" type="system" pointSize="17"/> |
|||
<nil key="textColor"/> |
|||
<nil key="highlightedColor"/> |
|||
</label> |
|||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="arrow.up" catalog="system" translatesAutoresizingMaskIntoConstraints="NO" id="eST-DU-WIK"> |
|||
<rect key="frame" x="221" y="47.5" width="17" height="18"/> |
|||
<constraints> |
|||
<constraint firstAttribute="width" constant="17" id="gkK-pz-TDJ"/> |
|||
</constraints> |
|||
</imageView> |
|||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="..." textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="gm7-vT-KrH" userLabel="..."> |
|||
<rect key="frame" x="290" y="40" width="14" height="33"/> |
|||
<constraints> |
|||
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="14" id="KoT-51-551"/> |
|||
</constraints> |
|||
<fontDescription key="fontDescription" type="system" pointSize="17"/> |
|||
<nil key="textColor"/> |
|||
<nil key="highlightedColor"/> |
|||
</label> |
|||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="from" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="aqr-Mt-cor"> |
|||
<rect key="frame" x="246" y="40" width="36" height="33"/> |
|||
<constraints> |
|||
<constraint firstAttribute="height" constant="33" id="u9N-WC-Os2"/> |
|||
</constraints> |
|||
<fontDescription key="fontDescription" type="system" pointSize="17"/> |
|||
<nil key="textColor"/> |
|||
<nil key="highlightedColor"/> |
|||
</label> |
|||
</subviews> |
|||
<constraints> |
|||
<constraint firstItem="aqr-Mt-cor" firstAttribute="top" secondItem="aaf-Pc-Y9i" secondAttribute="bottom" constant="11" id="0ca-1C-JqG"/> |
|||
<constraint firstItem="ssy-KU-ocm" firstAttribute="trailing" secondItem="aaf-Pc-Y9i" secondAttribute="trailing" constant="16" id="197-jr-Kn5"/> |
|||
<constraint firstItem="eST-DU-WIK" firstAttribute="centerY" secondItem="aqr-Mt-cor" secondAttribute="centerY" id="2yd-pY-y1Y"/> |
|||
<constraint firstItem="bcB-MD-aJf" firstAttribute="leading" secondItem="vU4-uK-6ow" secondAttribute="trailing" constant="8" id="5bB-Zv-Yeq"/> |
|||
<constraint firstItem="lkL-gv-1a1" firstAttribute="leading" secondItem="ssy-KU-ocm" secondAttribute="leading" constant="16" id="Bgx-xM-CSS"/> |
|||
<constraint firstItem="ssy-KU-ocm" firstAttribute="bottom" secondItem="bcB-MD-aJf" secondAttribute="bottom" constant="12" id="EPP-OS-3b6"/> |
|||
<constraint firstItem="vU4-uK-6ow" firstAttribute="leading" secondItem="ssy-KU-ocm" secondAttribute="leading" constant="16" id="EkD-jp-arv"/> |
|||
<constraint firstItem="gm7-vT-KrH" firstAttribute="centerY" secondItem="aqr-Mt-cor" secondAttribute="centerY" id="Eo2-n1-zbi"/> |
|||
<constraint firstItem="ssy-KU-ocm" firstAttribute="bottom" secondItem="vU4-uK-6ow" secondAttribute="bottom" constant="12" id="JSh-ZE-k1H"/> |
|||
<constraint firstItem="bcB-MD-aJf" firstAttribute="centerY" secondItem="vU4-uK-6ow" secondAttribute="centerY" id="MUL-tE-LmX"/> |
|||
<constraint firstItem="bEQ-e6-Puo" firstAttribute="leading" secondItem="lkL-gv-1a1" secondAttribute="trailing" constant="8" id="Ml2-4o-Yqk"/> |
|||
<constraint firstItem="ssy-KU-ocm" firstAttribute="trailing" secondItem="gm7-vT-KrH" secondAttribute="trailing" constant="16" id="OLV-lQ-T8a"/> |
|||
<constraint firstItem="gm7-vT-KrH" firstAttribute="centerY" secondItem="bEQ-e6-Puo" secondAttribute="centerY" id="Rle-PT-j9m"/> |
|||
<constraint firstItem="gm7-vT-KrH" firstAttribute="leading" secondItem="aqr-Mt-cor" secondAttribute="trailing" constant="8" id="Rtu-ah-AvP"/> |
|||
<constraint firstItem="gm7-vT-KrH" firstAttribute="firstBaseline" secondItem="aqr-Mt-cor" secondAttribute="firstBaseline" id="YIV-xq-qlw"/> |
|||
<constraint firstItem="bEQ-e6-Puo" firstAttribute="centerY" secondItem="lkL-gv-1a1" secondAttribute="centerY" id="Ys3-7f-RIc"/> |
|||
<constraint firstItem="aaf-Pc-Y9i" firstAttribute="leading" secondItem="S3S-Oj-5AN" secondAttribute="leading" constant="16" id="a1b-Yq-aZb"/> |
|||
<constraint firstItem="aaf-Pc-Y9i" firstAttribute="top" secondItem="S3S-Oj-5AN" secondAttribute="top" constant="8" id="aIo-h1-w4F"/> |
|||
<constraint firstItem="lkL-gv-1a1" firstAttribute="top" secondItem="aaf-Pc-Y9i" secondAttribute="bottom" constant="11" id="dET-8J-W4K"/> |
|||
<constraint firstItem="ssy-KU-ocm" firstAttribute="trailing" secondItem="bcB-MD-aJf" secondAttribute="trailing" constant="16" id="kkD-VZ-BAt"/> |
|||
<constraint firstItem="vU4-uK-6ow" firstAttribute="firstBaseline" secondItem="lkL-gv-1a1" secondAttribute="baseline" constant="16" symbolType="layoutAnchor" id="lml-Hc-8Sv"/> |
|||
<constraint firstItem="aqr-Mt-cor" firstAttribute="leading" secondItem="eST-DU-WIK" secondAttribute="trailing" constant="8" id="t4j-U9-sOm"/> |
|||
</constraints> |
|||
<viewLayoutGuide key="safeArea" id="ssy-KU-ocm"/> |
|||
</view> |
|||
<extendedEdge key="edgesForExtendedLayout"/> |
|||
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/> |
|||
<size key="freeformSize" width="320" height="100"/> |
|||
<connections> |
|||
<outlet property="currencyLabel" destination="lkL-gv-1a1" id="Gzb-TF-E6W"/> |
|||
<outlet property="lastPrice" destination="gm7-vT-KrH" id="YIE-KJ-0qW"/> |
|||
<outlet property="lastPriceArrowImage" destination="eST-DU-WIK" id="VWH-ED-VL1"/> |
|||
<outlet property="lastPriceFromLabel" destination="aqr-Mt-cor" id="p17-Aq-ufa"/> |
|||
<outlet property="lastUpdatedDate" destination="bcB-MD-aJf" id="A9U-MB-qJq"/> |
|||
<outlet property="priceLabel" destination="bEQ-e6-Puo" id="0IP-Yg-dWr"/> |
|||
</connections> |
|||
</viewController> |
|||
<placeholder placeholderIdentifier="IBFirstResponder" id="vXp-U4-Rya" userLabel="First Responder" sceneMemberID="firstResponder"/> |
|||
</objects> |
|||
<point key="canvasLocation" x="137.68115942028987" y="96.428571428571431"/> |
|||
</scene> |
|||
</scenes> |
|||
<resources> |
|||
<image name="arrow.up" catalog="system" width="60" height="64"/> |
|||
</resources> |
|||
</document> |
@ -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> |
@ -0,0 +1,31 @@ |
|||
<?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>$(PRODUCT_NAME)</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>4.8.0</string> |
|||
<key>CFBundleVersion</key> |
|||
<string>1</string> |
|||
<key>NSExtension</key> |
|||
<dict> |
|||
<key>NSExtensionMainStoryboard</key> |
|||
<string>MainInterface</string> |
|||
<key>NSExtensionPointIdentifier</key> |
|||
<string>com.apple.widget-extension</string> |
|||
</dict> |
|||
</dict> |
|||
</plist> |
@ -0,0 +1,65 @@ |
|||
// |
|||
// API.swift |
|||
// TodayExtension |
|||
// |
|||
// Created by Marcos Rodriguez on 11/2/19. |
|||
// Copyright © 2019 Facebook. All rights reserved. |
|||
// |
|||
|
|||
import Foundation |
|||
|
|||
class API { |
|||
|
|||
static func fetchPrice(currency: String, completion: @escaping ((Dictionary<String, Any>?, Error?) -> Void)) { |
|||
guard let url = URL(string: "https://api.coindesk.com/v1/bpi/currentPrice/\(currency).json") else {return} |
|||
|
|||
URLSession.shared.dataTask(with: url) { (data, response, error) in |
|||
guard let dataResponse = data, |
|||
let json = try? JSONSerialization.jsonObject(with: dataResponse, options: .mutableContainers) as? Dictionary<String, Any>, |
|||
error == nil else { |
|||
print(error?.localizedDescription ?? "Response Error") |
|||
completion(nil, error) |
|||
return } |
|||
|
|||
completion(json, nil) |
|||
}.resume() |
|||
} |
|||
|
|||
static func getUserPreferredCurrency() -> String { |
|||
guard let userDefaults = UserDefaults(suiteName: "group.io.bluewallet.bluewallet"), |
|||
let preferredCurrency = userDefaults.string(forKey: "preferredCurrency") |
|||
else { |
|||
return "USD" |
|||
} |
|||
|
|||
if preferredCurrency != API.getLastSelectedCurrency() { |
|||
UserDefaults.standard.removeObject(forKey: TodayData.TodayCachedDataStoreKey) |
|||
UserDefaults.standard.removeObject(forKey: TodayData.TodayDataStoreKey) |
|||
UserDefaults.standard.synchronize() |
|||
} |
|||
|
|||
return preferredCurrency |
|||
} |
|||
|
|||
static func getUserPreferredCurrencyLocale() -> String { |
|||
guard let userDefaults = UserDefaults(suiteName: "group.io.bluewallet.bluewallet"), |
|||
let preferredCurrency = userDefaults.string(forKey: "preferredCurrencyLocale") |
|||
else { |
|||
return "en_US" |
|||
} |
|||
return preferredCurrency |
|||
} |
|||
|
|||
static func getLastSelectedCurrency() -> String { |
|||
guard let dataStore = UserDefaults.standard.string(forKey: "currency") else { |
|||
return "USD" |
|||
} |
|||
|
|||
return dataStore |
|||
} |
|||
|
|||
static func saveNewSelectedCurrency() { |
|||
UserDefaults.standard.setValue(API.getUserPreferredCurrency(), forKey: "currency") |
|||
} |
|||
|
|||
} |
@ -0,0 +1,89 @@ |
|||
// |
|||
// TodayDataStore.swift |
|||
// TodayExtension |
|||
// |
|||
// Created by Marcos Rodriguez on 11/3/19. |
|||
// Copyright © 2019 Facebook. All rights reserved. |
|||
// |
|||
|
|||
import Foundation |
|||
|
|||
struct TodayDataStore { |
|||
let rate: String |
|||
let lastUpdate: String |
|||
|
|||
var formattedDate: String? { |
|||
let isoDateFormatter = ISO8601DateFormatter() |
|||
let dateFormatter = DateFormatter() |
|||
dateFormatter.timeStyle = .short |
|||
dateFormatter.dateStyle = .short |
|||
|
|||
if let date = isoDateFormatter.date(from: lastUpdate) { |
|||
return dateFormatter.string(from: date) |
|||
} |
|||
return nil |
|||
} |
|||
|
|||
var rateDoubleValue: Double? { |
|||
let rateDigits = rate.replacingOccurrences(of: ",", with: ""); |
|||
let numberFormatter = NumberFormatter() |
|||
numberFormatter.numberStyle = .decimal |
|||
numberFormatter.maximumFractionDigits = 2 |
|||
numberFormatter.minimumFractionDigits = 2 |
|||
|
|||
if let rateDoubleValue = numberFormatter.number(from: rateDigits) { |
|||
return rateDoubleValue.doubleValue |
|||
} |
|||
|
|||
return nil |
|||
} |
|||
|
|||
var formattedRate: String? { |
|||
let rateDigits = rate.replacingOccurrences(of: ",", with: ""); |
|||
let numberFormatter = NumberFormatter() |
|||
numberFormatter.numberStyle = .decimal |
|||
numberFormatter.maximumFractionDigits = 2 |
|||
numberFormatter.minimumFractionDigits = 2 |
|||
if let rateNumber = numberFormatter.number(from: rateDigits) { |
|||
numberFormatter.numberStyle = .currency |
|||
numberFormatter.locale = Locale(identifier: API.getUserPreferredCurrencyLocale()) |
|||
return numberFormatter.string(from: rateNumber); |
|||
} |
|||
return nil |
|||
} |
|||
} |
|||
|
|||
class TodayData { |
|||
|
|||
static let TodayDataStoreKey = "TodayDataStoreKey" |
|||
static let TodayCachedDataStoreKey = "TodayCachedDataStoreKey" |
|||
|
|||
static func savePriceRateAndLastUpdate(rate: String, lastUpdate: String) { |
|||
UserDefaults.standard.setValue(["rate": rate, "lastUpdate": lastUpdate], forKey: TodayDataStoreKey) |
|||
UserDefaults.standard.synchronize() |
|||
} |
|||
|
|||
static func getPriceRateAndLastUpdate() -> TodayDataStore? { |
|||
guard let dataStore = UserDefaults.standard.value(forKey: TodayDataStoreKey) as? [String: String], let rate = dataStore["rate"], let lastUpdate = dataStore["lastUpdate"] else { |
|||
return nil |
|||
} |
|||
return TodayDataStore(rate: rate, lastUpdate: lastUpdate) |
|||
} |
|||
|
|||
static func saveCachePriceRateAndLastUpdate(rate: String, lastUpdate: String) { |
|||
UserDefaults.standard.setValue(["rate": rate, "lastUpdate": lastUpdate], forKey: TodayCachedDataStoreKey) |
|||
UserDefaults.standard.synchronize() |
|||
} |
|||
|
|||
static func getCachedPriceRateAndLastUpdate() -> TodayDataStore? { |
|||
guard let dataStore = UserDefaults.standard.value(forKey: TodayCachedDataStoreKey) as? [String: String], var rate = dataStore["rate"], let lastUpdate = dataStore["lastUpdate"] else { |
|||
return nil |
|||
} |
|||
rate = rate.replacingOccurrences(of: ",", with: ""); |
|||
return TodayDataStore(rate: rate, lastUpdate: lastUpdate) |
|||
} |
|||
|
|||
|
|||
|
|||
|
|||
} |
@ -0,0 +1,130 @@ |
|||
// |
|||
// TodayViewController.swift |
|||
// TodayExtension |
|||
// |
|||
// Created by Marcos Rodriguez on 11/2/19. |
|||
// Copyright © 2019 Facebook. All rights reserved. |
|||
// |
|||
|
|||
import UIKit |
|||
import NotificationCenter |
|||
|
|||
class TodayViewController: UIViewController, NCWidgetProviding { |
|||
|
|||
|
|||
@IBOutlet weak var currencyLabel: UILabel! |
|||
@IBOutlet weak var lastUpdatedDate: UILabel! |
|||
@IBOutlet weak var priceLabel: UILabel! |
|||
|
|||
@IBOutlet weak var lastPriceArrowImage: UIImageView! |
|||
@IBOutlet weak var lastPrice: UILabel! |
|||
@IBOutlet weak var lastPriceFromLabel: UILabel! |
|||
private var lastPriceNumber: NSNumber? |
|||
|
|||
|
|||
override func viewDidLoad() { |
|||
super.viewDidLoad() |
|||
|
|||
setLastPriceOutletsHidden(isHidden: true) |
|||
if let lastStoredTodayStore = TodayData.getPriceRateAndLastUpdate() { |
|||
processRateAndLastUpdate(todayStore: lastStoredTodayStore) |
|||
} else { |
|||
setLastPriceOutletsHidden(isHidden: true) |
|||
} |
|||
} |
|||
|
|||
func setLastPriceOutletsHidden(isHidden: Bool) { |
|||
lastPrice.isHidden = isHidden |
|||
lastPriceFromLabel.isHidden = isHidden |
|||
lastPriceArrowImage.isHidden = isHidden |
|||
} |
|||
|
|||
func processRateAndLastUpdate(todayStore: TodayDataStore) { |
|||
guard let rateString = todayStore.formattedRate, let dateFormatted = todayStore.formattedDate else { return } |
|||
|
|||
priceLabel.text = rateString |
|||
lastUpdatedDate.text = dateFormatted |
|||
} |
|||
|
|||
func processStoredRateAndLastUpdate(todayStore: TodayDataStore) { |
|||
guard let lastPriceNumber = todayStore.formattedRate else { return } |
|||
|
|||
lastPrice.text = lastPriceNumber |
|||
} |
|||
|
|||
func processCachedStoredRateAndLastUpdate(new: TodayDataStore, cached: TodayDataStore) { |
|||
guard let newPriceDoubleValue = new.rateDoubleValue, let cachedPriceNumber = cached.formattedRate, let cachedPriceNumberDoubleValue = cached.rateDoubleValue else { return } |
|||
|
|||
lastPrice.text = cachedPriceNumber |
|||
|
|||
|
|||
if newPriceDoubleValue > cachedPriceNumberDoubleValue { |
|||
self.lastPriceArrowImage.image = UIImage(systemName: "arrow.up") |
|||
self.setLastPriceOutletsHidden(isHidden: false) |
|||
} else { |
|||
self.lastPriceArrowImage.image = UIImage(systemName: "arrow.down") |
|||
self.setLastPriceOutletsHidden(isHidden: false) |
|||
} |
|||
} |
|||
|
|||
func widgetPerformUpdate(completionHandler: (@escaping (NCUpdateResult) -> Void)) { |
|||
// Perform any setup necessary in order to update the view. |
|||
|
|||
// If an error is encountered, use NCUpdateResult.Failed |
|||
// If there's no update required, use NCUpdateResult.NoData |
|||
// If there's an update, use NCUpdateResult.NewData |
|||
let userPreferredCurrency = API.getUserPreferredCurrency(); |
|||
self.currencyLabel.text = userPreferredCurrency |
|||
API.fetchPrice(currency: userPreferredCurrency, completion: { (result, error) in |
|||
DispatchQueue.main.async { [unowned self] in |
|||
guard let result = result else { |
|||
completionHandler(.failed) |
|||
return |
|||
} |
|||
|
|||
guard let bpi = result["bpi"] as? Dictionary<String, Any>, let preferredCurrency = bpi[userPreferredCurrency] as? Dictionary<String, Any>, let rateString = preferredCurrency["rate"] as? String, |
|||
let time = result["time"] as? Dictionary<String, Any>, let lastUpdatedString = time["updatedISO"] as? String |
|||
else { |
|||
return |
|||
} |
|||
|
|||
let latestRateDataStore = TodayDataStore(rate: rateString, lastUpdate: lastUpdatedString) |
|||
|
|||
if let lastStoredTodayStore = TodayData.getPriceRateAndLastUpdate(), lastStoredTodayStore.lastUpdate == latestRateDataStore.lastUpdate, rateString == lastStoredTodayStore.rate, API.getLastSelectedCurrency() == userPreferredCurrency { |
|||
if let cached = TodayData.getCachedPriceRateAndLastUpdate() { |
|||
self.processCachedStoredRateAndLastUpdate(new: lastStoredTodayStore, cached: cached) |
|||
} else { |
|||
self.setLastPriceOutletsHidden(isHidden: true) |
|||
} |
|||
completionHandler(.noData) |
|||
} else { |
|||
self.processRateAndLastUpdate(todayStore: latestRateDataStore) |
|||
let priceRiceAndLastUpdate = TodayData.getPriceRateAndLastUpdate() |
|||
|
|||
if let rate = priceRiceAndLastUpdate?.rate, let lastUpdate = priceRiceAndLastUpdate?.lastUpdate { |
|||
TodayData.saveCachePriceRateAndLastUpdate(rate: rate, lastUpdate: lastUpdate); |
|||
} |
|||
|
|||
if let latestRateDataStore = latestRateDataStore.rateDoubleValue, let lastStoredPriceNumber = priceRiceAndLastUpdate?.rateDoubleValue, API.getLastSelectedCurrency() == userPreferredCurrency { |
|||
|
|||
if latestRateDataStore > lastStoredPriceNumber { |
|||
self.lastPriceArrowImage.image = UIImage(systemName: "arrow.up") |
|||
self.setLastPriceOutletsHidden(isHidden: false) |
|||
} else { |
|||
self.lastPriceArrowImage.image = UIImage(systemName: "arrow.down") |
|||
self.setLastPriceOutletsHidden(isHidden: false) |
|||
} |
|||
self.lastPrice.text = priceRiceAndLastUpdate?.formattedRate |
|||
} else { |
|||
self.setLastPriceOutletsHidden(isHidden: true) |
|||
} |
|||
|
|||
TodayData.savePriceRateAndLastUpdate(rate: latestRateDataStore.rate, lastUpdate: latestRateDataStore.lastUpdate) |
|||
API.saveNewSelectedCurrency() |
|||
completionHandler(.newData) |
|||
} |
|||
} |
|||
}) |
|||
} |
|||
|
|||
} |
@ -1,61 +1,49 @@ |
|||
Always backup your keys! While your coins are safe, bugs happen, and app |
|||
could sometimes lose your wallets (fixed). |
|||
|
|||
v4.4.1 |
|||
v4.8.0 |
|||
====== |
|||
|
|||
* FIX: crash on ManageFunds |
|||
* ADD: marketplace for regular onchain btc wallets |
|||
* ADD: WatchApp Complication. |
|||
* FIX: Wallet gradient for Bech32 on watch app |
|||
* FIX: v3.9.8 fails to fill value #470 |
|||
* FIX: Don't allow more than one leading zero |
|||
* ADD: Today Extension and Quick Actions |
|||
* ADD: Send max option on advanced menu |
|||
* ADD: Add Onchain address view for Lightning |
|||
* FIX: Allow textfield to be visible above keyboard |
|||
* FIX: lapp browser when typing URL without https scheme it doesnt work |
|||
* ADD: Value and memo to the success screen fix logic for both sent and receive |
|||
* FIX: layout for small devices with flexbox |
|||
* FIX: Dont allow zero invoices to enable create invoice button |
|||
* FIX: Change create button on Receive LN payment should be create invoice |
|||
* FIX: Update for watch |
|||
|
|||
|
|||
v4.4.0 |
|||
v4.7.1 |
|||
====== |
|||
|
|||
* ADD: send MAX (for BIP84 & BIP49) |
|||
* ADD: Scan to receive (lnurl spec) |
|||
* ADD: New TX status screen |
|||
* ADD: Share QRCode along with address |
|||
* ADD: Allow user to hide their balance |
|||
* ADD: KRW Fiat |
|||
* FIX: wallet selector on send view |
|||
* FIX: all data is stored in OS secure keystore |
|||
* FIX: broken LIGHTNING scheme handling |
|||
* FIX: import legacy address by WIF with uncompressed pubkey (closes #590) |
|||
* ADD: Handoff for a transaction and wallets |
|||
* FIX: QR Correctness for watch app |
|||
* FIX: Tap to copy preimage text |
|||
* FIX: Show last saved exchange rate |
|||
|
|||
v4.2.0 |
|||
* ADD: Lapp browser |
|||
* FIX: White screen on boot |
|||
* FIX: Lightning wallet was not shown on Watch app |
|||
* FIX: crash on PSBT tx broadcast (when using with hardware wallet) |
|||
* REF: mnemonic backup screen |
|||
* DEL: Auto brightenss |
|||
|
|||
v4.7.0 |
|||
====== |
|||
|
|||
* ADD: bumpfee (RBF) & cancelTx (RBF) for BIP84 HD wallet |
|||
* ADD: CPFP for BIP84 HD wallets |
|||
* ADD: Electrum server configuration |
|||
* ADD: Hungarian localization |
|||
* ADD: HUF fiat unit |
|||
* FIX: receive address generation with no internet |
|||
* FIX: wait for electrum connection before fetching tx or broadcast |
|||
* FIX: Receive UI jumpiness |
|||
* FIX: iOS App crashes when scaning QR Code |
|||
* FIX: Amount when scanning was not displayed in amount UI |
|||
* FIX: ln transaction details screen |
|||
* FIX: import LN wallet with custom lndhub |
|||
* FIX: BIP84 txs with low confirmations not updating |
|||
* FIX: crash |
|||
* REF: Swedish translation updates |
|||
* REF: better initial HD rescan |
|||
|
|||
|
|||
v4.1.0 |
|||
* ADD: external marketplace link |
|||
* FIX: electrum connection |
|||
* FIX: Now able to use biometrics with encrypted storage (not for unlocking) |
|||
* FIX: LApp marketplace address is now editable |
|||
* FIX: single address watch-only wallet Receive button crash |
|||
|
|||
v4.6.0 |
|||
====== |
|||
|
|||
* REF: faster initial HD rescan |
|||
* FIX: ln transaction details screen |
|||
* FIX: import LN wallet with custom lndhub |
|||
* FIX: BIP84 txs with low confirmations not updating |
|||
* FIX: crash |
|||
* REF: Swedish translation updates |
|||
* ADD: Optional biometrics unlock (this does not exclude full encryption) |
|||
* ADD: Cryptoadvance HW wallet support (for BIP84) via PSBT and QR codes |
|||
* ADD: LN Refill with external wallet |
|||
* ADD: Default into wallet on launch |
|||
* FIX: NaN when sending onchain |
|||
* FIX: zero on send success screen |
|||
* FIX: Time shown for top-most transaction |
|||
* FIX: minor issue with scanQrWif |
|||
* FIX: typo on NL language |
|||
* FIX: better wallet export QR readability |
|||
* FIX: RBF tx memo porting |
|||
* REF: better initial HD rescan |
@ -1,5 +1,5 @@ |
|||
defaults.url=https://sentry.io/ |
|||
defaults.org=bluewallet |
|||
defaults.project=bluewallet |
|||
auth.token=0ee298bd4d3743819f710a5ed555f5429e4ffe64acbb41ac933f2745b0c163da |
|||
auth.token=8020b31b54e94e7b86b4a69f60869f3d5a1320f44efe4f22bb9fa27e0b371448 |
|||
cli.executable=node_modules/@sentry/cli/bin/sentry-cli |
|||
|
@ -0,0 +1,236 @@ |
|||
module.exports = { |
|||
_: { |
|||
storage_is_encrypted: 'U geheue spasie is nou ge-enkripteer. ‘n Wagwoord word benodig om toegang te verkry. ', |
|||
enter_password: 'Sleutel wagwoord in', |
|||
bad_password: 'Verkeerde wagwoord, probeer weer', |
|||
never: 'nooit', |
|||
continue: 'Gaan voort', |
|||
ok: 'OK', |
|||
}, |
|||
wallets: { |
|||
select_wallet: 'Kies Beursie', |
|||
options: 'opsies', |
|||
createBitcoinWallet: |
|||
'U het nie huidiglik `n geldige Bitcoin Beursie nie. Skep of voer eers ‘n Bitcoin Beursie in, sodat ‘n Bitcoin Lightning Beursie geskep en bevonds mag word. Wil U voortgaan?', |
|||
list: { |
|||
app_name: 'BlueWallet', |
|||
title: 'beursies', |
|||
header: |
|||
'U beursie verteenwoordig ‘n sleutelkombinasie, bestaande uit geheims (privaat sleutel) en address' + |
|||
'wat u kan gebruik om fondse te ontvang.', |
|||
add: 'Skep Beursie', |
|||
create_a_wallet: 'Skep ‘n beursie', |
|||
create_a_wallet1: 'Dit is gratis so skep', |
|||
create_a_wallet2: 'soveel as wat u benodig', |
|||
latest_transaction: 'laaste transaksie', |
|||
empty_txs1: 'U transaksies is hier beskikbaar,', |
|||
empty_txs2: 'huidiglik geen transaksies', |
|||
tap_here_to_buy: 'Raak hier om Bitcoin te koop', |
|||
}, |
|||
reorder: { |
|||
title: 'Herorganiseer Beursies', |
|||
}, |
|||
add: { |
|||
title: 'skep beursie', |
|||
description: |
|||
'U kan ‘n beursie invoer (in WIF - Wallet Import Format), of ‘n nuwe beursie skep. Beursies ondersteun Segwit as standaard.', |
|||
scan: 'Skandeer', |
|||
create: 'Skep', |
|||
label_new_segwit: 'Nuwe SegWit', |
|||
label_new_lightning: 'Nuwe Lightning', |
|||
wallet_name: 'beursie naam', |
|||
wallet_type: 'tipe', |
|||
or: 'of', |
|||
import_wallet: 'Beursie Invoer', |
|||
imported: 'Ingevoer', |
|||
coming_soon: 'In die toekoms', |
|||
lightning: 'Lightning', |
|||
bitcoin: 'Bitcoin', |
|||
}, |
|||
details: { |
|||
title: 'Beursiet', |
|||
address: 'AdresAddress', |
|||
type: 'Tipe', |
|||
label: 'Etiket', |
|||
destination: 'bestemming', |
|||
description: 'beskrywing', |
|||
are_you_sure: 'Is u Seker?', |
|||
yes_delete: 'Ja, vernietig', |
|||
no_cancel: 'Nee, kanseleerl', |
|||
delete: 'Vernietig', |
|||
save: 'Berg', |
|||
delete_this_wallet: 'Vernietig hierdie beursie', |
|||
export_backup: 'voer uit / kopieer', |
|||
buy_bitcoin: 'Koop Bitcoin', |
|||
show_xpub: 'Wys beursie XPUB', |
|||
}, |
|||
export: { |
|||
title: 'beursie uitvoer', |
|||
}, |
|||
xpub: { |
|||
title: 'beursie XPUB', |
|||
copiedToClipboard: 'Gestuur na klipbord.', |
|||
}, |
|||
import: { |
|||
title: 'Invoer', |
|||
explanation: |
|||
'Sleutel mnemonic, privaat sleutel, WIF, of enige text verwysing. BlueWallet sal die korrekte formaat kies en u beursie importeer ', |
|||
imported: 'Invoer suksesvol', |
|||
error: 'U invoer het misluk. Maak asseblief seker u data is korrek en geldig.', |
|||
success: 'Suksesvol', |
|||
do_import: 'Invoer', |
|||
scan_qr: 'of skandeer QR kode?', |
|||
}, |
|||
scanQrWif: { |
|||
go_back: 'Gaan Terug', |
|||
cancel: 'Kanseleer', |
|||
decoding: 'Decoding', |
|||
input_password: 'Input password', |
|||
password_explain: 'Hierdie is ‘n BIP38 ge-enkripteerde privaat sleutel', |
|||
bad_password: 'Wagwoord verkeerd', |
|||
wallet_already_exists: 'Hierdie beursie bestaan alreeds', |
|||
bad_wif: 'WIF verkeerd', |
|||
imported_wif: 'WIF invoer suksesvol ', |
|||
with_address: ' met adres ', |
|||
imported_segwit: 'Segwit Invoer Suksesvol', |
|||
imported_legacy: 'Legacy Invoer', |
|||
imported_watchonly: 'Kyk Slegs invoer suksesvol', |
|||
}, |
|||
}, |
|||
transactions: { |
|||
list: { |
|||
tabBarLabel: 'Transaksies', |
|||
title: 'transaksies', |
|||
description: 'Lys met inkomende en uitgaande transaksies van u beursies', |
|||
conf: 'bev.', |
|||
}, |
|||
details: { |
|||
title: 'Transaksie', |
|||
from: 'Inset', |
|||
to: 'Resultaat', |
|||
copy: 'Kopieer', |
|||
transaction_details: 'Transaksie besonderhede', |
|||
show_in_block_explorer: 'Wys in blok verkenner', |
|||
}, |
|||
}, |
|||
send: { |
|||
header: 'Stuur', |
|||
details: { |
|||
title: 'skep transaksie', |
|||
amount_field_is_not_valid: 'Bedrag is ongeldig', |
|||
fee_field_is_not_valid: 'Fooi spasie is ongeldig', |
|||
address_field_is_not_valid: 'Adres is ongeldig', |
|||
total_exceeds_balance: 'Die bedrag is meer as die beskikbare balans.', |
|||
create_tx_error: 'Daar was ‘n probleem met die skepping van die transaksie. Bevestig asseblief die adres is geldig.', |
|||
address: 'adres', |
|||
amount_placeholder: 'bedrag om te stuur (in BTC)', |
|||
fee_placeholder: 'plus transaksie fooi (in BTC)', |
|||
note_placeholder: 'persoonlike notas', |
|||
cancel: 'Kanselleer', |
|||
scan: 'Skandeer', |
|||
send: 'Stuur', |
|||
create: 'Skep', |
|||
remaining_balance: 'Oorblywende balans', |
|||
}, |
|||
confirm: { |
|||
header: 'Bevestig', |
|||
sendNow: 'Stuur nou', |
|||
}, |
|||
success: { |
|||
done: 'Klaar', |
|||
}, |
|||
create: { |
|||
details: 'Besonderhede', |
|||
title: 'skep transaksie', |
|||
error: 'Daar is ‘n probleem met die transaksie. Ongeldige adres of bedrag?', |
|||
go_back: 'Gaan Terug', |
|||
this_is_hex: 'Hierdie is die transaksie hex, geteken en gereed om na die netwerk uitgesaai te word.', |
|||
to: 'Aan', |
|||
amount: 'Bedrag', |
|||
fee: 'Fooi', |
|||
tx_size: 'TX groote', |
|||
satoshi_per_byte: 'Satoshi per byte', |
|||
memo: 'Memo', |
|||
broadcast: 'Saai uit', |
|||
not_enough_fee: 'Fooi te laag. Vermeerder die fooi', |
|||
}, |
|||
}, |
|||
receive: { |
|||
header: 'Ontvang', |
|||
details: { |
|||
title: 'Deel adres met krediteur', |
|||
share: 'deel', |
|||
copiedToClipboard: 'Gekopieer na klipbord.', |
|||
label: 'Beskrywing', |
|||
create: 'Skep', |
|||
setAmount: 'Bedrag ontvang', |
|||
}, |
|||
}, |
|||
buyBitcoin: { |
|||
header: 'Koop Bitcoin', |
|||
tap_your_address: 'Raak aan die adres om dit na die klipbord the stuur:', |
|||
copied: 'Gekopieer na klipbord!', |
|||
}, |
|||
settings: { |
|||
header: 'instellings', |
|||
plausible_deniability: 'Geloofwaardige ontkenbaarheid...', |
|||
storage_not_encrypted: 'Berging: Nie-geenkripteer nie', |
|||
storage_encrypted: 'Berging: Ge-enkripteer', |
|||
password: 'Wagwoord', |
|||
password_explain: 'Skep die wagwoord wat u sal gebruik om u berging te de-enkripteer', |
|||
retype_password: 'Hervoer wagwoord', |
|||
passwords_do_not_match: 'Wagwoorde stem nie oor een nie', |
|||
encrypt_storage: 'Enkripteer Berging', |
|||
lightning_settings: 'Lightning Instellings', |
|||
lightning_settings_explain: |
|||
'Om u eie LND node te konnekteer, installeer asseblief LndHub' + |
|||
' and put its URL here in settings. Leave blank om die standaard LndHub' + |
|||
'(lndhub.io) te gebruik', |
|||
save: 'stoor', |
|||
about: 'info', |
|||
language: 'Taal', |
|||
currency: 'Geldeenheid', |
|||
}, |
|||
plausibledeniability: { |
|||
title: 'Geloofwaardige Ontkenbaarheid', |
|||
help: |
|||
'Onder sekere omstandighede mag u dalk geforseer word om u ' + |
|||
'wagwoord te deel teen u wil. Om u te beskerm kan Bluewallet ‘n ' + |
|||
'tweede “fantasie” beursie skep wat as skerm kan dien. Indien u ' + |
|||
'hierdie wagwoord deel sal die 3de party nie toegang tot u hoof fondse kry nie.', |
|||
help2: 'Fantasie berging is heeltemal funksioneel', |
|||
create_fake_storage: 'Skep fantasie berging wagwoord', |
|||
go_back: 'Gaan terug', |
|||
create_password: 'Skep ‘n wagwoord', |
|||
create_password_explanation: 'Die wagwoord vir fantasie berging moet verskil van die wagwoord vir hoof berging', |
|||
password_should_not_match: 'Die wagwoord vir fantasie berging moet verskil van die wagwoord vir hoof berging.', |
|||
retype_password: 'Hervoer wagwoord', |
|||
passwords_do_not_match: 'Wagwoorde vergelyk nie, probeer weer', |
|||
success: 'Sukses', |
|||
}, |
|||
lnd: { |
|||
title: 'bestuur fondse', |
|||
choose_source_wallet: 'Kies ‘n bron beursie', |
|||
refill_lnd_balance: 'Herlaai Lightning beursie', |
|||
refill: 'Herlaai', |
|||
withdraw: 'Ontrek', |
|||
expired: 'Verval', |
|||
placeholder: 'Faktuur', |
|||
sameWalletAsInvoiceError: 'U kan nie ‘n faktuur betaal met die selfde beursie waarmee die faktuur geksep is nie.', |
|||
}, |
|||
pleasebackup: { |
|||
title: 'Your wallet is created...', |
|||
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.", |
|||
ok: 'OK, I wrote this down!', |
|||
}, |
|||
lndViewInvoice: { |
|||
wasnt_paid_and_expired: 'This invoice was not paid for and has expired', |
|||
has_been_paid: 'This invoice has been paid for', |
|||
please_pay: 'Please pay', |
|||
sats: 'sats', |
|||
for: 'For:', |
|||
additional_info: 'Additional Information', |
|||
open_direct_channel: 'Open direct channel with this node:', |
|||
}, |
|||
}; |
@ -0,0 +1,239 @@ |
|||
module.exports = { |
|||
_: { |
|||
storage_is_encrypted: 'Ukugcinwa kwakho kubhaliwe. Inombolo yokuvula iyadingeka ukuba ichithwe', |
|||
enter_password: 'Faka inombolo yokuvula', |
|||
bad_password: 'Iphasiwedi engalunganga, zama kwakhona', |
|||
never: 'Ungalingi', |
|||
continue: 'Qhubeka', |
|||
ok: 'OK', |
|||
}, |
|||
wallets: { |
|||
select_wallet: 'Khetha ingxowa', |
|||
options: 'Ukhetho', |
|||
createBitcoinWallet: |
|||
'Okwangoku awunayo ingxowa yebitcoin. Ukuze kuxhaswe ingxowa ekhawulezayo, Ingxowa yeBitcoin kufuneka idalwe okanye ikhutshelwe. Ungathanda ukuqhubeka ?', |
|||
list: { |
|||
app_name: 'BlueWallet', |
|||
title: 'Ingxowa', |
|||
header: 'Ingxowa imele ukuba nemfihlelo yokuyivula nekheli kwaye unokuyisebenzisa ukwamkela imali.', |
|||
add: 'Yongeza Ingxowa', |
|||
create_a_wallet: 'Yenza ingxowa', |
|||
create_a_wallet1: 'Ayihlawulelwa kwaye ungayenza', |
|||
create_a_wallet2: 'Ungenza zibeninzi indlela zokuhlawula', |
|||
latest_transaction: 'Utshintsho olutsha', |
|||
empty_txs1: 'Intengiso yakho iya kubonakala apha,', |
|||
empty_txs2: 'akuho nanye okwangoku', |
|||
tap_here_to_buy: 'Cofa apha ukuthenga ibitcoin', |
|||
}, |
|||
reorder: { |
|||
title: 'Yenza kwakhona ingxowa', |
|||
}, |
|||
add: { |
|||
title: 'yongeza ingxowa', |
|||
description: |
|||
'Unokukhangela ingxowa yephepha yokugcinwa kwephepha ( kwi-WIF – indlela lokungenisa ingxowa), okanye wenze ingxowa entsha. Ingxowa yeSegwit exhaswa yi-default.', |
|||
scan: 'Ukuqondisa', |
|||
create: 'Yakha', |
|||
label_new_segwit: 'SegWit entsha', |
|||
label_new_lightning: 'Umbane omtsha', |
|||
wallet_name: 'igama lengxowa', |
|||
wallet_type: 'uhlobo', |
|||
or: 'okanye', |
|||
import_wallet: 'Ukungenisa ingxowa', |
|||
imported: 'ngeniswa', |
|||
coming_soon: 'Kuza ngokukhawuleza', |
|||
lightning: 'Umbane', |
|||
bitcoin: 'Bitcoin', |
|||
}, |
|||
details: { |
|||
title: 'Ingxowa', |
|||
address: 'Ikheli', |
|||
type: 'Uhlobo', |
|||
label: 'Igama', |
|||
destination: 'ukuya kuyo', |
|||
description: 'ukuya kuyo', |
|||
are_you_sure: 'Ingaba uqinisekile?', |
|||
yes_delete: 'Ewe, yisuse', |
|||
no_cancel: 'Hayi, rhoxisa', |
|||
delete: 'Cima', |
|||
save: 'Gcina', |
|||
delete_this_wallet: 'Cima le ngxowa', |
|||
export_backup: 'Ukuthumela ngaphandle / yokugcina', |
|||
buy_bitcoin: 'Thenga ibitcoin', |
|||
show_xpub: 'Bonise ingxowa XPUB', |
|||
}, |
|||
export: { |
|||
title: 'ukuthunyelwa kweebhanki ', |
|||
}, |
|||
xpub: { |
|||
title: 'ingxowa XPUB', |
|||
copiedToClipboard: 'Ikopishwe kwi-clipboard', |
|||
}, |
|||
import: { |
|||
title: 'ukungenisa', |
|||
explanation: |
|||
'Bhale apha imnemonic yakho, ngundoqo, WIF , okanye nantoni na onayo. BlueWallet uya kwenza konke okusemandleni ukuqiqa ifomathi efanelekileyo kwaye ingenise ingxowa yakho', |
|||
imported: 'Ngenisiwe', |
|||
error: 'Ayiphumelelanga ukungenisa. Nceda, uqiniseka ukuba idata ehlinzekiweyo iyasebenza.', |
|||
success: 'Iphumelele', |
|||
do_import: 'Ngeniswe', |
|||
scan_qr: 'okanye ukukhangela iQR code?', |
|||
}, |
|||
scanQrWif: { |
|||
go_back: 'Buya Umva', |
|||
cancel: 'Rhoxisa', |
|||
decoding: 'Ukumisela', |
|||
input_password: 'Igama lokungena', |
|||
password_explain: 'Yi le BIP38 ikhifidi yangasese itsixe', |
|||
bad_password: 'Inombolo yokuvula eli ngalunganga ', |
|||
wallet_already_exists: 'Ikhredithi enjalo sele ikhona', |
|||
bad_wif: 'Ezimbi WIF', |
|||
imported_wif: 'Ngeniswa WIF ', |
|||
with_address: ' Nge dilesi ', |
|||
imported_segwit: 'Ngeniswa SegWit', |
|||
imported_legacy: 'Ngeniswa ilifa', |
|||
imported_watchonly: 'Ngeniswa bukele-kuphela', |
|||
}, |
|||
}, |
|||
transactions: { |
|||
list: { |
|||
tabBarLabel: 'Ngeniswa', |
|||
title: 'ngeniswa', |
|||
description: 'Uluhlu lokungena okanye ukuphuma kweekhredithi zakho', |
|||
conf: 'conf', |
|||
}, |
|||
details: { |
|||
title: 'Ngeniswa', |
|||
from: 'Negalelo', |
|||
to: 'Mveliso', |
|||
copy: 'Ikopi', |
|||
transaction_details: 'Iinkcukacha zentengiselwano', |
|||
show_in_block_explorer: 'Bonisa ibhloko umhloi', |
|||
}, |
|||
}, |
|||
send: { |
|||
header: 'Thumela', |
|||
details: { |
|||
title: 'ukudala ukuthenga', |
|||
amount_field_is_not_valid: 'intsimi yexabiso ayivumelekanga', |
|||
fee_field_is_not_valid: 'Intsimi yentlawulo ayivumelekanga ', |
|||
address_field_is_not_valid: 'Intsimi yeedilesi ayivumelekanga', |
|||
total_exceeds_balance: 'Imali yokuthumela idlula imali ekhoyo.', |
|||
create_tx_error: 'Kukho impazamo yokudala ukuthengiselana. Nceda, qinisekisa ukuba idilesi iyasebenza.', |
|||
address: 'idilesi', |
|||
amount_placeholder: 'inani lokuthumela (nge BTC)', |
|||
fee_placeholder: 'kunye nentlawulo yokuthengiswa (nge BTC)', |
|||
note_placeholder: 'inqaku kumntu', |
|||
cancel: 'Rhoxisa', |
|||
scan: 'Ukutshekisha', |
|||
send: 'Thumela', |
|||
create: 'Yenza', |
|||
remaining_balance: 'Ibhalansi eseleyo', |
|||
}, |
|||
confirm: { |
|||
header: 'Qiniseka', |
|||
sendNow: 'Thumela ngoku', |
|||
}, |
|||
success: { |
|||
done: 'Kwenzekile', |
|||
}, |
|||
create: { |
|||
details: 'Iinkcukacha', |
|||
title: 'ukudala ukuthenga', |
|||
error: 'Impazamo yokudala ukuthengiselana. Idilesi engavumelekanga okanye imali yokuthumela?', |
|||
go_back: 'Buya umva', |
|||
this_is_hex: 'Le yi ntengo hex, ityikityiwe ilungele ukukhutshelwa kumnatha.', |
|||
to: 'Iya ku', |
|||
amount: 'Isixa', |
|||
fee: 'Ntlawulo', |
|||
tx_size: 'TX ubungakanani', |
|||
satoshi_per_byte: 'Satoshi nge-byte', |
|||
memo: 'Memo', |
|||
broadcast: 'Sasazwa', |
|||
not_enough_fee: 'Akukho mali e neleyo. UKwandisa intlawulo ', |
|||
}, |
|||
}, |
|||
receive: { |
|||
header: 'Fumana', |
|||
details: { |
|||
title: 'Wabelane ngale dilesi nomhlawuli', |
|||
share: 'yabelana', |
|||
copiedToClipboard: 'Ikhutshelwe kwi-clipboard', |
|||
label: 'Inkcazo', |
|||
create: 'Yenza', |
|||
setAmount: 'Fumana ngexabiso', |
|||
}, |
|||
}, |
|||
buyBitcoin: { |
|||
header: 'Thenga Ibitcoin', |
|||
tap_your_address: 'Thepha idilesi yakho ukuyikopisha kwi-clipboard:', |
|||
copied: 'Ikhutshelwe kwi-clipboard!', |
|||
}, |
|||
settings: { |
|||
header: 'Izicwangciso', |
|||
plausible_deniability: 'Ukuphika...', |
|||
storage_not_encrypted: 'Ukugciwa: hayi ngekhodi', |
|||
storage_encrypted: 'Ukugciwa: ngekhodi', |
|||
password: 'Inombolo yokuvula', |
|||
password_explain: 'Ukudala iinombolo yokuvula oyisebenzisayo ukucima ukugcina', |
|||
retype_password: 'Phina inombolo yokuvula', |
|||
passwords_do_not_match: 'Inombolo yokuvula azifani', |
|||
encrypt_storage: 'Kubhala u kubhala', |
|||
lightning_settings: 'Izixhobo zokukhanyisa', |
|||
lightning_settings_explain: |
|||
'Ukuxhuma kwi-node yakho ye-LND nceda ufake iLndHub' + |
|||
' kwaye ufake iURL apha izicwangciso. Shiya kungenanto yokusebenzisa iLndHub (Indhub.io)', |
|||
save: 'ndoloza', |
|||
about: 'Malunga', |
|||
language: 'Ulwimi', |
|||
currency: 'Lwemali', |
|||
}, |
|||
plausibledeniability: { |
|||
title: 'Ukuphika', |
|||
help: |
|||
'Phantsi kweemeko unokunyaneliswa ukuba uchaze a ' + |
|||
'inombolo yokuvula. BlueWallet ukugcina imali yakho ikhuselekile, unokudala enye ' + |
|||
'ukugcinwa kwekhowudi, ngegama eligqithisiweyo. Phantsi kwefuthe, ' + |
|||
'unako ukutyhila le phasiwedi kumntu wesithatu. Ukuba ungenayo ' + |
|||
'BlueWallet, iya kuvula ukugcinwa kwetyala ‘entsha’. Oku kuya kubonakala ' + |
|||
'Umlenze kumntu wesithathu kodwa uza kugcina ngasese ukugcinwa kwakho ' + |
|||
'ngemali ekhuselekile..', |
|||
help2: |
|||
'Igumbi lokugcina elitsha liza kusebenza ngokupheleleyo, kwaye unako ukugcina okunye ‘ + ‘lxabiso elincinci apho likhangeleka ngakumbi.', |
|||
create_fake_storage: 'Ukudala igumbi lokugcina elifihlakeleyo', |
|||
go_back: 'Buya Umva', |
|||
create_password: 'Yenza inombolo yokuvula', |
|||
create_password_explanation: |
|||
'Inombolo yakho yokuvula igumbi lokugcina inkohliso akumele ifane ne nombolo yokuvula igumbi lakho elinyanisekileyo', |
|||
password_should_not_match: |
|||
'Inombolo yakho yokuvula igumbi lokugcina inkohliso akumele ifane ne nombolo yokuvula igumbi lakho elinyanisekileyo', |
|||
retype_password: 'Phinda inombolo yokuvula', |
|||
passwords_do_not_match: 'Inombolo yokuvula ayihambelani, zama kwakhona', |
|||
success: 'Iphumelele', |
|||
}, |
|||
lnd: { |
|||
title: 'lawula imali', |
|||
choose_source_wallet: 'Ukhethe ingxowa yomthombo', |
|||
refill_lnd_balance: 'Gcwalisa ingxowa yakho yemali', |
|||
refill: 'Gcwalisa', |
|||
withdraw: 'Khupha imali', |
|||
expired: 'Iphelewe lixesha', |
|||
placeholder: 'Invoyisi', |
|||
sameWalletAsInvoiceError: ': Awukwazi ukuhlawula i-invoyisi kunye ngengxowa oyisebenzisile ukudala leyo invoyisi.', |
|||
}, |
|||
pleasebackup: { |
|||
title: 'Your wallet is created...', |
|||
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.", |
|||
ok: 'OK, I wrote this down!', |
|||
}, |
|||
lndViewInvoice: { |
|||
wasnt_paid_and_expired: 'This invoice was not paid for and has expired', |
|||
has_been_paid: 'This invoice has been paid for', |
|||
please_pay: 'Please pay', |
|||
sats: 'sats', |
|||
for: 'For:', |
|||
additional_info: 'Additional Information', |
|||
open_direct_channel: 'Open direct channel with this node:', |
|||
}, |
|||
}; |
@ -0,0 +1,244 @@ |
|||
module.exports = { |
|||
_: { |
|||
storage_is_encrypted: 'Lưu trữ của bạn được mã hoá. Mật khẩu được yêu cầu để giải mã', |
|||
enter_password: 'Enter password', |
|||
bad_password: 'Bad password, try again', |
|||
never: 'never', |
|||
continue: 'Continue', |
|||
ok: 'OK', |
|||
}, |
|||
wallets: { |
|||
select_wallet: 'Select Wallet', |
|||
options: 'options', |
|||
createBitcoinWallet: |
|||
'You currently do not have a Bitcoin wallet. In order to fund a Lightning wallet, a Bitcoin wallet needs to be created or imported. Would you like to continue anyway?', |
|||
list: { |
|||
app_name: 'BlueWallet', |
|||
title: 'wallets', |
|||
header: 'A wallet represents a pair of a secret (private key) and an address' + 'you can share to receive coins.', |
|||
add: 'Add Wallet', |
|||
create_a_wallet: 'Create a wallet', |
|||
create_a_wallet1: "It's free and you can create", |
|||
create_a_wallet2: 'as many as you like', |
|||
latest_transaction: 'latest transaction', |
|||
empty_txs1: 'Your transactions will appear here,', |
|||
empty_txs2: 'none at the moment', |
|||
empty_txs1_lightning: |
|||
'Lightning wallet should be used for your daily transactions. Fees are unfairly cheap and speed is blazing fast.', |
|||
empty_txs2_lightning: '\nTo start using it tap on "manage funds" and topup your balance.', |
|||
tap_here_to_buy: 'Tap here to buy Bitcoin', |
|||
}, |
|||
reorder: { |
|||
title: 'Reorder Wallets', |
|||
}, |
|||
add: { |
|||
title: 'add wallet', |
|||
description: |
|||
'You can either scan backup paper wallet (in WIF - Wallet Import Format), or create a new wallet. Segwit wallets supported by default.', |
|||
scan: 'Scan', |
|||
create: 'Create', |
|||
label_new_segwit: 'New SegWit', |
|||
label_new_lightning: 'New Lightning', |
|||
wallet_name: 'name', |
|||
wallet_type: 'type', |
|||
or: 'or', |
|||
import_wallet: 'Import wallet', |
|||
imported: 'Imported', |
|||
coming_soon: 'Coming soon', |
|||
lightning: 'Lightning', |
|||
bitcoin: 'Bitcoin', |
|||
}, |
|||
details: { |
|||
title: 'Wallet', |
|||
address: 'Address', |
|||
type: 'Type', |
|||
label: 'Label', |
|||
destination: 'destination', |
|||
description: 'description', |
|||
are_you_sure: 'Are you sure?', |
|||
yes_delete: 'Yes, delete', |
|||
no_cancel: 'No, cancel', |
|||
delete: 'Delete', |
|||
save: 'Save', |
|||
delete_this_wallet: 'Delete this wallet', |
|||
export_backup: 'Export / backup', |
|||
buy_bitcoin: 'Buy Bitcoin', |
|||
show_xpub: 'Show wallet XPUB', |
|||
}, |
|||
export: { |
|||
title: 'wallet export', |
|||
}, |
|||
xpub: { |
|||
title: 'wallet XPUB', |
|||
copiedToClipboard: 'Copied to clipboard.', |
|||
}, |
|||
import: { |
|||
title: '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", |
|||
imported: 'Imported', |
|||
error: 'Failed to import. Please, make sure that the provided data is valid.', |
|||
success: 'Success', |
|||
do_import: 'Import', |
|||
scan_qr: 'or scan QR code instead?', |
|||
}, |
|||
scanQrWif: { |
|||
go_back: 'Go Back', |
|||
cancel: 'Cancel', |
|||
decoding: 'Decoding', |
|||
input_password: 'Input password', |
|||
password_explain: 'This is BIP38 encrypted private key', |
|||
bad_password: 'Bad password', |
|||
wallet_already_exists: 'Such wallet already exists', |
|||
bad_wif: 'Bad WIF', |
|||
imported_wif: 'Imported WIF ', |
|||
with_address: ' with address ', |
|||
imported_segwit: 'Imported SegWit', |
|||
imported_legacy: 'Imported Legacy', |
|||
imported_watchonly: 'Imported Watch-only', |
|||
}, |
|||
}, |
|||
transactions: { |
|||
list: { |
|||
tabBarLabel: 'Transactions', |
|||
title: 'transactions', |
|||
description: 'A list of ingoing or outgoing transactions of your wallets', |
|||
conf: 'conf', |
|||
}, |
|||
details: { |
|||
title: 'Transaction', |
|||
from: 'Input', |
|||
to: 'Output', |
|||
copy: 'Copy', |
|||
transaction_details: 'Transaction details', |
|||
show_in_block_explorer: 'View in block explorer', |
|||
}, |
|||
}, |
|||
send: { |
|||
header: 'Send', |
|||
details: { |
|||
title: 'create transaction', |
|||
amount_field_is_not_valid: 'Amount field is not valid', |
|||
fee_field_is_not_valid: 'Fee field is not valid', |
|||
address_field_is_not_valid: 'Address field is not valid', |
|||
total_exceeds_balance: 'The sending amount exceeds the available balance.', |
|||
create_tx_error: 'There was an error creating the transaction. Please, make sure the address is valid.', |
|||
address: 'address', |
|||
amount_placeholder: 'amount to send (in BTC)', |
|||
fee_placeholder: 'plus transaction fee (in BTC)', |
|||
note_placeholder: 'note to self', |
|||
cancel: 'Cancel', |
|||
scan: 'Scan', |
|||
send: 'Send', |
|||
create: 'Create', |
|||
remaining_balance: 'Remaining balance', |
|||
}, |
|||
confirm: { |
|||
header: 'Confirm', |
|||
sendNow: 'Send now', |
|||
}, |
|||
success: { |
|||
done: 'Done', |
|||
}, |
|||
create: { |
|||
details: 'Details', |
|||
title: 'create transaction', |
|||
error: 'Error creating transaction. Invalid address or send amount?', |
|||
go_back: 'Go Back', |
|||
this_is_hex: 'This is transaction hex, signed and ready to be broadcast to the network.', |
|||
to: 'To', |
|||
amount: 'Amount', |
|||
fee: 'Fee', |
|||
tx_size: 'TX size', |
|||
satoshi_per_byte: 'Satoshi per byte', |
|||
memo: 'Memo', |
|||
broadcast: 'Broadcast', |
|||
not_enough_fee: 'Not enough fee. Increase the fee', |
|||
}, |
|||
}, |
|||
receive: { |
|||
header: 'Receive', |
|||
details: { |
|||
title: 'Share this address with payer', |
|||
share: 'share', |
|||
copiedToClipboard: 'Copied to clipboard.', |
|||
label: 'Description', |
|||
create: 'Create', |
|||
setAmount: 'Receive with amount', |
|||
}, |
|||
scan_lnurl: 'Scan to receive', |
|||
}, |
|||
buyBitcoin: { |
|||
header: 'Buy Bitcoin', |
|||
tap_your_address: 'Tap your address to copy it to clipboard:', |
|||
copied: 'Copied to Clipboard!', |
|||
}, |
|||
settings: { |
|||
header: 'settings', |
|||
plausible_deniability: 'Plausible deniability...', |
|||
storage_not_encrypted: 'Storage: not encrypted', |
|||
storage_encrypted: 'Storage: encrypted', |
|||
password: 'Password', |
|||
password_explain: 'Create the password you will use to decrypt the storage', |
|||
retype_password: 'Re-type password', |
|||
passwords_do_not_match: 'Passwords do not match', |
|||
encrypt_storage: 'Encrypt storage', |
|||
lightning_settings: 'Lightning Settings', |
|||
lightning_settings_explain: |
|||
'To connect to your own LND node please install LndHub' + |
|||
" and put its URL here in settings. Leave blank to use BlueWallet's LNDHub (lndhub.io). Wallets created after saving changes will connect to the specified LNDHub.", |
|||
electrum_settings: 'Electrum Settings', |
|||
electrum_settings_explain: 'Set to blank to use default', |
|||
save: 'Save', |
|||
about: 'About', |
|||
language: 'Language', |
|||
currency: 'Currency', |
|||
advanced_options: 'Advanced Options', |
|||
enable_advanced_mode: 'Enable advanced mode', |
|||
}, |
|||
plausibledeniability: { |
|||
title: 'Plausible Deniability', |
|||
help: |
|||
'Under certain circumstances, you might be forced to disclose a ' + |
|||
'password. To keep your coins safe, BlueWallet can create another ' + |
|||
'encrypted storage, with a different password. Under pressure, ' + |
|||
'you can disclose this password to a 3rd party. If entered in ' + |
|||
"BlueWallet, it will unlock new 'fake' storage. This will seem " + |
|||
'legit to a 3rd party, but will secretly keep your main storage ' + |
|||
'with coins safe.', |
|||
help2: 'New storage will be fully functional, and you can store some ' + 'minimum amounts there so it looks more believable.', |
|||
create_fake_storage: 'Create fake encrypted storage', |
|||
go_back: 'Go Back', |
|||
create_password: 'Create a password', |
|||
create_password_explanation: 'Password for fake storage should not match password for your main storage', |
|||
password_should_not_match: 'Password for fake storage should not match password for your main storage', |
|||
retype_password: 'Retype password', |
|||
passwords_do_not_match: 'Passwords do not match, try again', |
|||
success: 'Success', |
|||
}, |
|||
lnd: { |
|||
title: 'manage funds', |
|||
choose_source_wallet: 'Choose a source wallet', |
|||
refill_lnd_balance: 'Refill Lightning wallet balance', |
|||
refill: 'Refill', |
|||
withdraw: 'Withdraw', |
|||
expired: 'Expired', |
|||
placeholder: 'Invoice', |
|||
sameWalletAsInvoiceError: 'You can not pay an invoice with the same wallet used to create it.', |
|||
}, |
|||
pleasebackup: { |
|||
title: 'Your wallet is created...', |
|||
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.", |
|||
ok: 'OK, I wrote this down!', |
|||
}, |
|||
lndViewInvoice: { |
|||
wasnt_paid_and_expired: 'This invoice was not paid for and has expired', |
|||
has_been_paid: 'This invoice has been paid for', |
|||
please_pay: 'Please pay', |
|||
sats: 'sats', |
|||
for: 'For:', |
|||
additional_info: 'Additional Information', |
|||
open_direct_channel: 'Open direct channel with this node:', |
|||
}, |
|||
}; |
@ -0,0 +1,235 @@ |
|||
module.exports = { |
|||
_: { |
|||
storage_is_encrypted: '你的資訊已經被加密, 請輸入密碼解密', |
|||
enter_password: '輸入密碼', |
|||
bad_password: '密碼無效,請重試', |
|||
never: '不', |
|||
continue: '繼續', |
|||
ok: '好的', |
|||
}, |
|||
wallets: { |
|||
select_wallet: '選擇錢包', |
|||
options: '選項', |
|||
createBitcoinWallet: '您當前沒有bitcoin錢包. 為了支援閃電錢包, 我們需要建立或者匯入一個比特幣錢包. 是否需要繼續?', |
|||
list: { |
|||
app_name: 'BlueWallet', |
|||
title: '錢包', |
|||
header: '一個錢包代表一對的私鑰和地址' + '你可以通過分享收款.', |
|||
add: '新增錢包', |
|||
create_a_wallet: '建立一個錢包', |
|||
create_a_wallet1: '建立錢包是免費的,你可以', |
|||
create_a_wallet2: '想建立多少就建立多少個', |
|||
latest_transaction: '最近的轉賬', |
|||
empty_txs1: '你的轉賬資訊將展示在這裡', |
|||
empty_txs2: '當前無資訊', |
|||
empty_txs1_lightning: |
|||
'Lightning wallet should be used for your daily transactions. Fees are unfairly cheap and speed is blazing fast.', |
|||
empty_txs2_lightning: '\nTo start using it tap on "manage funds" and topup your balance.', |
|||
tap_here_to_buy: '點選購買比特幣', |
|||
}, |
|||
reorder: { |
|||
title: '重新排列錢包', |
|||
}, |
|||
add: { |
|||
title: '新增錢包', |
|||
description: '你可以掃描你的紙質備份錢包 (WIF格式), 或者建立一個新錢包. 預設支援隔離見證錢包', |
|||
scan: '掃描', |
|||
create: '建立', |
|||
label_new_segwit: '新隔離見證(Segwit)', |
|||
label_new_lightning: '新閃電', |
|||
wallet_name: '錢包名稱', |
|||
wallet_type: '類型', |
|||
or: '或', |
|||
import_wallet: '匯入錢包', |
|||
imported: '已經匯入', |
|||
coming_soon: '即將來臨', |
|||
lightning: '閃電', |
|||
bitcoin: '比特幣', |
|||
}, |
|||
details: { |
|||
title: '錢包', |
|||
address: '地址', |
|||
type: '類型', |
|||
label: '標籤', |
|||
destination: '目的', |
|||
description: '描述', |
|||
are_you_sure: '你確認麼?', |
|||
yes_delete: '是的,刪除', |
|||
no_cancel: '不,取消', |
|||
delete: '刪除', |
|||
save: '儲存', |
|||
delete_this_wallet: '刪除這個錢包', |
|||
export_backup: '匯出備份', |
|||
buy_bitcoin: '購買比特幣', |
|||
show_xpub: '展示錢包 XPUB', |
|||
}, |
|||
export: { |
|||
title: '錢包匯出', |
|||
}, |
|||
xpub: { |
|||
title: '錢包 XPUB', |
|||
copiedToClipboard: '複製到貼上板.', |
|||
}, |
|||
import: { |
|||
title: '匯入', |
|||
explanation: '輸入你的助記詞,私鑰或者WIF, 或者其他格式的資料. BlueWallet將盡可能的自動識別資料格式並匯入錢包', |
|||
imported: '已經匯入', |
|||
error: '匯入失敗,請確認你提供的資訊是有效的', |
|||
success: '成功', |
|||
do_import: '匯入', |
|||
scan_qr: '或掃面二維碼', |
|||
}, |
|||
scanQrWif: { |
|||
go_back: '回退', |
|||
cancel: '取消', |
|||
decoding: '解碼中', |
|||
input_password: '輸入密碼', |
|||
password_explain: '這是一個BIP38加密的私鑰', |
|||
bad_password: '密碼錯誤', |
|||
wallet_already_exists: '當前錢包已經存在', |
|||
bad_wif: 'WIF格式無效', |
|||
imported_wif: 'WIF已經匯入', |
|||
with_address: ' 地址為', |
|||
imported_segwit: 'SegWit已經匯入', |
|||
imported_legacy: 'Legacy已經匯入', |
|||
imported_watchonly: '匯入只讀', |
|||
}, |
|||
}, |
|||
transactions: { |
|||
list: { |
|||
tabBarLabel: '轉賬', |
|||
title: '轉賬', |
|||
description: '當前所有錢包的轉入和轉出記錄', |
|||
conf: '配置', |
|||
}, |
|||
details: { |
|||
title: '轉賬', |
|||
from: '輸入', |
|||
to: '輸出', |
|||
copy: '複製', |
|||
transaction_details: '轉賬詳情', |
|||
show_in_block_explorer: '區塊瀏覽器展示', |
|||
}, |
|||
}, |
|||
send: { |
|||
header: '傳送', |
|||
details: { |
|||
title: '建立交易', |
|||
amount_field_is_not_valid: '金額格式無效', |
|||
fee_field_is_not_valid: '費用格式無效', |
|||
address_field_is_not_valid: '地址內容無效', |
|||
total_exceeds_balance: '餘額不足', |
|||
create_tx_error: '建立交易失敗. 請確認地址格式正確.', |
|||
address: '地址', |
|||
amount_placeholder: '傳送金額(in BTC)', |
|||
fee_placeholder: '手續費用 (in BTC)', |
|||
note_placeholder: '訊息', |
|||
cancel: '取消', |
|||
scan: '掃描', |
|||
send: '傳送', |
|||
create: '建立', |
|||
remaining_balance: '剩餘金額', |
|||
}, |
|||
confirm: { |
|||
header: '確認', |
|||
sendNow: '現在傳送', |
|||
}, |
|||
success: { |
|||
done: '完成', |
|||
}, |
|||
create: { |
|||
details: '詳情', |
|||
title: '建立詳情', |
|||
error: '建立交易失敗. 無效地址或金額?', |
|||
go_back: '回退', |
|||
this_is_hex: '這個是交易的十六進位制資料, 簽名並廣播到全網路.', |
|||
to: '到', |
|||
amount: '金額', |
|||
fee: '手續費', |
|||
tx_size: '交易大小', |
|||
satoshi_per_byte: '蔥每byte', |
|||
memo: '訊息', |
|||
broadcast: '廣播', |
|||
not_enough_fee: '手續費不夠,請增加手續費', |
|||
}, |
|||
}, |
|||
receive: { |
|||
header: '收款', |
|||
details: { |
|||
title: '分享這個地址給付款人', |
|||
share: '分享', |
|||
copiedToClipboard: '複製到貼上板.', |
|||
label: '描述', |
|||
create: '建立', |
|||
setAmount: '收款金額', |
|||
}, |
|||
}, |
|||
buyBitcoin: { |
|||
header: '購買比特幣', |
|||
tap_your_address: '點選地址複製到貼上板:', |
|||
copied: '複製到貼上板!', |
|||
}, |
|||
settings: { |
|||
header: '設定', |
|||
plausible_deniability: '可否認性...', |
|||
storage_not_encrypted: '儲存:未加密', |
|||
storage_encrypted: '儲存:加密中', |
|||
password: '密碼', |
|||
password_explain: '建立你的加密密碼', |
|||
retype_password: '再次輸入密碼', |
|||
passwords_do_not_match: '兩次輸入密碼不同', |
|||
encrypt_storage: '加密儲存', |
|||
lightning_settings: '閃電網路設定', |
|||
lightning_settings_explain: '如要要連線你自己的閃電節點請安裝LndHub' + ' 並把url地址輸入到下面. 空白將使用預設的LndHub (lndhub.io)', |
|||
save: '儲存', |
|||
about: '關於', |
|||
language: '語言', |
|||
currency: '貨幣', |
|||
advanced_options: 'Advanced Options', |
|||
enable_advanced_mode: 'Enable advanced mode', |
|||
}, |
|||
plausibledeniability: { |
|||
title: '可否認性', |
|||
help: |
|||
'在某些情況下, 你不得不暴露 ' + |
|||
'密碼. 為了讓你的比特幣更加安全, BlueWallet可以建立一些 ' + |
|||
'加密空間, 用不同的密碼. 在壓力之下, ' + |
|||
'你可以暴露這個錢包密碼. 再次進入 ' + |
|||
'BlueWallet, 我們會解鎖一些虛擬空間. 對第三方來說看上去' + |
|||
'是合理的, 但會偷偷的幫你保證主錢包的安全 ' + |
|||
'幣也就安全了.', |
|||
help2: '新的空間具備完整的功能,你可以存在 ' + '少量的金額在裡面.', |
|||
create_fake_storage: '建立虛擬加密儲存', |
|||
go_back: '回退', |
|||
create_password: '建立密碼', |
|||
create_password_explanation: '虛擬儲存空間密碼不能和主儲存空間密碼相同', |
|||
password_should_not_match: '虛擬儲存空間密碼不能和主儲存空間密碼相同', |
|||
retype_password: '重輸密碼', |
|||
passwords_do_not_match: '兩次輸入密碼不同,請重新輸入', |
|||
success: '成功', |
|||
}, |
|||
lnd: { |
|||
title: '配置資金支援', |
|||
choose_source_wallet: '選擇一個資金源錢包', |
|||
refill_lnd_balance: '給閃電錢包充值', |
|||
refill: '充值', |
|||
withdraw: '提取', |
|||
expired: '超時', |
|||
sameWalletAsInvoiceError: '你不能用建立賬單的錢包去支付該賬單', |
|||
}, |
|||
pleasebackup: { |
|||
title: 'Your wallet is created...', |
|||
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.", |
|||
ok: 'OK, I wrote this down!', |
|||
}, |
|||
lndViewInvoice: { |
|||
wasnt_paid_and_expired: 'This invoice was not paid for and has expired', |
|||
has_been_paid: 'This invoice has been paid for', |
|||
please_pay: 'Please pay', |
|||
sats: 'sats', |
|||
for: 'For:', |
|||
additional_info: 'Additional Information', |
|||
open_direct_channel: 'Open direct channel with this node:', |
|||
}, |
|||
}; |
File diff suppressed because it is too large
@ -1,12 +0,0 @@ |
|||
--- a/node_modules/bitcoinjs-lib/src/transaction.js 2018-07-18 00:17:03.540824839 +0100
|
|||
+++ b/node_modules/bitcoinjs-lib/src/transaction.js 2018-07-18 00:24:55.840803782 +0100
|
|||
@@ -408,7 +408,8 @@
|
|||
|
|||
Transaction.prototype.getId = function () { |
|||
// transaction hash's are displayed in reverse order |
|||
- return this.getHash().reverse().toString('hex')
|
|||
+ var bufferReverse = require('buffer-reverse')
|
|||
+ return bufferReverse(this.getHash()).toString('hex')
|
|||
} |
|||
|
|||
Transaction.prototype.toBuffer = function (buffer, initialOffset) { |
@ -1,12 +0,0 @@ |
|||
--- a/node_modules/bitcoinjs-lib/src/transaction_builder.js 2018-07-18 00:09:22.924845375 +0100
|
|||
+++ b/node_modules/bitcoinjs-lib/src/transaction_builder.js 2018-07-18 00:14:20.996832086 +0100
|
|||
@@ -536,7 +536,8 @@
|
|||
// is it a hex string? |
|||
if (typeof txHash === 'string') { |
|||
// transaction hashs's are displayed in reverse order, un-reverse it |
|||
- txHash = Buffer.from(txHash, 'hex').reverse()
|
|||
+ var bufferReverse = require('buffer-reverse')
|
|||
+ txHash = bufferReverse(new Buffer(txHash, 'hex'))
|
|||
|
|||
// is it a Transaction object? |
|||
} else if (txHash instanceof Transaction) { |
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue