Permalink
Browse files

feat(assets): add asset reissue

Added reissue dialog and confirmation.
Added reissue possibility checking to enable/disable reissue button
  • Loading branch information...
1 parent b57c154 commit 9c98c0f8e3c21ab8fd8315e309c307eb952d2bfd @beregovoy68 beregovoy68 committed Nov 16, 2016
View
@@ -157,6 +157,7 @@ module.exports = function (grunt) {
'src/js/portfolio/asset.list.controller.js',
'src/js/portfolio/asset.transfer.controller.js',
'src/js/portfolio/asset.details.controller.js',
+ 'src/js/portfolio/asset.reissue.controller.js',
'src/js/portfolio/asset.filter.js',
'src/js/**/*.spec.js'
View
@@ -462,7 +462,7 @@ <h2 id="AccHeader">{{accounts.caption}}</h2>
<td>{{tx.balance}}</td>
<td>
<button ng-click="assetList.assetTransfer(tx.id)">Transfer</button><span class="divider-2"></span>
- <button>Reissue</button><span class="divider-2"></span>
+ <button ng-enable="tx.formatted.canReissue" ng-click="assetList.assetReissue(tx.id)">Reissue</button><span class="divider-2"></span>
<button ng-click="assetList.assetDetails(tx.id)">Details</button>
</td>
</tr>
@@ -509,8 +509,8 @@ <h2 id="AccHeader">{{accounts.caption}}</h2>
</table>
</div>
</div>
- <div ng-controller="assetTransferController as transfer">
- <div id="transfer-asset-dialog" waves-dialog ok-button-caption="TRANSFER" on-dialog-ok="transfer.submitTransfer()">
+ <div class="noDisp" ng-controller="assetTransferController as transfer">
+ <div id="asset-transfer-dialog" waves-dialog ok-button-caption="TRANSFER" on-dialog-ok="transfer.submitTransfer()">
<form id="transfer-asset-form" name="transferAssetForm" novalidate ng-validate="transfer.validationOptions">
<h2>ASSET TRANSFER</h2>
<div class="balanceAmt">
@@ -566,6 +566,63 @@ <h2 id="AccHeader">{{accounts.caption}}</h2>
<p>Please <span class="fontBold"> CONFIRM </span>to execute or <span class="fontBold"> CANCEL </span> to discard.</p>
</div>
</div>
+ <div class="noDisp" ng-controller="assetReissueController as reissue">
+ <div id="asset-reissue-dialog" waves-dialog ok-button-caption="REISSUE" ok-button-enabled="!reissue.confirm.pendingReissue" on-dialog-ok="reissue.submitReissue()">
+ <form id="asset-reissue-form" name="assetReissueForm" novalidate ng-validate="reissue.validationOptions">
+ <h2>ASSET REISSUE</h2>
+ <div class="balanceAmt">
+ <p>Total tokens issued: </p><span class="balancewaves">{{reissue.totalTokens}}</span>
+ </div>
+ <table>
+ <thead>
+ <tr>
+ <th>DESCRIPTION</th>
+ <th>INPUT</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>Asset identifier</td>
+ <td>{{reissue.assetId}}</td>
+ </tr>
+ <tr>
+ <td>Asset name</td>
+ <td>{{reissue.assetName}}</td>
+ </tr>
+
+ <tr>
+ <td>Additional amount</td>
+ <td>
+ <div class="form-field">
+ <input class="wInput form-control" name="assetAmount" type="text" placeholder="Amount" ng-model="reissue.amount" />
+ </div>
+ </td>
+ </tr>
+ <tr>
+ <td>Reissue enabled</td>
+ <td>
+ <div class="form-field">
+ <input class="wInput form-control" name="assetReissue" type="checkbox" ng-model="reissue.reissuable" />
+ </div>
+ </td>
+ </tr>
+ <tr>
+ <td>Fee</td>
+ <td>{{reissue.fee.formatAmount(true)}}</td>
+ </tr>
+ </tbody>
+ </table>
+ </form>
+ </div>
+ <div id="asset-reissue-confirm-dialog" waves-dialog ok-button-caption="CONFIRM" ok-button-enabled="!reissue.confirm.reissuePending" on-dialog-ok="reissue.broadcastTransaction()">
+ <p>You are issuing additional amount of <span class="confirmation-value">{{reissue.confirm.amount.value}}</span> tokens <br/>
+ to the asset <span class="confirmation-value">{{reissue.confirm.amount.currency}}</span>
+ with <span class="confirmation-value">{{reissue.confirm.fee.value}}</span>
+ <span class="confirmation-value">{{reissue.confirm.fee.currency}}</span> fee
+ </p>
+ <p>Please <span class="fontBold"> CONFIRM </span>to execute or <span class="fontBold"> CANCEL </span> to discard.</p>
+ </div>
+ </div>
</div>
</div>
<!-- / PORTFOLIO TAB -->
@@ -865,6 +922,7 @@ <h2 id="AccHeader">{{accounts.caption}}</h2>
<script src="js/portfolio/asset.list.controller.js"></script>
<script src="js/portfolio/asset.transfer.controller.js"></script>
<script src="js/portfolio/asset.details.controller.js"></script>
+ <script src="js/portfolio/asset.reissue.controller.js"></script>
<script src="js/portfolio/asset.filter.js"></script>
<script src="js/style.js"></script>
@@ -1,7 +1,7 @@
(function () {
'use strict';
- function WavesAssetDetailsController($scope, events, applicationContext) {
+ function WavesAssetDetailsController($scope, events, applicationContext, dialogService) {
var details = this;
function transformAddress(address) {
@@ -17,7 +17,7 @@
return address === applicationContext.account.address;
}
- $scope.$on(events.ASSET_SELECTED, function (event, assetId) {
+ $scope.$on(events.ASSET_DETAILS, function (event, assetId) {
var asset = applicationContext.cache.assets[assetId];
if (angular.isUndefined(asset))
throw new Error('Failed to find asset details by id ' + assetId);
@@ -30,10 +30,12 @@
details.timestamp = asset.timestamp;
details.totalTokens = asset.totalTokens.formatAmount();
details.reissuable = asset.reissuable ? 'Yes' : 'No';
+
+ dialogService.open('#asset-details-dialog');
});
}
- WavesAssetDetailsController.$inject = ['$scope', 'portfolio.events', 'applicationContext'];
+ WavesAssetDetailsController.$inject = ['$scope', 'portfolio.events', 'applicationContext', 'dialogService'];
angular
.module('app.portfolio')
@@ -5,15 +5,20 @@
function transformAddress (rawAddress) {
var result = angular.isDefined(rawAddress) ? rawAddress : 'none';
- if (result === applicationContext.account.address)
+ if (isMyAddress(result))
result = 'You';
return result;
}
+ function isMyAddress(address) {
+ return address === applicationContext.account.address;
+ }
+
function formatAsset (transaction) {
transaction.formatted = {
- sender: transformAddress(transaction.sender)
+ sender: transformAddress(transaction.sender),
+ canReissue: transaction.reissuable && isMyAddress(transaction.sender)
};
transaction.formatted.isSenderCopiable = addressService.validateAddress(transaction.formatted.sender);
@@ -10,6 +10,7 @@
assetList.assets = [];
assetList.assetTransfer = assetTransfer;
assetList.assetDetails = assetDetails;
+ assetList.assetReissue = assetReissue;
loadDataFromBackend();
$scope.$on('$destroy', function () {
@@ -28,13 +29,15 @@
}
function assetTransfer(assetId) {
- $scope.$broadcast(events.ASSET_SELECTED, assetId);
- dialogService.open('#transfer-asset-dialog');
+ $scope.$broadcast(events.ASSET_TRANSFER, assetId);
}
function assetDetails(assetId) {
- $scope.$broadcast(events.ASSET_SELECTED, assetId);
- dialogService.open('#asset-details-dialog');
+ $scope.$broadcast(events.ASSET_DETAILS, assetId);
+ }
+
+ function assetReissue(assetId) {
+ $scope.$broadcast(events.ASSET_REISSUE, assetId);
}
function tryToLoadAssetDataFromCache(asset) {
@@ -0,0 +1,145 @@
+(function () {
+ 'use strict';
+
+ var FIXED_REISSUE_FEE = new Money(1, Currency.WAV);
+
+ function WavesAssetReissueController($scope, $timeout, events, applicationContext, assetService, dialogService,
+ notificationService, formattingService, apiService) {
+ var transaction;
+ var reissue = this;
+ reissue.confirm = {
+ amount: {},
+ fee: {},
+ reissuePending: false
+ };
+ reissue.fee = FIXED_REISSUE_FEE;
+ reissue.validationOptions = {
+ rules: {
+ assetAmount: {
+ required: true,
+ decimal: 0,
+ min: 1
+ }
+ },
+ messages: {
+ assetAmount: {
+ required: 'Amount to reissue is required'
+ }
+ }
+ };
+ reissue.submitReissue = submitReissue;
+ reissue.broadcastTransaction = broadcastTransaction;
+
+ resetReissueForm();
+
+ $scope.$on(events.ASSET_REISSUE, function (event, assetId) {
+ var asset = applicationContext.cache.assets[assetId];
+ if (angular.isUndefined(asset))
+ throw new Error('Failed to find asset data by id ' + assetId);
+
+ reissue.assetId = assetId;
+ reissue.assetName = asset.currency.displayName;
+ reissue.totalTokens = asset.totalTokens.formatAmount();
+ reissue.asset = asset;
+
+ // update validation options and check how it affects form validation
+ reissue.validationOptions.rules.assetAmount.decimal = asset.currency.precision;
+ var minimumPayment = Money.fromCoins(1, asset.currency);
+ reissue.validationOptions.rules.assetAmount.min = minimumPayment.toTokens();
+ reissue.validationOptions.messages.assetAmount.decimal = 'The amount to reissue must be a number ' +
+ 'with no more than ' + minimumPayment.currency.precision +
+ ' digits after the decimal point (.)';
+ reissue.validationOptions.messages.assetAmount.min = 'Amount to reissue is too small. ' +
+ 'It should be greater or equal to ' + minimumPayment.formatAmount(false);
+
+ dialogService.open('#asset-reissue-dialog');
+ });
+
+ function submitReissue () {
+ var form = getReissueForm();
+ if (!form.validate(reissue.validationOptions))
+ // prevent dialog from closing
+ return false;
+
+ var assetReissue = {
+ totalTokens: Money.fromTokens(reissue.amount, reissue.asset.currency),
+ reissuable: reissue.reissuable,
+ fee: reissue.fee
+ };
+
+ var sender = {
+ publicKey: applicationContext.account.keyPair.public,
+ privateKey: applicationContext.account.keyPair.private
+ };
+ // creating the transaction and waiting for confirmation
+ transaction = assetService.createAssetReissueTransaction(assetReissue, sender);
+
+ // setting data for the confirmation dialog
+ reissue.confirm.amount.value = assetReissue.totalTokens.formatAmount(true);
+ reissue.confirm.amount.currency = assetReissue.totalTokens.currency.displayName;
+ reissue.confirm.fee.value = assetReissue.fee.formatAmount(true);
+ reissue.confirm.fee.currency = assetReissue.fee.currency.displayName;
+
+ // open confirmation dialog
+ // doing it async because this method is called while another dialog is open
+ $timeout(function () {
+ dialogService.open('#asset-reissue-confirm-dialog');
+ }, 1);
+
+ resetReissueForm();
+
+ // it's ok to close reissue dialog
+ return true;
+ }
+
+ function broadcastTransaction () {
+ // checking if transaction was saved
+ if (angular.isUndefined(transaction))
+ return;
+
+ // prevent method execution when there is a pending reissue request
+ if (reissue.confirm.reissuePending)
+ return;
+
+ //disable confirm button
+ reissue.confirm.reissuePending = true;
+
+ apiService.assets.reissue(transaction).then(function () {
+ var amount = Money.fromCoins(transaction.quantity, reissue.asset);
+ var displayMessage = 'Reissued ' + amount.formatAmount(true) + ' tokens of asset ' +
+ reissue.asset.currency.displayName + '<br/>Date: ' +
+ formattingService.formatTimestamp(transaction.timestamp);
+ notificationService.notice(displayMessage);
+ //enable confirm button
+ reissue.confirm.reissuePending = false;
+ transaction = undefined;
+ }, function (response) {
+ if (angular.isDefined(response.data))
+ notificationService.error('Error:' + response.data.error + ' - ' + response.data.message);
+ else
+ notificationService.error('Request failed. Status: ' + response.status + ' - ' +
+ response.statusText);
+ //enable confirm button
+ reissue.confirm.reissuePending = false;
+ transaction = undefined;
+ });
+ }
+
+ function getReissueForm() {
+ // here we have a direct markup dependency
+ // but other ways of getting the form from a child scope are even more ugly
+ return angular.element('#asset-reissue-form').scope().assetReissueForm;
+ }
+
+ function resetReissueForm() {
+ reissue.amount = '0';
+ }
+ }
+
+ WavesAssetReissueController.$inject = ['$scope', '$timeout', 'portfolio.events', 'applicationContext',
+ 'assetService', 'dialogService', 'notificationService', 'formattingService', 'apiService'];
+
+ angular
+ .module('app.portfolio')
+ .controller('assetReissueController', WavesAssetReissueController);
+})();
@@ -23,7 +23,6 @@
};
transfer.autocomplete = autocomplete;
transfer.validationOptions = {
- debug: true,
rules: {
assetRecipient: {
required: true,
@@ -61,7 +60,7 @@
resetPaymentForm();
- $scope.$on(events.ASSET_SELECTED, function (event, assetId) {
+ $scope.$on(events.ASSET_TRANSFER, function (event, assetId) {
var asset = applicationContext.cache.assets[assetId];
transfer.availableBalance = asset.balance.formatAmount();
transfer.asset = asset;
@@ -75,6 +74,8 @@
' digits after the decimal point (.)';
transfer.validationOptions.messages.assetAmount.min = 'Payment amount is too small. ' +
'It should be greater or equal to ' + minimumPayment.formatAmount(false);
+
+ dialogService.open('#asset-transfer-dialog');
});
function getTransferForm() {
@@ -139,7 +140,7 @@
var amount = Money.fromCoins(transaction.amount, transfer.asset);
var address = transaction.recipient;
var displayMessage = 'Sent ' + amount.formatAmount(true) + ' of ' +
- transaction.asset.currency.displayName +
+ transfer.asset.currency.displayName +
'<br/>Recipient ' + address.substr(0,15) + '...<br/>Date: ' +
formattingService.formatTimestamp(transaction.timestamp);
notificationService.notice(displayMessage);
@@ -3,6 +3,8 @@
angular.module('app.portfolio', ['app.shared'])
.constant('portfolio.events', {
- ASSET_SELECTED: 'asset-selected'
+ ASSET_TRANSFER: 'asset-transfer',
+ ASSET_REISSUE: 'asset-reissue',
+ ASSET_DETAILS: 'asset-details'
});
})();

0 comments on commit 9c98c0f

Please sign in to comment.