@abcpros/bitcore-wallet-service
Version:
A service for Mutisig HD Bitcoin Wallets
178 lines (157 loc) • 5 kB
text/typescript
import * as requestStream from 'request';
import * as request from 'request-promise-native';
import { URL } from 'url';
import logger from '../../logger';
const bitcoreLib = require('@abcpros/bitcore-lib');
const secp256k1 = require('secp256k1');
export class Client {
authKey: { bn: { toBuffer: (arg) => Buffer } };
baseUrl: string;
constructor(params) {
Object.assign(this, params);
}
getMessage(params: { method: string; url: string; payload?: any }) {
const { method, url, payload = {} } = params;
const parsedUrl = new URL(url);
return [method, parsedUrl.pathname + parsedUrl.search, JSON.stringify(payload)].join('|');
}
sign(params: { method: string; url: string; payload?: any }) {
const message = this.getMessage(params);
const privateKey = this.authKey.bn.toBuffer({ size: 32 });
const messageHash = bitcoreLib.crypto.Hash.sha256sha256(Buffer.from(message));
return secp256k1.sign(messageHash, privateKey).signature.toString('hex');
}
async register(params) {
const { payload } = params;
// allow you to overload the client's baseUrl
const { baseUrl = this.baseUrl } = payload;
const url = `${baseUrl}/wallet`;
const signature = this.sign({ method: 'POST', url, payload });
return request.post(url, {
headers: { 'x-signature': signature },
body: payload,
json: true
});
}
async getBalance(params) {
const { payload, pubKey, tokenAddress, multisigContractAddress } = params;
let query = '';
let apiUrl = `${this.baseUrl}/wallet/${pubKey}/balance`;
if (tokenAddress) {
query = `?tokenAddress=${tokenAddress}`;
}
if (multisigContractAddress) {
apiUrl = `${this.baseUrl}/address/${multisigContractAddress}/balance`;
}
const url = apiUrl + query;
const signature = this.sign({ method: 'GET', url, payload });
return request.get(url, {
headers: { 'x-signature': signature },
body: payload,
json: true
});
}
async getCheckData(params) {
const { payload, pubKey } = params;
const url = `${this.baseUrl}/wallet/${pubKey}/check`;
logger.debug('WALLET CHECK');
const signature = this.sign({ method: 'GET', url, payload });
return request.get(url, {
headers: { 'x-signature': signature },
body: payload,
json: true
});
}
async getAddressTxos(params) {
const { unspent, address } = params;
const args = unspent ? `?unspent=${unspent}` : '';
const url = `${this.baseUrl}/address/${address}${args}`;
return request.get(url, {
json: true
});
}
async getTx(params) {
const { txid } = params;
const url = `${this.baseUrl}/tx/${txid}`;
return request.get(url, {
json: true
});
}
async getCoins(params) {
const { payload, pubKey, includeSpent } = params;
var extra = '';
if (includeSpent) {
extra = `?includeSpent=${includeSpent}`;
}
const url = `${this.baseUrl}/wallet/${pubKey}/utxos${extra}`;
logger.debug('GET UTXOS:', url);
const signature = this.sign({ method: 'GET', url, payload });
return request.get(url, {
headers: { 'x-signature': signature },
body: payload,
json: true
});
}
async getCoinsForTx(params) {
const { txId } = params;
const url = `${this.baseUrl}/tx/${txId}/coins`;
logger.debug('GET COINS FOR TX:', url);
return request.get(url, {
json: true
});
}
listTransactions(params) {
const {
pubKey,
startBlock,
startDate,
endBlock,
endDate,
includeMempool,
tokenAddress,
multisigContractAddress
} = params;
let query = '';
let apiUrl = `${this.baseUrl}/wallet/${pubKey}/transactions?`;
if (startBlock) {
query += `startBlock=${startBlock}&`;
}
if (endBlock) {
query += `endBlock=${endBlock}&`;
}
if (tokenAddress) {
query += `tokenAddress=${tokenAddress}&`;
}
if (multisigContractAddress) {
apiUrl = `${this.baseUrl}/ethmultisig/transactions/${multisigContractAddress}?`;
}
if (includeMempool) {
query += 'includeMempool=true';
}
const url = apiUrl + query;
const signature = this.sign({ method: 'GET', url });
logger.debug('List transactions', url);
return requestStream.get(url, {
headers: { 'x-signature': signature },
json: true
});
}
async importAddresses(params) {
const { payload, pubKey } = params;
const url = `${this.baseUrl}/wallet/${pubKey}`;
logger.debug('addAddresses:', url, payload);
const signature = this.sign({ method: 'POST', url, payload });
const h = { 'x-signature': signature };
return request.post(url, {
headers: h,
body: payload,
json: true
});
}
async broadcast(params) {
const { payload } = params;
const url = `${this.baseUrl}/tx/send`;
logger.debug('Broadcast', url);
return request.post(url, { body: payload, json: true });
}
}