Browse Source

Merge pull request #273 from isocolsky/email_link_to_tx

Allow link to tx in emails
activeAddress
Matias Alejo Garcia 9 years ago
parent
commit
4edb212c49
  1. 4
      lib/blockchainexplorers/insight.js
  2. 5
      lib/blockchainmonitor.js
  3. 33
      lib/emailservice.js
  4. 2
      package.json
  5. 1
      test/blockchainexplorer.js
  6. 15
      test/integration/server.js

4
lib/blockchainexplorers/insight.js

@ -108,4 +108,8 @@ Insight.prototype.initSocket = function() {
return socket; return socket;
}; };
Insight.prototype.getPublicUrlForTx = function(txid) {
return this.url + '/tx/' + txid;
};
module.exports = Insight; module.exports = Insight;

5
lib/blockchainmonitor.js

@ -28,7 +28,10 @@ BlockchainMonitor.prototype.start = function(opts, cb) {
if (opts.blockchainExplorers) { if (opts.blockchainExplorers) {
explorer = opts.blockchainExplorers[network]; explorer = opts.blockchainExplorers[network];
} else { } else {
var config = opts.blockchainExplorerOpts[network] || {}; var config = {}
if (opts.blockchainExplorerOpts && opts.blockchainExplorerOpts[network]) {
config = opts.blockchainExplorerOpts[network];
}
var explorer = new BlockchainExplorer({ var explorer = new BlockchainExplorer({
provider: config.provider, provider: config.provider,
network: network, network: network,

33
lib/emailservice.js

@ -14,6 +14,7 @@ var WalletUtils = require('bitcore-wallet-utils');
var Storage = require('./storage'); var Storage = require('./storage');
var MessageBroker = require('./messagebroker'); var MessageBroker = require('./messagebroker');
var Lock = require('./lock'); var Lock = require('./lock');
var BlockchainExplorer = require('./blockchainexplorer');
var Model = require('./model'); var Model = require('./model');
@ -95,6 +96,27 @@ EmailService.prototype.start = function(opts, cb) {
self.lock = opts.lock || new Lock(opts.lockOpts); self.lock = opts.lock || new Lock(opts.lockOpts);
done(); done();
}, },
function(done) {
self.explorers = _.indexBy(_.map(['livenet', 'testnet'], function(network) {
var explorer;
if (opts.blockchainExplorers) {
explorer = opts.blockchainExplorers[network];
} else {
var config = {}
if (opts.blockchainExplorerOpts && opts.blockchainExplorerOpts[network]) {
config = opts.blockchainExplorerOpts[network];
}
var explorer = new BlockchainExplorer({
provider: config.provider,
network: network,
url: config.url,
});
}
$.checkState(explorer);
return explorer;
}), 'network');
done();
},
function(done) { function(done) {
self.mailer = opts.mailer || nodemailer.createTransport(opts.emailOpts); self.mailer = opts.mailer || nodemailer.createTransport(opts.emailOpts);
self.subjectPrefix = opts.emailOpts.subjectPrefix || '[Wallet service]'; self.subjectPrefix = opts.emailOpts.subjectPrefix || '[Wallet service]';
@ -109,8 +131,11 @@ EmailService.prototype.start = function(opts, cb) {
}); });
}; };
EmailService.prototype._compileTemplate = function(template) { EmailService.prototype._compileTemplate = function(template, extension) {
var lines = template.split('\n'); var lines = template.split('\n');
if (extension == '.html') {
lines.unshift('');
}
return { return {
subject: lines[0], subject: lines[0],
body: _.rest(lines).join('\n'), body: _.rest(lines).join('\n'),
@ -135,7 +160,7 @@ EmailService.prototype._loadTemplate = function(emailType, recipient, extension,
self._readTemplateFile(recipient.language, emailType.filename + extension, function(err, template) { self._readTemplateFile(recipient.language, emailType.filename + extension, function(err, template) {
if (err) return cb(err); if (err) return cb(err);
return cb(null, self._compileTemplate(template)); return cb(null, self._compileTemplate(template, extension));
}); });
}; };
@ -228,6 +253,10 @@ EmailService.prototype._getDataForTemplate = function(notification, recipient, c
}); });
data.rejectorsNames = rejectors.join(', '); data.rejectorsNames = rejectors.join(', ');
} }
if (_.contains(['NewIncomingTx', 'NewOutgoingTx'], notification.type) && data.txid) {
data.urlForTx = self.explorers[wallet.network].getPublicUrlForTx(data.txid);
}
return cb(null, data); return cb(null, data);
}); });
}; };

