2019-02-25 20:33:29 -05:00
|
|
|
import { BitcoinUnit, Chain } from '../models/bitcoinUnits';
|
2019-10-02 23:06:47 -04:00
|
|
|
const createHash = require('create-hash');
|
2020-02-27 14:24:26 +00:00
|
|
|
|
2018-03-20 22:41:07 +02:00
|
|
|
export class AbstractWallet {
|
2018-12-28 16:52:06 +01:00
|
|
|
static type = 'abstract';
|
|
|
|
static typeReadable = 'abstract';
|
|
|
|
|
|
|
|
static fromJson(obj) {
|
|
|
|
let obj2 = JSON.parse(obj);
|
|
|
|
let temp = new this();
|
|
|
|
for (let key2 of Object.keys(obj2)) {
|
|
|
|
temp[key2] = obj2[key2];
|
|
|
|
}
|
|
|
|
|
|
|
|
return temp;
|
|
|
|
}
|
|
|
|
|
2018-03-20 22:41:07 +02:00
|
|
|
constructor() {
|
2018-12-28 18:02:39 +01:00
|
|
|
this.type = this.constructor.type;
|
|
|
|
this.typeReadable = this.constructor.typeReadable;
|
2018-03-20 22:41:07 +02:00
|
|
|
this.label = '';
|
|
|
|
this.secret = ''; // private key or recovery phrase
|
|
|
|
this.balance = 0;
|
2018-07-05 01:56:31 +01:00
|
|
|
this.unconfirmed_balance = 0;
|
2018-03-20 22:41:07 +02:00
|
|
|
this.transactions = [];
|
|
|
|
this._address = false; // cache
|
|
|
|
this.utxo = [];
|
2018-07-28 21:19:11 +01:00
|
|
|
this._lastTxFetch = 0;
|
|
|
|
this._lastBalanceFetch = 0;
|
2018-12-13 23:31:13 -05:00
|
|
|
this.preferredBalanceUnit = BitcoinUnit.BTC;
|
2019-02-25 20:33:29 -05:00
|
|
|
this.chain = Chain.ONCHAIN;
|
2019-08-03 17:29:15 -04:00
|
|
|
this.hideBalance = false;
|
2019-12-24 21:35:47 -06:00
|
|
|
this.userHasSavedExport = false;
|
2018-03-20 22:41:07 +02:00
|
|
|
}
|
|
|
|
|
2019-10-02 23:06:47 -04:00
|
|
|
getID() {
|
|
|
|
return createHash('sha256')
|
|
|
|
.update(this.getSecret())
|
|
|
|
.digest()
|
|
|
|
.toString('hex');
|
|
|
|
}
|
|
|
|
|
2018-12-28 16:52:06 +01:00
|
|
|
getTransactions() {
|
|
|
|
return this.transactions;
|
2018-03-20 22:41:07 +02:00
|
|
|
}
|
|
|
|
|
2019-12-24 21:35:47 -06:00
|
|
|
getUserHasSavedExport() {
|
|
|
|
return this.userHasSavedExport;
|
|
|
|
}
|
|
|
|
|
|
|
|
setUserHasSavedExport(value) {
|
|
|
|
this.userHasSavedExport = value;
|
|
|
|
}
|
|
|
|
|
2018-03-20 22:41:07 +02:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @returns {string}
|
|
|
|
*/
|
|
|
|
getLabel() {
|
2019-12-21 14:35:34 -05:00
|
|
|
if (this.label.trim().length === 0) {
|
|
|
|
return 'Wallet';
|
|
|
|
}
|
2018-03-20 22:41:07 +02:00
|
|
|
return this.label;
|
|
|
|
}
|
|
|
|
|
2019-08-14 15:00:30 -04:00
|
|
|
getXpub() {
|
|
|
|
return this._address;
|
|
|
|
}
|
|
|
|
|
2019-05-05 23:17:31 +01:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @returns {number} Available to spend amount, int, in sats
|
|
|
|
*/
|
2018-03-20 22:41:07 +02:00
|
|
|
getBalance() {
|
|
|
|
return this.balance;
|
|
|
|
}
|
|
|
|
|
2018-12-13 23:31:13 -05:00
|
|
|
getPreferredBalanceUnit() {
|
2018-12-23 13:18:27 -05:00
|
|
|
for (let value of Object.values(BitcoinUnit)) {
|
|
|
|
if (value === this.preferredBalanceUnit) {
|
|
|
|
return this.preferredBalanceUnit;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return BitcoinUnit.BTC;
|
2018-12-13 23:31:13 -05:00
|
|
|
}
|
|
|
|
|
2018-07-07 12:30:50 +01:00
|
|
|
allowReceive() {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
allowSend() {
|
2018-10-06 01:45:24 +01:00
|
|
|
return true;
|
2018-07-07 12:30:50 +01:00
|
|
|
}
|
|
|
|
|
2019-08-04 20:33:15 +01:00
|
|
|
allowSendMax(): boolean {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-10-31 20:14:28 +00:00
|
|
|
allowRBF() {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-06-08 00:06:21 +01:00
|
|
|
allowBatchSend() {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-09-11 21:59:11 -04:00
|
|
|
weOwnAddress(address) {
|
2020-03-09 18:51:34 +00:00
|
|
|
throw Error('not implemented');
|
2019-09-11 21:59:11 -04:00
|
|
|
}
|
|
|
|
|
2018-07-05 01:56:31 +01:00
|
|
|
/**
|
|
|
|
* Returns delta of unconfirmed balance. For example, if theres no
|
|
|
|
* unconfirmed balance its 0
|
|
|
|
*
|
|
|
|
* @return {number}
|
|
|
|
*/
|
|
|
|
getUnconfirmedBalance() {
|
|
|
|
return this.unconfirmed_balance;
|
|
|
|
}
|
|
|
|
|
2018-03-20 22:41:07 +02:00
|
|
|
setLabel(newLabel) {
|
|
|
|
this.label = newLabel;
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
getSecret() {
|
|
|
|
return this.secret;
|
|
|
|
}
|
|
|
|
|
|
|
|
setSecret(newSecret) {
|
2020-03-09 18:51:34 +00:00
|
|
|
this.secret = newSecret
|
|
|
|
.trim()
|
|
|
|
.replace('bitcoin:', '')
|
|
|
|
.replace('BITCOIN:', '');
|
|
|
|
|
|
|
|
if (this.secret.startsWith('BC1')) this.secret = this.secret.toLowerCase();
|
2020-02-24 21:45:14 +00:00
|
|
|
|
|
|
|
try {
|
|
|
|
const parsedSecret = JSON.parse(this.secret);
|
|
|
|
if (parsedSecret && parsedSecret.keystore && parsedSecret.keystore.xpub) {
|
|
|
|
let masterFingerprint = false;
|
|
|
|
if (parsedSecret.keystore.ckcc_xfp) {
|
|
|
|
// It is a ColdCard Hardware Wallet
|
|
|
|
masterFingerprint = Number(parsedSecret.keystore.ckcc_xfp);
|
|
|
|
}
|
|
|
|
this.secret = parsedSecret.keystore.xpub;
|
|
|
|
this.masterFingerprint = masterFingerprint;
|
|
|
|
}
|
|
|
|
} catch (_) {}
|
2018-03-20 22:41:07 +02:00
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2018-06-24 23:22:46 +01:00
|
|
|
getLatestTransactionTime() {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-03-20 22:41:07 +02:00
|
|
|
// createTx () { throw Error('not implemented') }
|
2019-10-16 22:38:23 +01:00
|
|
|
|
|
|
|
getAddress() {
|
|
|
|
throw Error('not implemented');
|
|
|
|
}
|
|
|
|
|
|
|
|
getAddressAsync() {
|
|
|
|
return new Promise(resolve => resolve(this.getAddress()));
|
|
|
|
}
|
2020-02-27 14:24:26 +00:00
|
|
|
|
|
|
|
useWithHardwareWalletEnabled() {
|
|
|
|
return false;
|
|
|
|
}
|
2018-03-20 22:41:07 +02:00
|
|
|
}
|