mirror of
https://github.com/BlueWallet/BlueWallet.git
synced 2025-01-18 21:35:21 +01:00
Merge branch 'master' into rtl
This commit is contained in:
commit
b520e70c2b
@ -578,8 +578,10 @@ const styleCopyTextToClipboard = StyleSheet.create({
|
||||
});
|
||||
|
||||
export const SafeBlueArea = props => {
|
||||
const { style, ...nonStyleProps } = props;
|
||||
const { colors } = useTheme();
|
||||
return <SafeAreaView forceInset={{ horizontal: 'always' }} style={{ flex: 1, backgroundColor: colors.background }} {...props} />;
|
||||
const baseStyle = { flex: 1, backgroundColor: colors.background }
|
||||
return <SafeAreaView forceInset={{ horizontal: 'always' }} style={[baseStyle, style]} {...nonStyleProps} />;
|
||||
};
|
||||
|
||||
export const BlueCard = props => {
|
||||
|
@ -2,6 +2,7 @@ import React, { useContext, useEffect, useState } from 'react';
|
||||
import { View, Image, TouchableOpacity, StyleSheet, StatusBar, ActivityIndicator, useColorScheme } from 'react-native';
|
||||
import { Icon } from 'react-native-elements';
|
||||
import Biometric from './class/biometrics';
|
||||
import LottieView from 'lottie-react-native';
|
||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||
import { StackActions, useNavigation, useRoute } from '@react-navigation/native';
|
||||
import { BlueStorageContext } from './blue_modules/storage-context';
|
||||
@ -13,21 +14,12 @@ const styles = StyleSheet.create({
|
||||
flex: 1,
|
||||
},
|
||||
container: {
|
||||
flex: 2,
|
||||
flex: 1,
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
},
|
||||
qrCode: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
qrCodeImage: {
|
||||
width: 120,
|
||||
height: 120,
|
||||
},
|
||||
biometric: {
|
||||
flex: 0.2,
|
||||
flex: 1,
|
||||
justifyContent: 'flex-end',
|
||||
marginBottom: 58,
|
||||
},
|
||||
@ -141,9 +133,7 @@ const UnlockWith = () => {
|
||||
<SafeAreaView style={styles.root}>
|
||||
<StatusBar barStyle="default" />
|
||||
<View style={styles.container}>
|
||||
<View style={styles.qrCode}>
|
||||
<Image source={require('./img/qr-code.png')} style={styles.qrCodeImage} />
|
||||
</View>
|
||||
<LottieView source={require('./img/bluewalletsplash.json')} progress={1} loop={false} />
|
||||
<View style={styles.biometric}>
|
||||
<View style={styles.biometricRow}>{renderUnlockOptions()}</View>
|
||||
</View>
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { AppStorage, LightningCustodianWallet } from './';
|
||||
import { AppStorage, LightningCustodianWallet, WatchOnlyWallet } from './';
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
import RNFS from 'react-native-fs';
|
||||
import url from 'url';
|
||||
@ -178,6 +178,17 @@ class DeeplinkSchemaMatch {
|
||||
params: Azteco.getParamsFromUrl(event.url),
|
||||
},
|
||||
]);
|
||||
} else if (new WatchOnlyWallet().setSecret(event.url).init().valid()) {
|
||||
completionHandler([
|
||||
'AddWalletRoot',
|
||||
{
|
||||
screen: 'ImportWallet',
|
||||
params: {
|
||||
triggerImport: true,
|
||||
label: event.url,
|
||||
},
|
||||
},
|
||||
]);
|
||||
} else {
|
||||
const urlObject = url.parse(event.url, true); // eslint-disable-line node/no-deprecated-api
|
||||
(async () => {
|
||||
|
@ -56,13 +56,15 @@ export class WatchOnlyWallet extends LegacyWallet {
|
||||
* this method creates appropriate HD wallet class, depending on whether we have xpub, ypub or zpub
|
||||
* as a property of `this`, and in case such property exists - it recreates it and copies data from old one.
|
||||
* this is needed after serialization/save/load/deserialization procedure.
|
||||
*
|
||||
* @return {WatchOnlyWallet} this
|
||||
*/
|
||||
init() {
|
||||
let hdWalletInstance;
|
||||
if (this.secret.startsWith('xpub')) hdWalletInstance = new HDLegacyP2PKHWallet();
|
||||
else if (this.secret.startsWith('ypub')) hdWalletInstance = new HDSegwitP2SHWallet();
|
||||
else if (this.secret.startsWith('zpub')) hdWalletInstance = new HDSegwitBech32Wallet();
|
||||
else return;
|
||||
else return this;
|
||||
hdWalletInstance._xpub = this.secret;
|
||||
if (this._hdWalletInstance) {
|
||||
// now, porting all properties from old object to new one
|
||||
@ -75,6 +77,8 @@ export class WatchOnlyWallet extends LegacyWallet {
|
||||
delete hdWalletInstance._node0;
|
||||
}
|
||||
this._hdWalletInstance = hdWalletInstance;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
prepareForSerialization() {
|
||||
|
@ -4,13 +4,14 @@
|
||||
*
|
||||
* @param navigateFunc {function}
|
||||
* @param currentScreenName {string}
|
||||
* @param showFileImportButton {boolean}
|
||||
*
|
||||
* @return {Promise<string>}
|
||||
*/
|
||||
module.exports = function (navigateFunc, currentScreenName) {
|
||||
module.exports = function scanQrHelper(navigateFunc, currentScreenName, showFileImportButton = true) {
|
||||
return new Promise(resolve => {
|
||||
const params = {};
|
||||
params.showFileImportButton = true;
|
||||
params.showFileImportButton = !!showFileImportButton;
|
||||
|
||||
params.onBarScanned = function (data) {
|
||||
setTimeout(() => resolve(data.data || data), 1);
|
||||
|
@ -174,7 +174,6 @@
|
||||
"details_address_field_is_not_valid": "The address is not valid.",
|
||||
"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": "Are you sure you want to use your wallet’s full balance for this transaction?",
|
||||
"details_adv_import": "Import Transaction",
|
||||
"details_amount_field_is_not_valid": "The amount is not valid.",
|
||||
|
@ -62,7 +62,7 @@
|
||||
"cont_title": "Sopimukseni",
|
||||
"filter_any": "Mikä tahansa",
|
||||
"filter_buying": "Ostaminen",
|
||||
"filter_country_global": "Maailmanlaajuiset tarjoukset",
|
||||
"filter_country_global": "Globaalit tarjoukset",
|
||||
"filter_currency": "Valuutta",
|
||||
"filter_detail": "Tiedot",
|
||||
"filter_filters": "Suodattimet",
|
||||
@ -75,7 +75,7 @@
|
||||
"item_nooffers": "Ei tarjouksia. Yritä muuttaa \"Lähellä minua\" kansainvälisiksi tarjouksiksi!",
|
||||
"item_rating": "{rating} vaihdot",
|
||||
"item_rating_no": "Ei luokitusta",
|
||||
"local_trader": "Paikallinen kauppias",
|
||||
"local_trader": "Osta välittäjältä",
|
||||
"local_trader_new": "Uusi",
|
||||
"login": "Kirjaudu sisään",
|
||||
"logout": "kirjaudu ulos",
|
||||
@ -116,7 +116,7 @@
|
||||
"open_direct_channel": "Avaa suora kanava tällä solmulla:",
|
||||
"please_pay": "Ole hyvä ja maksa",
|
||||
"preimage": "Alkukuva",
|
||||
"sats": "sats",
|
||||
"sats": "sattia",
|
||||
"wasnt_paid_and_expired": "Tätä laskua ei maksettu, ja se on vanhentunut."
|
||||
},
|
||||
"plausibledeniability": {
|
||||
@ -166,19 +166,18 @@
|
||||
"create_satoshi_per_byte": "Satoshia per tavu",
|
||||
"create_this_is_hex": "Tämä on siirtotapahtuman hex, allekirjoitettu ja valmis lähetettävksi verkkoon.",
|
||||
"create_to": "Vastaanottaja",
|
||||
"create_tx_size": "TX koko",
|
||||
"create_tx_size": "Siirtotapahtuman koko",
|
||||
"create_verify": "Varmenna coinb.in :ssä",
|
||||
"details_add_rec_add": "Lisää Vastaanottaja",
|
||||
"details_add_rec_rem": "Poista Vastaanottaja",
|
||||
"details_address": "osoite",
|
||||
"details_address_field_is_not_valid": "Osoite ei kelpaa",
|
||||
"details_adv_fee_bump": "Salli Siirtokulun Nosto",
|
||||
"details_adv_full": "Käytä Koko Saldo",
|
||||
"details_adv_full_remove": "Muut vastaanottajat poistetaan tästä siirtotapahtumasta.",
|
||||
"details_adv_full": "Käytä koko saldo",
|
||||
"details_adv_full_sure": "Haluatko varmasti käyttää lompakon koko saldon tähän siirtotapahtumaan?",
|
||||
"details_adv_import": "Tuo Siirtotapahtuma",
|
||||
"details_amount_field_is_not_valid": "Määrä ei kelpaa",
|
||||
"details_amount_field_is_less_than_minimum_amount_sat": "Määritetty määrä on liian pieni. Anna summa, joka on yli 500 sats. ",
|
||||
"details_amount_field_is_less_than_minimum_amount_sat": "Määritetty määrä on liian pieni. Anna summa, joka on yli 500 sattia. ",
|
||||
"details_create": "Luo Lasku",
|
||||
"details_error_decode": "Bitcoin-osoitetta ei voida dekoodata ",
|
||||
"details_fee_field_is_not_valid": "Siirtokulukenttä ei ole pätevä",
|
||||
@ -233,7 +232,7 @@
|
||||
},
|
||||
"settings": {
|
||||
"about": "Tietoa",
|
||||
"about_awesome": "Mahtavasti rakennettu",
|
||||
"about_awesome": "Loistavasti rakennettu",
|
||||
"about_backup": "Varmuuskopioi aina avaimesi!",
|
||||
"about_free": "BlueWallet on ilmainen ja avoimen lähdekoodin projekti. Bitcoin käyttäjien tekemä.",
|
||||
"about_license": "MIT-lisenssi",
|
||||
@ -288,8 +287,8 @@
|
||||
"encrypt_use": "Käytä {type}",
|
||||
"encrypt_use_expl": "{type} käytetään henkilöllisyytesi vahvistamiseen ennen siirtotapahtuman tekemistä, lompakon lukituksen avaamista, vientiä tai poistamista. {type} ei käytetä salatun tallennustilan lukituksen avaamiseen.",
|
||||
"general": "Yleinen",
|
||||
"general_adv_mode": "Kehittynyt tila",
|
||||
"general_adv_mode_e": "Kun tämä asetus on käytössä, näet lisäasetukset, kuten erilaiset lompakkotyypit, kyvyn määrittää LNDHub-instanssi, johon haluat muodostaa yhteyden, ja mukautetun entropian lompakon luomisen aikana.",
|
||||
"general_adv_mode": "Lisäasetukset",
|
||||
"general_adv_mode_e": "Kun tämä asetus on käytössä, näet lisäasetukset, kuten erilaiset lompakkotyypit, kyvyn määrittää LNDHub-instanssi, johon haluat muodostaa yhteyden ja mukautetun entropian lompakon luomisen aikana.",
|
||||
"general_continuity": "Jatkuvuus",
|
||||
"general_continuity_e": "Kun tämä asetus on käytössä, voit tarkastella valittuja lompakoita ja siirtotapahtumia muilla Apple iCloud -laitteilla.",
|
||||
"groundcontrol_explanation": "GroundControl on ilmainen avoimen lähdekoodin push-ilmoituspalvelin bitcoin-lompakoille. Voit asentaa oman GroundControl-palvelimen ja laittaa sen URL-osoitteen tähän, jotta et luota BlueWallet-infrastruktuuriin. Jätä tyhjäksi käyttääksesi oletusasetusta",
|
||||
@ -430,10 +429,10 @@
|
||||
"list_create_a_wallet": "Lisää lompakko",
|
||||
"list_create_a_wallet_text": "Se on ilmainen ja voit luoda\nniin monta kuin haluat",
|
||||
"list_empty_txs1": "Siirtotapahtumasi näkyvät tässä,",
|
||||
"list_empty_txs1_lightning": "Lightning-lompakkoa tulisi käyttää päivittäisiin siirtotapahtumiin. Siirtokulut ovat kohtuuttoman halpoja ja nopeus on liekehtivän kova.",
|
||||
"list_empty_txs1_lightning": "Lightning-lompakkoa voit käyttää päivittäisiin siirtoihin. Siirtokulut ovat kohtuuttoman halvat ja se toimii todella nopeasti.",
|
||||
"list_empty_txs2": "Aloita lompakostasi. ",
|
||||
"list_empty_txs2_lightning": "Aloita sen käyttäminen napsauttamalla \"hallinnoi varoja\" ja lisää saldoasi.\n",
|
||||
"list_header": "Lompakko edustaa avainparia, yhtä yksityistä ja yhtä, jonka voit jakaa vastaanottaaksesi kolikoita.",
|
||||
"list_empty_txs2_lightning": "Aloita lompakon käyttäminen napsauttamalla \"hallinnoi varoja\" ja lisää saldoasi.\n",
|
||||
"list_header": "Lompakko edustaa avainparia, yhtä yksityistä ja yhtä, jonka voit jakaa vastaanottaaksesi varoja.",
|
||||
"list_import_error": "Tämän lompakon tuomisessa tapahtui virhe.",
|
||||
"list_import_problem": "Tämän lompakon tuomisessa oli ongelma",
|
||||
"list_latest_transaction": "viimeisin siirto",
|
||||
@ -462,11 +461,11 @@
|
||||
"xpub_title": "lompakon XPUB"
|
||||
},
|
||||
"multisig": {
|
||||
"multisig_vault": "Holvi",
|
||||
"multisig_vault": "Vault",
|
||||
"default_label": "Multisig Vault",
|
||||
"multisig_vault_explain": "Paras turvallisuus suurille summille",
|
||||
"provide_signature": "Toimita allekirjoitus",
|
||||
"vault_key": "Holvi avain {number}",
|
||||
"vault_key": "Vault-avain {number}",
|
||||
"required_keys_out_of_total": "Vaaditut avaimet kokonaismäärästä",
|
||||
"fee": "Siirtokulu: {number}",
|
||||
"fee_btc": "{number} BTC",
|
||||
@ -488,12 +487,12 @@
|
||||
"wrapped_segwit_title": "Paras yhteensopivuus",
|
||||
"legacy_title": "Perintö",
|
||||
"co_sign_transaction": "Allekirjoita siirtotapahtuma",
|
||||
"what_is_vault": "Holvi on a",
|
||||
"what_is_vault": "Vault on",
|
||||
"what_is_vault_numberOfWallets": "{m} {n} multisig",
|
||||
"what_is_vault_wallet": "lompakko",
|
||||
"vault_advanced_customize": "Holvin Asetukset...",
|
||||
"vault_advanced_customize": "Vault-asetukset...",
|
||||
"needs": "Tarpeet",
|
||||
"what_is_vault_description_number_of_vault_keys": "{m} holvin avaimet",
|
||||
"what_is_vault_description_number_of_vault_keys": "{m} vault-avaimet",
|
||||
"what_is_vault_description_to_spend": "kuluttaa ja kolmas sinulle\nvoidaan käyttää varmuuskopiona.",
|
||||
"what_is_vault_description_to_spend_other": "kuluttaa.",
|
||||
"quorum": "{m} {n} quorum",
|
||||
@ -510,9 +509,9 @@
|
||||
"i_have_mnemonics": "Minulla on siemen tälle avaimelle...",
|
||||
"please_write_down_mnemonics": "Kirjoita tämä muistilauseke paperille. Älä huoli, voit kirjoittaa sen myöhemmin.",
|
||||
"i_wrote_it_down": "Ok, kirjoitin sen ylös",
|
||||
"type_your_mnemonics": "Lisää siemen tuodaksesi nykyisen holviavaimesi",
|
||||
"type_your_mnemonics": "Lisää siemen tuodaksesi Vault-avaimesi",
|
||||
"this_is_cosigners_xpub": "Tämä on allekirjoittajan xpub, joka on valmis tuotavaksi toiseen lompakkoon. On turvallista jakaa se.",
|
||||
"wallet_key_created": "Holviavaimesi luotiin. Käytä hetki muistisiemenesi turvalliseen varmuuskopioimiseen",
|
||||
"wallet_key_created": "Vault-avaimesi luotiin. Käytä hetki muistisanojen turvalliseen varmuuskopioimiseen",
|
||||
"are_you_sure_seed_will_be_lost": "Oletko varma? Muistisiemenesi menetetään, jos sinulla ei ole varmuuskopiota",
|
||||
"forget_this_seed": "Unohda tämä siemen ja käytä XPUB:ia",
|
||||
"invalid_fingerprint": "Tämän siemenen sormenjälki ei vastaa tämän allekirjoittajan sormenjälkeä",
|
||||
@ -524,18 +523,18 @@
|
||||
"input_path": "Syöte johtamisen polku",
|
||||
"input_path_explain": "ohita käyttääksesi oletusarvoa ({default})",
|
||||
"ms_help": "Apu",
|
||||
"ms_help_title": "Kuinka Multisig Vaults toimii. Vinkkejä",
|
||||
"ms_help_title": "Kuinka Multisig Vault toimii. Vinkit ja neuvot.",
|
||||
"ms_help_text": "Lompakko, jossa on useita avaimia, turvallisuuden eksponentiaaliseen parantamiseen tai jaettuun säilöön.",
|
||||
"ms_help_title1": "Useita laitteita suositellaan",
|
||||
"ms_help_1": "Vault toimii muiden BlueWallet-sovellusten ja PSBT-yhteensopivien lompakoiden kanssa, kuten Electrum, Spectre, Coldcard, Cobo vault jne.",
|
||||
"ms_help_title2": "Avainten Muokkaus",
|
||||
"ms_help_2": "Voit luoda kaikki Vault-avaimet tälle laitteelle ja poistaa tai muokata niitä myöhemmin. Pitämällä kaikki avaimet samalla laitteella on vastaavanlainen suojaus kuin tavallisella Bitcoin-lompakolla.",
|
||||
"ms_help_title3": "Vault Varmuuskopiot",
|
||||
"ms_help_title3": "Vault-varmuuskopiot",
|
||||
"ms_help_3": "Lompakon vaihtoehdoista löydät Vault-varmuuskopion ja vain-lukuoikeus varmuuskopion. Tämä varmuuskopio on kuin kartta lompakkoosi. Se on välttämätöntä lompakon palauttamiseksi, jos menetät yhden siemenistäsi.",
|
||||
"ms_help_title4": "Tuodaan Vaults",
|
||||
"ms_help_4": "Voit tuoda Multisig:in käyttämällä multisig-varmuuskopiotiedostoa ja käyttämällä tuontiominaisuutta. Jos sinulla on vain laajennettuja avaimia ja siemeniä, voit käyttää yksittäisiä tuontikenttiä Lisää Vault -kulkuun.",
|
||||
"ms_help_title4": "Tuodaan Vault:ia",
|
||||
"ms_help_4": "Voit tuoda multisig:in käyttämällä varmuuskopiotiedostoasi ja Tuo-ominaisuutta. Jos sinulla on vain laajennettuja avaimia ja siemensanoja, voit käyttää yksittäistä Tuo-näppäintä, kun luot Vault -avaimia.",
|
||||
"ms_help_title5": "Lisäasetukset",
|
||||
"ms_help_5": "Oletuksena BlueWallet luo 2/3 Vaultin. Jos haluat luoda erilaisen päätösvallan tai muuttaa osoitetyyppiä, aktivoi lisäasetukset Asetuksissa."
|
||||
"ms_help_5": "Oletuksena BlueWallet luo 2/3 Vaultin. Jos haluat luoda erilaisen päätösvallan tai muuttaa osoitetyyppiä, aktivoi Lisäasetukset Asetuksista."
|
||||
},
|
||||
"is_it_my_address": {
|
||||
"title": "Onko se osoitteeni?",
|
||||
@ -560,6 +559,6 @@
|
||||
"BTC": "BTC",
|
||||
"MAX": "MAX",
|
||||
"sat_byte": "sat/bitti",
|
||||
"sats": "sats"
|
||||
"sats": "sattia"
|
||||
}
|
||||
}
|
||||
|
58
package-lock.json
generated
58
package-lock.json
generated
@ -5744,11 +5744,11 @@
|
||||
"integrity": "sha512-8IeHfDwJ9/CTUwFs6x90VlobV3BfuPgNLjTgC6dRZovfCWigaZwVNIFFJnHBakK3pW2xErAPwhdvNR4JeNoYbw=="
|
||||
},
|
||||
"@react-navigation/core": {
|
||||
"version": "5.15.1",
|
||||
"resolved": "https://registry.npmjs.org/@react-navigation/core/-/core-5.15.1.tgz",
|
||||
"integrity": "sha512-GDCpIVQd0NgHYCSdUMY69hrpeWKuYgj5SIRqHI2sYh9OguwGcV52ZZOafc+pQuyfuiLLIMidw34jiqb47QrlhA==",
|
||||
"version": "5.15.2",
|
||||
"resolved": "https://registry.npmjs.org/@react-navigation/core/-/core-5.15.2.tgz",
|
||||
"integrity": "sha512-jNSP0FMu1N6Pa1Slsy8b/JbmlTAXcVeXVwnxrEMVGWeiNqUVYl+tx1FuQAqi3q1m4cg9ygXkGsgLgRmnXAEC8g==",
|
||||
"requires": {
|
||||
"@react-navigation/routers": "^5.7.1",
|
||||
"@react-navigation/routers": "^5.7.2",
|
||||
"escape-string-regexp": "^4.0.0",
|
||||
"nanoid": "^3.1.15",
|
||||
"query-string": "^6.13.6",
|
||||
@ -5792,11 +5792,11 @@
|
||||
}
|
||||
},
|
||||
"@react-navigation/native": {
|
||||
"version": "5.9.2",
|
||||
"resolved": "https://registry.npmjs.org/@react-navigation/native/-/native-5.9.2.tgz",
|
||||
"integrity": "sha512-O8K+Lr6Vy25gTTyXAns9BVyFvwTkKqfFH0RpOimilYndUL6tlhV56oDSp7Hryjy8xsjx6ESWqr6eIu4sS3Z9nQ==",
|
||||
"version": "5.9.3",
|
||||
"resolved": "https://registry.npmjs.org/@react-navigation/native/-/native-5.9.3.tgz",
|
||||
"integrity": "sha512-xaRlCDRVuFGxHsP/IetwLdNvLJwIJBYCUIx/ufWs6QkT9Q0EB0DtKzXCItuHydjMEVPd1Cy7lfjUlSM6hZ6Q3Q==",
|
||||
"requires": {
|
||||
"@react-navigation/core": "^5.15.1",
|
||||
"@react-navigation/core": "^5.15.2",
|
||||
"escape-string-regexp": "^4.0.0",
|
||||
"nanoid": "^3.1.15"
|
||||
},
|
||||
@ -5809,9 +5809,9 @@
|
||||
}
|
||||
},
|
||||
"@react-navigation/routers": {
|
||||
"version": "5.7.1",
|
||||
"resolved": "https://registry.npmjs.org/@react-navigation/routers/-/routers-5.7.1.tgz",
|
||||
"integrity": "sha512-M5R4AFgJZ0uBUV+DjMyNy2HXRfvo0ldM+59Gj1NQWXaYnst3m0xJTfWiln94mnrbrHEq087gMP4ZLHGIJ8D1Ig==",
|
||||
"version": "5.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@react-navigation/routers/-/routers-5.7.2.tgz",
|
||||
"integrity": "sha512-BxNSMLHpU+oS37Xok0ql6rc9U7IC8aUD4+U5ZPbjDJ0pwzZxGGh0YOEBzfV4k/Ig3cbPdvVWbc1C9HHbCVr2oQ==",
|
||||
"requires": {
|
||||
"nanoid": "^3.1.15"
|
||||
}
|
||||
@ -16767,9 +16767,9 @@
|
||||
"integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw=="
|
||||
},
|
||||
"nanoid": {
|
||||
"version": "3.1.20",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz",
|
||||
"integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw=="
|
||||
"version": "3.1.22",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.22.tgz",
|
||||
"integrity": "sha512-/2ZUaJX2ANuLtTvqTlgqBQNJoQO398KyJgZloL0PZkC0dpysjncRUPsFe3DUPzz/y3h+u7C46np8RMuvF3jsSQ=="
|
||||
},
|
||||
"nanomatch": {
|
||||
"version": "1.2.13",
|
||||
@ -17889,9 +17889,9 @@
|
||||
"integrity": "sha512-A1kFqHekCTM7cz0udomYUoYNWjBebHm/5wzU/XqrBRBNWectVH0QIiN+NEcZ0Dte5hvzHwbr8+XQmguPhJ6WdQ=="
|
||||
},
|
||||
"query-string": {
|
||||
"version": "6.14.0",
|
||||
"resolved": "https://registry.npmjs.org/query-string/-/query-string-6.14.0.tgz",
|
||||
"integrity": "sha512-In3o+lUxlgejoVJgwEdYtdxrmlL0cQWJXj0+kkI7RWVo7hg5AhFtybeKlC9Dpgbr8eOC4ydpEh8017WwyfzqVQ==",
|
||||
"version": "6.14.1",
|
||||
"resolved": "https://registry.npmjs.org/query-string/-/query-string-6.14.1.tgz",
|
||||
"integrity": "sha512-XDxAeVmpfu1/6IjyT/gXHOl+S0vQ9owggJ30hhWKdHAsNPOcasn5o9BW0eejZqL2e4vMjhAxoW3jVHcD6mbcYw==",
|
||||
"requires": {
|
||||
"decode-uri-component": "^0.2.0",
|
||||
"filter-obj": "^1.1.0",
|
||||
@ -18422,9 +18422,9 @@
|
||||
"integrity": "sha512-sQDYwGEdxwKwXKP/8Intc81FyH33Rv8ZvOxdmPX4NM75RAIVeBc13pdabEqycAimNZoY5IDvGp4o1cTTa5gNrA=="
|
||||
},
|
||||
"react-native-device-info": {
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npmjs.org/react-native-device-info/-/react-native-device-info-8.0.1.tgz",
|
||||
"integrity": "sha512-5fIcrEfxsyIJ0HZ/pHd+DeYwC81wi5tupFkPSASYXz/7QhatF8W0W6qR+YlvI6gJVSFNgQKgrPrh18RGMgbZdg=="
|
||||
"version": "8.0.2",
|
||||
"resolved": "https://registry.npmjs.org/react-native-device-info/-/react-native-device-info-8.0.2.tgz",
|
||||
"integrity": "sha512-5X5sMO2N9WpnqA4BXHlby0ml0WKlHconLhgf8fCiXDELf7DIjOMX8z6iYZ7WDgmn0E/6Psubq9yb5D2Qdc30Wg=="
|
||||
},
|
||||
"react-native-document-picker": {
|
||||
"version": "git+ssh://git@github.com/BlueWallet/react-native-document-picker.git#3684d4fcc2bc0b47c32be39024e4796004c3e428",
|
||||
@ -18467,9 +18467,9 @@
|
||||
}
|
||||
},
|
||||
"react-native-gesture-handler": {
|
||||
"version": "1.10.2",
|
||||
"resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-1.10.2.tgz",
|
||||
"integrity": "sha512-j9ifSk2KX/3Lg7Yiku9URJEAJH0NZLjhE52eGHG0QZQ/oKnfcQrJY1DjHefrcNwNAjvoQp+IWkBdyoGlcT2GqA==",
|
||||
"version": "1.10.3",
|
||||
"resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-1.10.3.tgz",
|
||||
"integrity": "sha512-cBGMi1IEsIVMgoox4RvMx7V2r6bNKw0uR1Mu1o7NbuHS6BRSVLq0dP34l2ecnPlC+jpWd3le6Yg1nrdCjby2Mw==",
|
||||
"requires": {
|
||||
"@egjs/hammerjs": "^2.0.17",
|
||||
"fbjs": "^3.0.0",
|
||||
@ -18670,18 +18670,18 @@
|
||||
}
|
||||
},
|
||||
"react-native-screens": {
|
||||
"version": "2.17.1",
|
||||
"resolved": "https://registry.npmjs.org/react-native-screens/-/react-native-screens-2.17.1.tgz",
|
||||
"integrity": "sha512-B4gD5e4csvlVwlhf+RNqjQZ9mHTwe/iL3rXondgZxnKz4oW0QAmtLnLRKOrYVxoaJaF9Fy7jhjo//24/472APQ=="
|
||||
"version": "2.18.0",
|
||||
"resolved": "https://registry.npmjs.org/react-native-screens/-/react-native-screens-2.18.0.tgz",
|
||||
"integrity": "sha512-8+lCEsxzSu55GWRw6yZpyt3OszxN1OngfBsFXdqspaEfq6uIChanzlcD2PLVQl+iN82GAcrZM800Kd1pA477ZQ=="
|
||||
},
|
||||
"react-native-secure-key-store": {
|
||||
"version": "git+ssh://git@github.com/BlueWallet/react-native-secure-key-store.git#4828fd1a67d12e4c0e21eee0bee673fde75e6f9a",
|
||||
"from": "react-native-secure-key-store@git+https://github.com/BlueWallet/react-native-secure-key-store.git#4828fd1a67d12e4c0e21eee0bee673fde75e6f9a"
|
||||
},
|
||||
"react-native-share": {
|
||||
"version": "5.1.3",
|
||||
"resolved": "https://registry.npmjs.org/react-native-share/-/react-native-share-5.1.3.tgz",
|
||||
"integrity": "sha512-d61vVz3B3qjltnC9QBOdvbOvEEIogpYtZ5LeGJ/f+Kqeu70DUoilVJ80MMzqKBcfPlJM6GPq3YyyF0qLNJ0G3w=="
|
||||
"version": "5.1.4",
|
||||
"resolved": "https://registry.npmjs.org/react-native-share/-/react-native-share-5.1.4.tgz",
|
||||
"integrity": "sha512-/eNBTuimOmzeeBbnZkwW6hbzSZvJnhfkx5cSdQkFS45KRHekD9twP6F8QHn+zJxeJGAP+EgpVCXoA7yCrgKrhQ=="
|
||||
},
|
||||
"react-native-snap-carousel": {
|
||||
"version": "3.9.1",
|
||||
|
10
package.json
10
package.json
@ -78,7 +78,7 @@
|
||||
"@react-native-community/push-notification-ios": "1.8.0",
|
||||
"@react-native-community/slider": "3.0.3",
|
||||
"@react-navigation/drawer": "5.12.4",
|
||||
"@react-navigation/native": "5.9.2",
|
||||
"@react-navigation/native": "5.9.3",
|
||||
"@react-navigation/stack": "5.14.3",
|
||||
"@remobile/react-native-qrcode-local-image": "git+https://github.com/BlueWallet/react-native-qrcode-local-image.git",
|
||||
"@sentry/react-native": "1.9.0",
|
||||
@ -128,12 +128,12 @@
|
||||
"react-native-blue-crypto": "git+https://github.com/Overtorment/react-native-blue-crypto.git",
|
||||
"react-native-camera": "3.43.0",
|
||||
"react-native-default-preference": "1.4.3",
|
||||
"react-native-device-info": "8.0.1",
|
||||
"react-native-device-info": "8.0.2",
|
||||
"react-native-document-picker": "git+https://github.com/BlueWallet/react-native-document-picker.git#3684d4fcc2bc0b47c32be39024e4796004c3e428",
|
||||
"react-native-elements": "2.3.2",
|
||||
"react-native-fingerprint-scanner": "git+https://github.com/BlueWallet/react-native-fingerprint-scanner.git#ce644673681716335d786727bab998f7e632ab5e",
|
||||
"react-native-fs": "2.16.6",
|
||||
"react-native-gesture-handler": "1.10.2",
|
||||
"react-native-gesture-handler": "1.10.3",
|
||||
"react-native-handoff": "git+https://github.com/marcosrdz/react-native-handoff.git#f5becc63f3e36bf2da1ed1fc60fc690323e73602",
|
||||
"react-native-haptic-feedback": "1.11.0",
|
||||
"react-native-idle-timer": "git+https://github.com/BlueWallet/react-native-idle-timer.git#8587876d68ab5920e79619726aeca9e672beaf2b",
|
||||
@ -157,9 +157,9 @@
|
||||
"react-native-rate": "1.2.4",
|
||||
"react-native-reanimated": "1.13.2",
|
||||
"react-native-safe-area-context": "3.1.9",
|
||||
"react-native-screens": "2.17.1",
|
||||
"react-native-screens": "2.18.0",
|
||||
"react-native-secure-key-store": "git+https://github.com/BlueWallet/react-native-secure-key-store.git#4828fd1a67d12e4c0e21eee0bee673fde75e6f9a",
|
||||
"react-native-share": "5.1.3",
|
||||
"react-native-share": "5.1.4",
|
||||
"react-native-snap-carousel": "3.9.1",
|
||||
"react-native-sortable-list": "0.0.24",
|
||||
"react-native-svg": "12.1.0",
|
||||
|
@ -51,7 +51,7 @@ const LNDViewAdditionalInvoiceInformation = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<SafeBlueArea style={[styles.root, stylesHook.root]}>
|
||||
<SafeBlueArea style={stylesHook.root}>
|
||||
<View style={styles.wrapper}>
|
||||
<View style={styles.qrcode}>
|
||||
<QRCode
|
||||
@ -89,13 +89,9 @@ const LNDViewAdditionalInvoiceInformation = () => {
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
loading: {
|
||||
flex: 1,
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
},
|
||||
root: {
|
||||
flex: 1,
|
||||
},
|
||||
wrapper: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
|
@ -18,7 +18,7 @@ const LNDViewAdditionalInvoicePreImage = () => {
|
||||
});
|
||||
|
||||
return (
|
||||
<SafeBlueArea style={[styles.root, stylesHook.root]}>
|
||||
<SafeBlueArea style={stylesHook.root}>
|
||||
<View style={styles.wrapper}>
|
||||
<BlueTextCentered>{loc.lndViewInvoice.preimage}:</BlueTextCentered>
|
||||
<BlueSpacing20 />
|
||||
@ -41,9 +41,6 @@ const LNDViewAdditionalInvoicePreImage = () => {
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
root: {
|
||||
flex: 1,
|
||||
},
|
||||
wrapper: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
|
@ -278,7 +278,7 @@ const LNDViewInvoice = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<SafeBlueArea styles={[styles.root, stylesHook.root]} onLayout={onLayout}>
|
||||
<SafeBlueArea onLayout={onLayout}>
|
||||
<StatusBar barStyle="default" />
|
||||
<ScrollView>{render()}</ScrollView>
|
||||
</SafeBlueArea>
|
||||
|
@ -157,7 +157,7 @@ export default class LnurlPay extends Component {
|
||||
|
||||
renderGotPayload() {
|
||||
return (
|
||||
<SafeBlueArea style={styles.root}>
|
||||
<SafeBlueArea>
|
||||
<ScrollView>
|
||||
<BlueCard>
|
||||
<AmountInput
|
||||
|
@ -163,8 +163,7 @@ const styles = StyleSheet.create({
|
||||
alignSelf: 'center',
|
||||
},
|
||||
root: {
|
||||
flex: 1,
|
||||
paddingTop: 0,
|
||||
padding: 0,
|
||||
},
|
||||
iconContainer: {
|
||||
backgroundColor: '#ccddf9',
|
||||
|
@ -285,7 +285,7 @@ const ScanLndInvoice = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={[styles.root, stylesHook.root]}>
|
||||
<SafeBlueArea style={stylesHook.root}>
|
||||
<StatusBar barStyle="light-content" />
|
||||
<View style={[styles.root, stylesHook.root]}>
|
||||
<ScrollView contentContainerStyle={styles.scroll}>
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* global alert */
|
||||
import React, { useContext, useState } from 'react';
|
||||
import { ScrollView, StyleSheet } from 'react-native';
|
||||
import { useNavigation, useTheme } from '@react-navigation/native';
|
||||
import { ScrollView } from 'react-native';
|
||||
import { useNavigation } from '@react-navigation/native';
|
||||
import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
|
||||
|
||||
import navigationStyle from '../components/navigationStyle';
|
||||
@ -10,22 +10,10 @@ import loc from '../loc';
|
||||
import { BlueStorageContext } from '../blue_modules/storage-context';
|
||||
const prompt = require('../blue_modules/prompt');
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
root: {
|
||||
flex: 1,
|
||||
},
|
||||
});
|
||||
|
||||
const PlausibleDeniability = () => {
|
||||
const { cachedPassword, isPasswordInUse, createFakeStorage, resetWallets } = useContext(BlueStorageContext);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const { popToTop } = useNavigation();
|
||||
const { colors } = useTheme();
|
||||
const stylesHook = StyleSheet.create({
|
||||
root: {
|
||||
backgroundColor: colors.background,
|
||||
},
|
||||
});
|
||||
|
||||
const handleOnCreateFakeStorageButtonPressed = async () => {
|
||||
setIsLoading(true);
|
||||
@ -59,11 +47,11 @@ const PlausibleDeniability = () => {
|
||||
};
|
||||
|
||||
return isLoading ? (
|
||||
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={[styles.root, stylesHook.root]}>
|
||||
<SafeBlueArea>
|
||||
<BlueLoading />
|
||||
</SafeBlueArea>
|
||||
) : (
|
||||
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={[styles.root, stylesHook.root]}>
|
||||
<SafeBlueArea>
|
||||
<BlueCard>
|
||||
<ScrollView maxHeight={450}>
|
||||
<BlueText>{loc.plausibledeniability.help}</BlueText>
|
||||
|
@ -6,17 +6,12 @@ import loc from '../loc';
|
||||
import { BlueSpacing20, SafeBlueArea, BlueCard, BlueText, BlueLoading } from '../BlueComponents';
|
||||
import navigationStyle from '../components/navigationStyle';
|
||||
import { SegwitP2SHWallet, LegacyWallet, HDSegwitP2SHWallet, HDSegwitBech32Wallet, HDAezeedWallet } from '../class';
|
||||
import { BlueCurrentTheme } from '../components/themes';
|
||||
const bitcoin = require('bitcoinjs-lib');
|
||||
const BlueCrypto = require('react-native-blue-crypto');
|
||||
const encryption = require('../blue_modules/encryption');
|
||||
const BlueElectrum = require('../blue_modules/BlueElectrum');
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
root: {
|
||||
flex: 1,
|
||||
backgroundColor: BlueCurrentTheme.colors.background,
|
||||
},
|
||||
center: {
|
||||
alignItems: 'center',
|
||||
},
|
||||
@ -226,7 +221,7 @@ export default class Selftest extends Component {
|
||||
}
|
||||
|
||||
return (
|
||||
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.root}>
|
||||
<SafeBlueArea>
|
||||
<BlueCard>
|
||||
<ScrollView>
|
||||
<BlueSpacing20 />
|
||||
|
@ -315,17 +315,9 @@ const ScanQRCode = () => {
|
||||
testID="scanQrBackdoorOkButton"
|
||||
onPress={() => {
|
||||
setBackdoorVisible(false);
|
||||
let data;
|
||||
try {
|
||||
data = JSON.parse(backdoorText);
|
||||
// this might be a json string (for convenience - in case there are "\n" in there)
|
||||
} catch (_) {
|
||||
data = backdoorText;
|
||||
} finally {
|
||||
setBackdoorText('');
|
||||
}
|
||||
setBackdoorText('');
|
||||
|
||||
if (data) onBarCodeRead({ data });
|
||||
if (backdoorText) onBarCodeRead({ data: backdoorText });
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
|
@ -116,7 +116,7 @@ const Broadcast = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<SafeBlueArea style={styles.blueArea}>
|
||||
<SafeBlueArea>
|
||||
<KeyboardAvoidingView
|
||||
enabled={!Platform.isPad}
|
||||
behavior={Platform.OS === 'ios' ? 'position' : null}
|
||||
@ -176,9 +176,6 @@ const styles = StyleSheet.create({
|
||||
alignItems: 'center',
|
||||
justifyContent: 'flex-start',
|
||||
},
|
||||
blueArea: {
|
||||
flex: 1,
|
||||
},
|
||||
broadcastResultWrapper: {
|
||||
flex: 1,
|
||||
flexDirection: 'column',
|
||||
|
@ -388,7 +388,7 @@ const CoinControl = () => {
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<SafeBlueArea style={[styles.root, styles.center, { backgroundColor: colors.elevated }]}>
|
||||
<SafeBlueArea style={[styles.center, { backgroundColor: colors.elevated }]}>
|
||||
<ActivityIndicator testID="Loading" />
|
||||
</SafeBlueArea>
|
||||
);
|
||||
|
@ -174,7 +174,7 @@ export default class Confirm extends Component {
|
||||
/>
|
||||
<View style={styles.cardContainer}>
|
||||
<BlueCard>
|
||||
<Text style={styles.cardText}>
|
||||
<Text style={styles.cardText} testID="TransactionFee">
|
||||
{loc.send.create_fee}: {formatBalance(this.state.feeSatoshi, BitcoinUnit.BTC)} (
|
||||
{currency.satoshiToLocalCurrency(this.state.feeSatoshi)})
|
||||
</Text>
|
||||
@ -269,7 +269,6 @@ const styles = StyleSheet.create({
|
||||
margin: 16,
|
||||
},
|
||||
root: {
|
||||
flex: 1,
|
||||
paddingTop: 19,
|
||||
backgroundColor: BlueCurrentTheme.colors.elevated,
|
||||
},
|
||||
|
@ -210,7 +210,6 @@ const styles = StyleSheet.create({
|
||||
marginVertical: 16,
|
||||
},
|
||||
root: {
|
||||
flex: 1,
|
||||
backgroundColor: BlueCurrentTheme.colors.elevated,
|
||||
},
|
||||
card: {
|
||||
|
@ -85,7 +85,7 @@ const SendDetails = () => {
|
||||
|
||||
// if cutomFee is not set, we need to choose highest possible fee for wallet balance
|
||||
// if there are no funds for even Slow option, use 1 sat/byte fee
|
||||
const fee = useMemo(() => {
|
||||
const feeRate = useMemo(() => {
|
||||
if (customFee) return customFee;
|
||||
if (feePrecalc.slowFee === null) return '1'; // wait for precalculated fees
|
||||
let initialFee;
|
||||
@ -133,15 +133,11 @@ const SendDetails = () => {
|
||||
setAmountUnit(wallet.preferredBalanceUnit); // default for whole screen
|
||||
|
||||
// decode route params
|
||||
const addresses = [];
|
||||
let initialMemo = '';
|
||||
if (routeParams.uri) {
|
||||
try {
|
||||
const { address, amount, memo, payjoinUrl } = DeeplinkSchemaMatch.decodeBitcoinUri(routeParams.uri);
|
||||
addresses.push({ address, amount, amountSats: currency.btcToSatoshi(amount), key: String(Math.random()) });
|
||||
initialMemo = memo;
|
||||
setAddresses(addresses);
|
||||
setMemo(initialMemo);
|
||||
const { address, amount, memo: initialMemo, payjoinUrl } = DeeplinkSchemaMatch.decodeBitcoinUri(routeParams.uri);
|
||||
setAddresses([{ address, amount, amountSats: currency.btcToSatoshi(amount), key: String(Math.random()) }]);
|
||||
setMemo(initialMemo || '');
|
||||
setAmountUnit(BitcoinUnit.BTC);
|
||||
setPayjoinUrl(payjoinUrl);
|
||||
} catch (error) {
|
||||
@ -149,13 +145,11 @@ const SendDetails = () => {
|
||||
Alert.alert(loc.errors.error, loc.send.details_error_decode);
|
||||
}
|
||||
} else if (routeParams.address) {
|
||||
addresses.push({ address: routeParams.address, key: String(Math.random()) });
|
||||
if (routeParams.memo) initialMemo = routeParams.memo;
|
||||
setAddresses(addresses);
|
||||
setMemo(initialMemo);
|
||||
setAddresses([{ address: routeParams.address, key: String(Math.random()) }]);
|
||||
setMemo(routeParams.memo || '');
|
||||
setAmountUnit(BitcoinUnit.BTC);
|
||||
} else {
|
||||
setAddresses([{ address: '', key: String(Math.random()) }]);
|
||||
setAddresses([{ address: '', key: String(Math.random()) }]); // key is for the FlatList
|
||||
}
|
||||
|
||||
// we are ready!
|
||||
@ -212,7 +206,7 @@ const SendDetails = () => {
|
||||
if (!wallet) return; // wait for it
|
||||
const fees = networkTransactionFees;
|
||||
const changeAddress = getChangeAddressFast();
|
||||
const requestedSatPerByte = Number(fee);
|
||||
const requestedSatPerByte = Number(feeRate);
|
||||
const lutxo = utxo || wallet.getUtxo();
|
||||
|
||||
const options = [
|
||||
@ -279,7 +273,7 @@ const SendDetails = () => {
|
||||
}
|
||||
|
||||
setFeePrecalc(newFeePrecalc);
|
||||
}, [wallet, networkTransactionFees, utxo, addresses, fee, dumb]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
}, [wallet, networkTransactionFees, utxo, addresses, feeRate, dumb]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
const getChangeAddressFast = () => {
|
||||
if (changeAddress) return changeAddress; // cache
|
||||
@ -340,14 +334,16 @@ const SendDetails = () => {
|
||||
return Alert.alert(loc.errors.error, loc.send.details_address_field_is_not_valid);
|
||||
}
|
||||
|
||||
const recipients = [...addresses];
|
||||
const unitsCopy = [...units];
|
||||
const dataWithoutSchema = data.replace('bitcoin:', '').replace('BITCOIN:', '');
|
||||
if (wallet.isAddressValid(dataWithoutSchema)) {
|
||||
recipients[scrollIndex.current].address = dataWithoutSchema;
|
||||
unitsCopy[scrollIndex.current] = amountUnit;
|
||||
setAddresses(recipients);
|
||||
setUnits(unitsCopy);
|
||||
setAddresses(addresses => {
|
||||
addresses[scrollIndex.current].address = dataWithoutSchema;
|
||||
return [...addresses];
|
||||
});
|
||||
setUnits(units => {
|
||||
units[scrollIndex.current] = amountUnit;
|
||||
return [...units];
|
||||
});
|
||||
setIsLoading(false);
|
||||
return;
|
||||
}
|
||||
@ -369,13 +365,17 @@ const SendDetails = () => {
|
||||
|
||||
console.log('options', options);
|
||||
if (btcAddressRx.test(address) || address.startsWith('bc1') || address.startsWith('BC1')) {
|
||||
unitsCopy[scrollIndex.current] = BitcoinUnit.BTC; // also resetting current unit to BTC
|
||||
recipients[scrollIndex.current].address = address;
|
||||
recipients[scrollIndex.current].amount = options.amount;
|
||||
recipients[scrollIndex.current].amountSats = new BigNumber(options.amount).multipliedBy(100000000).toNumber();
|
||||
setAddresses(recipients);
|
||||
setAddresses(addresses => {
|
||||
addresses[scrollIndex.current].address = address;
|
||||
addresses[scrollIndex.current].amount = options.amount;
|
||||
addresses[scrollIndex.current].amountSats = new BigNumber(options.amount).multipliedBy(100000000).toNumber();
|
||||
return [...addresses];
|
||||
});
|
||||
setUnits(units => {
|
||||
units[scrollIndex.current] = BitcoinUnit.BTC; // also resetting current unit to BTC
|
||||
return [...units];
|
||||
});
|
||||
setMemo(options.label || options.message);
|
||||
setUnits(unitsCopy);
|
||||
setAmountUnit(BitcoinUnit.BTC);
|
||||
setPayjoinUrl(options.pj || '');
|
||||
}
|
||||
@ -386,7 +386,7 @@ const SendDetails = () => {
|
||||
const createTransaction = async () => {
|
||||
Keyboard.dismiss();
|
||||
setIsLoading(true);
|
||||
const requestedSatPerByte = fee;
|
||||
const requestedSatPerByte = feeRate;
|
||||
for (const [index, transaction] of addresses.entries()) {
|
||||
let error;
|
||||
if (!transaction.amount || transaction.amount < 0 || parseFloat(transaction.amount) === 0) {
|
||||
@ -444,16 +444,16 @@ const SendDetails = () => {
|
||||
|
||||
const createPsbtTransaction = async () => {
|
||||
const changeAddress = await getChangeAddressAsync();
|
||||
const requestedSatPerByte = Number(fee);
|
||||
const requestedSatPerByte = Number(feeRate);
|
||||
const lutxo = utxo || wallet.getUtxo();
|
||||
console.log({ requestedSatPerByte, utxo });
|
||||
|
||||
let targets = [];
|
||||
const targets = [];
|
||||
for (const transaction of addresses) {
|
||||
if (transaction.amount === BitcoinUnit.MAX) {
|
||||
// single output with MAX
|
||||
targets = [{ address: transaction.address }];
|
||||
break;
|
||||
// output with MAX
|
||||
targets.push({ address: transaction.address });
|
||||
continue;
|
||||
}
|
||||
const value = parseInt(transaction.amountSats);
|
||||
if (value > 0) {
|
||||
@ -465,7 +465,7 @@ const SendDetails = () => {
|
||||
}
|
||||
}
|
||||
|
||||
const { tx, outputs, psbt } = wallet.createTransaction(
|
||||
const { tx, outputs, psbt, fee } = wallet.createTransaction(
|
||||
lutxo,
|
||||
targets,
|
||||
requestedSatPerByte,
|
||||
@ -531,14 +531,16 @@ const SendDetails = () => {
|
||||
[
|
||||
{
|
||||
text: loc._.ok,
|
||||
onPress: async () => {
|
||||
const firstTransaction =
|
||||
addresses.find(element => {
|
||||
const feeSatoshi = new BigNumber(element.amount).multipliedBy(100000000);
|
||||
return element.address.length > 0 && feeSatoshi > 0;
|
||||
}) || addresses[0];
|
||||
onPress: () => {
|
||||
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
|
||||
setAddresses([firstTransaction]);
|
||||
setAddresses(addresses => {
|
||||
const firstTransaction =
|
||||
addresses.find(element => {
|
||||
const feeSatoshi = new BigNumber(element.amount).multipliedBy(100000000);
|
||||
return element.address.length > 0 && feeSatoshi > 0;
|
||||
}) || addresses[0];
|
||||
return [firstTransaction];
|
||||
});
|
||||
changeWallet();
|
||||
},
|
||||
style: 'default',
|
||||
@ -547,7 +549,10 @@ const SendDetails = () => {
|
||||
],
|
||||
{ cancelable: false },
|
||||
);
|
||||
} else if (addresses.some(element => element.amount === BitcoinUnit.MAX) && !wallet.allowSendMax()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (addresses.some(element => element.amount === BitcoinUnit.MAX) && !wallet.allowSendMax()) {
|
||||
ReactNativeHapticFeedback.trigger('notificationWarning');
|
||||
Alert.alert(
|
||||
loc.send.details_wallet_selection,
|
||||
@ -555,11 +560,13 @@ const SendDetails = () => {
|
||||
[
|
||||
{
|
||||
text: loc._.ok,
|
||||
onPress: async () => {
|
||||
const firstTransaction = addresses.find(element => element.amount === BitcoinUnit.MAX) || addresses[0];
|
||||
firstTransaction.amount = 0;
|
||||
onPress: () => {
|
||||
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
|
||||
setAddresses([firstTransaction]);
|
||||
setAddresses(addresses => {
|
||||
const firstTransaction = addresses.find(element => element.amount === BitcoinUnit.MAX) || addresses[0];
|
||||
firstTransaction.amount = 0;
|
||||
return [firstTransaction];
|
||||
});
|
||||
changeWallet();
|
||||
},
|
||||
style: 'default',
|
||||
@ -568,9 +575,10 @@ const SendDetails = () => {
|
||||
],
|
||||
{ cancelable: false },
|
||||
);
|
||||
} else {
|
||||
changeWallet();
|
||||
return;
|
||||
}
|
||||
|
||||
changeWallet();
|
||||
};
|
||||
|
||||
/**
|
||||
@ -757,9 +765,8 @@ const SendDetails = () => {
|
||||
};
|
||||
|
||||
const handleAddRecipient = async () => {
|
||||
addresses.push({ address: '', key: String(Math.random()) }); // key is for the FlatList
|
||||
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut, () => scrollView.current.scrollToEnd());
|
||||
setAddresses([...addresses]);
|
||||
setAddresses(addresses => [...addresses, { address: '', key: String(Math.random()) }]);
|
||||
setOptionsVisible(false);
|
||||
scrollView.current.scrollToEnd();
|
||||
if (addresses.length === 0) return;
|
||||
@ -769,9 +776,11 @@ const SendDetails = () => {
|
||||
|
||||
const handleRemoveRecipient = async () => {
|
||||
const last = scrollIndex.current === addresses.length - 1;
|
||||
addresses.splice(scrollIndex.current, 1);
|
||||
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
|
||||
setAddresses([...addresses]);
|
||||
setAddresses(addresses => {
|
||||
addresses.splice(scrollIndex.current, 1);
|
||||
return [...addresses];
|
||||
});
|
||||
setOptionsVisible(false);
|
||||
if (addresses.length === 0) return;
|
||||
await sleep(200); // wait for animation
|
||||
@ -858,18 +867,22 @@ const SendDetails = () => {
|
||||
ReactNativeHapticFeedback.trigger('notificationWarning');
|
||||
Alert.alert(
|
||||
loc.send.details_adv_full,
|
||||
loc.send.details_adv_full_sure + ' ' + (addresses.length > 1 ? loc.send.details_adv_full_remove : ''),
|
||||
loc.send.details_adv_full_sure,
|
||||
[
|
||||
{
|
||||
text: loc._.ok,
|
||||
onPress: async () => {
|
||||
onPress: () => {
|
||||
Keyboard.dismiss();
|
||||
const recipient = addresses[scrollIndex.current];
|
||||
recipient.amount = BitcoinUnit.MAX;
|
||||
recipient.amountSats = BitcoinUnit.MAX;
|
||||
setAddresses(addresses => {
|
||||
addresses[scrollIndex.current].amount = BitcoinUnit.MAX;
|
||||
addresses[scrollIndex.current].amountSats = BitcoinUnit.MAX;
|
||||
return [...addresses];
|
||||
});
|
||||
setUnits(units => {
|
||||
units[scrollIndex.current] = BitcoinUnit.BTC;
|
||||
return [...units];
|
||||
});
|
||||
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
|
||||
setAddresses([recipient]);
|
||||
setUnits([BitcoinUnit.BTC]);
|
||||
setOptionsVisible(false);
|
||||
},
|
||||
style: 'default',
|
||||
@ -947,21 +960,21 @@ const SendDetails = () => {
|
||||
time: loc.send.fee_10m,
|
||||
fee: feePrecalc.fastestFee,
|
||||
rate: nf.fastestFee,
|
||||
active: Number(fee) === nf.fastestFee,
|
||||
active: Number(feeRate) === nf.fastestFee,
|
||||
},
|
||||
{
|
||||
label: loc.send.fee_medium,
|
||||
time: loc.send.fee_3h,
|
||||
fee: feePrecalc.mediumFee,
|
||||
rate: nf.mediumFee,
|
||||
active: Number(fee) === nf.mediumFee,
|
||||
active: Number(feeRate) === nf.mediumFee,
|
||||
},
|
||||
{
|
||||
label: loc.send.fee_slow,
|
||||
time: loc.send.fee_1d,
|
||||
fee: feePrecalc.slowFee,
|
||||
rate: nf.slowFee,
|
||||
active: Number(fee) === nf.slowFee,
|
||||
active: Number(feeRate) === nf.slowFee,
|
||||
},
|
||||
];
|
||||
|
||||
@ -1033,8 +1046,6 @@ const SendDetails = () => {
|
||||
};
|
||||
|
||||
const renderOptionsModal = () => {
|
||||
const isSendMaxUsed = addresses.some(element => element.amount === BitcoinUnit.MAX);
|
||||
|
||||
return (
|
||||
<BottomModal deviceWidth={width + width / 2} isVisible={optionsVisible} onClose={hideOptions}>
|
||||
<KeyboardAvoidingView enabled={!Platform.isPad} behavior={Platform.OS === 'ios' ? 'position' : null}>
|
||||
@ -1088,7 +1099,6 @@ const SendDetails = () => {
|
||||
<>
|
||||
<BlueListItem
|
||||
testID="AddRecipient"
|
||||
disabled={isSendMaxUsed}
|
||||
title={loc.send.details_add_rec_add}
|
||||
hideChevron
|
||||
component={TouchableOpacity}
|
||||
@ -1181,42 +1191,48 @@ const SendDetails = () => {
|
||||
isLoading={isLoading}
|
||||
amount={item.amount ? item.amount.toString() : null}
|
||||
onAmountUnitChange={unit => {
|
||||
units[index] = unit;
|
||||
const item = addresses[index];
|
||||
setAddresses(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 = AmountInput.getCachedSatoshis(item.amount) || currency.btcToSatoshi(currency.fiatToBTC(item.amount));
|
||||
break;
|
||||
}
|
||||
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 = AmountInput.getCachedSatoshis(item.amount) || currency.btcToSatoshi(currency.fiatToBTC(item.amount));
|
||||
break;
|
||||
}
|
||||
|
||||
addresses[index] = item;
|
||||
setUnits([...units]);
|
||||
setAddresses([...addresses]);
|
||||
addresses[index] = item;
|
||||
return [...addresses];
|
||||
});
|
||||
setUnits(units => {
|
||||
units[index] = unit;
|
||||
return [...units];
|
||||
});
|
||||
}}
|
||||
onChangeText={text => {
|
||||
item.amount = text;
|
||||
switch (units[index] || 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;
|
||||
}
|
||||
addresses[index] = item;
|
||||
setAddresses([...addresses]);
|
||||
setAddresses(addresses => {
|
||||
item.amount = text;
|
||||
switch (units[index] || 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;
|
||||
}
|
||||
addresses[index] = item;
|
||||
return [...addresses];
|
||||
});
|
||||
}}
|
||||
unit={units[index] || amountUnit}
|
||||
inputAccessoryViewID={wallet.allowSendMax() ? BlueUseAllFundsButton.InputAccessoryViewID : null}
|
||||
@ -1224,12 +1240,13 @@ const SendDetails = () => {
|
||||
<AddressInput
|
||||
onChangeText={async text => {
|
||||
text = text.trim();
|
||||
const transactions = [...addresses];
|
||||
const { address, amount, memo: lmemo, payjoinUrl } = DeeplinkSchemaMatch.decodeBitcoinUri(text);
|
||||
item.address = address || text;
|
||||
item.amount = amount || item.amount;
|
||||
transactions[index] = item;
|
||||
setAddresses(transactions);
|
||||
setAddresses(addresses => {
|
||||
item.address = address || text;
|
||||
item.amount = amount || item.amount;
|
||||
addresses[index] = item;
|
||||
return [...addresses];
|
||||
});
|
||||
setMemo(lmemo || memo);
|
||||
setIsLoading(false);
|
||||
setPayjoinUrl(payjoinUrl);
|
||||
@ -1260,6 +1277,7 @@ const SendDetails = () => {
|
||||
// if utxo is limited we use it to calculate available balance
|
||||
const balance = utxo ? utxo.reduce((prev, curr) => prev + curr.value, 0) : wallet.getBalance();
|
||||
const allBalance = formatBalanceWithoutSuffix(balance, BitcoinUnit.BTC, true);
|
||||
const isSendMaxUsed = addresses.some(element => element.amount === BitcoinUnit.MAX);
|
||||
|
||||
return (
|
||||
<TouchableWithoutFeedback onPress={Keyboard.dismiss} accessible={false}>
|
||||
@ -1305,7 +1323,7 @@ const SendDetails = () => {
|
||||
<Text style={[styles.feeLabel, stylesHook.feeLabel]}>{loc.send.create_fee}</Text>
|
||||
<View style={[styles.feeRow, stylesHook.feeRow]}>
|
||||
<Text style={stylesHook.feeValue}>
|
||||
{feePrecalc.current ? formatFee(feePrecalc.current) : fee + ' ' + loc.units.sat_byte}
|
||||
{feePrecalc.current ? formatFee(feePrecalc.current) : feeRate + ' ' + loc.units.sat_byte}
|
||||
</Text>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
@ -1318,14 +1336,14 @@ const SendDetails = () => {
|
||||
{Platform.select({
|
||||
ios: (
|
||||
<BlueUseAllFundsButton
|
||||
canUseAll={wallet.allowSendMax() && allBalance > 0}
|
||||
canUseAll={wallet.allowSendMax() && allBalance > 0 && !isSendMaxUsed}
|
||||
onUseAllPressed={onUseAllPressed}
|
||||
balance={allBalance}
|
||||
/>
|
||||
),
|
||||
android: isAmountToolbarVisibleForAndroid && (
|
||||
<BlueUseAllFundsButton
|
||||
canUseAll={wallet.allowSendMax() && allBalance > 0}
|
||||
canUseAll={wallet.allowSendMax() && allBalance > 0 && !isSendMaxUsed}
|
||||
onUseAllPressed={onUseAllPressed}
|
||||
balance={allBalance}
|
||||
/>
|
||||
|
@ -21,9 +21,6 @@ const IsItMyAddress = () => {
|
||||
const [result, setResult] = useState('');
|
||||
|
||||
const stylesHooks = StyleSheet.create({
|
||||
blueArea: {
|
||||
backgroundColor: colors.background,
|
||||
},
|
||||
text: {
|
||||
color: colors.foregroundColor,
|
||||
},
|
||||
@ -78,7 +75,7 @@ const IsItMyAddress = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<SafeBlueArea style={[styles.blueArea, stylesHooks.blueArea]}>
|
||||
<SafeBlueArea style={styles.blueArea}>
|
||||
<KeyboardAvoidingView
|
||||
enabled={!Platform.isPad}
|
||||
behavior={Platform.OS === 'ios' ? 'position' : null}
|
||||
@ -133,7 +130,6 @@ const styles = StyleSheet.create({
|
||||
justifyContent: 'flex-start',
|
||||
},
|
||||
blueArea: {
|
||||
flex: 1,
|
||||
paddingTop: 19,
|
||||
},
|
||||
broadcastResultWrapper: {
|
||||
|
@ -264,7 +264,7 @@ const PsbtMultisig = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<SafeBlueArea style={[styles.root, stylesHook.root]}>
|
||||
<SafeBlueArea style={stylesHook.root}>
|
||||
<View style={styles.container}>
|
||||
<View style={styles.mstopcontainer}>
|
||||
<View style={styles.mscontainer}>
|
||||
@ -303,9 +303,6 @@ const PsbtMultisig = () => {
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
root: {
|
||||
flex: 1,
|
||||
},
|
||||
mstopcontainer: {
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
|
@ -69,7 +69,7 @@ const PsbtMultisigQRCode = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<SafeBlueArea style={[styles.root, stylesHook.root]}>
|
||||
<SafeBlueArea style={stylesHook.root}>
|
||||
<ScrollView centerContent contentContainerStyle={styles.scrollViewContent}>
|
||||
<View style={[styles.modalContentShort, stylesHook.modalContentShort]}>
|
||||
<DynamicQRCode value={psbt.toHex()} />
|
||||
@ -98,9 +98,6 @@ const PsbtMultisigQRCode = () => {
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
root: {
|
||||
flex: 1,
|
||||
},
|
||||
scrollViewContent: {
|
||||
flexGrow: 1,
|
||||
justifyContent: 'space-between',
|
||||
|
@ -272,7 +272,7 @@ const PsbtWithHardwareWallet = () => {
|
||||
<ActivityIndicator />
|
||||
</View>
|
||||
) : (
|
||||
<SafeBlueArea style={[styles.root, stylesHook.root]}>
|
||||
<SafeBlueArea style={stylesHook.root}>
|
||||
<ScrollView centerContent contentContainerStyle={styles.scrollViewContent} testID="PsbtWithHardwareScrollView">
|
||||
<View style={styles.container}>
|
||||
<BlueCard>
|
||||
@ -333,9 +333,6 @@ export default PsbtWithHardwareWallet;
|
||||
PsbtWithHardwareWallet.navigationOptions = navigationStyle({}, opts => ({ ...opts, title: loc.send.header }));
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
root: {
|
||||
flex: 1,
|
||||
},
|
||||
scrollViewContent: {
|
||||
flexGrow: 1,
|
||||
justifyContent: 'space-between',
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { ScrollView, StyleSheet } from 'react-native';
|
||||
import { useNavigation, useTheme } from '@react-navigation/native';
|
||||
import { ScrollView } from 'react-native';
|
||||
import { useNavigation } from '@react-navigation/native';
|
||||
|
||||
import navigationStyle from '../../components/navigationStyle';
|
||||
import { SafeBlueArea, BlueListItem } from '../../BlueComponents';
|
||||
@ -8,13 +8,6 @@ import loc from '../../loc';
|
||||
|
||||
const NetworkSettings = () => {
|
||||
const { navigate } = useNavigation();
|
||||
const { colors } = useTheme();
|
||||
const styles = StyleSheet.create({
|
||||
root: {
|
||||
flex: 1,
|
||||
backgroundColor: colors.background,
|
||||
},
|
||||
});
|
||||
|
||||
const navigateToElectrumSettings = () => {
|
||||
navigate('ElectrumSettings');
|
||||
@ -29,7 +22,7 @@ const NetworkSettings = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.root}>
|
||||
<SafeBlueArea>
|
||||
<ScrollView>
|
||||
<BlueListItem title={loc.settings.network_electrum} onPress={navigateToElectrumSettings} testID="ElectrumSettings" chevron />
|
||||
<BlueListItem title={loc.settings.lightning_settings} onPress={navigateToLightningSettings} testID="LightningSettings" chevron />
|
||||
|
@ -14,9 +14,6 @@ const About = () => {
|
||||
const { colors } = useTheme();
|
||||
const { width, height } = useWindowDimensions();
|
||||
const styles = StyleSheet.create({
|
||||
root: {
|
||||
flex: 1,
|
||||
},
|
||||
center: {
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
@ -105,7 +102,7 @@ const About = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<SafeBlueArea style={styles.root}>
|
||||
<SafeBlueArea>
|
||||
<ScrollView testID="AboutScrollView">
|
||||
<BlueCard>
|
||||
<View style={styles.center}>
|
||||
|
@ -46,7 +46,7 @@ const Currency = () => {
|
||||
|
||||
if (selectedCurrency !== null && selectedCurrency !== undefined) {
|
||||
return (
|
||||
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.flex}>
|
||||
<SafeBlueArea>
|
||||
<FlatList
|
||||
style={styles.flex}
|
||||
keyExtractor={(_item, index) => `${index}`}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React, { useContext, useEffect, useState } from 'react';
|
||||
import { View, TouchableWithoutFeedback, StyleSheet } from 'react-native';
|
||||
import { View, TouchableWithoutFeedback } from 'react-native';
|
||||
import { useNavigation } from '@react-navigation/native';
|
||||
|
||||
import navigationStyle from '../../components/navigationStyle';
|
||||
@ -8,12 +8,6 @@ import OnAppLaunch from '../../class/on-app-launch';
|
||||
import loc from '../../loc';
|
||||
import { BlueStorageContext } from '../../blue_modules/storage-context';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
flex: {
|
||||
flex: 1,
|
||||
},
|
||||
});
|
||||
|
||||
const DefaultView = () => {
|
||||
const [defaultWalletLabel, setDefaultWalletLabel] = useState('');
|
||||
const [viewAllWalletsEnabled, setViewAllWalletsEnabled] = useState(true);
|
||||
@ -58,7 +52,7 @@ const DefaultView = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.flex}>
|
||||
<SafeBlueArea>
|
||||
<View>
|
||||
<BlueListItem
|
||||
title={loc.settings.default_wallets}
|
||||
|
@ -215,7 +215,7 @@ export default class ElectrumSettings extends Component {
|
||||
});
|
||||
|
||||
return (
|
||||
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.root}>
|
||||
<SafeBlueArea>
|
||||
<ScrollView>
|
||||
<BlueCard>
|
||||
<BlueText style={styles.status}>{loc.settings.electrum_status}</BlueText>
|
||||
@ -325,9 +325,6 @@ ElectrumSettings.propTypes = {
|
||||
ElectrumSettings.navigationOptions = navigationStyle({}, opts => ({ ...opts, title: loc.settings.electrum_settings_server }));
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
root: {
|
||||
flex: 1,
|
||||
},
|
||||
status: {
|
||||
textAlign: 'center',
|
||||
color: BlueCurrentTheme.colors.feeText,
|
||||
|
@ -124,11 +124,11 @@ const EncryptStorage = () => {
|
||||
};
|
||||
|
||||
return isLoading ? (
|
||||
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.root}>
|
||||
<SafeBlueArea>
|
||||
<BlueLoading />
|
||||
</SafeBlueArea>
|
||||
) : (
|
||||
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.root}>
|
||||
<SafeBlueArea>
|
||||
<ScrollView contentContainerStyle={styles.root}>
|
||||
{biometrics.isDeviceBiometricCapable && (
|
||||
<>
|
||||
|
@ -58,7 +58,7 @@ const Language = () => {
|
||||
return isLoading ? (
|
||||
<BlueLoading />
|
||||
) : (
|
||||
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={[styles.flex, stylesHook.flex]}>
|
||||
<SafeBlueArea>
|
||||
<FlatList
|
||||
style={[styles.flex, stylesHook.flex]}
|
||||
keyExtractor={(_item, index) => `${index}`}
|
||||
|
@ -1,14 +1,8 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { ScrollView, StyleSheet } from 'react-native';
|
||||
import { ScrollView } from 'react-native';
|
||||
import navigationStyle from '../../components/navigationStyle';
|
||||
import { SafeBlueArea, BlueCard, BlueText, BlueSpacing20, BlueLoading } from '../../BlueComponents';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
root: {
|
||||
flex: 1,
|
||||
},
|
||||
});
|
||||
|
||||
const Licensing = () => {
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
|
||||
@ -19,7 +13,7 @@ const Licensing = () => {
|
||||
return isLoading ? (
|
||||
<BlueLoading />
|
||||
) : (
|
||||
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.root}>
|
||||
<SafeBlueArea>
|
||||
<ScrollView>
|
||||
<BlueCard>
|
||||
<BlueText>MIT License</BlueText>
|
||||
|
@ -14,9 +14,6 @@ import { BlueCurrentTheme } from '../../components/themes';
|
||||
import DeeplinkSchemaMatch from '../../class/deeplink-schema-match';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
root: {
|
||||
flex: 1,
|
||||
},
|
||||
uri: {
|
||||
flexDirection: 'row',
|
||||
borderColor: BlueCurrentTheme.colors.formBorder,
|
||||
@ -111,7 +108,7 @@ const LightningSettings = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.root}>
|
||||
<SafeBlueArea>
|
||||
<BlueCard>
|
||||
<BlueText>{loc.settings.lightning_settings_explain}</BlueText>
|
||||
</BlueCard>
|
||||
|
@ -1,22 +1,14 @@
|
||||
import React from 'react';
|
||||
import { ScrollView, StyleSheet } from 'react-native';
|
||||
import { useTheme } from '@react-navigation/native';
|
||||
import { ScrollView } from 'react-native';
|
||||
import navigationStyle from '../../components/navigationStyle';
|
||||
import { SafeBlueArea, BlueCard, BlueText } from '../../BlueComponents';
|
||||
import loc from '../../loc';
|
||||
|
||||
const ReleaseNotes = () => {
|
||||
const notes = require('../../release-notes');
|
||||
const { colors } = useTheme();
|
||||
const styles = StyleSheet.create({
|
||||
root: {
|
||||
flex: 1,
|
||||
backgroundColor: colors.background,
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.root}>
|
||||
<SafeBlueArea>
|
||||
<ScrollView>
|
||||
<BlueCard>
|
||||
<BlueText>{notes}</BlueText>
|
||||
|
@ -31,7 +31,6 @@ const styles = StyleSheet.create({
|
||||
paddingTop: 20,
|
||||
},
|
||||
explain: {
|
||||
flex: 1,
|
||||
paddingBottom: 16,
|
||||
},
|
||||
center: {
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* global alert */
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { ActivityIndicator, View, StyleSheet, ScrollView } from 'react-native';
|
||||
import { ActivityIndicator, View, ScrollView } from 'react-native';
|
||||
import { BlueSpacing20, SafeBlueArea, BlueText } from '../../BlueComponents';
|
||||
import navigationStyle from '../../components/navigationStyle';
|
||||
import { HDSegwitBech32Transaction, HDSegwitBech32Wallet } from '../../class';
|
||||
@ -9,13 +9,6 @@ import CPFP from './CPFP';
|
||||
import loc from '../../loc';
|
||||
import { BlueStorageContext } from '../../blue_modules/storage-context';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
common: {
|
||||
flex: 1,
|
||||
paddingTop: 16,
|
||||
},
|
||||
});
|
||||
|
||||
export default class RBFCancel extends CPFP {
|
||||
static contextType = BlueStorageContext;
|
||||
async componentDidMount() {
|
||||
@ -83,7 +76,7 @@ export default class RBFCancel extends CPFP {
|
||||
render() {
|
||||
if (this.state.isLoading) {
|
||||
return (
|
||||
<View style={styles.root}>
|
||||
<View>
|
||||
<ActivityIndicator />
|
||||
</View>
|
||||
);
|
||||
@ -95,7 +88,7 @@ export default class RBFCancel extends CPFP {
|
||||
|
||||
if (this.state.nonReplaceable) {
|
||||
return (
|
||||
<SafeBlueArea style={styles.root}>
|
||||
<SafeBlueArea>
|
||||
<BlueSpacing20 />
|
||||
<BlueSpacing20 />
|
||||
<BlueSpacing20 />
|
||||
@ -108,7 +101,7 @@ export default class RBFCancel extends CPFP {
|
||||
}
|
||||
|
||||
return (
|
||||
<SafeBlueArea style={styles.root}>
|
||||
<SafeBlueArea>
|
||||
<ScrollView>{this.renderStage1(loc.transactions.cancel_explain)}</ScrollView>
|
||||
</SafeBlueArea>
|
||||
);
|
||||
|
@ -140,7 +140,7 @@ const TransactionsDetails = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.root}>
|
||||
<SafeBlueArea>
|
||||
<HandoffComponent
|
||||
title={`Bitcoin Transaction ${tx.hash}`}
|
||||
type="io.bluewallet.bluewallet"
|
||||
@ -249,9 +249,6 @@ const TransactionsDetails = () => {
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
root: {
|
||||
flex: 1,
|
||||
},
|
||||
scroll: {
|
||||
flex: 1,
|
||||
},
|
||||
|
@ -40,9 +40,6 @@ const TransactionsStatus = () => {
|
||||
const [tx, setTX] = useState();
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const stylesHook = StyleSheet.create({
|
||||
root: {
|
||||
backgroundColor: colors.background,
|
||||
},
|
||||
value: {
|
||||
color: colors.alternativeTextColor2,
|
||||
},
|
||||
@ -273,13 +270,13 @@ const TransactionsStatus = () => {
|
||||
|
||||
if (isLoading || !tx) {
|
||||
return (
|
||||
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={[styles.root, stylesHook.root]}>
|
||||
<SafeBlueArea>
|
||||
<BlueLoading />
|
||||
</SafeBlueArea>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={[styles.root, stylesHook.root]}>
|
||||
<SafeBlueArea>
|
||||
<HandoffComponent
|
||||
title={`Bitcoin Transaction ${tx.hash}`}
|
||||
type="io.bluewallet.bluewallet"
|
||||
@ -363,9 +360,6 @@ const TransactionsStatus = () => {
|
||||
|
||||
export default TransactionsStatus;
|
||||
const styles = StyleSheet.create({
|
||||
root: {
|
||||
flex: 1,
|
||||
},
|
||||
container: {
|
||||
flex: 1,
|
||||
justifyContent: 'space-between',
|
||||
|
@ -39,7 +39,7 @@ const WalletsAddMultisigHelp = () => {
|
||||
return isLoading ? (
|
||||
<BlueLoading />
|
||||
) : (
|
||||
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={stylesHook.root}>
|
||||
<SafeBlueArea style={stylesHook.root}>
|
||||
<ScrollView>
|
||||
<View style={[styles.intro, stylesHook.intro]}>
|
||||
<Text style={[styles.introTitle, stylesHook.introTitle]}>{loc.multisig.ms_help_title}</Text>
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { StyleSheet, StatusBar, Linking, Platform } from 'react-native';
|
||||
import { StatusBar, Linking, Platform } from 'react-native';
|
||||
import { WebView } from 'react-native-webview';
|
||||
import InAppBrowser from 'react-native-inappbrowser-reborn';
|
||||
|
||||
@ -11,12 +11,6 @@ import * as NavigationService from '../../NavigationService';
|
||||
import { BlueStorageContext } from '../../blue_modules/storage-context';
|
||||
const currency = require('../../blue_modules/currency');
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
root: {
|
||||
flex: 1,
|
||||
},
|
||||
});
|
||||
|
||||
export default class BuyBitcoin extends Component {
|
||||
static contextType = BlueStorageContext;
|
||||
constructor(props) {
|
||||
@ -86,7 +80,7 @@ export default class BuyBitcoin extends Component {
|
||||
}
|
||||
|
||||
return (
|
||||
<SafeBlueArea style={styles.root}>
|
||||
<SafeBlueArea>
|
||||
<StatusBar barStyle="default" />
|
||||
<WebView
|
||||
source={{
|
||||
|
@ -399,7 +399,7 @@ const WalletDetails = () => {
|
||||
<BlueLoading />
|
||||
</View>
|
||||
) : (
|
||||
<SafeBlueArea style={styles.root}>
|
||||
<SafeBlueArea>
|
||||
<StatusBar barStyle="default" />
|
||||
<TouchableWithoutFeedback onPress={Keyboard.dismiss} accessible={false}>
|
||||
<ScrollView contentContainerStyle={styles.scrollViewContent} testID="WalletDetailsScroll">
|
||||
|
@ -16,9 +16,6 @@ const styles = StyleSheet.create({
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
},
|
||||
root: {
|
||||
flex: 1,
|
||||
},
|
||||
scrollViewContent: {
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
@ -52,7 +49,6 @@ const WalletExport = () => {
|
||||
backgroundColor: colors.elevated,
|
||||
},
|
||||
root: {
|
||||
...styles.root,
|
||||
backgroundColor: colors.elevated,
|
||||
},
|
||||
type: { ...styles.type, color: colors.foregroundColor },
|
||||
|
@ -72,7 +72,7 @@ const ExportMultisigCoordinationSetup = () => {
|
||||
<ActivityIndicator />
|
||||
</View>
|
||||
) : (
|
||||
<SafeBlueArea style={[styles.root, stylesHook.root]}>
|
||||
<SafeBlueArea style={stylesHook.root}>
|
||||
<StatusBar barStyle="light-content" />
|
||||
<ScrollView contentContainerStyle={styles.scrollViewContent}>
|
||||
<View>
|
||||
@ -98,9 +98,6 @@ const styles = StyleSheet.create({
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
},
|
||||
root: {
|
||||
flex: 1,
|
||||
},
|
||||
scrollViewContent: {
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
|
@ -23,12 +23,12 @@ const WalletsImport = () => {
|
||||
const [isToolbarVisibleForAndroid, setIsToolbarVisibleForAndroid] = useState(false);
|
||||
const route = useRoute();
|
||||
const label = (route.params && route.params.label) || '';
|
||||
const triggerImport = (route.params && route.params.triggerImport) || false;
|
||||
const [importText, setImportText] = useState(label);
|
||||
const navigation = useNavigation();
|
||||
const { colors } = useTheme();
|
||||
const styles = StyleSheet.create({
|
||||
root: {
|
||||
flex: 1,
|
||||
paddingTop: 40,
|
||||
backgroundColor: colors.elevated,
|
||||
},
|
||||
@ -50,6 +50,11 @@ const WalletsImport = () => {
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (triggerImport) importButtonPressed();
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
const importButtonPressed = () => {
|
||||
if (importText.trim().length === 0) {
|
||||
return;
|
||||
@ -108,7 +113,7 @@ const WalletsImport = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.root}>
|
||||
<SafeBlueArea style={styles.root}>
|
||||
<StatusBar barStyle="light-content" />
|
||||
<BlueSpacing20 />
|
||||
<BlueFormLabel>{loc.wallets.import_explanation}</BlueFormLabel>
|
||||
|
@ -32,6 +32,7 @@ import { isCatalyst, isMacCatalina, isTablet } from '../../blue_modules/environm
|
||||
import BlueClipboard from '../../blue_modules/clipboard';
|
||||
import navigationStyle from '../../components/navigationStyle';
|
||||
|
||||
const scanqrHelper = require('../../helpers/scan-qr');
|
||||
const A = require('../../blue_modules/analytics');
|
||||
const fs = require('../../blue_modules/fs');
|
||||
const WalletsListSections = { CAROUSEL: 'CAROUSEL', LOCALTRADER: 'LOCALTRADER', TRANSACTIONS: 'TRANSACTIONS' };
|
||||
@ -351,18 +352,12 @@ const WalletsList = () => {
|
||||
if (isMacCatalina) {
|
||||
fs.showActionSheet({ anchor: walletActionButtonsRef.current }).then(onBarScanned);
|
||||
} else {
|
||||
navigate('ScanQRCodeRoot', {
|
||||
screen: 'ScanQRCode',
|
||||
params: {
|
||||
launchedBy: routeName,
|
||||
onBarScanned,
|
||||
showFileImportButton: false,
|
||||
},
|
||||
});
|
||||
scanqrHelper(navigate, routeName, false).then(onBarScanned);
|
||||
}
|
||||
};
|
||||
|
||||
const onBarScanned = value => {
|
||||
if (!value) return;
|
||||
DeeplinkSchemaMatch.navigationRouteFor({ url: value }, completionValue => {
|
||||
ReactNativeHapticFeedback.trigger('impactLight', { ignoreAndroidSystemSettings: false });
|
||||
navigate(...completionValue);
|
||||
@ -389,14 +384,7 @@ const WalletsList = () => {
|
||||
if (buttonIndex === 1) {
|
||||
fs.showImagePickerAndReadImage().then(onBarScanned);
|
||||
} else if (buttonIndex === 2) {
|
||||
navigate('ScanQRCodeRoot', {
|
||||
screen: 'ScanQRCode',
|
||||
params: {
|
||||
launchedBy: routeName,
|
||||
onBarScanned,
|
||||
showFileImportButton: false,
|
||||
},
|
||||
});
|
||||
scanqrHelper(navigate, routeName, false).then(onBarScanned);
|
||||
} else if (buttonIndex === 3) {
|
||||
copyFromClipboard();
|
||||
}
|
||||
@ -416,15 +404,7 @@ const WalletsList = () => {
|
||||
},
|
||||
{
|
||||
text: loc.wallets.list_long_scan,
|
||||
onPress: () =>
|
||||
navigate('ScanQRCodeRoot', {
|
||||
screen: 'ScanQRCode',
|
||||
params: {
|
||||
launchedBy: routeName,
|
||||
onBarScanned,
|
||||
showFileImportButton: false,
|
||||
},
|
||||
}),
|
||||
onPress: () => scanqrHelper(navigate, routeName, false).then(onBarScanned),
|
||||
},
|
||||
];
|
||||
if (!isClipboardEmpty) {
|
||||
|
@ -70,7 +70,7 @@ const PleaseBackup = () => {
|
||||
<ActivityIndicator />
|
||||
</View>
|
||||
) : (
|
||||
<SafeBlueArea style={[styles.flex, stylesHook.flex]}>
|
||||
<SafeBlueArea style={stylesHook.flex}>
|
||||
<StatusBar barStyle="default" />
|
||||
<ScrollView testID="PleaseBackupScrollView">
|
||||
<View style={styles.please}>
|
||||
@ -99,9 +99,6 @@ PleaseBackup.navigationOptions = navigationStyle(
|
||||
);
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
flex: {
|
||||
flex: 1,
|
||||
},
|
||||
loading: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
|
@ -24,7 +24,6 @@ const PleaseBackupLNDHub = () => {
|
||||
}, [navigation]);
|
||||
const styles = StyleSheet.create({
|
||||
root: {
|
||||
flex: 1,
|
||||
backgroundColor: colors.elevated,
|
||||
},
|
||||
scrollViewContent: {
|
||||
|
@ -27,10 +27,6 @@ const SelectWallet = () => {
|
||||
data = availableWallets;
|
||||
}
|
||||
const styles = StyleSheet.create({
|
||||
root: {
|
||||
flex: 1,
|
||||
backgroundColor: colors.background,
|
||||
},
|
||||
loading: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
@ -153,7 +149,7 @@ const SelectWallet = () => {
|
||||
);
|
||||
} else if (data.length <= 0) {
|
||||
return (
|
||||
<SafeBlueArea style={styles.root}>
|
||||
<SafeBlueArea>
|
||||
<StatusBar barStyle="light-content" />
|
||||
<View style={styles.noWallets}>
|
||||
<BlueText style={styles.center}>{loc.wallets.select_no_bitcoin}</BlueText>
|
||||
@ -164,7 +160,7 @@ const SelectWallet = () => {
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<SafeBlueArea style={styles.root}>
|
||||
<SafeBlueArea>
|
||||
<StatusBar barStyle="default" />
|
||||
<FlatList extraData={data} data={data} renderItem={renderItem} keyExtractor={(_item, index) => `${index}`} />
|
||||
</SafeBlueArea>
|
||||
|
@ -511,6 +511,8 @@ describe('BlueWallet UI Tests', () => {
|
||||
// created. verifying:
|
||||
await yo('TransactionValue');
|
||||
expect(element(by.id('TransactionValue'))).toHaveText('0.0001');
|
||||
const transactionFee = await extractTextFromElementById('TransactionFee');
|
||||
assert.ok(transactionFee.startsWith('Fee: 0.00000748 BTC'), 'Unexpected tx fee: ' + transactionFee);
|
||||
await element(by.id('TransactionDetailsButton')).tap();
|
||||
|
||||
let txhex = await extractTextFromElementById('TxhexInput');
|
||||
@ -525,6 +527,7 @@ describe('BlueWallet UI Tests', () => {
|
||||
const totalIns = 100000 + 5526; // we hardcode it since we know it in advance
|
||||
const totalOuts = transaction.outs.map(el => el.value).reduce((a, b) => a + b, 0);
|
||||
assert.strictEqual(Math.round((totalIns - totalOuts) / (txhex.length / 2)), feeRate);
|
||||
assert.strictEqual(transactionFee.split(' ')[1] * 100000000, totalIns - totalOuts);
|
||||
|
||||
if (device.getPlatform() === 'ios') {
|
||||
console.warn('rest of the test is Android only, skipped');
|
||||
@ -635,21 +638,58 @@ describe('BlueWallet UI Tests', () => {
|
||||
|
||||
await device.pressBack();
|
||||
await device.pressBack();
|
||||
await device.pressBack(); // go back to wallet tx list to reset the form
|
||||
await element(by.id('SendButton')).tap();
|
||||
|
||||
// set fee rate
|
||||
await element(by.id('chooseFee')).tap();
|
||||
await element(by.id('feeCustom')).tap();
|
||||
await element(by.type('android.widget.EditText')).typeText(feeRate + '');
|
||||
await element(by.text('OK')).tap();
|
||||
|
||||
// first send MAX output
|
||||
await element(by.id('AddressInput')).replaceText('bc1qnapskphjnwzw2w3dk4anpxntunc77v6qrua0f7');
|
||||
await element(by.id('BitcoinAmountInput')).typeText('0.0001\n');
|
||||
await element(by.id('advancedOptionsMenuButton')).tap();
|
||||
await element(by.id('sendMaxButton')).tap();
|
||||
await element(by.text('OK')).tap();
|
||||
|
||||
if (process.env.TRAVIS) await sleep(5000);
|
||||
try {
|
||||
await element(by.id('CreateTransactionButton')).tap();
|
||||
} catch (_) {}
|
||||
// created. verifying:
|
||||
await yo('TransactionValue');
|
||||
await yo('TransactionDetailsButton');
|
||||
await element(by.id('TransactionDetailsButton')).tap();
|
||||
txhex = await extractTextFromElementById('TxhexInput');
|
||||
transaction = bitcoin.Transaction.fromHex(txhex);
|
||||
assert.strictEqual(transaction.outs.length, 1, 'should be single output, no change');
|
||||
assert.ok(transaction.outs[0].value > 100000);
|
||||
|
||||
// add second output with amount
|
||||
await device.pressBack();
|
||||
await device.pressBack();
|
||||
await element(by.id('advancedOptionsMenuButton')).tap();
|
||||
await element(by.id('AddRecipient')).tap();
|
||||
await yo('Transaction1');
|
||||
await element(by.id('AddressInput').withAncestor(by.id('Transaction1'))).replaceText('bc1q063ctu6jhe5k4v8ka99qac8rcm2tzjjnuktyrl');
|
||||
await element(by.id('BitcoinAmountInput').withAncestor(by.id('Transaction1'))).typeText('0.0001\n');
|
||||
|
||||
if (process.env.TRAVIS) await sleep(5000);
|
||||
try {
|
||||
await element(by.id('CreateTransactionButton')).tap();
|
||||
} catch (_) {}
|
||||
// created. verifying:
|
||||
await yo('TransactionDetailsButton');
|
||||
await element(by.id('TransactionDetailsButton')).tap();
|
||||
txhex = await extractTextFromElementById('TxhexInput');
|
||||
transaction = bitcoin.Transaction.fromHex(txhex);
|
||||
assert.strictEqual(transaction.outs.length, 2, 'should be single output, no change');
|
||||
assert.strictEqual(bitcoin.address.fromOutputScript(transaction.outs[0].script), 'bc1qnapskphjnwzw2w3dk4anpxntunc77v6qrua0f7');
|
||||
assert.ok(transaction.outs[0].value > 50000);
|
||||
assert.strictEqual(bitcoin.address.fromOutputScript(transaction.outs[1].script), 'bc1q063ctu6jhe5k4v8ka99qac8rcm2tzjjnuktyrl');
|
||||
assert.strictEqual(transaction.outs[1].value, 10000);
|
||||
|
||||
// now, testing cosign psbt:
|
||||
|
||||
await device.pressBack();
|
||||
|
@ -101,7 +101,6 @@ it('HD (BIP49) can create TX', async () => {
|
||||
assert.strictEqual('3GcKN7q7gZuZ8eHygAhHrvPa5zZbG5Q1rK', toAddress);
|
||||
|
||||
// testing sendMAX
|
||||
|
||||
const utxo = [
|
||||
{
|
||||
height: 591862,
|
||||
@ -135,6 +134,7 @@ it('HD (BIP49) can create TX', async () => {
|
||||
},
|
||||
];
|
||||
|
||||
// one MAX output
|
||||
txNew = hd.createTransaction(
|
||||
utxo,
|
||||
[{ address: '3GcKN7q7gZuZ8eHygAhHrvPa5zZbG5Q1rK' }],
|
||||
@ -144,6 +144,19 @@ it('HD (BIP49) can create TX', async () => {
|
||||
tx = bitcoin.Transaction.fromHex(txNew.tx.toHex());
|
||||
assert.strictEqual(tx.outs.length, 1);
|
||||
assert.ok(tx.outs[0].value > 77000);
|
||||
|
||||
// MAX with regular output
|
||||
txNew = hd.createTransaction(
|
||||
utxo,
|
||||
[{ address: '3GcKN7q7gZuZ8eHygAhHrvPa5zZbG5Q1rK' }, { address: 'bc1qvd6w54sydc08z3802svkxr7297ez7cusd6266p', value: 25000 }],
|
||||
1,
|
||||
hd._getInternalAddressByIndex(hd.next_free_change_address_index),
|
||||
);
|
||||
tx = bitcoin.Transaction.fromHex(txNew.tx.toHex());
|
||||
assert.strictEqual(tx.outs.length, 2);
|
||||
assert.ok(tx.outs[0].value > 50000);
|
||||
assert.strictEqual(tx.outs[1].value, 25000
|
||||
);
|
||||
});
|
||||
|
||||
it('Segwit HD (BIP49) can fetch balance with many used addresses in hierarchy', async function () {
|
||||
|
@ -202,6 +202,81 @@ describe('unit - DeepLinkSchemaMatch', function () {
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
argument: {
|
||||
url: require('fs').readFileSync('./tests/unit/fixtures/skeleton-cobo.txt', 'ascii'),
|
||||
},
|
||||
expected: [
|
||||
'AddWalletRoot',
|
||||
{
|
||||
screen: 'ImportWallet',
|
||||
params: {
|
||||
triggerImport: true,
|
||||
label: require('fs').readFileSync('./tests/unit/fixtures/skeleton-cobo.txt', 'ascii'),
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
argument: {
|
||||
url: require('fs').readFileSync('./tests/unit/fixtures/skeleton-coldcard.txt', 'ascii'),
|
||||
},
|
||||
expected: [
|
||||
'AddWalletRoot',
|
||||
{
|
||||
screen: 'ImportWallet',
|
||||
params: {
|
||||
triggerImport: true,
|
||||
label: require('fs').readFileSync('./tests/unit/fixtures/skeleton-coldcard.txt', 'ascii'),
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
argument: {
|
||||
url: require('fs').readFileSync('./tests/unit/fixtures/skeleton-electrum.txt', 'ascii'),
|
||||
},
|
||||
expected: [
|
||||
'AddWalletRoot',
|
||||
{
|
||||
screen: 'ImportWallet',
|
||||
params: {
|
||||
triggerImport: true,
|
||||
label: require('fs').readFileSync('./tests/unit/fixtures/skeleton-electrum.txt', 'ascii'),
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
argument: {
|
||||
url: require('fs').readFileSync('./tests/unit/fixtures/skeleton-walletdescriptor.txt', 'ascii'),
|
||||
},
|
||||
expected: [
|
||||
'AddWalletRoot',
|
||||
{
|
||||
screen: 'ImportWallet',
|
||||
params: {
|
||||
triggerImport: true,
|
||||
label: require('fs').readFileSync('./tests/unit/fixtures/skeleton-walletdescriptor.txt', 'ascii'),
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
argument: {
|
||||
url: 'zpub6rFDtF1nuXZ9PUL4XzKURh3vJBW6Kj6TUrYL4qPtFNtDXtcTVfiqjQDyrZNwjwzt5HS14qdqo3Co2282Lv3Re6Y5wFZxAVuMEpeygnnDwfx',
|
||||
},
|
||||
expected: [
|
||||
'AddWalletRoot',
|
||||
{
|
||||
screen: 'ImportWallet',
|
||||
params: {
|
||||
triggerImport: true,
|
||||
label: 'zpub6rFDtF1nuXZ9PUL4XzKURh3vJBW6Kj6TUrYL4qPtFNtDXtcTVfiqjQDyrZNwjwzt5HS14qdqo3Co2282Lv3Re6Y5wFZxAVuMEpeygnnDwfx',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
const asyncNavigationRouteFor = async function (event) {
|
||||
|
1
tests/unit/fixtures/skeleton-cobo.txt
Normal file
1
tests/unit/fixtures/skeleton-cobo.txt
Normal file
@ -0,0 +1 @@
|
||||
{"ExtPubKey":"zpub6rcabYFcdr41zyUNRWRyHYs2Sm86E5XV8RjjRzTFYsiCngteeZnkwaF2xuhjmM6kpHjuNpFW42BMhzPmFwXt48e1FhddMB7xidZzN4SF24K","MasterFingerprint":"5271c071","CoboVaultFirmwareVersion":"1.2.4(BTC-Only)"}
|
1
tests/unit/fixtures/skeleton-coldcard.txt
Normal file
1
tests/unit/fixtures/skeleton-coldcard.txt
Normal file
@ -0,0 +1 @@
|
||||
{"keystore": {"ckcc_xpub": "xpub661MyMwAqRbcGmUDQVKxmhEESB5xTk8hbsdTSV3Pmhm3HE9Fj3s45R9Y8LwyaQWjXXPytZjuhTKSyCBPeNrB1VVWQq1HCvjbEZ27k44oNmg", "xpub": "zpub6rFDtF1nuXZ9PUL4XzKURh3vJBW6Kj6TUrYL4qPtFNtDXtcTVfiqjQDyrZNwjwzt5HS14qdqo3Co2282Lv3Re6Y5wFZxAVuMEpeygnnDwfx", "label": "Coldcard Import 168DD603", "ckcc_xfp": 64392470, "type": "hardware", "hw_type": "coldcard", "derivation": "m/84'/0'/0'"}, "wallet_type": "standard", "use_encryption": false, "seed_version": 17}
|
1
tests/unit/fixtures/skeleton-electrum.txt
Normal file
1
tests/unit/fixtures/skeleton-electrum.txt
Normal file
File diff suppressed because one or more lines are too long
1
tests/unit/fixtures/skeleton-walletdescriptor.txt
Normal file
1
tests/unit/fixtures/skeleton-walletdescriptor.txt
Normal file
@ -0,0 +1 @@
|
||||
[8cce63f8/84h/0h/0h]zpub6s2RJ9qAEBW8Abhojs6LyDzF7gttcDr6EsR3Umu2aptZBb45e734rGtt4KqsCMmNyR1EEzUU2ugdVYez2VywQvAbBjUSKn8ho4Zk2c5otkk
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user