Bug/select wallet incomplete / Refactor wallet Services (#4159)
* Addressbook: display error if select an incomplete wallet * Check if wallet is complete/needs_backup for Glidera and Coinbase * Ref/create a walletService * Ref. walletService * Fix Glidera and Coinbase * Removes txService * Fix glidera connection for mobile. Fix bitcode for xcode * Fix duplicated entry * Revert "Bump bwc version 2.3.1" * adds karma-mocha * Refactor * Refactor lock function * Refactor reject, remove and broadcast tx * add walletService tests WIP * add walletService tests WIP 2 * merge * update tests to mocha * fix tests. Angular 1.5? * Fix test * Generate angular-bwc before testing * Rever gitignore * Wording
This commit is contained in:
parent
aee30ec151
commit
98471e952a
27 changed files with 698 additions and 628 deletions
|
|
@ -127,6 +127,18 @@ angular.module('copayApp.services')
|
|||
case 'WALLET_NOT_COMPLETE':
|
||||
body = gettextCatalog.getString('Wallet is not complete');
|
||||
break;
|
||||
case 'WALLET_NEEDS_BACKUP':
|
||||
body = gettextCatalog.getString('Wallet needs backup');
|
||||
break;
|
||||
case 'MISSING_PARAMETER':
|
||||
body = gettextCatalog.getString('Missing parameter');
|
||||
break;
|
||||
case 'NO_PASSWORD_GIVEN':
|
||||
body = gettextCatalog.getString('Spending Password needed');
|
||||
break;
|
||||
case 'PASSWORD_INCORRECT':
|
||||
body = gettextCatalog.getString('Wrong spending password');
|
||||
break;
|
||||
case 'ERROR':
|
||||
body = (err.message || err.error);
|
||||
break;
|
||||
|
|
@ -147,7 +159,7 @@ angular.module('copayApp.services')
|
|||
};
|
||||
|
||||
root.cb = function(err, prefix, cb) {
|
||||
return cb(root.msg(err, prefix))
|
||||
return cb(root.msg(err, prefix));
|
||||
};
|
||||
|
||||
return root;
|
||||
|
|
|
|||
40
src/js/services/fingerprintService.js
Normal file
40
src/js/services/fingerprintService.js
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.services').factory('fingerprintService', function(gettextCatalog, configService) {
|
||||
var root = {};
|
||||
|
||||
var requestTouchId = function(cb) {
|
||||
try {
|
||||
window.plugins.touchid.verifyFingerprint(
|
||||
gettextCatalog.getString('Scan your fingerprint please'),
|
||||
function(msg) {
|
||||
$log.debug('Touch ID OK');
|
||||
return cb();
|
||||
},
|
||||
function(msg) {
|
||||
$log.debug('Touch ID Failed:' + JSON.stringify(msg));
|
||||
return cb(gettextCatalog.getString('Touch ID Failed') + ': ' + msg.localizedDescription);
|
||||
}
|
||||
);
|
||||
} catch (e) {
|
||||
$log.debug('Touch ID Failed:' + JSON.stringify(e));
|
||||
return cb(gettextCatalog.getString('Touch ID Failed'));
|
||||
};
|
||||
};
|
||||
|
||||
root.isAvailable = function(client) {
|
||||
var config = configService.getSync();
|
||||
config.touchIdFor = config.touchIdFor || {};
|
||||
return (window.touchidAvailable && config.touchIdFor[client.credentials.walletId]);
|
||||
};
|
||||
|
||||
root.check = function(client, cb) {
|
||||
if (root.isAvailable()) {
|
||||
requestTouchId(cb);
|
||||
} else {
|
||||
return cb();
|
||||
}
|
||||
};
|
||||
|
||||
return root;
|
||||
});
|
||||
|
|
@ -9,13 +9,13 @@ angular.module('copayApp.services').factory('glideraService', function($http, $l
|
|||
credentials.HOST = 'https://sandbox.glidera.io';
|
||||
if (isCordova) {
|
||||
credentials.REDIRECT_URI = 'copay://glidera';
|
||||
credentials.CLIENT_ID = 'dfc56e4336e32bb8ba46dde34f3d7d6d';
|
||||
credentials.CLIENT_SECRET = '5eb679058f6c7eb81123162323d4fba5';
|
||||
credentials.CLIENT_ID = '6163427a2f37d1b2022ececd6d6c9cdd';
|
||||
credentials.CLIENT_SECRET = '599cc3af26108c6fece8ab17c3f35867';
|
||||
}
|
||||
else {
|
||||
credentials.REDIRECT_URI = 'urn:ietf:wg:oauth:2.0:oob';
|
||||
credentials.CLIENT_ID = '9915b6ffa6dc3baffb87135ed3873d49';
|
||||
credentials.CLIENT_SECRET = 'd74eda05b9c6a228fd5c85cfbd0eb7eb';
|
||||
credentials.CLIENT_ID = 'c402f4a753755456e8c384fb65b7be1d';
|
||||
credentials.CLIENT_SECRET = '3ce826198e3618d0b8ed341ab91fe4e5';
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
|
|||
|
|
@ -638,7 +638,7 @@ angular.module('copayApp.services')
|
|||
$log.debug('Encrypting private key for', fc.credentials.walletName);
|
||||
|
||||
fc.setPrivateKeyEncryption(password);
|
||||
root.lockFC();
|
||||
fc.lock();
|
||||
root.updateCredentialsFC(function() {
|
||||
$log.debug('Wallet encrypted');
|
||||
return cb();
|
||||
|
|
@ -661,51 +661,6 @@ angular.module('copayApp.services')
|
|||
});
|
||||
};
|
||||
|
||||
root.lockFC = function() {
|
||||
var fc = root.focusedClient;
|
||||
try {
|
||||
fc.lock();
|
||||
} catch (e) {};
|
||||
};
|
||||
|
||||
root.unlockFC = function(opts, cb) {
|
||||
opts = opts || {};
|
||||
var fc = opts.selectedClient || root.focusedClient;
|
||||
|
||||
if (!fc.isPrivKeyEncrypted())
|
||||
return cb();
|
||||
|
||||
$log.debug('Wallet is encrypted');
|
||||
$rootScope.$emit('Local/NeedsPassword', false, function(err2, password) {
|
||||
|
||||
if (err2)
|
||||
return cb(err2);
|
||||
|
||||
if (!password)
|
||||
return cb(gettext('Spending Password needed'));
|
||||
|
||||
try {
|
||||
fc.unlock(password);
|
||||
} catch (e) {
|
||||
$log.warn('Error decrypting wallet:', e);
|
||||
return cb(gettext('Wrong spending password'));
|
||||
}
|
||||
return cb();
|
||||
});
|
||||
};
|
||||
|
||||
root.isBackupNeeded = function(walletId, cb) {
|
||||
var c = root.getClient(walletId);
|
||||
if (c.isPrivKeyExternal()) return cb(false);
|
||||
if (!c.credentials.mnemonic) return cb(false);
|
||||
if (c.credentials.network == 'testnet') return cb(false);
|
||||
|
||||
storageService.getBackupFlag(walletId, function(err, val) {
|
||||
if (err || val) return cb(false);
|
||||
return cb(true);
|
||||
});
|
||||
};
|
||||
|
||||
root.getWallets = function(network) {
|
||||
if (!root.profile) return [];
|
||||
|
||||
|
|
|
|||
|
|
@ -1,267 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.services').factory('txService', function($rootScope, profileService, gettextCatalog, lodash, trezor, ledger, configService, bwsError, $log, feeService) {
|
||||
var root = {};
|
||||
|
||||
var reportSigningStatus = function(opts) {
|
||||
opts = opts || {};
|
||||
if (!opts.reporterFn) return;
|
||||
|
||||
var fc = opts.selectedClient || profileService.focusedClient;
|
||||
|
||||
if (fc.isPrivKeyExternal()) {
|
||||
if (fc.getPrivKeyExternalSourceName() == 'ledger') {
|
||||
opts.reporterFn(gettextCatalog.getString('Requesting Ledger Wallet to sign'));
|
||||
} else if (fc.getPrivKeyExternalSourceName() == 'trezor') {
|
||||
opts.reporterFn(gettextCatalog.getString('Requesting Trezor Wallet to sign'));
|
||||
}
|
||||
} else {
|
||||
opts.reporterFn(gettextCatalog.getString('Signing payment'));
|
||||
}
|
||||
};
|
||||
|
||||
var reportBroadcastingStatus = function(opts) {
|
||||
if (!opts.reporterFn) return;
|
||||
|
||||
opts.reporterFn(gettextCatalog.getString('Broadcasting transaction'));
|
||||
};
|
||||
|
||||
var stopReport = function(opts) {
|
||||
if (!opts.reporterFn) return;
|
||||
|
||||
opts.reporterFn();
|
||||
};
|
||||
|
||||
var requestTouchId = function(cb) {
|
||||
try {
|
||||
window.plugins.touchid.verifyFingerprint(
|
||||
gettextCatalog.getString('Scan your fingerprint please'),
|
||||
function(msg) {
|
||||
$log.debug('Touch ID OK');
|
||||
return cb();
|
||||
},
|
||||
function(msg) {
|
||||
$log.debug('Touch ID Failed:' + JSON.stringify(msg));
|
||||
return cb(gettextCatalog.getString('Touch ID Failed') + ': ' + msg.localizedDescription);
|
||||
}
|
||||
);
|
||||
} catch (e) {
|
||||
$log.debug('Touch ID Failed:' + JSON.stringify(e));
|
||||
return cb(gettextCatalog.getString('Touch ID Failed'));
|
||||
};
|
||||
};
|
||||
|
||||
root.setTouchId = function(cb) {
|
||||
if (window.touchidAvailable) {
|
||||
requestTouchId(cb);
|
||||
} else {
|
||||
return cb();
|
||||
}
|
||||
};
|
||||
|
||||
root.checkTouchId = function(opts, cb) {
|
||||
opts = opts || {};
|
||||
var config = configService.getSync();
|
||||
var fc = opts.selectedClient || profileService.focusedClient;
|
||||
config.touchIdFor = config.touchIdFor || {};
|
||||
if (window.touchidAvailable && config.touchIdFor[fc.credentials.walletId]) {
|
||||
requestTouchId(cb);
|
||||
} else {
|
||||
return cb();
|
||||
}
|
||||
};
|
||||
|
||||
root.prepare = function(opts, cb) {
|
||||
$log.info("at .prepare");
|
||||
opts = opts || {};
|
||||
var fc = opts.selectedClient || profileService.focusedClient;
|
||||
$log.info('FC Client Dump:' + fc);
|
||||
if (!fc.canSign() && !fc.isPrivKeyExternal())
|
||||
return cb('Cannot sign'); // should never happen, no need to translate
|
||||
|
||||
root.checkTouchId(opts, function(err) {
|
||||
if (err) {
|
||||
$log.warn('CheckTouchId error:', err);
|
||||
return cb(err);
|
||||
};
|
||||
|
||||
profileService.unlockFC(opts, function(err) {
|
||||
if (err) {
|
||||
$log.warn("prepare/unlockFC error:", err);
|
||||
return cb(err);
|
||||
};
|
||||
|
||||
return cb();
|
||||
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
root.removeTx = function(txp, opts, cb) {
|
||||
opts = opts || {};
|
||||
var fc = opts.selectedClient || profileService.focusedClient;
|
||||
|
||||
fc.removeTxProposal(txp, function(err) {
|
||||
return cb(err);
|
||||
});
|
||||
};
|
||||
|
||||
root.createTx = function(opts, cb) {
|
||||
opts = opts || {};
|
||||
var fc = opts.selectedClient || profileService.focusedClient;
|
||||
var currentSpendUnconfirmed = configService.getSync().wallet.spendUnconfirmed;
|
||||
|
||||
var getFee = function(cb) {
|
||||
if (opts.lockedCurrentFeePerKb) {
|
||||
cb(null, opts.lockedCurrentFeePerKb);
|
||||
} else {
|
||||
feeService.getCurrentFeeValue(cb);
|
||||
}
|
||||
};
|
||||
|
||||
if (opts.sendMax) {
|
||||
fc.createTxProposal(opts, function(err, txp) {
|
||||
if (err) return cb(err);
|
||||
else return cb(null, txp);
|
||||
});
|
||||
}else {
|
||||
getFee(function(err, feePerKb) {
|
||||
if (err) return cb(err);
|
||||
|
||||
opts.feePerKb = feePerKb;
|
||||
opts.excludeUnconfirmedUtxos = currentSpendUnconfirmed ? false : true;
|
||||
fc.createTxProposal(opts, function(err, txp) {
|
||||
if (err) return cb(err);
|
||||
else return cb(null, txp);
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
root.publishTx = function(txp, opts, cb) {
|
||||
opts = opts || {};
|
||||
var fc = opts.selectedClient || profileService.focusedClient;
|
||||
fc.publishTxProposal({txp: txp}, function(err, txp) {
|
||||
if (err) return cb(err);
|
||||
else return cb(null, txp);
|
||||
});
|
||||
};
|
||||
|
||||
var _signWithLedger = function(txp, opts, cb) {
|
||||
opts = opts || {};
|
||||
var fc = opts.selectedClient || profileService.focusedClient;
|
||||
$log.info('Requesting Ledger Chrome app to sign the transaction');
|
||||
|
||||
ledger.signTx(txp, fc.credentials.account, function(result) {
|
||||
$log.debug('Ledger response', result);
|
||||
if (!result.success)
|
||||
return cb(result.message || result.error);
|
||||
|
||||
txp.signatures = lodash.map(result.signatures, function(s) {
|
||||
return s.substring(0, s.length - 2);
|
||||
});
|
||||
return fc.signTxProposal(txp, cb);
|
||||
});
|
||||
};
|
||||
|
||||
var _signWithTrezor = function(txp, opts, cb) {
|
||||
opts = opts || {};
|
||||
var fc = opts.selectedClient || profileService.focusedClient;
|
||||
$log.info('Requesting Trezor to sign the transaction');
|
||||
|
||||
var xPubKeys = lodash.pluck(fc.credentials.publicKeyRing, 'xPubKey');
|
||||
trezor.signTx(xPubKeys, txp, fc.credentials.account, function(err, result) {
|
||||
if (err) return cb(err);
|
||||
|
||||
$log.debug('Trezor response', result);
|
||||
txp.signatures = result.signatures;
|
||||
return fc.signTxProposal(txp, cb);
|
||||
});
|
||||
};
|
||||
|
||||
root.sign = function(txp, opts, cb) {
|
||||
$log.info('at .sign');
|
||||
opts = opts || {};
|
||||
var fc = opts.selectedClient || profileService.focusedClient;
|
||||
|
||||
if (fc.isPrivKeyExternal()) {
|
||||
switch (fc.getPrivKeyExternalSourceName()) {
|
||||
case 'ledger':
|
||||
return _signWithLedger(txp, opts, cb);
|
||||
case 'trezor':
|
||||
return _signWithTrezor(txp, opts, cb);
|
||||
default:
|
||||
var msg = 'Unsupported External Key:' + fc.getPrivKeyExternalSourceName();
|
||||
$log.error(msg);
|
||||
return cb(msg);
|
||||
}
|
||||
} else {
|
||||
|
||||
txp.signatures = null;
|
||||
$log.info('at .sign: (isEncrypted):', fc.isPrivKeyEncrypted());
|
||||
$log.info('txp BEFORE .signTxProposal:', txp);
|
||||
|
||||
fc.signTxProposal(txp, function(err, signedTxp) {
|
||||
$log.info('txp AFTER .signTxProposal:',err, signedTxp);
|
||||
profileService.lockFC();
|
||||
return cb(err, signedTxp);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
root.signAndBroadcast = function(txp, opts, cb) {
|
||||
$log.info('at .signAndBroadcast');
|
||||
opts = opts || {};
|
||||
reportSigningStatus(opts);
|
||||
|
||||
var fc = opts.selectedClient || profileService.focusedClient;
|
||||
root.sign(txp, opts, function(err, txp) {
|
||||
if (err) {
|
||||
stopReport(opts);
|
||||
return bwsError.cb(err, gettextCatalog.getString('Could not accept payment'), cb);
|
||||
};
|
||||
|
||||
if (txp.status != 'accepted') {
|
||||
stopReport(opts);
|
||||
return cb(null, txp);
|
||||
}
|
||||
|
||||
reportBroadcastingStatus(opts);
|
||||
fc.broadcastTxProposal(txp, function(err, txp, memo) {
|
||||
stopReport(opts);
|
||||
|
||||
if (err) {
|
||||
return bwsError.cb(err, gettextCatalog.getString('Could not broadcast payment'), cb);
|
||||
};
|
||||
|
||||
$log.debug('Transaction signed and broadcasted')
|
||||
|
||||
if (memo)
|
||||
$log.info(memo);
|
||||
|
||||
return cb(null, txp);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
root.prepareAndSignAndBroadcast = function(txp, opts, cb) {
|
||||
opts = opts || {};
|
||||
$log.info('at .prepareSignAndBroadcast');
|
||||
|
||||
root.prepare(opts, function(err) {
|
||||
if (err) {
|
||||
$log.warn('Prepare error:' + err);
|
||||
stopReport(opts);
|
||||
return cb(err);
|
||||
};
|
||||
root.signAndBroadcast(txp, opts, function(err, txp) {
|
||||
if (err) {
|
||||
stopReport(opts);
|
||||
return cb(err);
|
||||
};
|
||||
return cb(null, txp);
|
||||
});
|
||||
});
|
||||
};
|
||||
return root;
|
||||
});
|
||||
201
src/js/services/walletService.js
Normal file
201
src/js/services/walletService.js
Normal file
|
|
@ -0,0 +1,201 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.services').factory('walletService', function($log, lodash, trezor, ledger, storageService) {
|
||||
var root = {};
|
||||
|
||||
var _signWithLedger = function(client, txp, cb) {
|
||||
$log.info('Requesting Ledger Chrome app to sign the transaction');
|
||||
|
||||
ledger.signTx(txp, client.credentials.account, function(result) {
|
||||
$log.debug('Ledger response', result);
|
||||
if (!result.success)
|
||||
return cb(result.message || result.error);
|
||||
|
||||
txp.signatures = lodash.map(result.signatures, function(s) {
|
||||
return s.substring(0, s.length - 2);
|
||||
});
|
||||
return client.signTxProposal(txp, cb);
|
||||
});
|
||||
};
|
||||
|
||||
var _signWithTrezor = function(client, txp, cb) {
|
||||
$log.info('Requesting Trezor to sign the transaction');
|
||||
|
||||
var xPubKeys = lodash.pluck(client.credentials.publicKeyRing, 'xPubKey');
|
||||
trezor.signTx(xPubKeys, txp, client.credentials.account, function(err, result) {
|
||||
if (err) return cb(err);
|
||||
|
||||
$log.debug('Trezor response', result);
|
||||
txp.signatures = result.signatures;
|
||||
return client.signTxProposal(txp, cb);
|
||||
});
|
||||
};
|
||||
|
||||
root.isBackupNeeded = function(client, cb) {
|
||||
if (client.isPrivKeyExternal()) return cb(false);
|
||||
if (!client.credentials.mnemonic) return cb(false);
|
||||
if (client.credentials.network == 'testnet') return cb(false);
|
||||
|
||||
storageService.getBackupFlag(client.credentials.walletId, function(err, val) {
|
||||
if (err) $log.error(err);
|
||||
if (val) return cb(false);
|
||||
return cb(true);
|
||||
});
|
||||
};
|
||||
|
||||
root.isReady = function(client, cb) {
|
||||
if(!client.isComplete())
|
||||
return cb('WALLET_NOT_COMPLETE');
|
||||
root.isBackupNeeded(client, function(needsBackup) {
|
||||
if (needsBackup)
|
||||
return cb('WALLET_NEEDS_BACKUP');
|
||||
return cb();
|
||||
});
|
||||
};
|
||||
|
||||
root.isEncrypted = function(client) {
|
||||
if (lodash.isEmpty(client)) return;
|
||||
var isEncrypted = client.isPrivKeyEncrypted();
|
||||
if (isEncrypted) $log.debug('Wallet is encrypted');
|
||||
return isEncrypted;
|
||||
};
|
||||
|
||||
root.lock = function(client) {
|
||||
try {
|
||||
client.lock();
|
||||
} catch (e) {
|
||||
$log.warn('Encrypting wallet:', e);
|
||||
};
|
||||
};
|
||||
|
||||
root.unlock = function(client, password) {
|
||||
if (lodash.isEmpty(client))
|
||||
return 'MISSING_PARAMETER';
|
||||
if (lodash.isEmpty(password))
|
||||
return 'NO_PASSWORD_GIVEN';
|
||||
try {
|
||||
client.unlock(password);
|
||||
} catch (e) {
|
||||
$log.warn('Decrypting wallet:', e);
|
||||
return 'PASSWORD_INCORRECT';
|
||||
}
|
||||
};
|
||||
|
||||
root.createTx = function(client, txp, cb) {
|
||||
if (lodash.isEmpty(txp) || lodash.isEmpty(client))
|
||||
return cb('MISSING_PARAMETER');
|
||||
|
||||
if (txp.sendMax) {
|
||||
client.createTxProposal(txp, function(err, createdTxp) {
|
||||
if (err) return cb(err);
|
||||
else return cb(null, createdTxp);
|
||||
});
|
||||
} else {
|
||||
client.getFeeLevels(client.credentials.network, function(err, levels) {
|
||||
if (err) return cb(err);
|
||||
|
||||
var feeLevelValue = lodash.find(levels, {
|
||||
level: txp.feeLevel
|
||||
});
|
||||
|
||||
if (!feeLevelValue || !feeLevelValue.feePerKB)
|
||||
return cb({
|
||||
message: 'Could not get dynamic fee for level: ' + feeLevel
|
||||
});
|
||||
|
||||
$log.debug('Dynamic fee: ' + txp.feeLevel + ' ' + feeLevelValue.feePerKB + ' SAT');
|
||||
|
||||
txp.feePerKb = feeLevelValue.feePerKB;
|
||||
client.createTxProposal(txp, function(err, createdTxp) {
|
||||
if (err) return cb(err);
|
||||
else {
|
||||
$log.debug('Transaction created');
|
||||
return cb(null, createdTxp);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
root.publishTx = function(client, txp, cb) {
|
||||
if (lodash.isEmpty(txp) || lodash.isEmpty(client))
|
||||
return cb('MISSING_PARAMETER');
|
||||
|
||||
client.publishTxProposal({txp: txp}, function(err, publishedTx) {
|
||||
if (err) return cb(err);
|
||||
else {
|
||||
$log.debug('Transaction published');
|
||||
return cb(null, publishedTx);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
root.signTx = function(client, txp, cb) {
|
||||
if (lodash.isEmpty(txp) || lodash.isEmpty(client))
|
||||
return cb('MISSING_PARAMETER');
|
||||
|
||||
if (client.isPrivKeyExternal()) {
|
||||
switch (client.getPrivKeyExternalSourceName()) {
|
||||
case 'ledger':
|
||||
return _signWithLedger(client, txp, cb);
|
||||
case 'trezor':
|
||||
return _signWithTrezor(client, txp, cb);
|
||||
default:
|
||||
var msg = 'Unsupported External Key:' + client.getPrivKeyExternalSourceName();
|
||||
$log.error(msg);
|
||||
return cb(msg);
|
||||
}
|
||||
} else {
|
||||
|
||||
try {
|
||||
client.signTxProposal(txp, function(err, signedTxp) {
|
||||
$log.debug('Transaction signed');
|
||||
return cb(err, signedTxp);
|
||||
});
|
||||
} catch (e) {
|
||||
$log.warn('Error at signTxProposal:', e);
|
||||
return cb(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
root.broadcastTx = function(client, txp, cb) {
|
||||
if (lodash.isEmpty(txp) || lodash.isEmpty(client))
|
||||
return cb('MISSING_PARAMETER');
|
||||
|
||||
if (txp.status != 'accepted')
|
||||
return cb('TX_NOT_ACCEPTED');
|
||||
|
||||
client.broadcastTxProposal(txp, function(err, broadcastedTxp, memo) {
|
||||
if (err)
|
||||
return cb(err);
|
||||
|
||||
$log.debug('Transaction broadcasted');
|
||||
if (memo) $log.info(memo);
|
||||
|
||||
return cb(null, broadcastedTxp);
|
||||
});
|
||||
};
|
||||
|
||||
root.rejectTx = function(client, txp, cb) {
|
||||
if (lodash.isEmpty(txp) || lodash.isEmpty(client))
|
||||
return cb('MISSING_PARAMETER');
|
||||
|
||||
client.rejectTxProposal(txp, null, function(err, rejectedTxp) {
|
||||
$log.debug('Transaction rejected');
|
||||
return cb(err, rejectedTxp);
|
||||
});
|
||||
};
|
||||
|
||||
root.removeTx = function(client, txp, cb) {
|
||||
if (lodash.isEmpty(txp) || lodash.isEmpty(client))
|
||||
return cb('MISSING_PARAMETER');
|
||||
|
||||
client.removeTxProposal(txp, function(err) {
|
||||
$log.debug('Transaction removed');
|
||||
return cb(err);
|
||||
});
|
||||
};
|
||||
|
||||
return root;
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue