Permalink
Browse files

feat(assets): add an asset transfer dialog

Implemented UI and it's validation for assets transfer feature.
  • Loading branch information...
1 parent e5b2ad0 commit 82341101f1925eb1673ade4893f241dae79fdcaa @beregovoy68 beregovoy68 committed Nov 15, 2016
Showing with 172 additions and 10 deletions.
  1. +1 −1 bower.json
  2. +9 −1 src/index.html
  3. +1 −1 src/js/app.js
  4. +157 −4 src/js/portfolio/asset.transfer.controller.js
  5. +4 −3 src/js/wallet/wallet.controller.js
View
@@ -24,7 +24,7 @@
"angular-messages": "^1.5.8",
"angular-validation-match": "^1.9.0",
"angular-material": "^1.1.1",
- "waves-angular-validate": "git@github.com:beregovoy68/angular-validate.git#^1.1.2",
+ "waves-angular-validate": "git@github.com:beregovoy68/angular-validate.git#master",
"tooltipster": "^3.3.0"
},
"analytics": false
View
@@ -469,7 +469,7 @@ <h2 id="AccHeader">{{accounts.caption}}</h2>
</tbody>
</table>
<div ng-controller="assetTransferController as transfer">
- <div id="transfer-asset-dialog" waves-dialog ok-button-caption="TRANSFER" ok-button-enabled="!transfer.confirm.pendingTransfer" on-dialog-ok="transfer.submitPayment()">
+ <div id="transfer-asset-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">
@@ -516,6 +516,14 @@ <h2 id="AccHeader">{{accounts.caption}}</h2>
</table>
</form>
</div>
+ <div id="transfer-asset-confirmation" waves-dialog ok-button-caption="CONFIRM" ok-button-enabled="!transfer.confirm.pendingTransfer" on-dialog-ok="transfer.broadcastTransaction()">
+ <p>You are sending <span class="confirmation-value">{{transfer.confirm.amount.value}}</span>
+ <span class="confirmation-value">{{transfer.confirm.amount.currency}}</span> with
+ <span class="confirmation-value">{{transfer.confirm.fee.value}}</span>
+ <span class="confirmation-value">{{transfer.confirm.fee.currency}}</span> fee <br/>to the address: <span class="confirmation-value">{{transfer.confirm.recipient}}</span>
+ </p>
+ <p>Please <span class="fontBold"> CONFIRM </span>to execute or <span class="fontBold"> CANCEL </span> to discard.</p>
+ </div>
</div>
</div>
</div>
View
@@ -56,7 +56,7 @@ function AngularApplicationConfig($validatorProvider) {
$validatorProvider.addMethod('decimal', function(value, element, params) {
var maxdigits = angular.isNumber(params) ? params : Currency.WAV.precision;
- var regex = new RegExp('^(?:-?\\d+)?(?:\\.\\d{1,' + maxdigits + '})?$');
+ var regex = new RegExp('^(?:-?\\d+)?(?:\\.\\d{0,' + maxdigits + '})?$');
return this.optional(element) || regex.test(value);
}, 'Amount is expected with a dot (.) as a decimal separator with no more than {0} fraction digits');
$validatorProvider.addMethod('password', function(value, element) {
@@ -1,23 +1,176 @@
(function () {
'use strict';
- function WavesAssetTransferController($scope, events, autocomplete, applicationContext) {
+ function WavesAssetTransferController($scope, $timeout, constants, events, autocomplete, applicationContext,
+ assetService, apiService, dialogService,
+ formattingService, notificationService) {
+ var transaction;
var transfer = this;
+ var minimumFee = new Money(constants.MINIMUM_TRANSACTION_FEE, Currency.WAV);
transfer.availableBalance = 0;
transfer.confirm = {
+ amount: {
+ value: '0',
+ currency: ''
+ },
+ fee: {
+ value: '0',
+ currency: ''
+ },
+ recipient: '',
pendingTransfer: false
};
- transfer.autocomplete = angular.copy(autocomplete);
- transfer.validationOptions = {};
+ transfer.autocomplete = autocomplete;
+ transfer.validationOptions = {
+ debug: true,
+ rules: {
+ assetRecipient: {
+ required: true,
+ address: true
+ },
+ assetAmount: {
+ required: true,
+ decimal: 0,
+ min: 1
+ },
+ assetFee: {
+ required: true,
+ decimal: Currency.WAV.precision,
+ min: minimumFee.toTokens()
+ }
+ },
+ messages: {
+ assetRecipient: {
+ required: 'Recipient account number is required'
+ },
+ assetAmount: {
+ required: 'Amount to send is required'
+ },
+ assetFee: {
+ required: 'Transaction fee is required',
+ decimal: 'Transaction fee must be with no more than ' +
+ minimumFee.currency.precision + ' digits after the decimal point (.)',
+ min: 'Transaction fee is too small. It should be greater or equal to ' +
+ minimumFee.formatAmount(true)
+ }
+ }
+ };
+ transfer.submitTransfer = submitTransfer;
+ transfer.broadcastTransaction = broadcastTransaction;
+
+ resetPaymentForm();
$scope.$on(events.ASSET_SELECTED, function (event, assetId) {
var asset = applicationContext.cache.assets[assetId];
transfer.availableBalance = asset.balance.formatAmount();
+ transfer.asset = asset;
+
+ // update validation options and check how it affects form validation
+ transfer.validationOptions.rules.assetAmount.decimal = asset.currency.precision;
+ var minimumPayment = Money.fromCoins(1, asset.currency);
+ transfer.validationOptions.rules.assetAmount.min = minimumPayment.toTokens();
+ transfer.validationOptions.messages.assetAmount.decimal = 'The amount to send must be a number ' +
+ 'with no more than ' + minimumPayment.currency.precision +
+ ' 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);
});
+
+ function getTransferForm() {
+ // 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('#transfer-asset-form').scope().transferAssetForm;
+ }
+
+ function submitTransfer() {
+ var transferForm = getTransferForm();
+ var invalid = transferForm.invalid();
+ transfer.fee.isValid = angular.isDefined(invalid.assetFee) ?
+ !invalid.assetFee : true;
+ if (!transferForm.validate(transfer.validationOptions))
+ // prevent dialog from closing
+ return false;
+
+ var assetTransfer = {
+ recipient: transfer.recipient,
+ amount: Money.fromTokens(transfer.amount, transfer.asset.currency),
+ fee: Money.fromTokens(transfer.autocomplete.getFeeAmount(), Currency.WAV)
+ };
+ var sender = {
+ publicKey: applicationContext.account.keyPair.public,
+ privateKey: applicationContext.account.keyPair.private
+ };
+ // creating the transaction and waiting for confirmation
+ transaction = assetService.createAssetTransferTransaction(assetTransfer, sender);
+
+ // setting data for the confirmation dialog
+ transfer.confirm.amount.value = assetTransfer.amount.formatAmount(true);
+ transfer.confirm.amount.currency = assetTransfer.amount.currency.displayName;
+ transfer.confirm.fee.value = assetTransfer.fee.formatAmount(true);
+ transfer.confirm.fee.currency = assetTransfer.fee.currency.displayName;
+ transfer.confirm.recipient = assetTransfer.recipient;
+
+ // open confirmation dialog
+ // doing it async because this method is called while another dialog is open
+ $timeout(function () {
+ dialogService.open('#transfer-asset-confirmation');
+ }, 1);
+
+ resetPaymentForm();
+
+ // it's ok to close payment dialog
+ return true;
+ }
+
+ function broadcastTransaction() {
+ // checking if transaction was saved
+ if (angular.isUndefined(transaction))
+ return;
+
+ // prevent method execution when there is a pending transfer request
+ if (transfer.confirm.paymentPending)
+ return;
+
+ //disable confirm button
+ transfer.confirm.paymentPending = true;
+
+ apiService.assets.transfer(transaction).then(function () {
+ var amount = Money.fromCoins(transaction.amount, transfer.asset);
+ var address = transaction.recipient;
+ var displayMessage = 'Sent ' + amount.formatAmount(true) + ' of ' +
+ transaction.asset.currency.displayName +
+ '<br/>Recipient ' + address.substr(0,15) + '...<br/>Date: ' +
+ formattingService.formatTimestamp(transaction.timestamp);
+ notificationService.notice(displayMessage);
+ //enable confirm button
+ transfer.confirm.paymentPending = 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
+ transfer.confirm.paymentPending = false;
+ transaction = undefined;
+ });
+ }
+
+ function resetPaymentForm() {
+ transfer.recipient = '';
+ transfer.amount = '0';
+ transfer.fee = {
+ amount: '0.001',
+ isValid: true
+ };
+ }
}
- WavesAssetTransferController.$inject = ['$scope', 'portfolio.events', 'autocomplete.fees', 'applicationContext'];
+ WavesAssetTransferController.$inject = ['$scope', '$timeout', 'constants.ui', 'portfolio.events',
+ 'autocomplete.fees', 'applicationContext', 'assetService', 'apiService', 'dialogService',
+ 'formattingService', 'notificationService'];
angular
.module('app.portfolio')
@@ -51,7 +51,7 @@
recipient: '',
paymentPending: false
};
- wallet.transfer = angular.copy(autocomplete);
+ wallet.transfer = autocomplete;
wallet.paymentValidationOptions = {
rules: {
wavesrecipient: {
@@ -134,8 +134,9 @@
function submitPayment() {
var paymentForm = getPaymentForm();
- wallet.transfer.fee.isValid = angular.isDefined(paymentForm.invalid.wavessendfee) ?
- paymentForm.invalid.wavessendfee : true;
+ var invalid = paymentForm.invalid();
+ wallet.transfer.fee.isValid = angular.isDefined(invalid.wavessendfee) ?
+ !invalid.wavessendfee : true;
if (!paymentForm.validate())
// prevent payment dialog from closing if it's not valid
return false;

0 comments on commit 8234110

Please sign in to comment.