sememe 0.0.0-stage → 0.4.21

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 (76) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +2667 -2
  3. package/bin/sememe.mjs +556 -0
  4. package/index.mjs +48 -0
  5. package/interface/ata-ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL.json +62 -0
  6. package/interface/native-11111111111111111111111111111111.json +226 -0
  7. package/interface/native-ComputeBudget111111111111111111111111111111.json +72 -0
  8. package/interface/raydium-675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8.json +352 -0
  9. package/interface/token-TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA.json +334 -0
  10. package/interface/token-TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb.json +535 -0
  11. package/interface/token-metadata.json +132 -0
  12. package/package.json +71 -4
  13. package/src/account-list.mjs +308 -0
  14. package/src/account-union.mjs +523 -0
  15. package/src/account.mjs +199 -0
  16. package/src/acquire.mjs +145 -0
  17. package/src/adopt.mjs +205 -0
  18. package/src/ata-interface.mjs +276 -0
  19. package/src/ata.mjs +223 -0
  20. package/src/base58.mjs +96 -0
  21. package/src/canonical.mjs +24 -0
  22. package/src/cli-surface.mjs +300 -0
  23. package/src/codec.mjs +1069 -0
  24. package/src/conformance.mjs +431 -0
  25. package/src/corpus/harvest-compute-budget-2026-10-31.json +19122 -0
  26. package/src/corpus/harvest-system-2026-10-31.json +26090 -0
  27. package/src/decode.mjs +286 -0
  28. package/src/dialect.mjs +145 -0
  29. package/src/discriminators.mjs +177 -0
  30. package/src/drift.mjs +172 -0
  31. package/src/gap.mjs +205 -0
  32. package/src/lighthouse.mjs +168 -0
  33. package/src/lock.mjs +440 -0
  34. package/src/native-audit.mjs +56 -0
  35. package/src/native-corpus.mjs +57 -0
  36. package/src/native-interface.mjs +252 -0
  37. package/src/native.mjs +324 -0
  38. package/src/peer.mjs +95 -0
  39. package/src/program-id.mjs +74 -0
  40. package/src/pull.mjs +117 -0
  41. package/src/rawle.mjs +450 -0
  42. package/src/raydium-interface.mjs +747 -0
  43. package/src/raydium.mjs +391 -0
  44. package/src/receipt-digest.mjs +84 -0
  45. package/src/receipt-name.mjs +128 -0
  46. package/src/receipt-order.mjs +56 -0
  47. package/src/shank.mjs +73 -0
  48. package/src/short-forms.mjs +209 -0
  49. package/src/store-read.mjs +250 -0
  50. package/src/store-write.mjs +46 -0
  51. package/src/token-interface.mjs +394 -0
  52. package/src/token-metadata-interface.mjs +371 -0
  53. package/src/token-metadata.mjs +317 -0
  54. package/src/token.mjs +443 -0
  55. package/src/union.mjs +428 -0
  56. package/vendor/anza-solana-sdk/8db406e2edfafa25939ec782b77b5b6f30de164d/LICENSE.txt +201 -0
  57. package/vendor/anza-solana-sdk/8db406e2edfafa25939ec782b77b5b6f30de164d/compute-budget-interface/src/lib.rs +93 -0
  58. package/vendor/anza-solana-sdk/8db406e2edfafa25939ec782b77b5b6f30de164d/system-interface/src/instruction.rs +1899 -0
  59. package/vendor/lighthouse/4c579479c98635e419b1b167f08be02a71604a71/LICENSE +21 -0
  60. package/vendor/lighthouse/4c579479c98635e419b1b167f08be02a71604a71/lighthouse.json +2769 -0
  61. package/vendor/raydium-amm/91739d8d9f5cf347e0ce14ebe4d2bb7069fb31b6/LICENSE +201 -0
  62. package/vendor/raydium-amm/91739d8d9f5cf347e0ce14ebe4d2bb7069fb31b6/program/src/instruction.rs +1189 -0
  63. package/vendor/raydium-amm/91739d8d9f5cf347e0ce14ebe4d2bb7069fb31b6/program/src/state.rs +1348 -0
  64. package/vendor/spl-associated-token-account/fbf5379e7398ac8b231c73ee8a9ff677b43dd0ec/LICENSE +201 -0
  65. package/vendor/spl-associated-token-account/fbf5379e7398ac8b231c73ee8a9ff677b43dd0ec/interface/src/instruction.rs +169 -0
  66. package/vendor/spl-associated-token-account/fbf5379e7398ac8b231c73ee8a9ff677b43dd0ec/interface/src/lib.rs +12 -0
  67. package/vendor/spl-associated-token-account/fbf5379e7398ac8b231c73ee8a9ff677b43dd0ec/program/src/processor.rs +308 -0
  68. package/vendor/spl-token/737788ff5bcc3f1f44cfb222f25483187650be76/LICENSE.txt +176 -0
  69. package/vendor/spl-token/737788ff5bcc3f1f44cfb222f25483187650be76/interface/src/instruction.rs +1963 -0
  70. package/vendor/spl-token-2022/5251dcc07ecbcb721d6c4f0231090defadf00311/LICENSE.txt +176 -0
  71. package/vendor/spl-token-2022/5251dcc07ecbcb721d6c4f0231090defadf00311/interface/src/instruction.rs +2868 -0
  72. package/vendor/spl-token-metadata-interface/7038969ec74a89f1afdb9bc97c112d4d26fead9a/LICENSE +201 -0
  73. package/vendor/spl-token-metadata-interface/7038969ec74a89f1afdb9bc97c112d4d26fead9a/interface/src/error.rs +58 -0
  74. package/vendor/spl-token-metadata-interface/7038969ec74a89f1afdb9bc97c112d4d26fead9a/interface/src/instruction.rs +596 -0
  75. package/vendor/spl-token-metadata-interface/7038969ec74a89f1afdb9bc97c112d4d26fead9a/interface/src/lib.rs +21 -0
  76. package/vendor/spl-token-metadata-interface/7038969ec74a89f1afdb9bc97c112d4d26fead9a/interface/src/state.rs +229 -0
