wip
This commit is contained in:
parent
3c53b1284c
commit
71ca53f8ba
@ -5,10 +5,17 @@ var BufferReader = bitcore.encoding.BufferReader;
|
|||||||
|
|
||||||
function Encoding(servicePrefix) {
|
function Encoding(servicePrefix) {
|
||||||
this.servicePrefix = 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) {
|
Encoding.prototype.encodeWalletTransactionKey = function(walletId, height) {
|
||||||
var buffers = [this.servicePrefix];
|
var buffers = [this.servicePrefix, this._subKeyMap.transaction];
|
||||||
|
|
||||||
var walletIdSizeBuffer = new Buffer(1);
|
var walletIdSizeBuffer = new Buffer(1);
|
||||||
walletIdSizeBuffer.writeUInt8(walletId.length);
|
walletIdSizeBuffer.writeUInt8(walletId.length);
|
||||||
@ -28,7 +35,7 @@ Encoding.prototype.encodeWalletTransactionKey = function(walletId, height) {
|
|||||||
|
|
||||||
Encoding.prototype.decodeWalletTransactionKey = function(buffer) {
|
Encoding.prototype.decodeWalletTransactionKey = function(buffer) {
|
||||||
var reader = new BufferReader(buffer);
|
var reader = new BufferReader(buffer);
|
||||||
reader.read(1);
|
reader.read(3);
|
||||||
|
|
||||||
var walletSize = reader.readUInt8();
|
var walletSize = reader.readUInt8();
|
||||||
var walletId = reader.read(walletSize).toString('utf8');
|
var walletId = reader.read(walletSize).toString('utf8');
|
||||||
@ -51,7 +58,7 @@ Encoding.prototype.decodeWalletTransactionValue = function(buffer) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Encoding.prototype.encodeWalletUtxoKey = function(walletId, txid, outputIndex) {
|
Encoding.prototype.encodeWalletUtxoKey = function(walletId, txid, outputIndex) {
|
||||||
var buffers = [this.servicePrefix];
|
var buffers = [this.servicePrefix, this._subKeyMap.utxo];
|
||||||
|
|
||||||
var walletIdSizeBuffer = new Buffer(1);
|
var walletIdSizeBuffer = new Buffer(1);
|
||||||
walletIdSizeBuffer.writeUInt8(walletId.length);
|
walletIdSizeBuffer.writeUInt8(walletId.length);
|
||||||
@ -76,7 +83,7 @@ Encoding.prototype.encodeWalletUtxoKey = function(walletId, txid, outputIndex) {
|
|||||||
|
|
||||||
Encoding.prototype.decodeWalletUtxoKey = function(buffer) {
|
Encoding.prototype.decodeWalletUtxoKey = function(buffer) {
|
||||||
var reader = new BufferReader(buffer);
|
var reader = new BufferReader(buffer);
|
||||||
reader.read(1);
|
reader.read(3);
|
||||||
|
|
||||||
var walletIdSize = reader.readUInt8();
|
var walletIdSize = reader.readUInt8();
|
||||||
var walletId = reader.read(walletIdSize).toString('utf8');
|
var walletId = reader.read(walletIdSize).toString('utf8');
|
||||||
@ -100,8 +107,8 @@ Encoding.prototype.encodeWalletUtxoValue = function(height, satoshis, scriptBuff
|
|||||||
Encoding.prototype.decodeWalletUtxoValue = function(buffer) {
|
Encoding.prototype.decodeWalletUtxoValue = function(buffer) {
|
||||||
var reader = new BufferReader(buffer);
|
var reader = new BufferReader(buffer);
|
||||||
var height = reader.readUInt32BE();
|
var height = reader.readUInt32BE();
|
||||||
var satoshis = reader.readDoubleBE();
|
var satoshis = buffer.readDoubleBE(4);
|
||||||
var scriptBuffer = reader.read(buffer.length - 12);
|
var scriptBuffer = reader.read(12, buffer.length - 12);
|
||||||
return {
|
return {
|
||||||
height: height,
|
height: height,
|
||||||
satoshis: satoshis,
|
satoshis: satoshis,
|
||||||
@ -110,7 +117,7 @@ Encoding.prototype.decodeWalletUtxoValue = function(buffer) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Encoding.prototype.encodeWalletUtxoSatoshisKey = function(walletId, satoshis, txid, outputIndex) {
|
Encoding.prototype.encodeWalletUtxoSatoshisKey = function(walletId, satoshis, txid, outputIndex) {
|
||||||
var buffers = [this.servicePrefix];
|
var buffers = [this.servicePrefix, this._subKeyMap.utxoSat];
|
||||||
|
|
||||||
var walletIdSizeBuffer = new Buffer(1);
|
var walletIdSizeBuffer = new Buffer(1);
|
||||||
walletIdSizeBuffer.writeUInt8(walletId.length);
|
walletIdSizeBuffer.writeUInt8(walletId.length);
|
||||||
@ -141,12 +148,12 @@ Encoding.prototype.encodeWalletUtxoSatoshisKey = function(walletId, satoshis, tx
|
|||||||
|
|
||||||
Encoding.prototype.decodeWalletUtxoSatoshisKey = function(buffer) {
|
Encoding.prototype.decodeWalletUtxoSatoshisKey = function(buffer) {
|
||||||
var reader = new BufferReader(buffer);
|
var reader = new BufferReader(buffer);
|
||||||
reader.read(1);
|
reader.read(3);
|
||||||
|
|
||||||
var walletIdSizeBuffer = reader.readUInt8();
|
var walletIdSize = reader.readUInt8();
|
||||||
var walletId = reader.read(walletIdSizeBuffer).toString('utf8');
|
var walletId = reader.read(walletIdSize).toString('utf8');
|
||||||
var satoshis = reader.readDoubleBE();
|
var satoshis = buffer.readDoubleBE(walletIdSize + 4);
|
||||||
var txid = reader.read(32).toString('hex');
|
var txid = reader.read(walletIdSize + 12, 32).toString('hex');
|
||||||
var outputIndex = reader.readUInt32BE();
|
var outputIndex = reader.readUInt32BE();
|
||||||
return {
|
return {
|
||||||
walletId: walletId,
|
walletId: walletId,
|
||||||
@ -173,9 +180,11 @@ Encoding.prototype.decodeWalletUtxoSatoshisValue = function(buffer) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Encoding.prototype.encodeWalletAddressesKey = function(walletId) {
|
Encoding.prototype.encodeWalletAddressesKey = function(walletId) {
|
||||||
var prefix = new Buffer('00', 'hex');
|
var prefix = this._subKeyMap.addresses;
|
||||||
var walletIdBuffer = new Buffer(walletId, 'hex');
|
var walletIdSizeBuffer = new Buffer(1);
|
||||||
return Buffer.concat([this.servicePrefix, prefix, walletIdBuffer]);
|
walletIdSizeBuffer.writeUInt8(walletId.length);
|
||||||
|
var walletIdBuffer = new Buffer(walletId, 'utf8');
|
||||||
|
return Buffer.concat([this.servicePrefix, prefix, walletIdSizeBuffer, walletIdBuffer]);
|
||||||
};
|
};
|
||||||
|
|
||||||
Encoding.prototype.decodeWalletAddressesKey = function(buffer) {
|
Encoding.prototype.decodeWalletAddressesKey = function(buffer) {
|
||||||
@ -201,19 +210,19 @@ Encoding.prototype.decodeWalletAddressesValue = function(buffer) {
|
|||||||
var reader = new BufferReader(buffer);
|
var reader = new BufferReader(buffer);
|
||||||
var addressesLength = reader.readUInt32BE();
|
var addressesLength = reader.readUInt32BE();
|
||||||
var addresses = [];
|
var addresses = [];
|
||||||
var addressSize = 0;
|
for(var i = 0; i < addressesLength; i++) {
|
||||||
for(var i = 0; i < addressesLength.length; i++) {
|
var addressSize = reader.readUInt8();
|
||||||
addressSize = reader.readUInt8(addressSize);
|
|
||||||
addresses.push(reader.read(addressSize).toString('utf8'));
|
addresses.push(reader.read(addressSize).toString('utf8'));
|
||||||
}
|
}
|
||||||
|
|
||||||
return addresses;
|
return addresses;
|
||||||
};
|
};
|
||||||
|
|
||||||
Encoding.prototype.encodeWalletBalanceKey = function(walletId) {
|
Encoding.prototype.encodeWalletBalanceKey = function(walletId) {
|
||||||
var prefix = new Buffer('01', 'hex');
|
var prefix = this._subKeyMap.balance;
|
||||||
var walletIdBuffer = new Buffer(walletId, 'hex');
|
var walletIdSizeBuffer = new Buffer(1);
|
||||||
return Buffer.concat([this.servicePrefix, prefix, walletIdBuffer]);
|
walletIdSizeBuffer.writeUInt8(walletId.length);
|
||||||
|
var walletIdBuffer = new Buffer(walletId, 'utf8');
|
||||||
|
return Buffer.concat([this.servicePrefix, prefix, walletIdSizeBuffer, walletIdBuffer]);
|
||||||
};
|
};
|
||||||
|
|
||||||
Encoding.prototype.decodeWalletBalanceKey = function(buffer) {
|
Encoding.prototype.decodeWalletBalanceKey = function(buffer) {
|
||||||
@ -222,14 +231,12 @@ Encoding.prototype.decodeWalletBalanceKey = function(buffer) {
|
|||||||
|
|
||||||
Encoding.prototype.encodeWalletBalanceValue = function(balance) {
|
Encoding.prototype.encodeWalletBalanceValue = function(balance) {
|
||||||
var balanceBuffer = new Buffer(8);
|
var balanceBuffer = new Buffer(8);
|
||||||
balanceBuffer.writeUInt32BE(balance);
|
balanceBuffer.writeDoubleBE(balance);
|
||||||
return balanceBuffer;
|
return balanceBuffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
Encoding.prototype.decodeWalletBalanceValue = function(buffer) {
|
Encoding.prototype.decodeWalletBalanceValue = function(buffer) {
|
||||||
var reader = new BufferReader(buffer);
|
var balance = buffer.readDoubleBE();
|
||||||
var balance = reader.readDoubleBE();
|
|
||||||
|
|
||||||
return balance;
|
return balance;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -34,7 +34,8 @@ inherits(WalletService, BaseService);
|
|||||||
|
|
||||||
WalletService.dependencies = [
|
WalletService.dependencies = [
|
||||||
'bitcoind',
|
'bitcoind',
|
||||||
'web'
|
'web',
|
||||||
|
'address'
|
||||||
];
|
];
|
||||||
|
|
||||||
WalletService.prototype.getAPIMethods = function() {
|
WalletService.prototype.getAPIMethods = function() {
|
||||||
@ -327,8 +328,7 @@ WalletService.prototype._loadAllAddresses = function(callback) {
|
|||||||
stream.on('data', function(data) {
|
stream.on('data', function(data) {
|
||||||
var key = self._encoding.decodeWalletAddressesKey(data.key);
|
var key = self._encoding.decodeWalletAddressesKey(data.key);
|
||||||
var value = self._encoding.decodeWalletAddressesValue(data.value);
|
var value = self._encoding.decodeWalletAddressesValue(data.value);
|
||||||
|
value.forEach(function(address) {
|
||||||
value.addresses.forEach(function(address) {
|
|
||||||
if(!self._addressMap[address]) {
|
if(!self._addressMap[address]) {
|
||||||
self._addressMap[address] = [];
|
self._addressMap[address] = [];
|
||||||
}
|
}
|
||||||
@ -392,7 +392,7 @@ WalletService.prototype._endpointUTXOs = function() {
|
|||||||
var options = {
|
var options = {
|
||||||
queryMempool: queryMempool
|
queryMempool: queryMempool
|
||||||
};
|
};
|
||||||
self._getUtxos(walletId, height, options, function(err, utxos) {
|
self._getUtxos(walletId, function(err, utxos) {
|
||||||
if(err) {
|
if(err) {
|
||||||
return utils.sendError(err, res);
|
return utils.sendError(err, res);
|
||||||
}
|
}
|
||||||
@ -422,7 +422,7 @@ WalletService.prototype._endpointGetBalance= function() {
|
|||||||
byAddress: byAddress
|
byAddress: byAddress
|
||||||
};
|
};
|
||||||
|
|
||||||
self._getBalance(walletId, height, options, function(err, result) {
|
self._getBalance(walletId, function(err, result) {
|
||||||
if(err) {
|
if(err) {
|
||||||
return utils.sendError(err, res);
|
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() {
|
WalletService.prototype._endpointGetAddresses = function() {
|
||||||
var self = this;
|
var self = this;
|
||||||
return function(req, res) {
|
return function(req, res) {
|
||||||
@ -461,15 +478,31 @@ WalletService.prototype._endpointPostAddresses = function() {
|
|||||||
}
|
}
|
||||||
var walletId = utils.getWalletId();
|
var walletId = utils.getWalletId();
|
||||||
|
|
||||||
// TODO make imdempotent
|
//if this is a post to /wallets, then it is expected that a new wallet is to be created
|
||||||
self._importAddresses(walletId, addresses, function(err) {
|
async.series([
|
||||||
if(err) {
|
function(next) {
|
||||||
return utils.sendError(err, res);
|
self._createWallet(walletId, [], function(err) {
|
||||||
}
|
if(err) {
|
||||||
res.status(201).jsonp({
|
return next(err);
|
||||||
walletId: walletId
|
}
|
||||||
|
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) {
|
WalletService.prototype._getAddresses = function(walletId, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var key = self._encoding.encodeWalletAddressKey(walletId);
|
var key = self._encoding.encodeWalletAddressesKey(walletId);
|
||||||
self.store.get(key, function(err, value) {
|
self.store.get(key, function(err, value) {
|
||||||
if(err) {
|
if(err) {
|
||||||
return callback(err);
|
return callback(err);
|
||||||
@ -705,10 +753,17 @@ WalletService.prototype._getAddresses = function(walletId, callback) {
|
|||||||
if (!value) {
|
if (!value) {
|
||||||
return callback(null, []);
|
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) {
|
WalletService.prototype._importAddresses = function(walletId, addresses, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
@ -720,7 +775,7 @@ WalletService.prototype._importAddresses = function(walletId, addresses, callbac
|
|||||||
async.parallel(
|
async.parallel(
|
||||||
[
|
[
|
||||||
self._getUTXOIndexOperations.bind(self, walletId, addresses),
|
self._getUTXOIndexOperations.bind(self, walletId, addresses),
|
||||||
self._getTxidOperations.bind(self, walletId, addresses)
|
self._getTxidIndexOperations.bind(self, walletId, addresses)
|
||||||
],
|
],
|
||||||
function(err, results) {
|
function(err, results) {
|
||||||
if(err) {
|
if(err) {
|
||||||
@ -730,8 +785,8 @@ WalletService.prototype._importAddresses = function(walletId, addresses, callbac
|
|||||||
var operations = results[0].concat(results[1]);
|
var operations = results[0].concat(results[1]);
|
||||||
operations.push({
|
operations.push({
|
||||||
type: 'put',
|
type: 'put',
|
||||||
key: self._encoding.encodeWalletAddressKey(walletId),
|
key: self._encoding.encodeWalletAddressesKey(walletId),
|
||||||
value: self._encoding.encodeWalletAddressValue(oldAddresses.concat(addresses))
|
value: self._encoding.encodeWalletAddressesValue(oldAddresses.concat(addresses))
|
||||||
});
|
});
|
||||||
|
|
||||||
self.store.batch(operations, function(err) {
|
self.store.batch(operations, function(err) {
|
||||||
@ -772,7 +827,7 @@ WalletService.prototype._getUTXOIndexOperations = function(walletId, addresses,
|
|||||||
balance = initialBalance;
|
balance = initialBalance;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.services.address.getUnspentOutputs(addresses, function(err, utxos) {
|
self.node.services.address.getUnspentOutputs(addresses, false, function(err, utxos) {
|
||||||
if(err) {
|
if(err) {
|
||||||
return callback(err);
|
return callback(err);
|
||||||
}
|
}
|
||||||
@ -814,7 +869,7 @@ WalletService.prototype._getTxidIndexOperations = function(walletId, addresses,
|
|||||||
var txids = {};
|
var txids = {};
|
||||||
|
|
||||||
async.eachLimit(addresses, 10, function(address, next) {
|
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) {
|
if(err) {
|
||||||
return next(err);
|
return next(err);
|
||||||
}
|
}
|
||||||
@ -840,7 +895,7 @@ WalletService.prototype._getTxidIndexOperations = function(walletId, addresses,
|
|||||||
};
|
};
|
||||||
|
|
||||||
WalletService.prototype._storeAddresses = function(walletId, addresses, callback) {
|
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);
|
var value = this._encoding.encodeWalletValue(addresses);
|
||||||
this.store.put(key, value, callback);
|
this.store.put(key, value, callback);
|
||||||
};
|
};
|
||||||
@ -875,6 +930,9 @@ WalletService.prototype.setupRoutes = function(app) {
|
|||||||
app.get('/wallets/:walletId',
|
app.get('/wallets/:walletId',
|
||||||
s._endpointGetAddresses()
|
s._endpointGetAddresses()
|
||||||
);
|
);
|
||||||
|
app.delete('/wallets/:walletId',
|
||||||
|
s._endpointRemoveWallet()
|
||||||
|
);
|
||||||
app.put('/wallets/:walletId/addresses',
|
app.put('/wallets/:walletId/addresses',
|
||||||
s._endpointPutAddresses()
|
s._endpointPutAddresses()
|
||||||
);
|
);
|
||||||
@ -886,7 +944,6 @@ WalletService.prototype.setupRoutes = function(app) {
|
|||||||
v.checkAddresses,
|
v.checkAddresses,
|
||||||
s._endpointPostAddresses()
|
s._endpointPostAddresses()
|
||||||
);
|
);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
WalletService.prototype.getRoutePrefix = function() {
|
WalletService.prototype.getRoutePrefix = function() {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user