diff --git a/__tests__/functional/transaction-forging/vote.test.ts b/__tests__/functional/transaction-forging/vote.test.ts index 432b625931..28d94d4bf3 100644 --- a/__tests__/functional/transaction-forging/vote.test.ts +++ b/__tests__/functional/transaction-forging/vote.test.ts @@ -9,24 +9,66 @@ beforeAll(support.setUp); afterAll(support.tearDown); describe("Transaction Forging - Vote", () => { - it("should broadcast, accept and forge it [Signed with 1 Passphase]", async () => { - // Initial Funds - const initialFunds = TransactionFactory.transfer(Identities.Address.fromPassphrase(passphrase), 100 * 1e8) - .withPassphrase(secrets[0]) - .createOne(); - - await expect(initialFunds).toBeAccepted(); - await support.snoozeForBlock(1); - await expect(initialFunds.id).toBeForged(); - - // Submit a vote - const transactions = TransactionFactory.vote(Identities.PublicKey.fromPassphrase(secrets[0])) - .withPassphrase(passphrase) - .createOne(); - - await expect(transactions).toBeAccepted(); - await support.snoozeForBlock(1); - await expect(transactions.id).toBeForged(); + describe("Signed with 1 Passphase", () => { + it("should broadcast, accept and forge it", async () => { + // Initial Funds + const initialFunds = TransactionFactory.transfer(Identities.Address.fromPassphrase(passphrase), 100 * 1e8) + .withPassphrase(secrets[0]) + .createOne(); + + await expect(initialFunds).toBeAccepted(); + await support.snoozeForBlock(1); + await expect(initialFunds.id).toBeForged(); + + // Register a delegate + const registration = TransactionFactory.delegateRegistration() + .withPassphrase(passphrase) + .createOne(); + + await expect(registration).toBeAccepted(); + await support.snoozeForBlock(1); + await expect(registration.id).toBeForged(); + + // Submit a vote + const vote = TransactionFactory.vote(Identities.PublicKey.fromPassphrase(passphrase)) + .withPassphrase(passphrase) + .createOne(); + + await expect(vote).toBeAccepted(); + await support.snoozeForBlock(1); + await expect(vote.id).toBeForged(); + }); + + it("should broadcast, accept and forge it if unvoting a resigned delegate", async () => { + // Resign a delegate + const resignation = TransactionFactory.delegateResignation() + .withPassphrase(passphrase) + .createOne(); + + await expect(resignation).toBeAccepted(); + await support.snoozeForBlock(1); + await expect(resignation.id).toBeForged(); + + // Submit an unvote + const unvote = TransactionFactory.unvote(Identities.PublicKey.fromPassphrase(passphrase)) + .withPassphrase(passphrase) + .createOne(); + + await expect(unvote).toBeAccepted(); + await support.snoozeForBlock(1); + await expect(unvote.id).toBeForged(); + }); + + it("should broadcast, reject and not forge it if voting for a resigned delegate", async () => { + // Submit a vote + const vote = TransactionFactory.vote(Identities.PublicKey.fromPassphrase(passphrase)) + .withPassphrase(passphrase) + .createOne(); + + await expect(vote).toBeRejected(); + await support.snoozeForBlock(1); + await expect(vote.id).not.toBeForged(); + }); }); it("should broadcast, accept and forge it [Signed with 2 Passphrases]", async () => { diff --git a/packages/core-transactions/src/handlers/vote.ts b/packages/core-transactions/src/handlers/vote.ts index 25b56bf7fe..690e6a8566 100644 --- a/packages/core-transactions/src/handlers/vote.ts +++ b/packages/core-transactions/src/handlers/vote.ts @@ -62,13 +62,21 @@ export class VoteTransactionHandler extends TransactionHandler { walletManager: State.IWalletManager, ): Promise { const { data }: Interfaces.ITransaction = transaction; + const vote: string = data.asset.votes[0]; const walletVote: string = wallet.getAttribute("vote"); + const delegatePublicKey: string = vote.slice(1); + const delegateWallet: State.IWallet = walletManager.findByPublicKey(delegatePublicKey); + if (vote.startsWith("+")) { if (walletVote) { throw new AlreadyVotedError(); } + + if (delegateWallet.hasAttribute("delegate.resigned")) { + throw new VotedForResignedDelegateError(vote); + } } else { if (!walletVote) { throw new NoVoteError(); @@ -77,17 +85,10 @@ export class VoteTransactionHandler extends TransactionHandler { } } - const delegatePublicKey: string = vote.slice(1); - const delegateWallet: State.IWallet = walletManager.findByPublicKey(delegatePublicKey); - if (!delegateWallet.isDelegate()) { throw new VotedForNonDelegateError(vote); } - if (delegateWallet.hasAttribute("delegate.resigned")) { - throw new VotedForResignedDelegateError(vote); - } - return super.throwIfCannotBeApplied(transaction, wallet, walletManager); }