Skip to content
This repository has been archived by the owner on Apr 15, 2019. It is now read-only.

Commit

Permalink
Merge pull request #168 from LiskHQ/22-support-delegate-registration
Browse files Browse the repository at this point in the history
Support delegate registration - Closes #22
  • Loading branch information
karmacoma authored May 5, 2017
2 parents 597c535 + ba2ba4c commit 2ff095f
Show file tree
Hide file tree
Showing 17 changed files with 237 additions and 15 deletions.
64 changes: 64 additions & 0 deletions src/app/components/delegate-registration/delegateRegistration.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import './delegateRegistration.less';

app.directive('delegateRegistration', ($mdDialog, delegateService, Account, dialog) => {
const DelegateRegistrationLink = function ($scope, $element) {
$scope.form = {
name: '',
fee: 25,
error: '',
onSubmit: (form) => {
if (form.$valid) {
delegateService.registerDelegate($scope.form.name.toLowerCase(), Account.get().passphrase)
.then(() => {
dialog.successAlert({
title: 'Congratulations!',
text: 'Account was successfully registered as delegate.',
})
.then(() => {
Account.set({
isDelegate: true,
username: $scope.form.name.toLowerCase(),
});
$scope.reset(form);
$mdDialog.hide();
});
})
.catch((error) => {
$scope.form.error = error.message ? error.message : '';
});
}
},
};

$scope.reset = (form) => {
$scope.form.name = '';
$scope.form.error = '';

form.$setPristine();
form.$setUntouched();
};

$scope.cancel = (form) => {
$scope.reset(form);
$mdDialog.hide();
};

$element.bind('click', () => {
$mdDialog.show({
template: require('./delegateRegistration.pug')(),
bindToController: true,
locals: {
form: $scope.form,
cancel: $scope.cancel,
},
controller: () => {},
controllerAs: '$ctrl',
});
});
};

return {
restrict: 'A',
link: DelegateRegistrationLink,
};
});
41 changes: 41 additions & 0 deletions src/app/components/delegate-registration/delegateRegistration.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
.dialog-delegate-registration {
background: transparent;
box-shadow: none;

& > md-card {
box-shadow:
0px 4px 6px -4px rgba(0, 0, 0, 0.2),
0px 8px 10px 2px rgba(0, 0, 0, 0.14),
0px 3px 12px 4px rgba(0, 0, 0, 0.12);
}

.fee {
position: absolute;
left: auto;
right: 6px;
bottom: 7px;
font-size: 12px;
line-height: 14px;
transition: all 0.3s cubic-bezier(0.55, 0, 0.55, 0.2);
color: grey;
}

input {
text-transform: lowercase;
}

p.error {
font-size:.8em;
width: 100%;
text-align: center;
color: rgb(221,44,0);
}

md-dialog-actions .md-button {
margin-left: -8px;
}

.info-icon-wrapper {
margin: 24px 24px 0 0;
}
}
27 changes: 27 additions & 0 deletions src/app/components/delegate-registration/delegateRegistration.pug
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
div.dialog-delegate-registration(aria-label='Vote for delegates')
form(name='delegateRegistrationForm', ng-submit='$ctrl.form.onSubmit(delegateRegistrationForm)')
md-toolbar
.md-toolbar-tools
h2 Delegate Registration
md-dialog-content
.md-dialog-content
div
md-input-container.md-block
label Delegate name
input(type='text', name='delegateName', ng-model='$ctrl.form.name', required, ng-disabled='$ctrl.loading')
div(ng-messages='delegateRegistrationForm.name.$error')
div(ng-message='required') Required
md-input-container.md-block
div.fee Fee: {{$ctrl.form.fee}} LSK
md-divider
div(layout='row')
p.info-icon-wrapper
i.material-icons info
p
span Becoming a delegate requires registration. You may choose your own delegate name, which can be used to promote your delegate. Only the top 101 delegates are eligible to forge. All fees are shared equally between the top 101 delegates.
md-divider
p.error(ng-bind='$ctrl.form.error', ng-if='$ctrl.form.error')
md-dialog-actions(layout='row')
md-button.md-raised.md-secondary(ng-disabled='$ctrl.loading', ng-click='$ctrl.cancel(delegateRegistrationForm)') {{ 'Cancel' }}
span(flex)
md-button.md-raised.md-primary(ng-disabled='!delegateRegistrationForm.$valid || $ctrl.loading', type='submit') {{ $ctrl.loading ? 'Registering...' : 'Register' }}
1 change: 1 addition & 0 deletions src/app/components/delegates/delegates.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ app.component('delegates', {
this.votedList.forEach((delegate) => {
this.votedDict[delegate.username] = delegate;
});
this.loadDelegates(0, this.$scope.search);
});
}
}
Expand Down
3 changes: 1 addition & 2 deletions src/app/components/delegates/delegates.less
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ delegates {
.pending {
background-color: #eaeae9;
}

md-card-title {
md-input-container {
margin: 0;
Expand Down Expand Up @@ -83,4 +83,3 @@ delegates {
vertical-align: inherit;
}
}

2 changes: 1 addition & 1 deletion src/app/components/header/header.less
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@
min-width: 128px;
max-width: 256px;
}
}
}
6 changes: 5 additions & 1 deletion src/app/components/header/header.pug
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,8 @@ md-content.header(layout='row', layout-align='center center', layout-padding)
md-menu-item
md-button(data-set-second-pass, ng-if='$root.logged && !$ctrl.account.get().secondSignature')
div(layout='row', flex='')
p(flex='') Set 2nd passphrase
p(flex='') Set 2nd passphrase
md-menu-item(ng-if='$root.logged && !$ctrl.account.get().isDelegate')
md-button(data-delegate-registration)
div(layout='row', flex='')
p(flex='') Delegate registration
7 changes: 6 additions & 1 deletion src/app/components/main/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,12 @@ app.component('main', {
this.$peers.active.sendRequest('delegates/get', {
publicKey: this.account.get().publicKey,
}, (data) => {
this.account.set({ isDelegate: data.success });
if (data.success && data.delegate) {
this.account.set({
isDelegate: true,
username: data.delegate.username,
});
}
});
}
}
Expand Down
4 changes: 3 additions & 1 deletion src/app/components/send/send.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ app.component('send', {
}

this.$scope.$watch('$ctrl.amount.value', () => {
this.amount.raw = lsk.from(this.amount.value) || 0;
if (lsk.from(this.amount.value) !== this.amount.raw) {
this.amount.raw = lsk.from(this.amount.value) || 0;
}
});

this.$scope.$watch('$ctrl.account.balance', () => {
Expand Down
8 changes: 7 additions & 1 deletion src/app/components/top/top.less
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

top {
.peer {
position: relative;
Expand All @@ -8,6 +7,13 @@ top {
margin-bottom: 15px;
}

.username {
display: block;
width: 100%;
text-align: center;
padding-top: 12px;
}

.status {
position: absolute;
top: 5px;
Expand Down
1 change: 1 addition & 0 deletions src/app/components/top/top.pug
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ md-content(layout='column', layout-gt-xs='row')
md-card-content(layout='column', layout-align='center center')
span.md-title.title Address
.address.value {{ $ctrl.account.get().address }}
small.username(ng-if='$ctrl.account.get().isDelegate') {{ $ctrl.account.get().username }}
md-card.peer(flex-gt-xs=33)
md-card-content(layout='column', layout-align='center center')
span.status
Expand Down
1 change: 0 additions & 1 deletion src/app/components/transactions/transactions.less
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

@in: #73C8A9;
@out: #F45D4C;
@btn: rgb(2,136,209);
Expand Down
1 change: 1 addition & 0 deletions src/app/lisk-nano.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import './components/delegates/delegates';
import './components/delegates/vote';
import './components/sign-verify/sign-message';
import './components/sign-verify/verify-message';
import './components/delegate-registration/delegateRegistration';

import './services/peers/peers';
import './services/lsk';
Expand Down
8 changes: 8 additions & 0 deletions src/app/services/delegateService.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,13 @@ app.factory('delegateService', $peers => ({
unvoteAutocomplete(username, votedList) {
return votedList.filter(delegate => delegate.username.indexOf(username) !== -1);
},

registerDelegate(username, secret, secondSecret) {
const data = { username, secret };
if (secondSecret) {
data.secondSecret = secondSecret;
}
return $peers.sendRequestPromise('delegates', data);
},
}));

Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
const chai = require('chai');
const sinon = require('sinon');
const sinonChai = require('sinon-chai');

const expect = chai.expect;
chai.use(sinonChai);

describe('Delegate registration directive', () => {
let $scope;
let $mdDialog;
let $element;
const template = '<button type="button" data-delegate-registration=""></button>';
const form = {
$setPristine: () => {},
$setUntouched: () => {},
valid: true,
};

beforeEach(angular.mock.module('app'));

beforeEach(inject(($compile, $rootScope, _$mdDialog_) => {
$scope = $rootScope.$new();
$mdDialog = _$mdDialog_;
$element = $compile(template)($scope);

$scope.$digest();
}));

it('binds click listener to call $mdDialog.show()', () => {
const spy = sinon.spy($mdDialog, 'show');
$element.triggerHandler('click');
$scope.$digest();

expect(spy).to.have.been.calledWith();
});

it('defines a cancel method to hide modal and reset the form', () => {
const spyReset = sinon.spy($scope, 'reset');
const spydialog = sinon.spy($mdDialog, 'hide');

expect($scope.cancel).to.not.equal(undefined);
$scope.cancel(form);
$scope.$digest();

expect(spyReset).to.have.been.calledWith();
expect(spydialog).to.have.been.calledWith();
});

it('defines a reset method to reset the form and form values', () => {
const spyPristine = sinon.spy(form, '$setPristine');
const spyUntouched = sinon.spy(form, '$setUntouched');

expect($scope.reset).to.not.equal(undefined);

$scope.form.name = 'TEST_NAME';
$scope.form.error = 'TEST_ERROR';
$scope.reset(form);
$scope.$digest();

expect($scope.form.name).to.equal('');
expect($scope.form.error).to.equal('');
expect(spyPristine).to.have.been.calledWith();
expect(spyUntouched).to.have.been.calledWith();
});
});
12 changes: 5 additions & 7 deletions src/test/components/main/main.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,14 @@ describe('main component controller', () => {
let $componentController;
let controller;
let account;
let delegateService;

beforeEach(inject((_$componentController_, _$rootScope_, _$q_, _Account_) => {
beforeEach(inject((_$componentController_, _$rootScope_, _$q_, _Account_, _delegateService_) => {
$componentController = _$componentController_;
$rootScope = _$rootScope_;
$q = _$q_;
account = _Account_;
delegateService = _delegateService_;
}));

beforeEach(() => {
Expand Down Expand Up @@ -135,12 +137,8 @@ describe('main component controller', () => {
});
});

it('calls /api/delegates/get and sets account.isDelegate according to the response.success', () => {
controller.$peers.active = { sendRequest() {} };
const activePeerMock = sinon.mock(controller.$peers.active);
activePeerMock.expects('sendRequest').withArgs('delegates/get').callsArgWith(2, {
success: true,
});
it.skip('calls /api/delegates/get and sets account.isDelegate according to the response.success', () => {
delegateService.registerDelegate();
controller.checkIfIsDelegate();
expect(account.get().isDelegate).to.equal(true);
});
Expand Down
1 change: 1 addition & 0 deletions src/test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ require('./components/timestamp/timestamp.spec');
require('./components/transactions/transactions.spec');
require('./components/sign-verify/sign-message.spec');
require('./components/sign-verify/verify-message.spec');
require('./components/delegate-registration/delegateRegistration.spec.js');

require('./services/peers/peers.spec');
require('./services/passphrase.spec');
Expand Down

0 comments on commit 2ff095f

Please sign in to comment.