@solana/web3.js 1.31.0 → 1.33.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.browser.esm.js +577 -68
- package/lib/index.browser.esm.js.map +1 -1
- package/lib/index.cjs.js +582 -67
- package/lib/index.cjs.js.map +1 -1
- package/lib/index.d.ts +221 -19
- package/lib/index.esm.js +577 -68
- package/lib/index.esm.js.map +1 -1
- package/lib/index.iife.js +582 -67
- package/lib/index.iife.js.map +1 -1
- package/lib/index.iife.min.js +3 -3
- package/lib/index.iife.min.js.map +1 -1
- package/module.flow.js +260 -20
- package/package.json +5 -10
- package/src/connection.ts +323 -42
- package/src/index.ts +1 -0
- package/src/layout.ts +15 -0
- package/src/publickey.ts +4 -0
- package/src/sysvar.ts +16 -4
- package/src/transaction.ts +4 -1
- package/src/util/cluster.ts +2 -2
- package/src/util/send-and-confirm-transaction.ts +1 -0
- package/src/vote-account.ts +104 -31
- package/src/vote-program.ts +290 -0
package/src/sysvar.ts
CHANGED
|
@@ -4,6 +4,14 @@ export const SYSVAR_CLOCK_PUBKEY = new PublicKey(
|
|
|
4
4
|
'SysvarC1ock11111111111111111111111111111111',
|
|
5
5
|
);
|
|
6
6
|
|
|
7
|
+
export const SYSVAR_EPOCH_SCHEDULE_PUBKEY = new PublicKey(
|
|
8
|
+
'SysvarEpochSchedu1e111111111111111111111111',
|
|
9
|
+
);
|
|
10
|
+
|
|
11
|
+
export const SYSVAR_INSTRUCTIONS_PUBKEY = new PublicKey(
|
|
12
|
+
'Sysvar1nstructions1111111111111111111111111',
|
|
13
|
+
);
|
|
14
|
+
|
|
7
15
|
export const SYSVAR_RECENT_BLOCKHASHES_PUBKEY = new PublicKey(
|
|
8
16
|
'SysvarRecentB1ockHashes11111111111111111111',
|
|
9
17
|
);
|
|
@@ -16,10 +24,14 @@ export const SYSVAR_REWARDS_PUBKEY = new PublicKey(
|
|
|
16
24
|
'SysvarRewards111111111111111111111111111111',
|
|
17
25
|
);
|
|
18
26
|
|
|
19
|
-
export const
|
|
20
|
-
'
|
|
27
|
+
export const SYSVAR_SLOT_HASHES_PUBKEY = new PublicKey(
|
|
28
|
+
'SysvarS1otHashes111111111111111111111111111',
|
|
21
29
|
);
|
|
22
30
|
|
|
23
|
-
export const
|
|
24
|
-
'
|
|
31
|
+
export const SYSVAR_SLOT_HISTORY_PUBKEY = new PublicKey(
|
|
32
|
+
'SysvarS1otHistory11111111111111111111111111',
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
export const SYSVAR_STAKE_HISTORY_PUBKEY = new PublicKey(
|
|
36
|
+
'SysvarStakeHistory1111111111111111111111111',
|
|
25
37
|
);
|
package/src/transaction.ts
CHANGED
|
@@ -259,9 +259,12 @@ export class Transaction {
|
|
|
259
259
|
|
|
260
260
|
// Sort. Prioritizing first by signer, then by writable
|
|
261
261
|
accountMetas.sort(function (x, y) {
|
|
262
|
+
const pubkeySorting = x.pubkey
|
|
263
|
+
.toBase58()
|
|
264
|
+
.localeCompare(y.pubkey.toBase58());
|
|
262
265
|
const checkSigner = x.isSigner === y.isSigner ? 0 : x.isSigner ? -1 : 1;
|
|
263
266
|
const checkWritable =
|
|
264
|
-
x.isWritable === y.isWritable ?
|
|
267
|
+
x.isWritable === y.isWritable ? pubkeySorting : x.isWritable ? -1 : 1;
|
|
265
268
|
return checkSigner || checkWritable;
|
|
266
269
|
});
|
|
267
270
|
|
package/src/util/cluster.ts
CHANGED
|
@@ -2,12 +2,12 @@ const endpoint = {
|
|
|
2
2
|
http: {
|
|
3
3
|
devnet: 'http://api.devnet.solana.com',
|
|
4
4
|
testnet: 'http://api.testnet.solana.com',
|
|
5
|
-
'mainnet-beta': 'http://api.mainnet-beta.solana.com',
|
|
5
|
+
'mainnet-beta': 'http://api.mainnet-beta.solana.com/',
|
|
6
6
|
},
|
|
7
7
|
https: {
|
|
8
8
|
devnet: 'https://api.devnet.solana.com',
|
|
9
9
|
testnet: 'https://api.testnet.solana.com',
|
|
10
|
-
'mainnet-beta': 'https://api.mainnet-beta.solana.com',
|
|
10
|
+
'mainnet-beta': 'https://api.mainnet-beta.solana.com/',
|
|
11
11
|
},
|
|
12
12
|
};
|
|
13
13
|
|
|
@@ -24,6 +24,7 @@ export async function sendAndConfirmTransaction(
|
|
|
24
24
|
const sendOptions = options && {
|
|
25
25
|
skipPreflight: options.skipPreflight,
|
|
26
26
|
preflightCommitment: options.preflightCommitment || options.commitment,
|
|
27
|
+
maxRetries: options.maxRetries,
|
|
27
28
|
};
|
|
28
29
|
|
|
29
30
|
const signature = await connection.sendTransaction(
|
package/src/vote-account.ts
CHANGED
|
@@ -23,6 +23,22 @@ export type EpochCredits = {
|
|
|
23
23
|
prevCredits: number;
|
|
24
24
|
};
|
|
25
25
|
|
|
26
|
+
export type AuthorizedVoter = {
|
|
27
|
+
epoch: number;
|
|
28
|
+
authorizedVoter: PublicKey;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export type PriorVoter = {
|
|
32
|
+
authorizedPubkey: PublicKey;
|
|
33
|
+
epochOfLastAuthorizedSwitch: number;
|
|
34
|
+
targetEpoch: number;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export type BlockTimestamp = {
|
|
38
|
+
slot: number;
|
|
39
|
+
timetamp: number;
|
|
40
|
+
};
|
|
41
|
+
|
|
26
42
|
/**
|
|
27
43
|
* See https://github.com/solana-labs/solana/blob/8a12ed029cfa38d4a45400916c2463fb82bbec8c/programs/vote_api/src/vote_state.rs#L68-L88
|
|
28
44
|
*
|
|
@@ -30,8 +46,7 @@ export type EpochCredits = {
|
|
|
30
46
|
*/
|
|
31
47
|
const VoteAccountLayout = BufferLayout.struct([
|
|
32
48
|
Layout.publicKey('nodePubkey'),
|
|
33
|
-
Layout.publicKey('
|
|
34
|
-
Layout.publicKey('authorizedWithdrawerPubkey'),
|
|
49
|
+
Layout.publicKey('authorizedWithdrawer'),
|
|
35
50
|
BufferLayout.u8('commission'),
|
|
36
51
|
BufferLayout.nu64(), // votes.length
|
|
37
52
|
BufferLayout.seq(
|
|
@@ -44,9 +59,31 @@ const VoteAccountLayout = BufferLayout.struct([
|
|
|
44
59
|
),
|
|
45
60
|
BufferLayout.u8('rootSlotValid'),
|
|
46
61
|
BufferLayout.nu64('rootSlot'),
|
|
47
|
-
BufferLayout.nu64(
|
|
48
|
-
BufferLayout.
|
|
49
|
-
|
|
62
|
+
BufferLayout.nu64(), // authorizedVoters.length
|
|
63
|
+
BufferLayout.seq(
|
|
64
|
+
BufferLayout.struct([
|
|
65
|
+
BufferLayout.nu64('epoch'),
|
|
66
|
+
Layout.publicKey('authorizedVoter'),
|
|
67
|
+
]),
|
|
68
|
+
BufferLayout.offset(BufferLayout.u32(), -8),
|
|
69
|
+
'authorizedVoters',
|
|
70
|
+
),
|
|
71
|
+
BufferLayout.struct(
|
|
72
|
+
[
|
|
73
|
+
BufferLayout.seq(
|
|
74
|
+
BufferLayout.struct([
|
|
75
|
+
Layout.publicKey('authorizedPubkey'),
|
|
76
|
+
BufferLayout.nu64('epochOfLastAuthorizedSwitch'),
|
|
77
|
+
BufferLayout.nu64('targetEpoch'),
|
|
78
|
+
]),
|
|
79
|
+
32,
|
|
80
|
+
'buf',
|
|
81
|
+
),
|
|
82
|
+
BufferLayout.nu64('idx'),
|
|
83
|
+
BufferLayout.u8('isEmpty'),
|
|
84
|
+
],
|
|
85
|
+
'priorVoters',
|
|
86
|
+
),
|
|
50
87
|
BufferLayout.nu64(), // epochCredits.length
|
|
51
88
|
BufferLayout.seq(
|
|
52
89
|
BufferLayout.struct([
|
|
@@ -57,19 +94,22 @@ const VoteAccountLayout = BufferLayout.struct([
|
|
|
57
94
|
BufferLayout.offset(BufferLayout.u32(), -8),
|
|
58
95
|
'epochCredits',
|
|
59
96
|
),
|
|
97
|
+
BufferLayout.struct(
|
|
98
|
+
[BufferLayout.nu64('slot'), BufferLayout.nu64('timestamp')],
|
|
99
|
+
'lastTimestamp',
|
|
100
|
+
),
|
|
60
101
|
]);
|
|
61
102
|
|
|
62
103
|
type VoteAccountArgs = {
|
|
63
104
|
nodePubkey: PublicKey;
|
|
64
|
-
|
|
65
|
-
authorizedWithdrawerPubkey: PublicKey;
|
|
105
|
+
authorizedWithdrawer: PublicKey;
|
|
66
106
|
commission: number;
|
|
67
|
-
votes: Array<Lockout>;
|
|
68
107
|
rootSlot: number | null;
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
epochCredits:
|
|
108
|
+
votes: Lockout[];
|
|
109
|
+
authorizedVoters: AuthorizedVoter[];
|
|
110
|
+
priorVoters: PriorVoter[];
|
|
111
|
+
epochCredits: EpochCredits[];
|
|
112
|
+
lastTimestamp: BlockTimestamp;
|
|
73
113
|
};
|
|
74
114
|
|
|
75
115
|
/**
|
|
@@ -77,30 +117,28 @@ type VoteAccountArgs = {
|
|
|
77
117
|
*/
|
|
78
118
|
export class VoteAccount {
|
|
79
119
|
nodePubkey: PublicKey;
|
|
80
|
-
|
|
81
|
-
authorizedWithdrawerPubkey: PublicKey;
|
|
120
|
+
authorizedWithdrawer: PublicKey;
|
|
82
121
|
commission: number;
|
|
83
|
-
votes: Array<Lockout>;
|
|
84
122
|
rootSlot: number | null;
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
epochCredits:
|
|
123
|
+
votes: Lockout[];
|
|
124
|
+
authorizedVoters: AuthorizedVoter[];
|
|
125
|
+
priorVoters: PriorVoter[];
|
|
126
|
+
epochCredits: EpochCredits[];
|
|
127
|
+
lastTimestamp: BlockTimestamp;
|
|
89
128
|
|
|
90
129
|
/**
|
|
91
130
|
* @internal
|
|
92
131
|
*/
|
|
93
132
|
constructor(args: VoteAccountArgs) {
|
|
94
133
|
this.nodePubkey = args.nodePubkey;
|
|
95
|
-
this.
|
|
96
|
-
this.authorizedWithdrawerPubkey = args.authorizedWithdrawerPubkey;
|
|
134
|
+
this.authorizedWithdrawer = args.authorizedWithdrawer;
|
|
97
135
|
this.commission = args.commission;
|
|
98
|
-
this.votes = args.votes;
|
|
99
136
|
this.rootSlot = args.rootSlot;
|
|
100
|
-
this.
|
|
101
|
-
this.
|
|
102
|
-
this.
|
|
137
|
+
this.votes = args.votes;
|
|
138
|
+
this.authorizedVoters = args.authorizedVoters;
|
|
139
|
+
this.priorVoters = args.priorVoters;
|
|
103
140
|
this.epochCredits = args.epochCredits;
|
|
141
|
+
this.lastTimestamp = args.lastTimestamp;
|
|
104
142
|
}
|
|
105
143
|
|
|
106
144
|
/**
|
|
@@ -112,7 +150,8 @@ export class VoteAccount {
|
|
|
112
150
|
static fromAccountData(
|
|
113
151
|
buffer: Buffer | Uint8Array | Array<number>,
|
|
114
152
|
): VoteAccount {
|
|
115
|
-
const
|
|
153
|
+
const versionOffset = 4;
|
|
154
|
+
const va = VoteAccountLayout.decode(toBuffer(buffer), versionOffset);
|
|
116
155
|
|
|
117
156
|
let rootSlot: number | null = va.rootSlot;
|
|
118
157
|
if (!va.rootSlotValid) {
|
|
@@ -121,15 +160,49 @@ export class VoteAccount {
|
|
|
121
160
|
|
|
122
161
|
return new VoteAccount({
|
|
123
162
|
nodePubkey: new PublicKey(va.nodePubkey),
|
|
124
|
-
|
|
125
|
-
authorizedWithdrawerPubkey: new PublicKey(va.authorizedWithdrawerPubkey),
|
|
163
|
+
authorizedWithdrawer: new PublicKey(va.authorizedWithdrawer),
|
|
126
164
|
commission: va.commission,
|
|
127
165
|
votes: va.votes,
|
|
128
166
|
rootSlot,
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
lastEpochCredits: va.lastEpochCredits,
|
|
167
|
+
authorizedVoters: va.authorizedVoters.map(parseAuthorizedVoter),
|
|
168
|
+
priorVoters: getPriorVoters(va.priorVoters),
|
|
132
169
|
epochCredits: va.epochCredits,
|
|
170
|
+
lastTimestamp: va.lastTimestamp,
|
|
133
171
|
});
|
|
134
172
|
}
|
|
135
173
|
}
|
|
174
|
+
|
|
175
|
+
function parseAuthorizedVoter({epoch, authorizedVoter}: AuthorizedVoter) {
|
|
176
|
+
return {
|
|
177
|
+
epoch,
|
|
178
|
+
authorizedVoter: new PublicKey(authorizedVoter),
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function parsePriorVoters({
|
|
183
|
+
authorizedPubkey,
|
|
184
|
+
epochOfLastAuthorizedSwitch,
|
|
185
|
+
targetEpoch,
|
|
186
|
+
}: PriorVoter) {
|
|
187
|
+
return {
|
|
188
|
+
authorizedPubkey: new PublicKey(authorizedPubkey),
|
|
189
|
+
epochOfLastAuthorizedSwitch,
|
|
190
|
+
targetEpoch,
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function getPriorVoters({
|
|
195
|
+
buf,
|
|
196
|
+
idx,
|
|
197
|
+
isEmpty,
|
|
198
|
+
}: {
|
|
199
|
+
buf: PriorVoter[];
|
|
200
|
+
idx: number;
|
|
201
|
+
isEmpty: boolean;
|
|
202
|
+
}): PriorVoter[] {
|
|
203
|
+
if (isEmpty) {
|
|
204
|
+
return [];
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return [...buf.slice(idx + 1).map(parsePriorVoters), ...buf.slice(0, idx)];
|
|
208
|
+
}
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
import * as BufferLayout from '@solana/buffer-layout';
|
|
2
|
+
|
|
3
|
+
import {encodeData, decodeData, InstructionType} from './instruction';
|
|
4
|
+
import * as Layout from './layout';
|
|
5
|
+
import {PublicKey} from './publickey';
|
|
6
|
+
import {SystemProgram} from './system-program';
|
|
7
|
+
import {SYSVAR_CLOCK_PUBKEY, SYSVAR_RENT_PUBKEY} from './sysvar';
|
|
8
|
+
import {Transaction, TransactionInstruction} from './transaction';
|
|
9
|
+
import {toBuffer} from './util/to-buffer';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Vote account info
|
|
13
|
+
*/
|
|
14
|
+
export class VoteInit {
|
|
15
|
+
nodePubkey: PublicKey;
|
|
16
|
+
authorizedVoter: PublicKey;
|
|
17
|
+
authorizedWithdrawer: PublicKey;
|
|
18
|
+
commission: number; /** [0, 100] */
|
|
19
|
+
|
|
20
|
+
constructor(
|
|
21
|
+
nodePubkey: PublicKey,
|
|
22
|
+
authorizedVoter: PublicKey,
|
|
23
|
+
authorizedWithdrawer: PublicKey,
|
|
24
|
+
commission: number,
|
|
25
|
+
) {
|
|
26
|
+
this.nodePubkey = nodePubkey;
|
|
27
|
+
this.authorizedVoter = authorizedVoter;
|
|
28
|
+
this.authorizedWithdrawer = authorizedWithdrawer;
|
|
29
|
+
this.commission = commission;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Create vote account transaction params
|
|
35
|
+
*/
|
|
36
|
+
export type CreateVoteAccountParams = {
|
|
37
|
+
fromPubkey: PublicKey;
|
|
38
|
+
votePubkey: PublicKey;
|
|
39
|
+
voteInit: VoteInit;
|
|
40
|
+
lamports: number;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* InitializeAccount instruction params
|
|
45
|
+
*/
|
|
46
|
+
export type InitializeAccountParams = {
|
|
47
|
+
votePubkey: PublicKey;
|
|
48
|
+
nodePubkey: PublicKey;
|
|
49
|
+
voteInit: VoteInit;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Withdraw from vote account transaction params
|
|
54
|
+
*/
|
|
55
|
+
export type WithdrawFromVoteAccountParams = {
|
|
56
|
+
votePubkey: PublicKey;
|
|
57
|
+
authorizedWithdrawerPubkey: PublicKey;
|
|
58
|
+
lamports: number;
|
|
59
|
+
toPubkey: PublicKey;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Vote Instruction class
|
|
64
|
+
*/
|
|
65
|
+
export class VoteInstruction {
|
|
66
|
+
/**
|
|
67
|
+
* @internal
|
|
68
|
+
*/
|
|
69
|
+
constructor() {}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Decode a vote instruction and retrieve the instruction type.
|
|
73
|
+
*/
|
|
74
|
+
static decodeInstructionType(
|
|
75
|
+
instruction: TransactionInstruction,
|
|
76
|
+
): VoteInstructionType {
|
|
77
|
+
this.checkProgramId(instruction.programId);
|
|
78
|
+
|
|
79
|
+
const instructionTypeLayout = BufferLayout.u32('instruction');
|
|
80
|
+
const typeIndex = instructionTypeLayout.decode(instruction.data);
|
|
81
|
+
|
|
82
|
+
let type: VoteInstructionType | undefined;
|
|
83
|
+
for (const [ixType, layout] of Object.entries(VOTE_INSTRUCTION_LAYOUTS)) {
|
|
84
|
+
if (layout.index == typeIndex) {
|
|
85
|
+
type = ixType as VoteInstructionType;
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (!type) {
|
|
91
|
+
throw new Error('Instruction type incorrect; not a VoteInstruction');
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return type;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Decode an initialize vote instruction and retrieve the instruction params.
|
|
99
|
+
*/
|
|
100
|
+
static decodeInitializeAccount(
|
|
101
|
+
instruction: TransactionInstruction,
|
|
102
|
+
): InitializeAccountParams {
|
|
103
|
+
this.checkProgramId(instruction.programId);
|
|
104
|
+
this.checkKeyLength(instruction.keys, 4);
|
|
105
|
+
|
|
106
|
+
const {voteInit} = decodeData(
|
|
107
|
+
VOTE_INSTRUCTION_LAYOUTS.InitializeAccount,
|
|
108
|
+
instruction.data,
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
return {
|
|
112
|
+
votePubkey: instruction.keys[0].pubkey,
|
|
113
|
+
nodePubkey: instruction.keys[3].pubkey,
|
|
114
|
+
voteInit: new VoteInit(
|
|
115
|
+
new PublicKey(voteInit.nodePubkey),
|
|
116
|
+
new PublicKey(voteInit.authorizedVoter),
|
|
117
|
+
new PublicKey(voteInit.authorizedWithdrawer),
|
|
118
|
+
voteInit.commission,
|
|
119
|
+
),
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Decode a withdraw instruction and retrieve the instruction params.
|
|
125
|
+
*/
|
|
126
|
+
static decodeWithdraw(
|
|
127
|
+
instruction: TransactionInstruction,
|
|
128
|
+
): WithdrawFromVoteAccountParams {
|
|
129
|
+
this.checkProgramId(instruction.programId);
|
|
130
|
+
this.checkKeyLength(instruction.keys, 3);
|
|
131
|
+
|
|
132
|
+
const {lamports} = decodeData(
|
|
133
|
+
VOTE_INSTRUCTION_LAYOUTS.Withdraw,
|
|
134
|
+
instruction.data,
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
return {
|
|
138
|
+
votePubkey: instruction.keys[0].pubkey,
|
|
139
|
+
authorizedWithdrawerPubkey: instruction.keys[2].pubkey,
|
|
140
|
+
lamports,
|
|
141
|
+
toPubkey: instruction.keys[1].pubkey,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* @internal
|
|
147
|
+
*/
|
|
148
|
+
static checkProgramId(programId: PublicKey) {
|
|
149
|
+
if (!programId.equals(VoteProgram.programId)) {
|
|
150
|
+
throw new Error('invalid instruction; programId is not VoteProgram');
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* @internal
|
|
156
|
+
*/
|
|
157
|
+
static checkKeyLength(keys: Array<any>, expectedLength: number) {
|
|
158
|
+
if (keys.length < expectedLength) {
|
|
159
|
+
throw new Error(
|
|
160
|
+
`invalid instruction; found ${keys.length} keys, expected at least ${expectedLength}`,
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* An enumeration of valid VoteInstructionType's
|
|
168
|
+
*/
|
|
169
|
+
export type VoteInstructionType = 'InitializeAccount' | 'Withdraw';
|
|
170
|
+
|
|
171
|
+
const VOTE_INSTRUCTION_LAYOUTS: {
|
|
172
|
+
[type in VoteInstructionType]: InstructionType;
|
|
173
|
+
} = Object.freeze({
|
|
174
|
+
InitializeAccount: {
|
|
175
|
+
index: 0,
|
|
176
|
+
layout: BufferLayout.struct([
|
|
177
|
+
BufferLayout.u32('instruction'),
|
|
178
|
+
Layout.voteInit(),
|
|
179
|
+
]),
|
|
180
|
+
},
|
|
181
|
+
Withdraw: {
|
|
182
|
+
index: 3,
|
|
183
|
+
layout: BufferLayout.struct([
|
|
184
|
+
BufferLayout.u32('instruction'),
|
|
185
|
+
BufferLayout.ns64('lamports'),
|
|
186
|
+
]),
|
|
187
|
+
},
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Factory class for transactions to interact with the Vote program
|
|
192
|
+
*/
|
|
193
|
+
export class VoteProgram {
|
|
194
|
+
/**
|
|
195
|
+
* @internal
|
|
196
|
+
*/
|
|
197
|
+
constructor() {}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Public key that identifies the Vote program
|
|
201
|
+
*/
|
|
202
|
+
static programId: PublicKey = new PublicKey(
|
|
203
|
+
'Vote111111111111111111111111111111111111111',
|
|
204
|
+
);
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Max space of a Vote account
|
|
208
|
+
*
|
|
209
|
+
* This is generated from the solana-vote-program VoteState struct as
|
|
210
|
+
* `VoteState::size_of()`:
|
|
211
|
+
* https://docs.rs/solana-vote-program/1.9.5/solana_vote_program/vote_state/struct.VoteState.html#method.size_of
|
|
212
|
+
*/
|
|
213
|
+
static space: number = 3731;
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Generate an Initialize instruction.
|
|
217
|
+
*/
|
|
218
|
+
static initializeAccount(
|
|
219
|
+
params: InitializeAccountParams,
|
|
220
|
+
): TransactionInstruction {
|
|
221
|
+
const {votePubkey, nodePubkey, voteInit} = params;
|
|
222
|
+
const type = VOTE_INSTRUCTION_LAYOUTS.InitializeAccount;
|
|
223
|
+
const data = encodeData(type, {
|
|
224
|
+
voteInit: {
|
|
225
|
+
nodePubkey: toBuffer(voteInit.nodePubkey.toBuffer()),
|
|
226
|
+
authorizedVoter: toBuffer(voteInit.authorizedVoter.toBuffer()),
|
|
227
|
+
authorizedWithdrawer: toBuffer(
|
|
228
|
+
voteInit.authorizedWithdrawer.toBuffer(),
|
|
229
|
+
),
|
|
230
|
+
commission: voteInit.commission,
|
|
231
|
+
},
|
|
232
|
+
});
|
|
233
|
+
const instructionData = {
|
|
234
|
+
keys: [
|
|
235
|
+
{pubkey: votePubkey, isSigner: false, isWritable: true},
|
|
236
|
+
{pubkey: SYSVAR_RENT_PUBKEY, isSigner: false, isWritable: false},
|
|
237
|
+
{pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false},
|
|
238
|
+
{pubkey: nodePubkey, isSigner: true, isWritable: false},
|
|
239
|
+
],
|
|
240
|
+
programId: this.programId,
|
|
241
|
+
data,
|
|
242
|
+
};
|
|
243
|
+
return new TransactionInstruction(instructionData);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Generate a transaction that creates a new Vote account.
|
|
248
|
+
*/
|
|
249
|
+
static createAccount(params: CreateVoteAccountParams): Transaction {
|
|
250
|
+
const transaction = new Transaction();
|
|
251
|
+
transaction.add(
|
|
252
|
+
SystemProgram.createAccount({
|
|
253
|
+
fromPubkey: params.fromPubkey,
|
|
254
|
+
newAccountPubkey: params.votePubkey,
|
|
255
|
+
lamports: params.lamports,
|
|
256
|
+
space: this.space,
|
|
257
|
+
programId: this.programId,
|
|
258
|
+
}),
|
|
259
|
+
);
|
|
260
|
+
|
|
261
|
+
return transaction.add(
|
|
262
|
+
this.initializeAccount({
|
|
263
|
+
votePubkey: params.votePubkey,
|
|
264
|
+
nodePubkey: params.voteInit.nodePubkey,
|
|
265
|
+
voteInit: params.voteInit,
|
|
266
|
+
}),
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Generate a transaction to withdraw from a Vote account.
|
|
272
|
+
*/
|
|
273
|
+
static withdraw(params: WithdrawFromVoteAccountParams): Transaction {
|
|
274
|
+
const {votePubkey, authorizedWithdrawerPubkey, lamports, toPubkey} = params;
|
|
275
|
+
const type = VOTE_INSTRUCTION_LAYOUTS.Withdraw;
|
|
276
|
+
const data = encodeData(type, {lamports});
|
|
277
|
+
|
|
278
|
+
const keys = [
|
|
279
|
+
{pubkey: votePubkey, isSigner: false, isWritable: true},
|
|
280
|
+
{pubkey: toPubkey, isSigner: false, isWritable: true},
|
|
281
|
+
{pubkey: authorizedWithdrawerPubkey, isSigner: true, isWritable: false},
|
|
282
|
+
];
|
|
283
|
+
|
|
284
|
+
return new Transaction().add({
|
|
285
|
+
keys,
|
|
286
|
+
programId: this.programId,
|
|
287
|
+
data,
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
}
|