@solana/web3.js 1.51.0 → 1.54.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.
Files changed (60) hide show
  1. package/lib/index.browser.cjs.js +3600 -3205
  2. package/lib/index.browser.cjs.js.map +1 -1
  3. package/lib/index.browser.esm.js +3595 -3206
  4. package/lib/index.browser.esm.js.map +1 -1
  5. package/lib/index.cjs.js +3602 -3205
  6. package/lib/index.cjs.js.map +1 -1
  7. package/lib/index.d.ts +953 -831
  8. package/lib/index.esm.js +3597 -3206
  9. package/lib/index.esm.js.map +1 -1
  10. package/lib/index.iife.js +2630 -2235
  11. package/lib/index.iife.js.map +1 -1
  12. package/lib/index.iife.min.js +3 -3
  13. package/lib/index.iife.min.js.map +1 -1
  14. package/lib/index.native.js +3600 -3204
  15. package/lib/index.native.js.map +1 -1
  16. package/package.json +1 -2
  17. package/src/account-data.ts +39 -0
  18. package/src/account.ts +1 -1
  19. package/src/connection.ts +49 -16
  20. package/src/fee-calculator.ts +2 -0
  21. package/src/index.ts +3 -14
  22. package/src/layout.ts +7 -0
  23. package/src/loader.ts +4 -5
  24. package/src/message/index.ts +45 -0
  25. package/src/{message.ts → message/legacy.ts} +46 -27
  26. package/src/message/v0.ts +324 -0
  27. package/src/message/versioned.ts +27 -0
  28. package/src/nonce-account.ts +1 -1
  29. package/src/{address-lookup-table-program.ts → programs/address-lookup-table/index.ts} +8 -6
  30. package/src/programs/address-lookup-table/state.ts +84 -0
  31. package/src/{compute-budget.ts → programs/compute-budget.ts} +4 -4
  32. package/src/{ed25519-program.ts → programs/ed25519.ts} +4 -4
  33. package/src/programs/index.ts +7 -0
  34. package/src/{secp256k1-program.ts → programs/secp256k1.ts} +4 -4
  35. package/src/{stake-program.ts → programs/stake.ts} +7 -7
  36. package/src/{system-program.ts → programs/system.ts} +8 -8
  37. package/src/{vote-program.ts → programs/vote.ts} +28 -7
  38. package/src/publickey.ts +9 -4
  39. package/src/{transaction-constants.ts → transaction/constants.ts} +2 -0
  40. package/src/{util/tx-expiry-custom-errors.ts → transaction/expiry-custom-errors.ts} +0 -0
  41. package/src/transaction/index.ts +4 -0
  42. package/src/{transaction.ts → transaction/legacy.ts} +10 -13
  43. package/src/transaction/versioned.ts +108 -0
  44. package/src/{util → utils}/assert.ts +0 -0
  45. package/src/{util → utils}/bigint.ts +0 -0
  46. package/src/{util → utils}/borsh-schema.ts +0 -0
  47. package/src/{util → utils}/cluster.ts +0 -0
  48. package/src/utils/index.ts +4 -0
  49. package/src/utils/makeWebsocketUrl.ts +26 -0
  50. package/src/{util → utils}/promise-timeout.ts +0 -0
  51. package/src/{util → utils}/send-and-confirm-raw-transaction.ts +0 -0
  52. package/src/{util → utils}/send-and-confirm-transaction.ts +0 -0
  53. package/src/{util → utils}/shortvec-encoding.ts +0 -0
  54. package/src/{util → utils}/sleep.ts +0 -0
  55. package/src/{util → utils}/to-buffer.ts +0 -0
  56. package/src/validator-info.ts +4 -6
  57. package/src/vote-account.ts +1 -1
  58. package/src/util/__forks__/react-native/url-impl.ts +0 -2
  59. package/src/util/makeWebsocketUrl.ts +0 -20
  60. package/src/util/url-impl.ts +0 -2
