This commit is contained in:
Chris Kleeschulte 2017-02-04 13:42:32 -05:00
parent 3c53b1284c
commit 71ca53f8ba
2 changed files with 112 additions and 48 deletions

View File

@ -5,10 +5,17 @@ var BufferReader = bitcore.encoding.BufferReader;
function Encoding(servicePrefix) {
this.servicePrefix = servicePrefix;
this._subKeyMap = {
transaction: new Buffer('00', 'hex'),
addresses: new Buffer('01', 'hex'),
utxo: new Buffer('02', 'hex'),
utxoSat: new Buffer('03', 'hex'),
balance: new Buffer('04', 'hex')
};
}
Encoding.prototype.encodeWalletTransactionKey = function(walletId, height) {
var buffers = [this.servicePrefix];
var buffers = [this.servicePrefix, this._subKeyMap.transaction];
var walletIdSizeBuffer = new Buffer(1);
walletIdSizeBuffer.writeUInt8(walletId.length);
@ -28,7 +35,7 @@ Encoding.prototype.encodeWalletTransactionKey = function(walletId, height) {
Encoding.prototype.decodeWalletTransactionKey = function(buffer) {
var reader = new BufferReader(buffer);
reader.read(1);
reader.read(3);
var walletSize = reader.readUInt8();
var walletId = reader.read(walletSize).toString('utf8');
@ -51,7 +58,7 @@ Encoding.prototype.decodeWalletTransactionValue = function(buffer) {
};
Encoding.prototype.encodeWalletUtxoKey = function(walletId, txid, outputIndex) {
var buffers = [this.servicePrefix];
var buffers = [this.servicePrefix, this._subKeyMap.utxo];
var walletIdSizeBuffer = new Buffer(1);
walletIdSizeBuffer.writeUInt8(walletId.length);
@ -76,7 +83,7 @@ Encoding.prototype.encodeWalletUtxoKey = function(walletId, txid, outputIndex) {
Encoding.prototype.decodeWalletUtxoKey = function(buffer) {
var reader = new BufferReader(buffer);
reader.read(1);
reader.read(3);
var walletIdSize = reader.readUInt8();
var walletId = reader.read(walletIdSize).toString('utf8');
@ -100,8 +107,8 @@ Encoding.prototype.encodeWalletUtxoValue = function(height, satoshis, scriptBuff
Encoding.prototype.decodeWalletUtxoValue = function(buffer) {
var reader = new BufferReader(buffer);
var height = reader.readUInt32BE();
var satoshis = reader.readDoubleBE();
var scriptBuffer = reader.read(buffer.length - 12);
var satoshis = buffer.readDoubleBE(4);
var scriptBuffer = reader.read(12, buffer.length - 12);
return {
height: height,
satoshis: satoshis,
@ -110,7 +117,7 @@ Encoding.prototype.decodeWalletUtxoValue = function(buffer) {
};
Encoding.prototype.encodeWalletUtxoSatoshisKey = function(walletId, satoshis, txid, outputIndex) {
var buffers = [this.servicePrefix];
var buffers = [this.servicePrefix, this._subKeyMap.utxoSat];
var walletIdSizeBuffer = new Buffer(1);
walletIdSizeBuffer.writeUInt8(walletId.length);
@ -141,12 +148,12 @@ Encoding.prototype.encodeWalletUtxoSatoshisKey = function(walletId, satoshis, tx
Encoding.prototype.decodeWalletUtxoSatoshisKey = function(buffer) {
var reader = new BufferReader(buffer);
reader.read(1);
reader.read(3);
var walletIdSizeBuffer = reader.readUInt8();
var walletId = reader.read(walletIdSizeBuffer).toString('utf8');
var satoshis = reader.readDoubleBE();
var txid = reader.read(32).toString('hex');
var walletIdSize = reader.readUInt8();
var walletId = reader.read(walletIdSize).toString('utf8');
var satoshis = buffer.readDoubleBE(walletIdSize + 4);
var txid = reader.read(walletIdSize + 12, 32).toString('hex');
var outputIndex = reader.readUInt32BE();
return {
walletId: walletId,
@ -173,9 +180,11 @@ Encoding.prototype.decodeWalletUtxoSatoshisValue = function(buffer) {
};
Encoding.prototype.encodeWalletAddressesKey = function(walletId) {
var prefix = new Buffer('00', 'hex');
var walletIdBuffer = new Buffer(walletId, 'hex');
return Buffer.concat([this.servicePrefix, prefix, walletIdBuffer]);
var prefix = this._subKeyMap.addresses;
var walletIdSizeBuffer = new Buffer(1);
walletIdSizeBuffer.writeUInt8(walletId.length);
var walletIdBuffer = new Buffer(walletId, 'utf8');
return Buffer.concat([this.servicePrefix, prefix, walletIdSizeBuffer, walletIdBuffer]);
};
Encoding.prototype.decodeWalletAddressesKey = function(buffer) {
@ -201,19 +210,19 @@ Encoding.prototype.decodeWalletAddressesValue = function(buffer) {
var reader = new BufferReader(buffer);
var addressesLength = reader.readUInt32BE();
var addresses = [];
var addressSize = 0;
for(var i = 0; i < addressesLength.length; i++) {
addressSize = reader.readUInt8(addressSize);
for(var i = 0; i < addressesLength; i++) {
var addressSize = reader.readUInt8();
addresses.push(reader.read(addressSize).toString('utf8'));
}
return addresses;
};
Encoding.prototype.encodeWalletBalanceKey = function(walletId) {
var prefix = new Buffer('01', 'hex');
var walletIdBuffer = new Buffer(walletId, 'hex');
return Buffer.concat([this.servicePrefix, prefix, walletIdBuffer]);
var prefix = this._subKeyMap.balance;
var walletIdSizeBuffer = new Buffer(1);
walletIdSizeBuffer.writeUInt8(walletId.length);
var walletIdBuffer = new Buffer(walletId, 'utf8');
return Buffer.concat([this.servicePrefix, prefix, walletIdSizeBuffer, walletIdBuffer]);
};
Encoding.prototype.decodeWalletBalanceKey = function(buffer) {
@ -222,14 +231,12 @@ Encoding.prototype.decodeWalletBalanceKey = function(buffer) {
Encoding.prototype.encodeWalletBalanceValue = function(balance) {
var balanceBuffer = new Buffer(8);
balanceBuffer.writeUInt32BE(balance);
balanceBuffer.writeDoubleBE(balance);
return balanceBuffer;
};
Encoding.prototype.decodeWalletBalanceValue = function(buffer) {
var reader = new BufferReader(buffer);
var balance = reader.readDoubleBE();
var balance = buffer.readDoubleBE();
return balance;
};

View File

@ -34,7 +34,8 @@ inherits(WalletService, BaseService);
WalletService.dependencies = [
'bitcoind',
'web'
'web',
'address'
];
WalletService.prototype.getAPIMethods = function() {
@ -327,8 +328,7 @@ WalletService.prototype._loadAllAddresses = function(callback) {
stream.on('data', function(data) {
var key = self._encoding.decodeWalletAddressesKey(data.key);
var value = self._encoding.decodeWalletAddressesValue(data.value);
value.addresses.forEach(function(address) {
value.forEach(function(address) {
if(!self._addressMap[address]) {
self._addressMap[address] = [];
}
@ -392,7 +392,7 @@ WalletService.prototype._endpointUTXOs = function() {
var options = {
queryMempool: queryMempool
};
self._getUtxos(walletId, height, options, function(err, utxos) {
self._getUtxos(walletId, function(err, utxos) {
if(err) {
return utils.sendError(err, res);
}
@ -422,7 +422,7 @@ WalletService.prototype._endpointGetBalance= function() {
byAddress: byAddress
};
self._getBalance(walletId, height, options, function(err, result) {
self._getBalance(walletId, function(err, result) {
if(err) {
return utils.sendError(err, res);
}
@ -431,6 +431,23 @@ WalletService.prototype._endpointGetBalance= function() {
};
};
WalletService.prototype._endpointRemoveWallet = function() {
var self = this;
return function(req, res) {
var walletId = req.params.walletId;
self._removeWallet(walletId, function(err) {
if(err) {
return utils.sendError(err, res);
}
res.status(200).jsonp({
walletId: walletId,
result: 'removed'
});
});
};
};
WalletService.prototype._endpointGetAddresses = function() {
var self = this;
return function(req, res) {
@ -461,15 +478,31 @@ WalletService.prototype._endpointPostAddresses = function() {
}
var walletId = utils.getWalletId();
// TODO make imdempotent
self._importAddresses(walletId, addresses, function(err) {
if(err) {
return utils.sendError(err, res);
}
res.status(201).jsonp({
walletId: walletId
//if this is a post to /wallets, then it is expected that a new wallet is to be created
async.series([
function(next) {
self._createWallet(walletId, [], function(err) {
if(err) {
return next(err);
}
next();
});
}, function(next) {
// TODO make imdempotent
self._importAddresses(walletId, addresses, function(err) {
if(err) {
return next(err);
}
next();
});
}], function(err) {
if(err) {
return utils.sendError(err, res);
}
res.status(201).jsonp({
walletId: walletId
});
});
});
};
};
@ -695,9 +728,24 @@ WalletService.prototype._getTransactions = function(walletId, options, callback)
//}
};
WalletService.prototype._removeWallet = function(walletId, callback) {
var self = this;
var boundary = self._encoding.encodeWalletAddressesKey(walletId);
//wallet tz
// wallet addresses
// utxo
// utxosat
//wallet balance
var txStream = self.store.createReadStream({
gte: boundary
lte: boundary
});
};
WalletService.prototype._getAddresses = function(walletId, callback) {
var self = this;
var key = self._encoding.encodeWalletAddressKey(walletId);
var key = self._encoding.encodeWalletAddressesKey(walletId);
self.store.get(key, function(err, value) {
if(err) {
return callback(err);
@ -705,10 +753,17 @@ WalletService.prototype._getAddresses = function(walletId, callback) {
if (!value) {
return callback(null, []);
}
callback(null, self._encoding.decodeWalletAddressValue(value));
callback(null, self._encoding.decodeWalletAddressesValue(value));
});
};
WalletService.prototype._createWallet = function(walletId, addresses, callback) {
var self = this;
var key = self._encoding.encodeWalletAddressesKey(walletId);
var value = self._encoding.encodeWalletAddressesValue(addresses);
this.store.put(key, value, callback);
};
WalletService.prototype._importAddresses = function(walletId, addresses, callback) {
var self = this;
@ -720,7 +775,7 @@ WalletService.prototype._importAddresses = function(walletId, addresses, callbac
async.parallel(
[
self._getUTXOIndexOperations.bind(self, walletId, addresses),
self._getTxidOperations.bind(self, walletId, addresses)
self._getTxidIndexOperations.bind(self, walletId, addresses)
],
function(err, results) {
if(err) {
@ -730,8 +785,8 @@ WalletService.prototype._importAddresses = function(walletId, addresses, callbac
var operations = results[0].concat(results[1]);
operations.push({
type: 'put',
key: self._encoding.encodeWalletAddressKey(walletId),
value: self._encoding.encodeWalletAddressValue(oldAddresses.concat(addresses))
key: self._encoding.encodeWalletAddressesKey(walletId),
value: self._encoding.encodeWalletAddressesValue(oldAddresses.concat(addresses))
});
self.store.batch(operations, function(err) {
@ -772,7 +827,7 @@ WalletService.prototype._getUTXOIndexOperations = function(walletId, addresses,
balance = initialBalance;
}
self.services.address.getUnspentOutputs(addresses, function(err, utxos) {
self.node.services.address.getUnspentOutputs(addresses, false, function(err, utxos) {
if(err) {
return callback(err);
}
@ -814,7 +869,7 @@ WalletService.prototype._getTxidIndexOperations = function(walletId, addresses,
var txids = {};
async.eachLimit(addresses, 10, function(address, next) {
self.services.address.getAddressTxidsWithHeights(address, {}, function(err, tmpTxids) {
self.node.services.address.getAddressTxidsWithHeights(address, {}, function(err, tmpTxids) {
if(err) {
return next(err);
}
@ -840,7 +895,7 @@ WalletService.prototype._getTxidIndexOperations = function(walletId, addresses,
};
WalletService.prototype._storeAddresses = function(walletId, addresses, callback) {
var key = this._encoding.encodeWalletAddressKey(walletId);
var key = this._encoding.encodeWalletAddressesKey(walletId);
var value = this._encoding.encodeWalletValue(addresses);
this.store.put(key, value, callback);
};
@ -875,6 +930,9 @@ WalletService.prototype.setupRoutes = function(app) {
app.get('/wallets/:walletId',
s._endpointGetAddresses()
);
app.delete('/wallets/:walletId',
s._endpointRemoveWallet()
);
app.put('/wallets/:walletId/addresses',
s._endpointPutAddresses()
);
@ -886,7 +944,6 @@ WalletService.prototype.setupRoutes = function(app) {
v.checkAddresses,
s._endpointPostAddresses()
);
};
WalletService.prototype.getRoutePrefix = function() {