@@ -0,0 +1,1963 @@
1
+ //! Instruction types
2
+
3
+ use {
4
+ crate::{check_program_account, error::TokenError},
5
+ solana_instruction::{AccountMeta, Instruction},
6
+ solana_program_error::ProgramError,
7
+ solana_program_option::COption,
8
+ solana_pubkey::Pubkey,
9
+ solana_sdk_ids::sysvar,
10
+ std::{convert::TryInto, mem::size_of},
11
+ };
12
+
13
+ /// Minimum number of multisignature signers (min N)
14
+ pub const MIN_SIGNERS: usize = 1;
15
+ /// Maximum number of multisignature signers (max N)
16
+ pub const MAX_SIGNERS: usize = 11;
17
+ /// Serialized length of a `u64`, for unpacking
18
+ const U64_BYTES: usize = 8;
19
+
20
+ /// Instructions supported by the token program.
21
+ #[repr(C, u8)]
22
+ #[derive(Clone, Debug, PartialEq)]
23
+ pub enum TokenInstruction<'a> {
24
+ /// Initializes a new mint and optionally deposits all the newly minted
25
+ /// tokens in an account.
26
+ ///
27
+ /// The `InitializeMint` instruction requires no signers and MUST be
28
+ /// included within the same Transaction as the system program's
29
+ /// `CreateAccount` instruction that creates the account being initialized.
30
+ /// Otherwise another party can acquire ownership of the uninitialized
31
+ /// account.
32
+ ///
33
+ /// Accounts expected by this instruction:
34
+ ///
35
+ /// 0. `[writable]` The mint to initialize.
36
+ /// 1. `[]` Rent sysvar
37
+ InitializeMint {
38
+ /// Number of base 10 digits to the right of the decimal place.
39
+ decimals: u8,
40
+ /// The authority/multisignature to mint tokens.
41
+ mint_authority: Pubkey,
42
+ /// The freeze authority/multisignature of the mint.
43
+ freeze_authority: COption<Pubkey>,
44
+ },
45
+ /// Initializes a new account to hold tokens. If this account is associated
46
+ /// with the native mint then the token balance of the initialized account
47
+ /// will be equal to the amount of SOL in the account. If this account is
48
+ /// associated with another mint, that mint must be initialized before this
49
+ /// command can succeed.
50
+ ///
51
+ /// The `InitializeAccount` instruction requires no signers and MUST be
52
+ /// included within the same Transaction as the system program's
53
+ /// `CreateAccount` instruction that creates the account being initialized.
54
+ /// Otherwise another party can acquire ownership of the uninitialized
55
+ /// account.
56
+ ///
57
+ /// Accounts expected by this instruction:
58
+ ///
59
+ /// 0. `[writable]` The account to initialize.
60
+ /// 1. `[]` The mint this account will be associated with.
61
+ /// 2. `[]` The new account's owner/multisignature.
62
+ /// 3. `[]` Rent sysvar
63
+ InitializeAccount,
64
+ /// Initializes a multisignature account with N provided signers.
65
+ ///
66
+ /// Multisignature accounts can used in place of any single owner/delegate
67
+ /// accounts in any token instruction that require an owner/delegate to be
68
+ /// present. The variant field represents the number of signers (M)
69
+ /// required to validate this multisignature account.
70
+ ///
71
+ /// The `InitializeMultisig` instruction requires no signers and MUST be
72
+ /// included within the same Transaction as the system program's
73
+ /// `CreateAccount` instruction that creates the account being initialized.
74
+ /// Otherwise another party can acquire ownership of the uninitialized
75
+ /// account.
76
+ ///
77
+ /// Accounts expected by this instruction:
78
+ ///
79
+ /// 0. `[writable]` The multisignature account to initialize.
80
+ /// 1. `[]` Rent sysvar
81
+ /// 2. ..`2+N`. `[]` The signer accounts, must equal to N where `1 <= N <=
82
+ /// 11`.
83
+ InitializeMultisig {
84
+ /// The number of signers (M) required to validate this multisignature
85
+ /// account.
86
+ m: u8,
87
+ },
88
+ /// Transfers tokens from one account to another either directly or via a
89
+ /// delegate. If this account is associated with the native mint then equal
90
+ /// amounts of SOL and Tokens will be transferred to the destination
91
+ /// account.
92
+ ///
93
+ /// Accounts expected by this instruction:
94
+ ///
95
+ /// * Single owner/delegate
96
+ /// 0. `[writable]` The source account.
97
+ /// 1. `[writable]` The destination account.
98
+ /// 2. `[signer]` The source account's owner/delegate.
99
+ ///
100
+ /// * Multisignature owner/delegate
101
+ /// 0. `[writable]` The source account.
102
+ /// 1. `[writable]` The destination account.
103
+ /// 2. `[]` The source account's multisignature owner/delegate.
104
+ /// 3. ..`3+M` `[signer]` M signer accounts.
105
+ Transfer {
106
+ /// The amount of tokens to transfer.
107
+ amount: u64,
108
+ },
109
+ /// Approves a delegate. A delegate is given the authority over tokens on
110
+ /// behalf of the source account's owner.
111
+ ///
112
+ /// Accounts expected by this instruction:
113
+ ///
114
+ /// * Single owner
115
+ /// 0. `[writable]` The source account.
116
+ /// 1. `[]` The delegate.
117
+ /// 2. `[signer]` The source account owner.
118
+ ///
119
+ /// * Multisignature owner
120
+ /// 0. `[writable]` The source account.
121
+ /// 1. `[]` The delegate.
122
+ /// 2. `[]` The source account's multisignature owner.
123
+ /// 3. ..`3+M` `[signer]` M signer accounts
124
+ Approve {
125
+ /// The amount of tokens the delegate is approved for.
126
+ amount: u64,
127
+ },
128
+ /// Revokes the delegate's authority.
129
+ ///
130
+ /// Accounts expected by this instruction:
131
+ ///
132
+ /// * Single owner
133
+ /// 0. `[writable]` The source account.
134
+ /// 1. `[signer]` The source account owner.
135
+ ///
136
+ /// * Multisignature owner
137
+ /// 0. `[writable]` The source account.
138
+ /// 1. `[]` The source account's multisignature owner.
139
+ /// 2. ..`2+M` `[signer]` M signer accounts
140
+ Revoke,
141
+ /// Sets a new authority of a mint or account.
142
+ ///
143
+ /// Accounts expected by this instruction:
144
+ ///
145
+ /// * Single authority
146
+ /// 0. `[writable]` The mint or account to change the authority of.
147
+ /// 1. `[signer]` The current authority of the mint or account.
148
+ ///
149
+ /// * Multisignature authority
150
+ /// 0. `[writable]` The mint or account to change the authority of.
151
+ /// 1. `[]` The mint's or account's current multisignature authority.
152
+ /// 2. ..`2+M` `[signer]` M signer accounts
153
+ SetAuthority {
154
+ /// The type of authority to update.
155
+ authority_type: AuthorityType,
156
+ /// The new authority
157
+ new_authority: COption<Pubkey>,
158
+ },
159
+ /// Mints new tokens to an account. The native mint does not support
160
+ /// minting.
161
+ ///
162
+ /// Accounts expected by this instruction:
163
+ ///
164
+ /// * Single authority
165
+ /// 0. `[writable]` The mint.
166
+ /// 1. `[writable]` The account to mint tokens to.
167
+ /// 2. `[signer]` The mint's minting authority.
168
+ ///
169
+ /// * Multisignature authority
170
+ /// 0. `[writable]` The mint.
171
+ /// 1. `[writable]` The account to mint tokens to.
172
+ /// 2. `[]` The mint's multisignature mint-tokens authority.
173
+ /// 3. ..`3+M` `[signer]` M signer accounts.
174
+ MintTo {
175
+ /// The amount of new tokens to mint.
176
+ amount: u64,
177
+ },
178
+ /// Burns tokens by removing them from an account. `Burn` does not support
179
+ /// accounts associated with the native mint, use `CloseAccount` instead.
180
+ ///
181
+ /// Accounts expected by this instruction:
182
+ ///
183
+ /// * Single owner/delegate
184
+ /// 0. `[writable]` The account to burn from.
185
+ /// 1. `[writable]` The token mint.
186
+ /// 2. `[signer]` The account's owner/delegate.
187
+ ///
188
+ /// * Multisignature owner/delegate
189
+ /// 0. `[writable]` The account to burn from.
190
+ /// 1. `[writable]` The token mint.
191
+ /// 2. `[]` The account's multisignature owner/delegate.
192
+ /// 3. ..`3+M` `[signer]` M signer accounts.
193
+ Burn {
194
+ /// The amount of tokens to burn.
195
+ amount: u64,
196
+ },
197
+ /// Close an account by transferring all its SOL to the destination account.
198
+ /// Non-native accounts may only be closed if its token amount is zero.
199
+ ///
200
+ /// Accounts expected by this instruction:
201
+ ///
202
+ /// * Single owner
203
+ /// 0. `[writable]` The account to close.
204
+ /// 1. `[writable]` The destination account.
205
+ /// 2. `[signer]` The account's owner.
206
+ ///
207
+ /// * Multisignature owner
208
+ /// 0. `[writable]` The account to close.
209
+ /// 1. `[writable]` The destination account.
210
+ /// 2. `[]` The account's multisignature owner.
211
+ /// 3. ..`3+M` `[signer]` M signer accounts.
212
+ CloseAccount,
213
+ /// Freeze an Initialized account using the Mint's `freeze_authority` (if
214
+ /// set).
215
+ ///
216
+ /// Accounts expected by this instruction:
217
+ ///
218
+ /// * Single owner
219
+ /// 0. `[writable]` The account to freeze.
220
+ /// 1. `[]` The token mint.
221
+ /// 2. `[signer]` The mint freeze authority.
222
+ ///
223
+ /// * Multisignature owner
224
+ /// 0. `[writable]` The account to freeze.
225
+ /// 1. `[]` The token mint.
226
+ /// 2. `[]` The mint's multisignature freeze authority.
227
+ /// 3. ..`3+M` `[signer]` M signer accounts.
228
+ FreezeAccount,
229
+ /// Thaw a Frozen account using the Mint's `freeze_authority` (if set).
230
+ ///
231
+ /// Accounts expected by this instruction:
232
+ ///
233
+ /// * Single owner
234
+ /// 0. `[writable]` The account to thaw.
235
+ /// 1. `[]` The token mint.
236
+ /// 2. `[signer]` The mint freeze authority.
237
+ ///
238
+ /// * Multisignature owner
239
+ /// 0. `[writable]` The account to thaw.
240
+ /// 1. `[]` The token mint.
241
+ /// 2. `[]` The mint's multisignature freeze authority.
242
+ /// 3. ..`3+M` `[signer]` M signer accounts.
243
+ ThawAccount,
244
+
245
+ /// Transfers tokens from one account to another either directly or via a
246
+ /// delegate. If this account is associated with the native mint then equal
247
+ /// amounts of SOL and Tokens will be transferred to the destination
248
+ /// account.
249
+ ///
250
+ /// This instruction differs from Transfer in that the token mint and
251
+ /// decimals value is checked by the caller. This may be useful when
252
+ /// creating transactions offline or within a hardware wallet.
253
+ ///
254
+ /// Accounts expected by this instruction:
255
+ ///
256
+ /// * Single owner/delegate
257
+ /// 0. `[writable]` The source account.
258
+ /// 1. `[]` The token mint.
259
+ /// 2. `[writable]` The destination account.
260
+ /// 3. `[signer]` The source account's owner/delegate.
261
+ ///
262
+ /// * Multisignature owner/delegate
263
+ /// 0. `[writable]` The source account.
264
+ /// 1. `[]` The token mint.
265
+ /// 2. `[writable]` The destination account.
266
+ /// 3. `[]` The source account's multisignature owner/delegate.
267
+ /// 4. ..`4+M` `[signer]` M signer accounts.
268
+ TransferChecked {
269
+ /// The amount of tokens to transfer.
270
+ amount: u64,
271
+ /// Expected number of base 10 digits to the right of the decimal place.
272
+ decimals: u8,
273
+ },
274
+ /// Approves a delegate. A delegate is given the authority over tokens on
275
+ /// behalf of the source account's owner.
276
+ ///
277
+ /// This instruction differs from Approve in that the token mint and
278
+ /// decimals value is checked by the caller. This may be useful when
279
+ /// creating transactions offline or within a hardware wallet.
280
+ ///
281
+ /// Accounts expected by this instruction:
282
+ ///
283
+ /// * Single owner
284
+ /// 0. `[writable]` The source account.
285
+ /// 1. `[]` The token mint.
286
+ /// 2. `[]` The delegate.
287
+ /// 3. `[signer]` The source account owner.
288
+ ///
289
+ /// * Multisignature owner
290
+ /// 0. `[writable]` The source account.
291
+ /// 1. `[]` The token mint.
292
+ /// 2. `[]` The delegate.
293
+ /// 3. `[]` The source account's multisignature owner.
294
+ /// 4. ..`4+M` `[signer]` M signer accounts
295
+ ApproveChecked {
296
+ /// The amount of tokens the delegate is approved for.
297
+ amount: u64,
298
+ /// Expected number of base 10 digits to the right of the decimal place.
299
+ decimals: u8,
300
+ },
301
+ /// Mints new tokens to an account. The native mint does not support
302
+ /// minting.
303
+ ///
304
+ /// This instruction differs from `MintTo` in that the decimals value is
305
+ /// checked by the caller. This may be useful when creating transactions
306
+ /// offline or within a hardware wallet.
307
+ ///
308
+ /// Accounts expected by this instruction:
309
+ ///
310
+ /// * Single authority
311
+ /// 0. `[writable]` The mint.
312
+ /// 1. `[writable]` The account to mint tokens to.
313
+ /// 2. `[signer]` The mint's minting authority.
314
+ ///
315
+ /// * Multisignature authority
316
+ /// 0. `[writable]` The mint.
317
+ /// 1. `[writable]` The account to mint tokens to.
318
+ /// 2. `[]` The mint's multisignature mint-tokens authority.
319
+ /// 3. ..`3+M` `[signer]` M signer accounts.
320
+ MintToChecked {
321
+ /// The amount of new tokens to mint.
322
+ amount: u64,
323
+ /// Expected number of base 10 digits to the right of the decimal place.
324
+ decimals: u8,
325
+ },
326
+ /// Burns tokens by removing them from an account. `BurnChecked` does not
327
+ /// support accounts associated with the native mint, use `CloseAccount`
328
+ /// instead.
329
+ ///
330
+ /// This instruction differs from Burn in that the decimals value is checked
331
+ /// by the caller. This may be useful when creating transactions offline or
332
+ /// within a hardware wallet.
333
+ ///
334
+ /// Accounts expected by this instruction:
335
+ ///
336
+ /// * Single owner/delegate
337
+ /// 0. `[writable]` The account to burn from.
338
+ /// 1. `[writable]` The token mint.
339
+ /// 2. `[signer]` The account's owner/delegate.
340
+ ///
341
+ /// * Multisignature owner/delegate
342
+ /// 0. `[writable]` The account to burn from.
343
+ /// 1. `[writable]` The token mint.
344
+ /// 2. `[]` The account's multisignature owner/delegate.
345
+ /// 3. ..`3+M` `[signer]` M signer accounts.
346
+ BurnChecked {
347
+ /// The amount of tokens to burn.
348
+ amount: u64,
349
+ /// Expected number of base 10 digits to the right of the decimal place.
350
+ decimals: u8,
351
+ },
352
+ /// Like [`TokenInstruction::InitializeAccount`], but the owner pubkey is
353
+ /// passed via instruction data rather than the accounts list. This
354
+ /// variant may be preferable when using Cross Program Invocation from
355
+ /// an instruction that does not need the owner's `AccountInfo`
356
+ /// otherwise.
357
+ ///
358
+ /// Accounts expected by this instruction:
359
+ ///
360
+ /// 0. `[writable]` The account to initialize.
361
+ /// 1. `[]` The mint this account will be associated with.
362
+ /// 3. `[]` Rent sysvar
363
+ InitializeAccount2 {
364
+ /// The new account's owner/multisignature.
365
+ owner: Pubkey,
366
+ },
367
+ /// Given a wrapped / native token account (a token account containing SOL)
368
+ /// updates its amount field based on the account's underlying `lamports`.
369
+ /// This is useful if a non-wrapped SOL account uses
370
+ /// `system_instruction::transfer` to move lamports to a wrapped token
371
+ /// account, and needs to have its token `amount` field updated.
372
+ ///
373
+ /// Accounts expected by this instruction:
374
+ ///
375
+ /// * Using runtime Rent sysvar
376
+ /// 0. `[writable]` The native token account to sync with its underlying
377
+ /// lamports.
378
+ ///
379
+ /// * Using Rent sysvar account
380
+ /// 0. `[writable]` The native token account to sync with its underlying
381
+ /// lamports.
382
+ /// 1. `[]` Rent sysvar.
383
+ SyncNative,
384
+ /// Like [`TokenInstruction::InitializeAccount2`], but does not require the
385
+ /// Rent sysvar to be provided
386
+ ///
387
+ /// Accounts expected by this instruction:
388
+ ///
389
+ /// 0. `[writable]` The account to initialize.
390
+ /// 1. `[]` The mint this account will be associated with.
391
+ InitializeAccount3 {
392
+ /// The new account's owner/multisignature.
393
+ owner: Pubkey,
394
+ },
395
+ /// Like [`TokenInstruction::InitializeMultisig`], but does not require the
396
+ /// Rent sysvar to be provided
397
+ ///
398
+ /// Accounts expected by this instruction:
399
+ ///
400
+ /// 0. `[writable]` The multisignature account to initialize.
401
+ /// 1. ..`1+N` `[]` The signer accounts, must equal to N where `1 <= N <=
402
+ /// 11`.
403
+ InitializeMultisig2 {
404
+ /// The number of signers (M) required to validate this multisignature
405
+ /// account.
406
+ m: u8,
407
+ },
408
+ /// Like [`TokenInstruction::InitializeMint`], but does not require the Rent
409
+ /// sysvar to be provided
410
+ ///
411
+ /// Accounts expected by this instruction:
412
+ ///
413
+ /// 0. `[writable]` The mint to initialize.
414
+ InitializeMint2 {
415
+ /// Number of base 10 digits to the right of the decimal place.
416
+ decimals: u8,
417
+ /// The authority/multisignature to mint tokens.
418
+ mint_authority: Pubkey,
419
+ /// The freeze authority/multisignature of the mint.
420
+ freeze_authority: COption<Pubkey>,
421
+ },
422
+ /// Gets the required size of an account for the given mint as a
423
+ /// little-endian `u64`.
424
+ ///
425
+ /// Return data can be fetched using `sol_get_return_data` and deserializing
426
+ /// the return data as a little-endian `u64`.
427
+ ///
428
+ /// Accounts expected by this instruction:
429
+ ///
430
+ /// 0. `[]` The mint to calculate for
431
+ GetAccountDataSize, // typically, there's also data, but this program ignores it
432
+ /// Initialize the Immutable Owner extension for the given token account
433
+ ///
434
+ /// Fails if the account has already been initialized, so must be called
435
+ /// before `InitializeAccount`.
436
+ ///
437
+ /// No-ops in this version of the program, but is included for compatibility
438
+ /// with the Associated Token Account program.
439
+ ///
440
+ /// Accounts expected by this instruction:
441
+ ///
442
+ /// 0. `[writable]` The account to initialize.
443
+ ///
444
+ /// Data expected by this instruction:
445
+ /// None
446
+ InitializeImmutableOwner,
447
+ /// Convert an Amount of tokens to a `UiAmount` string, using the given
448
+ /// mint. In this version of the program, the mint can only specify the
449
+ /// number of decimals.
450
+ ///
451
+ /// Fails on an invalid mint.
452
+ ///
453
+ /// Return data can be fetched using `sol_get_return_data` and deserialized
454
+ /// with `String::from_utf8`.
455
+ ///
456
+ /// Accounts expected by this instruction:
457
+ ///
458
+ /// 0. `[]` The mint to calculate for
459
+ AmountToUiAmount {
460
+ /// The amount of tokens to reformat.
461
+ amount: u64,
462
+ },
463
+ /// Convert a `UiAmount` of tokens to a little-endian `u64` raw Amount,
464
+ /// using the given mint. In this version of the program, the mint can
465
+ /// only specify the number of decimals.
466
+ ///
467
+ /// Return data can be fetched using `sol_get_return_data` and deserializing
468
+ /// the return data as a little-endian `u64`.
469
+ ///
470
+ /// Accounts expected by this instruction:
471
+ ///
472
+ /// 0. `[]` The mint to calculate for
473
+ UiAmountToAmount {
474
+ /// The `ui_amount` of tokens to reformat.
475
+ ui_amount: &'a str,
476
+ },
477
+ /// This instruction is to be used to rescue SOL sent to any `TokenProgram`
478
+ /// owned account by sending them to any other account, leaving behind only
479
+ /// lamports for rent exemption.
480
+ ///
481
+ /// Accounts expected by this instruction:
482
+ ///
483
+ /// * Single owner/delegate
484
+ /// 0. `[writable]` The source account.
485
+ /// 1. `[writable]` The destination account.
486
+ /// 2. `[signer]` The source account's owner/delegate.
487
+ ///
488
+ /// * Multisignature owner/delegate
489
+ /// 0. `[writable]` The source account.
490
+ /// 1. `[writable]` The destination account.
491
+ /// 2. `[]` The source account's multisignature owner/delegate.
492
+ /// 3. `..+M` `[signer]` M signer accounts.
493
+ WithdrawExcessLamports = 38,
494
+ /// Transfer lamports from a native SOL account to a destination account.
495
+ ///
496
+ /// This is useful to unwrap lamports from a wrapped SOL account.
497
+ ///
498
+ /// Accounts expected by this instruction:
499
+ ///
500
+ /// * Single owner/delegate
501
+ /// 0. `[writable]` The source account.
502
+ /// 1. `[writable]` The destination account.
503
+ /// 2. `[signer]` The source account's owner/delegate.
504
+ ///
505
+ /// * Multisignature owner/delegate
506
+ /// 0. `[writable]` The source account.
507
+ /// 1. `[writable]` The destination account.
508
+ /// 2. `[]` The source account's multisignature owner/delegate.
509
+ /// 3. `..+M` `[signer]` M signer accounts.
510
+ ///
511
+ /// Data expected by this instruction:
512
+ ///
513
+ /// - `Option<u64>` The amount of lamports to transfer. When an amount is
514
+ /// not specified, the entire balance of the source account will be
515
+ /// transferred.
516
+ UnwrapLamports {
517
+ /// The amount of lamports to transfer.
518
+ amount: COption<u64>,
519
+ } = 45,
520
+ /// Executes a batch of instructions. The instructions to be executed are
521
+ /// specified in sequence on the instruction data. Each instruction
522
+ /// provides:
523
+ /// - `u8`: number of accounts
524
+ /// - `u8`: instruction data length (includes the discriminator)
525
+ /// - `u8`: instruction discriminator
526
+ /// - `[u8]`: instruction data
527
+ ///
528
+ /// Accounts follow a similar pattern, where accounts for each instruction
529
+ /// are specified in sequence. Therefore, the number of accounts
530
+ /// expected by this instruction is variable, i.e., it depends on the
531
+ /// instructions provided.
532
+ ///
533
+ /// Both the number of accounts and instruction data length are used to
534
+ /// identify the slice of accounts and instruction data for each
535
+ /// instruction. Since the instruction data length is specified as a `u8`,
536
+ /// the maximum instruction data length is 255 bytes, which is sufficient
537
+ /// for all current instructions in the program.
538
+ ///
539
+ /// When one or more batched instructions write return data, the batch
540
+ /// instruction returns the data written by the last instruction that does
541
+ /// so. That instruction does not have to be the final instruction in the
542
+ /// batch: later instructions that do not write return data leave the last
543
+ /// written return data unchanged.
544
+ ///
545
+ /// Note that it is not sound to have a `batch` instruction that contains
546
+ /// other `batch` instruction; an error will be raised when this is
547
+ /// detected.
548
+ Batch = 255,
549
+ // Any new variants also need to be added to program-2022 `TokenInstruction`, so that the
550
+ // latter remains a superset of this instruction set. New variants also need to be added to
551
+ // token/js/src/instructions/types.ts to maintain @solana/spl-token compatibility
552
+ }
553
+ impl<'a> TokenInstruction<'a> {
554
+ /// Unpacks a byte buffer into a
555
+ /// [`TokenInstruction`](enum.TokenInstruction.html).
556
+ pub fn unpack(input: &'a [u8]) -> Result<Self, ProgramError> {
557
+ use TokenError::InvalidInstruction;
558
+
559
+ let (&tag, rest) = input.split_first().ok_or(InvalidInstruction)?;
560
+ Ok(match tag {
561
+ 0 => {
562
+ let (&decimals, rest) = rest.split_first().ok_or(InvalidInstruction)?;
563
+ let (mint_authority, rest) = Self::unpack_pubkey(rest)?;
564
+ let (freeze_authority, _rest) = Self::unpack_pubkey_option(rest)?;
565
+ Self::InitializeMint {
566
+ mint_authority,
567
+ freeze_authority,
568
+ decimals,
569
+ }
570
+ }
571
+ 1 => Self::InitializeAccount,
572
+ 2 => {
573
+ let &m = rest.first().ok_or(InvalidInstruction)?;
574
+ Self::InitializeMultisig { m }
575
+ }
576
+ 3 | 4 | 7 | 8 => {
577
+ let amount = rest
578
+ .get(..8)
579
+ .and_then(|slice| slice.try_into().ok())
580
+ .map(u64::from_le_bytes)
581
+ .ok_or(InvalidInstruction)?;
582
+ match tag {
583
+ 3 => Self::Transfer { amount },
584
+ 4 => Self::Approve { amount },
585
+ 7 => Self::MintTo { amount },
586
+ 8 => Self::Burn { amount },
587
+ _ => unreachable!(),
588
+ }
589
+ }
590
+ 5 => Self::Revoke,
591
+ 6 => {
592
+ let (authority_type, rest) = rest
593
+ .split_first()
594
+ .ok_or_else(|| ProgramError::from(InvalidInstruction))
595
+ .and_then(|(&t, rest)| Ok((AuthorityType::from(t)?, rest)))?;
596
+ let (new_authority, _rest) = Self::unpack_pubkey_option(rest)?;
597
+
598
+ Self::SetAuthority {
599
+ authority_type,
600
+ new_authority,
601
+ }
602
+ }
603
+ 9 => Self::CloseAccount,
604
+ 10 => Self::FreezeAccount,
605
+ 11 => Self::ThawAccount,
606
+ 12 => {
607
+ let (amount, decimals, _rest) = Self::unpack_amount_decimals(rest)?;
608
+ Self::TransferChecked { amount, decimals }
609
+ }
610
+ 13 => {
611
+ let (amount, decimals, _rest) = Self::unpack_amount_decimals(rest)?;
612
+ Self::ApproveChecked { amount, decimals }
613
+ }
614
+ 14 => {
615
+ let (amount, decimals, _rest) = Self::unpack_amount_decimals(rest)?;
616
+ Self::MintToChecked { amount, decimals }
617
+ }
618
+ 15 => {
619
+ let (amount, decimals, _rest) = Self::unpack_amount_decimals(rest)?;
620
+ Self::BurnChecked { amount, decimals }
621
+ }
622
+ 16 => {
623
+ let (owner, _rest) = Self::unpack_pubkey(rest)?;
624
+ Self::InitializeAccount2 { owner }
625
+ }
626
+ 17 => Self::SyncNative,
627
+ 18 => {
628
+ let (owner, _rest) = Self::unpack_pubkey(rest)?;
629
+ Self::InitializeAccount3 { owner }
630
+ }
631
+ 19 => {
632
+ let &m = rest.first().ok_or(InvalidInstruction)?;
633
+ Self::InitializeMultisig2 { m }
634
+ }
635
+ 20 => {
636
+ let (&decimals, rest) = rest.split_first().ok_or(InvalidInstruction)?;
637
+ let (mint_authority, rest) = Self::unpack_pubkey(rest)?;
638
+ let (freeze_authority, _rest) = Self::unpack_pubkey_option(rest)?;
639
+ Self::InitializeMint2 {
640
+ mint_authority,
641
+ freeze_authority,
642
+ decimals,
643
+ }
644
+ }
645
+ 21 => Self::GetAccountDataSize,
646
+ 22 => Self::InitializeImmutableOwner,
647
+ 23 => {
648
+ let (amount, _rest) = Self::unpack_u64(rest)?;
649
+ Self::AmountToUiAmount { amount }
650
+ }
651
+ 24 => {
652
+ let ui_amount = std::str::from_utf8(rest).map_err(|_| InvalidInstruction)?;
653
+ Self::UiAmountToAmount { ui_amount }
654
+ }
655
+ 38 => Self::WithdrawExcessLamports,
656
+ 45 => {
657
+ let (amount, _rest) = Self::unpack_u64_option(rest)?;
658
+ Self::UnwrapLamports { amount }
659
+ }
660
+ 255 => Self::Batch,
661
+ _ => return Err(TokenError::InvalidInstruction.into()),
662
+ })
663
+ }
664
+
665
+ /// Packs a [`TokenInstruction`](enum.TokenInstruction.html) into a byte
666
+ /// buffer.
667
+ pub fn pack(&self) -> Vec<u8> {
668
+ let mut buf = Vec::with_capacity(size_of::<Self>());
669
+ match self {
670
+ &Self::InitializeMint {
671
+ ref mint_authority,
672
+ ref freeze_authority,
673
+ decimals,
674
+ } => {
675
+ buf.push(0);
676
+ buf.push(decimals);
677
+ buf.extend_from_slice(mint_authority.as_ref());
678
+ Self::pack_pubkey_option(freeze_authority, &mut buf);
679
+ }
680
+ Self::InitializeAccount => buf.push(1),
681
+ &Self::InitializeMultisig { m } => {
682
+ buf.push(2);
683
+ buf.push(m);
684
+ }
685
+ &Self::Transfer { amount } => {
686
+ buf.push(3);
687
+ buf.extend_from_slice(&amount.to_le_bytes());
688
+ }
689
+ &Self::Approve { amount } => {
690
+ buf.push(4);
691
+ buf.extend_from_slice(&amount.to_le_bytes());
692
+ }
693
+ &Self::MintTo { amount } => {
694
+ buf.push(7);
695
+ buf.extend_from_slice(&amount.to_le_bytes());
696
+ }
697
+ &Self::Burn { amount } => {
698
+ buf.push(8);
699
+ buf.extend_from_slice(&amount.to_le_bytes());
700
+ }
701
+ Self::Revoke => buf.push(5),
702
+ Self::SetAuthority {
703
+ authority_type,
704
+ ref new_authority,
705
+ } => {
706
+ buf.push(6);
707
+ buf.push(authority_type.into());
708
+ Self::pack_pubkey_option(new_authority, &mut buf);
709
+ }
710
+ Self::CloseAccount => buf.push(9),
711
+ Self::FreezeAccount => buf.push(10),
712
+ Self::ThawAccount => buf.push(11),
713
+ &Self::TransferChecked { amount, decimals } => {
714
+ buf.push(12);
715
+ buf.extend_from_slice(&amount.to_le_bytes());
716
+ buf.push(decimals);
717
+ }
718
+ &Self::ApproveChecked { amount, decimals } => {
719
+ buf.push(13);
720
+ buf.extend_from_slice(&amount.to_le_bytes());
721
+ buf.push(decimals);
722
+ }
723
+ &Self::MintToChecked { amount, decimals } => {
724
+ buf.push(14);
725
+ buf.extend_from_slice(&amount.to_le_bytes());
726
+ buf.push(decimals);
727
+ }
728
+ &Self::BurnChecked { amount, decimals } => {
729
+ buf.push(15);
730
+ buf.extend_from_slice(&amount.to_le_bytes());
731
+ buf.push(decimals);
732
+ }
733
+ &Self::InitializeAccount2 { owner } => {
734
+ buf.push(16);
735
+ buf.extend_from_slice(owner.as_ref());
736
+ }
737
+ &Self::SyncNative => {
738
+ buf.push(17);
739
+ }
740
+ &Self::InitializeAccount3 { owner } => {
741
+ buf.push(18);
742
+ buf.extend_from_slice(owner.as_ref());
743
+ }
744
+ &Self::InitializeMultisig2 { m } => {
745
+ buf.push(19);
746
+ buf.push(m);
747
+ }
748
+ &Self::InitializeMint2 {
749
+ ref mint_authority,
750
+ ref freeze_authority,
751
+ decimals,
752
+ } => {
753
+ buf.push(20);
754
+ buf.push(decimals);
755
+ buf.extend_from_slice(mint_authority.as_ref());
756
+ Self::pack_pubkey_option(freeze_authority, &mut buf);
757
+ }
758
+ &Self::GetAccountDataSize => {
759
+ buf.push(21);
760
+ }
761
+ &Self::InitializeImmutableOwner => {
762
+ buf.push(22);
763
+ }
764
+ &Self::AmountToUiAmount { amount } => {
765
+ buf.push(23);
766
+ buf.extend_from_slice(&amount.to_le_bytes());
767
+ }
768
+ Self::UiAmountToAmount { ui_amount } => {
769
+ buf.push(24);
770
+ buf.extend_from_slice(ui_amount.as_bytes());
771
+ }
772
+ &Self::WithdrawExcessLamports => {
773
+ buf.push(38);
774
+ }
775
+ Self::UnwrapLamports { ref amount } => {
776
+ buf.push(45);
777
+ Self::pack_u64_option(amount, &mut buf);
778
+ }
779
+ &Self::Batch => {
780
+ buf.push(255);
781
+ }
782
+ };
783
+ buf
784
+ }
785
+
786
+ fn unpack_pubkey(input: &[u8]) -> Result<(Pubkey, &[u8]), ProgramError> {
787
+ if input.len() >= 32 {
788
+ let (key, rest) = input.split_at(32);
789
+ let pk = Pubkey::try_from(key).map_err(|_| TokenError::InvalidInstruction)?;
790
+ Ok((pk, rest))
791
+ } else {
792
+ Err(TokenError::InvalidInstruction.into())
793
+ }
794
+ }
795
+
796
+ fn unpack_pubkey_option(input: &[u8]) -> Result<(COption<Pubkey>, &[u8]), ProgramError> {
797
+ match input.split_first() {
798
+ Option::Some((&0, rest)) => Ok((COption::None, rest)),
799
+ Option::Some((&1, rest)) if rest.len() >= 32 => {
800
+ let (key, rest) = rest.split_at(32);
801
+ let pk = Pubkey::try_from(key).map_err(|_| TokenError::InvalidInstruction)?;
802
+ Ok((COption::Some(pk), rest))
803
+ }
804
+ _ => Err(TokenError::InvalidInstruction.into()),
805
+ }
806
+ }
807
+
808
+ fn pack_pubkey_option(value: &COption<Pubkey>, buf: &mut Vec<u8>) {
809
+ match *value {
810
+ COption::Some(ref key) => {
811
+ buf.push(1);
812
+ buf.extend_from_slice(&key.to_bytes());
813
+ }
814
+ COption::None => buf.push(0),
815
+ }
816
+ }
817
+
818
+ fn unpack_u64(input: &[u8]) -> Result<(u64, &[u8]), ProgramError> {
819
+ let value = input
820
+ .get(..U64_BYTES)
821
+ .and_then(|slice| slice.try_into().ok())
822
+ .map(u64::from_le_bytes)
823
+ .ok_or(TokenError::InvalidInstruction)?;
824
+ Ok((value, &input[U64_BYTES..]))
825
+ }
826
+
827
+ fn unpack_u64_option(input: &[u8]) -> Result<(COption<u64>, &[u8]), ProgramError> {
828
+ match input.split_first() {
829
+ Option::Some((&0, rest)) => Ok((COption::None, rest)),
830
+ Option::Some((&1, rest)) if rest.len() >= 8 => {
831
+ let (amount, rest) = rest
832
+ .split_first_chunk::<8>()
833
+ .ok_or(TokenError::InvalidInstruction)?;
834
+ let v = u64::from_le_bytes(*amount);
835
+ Ok((COption::Some(v), rest))
836
+ }
837
+ _ => Err(TokenError::InvalidInstruction.into()),
838
+ }
839
+ }
840
+
841
+ fn pack_u64_option(value: &COption<u64>, buf: &mut Vec<u8>) {
842
+ match *value {
843
+ COption::Some(ref amount) => {
844
+ buf.push(1);
845
+ buf.extend_from_slice(&amount.to_le_bytes());
846
+ }
847
+ COption::None => buf.push(0),
848
+ }
849
+ }
850
+
851
+ fn unpack_amount_decimals(input: &[u8]) -> Result<(u64, u8, &[u8]), ProgramError> {
852
+ let (amount, rest) = Self::unpack_u64(input)?;
853
+ let (&decimals, rest) = rest.split_first().ok_or(TokenError::InvalidInstruction)?;
854
+ Ok((amount, decimals, rest))
855
+ }
856
+ }
857
+
858
+ /// Specifies the authority type for `SetAuthority` instructions
859
+ #[repr(u8)]
860
+ #[derive(Clone, Debug, PartialEq)]
861
+ pub enum AuthorityType {
862
+ /// Authority to mint new tokens
863
+ MintTokens,
864
+ /// Authority to freeze any account associated with the Mint
865
+ FreezeAccount,
866
+ /// Owner of a given token account
867
+ AccountOwner,
868
+ /// Authority to close a token account
869
+ CloseAccount,
870
+ }
871
+
872
+ impl AuthorityType {
873
+ fn into(&self) -> u8 {
874
+ match self {
875
+ AuthorityType::MintTokens => 0,
876
+ AuthorityType::FreezeAccount => 1,
877
+ AuthorityType::AccountOwner => 2,
878
+ AuthorityType::CloseAccount => 3,
879
+ }
880
+ }
881
+
882
+ fn from(index: u8) -> Result<Self, ProgramError> {
883
+ match index {
884
+ 0 => Ok(AuthorityType::MintTokens),
885
+ 1 => Ok(AuthorityType::FreezeAccount),
886
+ 2 => Ok(AuthorityType::AccountOwner),
887
+ 3 => Ok(AuthorityType::CloseAccount),
888
+ _ => Err(TokenError::InvalidInstruction.into()),
889
+ }
890
+ }
891
+ }
892
+
893
+ /// Creates a `InitializeMint` instruction.
894
+ pub fn initialize_mint(
895
+ token_program_id: &Pubkey,
896
+ mint_pubkey: &Pubkey,
897
+ mint_authority_pubkey: &Pubkey,
898
+ freeze_authority_pubkey: Option<&Pubkey>,
899
+ decimals: u8,
900
+ ) -> Result<Instruction, ProgramError> {
901
+ check_program_account(token_program_id)?;
902
+ let freeze_authority = freeze_authority_pubkey.cloned().into();
903
+ let data = TokenInstruction::InitializeMint {
904
+ mint_authority: *mint_authority_pubkey,
905
+ freeze_authority,
906
+ decimals,
907
+ }
908
+ .pack();
909
+
910
+ let accounts = vec![
911
+ AccountMeta::new(*mint_pubkey, false),
912
+ AccountMeta::new_readonly(sysvar::rent::id(), false),
913
+ ];
914
+
915
+ Ok(Instruction {
916
+ program_id: *token_program_id,
917
+ accounts,
918
+ data,
919
+ })
920
+ }
921
+
922
+ /// Creates a `InitializeMint2` instruction.
923
+ pub fn initialize_mint2(
924
+ token_program_id: &Pubkey,
925
+ mint_pubkey: &Pubkey,
926
+ mint_authority_pubkey: &Pubkey,
927
+ freeze_authority_pubkey: Option<&Pubkey>,
928
+ decimals: u8,
929
+ ) -> Result<Instruction, ProgramError> {
930
+ check_program_account(token_program_id)?;
931
+ let freeze_authority = freeze_authority_pubkey.cloned().into();
932
+ let data = TokenInstruction::InitializeMint2 {
933
+ mint_authority: *mint_authority_pubkey,
934
+ freeze_authority,
935
+ decimals,
936
+ }
937
+ .pack();
938
+
939
+ let accounts = vec![AccountMeta::new(*mint_pubkey, false)];
940
+
941
+ Ok(Instruction {
942
+ program_id: *token_program_id,
943
+ accounts,
944
+ data,
945
+ })
946
+ }
947
+
948
+ /// Creates a `InitializeAccount` instruction.
949
+ pub fn initialize_account(
950
+ token_program_id: &Pubkey,
951
+ account_pubkey: &Pubkey,
952
+ mint_pubkey: &Pubkey,
953
+ owner_pubkey: &Pubkey,
954
+ ) -> Result<Instruction, ProgramError> {
955
+ check_program_account(token_program_id)?;
956
+ let data = TokenInstruction::InitializeAccount.pack();
957
+
958
+ let accounts = vec![
959
+ AccountMeta::new(*account_pubkey, false),
960
+ AccountMeta::new_readonly(*mint_pubkey, false),
961
+ AccountMeta::new_readonly(*owner_pubkey, false),
962
+ AccountMeta::new_readonly(sysvar::rent::id(), false),
963
+ ];
964
+
965
+ Ok(Instruction {
966
+ program_id: *token_program_id,
967
+ accounts,
968
+ data,
969
+ })
970
+ }
971
+
972
+ /// Creates a `InitializeAccount2` instruction.
973
+ pub fn initialize_account2(
974
+ token_program_id: &Pubkey,
975
+ account_pubkey: &Pubkey,
976
+ mint_pubkey: &Pubkey,
977
+ owner_pubkey: &Pubkey,
978
+ ) -> Result<Instruction, ProgramError> {
979
+ check_program_account(token_program_id)?;
980
+ let data = TokenInstruction::InitializeAccount2 {
981
+ owner: *owner_pubkey,
982
+ }
983
+ .pack();
984
+
985
+ let accounts = vec![
986
+ AccountMeta::new(*account_pubkey, false),
987
+ AccountMeta::new_readonly(*mint_pubkey, false),
988
+ AccountMeta::new_readonly(sysvar::rent::id(), false),
989
+ ];
990
+
991
+ Ok(Instruction {
992
+ program_id: *token_program_id,
993
+ accounts,
994
+ data,
995
+ })
996
+ }
997
+
998
+ /// Creates a `InitializeAccount3` instruction.
999
+ pub fn initialize_account3(
1000
+ token_program_id: &Pubkey,
1001
+ account_pubkey: &Pubkey,
1002
+ mint_pubkey: &Pubkey,
1003
+ owner_pubkey: &Pubkey,
1004
+ ) -> Result<Instruction, ProgramError> {
1005
+ check_program_account(token_program_id)?;
1006
+ let data = TokenInstruction::InitializeAccount3 {
1007
+ owner: *owner_pubkey,
1008
+ }
1009
+ .pack();
1010
+
1011
+ let accounts = vec![
1012
+ AccountMeta::new(*account_pubkey, false),
1013
+ AccountMeta::new_readonly(*mint_pubkey, false),
1014
+ ];
1015
+
1016
+ Ok(Instruction {
1017
+ program_id: *token_program_id,
1018
+ accounts,
1019
+ data,
1020
+ })
1021
+ }
1022
+
1023
+ /// Creates a `InitializeMultisig` instruction.
1024
+ pub fn initialize_multisig(
1025
+ token_program_id: &Pubkey,
1026
+ multisig_pubkey: &Pubkey,
1027
+ signer_pubkeys: &[&Pubkey],
1028
+ m: u8,
1029
+ ) -> Result<Instruction, ProgramError> {
1030
+ check_program_account(token_program_id)?;
1031
+ if !is_valid_signer_index(m as usize)
1032
+ || !is_valid_signer_index(signer_pubkeys.len())
1033
+ || m as usize > signer_pubkeys.len()
1034
+ {
1035
+ return Err(ProgramError::MissingRequiredSignature);
1036
+ }
1037
+ let data = TokenInstruction::InitializeMultisig { m }.pack();
1038
+
1039
+ let mut accounts = Vec::with_capacity(1 + 1 + signer_pubkeys.len());
1040
+ accounts.push(AccountMeta::new(*multisig_pubkey, false));
1041
+ accounts.push(AccountMeta::new_readonly(sysvar::rent::id(), false));
1042
+ for signer_pubkey in signer_pubkeys.iter() {
1043
+ accounts.push(AccountMeta::new_readonly(**signer_pubkey, false));
1044
+ }
1045
+
1046
+ Ok(Instruction {
1047
+ program_id: *token_program_id,
1048
+ accounts,
1049
+ data,
1050
+ })
1051
+ }
1052
+
1053
+ /// Creates a `InitializeMultisig2` instruction.
1054
+ pub fn initialize_multisig2(
1055
+ token_program_id: &Pubkey,
1056
+ multisig_pubkey: &Pubkey,
1057
+ signer_pubkeys: &[&Pubkey],
1058
+ m: u8,
1059
+ ) -> Result<Instruction, ProgramError> {
1060
+ check_program_account(token_program_id)?;
1061
+ if !is_valid_signer_index(m as usize)
1062
+ || !is_valid_signer_index(signer_pubkeys.len())
1063
+ || m as usize > signer_pubkeys.len()
1064
+ {
1065
+ return Err(ProgramError::MissingRequiredSignature);
1066
+ }
1067
+ let data = TokenInstruction::InitializeMultisig2 { m }.pack();
1068
+
1069
+ let mut accounts = Vec::with_capacity(1 + 1 + signer_pubkeys.len());
1070
+ accounts.push(AccountMeta::new(*multisig_pubkey, false));
1071
+ for signer_pubkey in signer_pubkeys.iter() {
1072
+ accounts.push(AccountMeta::new_readonly(**signer_pubkey, false));
1073
+ }
1074
+
1075
+ Ok(Instruction {
1076
+ program_id: *token_program_id,
1077
+ accounts,
1078
+ data,
1079
+ })
1080
+ }
1081
+
1082
+ /// Creates a `Transfer` instruction.
1083
+ pub fn transfer(
1084
+ token_program_id: &Pubkey,
1085
+ source_pubkey: &Pubkey,
1086
+ destination_pubkey: &Pubkey,
1087
+ authority_pubkey: &Pubkey,
1088
+ signer_pubkeys: &[&Pubkey],
1089
+ amount: u64,
1090
+ ) -> Result<Instruction, ProgramError> {
1091
+ check_program_account(token_program_id)?;
1092
+ let data = TokenInstruction::Transfer { amount }.pack();
1093
+
1094
+ let mut accounts = Vec::with_capacity(3 + signer_pubkeys.len());
1095
+ accounts.push(AccountMeta::new(*source_pubkey, false));
1096
+ accounts.push(AccountMeta::new(*destination_pubkey, false));
1097
+ accounts.push(AccountMeta::new_readonly(
1098
+ *authority_pubkey,
1099
+ signer_pubkeys.is_empty(),
1100
+ ));
1101
+ for signer_pubkey in signer_pubkeys.iter() {
1102
+ accounts.push(AccountMeta::new_readonly(**signer_pubkey, true));
1103
+ }
1104
+
1105
+ Ok(Instruction {
1106
+ program_id: *token_program_id,
1107
+ accounts,
1108
+ data,
1109
+ })
1110
+ }
1111
+
1112
+ /// Creates an `Approve` instruction.
1113
+ pub fn approve(
1114
+ token_program_id: &Pubkey,
1115
+ source_pubkey: &Pubkey,
1116
+ delegate_pubkey: &Pubkey,
1117
+ owner_pubkey: &Pubkey,
1118
+ signer_pubkeys: &[&Pubkey],
1119
+ amount: u64,
1120
+ ) -> Result<Instruction, ProgramError> {
1121
+ check_program_account(token_program_id)?;
1122
+ let data = TokenInstruction::Approve { amount }.pack();
1123
+
1124
+ let mut accounts = Vec::with_capacity(3 + signer_pubkeys.len());
1125
+ accounts.push(AccountMeta::new(*source_pubkey, false));
1126
+ accounts.push(AccountMeta::new_readonly(*delegate_pubkey, false));
1127
+ accounts.push(AccountMeta::new_readonly(
1128
+ *owner_pubkey,
1129
+ signer_pubkeys.is_empty(),
1130
+ ));
1131
+ for signer_pubkey in signer_pubkeys.iter() {
1132
+ accounts.push(AccountMeta::new_readonly(**signer_pubkey, true));
1133
+ }
1134
+
1135
+ Ok(Instruction {
1136
+ program_id: *token_program_id,
1137
+ accounts,
1138
+ data,
1139
+ })
1140
+ }
1141
+
1142
+ /// Creates a `Revoke` instruction.
1143
+ pub fn revoke(
1144
+ token_program_id: &Pubkey,
1145
+ source_pubkey: &Pubkey,
1146
+ owner_pubkey: &Pubkey,
1147
+ signer_pubkeys: &[&Pubkey],
1148
+ ) -> Result<Instruction, ProgramError> {
1149
+ check_program_account(token_program_id)?;
1150
+ let data = TokenInstruction::Revoke.pack();
1151
+
1152
+ let mut accounts = Vec::with_capacity(2 + signer_pubkeys.len());
1153
+ accounts.push(AccountMeta::new(*source_pubkey, false));
1154
+ accounts.push(AccountMeta::new_readonly(
1155
+ *owner_pubkey,
1156
+ signer_pubkeys.is_empty(),
1157
+ ));
1158
+ for signer_pubkey in signer_pubkeys.iter() {
1159
+ accounts.push(AccountMeta::new_readonly(**signer_pubkey, true));
1160
+ }
1161
+
1162
+ Ok(Instruction {
1163
+ program_id: *token_program_id,
1164
+ accounts,
1165
+ data,
1166
+ })
1167
+ }
1168
+
1169
+ /// Creates a `SetAuthority` instruction.
1170
+ pub fn set_authority(
1171
+ token_program_id: &Pubkey,
1172
+ owned_pubkey: &Pubkey,
1173
+ new_authority_pubkey: Option<&Pubkey>,
1174
+ authority_type: AuthorityType,
1175
+ owner_pubkey: &Pubkey,
1176
+ signer_pubkeys: &[&Pubkey],
1177
+ ) -> Result<Instruction, ProgramError> {
1178
+ check_program_account(token_program_id)?;
1179
+ let new_authority = new_authority_pubkey.cloned().into();
1180
+ let data = TokenInstruction::SetAuthority {
1181
+ authority_type,
1182
+ new_authority,
1183
+ }
1184
+ .pack();
1185
+
1186
+ let mut accounts = Vec::with_capacity(3 + signer_pubkeys.len());
1187
+ accounts.push(AccountMeta::new(*owned_pubkey, false));
1188
+ accounts.push(AccountMeta::new_readonly(
1189
+ *owner_pubkey,
1190
+ signer_pubkeys.is_empty(),
1191
+ ));
1192
+ for signer_pubkey in signer_pubkeys.iter() {
1193
+ accounts.push(AccountMeta::new_readonly(**signer_pubkey, true));
1194
+ }
1195
+
1196
+ Ok(Instruction {
1197
+ program_id: *token_program_id,
1198
+ accounts,
1199
+ data,
1200
+ })
1201
+ }
1202
+
1203
+ /// Creates a `MintTo` instruction.
1204
+ pub fn mint_to(
1205
+ token_program_id: &Pubkey,
1206
+ mint_pubkey: &Pubkey,
1207
+ account_pubkey: &Pubkey,
1208
+ owner_pubkey: &Pubkey,
1209
+ signer_pubkeys: &[&Pubkey],
1210
+ amount: u64,
1211
+ ) -> Result<Instruction, ProgramError> {
1212
+ check_program_account(token_program_id)?;
1213
+ let data = TokenInstruction::MintTo { amount }.pack();
1214
+
1215
+ let mut accounts = Vec::with_capacity(3 + signer_pubkeys.len());
1216
+ accounts.push(AccountMeta::new(*mint_pubkey, false));
1217
+ accounts.push(AccountMeta::new(*account_pubkey, false));
1218
+ accounts.push(AccountMeta::new_readonly(
1219
+ *owner_pubkey,
1220
+ signer_pubkeys.is_empty(),
1221
+ ));
1222
+ for signer_pubkey in signer_pubkeys.iter() {
1223
+ accounts.push(AccountMeta::new_readonly(**signer_pubkey, true));
1224
+ }
1225
+
1226
+ Ok(Instruction {
1227
+ program_id: *token_program_id,
1228
+ accounts,
1229
+ data,
1230
+ })
1231
+ }
1232
+
1233
+ /// Creates a `Burn` instruction.
1234
+ pub fn burn(
1235
+ token_program_id: &Pubkey,
1236
+ account_pubkey: &Pubkey,
1237
+ mint_pubkey: &Pubkey,
1238
+ authority_pubkey: &Pubkey,
1239
+ signer_pubkeys: &[&Pubkey],
1240
+ amount: u64,
1241
+ ) -> Result<Instruction, ProgramError> {
1242
+ check_program_account(token_program_id)?;
1243
+ let data = TokenInstruction::Burn { amount }.pack();
1244
+
1245
+ let mut accounts = Vec::with_capacity(3 + signer_pubkeys.len());
1246
+ accounts.push(AccountMeta::new(*account_pubkey, false));
1247
+ accounts.push(AccountMeta::new(*mint_pubkey, false));
1248
+ accounts.push(AccountMeta::new_readonly(
1249
+ *authority_pubkey,
1250
+ signer_pubkeys.is_empty(),
1251
+ ));
1252
+ for signer_pubkey in signer_pubkeys.iter() {
1253
+ accounts.push(AccountMeta::new_readonly(**signer_pubkey, true));
1254
+ }
1255
+
1256
+ Ok(Instruction {
1257
+ program_id: *token_program_id,
1258
+ accounts,
1259
+ data,
1260
+ })
1261
+ }
1262
+
1263
+ /// Creates a `CloseAccount` instruction.
1264
+ pub fn close_account(
1265
+ token_program_id: &Pubkey,
1266
+ account_pubkey: &Pubkey,
1267
+ destination_pubkey: &Pubkey,
1268
+ owner_pubkey: &Pubkey,
1269
+ signer_pubkeys: &[&Pubkey],
1270
+ ) -> Result<Instruction, ProgramError> {
1271
+ check_program_account(token_program_id)?;
1272
+ let data = TokenInstruction::CloseAccount.pack();
1273
+
1274
+ let mut accounts = Vec::with_capacity(3 + signer_pubkeys.len());
1275
+ accounts.push(AccountMeta::new(*account_pubkey, false));
1276
+ accounts.push(AccountMeta::new(*destination_pubkey, false));
1277
+ accounts.push(AccountMeta::new_readonly(
1278
+ *owner_pubkey,
1279
+ signer_pubkeys.is_empty(),
1280
+ ));
1281
+ for signer_pubkey in signer_pubkeys.iter() {
1282
+ accounts.push(AccountMeta::new_readonly(**signer_pubkey, true));
1283
+ }
1284
+
1285
+ Ok(Instruction {
1286
+ program_id: *token_program_id,
1287
+ accounts,
1288
+ data,
1289
+ })
1290
+ }
1291
+
1292
+ /// Creates a `FreezeAccount` instruction.
1293
+ pub fn freeze_account(
1294
+ token_program_id: &Pubkey,
1295
+ account_pubkey: &Pubkey,
1296
+ mint_pubkey: &Pubkey,
1297
+ owner_pubkey: &Pubkey,
1298
+ signer_pubkeys: &[&Pubkey],
1299
+ ) -> Result<Instruction, ProgramError> {
1300
+ check_program_account(token_program_id)?;
1301
+ let data = TokenInstruction::FreezeAccount.pack();
1302
+
1303
+ let mut accounts = Vec::with_capacity(3 + signer_pubkeys.len());
1304
+ accounts.push(AccountMeta::new(*account_pubkey, false));
1305
+ accounts.push(AccountMeta::new_readonly(*mint_pubkey, false));
1306
+ accounts.push(AccountMeta::new_readonly(
1307
+ *owner_pubkey,
1308
+ signer_pubkeys.is_empty(),
1309
+ ));
1310
+ for signer_pubkey in signer_pubkeys.iter() {
1311
+ accounts.push(AccountMeta::new_readonly(**signer_pubkey, true));
1312
+ }
1313
+
1314
+ Ok(Instruction {
1315
+ program_id: *token_program_id,
1316
+ accounts,
1317
+ data,
1318
+ })
1319
+ }
1320
+
1321
+ /// Creates a `ThawAccount` instruction.
1322
+ pub fn thaw_account(
1323
+ token_program_id: &Pubkey,
1324
+ account_pubkey: &Pubkey,
1325
+ mint_pubkey: &Pubkey,
1326
+ owner_pubkey: &Pubkey,
1327
+ signer_pubkeys: &[&Pubkey],
1328
+ ) -> Result<Instruction, ProgramError> {
1329
+ check_program_account(token_program_id)?;
1330
+ let data = TokenInstruction::ThawAccount.pack();
1331
+
1332
+ let mut accounts = Vec::with_capacity(3 + signer_pubkeys.len());
1333
+ accounts.push(AccountMeta::new(*account_pubkey, false));
1334
+ accounts.push(AccountMeta::new_readonly(*mint_pubkey, false));
1335
+ accounts.push(AccountMeta::new_readonly(
1336
+ *owner_pubkey,
1337
+ signer_pubkeys.is_empty(),
1338
+ ));
1339
+ for signer_pubkey in signer_pubkeys.iter() {
1340
+ accounts.push(AccountMeta::new_readonly(**signer_pubkey, true));
1341
+ }
1342
+
1343
+ Ok(Instruction {
1344
+ program_id: *token_program_id,
1345
+ accounts,
1346
+ data,
1347
+ })
1348
+ }
1349
+
1350
+ /// Creates a `TransferChecked` instruction.
1351
+ #[allow(clippy::too_many_arguments)]
1352
+ pub fn transfer_checked(
1353
+ token_program_id: &Pubkey,
1354
+ source_pubkey: &Pubkey,
1355
+ mint_pubkey: &Pubkey,
1356
+ destination_pubkey: &Pubkey,
1357
+ authority_pubkey: &Pubkey,
1358
+ signer_pubkeys: &[&Pubkey],
1359
+ amount: u64,
1360
+ decimals: u8,
1361
+ ) -> Result<Instruction, ProgramError> {
1362
+ check_program_account(token_program_id)?;
1363
+ let data = TokenInstruction::TransferChecked { amount, decimals }.pack();
1364
+
1365
+ let mut accounts = Vec::with_capacity(4 + signer_pubkeys.len());
1366
+ accounts.push(AccountMeta::new(*source_pubkey, false));
1367
+ accounts.push(AccountMeta::new_readonly(*mint_pubkey, false));
1368
+ accounts.push(AccountMeta::new(*destination_pubkey, false));
1369
+ accounts.push(AccountMeta::new_readonly(
1370
+ *authority_pubkey,
1371
+ signer_pubkeys.is_empty(),
1372
+ ));
1373
+ for signer_pubkey in signer_pubkeys.iter() {
1374
+ accounts.push(AccountMeta::new_readonly(**signer_pubkey, true));
1375
+ }
1376
+
1377
+ Ok(Instruction {
1378
+ program_id: *token_program_id,
1379
+ accounts,
1380
+ data,
1381
+ })
1382
+ }
1383
+
1384
+ /// Creates an `ApproveChecked` instruction.
1385
+ #[allow(clippy::too_many_arguments)]
1386
+ pub fn approve_checked(
1387
+ token_program_id: &Pubkey,
1388
+ source_pubkey: &Pubkey,
1389
+ mint_pubkey: &Pubkey,
1390
+ delegate_pubkey: &Pubkey,
1391
+ owner_pubkey: &Pubkey,
1392
+ signer_pubkeys: &[&Pubkey],
1393
+ amount: u64,
1394
+ decimals: u8,
1395
+ ) -> Result<Instruction, ProgramError> {
1396
+ check_program_account(token_program_id)?;
1397
+ let data = TokenInstruction::ApproveChecked { amount, decimals }.pack();
1398
+
1399
+ let mut accounts = Vec::with_capacity(4 + signer_pubkeys.len());
1400
+ accounts.push(AccountMeta::new(*source_pubkey, false));
1401
+ accounts.push(AccountMeta::new_readonly(*mint_pubkey, false));
1402
+ accounts.push(AccountMeta::new_readonly(*delegate_pubkey, false));
1403
+ accounts.push(AccountMeta::new_readonly(
1404
+ *owner_pubkey,
1405
+ signer_pubkeys.is_empty(),
1406
+ ));
1407
+ for signer_pubkey in signer_pubkeys.iter() {
1408
+ accounts.push(AccountMeta::new_readonly(**signer_pubkey, true));
1409
+ }
1410
+
1411
+ Ok(Instruction {
1412
+ program_id: *token_program_id,
1413
+ accounts,
1414
+ data,
1415
+ })
1416
+ }
1417
+
1418
+ /// Creates a `MintToChecked` instruction.
1419
+ pub fn mint_to_checked(
1420
+ token_program_id: &Pubkey,
1421
+ mint_pubkey: &Pubkey,
1422
+ account_pubkey: &Pubkey,
1423
+ owner_pubkey: &Pubkey,
1424
+ signer_pubkeys: &[&Pubkey],
1425
+ amount: u64,
1426
+ decimals: u8,
1427
+ ) -> Result<Instruction, ProgramError> {
1428
+ check_program_account(token_program_id)?;
1429
+ let data = TokenInstruction::MintToChecked { amount, decimals }.pack();
1430
+
1431
+ let mut accounts = Vec::with_capacity(3 + signer_pubkeys.len());
1432
+ accounts.push(AccountMeta::new(*mint_pubkey, false));
1433
+ accounts.push(AccountMeta::new(*account_pubkey, false));
1434
+ accounts.push(AccountMeta::new_readonly(
1435
+ *owner_pubkey,
1436
+ signer_pubkeys.is_empty(),
1437
+ ));
1438
+ for signer_pubkey in signer_pubkeys.iter() {
1439
+ accounts.push(AccountMeta::new_readonly(**signer_pubkey, true));
1440
+ }
1441
+
1442
+ Ok(Instruction {
1443
+ program_id: *token_program_id,
1444
+ accounts,
1445
+ data,
1446
+ })
1447
+ }
1448
+
1449
+ /// Creates a `BurnChecked` instruction.
1450
+ pub fn burn_checked(
1451
+ token_program_id: &Pubkey,
1452
+ account_pubkey: &Pubkey,
1453
+ mint_pubkey: &Pubkey,
1454
+ authority_pubkey: &Pubkey,
1455
+ signer_pubkeys: &[&Pubkey],
1456
+ amount: u64,
1457
+ decimals: u8,
1458
+ ) -> Result<Instruction, ProgramError> {
1459
+ check_program_account(token_program_id)?;
1460
+ let data = TokenInstruction::BurnChecked { amount, decimals }.pack();
1461
+
1462
+ let mut accounts = Vec::with_capacity(3 + signer_pubkeys.len());
1463
+ accounts.push(AccountMeta::new(*account_pubkey, false));
1464
+ accounts.push(AccountMeta::new(*mint_pubkey, false));
1465
+ accounts.push(AccountMeta::new_readonly(
1466
+ *authority_pubkey,
1467
+ signer_pubkeys.is_empty(),
1468
+ ));
1469
+ for signer_pubkey in signer_pubkeys.iter() {
1470
+ accounts.push(AccountMeta::new_readonly(**signer_pubkey, true));
1471
+ }
1472
+
1473
+ Ok(Instruction {
1474
+ program_id: *token_program_id,
1475
+ accounts,
1476
+ data,
1477
+ })
1478
+ }
1479
+
1480
+ /// Creates a `SyncNative` instruction
1481
+ pub fn sync_native(
1482
+ token_program_id: &Pubkey,
1483
+ account_pubkey: &Pubkey,
1484
+ ) -> Result<Instruction, ProgramError> {
1485
+ check_program_account(token_program_id)?;
1486
+
1487
+ Ok(Instruction {
1488
+ program_id: *token_program_id,
1489
+ accounts: vec![AccountMeta::new(*account_pubkey, false)],
1490
+ data: TokenInstruction::SyncNative.pack(),
1491
+ })
1492
+ }
1493
+
1494
+ /// Creates a `SyncNative` instruction with the Rent sysvar account
1495
+ /// added to the accounts list.
1496
+ pub fn sync_native_with_rent_sysvar(
1497
+ token_program_id: &Pubkey,
1498
+ account_pubkey: &Pubkey,
1499
+ ) -> Result<Instruction, ProgramError> {
1500
+ let mut instruction = sync_native(token_program_id, account_pubkey)?;
1501
+ instruction
1502
+ .accounts
1503
+ .push(AccountMeta::new_readonly(sysvar::rent::id(), false));
1504
+
1505
+ Ok(instruction)
1506
+ }
1507
+
1508
+ /// Creates a `GetAccountDataSize` instruction
1509
+ pub fn get_account_data_size(
1510
+ token_program_id: &Pubkey,
1511
+ mint_pubkey: &Pubkey,
1512
+ ) -> Result<Instruction, ProgramError> {
1513
+ check_program_account(token_program_id)?;
1514
+
1515
+ Ok(Instruction {
1516
+ program_id: *token_program_id,
1517
+ accounts: vec![AccountMeta::new_readonly(*mint_pubkey, false)],
1518
+ data: TokenInstruction::GetAccountDataSize.pack(),
1519
+ })
1520
+ }
1521
+
1522
+ /// Creates a `InitializeImmutableOwner` instruction
1523
+ pub fn initialize_immutable_owner(
1524
+ token_program_id: &Pubkey,
1525
+ account_pubkey: &Pubkey,
1526
+ ) -> Result<Instruction, ProgramError> {
1527
+ check_program_account(token_program_id)?;
1528
+ Ok(Instruction {
1529
+ program_id: *token_program_id,
1530
+ accounts: vec![AccountMeta::new(*account_pubkey, false)],
1531
+ data: TokenInstruction::InitializeImmutableOwner.pack(),
1532
+ })
1533
+ }
1534
+
1535
+ /// Creates an `AmountToUiAmount` instruction
1536
+ pub fn amount_to_ui_amount(
1537
+ token_program_id: &Pubkey,
1538
+ mint_pubkey: &Pubkey,
1539
+ amount: u64,
1540
+ ) -> Result<Instruction, ProgramError> {
1541
+ check_program_account(token_program_id)?;
1542
+
1543
+ Ok(Instruction {
1544
+ program_id: *token_program_id,
1545
+ accounts: vec![AccountMeta::new_readonly(*mint_pubkey, false)],
1546
+ data: TokenInstruction::AmountToUiAmount { amount }.pack(),
1547
+ })
1548
+ }
1549
+
1550
+ /// Creates a `UiAmountToAmount` instruction
1551
+ pub fn ui_amount_to_amount(
1552
+ token_program_id: &Pubkey,
1553
+ mint_pubkey: &Pubkey,
1554
+ ui_amount: &str,
1555
+ ) -> Result<Instruction, ProgramError> {
1556
+ check_program_account(token_program_id)?;
1557
+
1558
+ Ok(Instruction {
1559
+ program_id: *token_program_id,
1560
+ accounts: vec![AccountMeta::new_readonly(*mint_pubkey, false)],
1561
+ data: TokenInstruction::UiAmountToAmount { ui_amount }.pack(),
1562
+ })
1563
+ }
1564
+
1565
+ /// Creates a `WithdrawExcessLamports` instruction
1566
+ pub fn withdraw_excess_lamports(
1567
+ token_program_id: &Pubkey,
1568
+ account_pubkey: &Pubkey,
1569
+ destination_pubkey: &Pubkey,
1570
+ authority_pubkey: &Pubkey,
1571
+ signer_pubkeys: &[&Pubkey],
1572
+ ) -> Result<Instruction, ProgramError> {
1573
+ check_program_account(token_program_id)?;
1574
+ let data = TokenInstruction::WithdrawExcessLamports.pack();
1575
+
1576
+ let mut accounts = Vec::with_capacity(3 + signer_pubkeys.len());
1577
+ accounts.push(AccountMeta::new(*account_pubkey, false));
1578
+ accounts.push(AccountMeta::new(*destination_pubkey, false));
1579
+ accounts.push(AccountMeta::new_readonly(
1580
+ *authority_pubkey,
1581
+ signer_pubkeys.is_empty(),
1582
+ ));
1583
+ for signer_pubkey in signer_pubkeys.iter() {
1584
+ accounts.push(AccountMeta::new_readonly(**signer_pubkey, true));
1585
+ }
1586
+
1587
+ Ok(Instruction {
1588
+ program_id: *token_program_id,
1589
+ accounts,
1590
+ data,
1591
+ })
1592
+ }
1593
+
1594
+ /// Creates a `UnwrapLamports` instruction
1595
+ pub fn unwrap_lamports(
1596
+ token_program_id: &Pubkey,
1597
+ account_pubkey: &Pubkey,
1598
+ destination_pubkey: &Pubkey,
1599
+ authority_pubkey: &Pubkey,
1600
+ signer_pubkeys: &[&Pubkey],
1601
+ amount: Option<u64>,
1602
+ ) -> Result<Instruction, ProgramError> {
1603
+ check_program_account(token_program_id)?;
1604
+
1605
+ let amount = amount.into();
1606
+ let data = TokenInstruction::UnwrapLamports { amount }.pack();
1607
+
1608
+ let mut accounts = Vec::with_capacity(3 + signer_pubkeys.len());
1609
+ accounts.push(AccountMeta::new(*account_pubkey, false));
1610
+ accounts.push(AccountMeta::new(*destination_pubkey, false));
1611
+ accounts.push(AccountMeta::new_readonly(
1612
+ *authority_pubkey,
1613
+ signer_pubkeys.is_empty(),
1614
+ ));
1615
+ for signer_pubkey in signer_pubkeys.iter() {
1616
+ accounts.push(AccountMeta::new_readonly(**signer_pubkey, true));
1617
+ }
1618
+
1619
+ Ok(Instruction {
1620
+ program_id: *token_program_id,
1621
+ accounts,
1622
+ data,
1623
+ })
1624
+ }
1625
+
1626
+ /// Creates a `Batch` instruction
1627
+ pub fn batch(
1628
+ token_program_id: &Pubkey,
1629
+ instructions: &[Instruction],
1630
+ ) -> Result<Instruction, ProgramError> {
1631
+ check_program_account(token_program_id)?;
1632
+
1633
+ let mut data: Vec<u8> = TokenInstruction::Batch.pack();
1634
+ let mut accounts: Vec<AccountMeta> = vec![];
1635
+
1636
+ for instruction in instructions {
1637
+ if token_program_id != &instruction.program_id {
1638
+ return Err(ProgramError::IncorrectProgramId);
1639
+ }
1640
+
1641
+ data.push(instruction.accounts.len() as u8);
1642
+
1643
+ if instruction.data.len() > u8::MAX as usize {
1644
+ return Err(ProgramError::InvalidInstructionData);
1645
+ }
1646
+
1647
+ data.push(instruction.data.len() as u8);
1648
+
1649
+ data.extend_from_slice(&instruction.data);
1650
+ accounts.extend_from_slice(&instruction.accounts);
1651
+ }
1652
+
1653
+ Ok(Instruction {
1654
+ program_id: *token_program_id,
1655
+ data,
1656
+ accounts,
1657
+ })
1658
+ }
1659
+
1660
+ /// Utility function that checks index is between `MIN_SIGNERS` and
1661
+ /// `MAX_SIGNERS`
1662
+ pub fn is_valid_signer_index(index: usize) -> bool {
1663
+ (MIN_SIGNERS..=MAX_SIGNERS).contains(&index)
1664
+ }
1665
+
1666
+ #[cfg(test)]
1667
+ mod test {
1668
+ use {super::*, proptest::prelude::*};
1669
+
1670
+ #[test]
1671
+ fn test_instruction_packing() {
1672
+ let check = TokenInstruction::InitializeMint {
1673
+ decimals: 2,
1674
+ mint_authority: Pubkey::new_from_array([1u8; 32]),
1675
+ freeze_authority: COption::None,
1676
+ };
1677
+ let packed = check.pack();
1678
+ let mut expect = Vec::from([0u8, 2]);
1679
+ expect.extend_from_slice(&[1u8; 32]);
1680
+ expect.extend_from_slice(&[0]);
1681
+ assert_eq!(packed, expect);
1682
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
1683
+ assert_eq!(unpacked, check);
1684
+
1685
+ let check = TokenInstruction::InitializeMint {
1686
+ decimals: 2,
1687
+ mint_authority: Pubkey::new_from_array([2u8; 32]),
1688
+ freeze_authority: COption::Some(Pubkey::new_from_array([3u8; 32])),
1689
+ };
1690
+ let packed = check.pack();
1691
+ let mut expect = vec![0u8, 2];
1692
+ expect.extend_from_slice(&[2u8; 32]);
1693
+ expect.extend_from_slice(&[1]);
1694
+ expect.extend_from_slice(&[3u8; 32]);
1695
+ assert_eq!(packed, expect);
1696
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
1697
+ assert_eq!(unpacked, check);
1698
+
1699
+ let check = TokenInstruction::InitializeAccount;
1700
+ let packed = check.pack();
1701
+ let expect = Vec::from([1u8]);
1702
+ assert_eq!(packed, expect);
1703
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
1704
+ assert_eq!(unpacked, check);
1705
+
1706
+ let check = TokenInstruction::InitializeMultisig { m: 1 };
1707
+ let packed = check.pack();
1708
+ let expect = Vec::from([2u8, 1]);
1709
+ assert_eq!(packed, expect);
1710
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
1711
+ assert_eq!(unpacked, check);
1712
+
1713
+ let check = TokenInstruction::Transfer { amount: 1 };
1714
+ let packed = check.pack();
1715
+ let expect = Vec::from([3u8, 1, 0, 0, 0, 0, 0, 0, 0]);
1716
+ assert_eq!(packed, expect);
1717
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
1718
+ assert_eq!(unpacked, check);
1719
+
1720
+ let check = TokenInstruction::Approve { amount: 1 };
1721
+ let packed = check.pack();
1722
+ let expect = Vec::from([4u8, 1, 0, 0, 0, 0, 0, 0, 0]);
1723
+ assert_eq!(packed, expect);
1724
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
1725
+ assert_eq!(unpacked, check);
1726
+
1727
+ let check = TokenInstruction::Revoke;
1728
+ let packed = check.pack();
1729
+ let expect = Vec::from([5u8]);
1730
+ assert_eq!(packed, expect);
1731
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
1732
+ assert_eq!(unpacked, check);
1733
+
1734
+ let check = TokenInstruction::SetAuthority {
1735
+ authority_type: AuthorityType::FreezeAccount,
1736
+ new_authority: COption::Some(Pubkey::new_from_array([4u8; 32])),
1737
+ };
1738
+ let packed = check.pack();
1739
+ let mut expect = Vec::from([6u8, 1]);
1740
+ expect.extend_from_slice(&[1]);
1741
+ expect.extend_from_slice(&[4u8; 32]);
1742
+ assert_eq!(packed, expect);
1743
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
1744
+ assert_eq!(unpacked, check);
1745
+
1746
+ let check = TokenInstruction::MintTo { amount: 1 };
1747
+ let packed = check.pack();
1748
+ let expect = Vec::from([7u8, 1, 0, 0, 0, 0, 0, 0, 0]);
1749
+ assert_eq!(packed, expect);
1750
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
1751
+ assert_eq!(unpacked, check);
1752
+
1753
+ let check = TokenInstruction::Burn { amount: 1 };
1754
+ let packed = check.pack();
1755
+ let expect = Vec::from([8u8, 1, 0, 0, 0, 0, 0, 0, 0]);
1756
+ assert_eq!(packed, expect);
1757
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
1758
+ assert_eq!(unpacked, check);
1759
+
1760
+ let check = TokenInstruction::CloseAccount;
1761
+ let packed = check.pack();
1762
+ let expect = Vec::from([9u8]);
1763
+ assert_eq!(packed, expect);
1764
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
1765
+ assert_eq!(unpacked, check);
1766
+
1767
+ let check = TokenInstruction::FreezeAccount;
1768
+ let packed = check.pack();
1769
+ let expect = Vec::from([10u8]);
1770
+ assert_eq!(packed, expect);
1771
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
1772
+ assert_eq!(unpacked, check);
1773
+
1774
+ let check = TokenInstruction::ThawAccount;
1775
+ let packed = check.pack();
1776
+ let expect = Vec::from([11u8]);
1777
+ assert_eq!(packed, expect);
1778
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
1779
+ assert_eq!(unpacked, check);
1780
+
1781
+ let check = TokenInstruction::TransferChecked {
1782
+ amount: 1,
1783
+ decimals: 2,
1784
+ };
1785
+ let packed = check.pack();
1786
+ let expect = Vec::from([12u8, 1, 0, 0, 0, 0, 0, 0, 0, 2]);
1787
+ assert_eq!(packed, expect);
1788
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
1789
+ assert_eq!(unpacked, check);
1790
+
1791
+ let check = TokenInstruction::ApproveChecked {
1792
+ amount: 1,
1793
+ decimals: 2,
1794
+ };
1795
+ let packed = check.pack();
1796
+ let expect = Vec::from([13u8, 1, 0, 0, 0, 0, 0, 0, 0, 2]);
1797
+ assert_eq!(packed, expect);
1798
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
1799
+ assert_eq!(unpacked, check);
1800
+
1801
+ let check = TokenInstruction::MintToChecked {
1802
+ amount: 1,
1803
+ decimals: 2,
1804
+ };
1805
+ let packed = check.pack();
1806
+ let expect = Vec::from([14u8, 1, 0, 0, 0, 0, 0, 0, 0, 2]);
1807
+ assert_eq!(packed, expect);
1808
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
1809
+ assert_eq!(unpacked, check);
1810
+
1811
+ let check = TokenInstruction::BurnChecked {
1812
+ amount: 1,
1813
+ decimals: 2,
1814
+ };
1815
+ let packed = check.pack();
1816
+ let expect = Vec::from([15u8, 1, 0, 0, 0, 0, 0, 0, 0, 2]);
1817
+ assert_eq!(packed, expect);
1818
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
1819
+ assert_eq!(unpacked, check);
1820
+
1821
+ let check = TokenInstruction::InitializeAccount2 {
1822
+ owner: Pubkey::new_from_array([2u8; 32]),
1823
+ };
1824
+ let packed = check.pack();
1825
+ let mut expect = vec![16u8];
1826
+ expect.extend_from_slice(&[2u8; 32]);
1827
+ assert_eq!(packed, expect);
1828
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
1829
+ assert_eq!(unpacked, check);
1830
+
1831
+ let check = TokenInstruction::SyncNative;
1832
+ let packed = check.pack();
1833
+ let expect = vec![17u8];
1834
+ assert_eq!(packed, expect);
1835
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
1836
+ assert_eq!(unpacked, check);
1837
+
1838
+ let check = TokenInstruction::InitializeAccount3 {
1839
+ owner: Pubkey::new_from_array([2u8; 32]),
1840
+ };
1841
+ let packed = check.pack();
1842
+ let mut expect = vec![18u8];
1843
+ expect.extend_from_slice(&[2u8; 32]);
1844
+ assert_eq!(packed, expect);
1845
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
1846
+ assert_eq!(unpacked, check);
1847
+
1848
+ let check = TokenInstruction::InitializeMultisig2 { m: 1 };
1849
+ let packed = check.pack();
1850
+ let expect = Vec::from([19u8, 1]);
1851
+ assert_eq!(packed, expect);
1852
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
1853
+ assert_eq!(unpacked, check);
1854
+
1855
+ let check = TokenInstruction::InitializeMint2 {
1856
+ decimals: 2,
1857
+ mint_authority: Pubkey::new_from_array([1u8; 32]),
1858
+ freeze_authority: COption::None,
1859
+ };
1860
+ let packed = check.pack();
1861
+ let mut expect = Vec::from([20u8, 2]);
1862
+ expect.extend_from_slice(&[1u8; 32]);
1863
+ expect.extend_from_slice(&[0]);
1864
+ assert_eq!(packed, expect);
1865
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
1866
+ assert_eq!(unpacked, check);
1867
+
1868
+ let check = TokenInstruction::InitializeMint2 {
1869
+ decimals: 2,
1870
+ mint_authority: Pubkey::new_from_array([2u8; 32]),
1871
+ freeze_authority: COption::Some(Pubkey::new_from_array([3u8; 32])),
1872
+ };
1873
+ let packed = check.pack();
1874
+ let mut expect = vec![20u8, 2];
1875
+ expect.extend_from_slice(&[2u8; 32]);
1876
+ expect.extend_from_slice(&[1]);
1877
+ expect.extend_from_slice(&[3u8; 32]);
1878
+ assert_eq!(packed, expect);
1879
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
1880
+ assert_eq!(unpacked, check);
1881
+
1882
+ let check = TokenInstruction::GetAccountDataSize;
1883
+ let packed = check.pack();
1884
+ let expect = vec![21u8];
1885
+ assert_eq!(packed, expect);
1886
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
1887
+ assert_eq!(unpacked, check);
1888
+
1889
+ let check = TokenInstruction::InitializeImmutableOwner;
1890
+ let packed = check.pack();
1891
+ let expect = vec![22u8];
1892
+ assert_eq!(packed, expect);
1893
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
1894
+ assert_eq!(unpacked, check);
1895
+
1896
+ let check = TokenInstruction::AmountToUiAmount { amount: 42 };
1897
+ let packed = check.pack();
1898
+ let expect = vec![23u8, 42, 0, 0, 0, 0, 0, 0, 0];
1899
+ assert_eq!(packed, expect);
1900
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
1901
+ assert_eq!(unpacked, check);
1902
+
1903
+ let check = TokenInstruction::UiAmountToAmount { ui_amount: "0.42" };
1904
+ let packed = check.pack();
1905
+ let expect = vec![24u8, 48, 46, 52, 50];
1906
+ assert_eq!(packed, expect);
1907
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
1908
+ assert_eq!(unpacked, check);
1909
+
1910
+ let check = TokenInstruction::WithdrawExcessLamports;
1911
+ let packed = check.pack();
1912
+ let expect = vec![38u8];
1913
+ assert_eq!(packed, expect);
1914
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
1915
+ assert_eq!(unpacked, check);
1916
+
1917
+ let check = TokenInstruction::UnwrapLamports {
1918
+ amount: COption::Some(42),
1919
+ };
1920
+ let packed = check.pack();
1921
+ let expect = vec![45u8, 1, 42, 0, 0, 0, 0, 0, 0, 0];
1922
+ assert_eq!(packed, expect);
1923
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
1924
+ assert_eq!(unpacked, check);
1925
+
1926
+ let check = TokenInstruction::UnwrapLamports {
1927
+ amount: COption::None,
1928
+ };
1929
+ let packed = check.pack();
1930
+ let expect = vec![45u8, 0];
1931
+ assert_eq!(packed, expect);
1932
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
1933
+ assert_eq!(unpacked, check);
1934
+
1935
+ let check = TokenInstruction::Batch;
1936
+ let packed = check.pack();
1937
+ let expect = vec![255u8];
1938
+ assert_eq!(packed, expect);
1939
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
1940
+ assert_eq!(unpacked, check);
1941
+ }
1942
+
1943
+ #[test]
1944
+ fn test_instruction_unpack_panic() {
1945
+ for i in 0..255u8 {
1946
+ for j in 1..10 {
1947
+ let mut data = vec![0; j];
1948
+ data[0] = i;
1949
+ let _no_panic = TokenInstruction::unpack(&data);
1950
+ }
1951
+ }
1952
+ }
1953
+
1954
+ proptest! {
1955
+ #![proptest_config(ProptestConfig::with_cases(1024))]
1956
+ #[test]
1957
+ fn test_instruction_unpack_proptest(
1958
+ data in prop::collection::vec(any::<u8>(), 0..255)
1959
+ ) {
1960
+ let _no_panic = TokenInstruction::unpack(&data);
1961
+ }
1962
+ }
1963
+ }