@@ -0,0 +1,324 @@
1
+ import bs58 from 'bs58';
2
+ import * as BufferLayout from '@solana/buffer-layout';
3
+
4
+ import * as Layout from '../layout';
5
+ import {Blockhash} from '../blockhash';
6
+ import {
7
+ MessageHeader,
8
+ MessageAddressTableLookup,
9
+ MessageCompiledInstruction,
10
+ } from './index';
11
+ import {PublicKey, PUBLIC_KEY_LENGTH} from '../publickey';
12
+ import * as shortvec from '../utils/shortvec-encoding';
13
+ import assert from '../utils/assert';
14
+ import {PACKET_DATA_SIZE, VERSION_PREFIX_MASK} from '../transaction/constants';
15
+
16
+ /**
17
+ * Message constructor arguments
18
+ */
19
+ export type MessageV0Args = {
20
+ /** The message header, identifying signed and read-only `accountKeys` */
21
+ header: MessageHeader;
22
+ /** The static account keys used by this transaction */
23
+ staticAccountKeys: PublicKey[];
24
+ /** The hash of a recent ledger block */
25
+ recentBlockhash: Blockhash;
26
+ /** Instructions that will be executed in sequence and committed in one atomic transaction if all succeed. */
27
+ compiledInstructions: MessageCompiledInstruction[];
28
+ /** Instructions that will be executed in sequence and committed in one atomic transaction if all succeed. */
29
+ addressTableLookups: MessageAddressTableLookup[];
30
+ };
31
+
32
+ export class MessageV0 {
33
+ header: MessageHeader;
34
+ staticAccountKeys: Array<PublicKey>;
35
+ recentBlockhash: Blockhash;
36
+ compiledInstructions: Array<MessageCompiledInstruction>;
37
+ addressTableLookups: Array<MessageAddressTableLookup>;
38
+
39
+ constructor(args: MessageV0Args) {
40
+ this.header = args.header;
41
+ this.staticAccountKeys = args.staticAccountKeys;
42
+ this.recentBlockhash = args.recentBlockhash;
43
+ this.compiledInstructions = args.compiledInstructions;
44
+ this.addressTableLookups = args.addressTableLookups;
45
+ }
46
+
47
+ get version(): 0 {
48
+ return 0;
49
+ }
50
+
51
+ serialize(): Uint8Array {
52
+ const encodedStaticAccountKeysLength = Array<number>();
53
+ shortvec.encodeLength(
54
+ encodedStaticAccountKeysLength,
55
+ this.staticAccountKeys.length,
56
+ );
57
+
58
+ const serializedInstructions = this.serializeInstructions();
59
+ const encodedInstructionsLength = Array<number>();
60
+ shortvec.encodeLength(
61
+ encodedInstructionsLength,
62
+ this.compiledInstructions.length,
63
+ );
64
+
65
+ const serializedAddressTableLookups = this.serializeAddressTableLookups();
66
+ const encodedAddressTableLookupsLength = Array<number>();
67
+ shortvec.encodeLength(
68
+ encodedAddressTableLookupsLength,
69
+ this.addressTableLookups.length,
70
+ );
71
+
72
+ const messageLayout = BufferLayout.struct<{
73
+ prefix: number;
74
+ header: MessageHeader;
75
+ staticAccountKeysLength: Uint8Array;
76
+ staticAccountKeys: Array<Uint8Array>;
77
+ recentBlockhash: Uint8Array;
78
+ instructionsLength: Uint8Array;
79
+ serializedInstructions: Uint8Array;
80
+ addressTableLookupsLength: Uint8Array;
81
+ serializedAddressTableLookups: Uint8Array;
82
+ }>([
83
+ BufferLayout.u8('prefix'),
84
+ BufferLayout.struct<MessageHeader>(
85
+ [
86
+ BufferLayout.u8('numRequiredSignatures'),
87
+ BufferLayout.u8('numReadonlySignedAccounts'),
88
+ BufferLayout.u8('numReadonlyUnsignedAccounts'),
89
+ ],
90
+ 'header',
91
+ ),
92
+ BufferLayout.blob(
93
+ encodedStaticAccountKeysLength.length,
94
+ 'staticAccountKeysLength',
95
+ ),
96
+ BufferLayout.seq(
97
+ Layout.publicKey(),
98
+ this.staticAccountKeys.length,
99
+ 'staticAccountKeys',
100
+ ),
101
+ Layout.publicKey('recentBlockhash'),
102
+ BufferLayout.blob(encodedInstructionsLength.length, 'instructionsLength'),
103
+ BufferLayout.blob(
104
+ serializedInstructions.length,
105
+ 'serializedInstructions',
106
+ ),
107
+ BufferLayout.blob(
108
+ encodedAddressTableLookupsLength.length,
109
+ 'addressTableLookupsLength',
110
+ ),
111
+ BufferLayout.blob(
112
+ serializedAddressTableLookups.length,
113
+ 'serializedAddressTableLookups',
114
+ ),
115
+ ]);
116
+
117
+ const serializedMessage = new Uint8Array(PACKET_DATA_SIZE);
118
+ const MESSAGE_VERSION_0_PREFIX = 1 << 7;
119
+ const serializedMessageLength = messageLayout.encode(
120
+ {
121
+ prefix: MESSAGE_VERSION_0_PREFIX,
122
+ header: this.header,
123
+ staticAccountKeysLength: new Uint8Array(encodedStaticAccountKeysLength),
124
+ staticAccountKeys: this.staticAccountKeys.map(key => key.toBytes()),
125
+ recentBlockhash: bs58.decode(this.recentBlockhash),
126
+ instructionsLength: new Uint8Array(encodedInstructionsLength),
127
+ serializedInstructions,
128
+ addressTableLookupsLength: new Uint8Array(
129
+ encodedAddressTableLookupsLength,
130
+ ),
131
+ serializedAddressTableLookups,
132
+ },
133
+ serializedMessage,
134
+ );
135
+ return serializedMessage.slice(0, serializedMessageLength);
136
+ }
137
+
138
+ private serializeInstructions(): Uint8Array {
139
+ let serializedLength = 0;
140
+ const serializedInstructions = new Uint8Array(PACKET_DATA_SIZE);
141
+ for (const instruction of this.compiledInstructions) {
142
+ const encodedAccountKeyIndexesLength = Array<number>();
143
+ shortvec.encodeLength(
144
+ encodedAccountKeyIndexesLength,
145
+ instruction.accountKeyIndexes.length,
146
+ );
147
+
148
+ const encodedDataLength = Array<number>();
149
+ shortvec.encodeLength(encodedDataLength, instruction.data.length);
150
+
151
+ const instructionLayout = BufferLayout.struct<{
152
+ programIdIndex: number;
153
+ encodedAccountKeyIndexesLength: Uint8Array;
154
+ accountKeyIndexes: number[];
155
+ encodedDataLength: Uint8Array;
156
+ data: Uint8Array;
157
+ }>([
158
+ BufferLayout.u8('programIdIndex'),
159
+ BufferLayout.blob(
160
+ encodedAccountKeyIndexesLength.length,
161
+ 'encodedAccountKeyIndexesLength',
162
+ ),
163
+ BufferLayout.seq(
164
+ BufferLayout.u8(),
165
+ instruction.accountKeyIndexes.length,
166
+ 'accountKeyIndexes',
167
+ ),
168
+ BufferLayout.blob(encodedDataLength.length, 'encodedDataLength'),
169
+ BufferLayout.blob(instruction.data.length, 'data'),
170
+ ]);
171
+
172
+ serializedLength += instructionLayout.encode(
173
+ {
174
+ programIdIndex: instruction.programIdIndex,
175
+ encodedAccountKeyIndexesLength: new Uint8Array(
176
+ encodedAccountKeyIndexesLength,
177
+ ),
178
+ accountKeyIndexes: instruction.accountKeyIndexes,
179
+ encodedDataLength: new Uint8Array(encodedDataLength),
180
+ data: instruction.data,
181
+ },
182
+ serializedInstructions,
183
+ serializedLength,
184
+ );
185
+ }
186
+
187
+ return serializedInstructions.slice(0, serializedLength);
188
+ }
189
+
190
+ private serializeAddressTableLookups(): Uint8Array {
191
+ let serializedLength = 0;
192
+ const serializedAddressTableLookups = new Uint8Array(PACKET_DATA_SIZE);
193
+ for (const lookup of this.addressTableLookups) {
194
+ const encodedWritableIndexesLength = Array<number>();
195
+ shortvec.encodeLength(
196
+ encodedWritableIndexesLength,
197
+ lookup.writableIndexes.length,
198
+ );
199
+
200
+ const encodedReadonlyIndexesLength = Array<number>();
201
+ shortvec.encodeLength(
202
+ encodedReadonlyIndexesLength,
203
+ lookup.readonlyIndexes.length,
204
+ );
205
+
206
+ const addressTableLookupLayout = BufferLayout.struct<{
207
+ accountKey: Uint8Array;
208
+ encodedWritableIndexesLength: Uint8Array;
209
+ writableIndexes: number[];
210
+ encodedReadonlyIndexesLength: Uint8Array;
211
+ readonlyIndexes: number[];
212
+ }>([
213
+ Layout.publicKey('accountKey'),
214
+ BufferLayout.blob(
215
+ encodedWritableIndexesLength.length,
216
+ 'encodedWritableIndexesLength',
217
+ ),
218
+ BufferLayout.seq(
219
+ BufferLayout.u8(),
220
+ lookup.writableIndexes.length,
221
+ 'writableIndexes',
222
+ ),
223
+ BufferLayout.blob(
224
+ encodedReadonlyIndexesLength.length,
225
+ 'encodedReadonlyIndexesLength',
226
+ ),
227
+ BufferLayout.seq(
228
+ BufferLayout.u8(),
229
+ lookup.readonlyIndexes.length,
230
+ 'readonlyIndexes',
231
+ ),
232
+ ]);
233
+
234
+ serializedLength += addressTableLookupLayout.encode(
235
+ {
236
+ accountKey: lookup.accountKey.toBytes(),
237
+ encodedWritableIndexesLength: new Uint8Array(
238
+ encodedWritableIndexesLength,
239
+ ),
240
+ writableIndexes: lookup.writableIndexes,
241
+ encodedReadonlyIndexesLength: new Uint8Array(
242
+ encodedReadonlyIndexesLength,
243
+ ),
244
+ readonlyIndexes: lookup.readonlyIndexes,
245
+ },
246
+ serializedAddressTableLookups,
247
+ serializedLength,
248
+ );
249
+ }
250
+
251
+ return serializedAddressTableLookups.slice(0, serializedLength);
252
+ }
253
+
254
+ static deserialize(serializedMessage: Uint8Array): MessageV0 {
255
+ let byteArray = [...serializedMessage];
256
+
257
+ const prefix = byteArray.shift() as number;
258
+ const maskedPrefix = prefix & VERSION_PREFIX_MASK;
259
+ assert(
260
+ prefix !== maskedPrefix,
261
+ `Expected versioned message but received legacy message`,
262
+ );
263
+
264
+ const version = maskedPrefix;
265
+ assert(
266
+ version === 0,
267
+ `Expected versioned message with version 0 but found version ${version}`,
268
+ );
269
+
270
+ const header: MessageHeader = {
271
+ numRequiredSignatures: byteArray.shift() as number,
272
+ numReadonlySignedAccounts: byteArray.shift() as number,
273
+ numReadonlyUnsignedAccounts: byteArray.shift() as number,
274
+ };
275
+
276
+ const staticAccountKeys = [];
277
+ const staticAccountKeysLength = shortvec.decodeLength(byteArray);
278
+ for (let i = 0; i < staticAccountKeysLength; i++) {
279
+ staticAccountKeys.push(
280
+ new PublicKey(byteArray.splice(0, PUBLIC_KEY_LENGTH)),
281
+ );
282
+ }
283
+
284
+ const recentBlockhash = bs58.encode(byteArray.splice(0, PUBLIC_KEY_LENGTH));
285
+
286
+ const instructionCount = shortvec.decodeLength(byteArray);
287
+ const compiledInstructions: MessageCompiledInstruction[] = [];
288
+ for (let i = 0; i < instructionCount; i++) {
289
+ const programIdIndex = byteArray.shift() as number;
290
+ const accountKeyIndexesLength = shortvec.decodeLength(byteArray);
291
+ const accountKeyIndexes = byteArray.splice(0, accountKeyIndexesLength);
292
+ const dataLength = shortvec.decodeLength(byteArray);
293
+ const data = new Uint8Array(byteArray.splice(0, dataLength));
294
+ compiledInstructions.push({
295
+ programIdIndex,
296
+ accountKeyIndexes,
297
+ data,
298
+ });
299
+ }
300
+
301
+ const addressTableLookupsCount = shortvec.decodeLength(byteArray);
302
+ const addressTableLookups: MessageAddressTableLookup[] = [];
303
+ for (let i = 0; i < addressTableLookupsCount; i++) {
304
+ const accountKey = new PublicKey(byteArray.splice(0, PUBLIC_KEY_LENGTH));
305
+ const writableIndexesLength = shortvec.decodeLength(byteArray);
306
+ const writableIndexes = byteArray.splice(0, writableIndexesLength);
307
+ const readonlyIndexesLength = shortvec.decodeLength(byteArray);
308
+ const readonlyIndexes = byteArray.splice(0, readonlyIndexesLength);
309
+ addressTableLookups.push({
310
+ accountKey,
311
+ writableIndexes,
312
+ readonlyIndexes,
313
+ });
314
+ }
315
+
316
+ return new MessageV0({
317
+ header,
318
+ staticAccountKeys,
319
+ recentBlockhash,
320
+ compiledInstructions,
321
+ addressTableLookups,
322
+ });
323
+ }
324
+ }
@@ -0,0 +1,27 @@
1
+ import {VERSION_PREFIX_MASK} from '../transaction/constants';
2
+ import {Message} from './legacy';
3
+ import {MessageV0} from './v0';
4
+
5
+ export type VersionedMessage = Message | MessageV0;
6
+ // eslint-disable-next-line no-redeclare
7
+ export const VersionedMessage = {
8
+ deserialize: (serializedMessage: Uint8Array): VersionedMessage => {
9
+ const prefix = serializedMessage[0];
10
+ const maskedPrefix = prefix & VERSION_PREFIX_MASK;
11
+
12
+ // if the highest bit of the prefix is not set, the message is not versioned
13
+ if (maskedPrefix === prefix) {
14
+ return Message.from(serializedMessage);
15
+ }
16
+
17
+ // the lower 7 bits of the prefix indicate the message version
18
+ const version = maskedPrefix;
19
+ if (version === 0) {
20
+ return MessageV0.deserialize(serializedMessage);
21
+ } else {
22
+ throw new Error(
23
+ `Transaction message version ${version} deserialization is not supported`,
24
+ );
25
+ }
26
+ },
27
+ };
@@ -6,7 +6,7 @@ import * as Layout from './layout';
6
6
  import {PublicKey} from './publickey';
