-
Notifications
You must be signed in to change notification settings - Fork 263
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a partial support for vote program (#167)
* Add a partial support for vote program * Add tests * Add some comments * Fix linting errors
- Loading branch information
1 parent
4611d3e
commit 291286e
Showing
3 changed files
with
193 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
"""Byte layouts for vote program instructions.""" | ||
from enum import IntEnum | ||
|
||
from construct import Switch # type: ignore | ||
from construct import Int32ul, Int64ul | ||
from construct import Struct as cStruct | ||
|
||
|
||
class InstructionType(IntEnum): | ||
"""Instruction types for vote program.""" | ||
|
||
WITHDRAW_FROM_VOTE_ACCOUNT = 3 | ||
|
||
|
||
_WITHDRAW_FROM_VOTE_ACCOUNT_LAYOUT = cStruct("lamports" / Int64ul) | ||
|
||
VOTE_INSTRUCTIONS_LAYOUT = cStruct( | ||
"instruction_type" / Int32ul, | ||
"args" | ||
/ Switch( | ||
lambda this: this.instruction_type, | ||
{ | ||
InstructionType.WITHDRAW_FROM_VOTE_ACCOUNT: _WITHDRAW_FROM_VOTE_ACCOUNT_LAYOUT, | ||
}, | ||
), | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
"""Library to interface with the vote program.""" | ||
from __future__ import annotations | ||
|
||
from typing import NamedTuple | ||
|
||
from solana._layouts.vote_instructions import VOTE_INSTRUCTIONS_LAYOUT, InstructionType | ||
from solana.publickey import PublicKey | ||
from solana.transaction import AccountMeta, TransactionInstruction | ||
|
||
VOTE_PROGRAM_ID: PublicKey = PublicKey("Vote111111111111111111111111111111111111111") | ||
"""Public key that identifies the Vote program.""" | ||
|
||
|
||
# Instrection Params | ||
class WithdrawFromVoteAccountParams(NamedTuple): | ||
"""Transfer SOL from vote account to identity.""" | ||
|
||
vote_account_from_pubkey: PublicKey | ||
"""""" | ||
to_pubkey: PublicKey | ||
"""""" | ||
lamports: int | ||
"""""" | ||
withdrawer: PublicKey | ||
"""""" | ||
|
||
|
||
def withdraw_from_vote_account(params: WithdrawFromVoteAccountParams) -> TransactionInstruction: | ||
"""Generate an instruction that transfers lamports from a vote account to any other. | ||
>>> from solana.publickey import PublicKey | ||
>>> from solana.keypair import Keypair | ||
>>> vote = PublicKey(1) | ||
>>> withdrawer = Keypair.from_seed(bytes([0]*32)) | ||
>>> instruction = withdraw_from_vote_account( | ||
... WithdrawFromVoteAccountParams( | ||
... vote_account_from_pubkey=vote, | ||
... to_pubkey=withdrawer, | ||
... withdrawer=withdrawer, | ||
... lamports=3_000_000_000, | ||
... ) | ||
... ) | ||
>>> type(instruction) | ||
<class 'solana.transaction.TransactionInstruction'> | ||
""" | ||
data = VOTE_INSTRUCTIONS_LAYOUT.build( | ||
dict(instruction_type=InstructionType.WITHDRAW_FROM_VOTE_ACCOUNT, args=dict(lamports=params.lamports)) | ||
) | ||
|
||
return TransactionInstruction( | ||
keys=[ | ||
AccountMeta(pubkey=params.vote_account_from_pubkey, is_signer=False, is_writable=True), | ||
AccountMeta(pubkey=params.to_pubkey, is_signer=False, is_writable=True), | ||
AccountMeta(pubkey=params.withdrawer, is_signer=True, is_writable=True), | ||
], | ||
program_id=VOTE_PROGRAM_ID, | ||
data=data, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
"""Unit tests for solana.vote_program.""" | ||
import base64 | ||
|
||
import solana.vote_program as vp | ||
import solana.transaction as txlib | ||
from solana.keypair import Keypair | ||
from solana.publickey import PublicKey | ||
|
||
|
||
def test_withdraw_from_vote_account(): | ||
withdrawer_keypair = Keypair.from_secret_key( | ||
bytes( | ||
[ | ||
134, | ||
123, | ||
27, | ||
208, | ||
227, | ||
175, | ||
253, | ||
99, | ||
4, | ||
81, | ||
170, | ||
231, | ||
186, | ||
141, | ||
177, | ||
142, | ||
197, | ||
139, | ||
94, | ||
6, | ||
157, | ||
2, | ||
163, | ||
89, | ||
150, | ||
121, | ||
235, | ||
86, | ||
185, | ||
22, | ||
1, | ||
233, | ||
58, | ||
133, | ||
229, | ||
39, | ||
212, | ||
71, | ||
254, | ||
72, | ||
246, | ||
45, | ||
160, | ||
156, | ||
129, | ||
199, | ||
18, | ||
189, | ||
53, | ||
143, | ||
98, | ||
72, | ||
182, | ||
106, | ||
69, | ||
29, | ||
38, | ||
145, | ||
119, | ||
190, | ||
13, | ||
105, | ||
157, | ||
112, | ||
] | ||
) | ||
) | ||
vote_account_pubkey = PublicKey("CWqJy1JpmBcx7awpeANfrPk6AsQKkmego8ujjaYPGFEk") | ||
receiver_account_pubkey = PublicKey("A1V5gsis39WY42djdTKUFsgE5oamk4nrtg16WnKTuzZK") | ||
|
||
# solana withdraw-from-vote-account --dump-transaction-message \ | ||
# CWqJy1JpmBcx7awpeANfrPk6AsQKkmego8ujjaYPGFEk A1V5gsis39WY42djdTKUFsgE5oamk4nrtg16WnKTuzZK \ | ||
# --authorized-withdrawer withdrawer.json \ | ||
# 2 \ | ||
# --blockhash Add1tV7kJgNHhTtx3Dgs6dhC7kyXrGJQZ2tJGW15tLDH \ | ||
# --sign-only -k withdrawer.json | ||
wire_msg = base64.b64decode( | ||
b"AQABBDqF5SfUR/5I9i2gnIHHEr01j2JItmpFHSaRd74NaZ1wqxUGDtH5ah3TqEKWjcTmfHkpZC1h57NJL8Sx7Q6Olm2F2O70oOvzt1HgIVu+nySaSrWtJiK1eDacPPDWRxCwFgdhSB01dHS7fE12JOvTvbPYNV5z0RBD/A2jU4AAAAAAjxrQaMS7FjmaR++mvFr3XE6XbzMUTMJUIpITrUWBzGwBAwMBAgAMAwAAAACUNXcAAAAA" # noqa: E501 pylint: disable=line-too-long | ||
) | ||
|
||
txn = txlib.Transaction(fee_payer=withdrawer_keypair.public_key) | ||
txn.recent_blockhash = "Add1tV7kJgNHhTtx3Dgs6dhC7kyXrGJQZ2tJGW15tLDH" | ||
|
||
txn.add( | ||
vp.withdraw_from_vote_account( | ||
vp.WithdrawFromVoteAccountParams( | ||
vote_account_from_pubkey=vote_account_pubkey, | ||
to_pubkey=receiver_account_pubkey, | ||
withdrawer=withdrawer_keypair.public_key, | ||
lamports=2_000_000_000, | ||
) | ||
) | ||
) | ||
|
||
serialized_message = txn.serialize_message() | ||
assert serialized_message == wire_msg |