Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
gruve-p committed Aug 18, 2023
2 parents e1ed51f + e0d9f59 commit 4366728
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 12 deletions.
6 changes: 3 additions & 3 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ jobs:

lint:
docker:
- image: cimg/node:16.20.1
- image: cimg/node:16.20.2

working_directory: ~/repo

Expand All @@ -26,7 +26,7 @@ jobs:

unit:
docker:
- image: cimg/node:16.20.1
- image: cimg/node:16.20.2

working_directory: ~/repo

Expand All @@ -50,7 +50,7 @@ jobs:

integration:
docker:
- image: cimg/node:16.20.1
- image: cimg/node:16.20.2

working_directory: ~/repo

Expand Down
21 changes: 21 additions & 0 deletions class/wallets/abstract-wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,27 @@ export class AbstractWallet {
}
}

// is it output descriptor?
if (this.secret.startsWith('wpkh(') || this.secret.startsWith('pkh(') || this.secret.startsWith('sh(')) {
const xpubIndex = Math.max(this.secret.indexOf('xpub'), this.secret.indexOf('ypub'), this.secret.indexOf('zpub'));
const fpAndPath = this.secret.substring(this.secret.indexOf('(') + 1, xpubIndex);
const xpub = this.secret.substring(xpubIndex).replace(/\(|\)/, '');
const pathIndex = fpAndPath.indexOf('/');
const path = 'm' + fpAndPath.substring(pathIndex);
const fp = fpAndPath.substring(0, pathIndex);

this._derivationPath = path;
const mfp = Buffer.from(fp, 'hex').reverse().toString('hex');
this.masterFingerprint = parseInt(mfp, 16);

if (this.secret.startsWith('wpkh(')) {
this.secret = this._xpubToZpub(xpub);
} else {
// nop
this.secret = xpub;
}
}

return this;
}