7
7
  import type {FeeCalculator} from './fee-calculator';
8
8
  import {FeeCalculatorLayout} from './fee-calculator';
9
- import {toBuffer} from './util/to-buffer';
9
+ import {toBuffer} from './utils/to-buffer';
10
10
 
11
11
  /**
12
12
  * See https://github.com/solana-labs/solana/blob/0ea2843ec9cdc517572b8e62c959f41b55cf4453/sdk/src/nonce_state.rs#L29-L32
@@ -1,12 +1,14 @@
1
1
  import {toBufferLE} from 'bigint-buffer';
2
2
  import * as BufferLayout from '@solana/buffer-layout';
3
3
 
4
- import * as Layout from './layout';
5
- import {PublicKey} from './publickey';
6
- import * as bigintLayout from './util/bigint';
7
- import {SystemProgram} from './system-program';
8
- import {TransactionInstruction} from './transaction';
9
- import {decodeData, encodeData, IInstructionInputData} from './instruction';
4
+ import * as Layout from '../../layout';
5
+ import {PublicKey} from '../../publickey';
6
+ import * as bigintLayout from '../../utils/bigint';
7
+ import {SystemProgram} from '../system';
8
+ import {TransactionInstruction} from '../../transaction';
9
+ import {decodeData, encodeData, IInstructionInputData} from '../../instruction';
10
+
11
+ export * from './state';
10
12
 
11
13
  export type CreateLookupTableParams = {
12
14
  /** Account used to derive and control the new address lookup table. */
