mirror of
https://github.com/BlueWallet/BlueWallet.git
synced 2024-11-19 09:50:15 +01:00
153 lines
3.6 KiB
JavaScript
153 lines
3.6 KiB
JavaScript
import b58 from 'bs58check';
|
|
const HDNode = require('bip32');
|
|
|
|
export class MultisigCosigner {
|
|
constructor(data) {
|
|
this._data = data;
|
|
this._fp = false;
|
|
this._xpub = false;
|
|
this._path = false;
|
|
this._valid = false;
|
|
this._cosigners = [];
|
|
|
|
// is it plain simple Zpub/Ypub/xpub?
|
|
if (data.startsWith('Zpub') && MultisigCosigner.isXpubValid(data)) {
|
|
this._fp = '00000000';
|
|
this._xpub = data;
|
|
this._path = "m/48'/0'/0'/2'";
|
|
this._valid = true;
|
|
this._cosigners = [true];
|
|
return;
|
|
} else if (data.startsWith('Ypub') && MultisigCosigner.isXpubValid(data)) {
|
|
this._fp = '00000000';
|
|
this._xpub = data;
|
|
this._path = "m/48'/0'/0'/1'";
|
|
this._valid = true;
|
|
this._cosigners = [true];
|
|
return;
|
|
} else if (data.startsWith('xpub') && MultisigCosigner.isXpubValid(data)) {
|
|
this._fp = '00000000';
|
|
this._xpub = data;
|
|
this._path = "m/45'";
|
|
this._valid = true;
|
|
this._cosigners = [true];
|
|
return;
|
|
}
|
|
|
|
// is it wallet descriptor?
|
|
if (data.startsWith('[')) {
|
|
const end = data.indexOf(']');
|
|
const part = data.substr(1, end - 1).replace(/[h]/g, "'");
|
|
this._fp = part.split('/')[0];
|
|
const xpub = data.substr(end + 1);
|
|
|
|
if (MultisigCosigner.isXpubValid(xpub)) {
|
|
this._xpub = xpub;
|
|
this._path = 'm';
|
|
for (let c = 0; c < part.split('/').length; c++) {
|
|
if (c === 0) continue;
|
|
this._path += '/' + part.split('/')[c];
|
|
}
|
|
this._cosigners = [true];
|
|
this._valid = true;
|
|
return;
|
|
}
|
|
}
|
|
|
|
// is it cobo json?
|
|
try {
|
|
const json = JSON.parse(data);
|
|
if (json.xfp && json.xpub && json.path) {
|
|
this._fp = json.xfp;
|
|
this._xpub = json.xpub;
|
|
this._path = json.path;
|
|
this._cosigners = [true];
|
|
this._valid = true;
|
|
return;
|
|
}
|
|
} catch (_) {
|
|
this._valid = false;
|
|
}
|
|
|
|
// is it coldcard json?
|
|
try {
|
|
const json = JSON.parse(data);
|
|
if (json.p2sh && json.p2sh_deriv && json.xfp) {
|
|
const cc = new MultisigCosigner(MultisigCosigner.exportToJson(json.xfp, json.p2sh, json.p2sh_deriv));
|
|
this._valid = true;
|
|
this._cosigners.push(cc);
|
|
}
|
|
|
|
if (json.p2wsh_p2sh && json.p2wsh_p2sh_deriv && json.xfp) {
|
|
const cc = new MultisigCosigner(MultisigCosigner.exportToJson(json.xfp, json.p2wsh_p2sh, json.p2wsh_p2sh_deriv));
|
|
this._valid = true;
|
|
this._cosigners.push(cc);
|
|
}
|
|
|
|
if (json.p2wsh && json.p2wsh_deriv && json.xfp) {
|
|
const cc = new MultisigCosigner(MultisigCosigner.exportToJson(json.xfp, json.p2wsh, json.p2wsh_deriv));
|
|
this._valid = true;
|
|
this._cosigners.push(cc);
|
|
}
|
|
} catch (_) {
|
|
this._valid = false;
|
|
}
|
|
}
|
|
|
|
static _zpubToXpub(zpub) {
|
|
let data = b58.decode(zpub);
|
|
data = data.slice(4);
|
|
data = Buffer.concat([Buffer.from('0488b21e', 'hex'), data]);
|
|
|
|
return b58.encode(data);
|
|
}
|
|
|
|
static isXpubValid(key) {
|
|
let xpub;
|
|
|
|
try {
|
|
xpub = MultisigCosigner._zpubToXpub(key);
|
|
HDNode.fromBase58(xpub);
|
|
return true;
|
|
} catch (_) {}
|
|
|
|
return false;
|
|
}
|
|
|
|
static exportToJson(xfp, xpub, path) {
|
|
return JSON.stringify({
|
|
xfp: xfp,
|
|
xpub: xpub,
|
|
path: path,
|
|
});
|
|
}
|
|
|
|
isValid() {
|
|
return this._valid;
|
|
}
|
|
|
|
getFp() {
|
|
return this._fp;
|
|
}
|
|
|
|
getXpub() {
|
|
return this._xpub;
|
|
}
|
|
|
|
getPath() {
|
|
return this._path;
|
|
}
|
|
|
|
howManyCosignersWeHave() {
|
|
return this._cosigners.length;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @returns {Array.<MultisigCosigner>}
|
|
*/
|
|
getAllCosigners() {
|
|
return this._cosigners;
|
|
}
|
|
}
|