2
package.json

@ -2,7 +2,7 @@
"name": "bitcore-wallet-service", "name": "bitcore-wallet-service",
"description": "A service for Mutisig HD Bitcoin Wallets", "description": "A service for Mutisig HD Bitcoin Wallets",
"author": "BitPay Inc", "author": "BitPay Inc",
"version": "0.0.40", "version": "0.0.41",
"keywords": [ "keywords": [
"bitcoin", "bitcoin",
"copay", "copay",

1
test/blockchainexplorer.js

@ -20,6 +20,7 @@ describe('Blockchain explorer', function() {
exp.should.respondTo('getAddressActivity'); exp.should.respondTo('getAddressActivity');
exp.should.respondTo('getUnspentUtxos'); exp.should.respondTo('getUnspentUtxos');
exp.should.respondTo('initSocket'); exp.should.respondTo('initSocket');
exp.should.respondTo('getPublicUrlForTx');
var exp = new BlockchainExplorer({ var exp = new BlockchainExplorer({
provider: 'insight', provider: 'insight',
network: 'livenet', network: 'livenet',

15
test/integration/server.js

@ -353,7 +353,7 @@ describe('Wallet service', function() {
var _readTemplateFile_old = emailService._readTemplateFile; var _readTemplateFile_old = emailService._readTemplateFile;
emailService._readTemplateFile = function(language, filename, cb) { emailService._readTemplateFile = function(language, filename, cb) {
if (_.endsWith(filename, '.html')) { if (_.endsWith(filename, '.html')) {
return cb(null, 'Subject\n<html><body>{{walletName}}</body></html>'); return cb(null, '<html><body>{{walletName}}</body></html>');
} else { } else {
_readTemplateFile_old.call(emailService, language, filename, cb); _readTemplateFile_old.call(emailService, language, filename, cb);
} }
@ -375,7 +375,7 @@ describe('Wallet service', function() {
one.text.should.contain(wallet.name); one.text.should.contain(wallet.name);
one.text.should.contain(wallet.copayers[0].name); one.text.should.contain(wallet.copayers[0].name);
should.exist(one.html); should.exist(one.html);
one.html.should.contain('<body>'); one.html.indexOf('<html>').should.equal(0);
one.html.should.contain(wallet.name); one.html.should.contain(wallet.name);
server.storage.fetchUnsentEmails(function(err, unsent) { server.storage.fetchUnsentEmails(function(err, unsent) {
should.not.exist(err); should.not.exist(err);
@ -412,6 +412,14 @@ describe('Wallet service', function() {
}); });
it('should notify copayers a new outgoing tx has been created', function(done) { it('should notify copayers a new outgoing tx has been created', function(done) {
var _readTemplateFile_old = emailService._readTemplateFile;
emailService._readTemplateFile = function(language, filename, cb) {
if (_.endsWith(filename, '.html')) {
return cb(null, '<html>{{&urlForTx}}<html>');
} else {
_readTemplateFile_old.call(emailService, language, filename, cb);
}
};
helpers.stubUtxos(server, wallet, [1, 1], function() { helpers.stubUtxos(server, wallet, [1, 1], function() {
var txOpts = helpers.createSimpleProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 0.8, 'some message', TestData.copayers[0].privKey_1H_0); var txOpts = helpers.createSimpleProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 0.8, 'some message', TestData.copayers[0].privKey_1H_0);
@ -454,9 +462,12 @@ describe('Wallet service', function() {
one.subject.should.contain('Payment sent'); one.subject.should.contain('Payment sent');
one.text.should.contain(wallet.name); one.text.should.contain(wallet.name);
one.text.should.contain('800,000'); one.text.should.contain('800,000');
should.exist(one.html);
one.html.should.contain('https://insight.bitpay.com:443/tx/999');
server.storage.fetchUnsentEmails(function(err, unsent) { server.storage.fetchUnsentEmails(function(err, unsent) {
should.not.exist(err); should.not.exist(err);
unsent.should.be.empty; unsent.should.be.empty;
emailService._readTemplateFile = _readTemplateFile_old;
done(); done();
}); });
}, 100); }, 100);

Loading…
Cancel
Save