@@ -0,0 +1,84 @@
1
+ import * as BufferLayout from '@solana/buffer-layout';
2
+
3
+ import assert from '../../utils/assert';
4
+ import * as Layout from '../../layout';
5
+ import {PublicKey} from '../../publickey';
6
+ import {u64} from '../../utils/bigint';
7
+ import {decodeData} from '../../account-data';
8
+
9
+ export type AddressLookupTableState = {
10
+ deactivationSlot: bigint;
11
+ lastExtendedSlot: number;
12
+ lastExtendedSlotStartIndex: number;
13
+ authority?: PublicKey;
14
+ addresses: Array<PublicKey>;
15
+ };
16
+
17
+ export type AddressLookupTableAccountArgs = {
18
+ key: PublicKey;
19
+ state: AddressLookupTableState;
20
+ };
21
+
22
+ /// The serialized size of lookup table metadata
23
+ const LOOKUP_TABLE_META_SIZE = 56;
24
+
25
+ export class AddressLookupTableAccount {
26
+ key: PublicKey;
27
+ state: AddressLookupTableState;
28
+
29
+ constructor(args: AddressLookupTableAccountArgs) {
30
+ this.key = args.key;
31
+ this.state = args.state;
32
+ }
33
+
34
+ isActive(): boolean {
35
+ const U64_MAX = 2n ** 64n - 1n;
36
+ return this.state.deactivationSlot === U64_MAX;
37
+ }
38
+
39
+ static deserialize(accountData: Uint8Array): AddressLookupTableState {
40
+ const meta = decodeData(LookupTableMetaLayout, accountData);
41
+
42
+ const serializedAddressesLen = accountData.length - LOOKUP_TABLE_META_SIZE;
43
+ assert(serializedAddressesLen >= 0, 'lookup table is invalid');
44
+ assert(serializedAddressesLen % 32 === 0, 'lookup table is invalid');
45
+
46
+ const numSerializedAddresses = serializedAddressesLen / 32;
47
+ const {addresses} = BufferLayout.struct<{addresses: Array<Uint8Array>}>([
48
+ BufferLayout.seq(Layout.publicKey(), numSerializedAddresses, 'addresses'),
49
+ ]).decode(accountData.slice(LOOKUP_TABLE_META_SIZE));
50
+
51
+ return {
52
+ deactivationSlot: meta.deactivationSlot,
53
+ lastExtendedSlot: meta.lastExtendedSlot,
54
+ lastExtendedSlotStartIndex: meta.lastExtendedStartIndex,
55
+ authority:
56
+ meta.authority.length !== 0
57
+ ? new PublicKey(meta.authority[0])
58
+ : undefined,
59
+ addresses: addresses.map(address => new PublicKey(address)),
60
+ };
61
+ }
62
+ }
63
+
64
+ const LookupTableMetaLayout = {
65
+ index: 1,
66
+ layout: BufferLayout.struct<{
67
+ typeIndex: number;
68
+ deactivationSlot: bigint;
69
+ lastExtendedSlot: number;
70
+ lastExtendedStartIndex: number;
71
+ authority: Array<Uint8Array>;
72
+ }>([
73
+ BufferLayout.u32('typeIndex'),
74
+ u64('deactivationSlot'),
75
+ BufferLayout.nu64('lastExtendedSlot'),
76
+ BufferLayout.u8('lastExtendedStartIndex'),
77
+ BufferLayout.u8(), // option
78
+ BufferLayout.seq(
79
+ Layout.publicKey(),
80
+ BufferLayout.offset(BufferLayout.u8(), -1),
81
+ 'authority',
82
+ ),
83
+ ]),
84
+ };
@@ -5,10 +5,10 @@ import {
5
5
  decodeData,
6
6
  InstructionType,
7
7
  IInstructionInputData,
8
- } from './instruction';
9
- import {PublicKey} from './publickey';
10
- import {TransactionInstruction} from './transaction';
11
- import {u64} from './util/bigint';
8
+ } from '../instruction';
9
+ import {PublicKey} from '../publickey';
10
+ import {TransactionInstruction} from '../transaction';
11
+ import {u64} from '../utils/bigint';
12
12
 
