Vote decoding tweaks (#1270)

This commit is contained in:
Jaco Greeff
2019-08-06 11:09:58 +02:00
committed by GitHub
parent 7ab0871e0c
commit 1b94f0ca7f
2 changed files with 136 additions and 117 deletions
+102 -91
View File
@@ -7,104 +7,115 @@ import '../../injector';
import Vote from './Vote';
describe('Vote', (): void => {
it('constructs via boolean true', (): void => {
expect(new Vote(true).toU8a()).toEqual(new Uint8Array([128]));
expect(new Vote(true).isAye).toBe(true);
expect(new Vote(true).isNay).toBe(false);
describe('construction', (): void => {
it('constructs via boolean true', (): void => {
expect(new Vote(true).toU8a()).toEqual(new Uint8Array([128]));
expect(new Vote(true).isAye).toBe(true);
expect(new Vote(true).isNay).toBe(false);
});
it('constructs via boolean false', (): void => {
expect(new Vote(false).toU8a()).toEqual(new Uint8Array([0]));
expect(new Vote(false).isNay).toBe(true);
expect(new Vote(false).isAye).toBe(false);
});
it('has isYay for positive', (): void => {
// eslint-disable-next-line no-new-wrappers
expect(new Vote(true).isAye).toBe(true);
});
it('has isNay for negative', (): void => {
// eslint-disable-next-line no-new-wrappers
expect(new Vote(false).isNay).toBe(true);
});
it('is Aye for negative numbers', (): void => {
expect(new Vote(-128).isAye).toBe(true);
});
it('is Nay for positive numbers', (): void => {
expect(new Vote(127).isNay).toBe(true);
});
it('is Nay for 0', (): void => {
expect(new Vote(0).isNay).toBe(true);
});
});
it('constructs via boolean false', (): void => {
expect(new Vote(false).toU8a()).toEqual(new Uint8Array([0]));
expect(new Vote(false).isNay).toBe(true);
expect(new Vote(false).isAye).toBe(false);
describe('Vote with conviction', (): void => {
it('constructs Vote with raw boolean', (): void => {
expect(
new Vote({
aye: true,
conviction: 'Locked1x'
}).toU8a()
).toEqual(new Uint8Array([0b10000001]));
});
it('constructs with Vote aye is false, conviction is None', (): void => {
expect(
new Vote({
aye: false,
conviction: 'None'
}).toU8a()
).toEqual(new Uint8Array([0b00000000]));
});
it('constructs with Vote aye is true, conviction is Locked4x', (): void => {
expect(
new Vote({
aye: true,
conviction: 'Locked4x'
}).toU8a()
).toEqual(new Uint8Array([0b10000100]));
});
});
it('has isYay for positive', (): void => {
// eslint-disable-next-line no-new-wrappers
expect(new Vote(true).isAye).toBe(true);
});
describe('getters', (): void => {
it('Conviction getter works', (): void => {
expect(
new Vote({
aye: true,
conviction: 'Locked2x'
}).conviction.toString()
).toEqual('Locked2x');
});
it('has isNay for negative', (): void => {
// eslint-disable-next-line no-new-wrappers
expect(new Vote(false).isNay).toBe(true);
});
it('Conviction getter works with raw boolean and string conviction', (): void => {
expect(
new Vote({
aye: true,
conviction: 'Locked2x'
}).conviction.toString()
).toEqual('Locked2x');
});
it('is Aye for negative numbers', (): void => {
expect(new Vote(-128).isAye).toBe(true);
});
it('Conviction getter works with raw boolean and conviction index', (): void => {
expect(
new Vote({
aye: true,
conviction: 2
}).conviction.toString()
).toEqual('Locked2x');
});
it('is Nay for positive numbers', (): void => {
expect(new Vote(127).isNay).toBe(true);
});
it('isAye getter works', (): void => {
expect(
new Vote({
aye: true,
conviction: 'None'
}).isAye)
.toEqual(true);
});
it('constructs V2 Vote with raw boolean', (): void => {
expect(
new Vote({
aye: true,
conviction: 'Locked1x'
}).toU8a()
).toEqual(new Uint8Array([0b10000001]));
});
it('constructs with V2 Vote aye is false, conviction is None', (): void => {
expect(
new Vote({
aye: false,
conviction: 'None'
}).toU8a()
).toEqual(new Uint8Array([0b00000000]));
});
it('constructs with Vote aye is true, conviction is Locked4x', (): void => {
expect(
new Vote({
aye: true,
conviction: 'Locked4x'
}).toU8a()
).toEqual(new Uint8Array([0b10000100]));
});
it('Conviction getter works', (): void => {
expect(
new Vote({
aye: true,
conviction: 'Locked2x'
}).conviction.toString()
).toEqual('Locked2x');
});
it('Conviction getter works with raw boolean and string conviction', (): void => {
expect(
new Vote({
aye: true,
conviction: 'Locked2x'
}).conviction.toString()
).toEqual('Locked2x');
});
it('Conviction getter works with raw boolean and conviction index', (): void => {
expect(
new Vote({
aye: true,
conviction: 2
}).conviction.toString()
).toEqual('Locked2x');
});
it('isAye getter works', (): void => {
expect(
new Vote({
aye: true,
conviction: 'None'
}).isAye)
.toEqual(true);
});
it('isNay getter works', (): void => {
expect(
new Vote({
aye: true,
conviction: 'None'
}).isNay)
.toEqual(false);
it('isNay getter works', (): void => {
expect(
new Vote({
aye: true,
conviction: 'None'
}).isNay)
.toEqual(false);
});
});
});
+34 -26
View File
@@ -7,18 +7,24 @@ import { Conviction } from '../../interfaces/democracy';
import { isBoolean, isNumber, isObject, isU8a, isUndefined } from '@polkadot/util';
import createType from '../../codec/createType';
import U8a from '../../codec/U8a';
import U8aFixed from '../../codec/U8aFixed';
import Bool from '../Bool';
// For votes, the topmost bit indicated aye/nay, the lower bits indicate the conviction
const AYE_BITS = 0b10000000;
const NAY_BITS = 0b00000000;
const CON_MASK = 0b01111111;
const DEF_CONV = 0b00000000; // the default conviction, None
/**
* @name Vote
* @description
* A number of lock periods, plus a vote, one way or the other.
*/
export default class Vote extends U8a {
private _aye: Bool;
export default class Vote extends U8aFixed {
private _aye: boolean;
private _conviction: Conviction; // for V1, default to None
private _conviction: Conviction;
public constructor (value?: any) {
// decoded is just 1 byte
@@ -26,39 +32,34 @@ export default class Vote extends U8a {
// Conviction: 0000 - 0101
const decoded = Vote.decodeVote(value);
super(decoded);
super(decoded, 8);
const msb = decoded[0] >> 7;
const conviction = decoded[0] & 0b01111111;
this._aye = new Bool(msb);
this._conviction = createType('Conviction', conviction);
this._aye = (decoded[0] & AYE_BITS) === AYE_BITS;
this._conviction = createType('Conviction', decoded[0] & CON_MASK);
}
private static decodeVote (value?: any): Uint8Array {
if (isUndefined(value)) {
return new Uint8Array([0]);
return new Uint8Array([NAY_BITS]);
} else if (isBoolean(value)) {
return value
? new Uint8Array([0b10000000])
: new Uint8Array([0b0]);
} else if (value instanceof Bool) {
? new Uint8Array([AYE_BITS | DEF_CONV])
: new Uint8Array([NAY_BITS]);
} else if (value instanceof Boolean) {
return Vote.decodeVote(value.valueOf());
} else if (isNumber(value)) {
return value < 0
? new Uint8Array([0b10000000])
: new Uint8Array([0b0]);
} else if (isObject(value) && !isUndefined(value.aye) && !isUndefined(value.conviction)) {
const aye = new Bool(value.aye);
const convictionIndex = createType('Conviction', value.conviction).index;
const result = convictionIndex | (aye.eq(true) ? 0b1 << 7 : 0b0);
return new Uint8Array([result]);
? new Uint8Array([AYE_BITS | DEF_CONV])
: new Uint8Array([NAY_BITS]);
} else if (isU8a(value)) {
return value.length
? value
: new Uint8Array([0]);
? value.subarray(0, 1)
: new Uint8Array([NAY_BITS]);
} else if (isObject(value)) {
const vote = new Bool(value.aye).eq(true) ? AYE_BITS : NAY_BITS;
const conviction = createType('Conviction', isUndefined(value.conviction) ? DEF_CONV : value.conviction);
return new Uint8Array([vote | conviction.index]);
}
throw new Error(`Unable to convert input ${value} to Vote`);
@@ -75,7 +76,7 @@ export default class Vote extends U8a {
* @description true if the wrapped value is a positive vote
*/
public get isAye (): boolean {
return this._aye.eq(true);
return this._aye;
}
/**
@@ -84,4 +85,11 @@ export default class Vote extends U8a {
public get isNay (): boolean {
return !this.isAye;
}
/**
* @description Returns the base runtime type name for this instance
*/
public toRawType (): string {
return 'Vote';
}
}