Skip to content

Commit 700b9cd

Browse files
authored
feat(core-transactions): unvote+vote transaction (#4044)
1 parent a917e08 commit 700b9cd

File tree

3 files changed

+193
-58
lines changed
  • __tests__/unit/core-transactions/handlers/two
  • packages

3 files changed

+193
-58
lines changed

__tests__/unit/core-transactions/handlers/two/vote.test.ts

Lines changed: 156 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,12 @@ describe("VoteTransaction", () => {
8181
let unvoteTransaction: Interfaces.ITransaction;
8282
let secondSignatureUnvoteTransaction: Interfaces.ITransaction;
8383
let multiSignatureUnvoteTransaction: Interfaces.ITransaction;
84-
let delegateWallet: Wallets.Wallet;
84+
let voteUnvoteTransaction: Interfaces.ITransaction;
85+
let unvoteVoteTransaction: Interfaces.ITransaction;
86+
let voteVoteTransaction: Interfaces.ITransaction;
87+
let unvoteUnvoteTransaction: Interfaces.ITransaction;
88+
let delegateWallet1: Wallets.Wallet;
89+
let delegateWallet2: Wallets.Wallet;
8590
let handler: TransactionHandler;
8691

8792
beforeEach(async () => {
@@ -93,61 +98,93 @@ describe("VoteTransaction", () => {
9398
2,
9499
);
95100

96-
delegateWallet = factoryBuilder
101+
delegateWallet1 = factoryBuilder
97102
.get("Wallet")
98103
.withOptions({
99104
passphrase: passphrases[8],
100105
nonce: 0,
101106
})
102107
.make();
108+
delegateWallet1.setAttribute("delegate", { username: "test1" });
109+
walletRepository.index(delegateWallet1);
103110

104-
delegateWallet.setAttribute("delegate", { username: "test" });
105-
106-
walletRepository.index(delegateWallet);
111+
delegateWallet2 = factoryBuilder
112+
.get("Wallet")
113+
.withOptions({
114+
passphrase: passphrases[9],
115+
nonce: 0,
116+
})
117+
.make();
118+
delegateWallet2.setAttribute("delegate", { username: "test2" });
119+
walletRepository.index(delegateWallet2);
107120

108121
voteTransaction = BuilderFactory.vote()
109-
.votesAsset(["+" + delegateWallet.publicKey!])
122+
.votesAsset(["+" + delegateWallet1.publicKey!])
110123
.nonce("1")
111124
.sign(passphrases[0])
112125
.build();
113126

114127
secondSignatureVoteTransaction = BuilderFactory.vote()
115-
.votesAsset(["+" + delegateWallet.publicKey!])
128+
.votesAsset(["+" + delegateWallet1.publicKey!])
116129
.nonce("1")
117130
.sign(passphrases[1])
118131
.secondSign(passphrases[2])
119132
.build();
120133

121134
multiSignatureVoteTransaction = BuilderFactory.vote()
122135
.senderPublicKey(multiSignatureWallet.publicKey!)
123-
.votesAsset(["+" + delegateWallet.publicKey!])
136+
.votesAsset(["+" + delegateWallet1.publicKey!])
124137
.nonce("1")
125138
.multiSign(passphrases[0], 0)
126139
.multiSign(passphrases[1], 1)
127140
.multiSign(passphrases[2], 2)
128141
.build();
129142

130143
unvoteTransaction = BuilderFactory.vote()
131-
.votesAsset(["-" + delegateWallet.publicKey!])
144+
.votesAsset(["-" + delegateWallet1.publicKey!])
132145
.nonce("1")
133146
.sign(passphrases[0])
134147
.build();
135148

136149
secondSignatureUnvoteTransaction = BuilderFactory.vote()
137-
.votesAsset(["-" + delegateWallet.publicKey!])
150+
.votesAsset(["-" + delegateWallet1.publicKey!])
138151
.nonce("1")
139152
.sign(passphrases[1])
140153
.secondSign(passphrases[2])
141154
.build();
142155

143156
multiSignatureUnvoteTransaction = BuilderFactory.vote()
144157
.senderPublicKey(multiSignatureWallet.publicKey!)
145-
.votesAsset(["-" + delegateWallet.publicKey!])
158+
.votesAsset(["-" + delegateWallet1.publicKey!])
146159
.nonce("1")
147160
.multiSign(passphrases[0], 0)
148161
.multiSign(passphrases[1], 1)
149162
.multiSign(passphrases[2], 2)
150163
.build();
164+
165+
voteUnvoteTransaction = BuilderFactory.vote()
166+
.votesAsset(["+" + delegateWallet1.publicKey!, "-" + delegateWallet1.publicKey!])
167+
.nonce("1")
168+
.sign(passphrases[0])
169+
.build();
170+
171+
unvoteVoteTransaction = BuilderFactory.vote()
172+
.votesAsset(["-" + delegateWallet1.publicKey!, "+" + delegateWallet2.publicKey!])
173+
.nonce("1")
174+
.sign(passphrases[0])
175+
.build();
176+
177+
voteVoteTransaction = BuilderFactory.vote()
178+
.votesAsset(["+" + delegateWallet1.publicKey!, "+" + delegateWallet2.publicKey!])
179+
.nonce("1")
180+
.sign(passphrases[0])
181+
.build();
182+
183+
unvoteUnvoteTransaction = BuilderFactory.vote()
184+
.votesAsset(["-" + delegateWallet1.publicKey!, "-" + delegateWallet2.publicKey!])
185+
.nonce("1")
186+
.sign(passphrases[0])
187+
.build();
151188
});
152189

153190
describe("bootstrap", () => {
@@ -169,7 +206,7 @@ describe("VoteTransaction", () => {
169206
transactionHistoryService.streamByCriteria.mockImplementationOnce(async function* () {
170207
yield voteTransaction.data;
171208
});
172-
senderWallet.setAttribute("vote", delegateWallet.publicKey);
209+
senderWallet.setAttribute("vote", delegateWallet1.publicKey);
173210
await expect(handler.bootstrap()).rejects.toThrow(AlreadyVotedError);
174211
});
175212

@@ -258,34 +295,34 @@ describe("VoteTransaction", () => {
258295
});
259296

260297
it("should not throw if the unvote is valid and the wallet has voted", async () => {
261-
senderWallet.setAttribute("vote", delegateWallet.publicKey);
298+
senderWallet.setAttribute("vote", delegateWallet1.publicKey);
262299
await expect(handler.throwIfCannotBeApplied(unvoteTransaction, senderWallet)).toResolve();
263300
});
264301

265302
it("should not throw - second sign unvote", async () => {
266-
secondSignatureWallet.setAttribute("vote", delegateWallet.publicKey);
303+
secondSignatureWallet.setAttribute("vote", delegateWallet1.publicKey);
267304
await expect(
268305
handler.throwIfCannotBeApplied(secondSignatureUnvoteTransaction, secondSignatureWallet),
269306
).toResolve();
270307
});
271308

272309
it("should not throw - multi sign unvote", async () => {
273-
multiSignatureWallet.setAttribute("vote", delegateWallet.publicKey);
310+
multiSignatureWallet.setAttribute("vote", delegateWallet1.publicKey);
274311
await expect(
275312
handler.throwIfCannotBeApplied(multiSignatureUnvoteTransaction, multiSignatureWallet),
276313
).toResolve();
277314
});
278315

279316
it("should throw if wallet has already voted", async () => {
280-
senderWallet.setAttribute("vote", delegateWallet.publicKey);
317+
senderWallet.setAttribute("vote", delegateWallet1.publicKey);
281318
await expect(handler.throwIfCannotBeApplied(voteTransaction, senderWallet)).rejects.toThrow(
282319
AlreadyVotedError,
283320
);
284321
});
285322

286323
it("should throw if vote for non delegate wallet", async () => {
287-
delegateWallet.forgetAttribute("delegate");
288-
walletRepository.index(delegateWallet);
324+
delegateWallet1.forgetAttribute("delegate");
325+
walletRepository.index(delegateWallet1);
289326
await expect(handler.throwIfCannotBeApplied(voteTransaction, senderWallet)).rejects.toThrow(
290327
VotedForNonDelegateError,
291328
);
@@ -311,7 +348,7 @@ describe("VoteTransaction", () => {
311348

312349
it("should throw if wallet has insufficient funds for unvote", async () => {
313350
senderWallet.balance = Utils.BigNumber.ZERO;
314-
senderWallet.setAttribute("vote", delegateWallet.publicKey);
351+
senderWallet.setAttribute("vote", delegateWallet1.publicKey);
315352
await expect(handler.throwIfCannotBeApplied(unvoteTransaction, senderWallet)).rejects.toThrow(
316353
InsufficientBalanceError,
317354
);
@@ -332,6 +369,44 @@ describe("VoteTransaction", () => {
332369
Exceptions.Runtime.AssertionException,
333370
);
334371
});
372+
373+
it("should not throw on vote+unvote transaction when wallet has not voted", async () => {
374+
await handler.throwIfCannotBeApplied(voteUnvoteTransaction, senderWallet);
375+
});
376+
377+
it("should throw on vote+unvote transaction when wallet has voted", async () => {
378+
senderWallet.setAttribute("vote", delegateWallet1.publicKey);
379+
380+
await expect(handler.throwIfCannotBeApplied(voteUnvoteTransaction, senderWallet)).rejects.toThrow(
381+
AlreadyVotedError,
382+
);
383+
});
384+
385+
it("should not throw on unvote+vote transaction when wallet has voted", async () => {
386+
senderWallet.setAttribute("vote", delegateWallet1.publicKey);
387+
388+
await handler.throwIfCannotBeApplied(unvoteVoteTransaction, senderWallet);
389+
});
390+
391+
it("should throw on unvote+vote transaction when wallet has not voted", async () => {
392+
await expect(handler.throwIfCannotBeApplied(unvoteVoteTransaction, senderWallet)).rejects.toThrow(
393+
NoVoteError,
394+
);
395+
});
396+
397+
it("should throw on vote+vote transaction when wallet has not voted", async () => {
398+
await expect(handler.throwIfCannotBeApplied(voteVoteTransaction, senderWallet)).rejects.toThrow(
399+
AlreadyVotedError,
400+
);
401+
});
402+
403+
it("should throw on unvote+unvote transaction when wallet has voted", async () => {
404+
senderWallet.setAttribute("vote", delegateWallet1.publicKey);
405+
406+
await expect(handler.throwIfCannotBeApplied(unvoteUnvoteTransaction, senderWallet)).rejects.toThrow(
407+
NoVoteError,
408+
);
409+
});
335410
});
336411

337412
describe("throwIfCannotEnterPool", () => {
@@ -358,7 +433,7 @@ describe("VoteTransaction", () => {
358433
});
359434

360435
it("should not be ok", async () => {
361-
senderWallet.setAttribute("vote", delegateWallet.publicKey);
436+
senderWallet.setAttribute("vote", delegateWallet1.publicKey);
362437

363438
expect(senderWallet.getAttribute("vote")).not.toBeUndefined();
364439

@@ -370,7 +445,7 @@ describe("VoteTransaction", () => {
370445

371446
describe("unvote", () => {
372447
it("should remove the vote from the wallet", async () => {
373-
senderWallet.setAttribute("vote", delegateWallet.publicKey);
448+
senderWallet.setAttribute("vote", delegateWallet1.publicKey);
374449

375450
expect(senderWallet.getAttribute("vote")).not.toBeUndefined();
376451

@@ -379,6 +454,40 @@ describe("VoteTransaction", () => {
379454
expect(senderWallet.hasAttribute("vote")).toBeFalse();
380455
});
381456
});
457+
458+
describe("vote+unvote", () => {
459+
it("should apply when wallet has not voted", async () => {
460+
await handler.apply(voteUnvoteTransaction);
461+
462+
expect(senderWallet.hasAttribute("vote")).toBeFalse();
463+
});
464+
465+
it("should throw when wallet has voted", async () => {
466+
senderWallet.setAttribute("vote", delegateWallet1.publicKey);
467+
468+
await expect(handler.apply(voteUnvoteTransaction)).rejects.toThrow(AlreadyVotedError);
469+
});
470+
});
471+
472+
describe("unvote+vote", () => {
473+
it("should apply when wallet has voted", async () => {
474+
senderWallet.setAttribute("vote", delegateWallet1.publicKey);
475+
476+
await handler.apply(unvoteVoteTransaction);
477+
478+
expect(senderWallet.getAttribute("vote")).toEqual(delegateWallet2.publicKey);
479+
});
480+
481+
it("should throw when wallet has not voted", async () => {
482+
await expect(handler.apply(unvoteUnvoteTransaction)).rejects.toThrow(NoVoteError);
483+
});
484+
485+
it("should throw when wallet has voted for different delegate", async () => {
486+
senderWallet.setAttribute("vote", delegateWallet2.publicKey);
487+
488+
await expect(handler.apply(unvoteUnvoteTransaction)).rejects.toThrow(UnvoteMismatchError);
489+
});
490+
});
382491
});
383492

384493
describe("applyForSender", () => {
@@ -402,7 +511,7 @@ describe("VoteTransaction", () => {
402511
describe("revert", () => {
403512
describe("vote", () => {
404513
it("should remove the vote from the wallet", async () => {
405-
senderWallet.setAttribute("vote", delegateWallet.publicKey);
514+
senderWallet.setAttribute("vote", delegateWallet1.publicKey);
406515
senderWallet.nonce = Utils.BigNumber.make(1);
407516

408517
expect(senderWallet.getAttribute("vote")).not.toBeUndefined();
@@ -423,7 +532,28 @@ describe("VoteTransaction", () => {
423532
await handler.revert(unvoteTransaction);
424533

425534
expect(senderWallet.nonce.isZero()).toBeTrue();
426-
expect(senderWallet.getAttribute("vote")).toBe(delegateWallet.publicKey);
535+
expect(senderWallet.getAttribute("vote")).toBe(delegateWallet1.publicKey);
536+
});
537+
});
538+
539+
describe("vote+unvote", () => {
540+
it("should revert when wallet has no vote", async () => {
541+
senderWallet.nonce = Utils.BigNumber.make(1);
542+
543+
await handler.revert(voteUnvoteTransaction);
544+
545+
expect(senderWallet.hasAttribute("vote")).toBeFalse();
546+
});
547+
});
548+
549+
describe("unvote+vote", () => {
550+
it("should revert when wallet has no vote", async () => {
551+
senderWallet.setAttribute("vote", delegateWallet2.publicKey);
552+
senderWallet.nonce = Utils.BigNumber.make(1);
553+
554+
await handler.revert(unvoteVoteTransaction);
555+
556+
expect(senderWallet.getAttribute("vote")).toEqual(delegateWallet1.publicKey);
427557
});
428558
});
429559
});
@@ -444,7 +574,9 @@ describe("VoteTransaction", () => {
444574

445575
senderWallet.nonce = Utils.BigNumber.ONE;
446576

447-
await expect(handler.revertForSender(voteTransaction)).rejects.toThrow(Exceptions.Runtime.AssertionException);
577+
await expect(handler.revertForSender(voteTransaction)).rejects.toThrow(
578+
Exceptions.Runtime.AssertionException,
579+
);
448580
});
449581
});
450582
});

0 commit comments

Comments
 (0)