13
13
  /**
14
14
  * Compute Budget Instruction class
@@ -2,10 +2,10 @@ import {Buffer} from 'buffer';
2
2
  import * as BufferLayout from '@solana/buffer-layout';
3
3
  import nacl from 'tweetnacl';
4
4
 
5
- import {Keypair} from './keypair';
6
- import {PublicKey} from './publickey';
7
- import {TransactionInstruction} from './transaction';
8
- import assert from './util/assert';
5
+ import {Keypair} from '../keypair';
6
+ import {PublicKey} from '../publickey';
7
+ import {TransactionInstruction} from '../transaction';
8
+ import assert from '../utils/assert';
9
9
 
10
10
  const PRIVATE_KEY_BYTES = 64;
11
11
  const PUBLIC_KEY_BYTES = 32;
@@ -0,0 +1,7 @@
1
+ export * from './address-lookup-table';
2
+ export * from './compute-budget';
3
+ export * from './ed25519';
4
+ export * from './secp256k1';
5
+ export * from './stake';
6
+ export * from './system';
7
+ export * from './vote';
@@ -3,10 +3,10 @@ import * as BufferLayout from '@solana/buffer-layout';
3
3
  import secp256k1 from 'secp256k1';
4
4
  import sha3 from 'js-sha3';
5
5
 
6
- import {PublicKey} from './publickey';
7
- import {TransactionInstruction} from './transaction';
8
- import assert from './util/assert';
9
- import {toBuffer} from './util/to-buffer';
6
+ import {PublicKey} from '../publickey';
7
+ import {TransactionInstruction} from '../transaction';
8
+ import assert from '../utils/assert';
9
+ import {toBuffer} from '../utils/to-buffer';
10
10
 
11
11
  const {publicKeyCreate, ecdsaSign} = secp256k1;
12
12
 
@@ -5,17 +5,17 @@ import {
5
5
  decodeData,
6
6
  InstructionType,
7
7
  IInstructionInputData,
8
- } from './instruction';
9
- import * as Layout from './layout';
10
- import {PublicKey} from './publickey';
11
- import {SystemProgram} from './system-program';
8
+ } from '../instruction';
9
+ import * as Layout from '../layout';
10
+ import {PublicKey} from '../publickey';
11
+ import {SystemProgram} from './system';
12
12
  import {
13
13
  SYSVAR_CLOCK_PUBKEY,
14
14
  SYSVAR_RENT_PUBKEY,
15
15
  SYSVAR_STAKE_HISTORY_PUBKEY,
16
- } from './sysvar';
17
- import {Transaction, TransactionInstruction} from './transaction';
18
- import {toBuffer} from './util/to-buffer';
16
+ } from '../sysvar';
17
+ import {Transaction, TransactionInstruction} from '../transaction';
18
+ import {toBuffer} from '../utils/to-buffer';
19
19
 
20
20
  /**
21
21
  * Address of the stake config account which configures the rate
@@ -5,14 +5,14 @@ import {
5
5
  decodeData,
6
6
  InstructionType,
7
7
  IInstructionInputData,
8
- } from './instruction';
9
- import * as Layout from './layout';
10
- import {NONCE_ACCOUNT_LENGTH} from './nonce-account';
11
- import {PublicKey} from './publickey';
12
- import {SYSVAR_RECENT_BLOCKHASHES_PUBKEY, SYSVAR_RENT_PUBKEY} from './sysvar';
13
- import {Transaction, TransactionInstruction} from './transaction';
14
- import {toBuffer} from './util/to-buffer';
15
- import {u64} from './util/bigint';
8
+ } from '../instruction';
9
+ import * as Layout from '../layout';
10
+ import {NONCE_ACCOUNT_LENGTH} from '../nonce-account';
11
+ import {PublicKey} from '../publickey';
12
+ import {SYSVAR_RECENT_BLOCKHASHES_PUBKEY, SYSVAR_RENT_PUBKEY} from '../sysvar';
13
+ import {Transaction, TransactionInstruction} from '../transaction';
14
+ import {toBuffer} from '../utils/to-buffer';
15
+ import {u64} from '../utils/bigint';
16
16
 
17
17
  /**
18
18
  * Create account system transaction params
@@ -5,13 +5,13 @@ import {
5
5
  decodeData,
6
6
  InstructionType,
7
7
  IInstructionInputData,
8
- } from './instruction';
9
- import * as Layout from './layout';
10
- import {PublicKey} from './publickey';
11
- import {SystemProgram} from './system-program';
12
- import {SYSVAR_CLOCK_PUBKEY, SYSVAR_RENT_PUBKEY} from './sysvar';
13
- import {Transaction, TransactionInstruction} from './transaction';
14
- import {toBuffer} from './util/to-buffer';
8
+ } from '../instruction';
9
+ import * as Layout from '../layout';
10
+ import {PublicKey} from '../publickey';
11
+ import {SystemProgram} from './system';
12
+ import {SYSVAR_CLOCK_PUBKEY, SYSVAR_RENT_PUBKEY} from '../sysvar';
13
+ import {Transaction, TransactionInstruction} from '../transaction';
14
+ import {toBuffer} from '../utils/to-buffer';
15
15
 
16
16
  /**
17
17
  * Vote account info
@@ -410,4 +410,25 @@ export class VoteProgram {
410
410
  data,
411
411
  });
412
412
  }
413
+
414
+ /**
415
+ * Generate a transaction to withdraw safely from a Vote account.
416
+ *
417
+ * This function was created as a safeguard for vote accounts running validators, `safeWithdraw`
418
+ * checks that the withdraw amount will not exceed the specified balance while leaving enough left
419
+ * to cover rent. If you wish to close the vote account by withdrawing the full amount, call the
420
+ * `withdraw` method directly.
421
+ */
422
+ static safeWithdraw(
423
+ params: WithdrawFromVoteAccountParams,
424
+ currentVoteAccountBalance: number,
425
+ rentExemptMinimum: number,
426
+ ): Transaction {
427
+ if (params.lamports > currentVoteAccountBalance - rentExemptMinimum) {
428
+ throw new Error(
429
+ 'Withdraw will leave vote account with insuffcient funds.',
430
+ );
431
+ }
432
+ return VoteProgram.withdraw(params);
433
+ }
413
434
  }
