This commit is contained in:
Marcos Rodriguez 2020-01-02 22:02:41 -06:00
parent c54ef7d067
commit 338481a3de
8 changed files with 60 additions and 53 deletions

View File

@ -759,7 +759,8 @@ export class AbstractHDElectrumWallet extends AbstractHDWallet {
let pubkey = this._getPubkeyByAddress(input.address);
let masterFingerprintBuffer;
if (masterFingerprint) {
masterFingerprintBuffer = Buffer.from(masterFingerprint, 'hex');
const hexBuffer = Buffer.from(Number(masterFingerprint).toString(16), 'hex');
masterFingerprintBuffer = Buffer.from(reverse(hexBuffer));
} else {
masterFingerprintBuffer = Buffer.from([0x00, 0x00, 0x00, 0x00]);
}
@ -798,7 +799,8 @@ export class AbstractHDElectrumWallet extends AbstractHDWallet {
let masterFingerprintBuffer;
if (masterFingerprint) {
masterFingerprintBuffer = Buffer.from(masterFingerprint, 'hex');
const hexBuffer = Buffer.from(Number(masterFingerprint).toString(16), 'hex');
masterFingerprintBuffer = Buffer.from(reverse(hexBuffer));
} else {
masterFingerprintBuffer = Buffer.from([0x00, 0x00, 0x00, 0x00]);
}

View File

@ -1,6 +1,8 @@
import { AppStorage, LightningCustodianWallet } from './';
import AsyncStorage from '@react-native-community/async-storage';
import BitcoinBIP70TransactionDecode from '../bip70/bip70';
import RNFS from 'react-native-fs';
import url from 'url';
const bitcoin = require('bitcoinjs-lib');
const BlueApp = require('../BlueApp');
class DeeplinkSchemaMatch {
@ -30,6 +32,21 @@ class DeeplinkSchemaMatch {
if (typeof event.url !== 'string') {
return;
}
if (DeeplinkSchemaMatch.isPossiblyPSBTFile(event.url)) {
RNFS.readFile(event.url)
.then(file => {
if (file) {
completionHandler({
routeName: 'PsbtWithHardwareWallet',
params: {
deepLinkPSBT: file,
},
});
}
})
.catch(e => console.warn(e));
return;
}
let isBothBitcoinAndLightning;
try {
isBothBitcoinAndLightning = DeeplinkSchemaMatch.isBothBitcoinAndLightning(event.url);
@ -146,6 +163,10 @@ class DeeplinkSchemaMatch {
}
}
static isPossiblyPSBTFile(filePath) {
return filePath.toLowerCase().startsWith('file:') && filePath.toLowerCase().endsWith('-signed.psbt');
}
static isBitcoinAddress(address) {
address = address
.replace('bitcoin:', '')

View File

@ -51,9 +51,7 @@ export class WatchOnlyWallet extends LegacyWallet {
let masterFingerprint = false;
if (parsedSecret.keystore.ckcc_xfp) {
// It is a ColdCard Hardware Wallet
masterFingerprint = Buffer.from(Number(parsedSecret.keystore.ckcc_xfp).toString(16), 'hex')
.reverse()
.toString('hex');
masterFingerprint = Number(parsedSecret.keystore.ckcc_xfp);
}
this.setSecret(parsedSecret.keystore.xpub);
this.masterFingerprint = masterFingerprint;

View File

@ -10,6 +10,8 @@
</array>
<key>com.apple.developer.ubiquity-container-identifiers</key>
<array/>
<key>com.apple.developer.ubiquity-kvstore-identifier</key>
<string>$(TeamIdentifierPrefix)$(CFBundleIdentifier)</string>
<key>com.apple.security.application-groups</key>
<array>
<string>group.io.bluewallet.bluewallet</string>

View File

@ -711,10 +711,11 @@ export default class SendDetails extends Component {
importTransaction = async () => {
try {
const res = await DocumentPicker.pick();
const res = await DocumentPicker.pick({ type: ['io.bluewallet.psbt'] });
const file = await RNFS.readFile(res.uri, 'ascii');
const bufferDecoded = Buffer.from(file, 'ascii').toString('base64');
if (bufferDecoded) {
this.setState({ isAdvancedTransactionOptionsVisible: false });
if (this.state.fromWallet.type === WatchOnlyWallet.type) {
// watch-only wallets with enabled HW wallet support have different flow. we have to show PSBT to user as QR code
// so he can scan it and sign it. then we have to scan it back from user (via camera and QR code), and ask
@ -722,7 +723,7 @@ export default class SendDetails extends Component {
this.props.navigation.navigate('PsbtWithHardwareWallet', {
memo: this.state.memo,
fromWallet: this.state.fromWallet,
psbt: bufferDecoded,
psbt: file,
isFirstPSBTAlreadyBase64: true,
});
this.setState({ isLoading: false });
@ -736,7 +737,6 @@ export default class SendDetails extends Component {
alert('The selected file does not contain a signed transaction that can be imported.');
}
}
this.setState({ isAdvancedTransactionOptionsVisible: false });
};
renderAdvancedTransactionOptionsModal = () => {

View File

@ -51,10 +51,7 @@ export default class PsbtWithHardwareWallet extends Component {
this.setState({ renderScanner: false }, () => {
console.log(ret.data);
try {
let Tx = this.state.fromWallet.combinePsbt(
this.state.isFirstPSBTAlreadyBase64 ? this.state.psbt : this.state.psbt.toBase64(),
this.state.isSecondPSBTAlreadyBase64 ? ret.data : ret.data.toBase64(),
);
let Tx = this.state.fromWallet.combinePsbt(this.state.psbt, ret.data);
this.setState({ txhex: Tx.toHex() });
} catch (Err) {
alert(Err);
@ -73,9 +70,29 @@ export default class PsbtWithHardwareWallet extends Component {
fromWallet: props.navigation.getParam('fromWallet'),
isFirstPSBTAlreadyBase64: props.navigation.getParam('isFirstPSBTAlreadyBase64'),
isSecondPSBTAlreadyBase64: false,
deepLinkPSBT: undefined,
};
}
static getDerivedStateFromProps(nextProps, prevState) {
const deepLinkPSBT = nextProps.navigation.state.params.deepLinkPSBT;
if (deepLinkPSBT) {
try {
let Tx = prevState.fromWallet.combinePsbt(
prevState.isFirstPSBTAlreadyBase64 ? prevState.psbt : prevState.psbt.toBase64(),
deepLinkPSBT,
);
return {
...prevState,
txhex: Tx.toHex(),
};
} catch (Err) {
alert(Err);
}
}
return prevState;
}
componentDidMount() {
console.log('send/psbtWithHardwareWallet - componentDidMount');
}
@ -207,8 +224,8 @@ export default class PsbtWithHardwareWallet extends Component {
exportPSBT = async () => {
const fileName = `${Date.now()}.psbt`;
if (Platform.OS === 'ios') {
const filePath = RNFS.TemporaryDirectoryPath + `/${Date.now()}.psbt`;
await RNFS.writeFile(filePath, this.state.isFirstPSBTAlreadyBase64 ? this.state.psbt : this.state.psbt.toBase64(), 'ascii');
const filePath = RNFS.TemporaryDirectoryPath + `/${fileName}`;
await RNFS.writeFile(filePath, this.state.isFirstPSBTAlreadyBase64 ? this.state.psbt : this.state.psbt.toBase64());
Share.open({
url: 'file://' + filePath,
})
@ -242,11 +259,10 @@ export default class PsbtWithHardwareWallet extends Component {
openSignedTransaction = async () => {
try {
const res = await DocumentPicker.pick();
const file = await RNFS.readFile(res.uri, 'ascii');
const bufferDecoded = Buffer.from(file, 'ascii').toString('base64');
if (bufferDecoded) {
this.setState({ isSecondPSBTAlreadyBase64: true }, () => this.onBarCodeRead({ data: bufferDecoded }));
const res = await DocumentPicker.pick({ type: ['io.bluewallet.psbt'] });
const file = await RNFS.readFile(res.uri);
if (file) {
this.setState({ isSecondPSBTAlreadyBase64: true }, () => this.onBarCodeRead({ data: file }));
} else {
this.setState({ isSecondPSBTAlreadyBase64: false });
throw new Error();

View File

@ -48,9 +48,7 @@ const ScanQRCode = ({
if (fileParsed.keystore.xpub) {
let masterFingerprint;
if (fileParsed.keystore.ckcc_xfp) {
masterFingerprint = Buffer.from(Number(fileParsed.keystore.ckcc_xfp).toString(16), 'hex')
.reverse()
.toString('hex');
masterFingerprint = Number(fileParsed.keystore.ckcc_xfp);
}
onBarCodeRead({ data: fileParsed.keystore.xpub, additionalProperties: { masterFingerprint } });
} else {

View File

@ -51,13 +51,13 @@ export default class WalletDetails extends Component {
super(props);
const wallet = props.navigation.getParam('wallet');
console.warn(wallet.masterFingerprint)
const isLoading = true;
this.state = {
isLoading,
walletName: wallet.getLabel(),
wallet,
useWithHardwareWallet: !!wallet.use_with_hardware_wallet,
masterFingerprint: wallet.masterFingerprint ? String(wallet.masterFingerprint) : '',
};
this.props.navigation.setParams({ isLoading, saveAction: () => this.setLabel() });
}
@ -74,7 +74,6 @@ export default class WalletDetails extends Component {
this.props.navigation.setParams({ isLoading: true });
this.setState({ isLoading: true }, async () => {
this.state.wallet.setLabel(this.state.walletName);
this.state.wallet.masterFingerprint = String(this.state.masterFingerprint);
BlueApp.saveToDisk();
alert('Wallet updated.');
this.props.navigation.goBack(null);
@ -192,35 +191,6 @@ export default class WalletDetails extends Component {
{this.state.wallet.type === WatchOnlyWallet.type && this.state.wallet.getSecret().startsWith('zpub') && (
<>
<Text style={{ color: '#0c2550', fontWeight: '500', fontSize: 14, marginVertical: 16 }}>{'advanced'}</Text>
<BlueText>Master Fingerprint</BlueText>
<BlueSpacing20 />
<View
style={{
flexDirection: 'row',
borderColor: '#d2d2d2',
borderBottomColor: '#d2d2d2',
borderWidth: 1.0,
borderBottomWidth: 0.5,
backgroundColor: '#f5f5f5',
minHeight: 44,
height: 44,
alignItems: 'center',
borderRadius: 4,
}}
>
<TextInput
placeholder="Master Fingerprint"
value={this.state.masterFingerprint}
onChangeText={text => {
this.setState({ masterFingerprint: text });
}}
numberOfLines={1}
style={{ flex: 1, marginHorizontal: 8, minHeight: 33 }}
editable={!this.state.isLoading}
underlineColorAndroid="transparent"
/>
</View>
<BlueSpacing20 />
<View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between' }}>
<BlueText>{'Use with hardware wallet'}</BlueText>
<Switch