Expand Down
12 changes: 6 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@
"coinselect": "3.1.13",
"crypto-js": "4.1.1",
"dayjs": "1.11.9",
"detox": "20.9.1",
"detox": "20.11.3",
"ecpairgrs": "2.0.1",
"ecurve": "1.0.6",
"electrum-client": "https://github.com/BlueWallet/rn-electrum-client#76c0ea35e1a50c47f3a7f818d529ebd100161496",
Expand All @@ -149,7 +149,7 @@
"react-native-crypto": "2.2.0",
"react-native-default-preference": "1.4.4",
"react-native-device-info": "8.7.1",
"react-native-document-picker": "https://github.com/BlueWallet/react-native-document-picker#301c551970fd053d9f1b99a05e2236210ad9dcf8",
"react-native-document-picker": "https://github.com/BlueWallet/react-native-document-picker#857655cdddf17751c0fae1286a9121fda2a6d568",
"react-native-draggable-flatlist": "github:BlueWallet/react-native-draggable-flatlist#ebfddc4",
"react-native-elements": "3.4.3",
"react-native-fingerprint-scanner": "https://github.com/BlueWallet/react-native-fingerprint-scanner#ce644673681716335d786727bab998f7e632ab5e",
Expand All @@ -161,7 +161,7 @@
"react-native-image-picker": "4.8.5",
"react-native-ios-context-menu": "github:BlueWallet/react-native-ios-context-menu#v1.15.3",
"react-native-keychain": "8.1.2",
"react-native-linear-gradient": "2.8.0",
"react-native-linear-gradient": "2.8.2",
"react-native-localize": "3.0.2",
"react-native-modal": "13.0.1",
"react-native-navigation-bar-color": "https://github.com/BlueWallet/react-native-navigation-bar-color#3b2894ae62fbce99a3bd24105f0921cebaef5c94",
Expand All @@ -179,21 +179,21 @@
"react-native-screens": "3.20.0",
"react-native-secure-key-store": "https://github.com/BlueWallet/react-native-secure-key-store#2076b48",
"react-native-share": "8.2.2",
"react-native-svg": "13.10.0",
"react-native-svg": "13.11.0",
"react-native-tcp-socket": "5.6.2",
"react-native-tor": "0.1.8",
"react-native-vector-icons": "9.2.0",
"react-native-watch-connectivity": "1.1.0",
"react-native-webview": "12.4.0",
"react-native-widget-center": "https://github.com/BlueWallet/react-native-widget-center#a128c38",
"readable-stream": "3.6.2",
"realm": "11.10.1",
"realm": "11.10.2",
"rn-ldk": "github:BlueWallet/rn-ldk#v0.8.4",
"rn-nodeify": "10.3.0",
"scryptsy": "2.1.0",
"slip39": "https://github.com/BlueWallet/slip39-js",
"stream-browserify": "3.0.0",
"url": "0.11.0",
"url": "0.11.1",
"wifgrs": "2.0.6"
},
"react-native": {
Expand Down
8 changes: 5 additions & 3 deletions tests/e2e/bluewallet3.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ describe('BlueWallet UI Tests - import Watch-only wallet (zpub)', () => {
}
await device.launchApp({ newInstance: true });
await helperImportWallet(
'zpub6rDWXE4wbwefeCrHWehXJheXnti5F9PbpamDUeB5eFbqaY89x3jq86JADBuXpnJnSvRVwqkaTnyMaZERUg4BpxD9V4tSZfKeYh1ozPdL1xK',
// MNEMONICS_KEYSTONE
'zpub6s2EvLxwvDpaHNVP5vfordTyi8cH1fR8usmEjz7RsSQjfTTGU2qA5VEcEyYYBxpZAyBarJoTraB4VRJKVz97Au9jRNYfLAeeHC5UnRZbz8Y',
'watchOnly',
'Imported Watch-only',
'0.0001 GRS',
Expand Down Expand Up @@ -54,10 +55,11 @@ describe('BlueWallet UI Tests - import Watch-only wallet (zpub)', () => {
await element(by.id('advancedOptionsMenuButton')).tap();
await element(by.id('ImportQrTransactionButton')).tap(); // opens camera

// produced by real Keystone device using MNEMONICS_KEYSTONE
const unsignedPsbt =
'ur:bytes/tzahqumzwnlszqzjqgqqqqqp6uu247pvcz6zld9p77ghlnl753q8fgygggzv9ugjxsmggyy5gqcqqqqqqqq0llllluqepssqqqqqqqqqzcqpfkxmzh6ud2yrvcl37uyy9yswr2z4mx276qqqqqqqqqgpragvxqqqqqqqqqqkqq2tgxjzwa0000egemyzygsv92j2zdwvg5ejypszwe3qctjvrwul6t2ts7yhk8e5takxwzey2z70kdnykwd43jsptrzps95d6cp4gqqqsqqqqqyqqqqqpqqqqqqqqpqqqqqqqqq0vr0lj';
'UR:CRYPTO-PSBT/HDRNJOJKIDJYZMADAEGOAOAEAEAEADLFIAYKFPTOTIHSMNDLJTLFTYPAHTFHZESOAODIBNADFDCPFZZEKSSTTOJYKPRLJOAEAEAEAEAEZMZMZMZMADNBDSAEAEAEAEAEAECFKOPTBBCFBGNTGUVAEHNDPECFUYNBHKRNPMCMJNYTBKROYKLOPSAEAEAEAEAEADADCTBEDIAEAEAEAEAEAECMAEBBFTZSECYTJZTEKGOEKECAVOGHMTVWGYIAMHCSKOSWCPAMAXENRDWMCPOTZMHKGMFPNTHLMNDMCETOHLOXTANDAMEOTSURLFHHPLTSDPCSJTWSGACSRPLEYNVEGHAEAELAAEAEAELAAEAEAELAAEAEAEAEAEAEAEAEAEAEGETNJYFN';
const signedPsbt =
'ur:bytes/tyqjuurnvf607qgq2gpqqqqqq8tn32hc9nqtgta558mezl70l6jyqa9q3ppqfsh3zg6rdpqsj3qrqqqqqqqqpllllllsryxzqqqqqqqqqqtqq9xcmv2lt34gsdnr78msss5jpcdg2hvetmgqqqqqqqqpqy04pscqqqqqqqqqzcqpfdq6gfm4aaal9r8vsg3zps42fgf4e3znxgszqfmxyrpwfsdmnlfdfwrcj7clx30kcecty3gte7ekvjeekkx2q9vvgjpsg5pzzqxjc9xv3rlhu2n6u87pm94agwcmvcywwsx9k0jpvwyng8crytgrkcpzqae6amp5xy03x2lsklv5zgnmeht0grzns27tmsjtsg2j0ne2969kqyqsxpqpqqqqqgsxqfmxyrpwfsdmnlfdfwrcj7clx30kcecty3gte7ekvjeekkx2q9vvgxqk3htqx4qqqzqqqqqqsqqqqqyqqqqqqqqyqqqqqqqqear8ke';
'UR:CRYPTO-PSBT/HDWTJOJKIDJYZMADAEGOAOAEAEAEADLFIAYKFPTOTIHSMNDLJTLFTYPAHTFHZESOAODIBNADFDCPFZZEKSSTTOJYKPRLJOAEAEAEAEAEZMZMZMZMADNBDSAEAEAEAEAEAECFKOPTBBCFBGNTGUVAEHNDPECFUYNBHKRNPMCMJNYTBKROYKLOPSAEAEAEAEAEADADCTBEDIAEAEAEAEAEAECMAEBBFTZSECYTJZTEKGOEKECAVOGHMTVWGYIAMHCSKOSWADAYJEAOFLDYFYAOCXGEUTDNBDTNMKTOQDLASKMTTSCLCSHPOLGDBEHDBBZMNERLRFSFIDLTMHTLMTLYWKAOCXFRBWHGOSGYRLYKTSSSSSIEWDZOVOSTFNISKTBYCLLRLRHSHFCMSGTTVDRHURNSOLADCLAXENRDWMCPOTZMHKGMFPNTHLMNDMCETOHLOXTANDAMEOTSURLFHHPLTSDPCSJTWSGAAEAEDLFPLTSW';

// tapping 5 times invisible button is a backdoor:
for (let c = 0; c <= 5; c++) {
Expand Down
27 changes: 27 additions & 0 deletions tests/unit/watch-only-wallet.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,33 @@ describe('Watch only wallet', () => {
assert.ok(!w.useWithHardwareWalletEnabled());
});

it('can import wallet descriptor for BIP84 from Sparrow Wallet', async () => {
const payload =
'UR:CRYPTO-OUTPUT/TAADMWTAADDLOLAOWKAXHDCLAXINTOCTFTNNIERONTNYGALYEMAAWPHDAXDIEOWPJEGHKPGMKERHIABDTBLUBNMUMWAAHDCXFHSNBGTSGWSWPTDWVTDIHYHNHPLBBSJEOLSNFZBDIYJLTTPFIMEYTEECKTGSBZBDAHTAADEHOEADAEAOAEAMTAADDYOTADLNCSGHYKAEYKAEYKAOCYFNLBCYGMAXAXAYCYSRRTSPGADLMKBGTD';

const decoder = new BlueURDecoder();
decoder.receivePart(payload);
let data;
if (decoder.isComplete()) {
data = decoder.toString();
}

const w = new WatchOnlyWallet();
w.setSecret(data);
w.init();
assert.ok(w.valid());

assert.strictEqual(w.getMasterFingerprintHex(), '3c7f1a52');
assert.strictEqual(w.getDerivationPath(), "m/84'/0'/0'");

assert.strictEqual(w._getExternalAddressByIndex(0), 'bc1qr0y5c96xtfeulnzxnjl086f2njcmf8qmhenvpp');

assert.strictEqual(
w.getSecret(),
'zpub6rkkMBH6dE8bUPM9MC3WTMYQ3pDYR1kHnNDrqEGY3FotR4EUifR1S4xd7ynwczREFCbfWyk5S4mhzPL8YuGsCSgey1AwH7fk4w9AULpyDYL',
);
});

it('can combine signed PSBT and prepare it for broadcast', async () => {
const w = new WatchOnlyWallet();
w.setSecret('zpub6rjLjQVqVnj7crz9E4QWj4WgczmEseJq22u2B6k2HZr6NE2PQx3ZYg8BnbjN9kCfHymSeMd2EpwpM5iiz5Nrb3TzvddxW2RMcE3VXiWvk3Q');
Expand Down

0 comments on commit 4366728

Please sign in to comment.