package/src/publickey.ts CHANGED
@@ -4,14 +4,19 @@ import {Buffer} from 'buffer';
4
4
  import nacl from 'tweetnacl';
5
5
  import {sha256} from '@ethersproject/sha2';
6
6
 
7
- import {Struct, SOLANA_SCHEMA} from './util/borsh-schema';
8
- import {toBuffer} from './util/to-buffer';
7
+ import {Struct, SOLANA_SCHEMA} from './utils/borsh-schema';
8
+ import {toBuffer} from './utils/to-buffer';
9
9
 
10
10
  /**
11
11
  * Maximum length of derived pubkey seed
12
12
  */
13
13
  export const MAX_SEED_LENGTH = 32;
14
14
 
15
+ /**
16
+ * Size of public key in bytes
17
+ */
18
+ export const PUBLIC_KEY_LENGTH = 32;
19
+
15
20
  /**
16
21
  * Value to be converted into public key
17
22
  */
@@ -54,7 +59,7 @@ export class PublicKey extends Struct {
54
59
  if (typeof value === 'string') {
55
60
  // assume base 58 encoding by default
56
61
  const decoded = bs58.decode(value);
57
- if (decoded.length != 32) {
62
+ if (decoded.length != PUBLIC_KEY_LENGTH) {
58
63
  throw new Error(`Invalid public key input`);
59
64
  }
60
65
  this._bn = new BN(decoded);
@@ -103,7 +108,7 @@ export class PublicKey extends Struct {
103
108
  */
104
109
  toBuffer(): Buffer {
105
110
  const b = this._bn.toArrayLike(Buffer);
106
- if (b.length === 32) {
111
+ if (b.length === PUBLIC_KEY_LENGTH) {
107
112
  return b;
108
113
  }
109
114
 
@@ -7,4 +7,6 @@
7
7
  */
8
8
  export const PACKET_DATA_SIZE = 1280 - 40 - 8;
9
9
 
10
+ export const VERSION_PREFIX_MASK = 0x7f;
11
+
10
12
  export const SIGNATURE_LENGTH_IN_BYTES = 64;
@@ -0,0 +1,4 @@
1
+ export * from './constants';
2
+ export * from './expiry-custom-errors';
3
+ export * from './legacy';
4
+ export * from './versioned';