sememe 0.0.0-stage → 0.4.22

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 +2777 -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 +206 -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 +1118 -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 +180 -0
  29. package/src/discriminators.mjs +192 -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 +454 -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 +253 -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,2868 @@
1
+ //! Instruction types
2
+
3
+ // Needed to avoid deprecation warning when generating serde implementation for
4
+ // TokenInstruction
5
+ #![allow(deprecated)]
6
+
7
+ #[cfg(feature = "serde")]
8
+ use {
9
+ crate::serialization::{batch_fromstr, coption_fromstr, coption_u64_fromval},
10
+ serde::{Deserialize, Serialize},
11
+ serde_with::{As, DisplayFromStr},
12
+ };
13
+ use {
14
+ crate::{
15
+ check_program_account, check_spl_token_program_account, error::TokenError,
16
+ extension::ExtensionType,
17
+ },
18
+ alloc::{vec, vec::Vec},
19
+ bytemuck::Pod,
20
+ core::{
21
+ convert::{TryFrom, TryInto},
22
+ mem::size_of,
23
+ },
24
+ solana_address::{Address, ADDRESS_BYTES},
25
+ solana_instruction::{AccountMeta, Instruction},
26
+ solana_program_error::ProgramError,
27
+ solana_program_option::COption,
28
+ solana_sdk_ids::{system_program, sysvar},
29
+ };
30
+
31
+ /// Minimum number of multisignature signers (min N)
32
+ pub const MIN_SIGNERS: usize = 1;
33
+ /// Maximum number of multisignature signers (max N)
34
+ pub const MAX_SIGNERS: usize = 11;
35
+ /// Serialized length of a `u16`, for unpacking
36
+ const U16_BYTES: usize = 2;
37
+ /// Serialized length of a `u64`, for unpacking
38
+ const U64_BYTES: usize = 8;
39
+
40
+ /// Instructions supported by the token program.
41
+ #[repr(C)]
42
+ #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
43
+ #[cfg_attr(
44
+ feature = "serde",
45
+ serde(rename_all_fields = "camelCase", rename_all = "camelCase")
46
+ )]
47
+ #[derive(Clone, Debug, PartialEq)]
48
+ pub enum TokenInstruction<'a> {
49
+ // 0
50
+ /// Initializes a new mint and optionally deposits all the newly minted
51
+ /// tokens in an account.
52
+ ///
53
+ /// The `InitializeMint` instruction requires no signers and MUST be
54
+ /// included within the same Transaction as the system program's
55
+ /// `CreateAccount` instruction that creates the account being initialized.
56
+ /// Otherwise another party can acquire ownership of the uninitialized
57
+ /// account.
58
+ ///
59
+ /// All extensions must be initialized before calling this instruction.
60
+ ///
61
+ /// Accounts expected by this instruction:
62
+ ///
63
+ /// 0. `[writable]` The mint to initialize.
64
+ /// 1. `[]` Rent sysvar
65
+ InitializeMint {
66
+ /// Number of base 10 digits to the right of the decimal place.
67
+ decimals: u8,
68
+ /// The authority/multisignature to mint tokens.
69
+ #[cfg_attr(feature = "serde", serde(with = "As::<DisplayFromStr>"))]
70
+ mint_authority: Address,
71
+ /// The freeze authority/multisignature of the mint.
72
+ #[cfg_attr(feature = "serde", serde(with = "coption_fromstr"))]
73
+ freeze_authority: COption<Address>,
74
+ },
75
+ /// Initializes a new account to hold tokens. If this account is associated
76
+ /// with the native mint then the token balance of the initialized account
77
+ /// will be equal to the amount of SOL in the account. If this account is
78
+ /// associated with another mint, that mint must be initialized before this
79
+ /// command can succeed.
80
+ ///
81
+ /// The `InitializeAccount` instruction requires no signers and MUST be
82
+ /// included within the same Transaction as the system program's
83
+ /// `CreateAccount` instruction that creates the account being initialized.
84
+ /// Otherwise another party can acquire ownership of the uninitialized
85
+ /// account.
86
+ ///
87
+ /// Accounts expected by this instruction:
88
+ ///
89
+ /// 0. `[writable]` The account to initialize.
90
+ /// 1. `[]` The mint this account will be associated with.
91
+ /// 2. `[]` The new account's owner/multisignature.
92
+ /// 3. `[]` Rent sysvar
93
+ InitializeAccount,
94
+ /// Initializes a multisignature account with N provided signers.
95
+ ///
96
+ /// Multisignature accounts can used in place of any single owner/delegate
97
+ /// accounts in any token instruction that require an owner/delegate to be
98
+ /// present. The variant field represents the number of signers (M)
99
+ /// required to validate this multisignature account.
100
+ ///
101
+ /// The `InitializeMultisig` instruction requires no signers and MUST be
102
+ /// included within the same Transaction as the system program's
103
+ /// `CreateAccount` instruction that creates the account being initialized.
104
+ /// Otherwise another party can acquire ownership of the uninitialized
105
+ /// account.
106
+ ///
107
+ /// Accounts expected by this instruction:
108
+ ///
109
+ /// 0. `[writable]` The multisignature account to initialize.
110
+ /// 1. `[]` Rent sysvar
111
+ /// 2. ..`2+N`. `[]` The signer accounts, must equal to N where `1 <= N <=
112
+ /// 11`.
113
+ InitializeMultisig {
114
+ /// The number of signers (M) required to validate this multisignature
115
+ /// account.
116
+ m: u8,
117
+ },
118
+ /// NOTE This instruction is deprecated in favor of `TransferChecked` or
119
+ /// `TransferCheckedWithFee`
120
+ ///
121
+ /// Transfers tokens from one account to another either directly or via a
122
+ /// delegate. If this account is associated with the native mint then equal
123
+ /// amounts of SOL and Tokens will be transferred to the destination
124
+ /// account.
125
+ ///
126
+ /// If either account contains an `TransferFeeAmount` extension, this will
127
+ /// fail. Mints with the `TransferFeeConfig` extension are required in
128
+ /// order to assess the fee.
129
+ ///
130
+ /// Accounts expected by this instruction:
131
+ ///
132
+ /// * Single owner/delegate
133
+ /// 0. `[writable]` The source account.
134
+ /// 1. `[writable]` The destination account.
135
+ /// 2. `[signer]` The source account's owner/delegate.
136
+ ///
137
+ /// * Multisignature owner/delegate
138
+ /// 0. `[writable]` The source account.
139
+ /// 1. `[writable]` The destination account.
140
+ /// 2. `[]` The source account's multisignature owner/delegate.
141
+ /// 3. ..`3+M` `[signer]` M signer accounts.
142
+ #[deprecated(
143
+ since = "4.0.0",
144
+ note = "please use `TransferChecked` or `TransferCheckedWithFee` instead"
145
+ )]
146
+ Transfer {
147
+ /// The amount of tokens to transfer.
148
+ amount: u64,
149
+ },
150
+ /// Approves a delegate. A delegate is given the authority over tokens on
151
+ /// behalf of the source account's owner.
152
+ ///
153
+ /// Accounts expected by this instruction:
154
+ ///
155
+ /// * Single owner
156
+ /// 0. `[writable]` The source account.
157
+ /// 1. `[]` The delegate.
158
+ /// 2. `[signer]` The source account owner.
159
+ ///
160
+ /// * Multisignature owner
161
+ /// 0. `[writable]` The source account.
162
+ /// 1. `[]` The delegate.
163
+ /// 2. `[]` The source account's multisignature owner.
164
+ /// 3. ..`3+M` `[signer]` M signer accounts
165
+ Approve {
166
+ /// The amount of tokens the delegate is approved for.
167
+ amount: u64,
168
+ },
169
+ // 5
170
+ /// Revokes the delegate's authority.
171
+ ///
172
+ /// Accounts expected by this instruction:
173
+ ///
174
+ /// * Single owner
175
+ /// 0. `[writable]` The source account.
176
+ /// 1. `[signer]` The source account owner or current delegate.
177
+ ///
178
+ /// * Multisignature owner
179
+ /// 0. `[writable]` The source account.
180
+ /// 1. `[]` The source account's multisignature owner or current delegate.
181
+ /// 2. ..`2+M` `[signer]` M signer accounts
182
+ Revoke,
183
+ /// Sets a new authority of a mint or account.
184
+ ///
185
+ /// Accounts expected by this instruction:
186
+ ///
187
+ /// * Single authority
188
+ /// 0. `[writable]` The mint or account to change the authority of.
189
+ /// 1. `[signer]` The current authority of the mint or account.
190
+ ///
191
+ /// * Multisignature authority
192
+ /// 0. `[writable]` The mint or account to change the authority of.
193
+ /// 1. `[]` The mint's or account's current multisignature authority.
194
+ /// 2. ..`2+M` `[signer]` M signer accounts
195
+ SetAuthority {
196
+ /// The type of authority to update.
197
+ authority_type: AuthorityType,
198
+ /// The new authority
199
+ #[cfg_attr(feature = "serde", serde(with = "coption_fromstr"))]
200
+ new_authority: COption<Address>,
201
+ },
202
+ /// Mints new tokens to an account. The native mint does not support
203
+ /// minting.
204
+ ///
205
+ /// Accounts expected by this instruction:
206
+ ///
207
+ /// * Single authority
208
+ /// 0. `[writable]` The mint.
209
+ /// 1. `[writable]` The account to mint tokens to.
210
+ /// 2. `[signer]` The mint's minting authority.
211
+ ///
212
+ /// * Multisignature authority
213
+ /// 0. `[writable]` The mint.
214
+ /// 1. `[writable]` The account to mint tokens to.
215
+ /// 2. `[]` The mint's multisignature mint-tokens authority.
216
+ /// 3. ..`3+M` `[signer]` M signer accounts.
217
+ MintTo {
218
+ /// The amount of new tokens to mint.
219
+ amount: u64,
220
+ },
221
+ /// Burns tokens by removing them from an account. `Burn` does not support
222
+ /// accounts associated with the native mint, use `CloseAccount` instead.
223
+ ///
224
+ /// Accounts expected by this instruction:
225
+ ///
226
+ /// * Single owner/delegate
227
+ /// 0. `[writable]` The account to burn from.
228
+ /// 1. `[writable]` The token mint.
229
+ /// 2. `[signer]` The account's owner/delegate.
230
+ ///
231
+ /// * Multisignature owner/delegate
232
+ /// 0. `[writable]` The account to burn from.
233
+ /// 1. `[writable]` The token mint.
234
+ /// 2. `[]` The account's multisignature owner/delegate.
235
+ /// 3. ..`3+M` `[signer]` M signer accounts.
236
+ Burn {
237
+ /// The amount of tokens to burn.
238
+ amount: u64,
239
+ },
240
+ /// Close an account by transferring all its SOL to the destination account.
241
+ /// Non-native accounts may only be closed if its token amount is zero.
242
+ ///
243
+ /// Accounts with the `TransferFeeAmount` extension may only be closed if
244
+ /// the withheld amount is zero.
245
+ ///
246
+ /// Accounts with the `ConfidentialTransfer` extension may only be closed if
247
+ /// the pending and available balance ciphertexts are empty. Use
248
+ /// `ConfidentialTransferInstruction::ApplyPendingBalance` and
249
+ /// `ConfidentialTransferInstruction::EmptyAccount` to empty these
250
+ /// ciphertexts.
251
+ ///
252
+ /// Accounts with the `ConfidentialTransferFee` extension may only be closed
253
+ /// if the withheld amount ciphertext is empty. Use
254
+ /// `ConfidentialTransferFeeInstruction::HarvestWithheldTokensToMint` to
255
+ /// empty this ciphertext.
256
+ ///
257
+ /// Mints may be closed if they have the `MintCloseAuthority` extension and
258
+ /// their token supply is zero
259
+ ///
260
+ /// Accounts
261
+ ///
262
+ /// Accounts expected by this instruction:
263
+ ///
264
+ /// * Single owner
265
+ /// 0. `[writable]` The account to close.
266
+ /// 1. `[writable]` The destination account.
267
+ /// 2. `[signer]` The account's owner.
268
+ ///
269
+ /// * Multisignature owner
270
+ /// 0. `[writable]` The account to close.
271
+ /// 1. `[writable]` The destination account.
272
+ /// 2. `[]` The account's multisignature owner.
273
+ /// 3. ..`3+M` `[signer]` M signer accounts.
274
+ CloseAccount,
275
+ // 10
276
+ /// Freeze an Initialized account using the Mint's `freeze_authority` (if
277
+ /// set).
278
+ ///
279
+ /// Accounts expected by this instruction:
280
+ ///
281
+ /// * Single owner
282
+ /// 0. `[writable]` The account to freeze.
283
+ /// 1. `[]` The token mint.
284
+ /// 2. `[signer]` The mint freeze authority.
285
+ ///
286
+ /// * Multisignature owner
287
+ /// 0. `[writable]` The account to freeze.
288
+ /// 1. `[]` The token mint.
289
+ /// 2. `[]` The mint's multisignature freeze authority.
290
+ /// 3. ..`3+M` `[signer]` M signer accounts.
291
+ FreezeAccount,
292
+ /// Thaw a Frozen account using the Mint's `freeze_authority` (if set).
293
+ ///
294
+ /// Accounts expected by this instruction:
295
+ ///
296
+ /// * Single owner
297
+ /// 0. `[writable]` The account to thaw.
298
+ /// 1. `[]` The token mint.
299
+ /// 2. `[signer]` The mint freeze authority.
300
+ ///
301
+ /// * Multisignature owner
302
+ /// 0. `[writable]` The account to thaw.
303
+ /// 1. `[]` The token mint.
304
+ /// 2. `[]` The mint's multisignature freeze authority.
305
+ /// 3. ..`3+M` `[signer]` M signer accounts.
306
+ ThawAccount,
307
+
308
+ /// Transfers tokens from one account to another either directly or via a
309
+ /// delegate. If this account is associated with the native mint then equal
310
+ /// amounts of SOL and Tokens will be transferred to the destination
311
+ /// account.
312
+ ///
313
+ /// This instruction differs from `Transfer` in that the token mint and
314
+ /// decimals value is checked by the caller. This may be useful when
315
+ /// creating transactions offline or within a hardware wallet.
316
+ ///
317
+ /// If either account contains an `TransferFeeAmount` extension, the fee is
318
+ /// withheld in the destination account.
319
+ ///
320
+ /// Accounts expected by this instruction:
321
+ ///
322
+ /// * Single owner/delegate
323
+ /// 0. `[writable]` The source account.
324
+ /// 1. `[]` The token mint.
325
+ /// 2. `[writable]` The destination account.
326
+ /// 3. `[signer]` The source account's owner/delegate.
327
+ ///
328
+ /// * Multisignature owner/delegate
329
+ /// 0. `[writable]` The source account.
330
+ /// 1. `[]` The token mint.
331
+ /// 2. `[writable]` The destination account.
332
+ /// 3. `[]` The source account's multisignature owner/delegate.
333
+ /// 4. ..`4+M` `[signer]` M signer accounts.
334
+ TransferChecked {
335
+ /// The amount of tokens to transfer.
336
+ amount: u64,
337
+ /// Expected number of base 10 digits to the right of the decimal place.
338
+ decimals: u8,
339
+ },
340
+ /// Approves a delegate. A delegate is given the authority over tokens on
341
+ /// behalf of the source account's owner.
342
+ ///
343
+ /// This instruction differs from `Approve` in that the token mint and
344
+ /// decimals value is checked by the caller. This may be useful when
345
+ /// creating transactions offline or within a hardware wallet.
346
+ ///
347
+ /// Accounts expected by this instruction:
348
+ ///
349
+ /// * Single owner
350
+ /// 0. `[writable]` The source account.
351
+ /// 1. `[]` The token mint.
352
+ /// 2. `[]` The delegate.
353
+ /// 3. `[signer]` The source account owner.
354
+ ///
355
+ /// * Multisignature owner
356
+ /// 0. `[writable]` The source account.
357
+ /// 1. `[]` The token mint.
358
+ /// 2. `[]` The delegate.
359
+ /// 3. `[]` The source account's multisignature owner.
360
+ /// 4. ..`4+M` `[signer]` M signer accounts
361
+ ApproveChecked {
362
+ /// The amount of tokens the delegate is approved for.
363
+ amount: u64,
364
+ /// Expected number of base 10 digits to the right of the decimal place.
365
+ decimals: u8,
366
+ },
367
+ /// Mints new tokens to an account. The native mint does not support
368
+ /// minting.
369
+ ///
370
+ /// This instruction differs from `MintTo` in that the decimals value is
371
+ /// checked by the caller. This may be useful when creating transactions
372
+ /// offline or within a hardware wallet.
373
+ ///
374
+ /// Accounts expected by this instruction:
375
+ ///
376
+ /// * Single authority
377
+ /// 0. `[writable]` The mint.
378
+ /// 1. `[writable]` The account to mint tokens to.
379
+ /// 2. `[signer]` The mint's minting authority.
380
+ ///
381
+ /// * Multisignature authority
382
+ /// 0. `[writable]` The mint.
383
+ /// 1. `[writable]` The account to mint tokens to.
384
+ /// 2. `[]` The mint's multisignature mint-tokens authority.
385
+ /// 3. ..`3+M` `[signer]` M signer accounts.
386
+ MintToChecked {
387
+ /// The amount of new tokens to mint.
388
+ amount: u64,
389
+ /// Expected number of base 10 digits to the right of the decimal place.
390
+ decimals: u8,
391
+ },
392
+ // 15
393
+ /// Burns tokens by removing them from an account. `BurnChecked` does not
394
+ /// support accounts associated with the native mint, use `CloseAccount`
395
+ /// instead.
396
+ ///
397
+ /// This instruction differs from `Burn` in that the decimals value is
398
+ /// checked by the caller. This may be useful when creating transactions
399
+ /// offline or within a hardware wallet.
400
+ ///
401
+ /// Accounts expected by this instruction:
402
+ ///
403
+ /// * Single owner/delegate
404
+ /// 0. `[writable]` The account to burn from.
405
+ /// 1. `[writable]` The token mint.
406
+ /// 2. `[signer]` The account's owner/delegate.
407
+ ///
408
+ /// * Multisignature owner/delegate
409
+ /// 0. `[writable]` The account to burn from.
410
+ /// 1. `[writable]` The token mint.
411
+ /// 2. `[]` The account's multisignature owner/delegate.
412
+ /// 3. ..`3+M` `[signer]` M signer accounts.
413
+ BurnChecked {
414
+ /// The amount of tokens to burn.
415
+ amount: u64,
416
+ /// Expected number of base 10 digits to the right of the decimal place.
417
+ decimals: u8,
418
+ },
419
+ /// Like `InitializeAccount`, but the owner pubkey is passed via instruction
420
+ /// data rather than the accounts list. This variant may be preferable
421
+ /// when using Cross Program Invocation from an instruction that does
422
+ /// not need the owner's `AccountInfo` otherwise.
423
+ ///
424
+ /// Accounts expected by this instruction:
425
+ ///
426
+ /// 0. `[writable]` The account to initialize.
427
+ /// 1. `[]` The mint this account will be associated with.
428
+ /// 2. `[]` Rent sysvar
429
+ InitializeAccount2 {
430
+ /// The new account's owner/multisignature.
431
+ #[cfg_attr(feature = "serde", serde(with = "As::<DisplayFromStr>"))]
432
+ owner: Address,
433
+ },
434
+ /// Given a wrapped / native token account (a token account containing SOL)
435
+ /// updates its amount field based on the account's underlying `lamports`.
436
+ /// This is useful if a non-wrapped SOL account uses
437
+ /// `system_instruction::transfer` to move lamports to a wrapped token
438
+ /// account, and needs to have its token `amount` field updated.
439
+ ///
440
+ /// Accounts expected by this instruction:
441
+ ///
442
+ /// * Using runtime Rent sysvar
443
+ /// 0. `[writable]` The native token account to sync with its underlying
444
+ /// lamports.
445
+ ///
446
+ /// * Using Rent sysvar account
447
+ /// 0. `[writable]` The native token account to sync with its underlying
448
+ /// lamports.
449
+ /// 1. `[]` Rent sysvar.
450
+ SyncNative,
451
+ /// Like `InitializeAccount2`, but does not require the Rent sysvar to be
452
+ /// provided
453
+ ///
454
+ /// Accounts expected by this instruction:
455
+ ///
456
+ /// 0. `[writable]` The account to initialize.
457
+ /// 1. `[]` The mint this account will be associated with.
458
+ InitializeAccount3 {
459
+ /// The new account's owner/multisignature.
460
+ #[cfg_attr(feature = "serde", serde(with = "As::<DisplayFromStr>"))]
461
+ owner: Address,
462
+ },
463
+ /// Like `InitializeMultisig`, but does not require the Rent sysvar to be
464
+ /// provided
465
+ ///
466
+ /// Accounts expected by this instruction:
467
+ ///
468
+ /// 0. `[writable]` The multisignature account to initialize.
469
+ /// 1. ..`1+N`. `[]` The signer accounts, must equal to N where `1 <= N <=
470
+ /// 11`.
471
+ InitializeMultisig2 {
472
+ /// The number of signers (M) required to validate this multisignature
473
+ /// account.
474
+ m: u8,
475
+ },
476
+ // 20
477
+ /// Like `InitializeMint`, but does not require the Rent sysvar to be
478
+ /// provided
479
+ ///
480
+ /// Accounts expected by this instruction:
481
+ ///
482
+ /// 0. `[writable]` The mint to initialize.
483
+ InitializeMint2 {
484
+ /// Number of base 10 digits to the right of the decimal place.
485
+ decimals: u8,
486
+ /// The authority/multisignature to mint tokens.
487
+ #[cfg_attr(feature = "serde", serde(with = "As::<DisplayFromStr>"))]
488
+ mint_authority: Address,
489
+ /// The freeze authority/multisignature of the mint.
490
+ #[cfg_attr(feature = "serde", serde(with = "coption_fromstr"))]
491
+ freeze_authority: COption<Address>,
492
+ },
493
+ /// Gets the required size of an account for the given mint as a
494
+ /// little-endian `u64`.
495
+ ///
496
+ /// Return data can be fetched using `sol_get_return_data` and deserializing
497
+ /// the return data as a little-endian `u64`.
498
+ ///
499
+ /// Accounts expected by this instruction:
500
+ ///
501
+ /// 0. `[]` The mint to calculate for
502
+ GetAccountDataSize {
503
+ /// Additional extension types to include in the returned account size
504
+ extension_types: Vec<ExtensionType>,
505
+ },
506
+ /// Initialize the Immutable Owner extension for the given token account
507
+ ///
508
+ /// Fails if the account has already been initialized, so must be called
509
+ /// before `InitializeAccount`.
510
+ ///
511
+ /// Accounts expected by this instruction:
512
+ ///
513
+ /// 0. `[writable]` The account to initialize.
514
+ ///
515
+ /// Data expected by this instruction:
516
+ /// None
517
+ InitializeImmutableOwner,
518
+ /// Convert an Amount of tokens to a `UiAmount` string, using the given
519
+ /// mint.
520
+ ///
521
+ /// Fails on an invalid mint.
522
+ ///
523
+ /// Return data can be fetched using `sol_get_return_data` and deserialized
524
+ /// with `String::from_utf8`.
525
+ ///
526
+ /// WARNING: For mints using the interest-bearing or scaled-ui-amount
527
+ /// extensions, this instruction uses standard floating-point arithmetic to
528
+ /// convert values, which is not guaranteed to give consistent behavior.
529
+ ///
530
+ /// In particular, conversions will not always work in reverse. For example,
531
+ /// if you pass amount `A` to `AmountToUiAmount` and receive `B`, and pass
532
+ /// the result `B` to `UiAmountToAmount`, you will not always get back `A`.
533
+ ///
534
+ /// Accounts expected by this instruction:
535
+ ///
536
+ /// 0. `[]` The mint to calculate for
537
+ AmountToUiAmount {
538
+ /// The amount of tokens to convert.
539
+ amount: u64,
540
+ },
541
+ /// Convert a `UiAmount` of tokens to a little-endian `u64` raw Amount,
542
+ /// using the given mint.
543
+ ///
544
+ /// Return data can be fetched using `sol_get_return_data` and deserializing
545
+ /// the return data as a little-endian `u64`.
546
+ ///
547
+ /// WARNING: For mints using the interest-bearing or scaled-ui-amount
548
+ /// extensions, this instruction uses standard floating-point arithmetic to
549
+ /// convert values, which is not guaranteed to give consistent behavior.
550
+ ///
551
+ /// In particular, conversions will not always work in reverse. For example,
552
+ /// if you pass amount `A` to `UiAmountToAmount` and receive `B`, and pass
553
+ /// the result `B` to `AmountToUiAmount`, you will not always get back `A`.
554
+ ///
555
+ /// Accounts expected by this instruction:
556
+ ///
557
+ /// 0. `[]` The mint to calculate for
558
+ UiAmountToAmount {
559
+ /// The `ui_amount` of tokens to convert.
560
+ ui_amount: &'a str,
561
+ },
562
+ // 25
563
+ /// Initialize the close account authority on a new mint.
564
+ ///
565
+ /// Fails if the mint has already been initialized, so must be called before
566
+ /// `InitializeMint`.
567
+ ///
568
+ /// The mint must have exactly enough space allocated for the base mint (82
569
+ /// bytes), plus 83 bytes of padding, 1 byte reserved for the account type,
570
+ /// then space required for this extension, plus any others.
571
+ ///
572
+ /// Accounts expected by this instruction:
573
+ ///
574
+ /// 0. `[writable]` The mint to initialize.
575
+ InitializeMintCloseAuthority {
576
+ /// Authority that must sign the `CloseAccount` instruction on a mint
577
+ #[cfg_attr(feature = "serde", serde(with = "coption_fromstr"))]
578
+ close_authority: COption<Address>,
579
+ },
580
+ /// The common instruction prefix for Transfer Fee extension instructions.
581
+ ///
582
+ /// See `extension::transfer_fee::instruction::TransferFeeInstruction` for
583
+ /// further details about the extended instructions that share this
584
+ /// instruction prefix
585
+ TransferFeeExtension,
586
+ /// The common instruction prefix for Confidential Transfer extension
587
+ /// instructions.
588
+ ///
589
+ /// See `extension::confidential_transfer::instruction::ConfidentialTransferInstruction` for
590
+ /// further details about the extended instructions that share this
591
+ /// instruction prefix
592
+ ConfidentialTransferExtension,
593
+ /// The common instruction prefix for Default Account State extension
594
+ /// instructions.
595
+ ///
596
+ /// See `extension::default_account_state::instruction::DefaultAccountStateInstruction` for
597
+ /// further details about the extended instructions that share this
598
+ /// instruction prefix
599
+ DefaultAccountStateExtension,
600
+ /// Check to see if a token account is large enough for a list of
601
+ /// `ExtensionTypes`, and if not, use reallocation to increase the data
602
+ /// size.
603
+ ///
604
+ /// Accounts expected by this instruction:
605
+ ///
606
+ /// * Single owner
607
+ /// 0. `[writable]` The account to reallocate.
608
+ /// 1. `[signer, writable]` The payer account to fund reallocation
609
+ /// 2. `[]` System program for reallocation funding
610
+ /// 3. `[signer]` The account's owner.
611
+ ///
612
+ /// * Multisignature owner
613
+ /// 0. `[writable]` The account to reallocate.
614
+ /// 1. `[signer, writable]` The payer account to fund reallocation
615
+ /// 2. `[]` System program for reallocation funding
616
+ /// 3. `[]` The account's multisignature owner/delegate.
617
+ /// 4. ..`4+M` `[signer]` M signer accounts.
618
+ Reallocate {
619
+ /// New extension types to include in the reallocated account
620
+ extension_types: Vec<ExtensionType>,
621
+ },
622
+ // 30
623
+ /// The common instruction prefix for Memo Transfer account extension
624
+ /// instructions.
625
+ ///
626
+ /// See `extension::memo_transfer::instruction::RequiredMemoTransfersInstruction` for
627
+ /// further details about the extended instructions that share this
628
+ /// instruction prefix
629
+ MemoTransferExtension,
630
+ /// Creates the native mint.
631
+ ///
632
+ /// This instruction only needs to be invoked once after deployment and is
633
+ /// permissionless, Wrapped SOL (`native_mint::id()`) will not be
634
+ /// available until this instruction is successfully executed.
635
+ ///
636
+ /// Accounts expected by this instruction:
637
+ ///
638
+ /// 0. `[writeable,signer]` Funding account (must be a system account)
639
+ /// 1. `[writable]` The native mint address
640
+ /// 2. `[]` System program for mint account funding
641
+ CreateNativeMint,
642
+ /// Initialize the non transferable extension for the given mint account
643
+ ///
644
+ /// Fails if the account has already been initialized, so must be called
645
+ /// before `InitializeMint`.
646
+ ///
647
+ /// Accounts expected by this instruction:
648
+ ///
649
+ /// 0. `[writable]` The mint account to initialize.
650
+ ///
651
+ /// Data expected by this instruction:
652
+ /// None
653
+ InitializeNonTransferableMint,
654
+ /// The common instruction prefix for Interest Bearing extension
655
+ /// instructions.
656
+ ///
657
+ /// See `extension::interest_bearing_mint::instruction::InterestBearingMintInstruction` for
658
+ /// further details about the extended instructions that share this
659
+ /// instruction prefix
660
+ InterestBearingMintExtension,
661
+ /// The common instruction prefix for CPI Guard account extension
662
+ /// instructions.
663
+ ///
664
+ /// See `extension::cpi_guard::instruction::CpiGuardInstruction` for
665
+ /// further details about the extended instructions that share this
666
+ /// instruction prefix
667
+ CpiGuardExtension,
668
+ // 35
669
+ /// Initialize the permanent delegate on a new mint.
670
+ ///
671
+ /// Fails if the mint has already been initialized, so must be called before
672
+ /// `InitializeMint`.
673
+ ///
674
+ /// The mint must have exactly enough space allocated for the base mint (82
675
+ /// bytes), plus 83 bytes of padding, 1 byte reserved for the account type,
676
+ /// then space required for this extension, plus any others.
677
+ ///
678
+ /// Accounts expected by this instruction:
679
+ ///
680
+ /// 0. `[writable]` The mint to initialize.
681
+ ///
682
+ /// Data expected by this instruction:
683
+ /// Address for the permanent delegate
684
+ InitializePermanentDelegate {
685
+ /// Authority that may sign for `Transfer`s and `Burn`s on any account
686
+ #[cfg_attr(feature = "serde", serde(with = "As::<DisplayFromStr>"))]
687
+ delegate: Address,
688
+ },
689
+ /// The common instruction prefix for transfer hook extension instructions.
690
+ ///
691
+ /// See `extension::transfer_hook::instruction::TransferHookInstruction`
692
+ /// for further details about the extended instructions that share this
693
+ /// instruction prefix
694
+ TransferHookExtension,
695
+ /// The common instruction prefix for the confidential transfer fee
696
+ /// extension instructions.
697
+ ///
698
+ /// See `extension::confidential_transfer_fee::instruction::ConfidentialTransferFeeInstruction`
699
+ /// for further details about the extended instructions that share this
700
+ /// instruction prefix
701
+ ConfidentialTransferFeeExtension,
702
+ /// This instruction is to be used to rescue SOL sent to any `TokenProgram`
703
+ /// owned account by sending them to any other account, leaving behind only
704
+ /// lamports for rent exemption.
705
+ ///
706
+ /// 0. `[writable]` Source Account owned by the token program
707
+ /// 1. `[writable]` Destination account
708
+ /// 2. `[signer]` Authority
709
+ /// 3. ..`3+M` `[signer]` M signer accounts.
710
+ WithdrawExcessLamports,
711
+ /// The common instruction prefix for metadata pointer extension
712
+ /// instructions.
713
+ ///
714
+ /// See `extension::metadata_pointer::instruction::MetadataPointerInstruction`
715
+ /// for further details about the extended instructions that share this
716
+ /// instruction prefix
717
+ MetadataPointerExtension,
718
+ // 40
719
+ /// The common instruction prefix for group pointer extension instructions.
720
+ ///
721
+ /// See `extension::group_pointer::instruction::GroupPointerInstruction`
722
+ /// for further details about the extended instructions that share this
723
+ /// instruction prefix
724
+ GroupPointerExtension,
725
+ /// The common instruction prefix for group member pointer extension
726
+ /// instructions.
727
+ ///
728
+ /// See `extension::group_member_pointer::instruction::GroupMemberPointerInstruction`
729
+ /// for further details about the extended instructions that share this
730
+ /// instruction prefix
731
+ GroupMemberPointerExtension,
732
+ /// Instruction prefix for instructions to the confidential-mint-burn
733
+ /// extension
734
+ ConfidentialMintBurnExtension,
735
+ /// Instruction prefix for instructions to the scaled ui amount
736
+ /// extension
737
+ ScaledUiAmountExtension,
738
+ /// Instruction prefix for instructions to the pausable extension
739
+ PausableExtension,
740
+ // 45
741
+ /// Transfer lamports from a native SOL account to a destination account.
742
+ ///
743
+ /// This is useful to unwrap lamports from a wrapped SOL account.
744
+ ///
745
+ /// * Single owner/delegate
746
+ /// 0. `[writable]` The source account.
747
+ /// 1. `[writable]` The destination account.
748
+ /// 2. `[signer]` The source account's owner/delegate.
749
+ ///
750
+ /// * Multisignature owner/delegate
751
+ /// 0. `[writable]` The source account.
752
+ /// 1. `[writable]` The destination account.
753
+ /// 2. `[]` The source account's multisignature owner/delegate.
754
+ /// 3. `..+M` `[signer]` M signer accounts.
755
+ UnwrapLamports {
756
+ /// The amount of lamports to transfer. When an amount is
757
+ /// not specified, the entire balance of the source account will be
758
+ /// transferred.
759
+ #[cfg_attr(feature = "serde", serde(with = "coption_u64_fromval"))]
760
+ amount: COption<u64>,
761
+ },
762
+ /// Instruction prefix for instructions to the permissioned burn extension
763
+ PermissionedBurnExtension,
764
+ // 255
765
+ /// Executes a batch of instructions. The instructions to be executed are
766
+ /// specified in sequence on the instruction data. Each instruction
767
+ /// provides:
768
+ /// - `u8`: number of accounts
769
+ /// - `u8`: instruction data length (includes the discriminator)
770
+ /// - `u8`: instruction discriminator
771
+ /// - `[u8]`: instruction data
772
+ ///
773
+ /// Accounts follow a similar pattern, where accounts for each instruction
774
+ /// are specified in sequence. Therefore, the number of accounts
775
+ /// expected by this instruction is variable, i.e., it depends on the
776
+ /// instructions provided.
777
+ ///
778
+ /// Both the number of accounts and instruction data length are used to
779
+ /// identify the slice of accounts and instruction data for each
780
+ /// instruction.
781
+ ///
782
+ /// Note that it is not sound to have a `batch` instruction that contains
783
+ /// other `batch` instruction; an error will be raised when this is
784
+ /// detected.
785
+ Batch {
786
+ /// Data for the instructions in the batch, contains sequentially for
787
+ /// each instruction Account count-Data length-Variant-Instruction data
788
+ #[cfg_attr(feature = "serde", serde(with = "batch_fromstr"))]
789
+ data: Vec<u8>,
790
+ },
791
+ }
792
+ impl<'a> TokenInstruction<'a> {
793
+ /// Unpacks a byte buffer into a
794
+ /// [`TokenInstruction`](enum.TokenInstruction.html).
795
+ pub fn unpack(input: &'a [u8]) -> Result<Self, ProgramError> {
796
+ Self::unpack_with_rest(input).map(|(token_instruction, _)| token_instruction)
797
+ }
798
+
799
+ /// Packs a [`TokenInstruction`](enum.TokenInstruction.html) into a byte
800
+ /// buffer.
801
+ pub fn pack(&self) -> Vec<u8> {
802
+ let mut buf = Vec::with_capacity(size_of::<Self>());
803
+ match self {
804
+ &Self::InitializeMint {
805
+ ref mint_authority,
806
+ ref freeze_authority,
807
+ decimals,
808
+ } => {
809
+ buf.push(0);
810
+ buf.push(decimals);
811
+ buf.extend_from_slice(mint_authority.as_ref());
812
+ Self::pack_pubkey_option(freeze_authority, &mut buf);
813
+ }
814
+ Self::InitializeAccount => buf.push(1),
815
+ &Self::InitializeMultisig { m } => {
816
+ buf.push(2);
817
+ buf.push(m);
818
+ }
819
+ #[allow(deprecated)]
820
+ &Self::Transfer { amount } => {
821
+ buf.push(3);
822
+ buf.extend_from_slice(&amount.to_le_bytes());
823
+ }
824
+ &Self::Approve { amount } => {
825
+ buf.push(4);
826
+ buf.extend_from_slice(&amount.to_le_bytes());
827
+ }
828
+ &Self::MintTo { amount } => {
829
+ buf.push(7);
830
+ buf.extend_from_slice(&amount.to_le_bytes());
831
+ }
832
+ &Self::Burn { amount } => {
833
+ buf.push(8);
834
+ buf.extend_from_slice(&amount.to_le_bytes());
835
+ }
836
+ Self::Revoke => buf.push(5),
837
+ Self::SetAuthority {
838
+ authority_type,
839
+ ref new_authority,
840
+ } => {
841
+ buf.push(6);
842
+ buf.push(authority_type.into());
843
+ Self::pack_pubkey_option(new_authority, &mut buf);
844
+ }
845
+ Self::CloseAccount => buf.push(9),
846
+ Self::FreezeAccount => buf.push(10),
847
+ Self::ThawAccount => buf.push(11),
848
+ &Self::TransferChecked { amount, decimals } => {
849
+ buf.push(12);
850
+ buf.extend_from_slice(&amount.to_le_bytes());
851
+ buf.push(decimals);
852
+ }
853
+ &Self::ApproveChecked { amount, decimals } => {
854
+ buf.push(13);
855
+ buf.extend_from_slice(&amount.to_le_bytes());
856
+ buf.push(decimals);
857
+ }
858
+ &Self::MintToChecked { amount, decimals } => {
859
+ buf.push(14);
860
+ buf.extend_from_slice(&amount.to_le_bytes());
861
+ buf.push(decimals);
862
+ }
863
+ &Self::BurnChecked { amount, decimals } => {
864
+ buf.push(15);
865
+ buf.extend_from_slice(&amount.to_le_bytes());
866
+ buf.push(decimals);
867
+ }
868
+ &Self::InitializeAccount2 { owner } => {
869
+ buf.push(16);
870
+ buf.extend_from_slice(owner.as_ref());
871
+ }
872
+ &Self::SyncNative => {
873
+ buf.push(17);
874
+ }
875
+ &Self::InitializeAccount3 { owner } => {
876
+ buf.push(18);
877
+ buf.extend_from_slice(owner.as_ref());
878
+ }
879
+ &Self::InitializeMultisig2 { m } => {
880
+ buf.push(19);
881
+ buf.push(m);
882
+ }
883
+ &Self::InitializeMint2 {
884
+ ref mint_authority,
885
+ ref freeze_authority,
886
+ decimals,
887
+ } => {
888
+ buf.push(20);
889
+ buf.push(decimals);
890
+ buf.extend_from_slice(mint_authority.as_ref());
891
+ Self::pack_pubkey_option(freeze_authority, &mut buf);
892
+ }
893
+ Self::GetAccountDataSize { extension_types } => {
894
+ buf.push(21);
895
+ for extension_type in extension_types {
896
+ buf.extend_from_slice(&<[u8; 2]>::from(*extension_type));
897
+ }
898
+ }
899
+ &Self::InitializeImmutableOwner => {
900
+ buf.push(22);
901
+ }
902
+ &Self::AmountToUiAmount { amount } => {
903
+ buf.push(23);
904
+ buf.extend_from_slice(&amount.to_le_bytes());
905
+ }
906
+ Self::UiAmountToAmount { ui_amount } => {
907
+ buf.push(24);
908
+ buf.extend_from_slice(ui_amount.as_bytes());
909
+ }
910
+ Self::InitializeMintCloseAuthority { close_authority } => {
911
+ buf.push(25);
912
+ Self::pack_pubkey_option(close_authority, &mut buf);
913
+ }
914
+ Self::TransferFeeExtension => {
915
+ buf.push(26);
916
+ }
917
+ &Self::ConfidentialTransferExtension => {
918
+ buf.push(27);
919
+ }
920
+ &Self::DefaultAccountStateExtension => {
921
+ buf.push(28);
922
+ }
923
+ Self::Reallocate { extension_types } => {
924
+ buf.push(29);
925
+ for extension_type in extension_types {
926
+ buf.extend_from_slice(&<[u8; 2]>::from(*extension_type));
927
+ }
928
+ }
929
+ &Self::MemoTransferExtension => {
930
+ buf.push(30);
931
+ }
932
+ &Self::CreateNativeMint => {
933
+ buf.push(31);
934
+ }
935
+ &Self::InitializeNonTransferableMint => {
936
+ buf.push(32);
937
+ }
938
+ &Self::InterestBearingMintExtension => {
939
+ buf.push(33);
940
+ }
941
+ &Self::CpiGuardExtension => {
942
+ buf.push(34);
943
+ }
944
+ Self::InitializePermanentDelegate { delegate } => {
945
+ buf.push(35);
946
+ buf.extend_from_slice(delegate.as_ref());
947
+ }
948
+ &Self::TransferHookExtension => {
949
+ buf.push(36);
950
+ }
951
+ &Self::ConfidentialTransferFeeExtension => {
952
+ buf.push(37);
953
+ }
954
+ &Self::WithdrawExcessLamports => {
955
+ buf.push(38);
956
+ }
957
+ &Self::MetadataPointerExtension => {
958
+ buf.push(39);
959
+ }
960
+ &Self::GroupPointerExtension => {
961
+ buf.push(40);
962
+ }
963
+ &Self::GroupMemberPointerExtension => {
964
+ buf.push(41);
965
+ }
966
+ &Self::ConfidentialMintBurnExtension => {
967
+ buf.push(42);
968
+ }
969
+ &Self::ScaledUiAmountExtension => {
970
+ buf.push(43);
971
+ }
972
+ &Self::PausableExtension => {
973
+ buf.push(44);
974
+ }
975
+ &Self::UnwrapLamports { amount } => {
976
+ buf.push(45);
977
+ Self::pack_u64_option(&amount, &mut buf);
978
+ }
979
+ &Self::PermissionedBurnExtension => {
980
+ buf.push(46);
981
+ }
982
+ Self::Batch { data } => {
983
+ buf.push(255);
984
+ buf.extend_from_slice(data);
985
+ }
986
+ };
987
+ buf
988
+ }
989
+
990
+ pub(crate) fn unpack_with_rest(input: &'a [u8]) -> Result<(Self, &'a [u8]), ProgramError> {
991
+ use TokenError::InvalidInstruction;
992
+
993
+ let (&tag, rest) = input.split_first().ok_or(InvalidInstruction)?;
994
+ Ok(match tag {
995
+ 0 => {
996
+ let (&decimals, rest) = rest.split_first().ok_or(InvalidInstruction)?;
997
+ let (mint_authority, rest) = Self::unpack_pubkey(rest)?;
998
+ let (freeze_authority, rest) = Self::unpack_pubkey_option(rest)?;
999
+ (
1000
+ Self::InitializeMint {
1001
+ mint_authority,
1002
+ freeze_authority,
1003
+ decimals,
1004
+ },
1005
+ rest,
1006
+ )
1007
+ }
1008
+ 1 => (Self::InitializeAccount, rest),
1009
+ 2 => {
1010
+ let (&m, rest) = rest.split_first().ok_or(InvalidInstruction)?;
1011
+ (Self::InitializeMultisig { m }, rest)
1012
+ }
1013
+ 3 | 4 | 7 | 8 => {
1014
+ let (amount, rest) = rest
1015
+ .split_at_checked(U64_BYTES)
1016
+ .and_then(|(bytes, rest)| {
1017
+ let amount = u64::from_le_bytes(bytes.try_into().ok()?);
1018
+ Some((amount, rest))
1019
+ })
1020
+ .ok_or(InvalidInstruction)?;
1021
+
1022
+ (
1023
+ match tag {
1024
+ #[allow(deprecated)]
1025
+ 3 => Self::Transfer { amount },
1026
+ 4 => Self::Approve { amount },
1027
+ 7 => Self::MintTo { amount },
1028
+ 8 => Self::Burn { amount },
1029
+ _ => unreachable!(),
1030
+ },
1031
+ rest,
1032
+ )
1033
+ }
1034
+ 5 => (Self::Revoke, rest),
1035
+ 6 => {
1036
+ let (authority_type, rest) = rest
1037
+ .split_first()
1038
+ .ok_or_else(|| ProgramError::from(InvalidInstruction))
1039
+ .and_then(|(&t, rest)| Ok((AuthorityType::from(t)?, rest)))?;
1040
+ let (new_authority, rest) = Self::unpack_pubkey_option(rest)?;
1041
+
1042
+ (
1043
+ Self::SetAuthority {
1044
+ authority_type,
1045
+ new_authority,
1046
+ },
1047
+ rest,
1048
+ )
1049
+ }
1050
+ 9 => (Self::CloseAccount, rest),
1051
+ 10 => (Self::FreezeAccount, rest),
1052
+ 11 => (Self::ThawAccount, rest),
1053
+ 12 => {
1054
+ let (amount, decimals, rest) = Self::unpack_amount_decimals(rest)?;
1055
+ (Self::TransferChecked { amount, decimals }, rest)
1056
+ }
1057
+ 13 => {
1058
+ let (amount, decimals, rest) = Self::unpack_amount_decimals(rest)?;
1059
+ (Self::ApproveChecked { amount, decimals }, rest)
1060
+ }
1061
+ 14 => {
1062
+ let (amount, decimals, rest) = Self::unpack_amount_decimals(rest)?;
1063
+ (Self::MintToChecked { amount, decimals }, rest)
1064
+ }
1065
+ 15 => {
1066
+ let (amount, decimals, rest) = Self::unpack_amount_decimals(rest)?;
1067
+ (Self::BurnChecked { amount, decimals }, rest)
1068
+ }
1069
+ 16 => {
1070
+ let (owner, rest) = Self::unpack_pubkey(rest)?;
1071
+ (Self::InitializeAccount2 { owner }, rest)
1072
+ }
1073
+ 17 => (Self::SyncNative, rest),
1074
+ 18 => {
1075
+ let (owner, rest) = Self::unpack_pubkey(rest)?;
1076
+ (Self::InitializeAccount3 { owner }, rest)
1077
+ }
1078
+ 19 => {
1079
+ let (&m, rest) = rest.split_first().ok_or(InvalidInstruction)?;
1080
+ (Self::InitializeMultisig2 { m }, rest)
1081
+ }
1082
+ 20 => {
1083
+ let (&decimals, rest) = rest.split_first().ok_or(InvalidInstruction)?;
1084
+ let (mint_authority, rest) = Self::unpack_pubkey(rest)?;
1085
+ let (freeze_authority, rest) = Self::unpack_pubkey_option(rest)?;
1086
+ (
1087
+ Self::InitializeMint2 {
1088
+ mint_authority,
1089
+ freeze_authority,
1090
+ decimals,
1091
+ },
1092
+ rest,
1093
+ )
1094
+ }
1095
+ 21 => {
1096
+ let mut extension_types = vec![];
1097
+ for chunk in rest.chunks(size_of::<ExtensionType>()) {
1098
+ extension_types.push(chunk.try_into()?);
1099
+ }
1100
+ (Self::GetAccountDataSize { extension_types }, &[])
1101
+ }
1102
+ 22 => (Self::InitializeImmutableOwner, rest),
1103
+ 23 => {
1104
+ let (amount, rest) = Self::unpack_u64(rest)?;
1105
+ (Self::AmountToUiAmount { amount }, rest)
1106
+ }
1107
+ 24 => {
1108
+ let ui_amount = core::str::from_utf8(rest).map_err(|_| InvalidInstruction)?;
1109
+ (Self::UiAmountToAmount { ui_amount }, &[])
1110
+ }
1111
+ 25 => {
1112
+ let (close_authority, rest) = Self::unpack_pubkey_option(rest)?;
1113
+ (Self::InitializeMintCloseAuthority { close_authority }, rest)
1114
+ }
1115
+ 26 => (Self::TransferFeeExtension, rest),
1116
+ 27 => (Self::ConfidentialTransferExtension, rest),
1117
+ 28 => (Self::DefaultAccountStateExtension, rest),
1118
+ 29 => {
1119
+ let mut extension_types = vec![];
1120
+ for chunk in rest.chunks(size_of::<ExtensionType>()) {
1121
+ extension_types.push(chunk.try_into()?);
1122
+ }
1123
+ (Self::Reallocate { extension_types }, &[])
1124
+ }
1125
+ 30 => (Self::MemoTransferExtension, rest),
1126
+ 31 => (Self::CreateNativeMint, rest),
1127
+ 32 => (Self::InitializeNonTransferableMint, rest),
1128
+ 33 => (Self::InterestBearingMintExtension, rest),
1129
+ 34 => (Self::CpiGuardExtension, rest),
1130
+ 35 => {
1131
+ let (delegate, rest) = Self::unpack_pubkey(rest)?;
1132
+ (Self::InitializePermanentDelegate { delegate }, rest)
1133
+ }
1134
+ 36 => (Self::TransferHookExtension, rest),
1135
+ 37 => (Self::ConfidentialTransferFeeExtension, rest),
1136
+ 38 => (Self::WithdrawExcessLamports, rest),
1137
+ 39 => (Self::MetadataPointerExtension, rest),
1138
+ 40 => (Self::GroupPointerExtension, rest),
1139
+ 41 => (Self::GroupMemberPointerExtension, rest),
1140
+ 42 => (Self::ConfidentialMintBurnExtension, rest),
1141
+ 43 => (Self::ScaledUiAmountExtension, rest),
1142
+ 44 => (Self::PausableExtension, rest),
1143
+ 45 => {
1144
+ let (amount, rest) = Self::unpack_u64_option(rest)?;
1145
+ (Self::UnwrapLamports { amount }, rest)
1146
+ }
1147
+ 46 => (Self::PermissionedBurnExtension, rest),
1148
+ 255 => (
1149
+ Self::Batch {
1150
+ data: rest.to_vec(),
1151
+ },
1152
+ &[],
1153
+ ),
1154
+ _ => return Err(TokenError::InvalidInstruction.into()),
1155
+ })
1156
+ }
1157
+
1158
+ pub(crate) fn unpack_pubkey(input: &[u8]) -> Result<(Address, &[u8]), ProgramError> {
1159
+ let pk = input
1160
+ .get(..ADDRESS_BYTES)
1161
+ .and_then(|x| Address::try_from(x).ok())
1162
+ .ok_or(TokenError::InvalidInstruction)?;
1163
+ Ok((pk, &input[ADDRESS_BYTES..]))
1164
+ }
1165
+
1166
+ pub(crate) fn unpack_pubkey_option(
1167
+ input: &[u8],
1168
+ ) -> Result<(COption<Address>, &[u8]), ProgramError> {
1169
+ match input.split_first() {
1170
+ Option::Some((&0, rest)) => Ok((COption::None, rest)),
1171
+ Option::Some((&1, rest)) => {
1172
+ let (pk, rest) = Self::unpack_pubkey(rest)?;
1173
+ Ok((COption::Some(pk), rest))
1174
+ }
1175
+ _ => Err(TokenError::InvalidInstruction.into()),
1176
+ }
1177
+ }
1178
+
1179
+ pub(crate) fn pack_pubkey_option(value: &COption<Address>, buf: &mut Vec<u8>) {
1180
+ match *value {
1181
+ COption::Some(ref key) => {
1182
+ buf.push(1);
1183
+ buf.extend_from_slice(&key.to_bytes());
1184
+ }
1185
+ COption::None => buf.push(0),
1186
+ }
1187
+ }
1188
+
1189
+ pub(crate) fn unpack_u64_option(input: &[u8]) -> Result<(COption<u64>, &[u8]), ProgramError> {
1190
+ match input.split_first() {
1191
+ Option::Some((&0, rest)) => Ok((COption::None, rest)),
1192
+ Option::Some((&1, rest)) => {
1193
+ let (value, rest) = Self::unpack_u64(rest)?;
1194
+ Ok((COption::Some(value), rest))
1195
+ }
1196
+ _ => Err(TokenError::InvalidInstruction.into()),
1197
+ }
1198
+ }
1199
+
1200
+ pub(crate) fn pack_u64_option(value: &COption<u64>, buf: &mut Vec<u8>) {
1201
+ match *value {
1202
+ COption::Some(ref amount) => {
1203
+ buf.push(1);
1204
+ buf.extend_from_slice(&amount.to_le_bytes());
1205
+ }
1206
+ COption::None => buf.push(0),
1207
+ }
1208
+ }
1209
+
1210
+ pub(crate) fn unpack_u16(input: &[u8]) -> Result<(u16, &[u8]), ProgramError> {
1211
+ let value = input
1212
+ .get(..U16_BYTES)
1213
+ .and_then(|slice| slice.try_into().ok())
1214
+ .map(u16::from_le_bytes)
1215
+ .ok_or(TokenError::InvalidInstruction)?;
1216
+ Ok((value, &input[U16_BYTES..]))
1217
+ }
1218
+
1219
+ pub(crate) fn unpack_u64(input: &[u8]) -> Result<(u64, &[u8]), ProgramError> {
1220
+ let value = input
1221
+ .get(..U64_BYTES)
1222
+ .and_then(|slice| slice.try_into().ok())
1223
+ .map(u64::from_le_bytes)
1224
+ .ok_or(TokenError::InvalidInstruction)?;
1225
+ Ok((value, &input[U64_BYTES..]))
1226
+ }
1227
+
1228
+ pub(crate) fn unpack_amount_decimals(input: &[u8]) -> Result<(u64, u8, &[u8]), ProgramError> {
1229
+ let (amount, rest) = Self::unpack_u64(input)?;
1230
+ let (&decimals, rest) = rest.split_first().ok_or(TokenError::InvalidInstruction)?;
1231
+ Ok((amount, decimals, rest))
1232
+ }
1233
+ }
1234
+
1235
+ /// Specifies the authority type for `SetAuthority` instructions
1236
+ #[repr(u8)]
1237
+ #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1238
+ #[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
1239
+ #[derive(Clone, Debug, PartialEq)]
1240
+ pub enum AuthorityType {
1241
+ /// Authority to mint new tokens
1242
+ MintTokens,
1243
+ /// Authority to freeze any account associated with the Mint
1244
+ FreezeAccount,
1245
+ /// Owner of a given token account
1246
+ AccountOwner,
1247
+ /// Authority to close a token account
1248
+ CloseAccount,
1249
+ /// Authority to set the transfer fee
1250
+ TransferFeeConfig,
1251
+ /// Authority to withdraw withheld tokens from a mint
1252
+ WithheldWithdraw,
1253
+ /// Authority to close a mint account
1254
+ CloseMint,
1255
+ /// Authority to set the interest rate
1256
+ InterestRate,
1257
+ /// Authority to transfer or burn any tokens for a mint
1258
+ PermanentDelegate,
1259
+ /// Authority to update confidential transfer mint and approve accounts for
1260
+ /// confidential transfers
1261
+ ConfidentialTransferMint,
1262
+ /// Authority to set the transfer hook program id
1263
+ TransferHookProgramId,
1264
+ /// Authority to set the withdraw withheld authority encryption key
1265
+ ConfidentialTransferFeeConfig,
1266
+ /// Authority to set the metadata address
1267
+ MetadataPointer,
1268
+ /// Authority to set the group address
1269
+ GroupPointer,
1270
+ /// Authority to set the group member address
1271
+ GroupMemberPointer,
1272
+ /// Authority to set the UI amount scale
1273
+ ScaledUiAmount,
1274
+ /// Authority to pause or resume minting / transferring / burning
1275
+ Pause,
1276
+ /// Authority to perform a permissioned token burn
1277
+ PermissionedBurn,
1278
+ }
1279
+
1280
+ impl AuthorityType {
1281
+ fn into(&self) -> u8 {
1282
+ match self {
1283
+ AuthorityType::MintTokens => 0,
1284
+ AuthorityType::FreezeAccount => 1,
1285
+ AuthorityType::AccountOwner => 2,
1286
+ AuthorityType::CloseAccount => 3,
1287
+ AuthorityType::TransferFeeConfig => 4,
1288
+ AuthorityType::WithheldWithdraw => 5,
1289
+ AuthorityType::CloseMint => 6,
1290
+ AuthorityType::InterestRate => 7,
1291
+ AuthorityType::PermanentDelegate => 8,
1292
+ AuthorityType::ConfidentialTransferMint => 9,
1293
+ AuthorityType::TransferHookProgramId => 10,
1294
+ AuthorityType::ConfidentialTransferFeeConfig => 11,
1295
+ AuthorityType::MetadataPointer => 12,
1296
+ AuthorityType::GroupPointer => 13,
1297
+ AuthorityType::GroupMemberPointer => 14,
1298
+ AuthorityType::ScaledUiAmount => 15,
1299
+ AuthorityType::Pause => 16,
1300
+ AuthorityType::PermissionedBurn => 17,
1301
+ }
1302
+ }
1303
+
1304
+ /// Try to convert from a `u8` into the enum
1305
+ pub fn from(index: u8) -> Result<Self, ProgramError> {
1306
+ match index {
1307
+ 0 => Ok(AuthorityType::MintTokens),
1308
+ 1 => Ok(AuthorityType::FreezeAccount),
1309
+ 2 => Ok(AuthorityType::AccountOwner),
1310
+ 3 => Ok(AuthorityType::CloseAccount),
1311
+ 4 => Ok(AuthorityType::TransferFeeConfig),
1312
+ 5 => Ok(AuthorityType::WithheldWithdraw),
1313
+ 6 => Ok(AuthorityType::CloseMint),
1314
+ 7 => Ok(AuthorityType::InterestRate),
1315
+ 8 => Ok(AuthorityType::PermanentDelegate),
1316
+ 9 => Ok(AuthorityType::ConfidentialTransferMint),
1317
+ 10 => Ok(AuthorityType::TransferHookProgramId),
1318
+ 11 => Ok(AuthorityType::ConfidentialTransferFeeConfig),
1319
+ 12 => Ok(AuthorityType::MetadataPointer),
1320
+ 13 => Ok(AuthorityType::GroupPointer),
1321
+ 14 => Ok(AuthorityType::GroupMemberPointer),
1322
+ 15 => Ok(AuthorityType::ScaledUiAmount),
1323
+ 16 => Ok(AuthorityType::Pause),
1324
+ 17 => Ok(AuthorityType::PermissionedBurn),
1325
+ _ => Err(TokenError::InvalidInstruction.into()),
1326
+ }
1327
+ }
1328
+ }
1329
+
1330
+ /// Creates a `InitializeMint` instruction.
1331
+ pub fn initialize_mint(
1332
+ token_program_id: &Address,
1333
+ mint_pubkey: &Address,
1334
+ mint_authority_pubkey: &Address,
1335
+ freeze_authority_pubkey: Option<&Address>,
1336
+ decimals: u8,
1337
+ ) -> Result<Instruction, ProgramError> {
1338
+ check_spl_token_program_account(token_program_id)?;
1339
+ let freeze_authority = freeze_authority_pubkey.cloned().into();
1340
+ let data = TokenInstruction::InitializeMint {
1341
+ mint_authority: *mint_authority_pubkey,
1342
+ freeze_authority,
1343
+ decimals,
1344
+ }
1345
+ .pack();
1346
+
1347
+ let accounts = vec![
1348
+ AccountMeta::new(*mint_pubkey, false),
1349
+ AccountMeta::new_readonly(sysvar::rent::id(), false),
1350
+ ];
1351
+
1352
+ Ok(Instruction {
1353
+ program_id: *token_program_id,
1354
+ accounts,
1355
+ data,
1356
+ })
1357
+ }
1358
+
1359
+ /// Creates a `InitializeMint2` instruction.
1360
+ pub fn initialize_mint2(
1361
+ token_program_id: &Address,
1362
+ mint_pubkey: &Address,
1363
+ mint_authority_pubkey: &Address,
1364
+ freeze_authority_pubkey: Option<&Address>,
1365
+ decimals: u8,
1366
+ ) -> Result<Instruction, ProgramError> {
1367
+ check_spl_token_program_account(token_program_id)?;
1368
+ let freeze_authority = freeze_authority_pubkey.cloned().into();
1369
+ let data = TokenInstruction::InitializeMint2 {
1370
+ mint_authority: *mint_authority_pubkey,
1371
+ freeze_authority,
1372
+ decimals,
1373
+ }
1374
+ .pack();
1375
+
1376
+ let accounts = vec![AccountMeta::new(*mint_pubkey, false)];
1377
+
1378
+ Ok(Instruction {
1379
+ program_id: *token_program_id,
1380
+ accounts,
1381
+ data,
1382
+ })
1383
+ }
1384
+
1385
+ /// Creates a `InitializeAccount` instruction.
1386
+ pub fn initialize_account(
1387
+ token_program_id: &Address,
1388
+ account_pubkey: &Address,
1389
+ mint_pubkey: &Address,
1390
+ owner_pubkey: &Address,
1391
+ ) -> Result<Instruction, ProgramError> {
1392
+ check_spl_token_program_account(token_program_id)?;
1393
+ let data = TokenInstruction::InitializeAccount.pack();
1394
+
1395
+ let accounts = vec![
1396
+ AccountMeta::new(*account_pubkey, false),
1397
+ AccountMeta::new_readonly(*mint_pubkey, false),
1398
+ AccountMeta::new_readonly(*owner_pubkey, false),
1399
+ AccountMeta::new_readonly(sysvar::rent::id(), false),
1400
+ ];
1401
+
1402
+ Ok(Instruction {
1403
+ program_id: *token_program_id,
1404
+ accounts,
1405
+ data,
1406
+ })
1407
+ }
1408
+
1409
+ /// Creates a `InitializeAccount2` instruction.
1410
+ pub fn initialize_account2(
1411
+ token_program_id: &Address,
1412
+ account_pubkey: &Address,
1413
+ mint_pubkey: &Address,
1414
+ owner_pubkey: &Address,
1415
+ ) -> Result<Instruction, ProgramError> {
1416
+ check_spl_token_program_account(token_program_id)?;
1417
+ let data = TokenInstruction::InitializeAccount2 {
1418
+ owner: *owner_pubkey,
1419
+ }
1420
+ .pack();
1421
+
1422
+ let accounts = vec![
1423
+ AccountMeta::new(*account_pubkey, false),
1424
+ AccountMeta::new_readonly(*mint_pubkey, false),
1425
+ AccountMeta::new_readonly(sysvar::rent::id(), false),
1426
+ ];
1427
+
1428
+ Ok(Instruction {
1429
+ program_id: *token_program_id,
1430
+ accounts,
1431
+ data,
1432
+ })
1433
+ }
1434
+
1435
+ /// Creates a `InitializeAccount3` instruction.
1436
+ pub fn initialize_account3(
1437
+ token_program_id: &Address,
1438
+ account_pubkey: &Address,
1439
+ mint_pubkey: &Address,
1440
+ owner_pubkey: &Address,
1441
+ ) -> Result<Instruction, ProgramError> {
1442
+ check_spl_token_program_account(token_program_id)?;
1443
+ let data = TokenInstruction::InitializeAccount3 {
1444
+ owner: *owner_pubkey,
1445
+ }
1446
+ .pack();
1447
+
1448
+ let accounts = vec![
1449
+ AccountMeta::new(*account_pubkey, false),
1450
+ AccountMeta::new_readonly(*mint_pubkey, false),
1451
+ ];
1452
+
1453
+ Ok(Instruction {
1454
+ program_id: *token_program_id,
1455
+ accounts,
1456
+ data,
1457
+ })
1458
+ }
1459
+
1460
+ /// Creates a `InitializeMultisig` instruction.
1461
+ pub fn initialize_multisig(
1462
+ token_program_id: &Address,
1463
+ multisig_pubkey: &Address,
1464
+ signer_pubkeys: &[&Address],
1465
+ m: u8,
1466
+ ) -> Result<Instruction, ProgramError> {
1467
+ check_spl_token_program_account(token_program_id)?;
1468
+ if !is_valid_signer_index(m as usize)
1469
+ || !is_valid_signer_index(signer_pubkeys.len())
1470
+ || m as usize > signer_pubkeys.len()
1471
+ {
1472
+ return Err(ProgramError::MissingRequiredSignature);
1473
+ }
1474
+ let data = TokenInstruction::InitializeMultisig { m }.pack();
1475
+
1476
+ let mut accounts = Vec::with_capacity(1 + 1 + signer_pubkeys.len());
1477
+ accounts.push(AccountMeta::new(*multisig_pubkey, false));
1478
+ accounts.push(AccountMeta::new_readonly(sysvar::rent::id(), false));
1479
+ for signer_pubkey in signer_pubkeys.iter() {
1480
+ accounts.push(AccountMeta::new_readonly(**signer_pubkey, false));
1481
+ }
1482
+
1483
+ Ok(Instruction {
1484
+ program_id: *token_program_id,
1485
+ accounts,
1486
+ data,
1487
+ })
1488
+ }
1489
+
1490
+ /// Creates a `InitializeMultisig2` instruction.
1491
+ pub fn initialize_multisig2(
1492
+ token_program_id: &Address,
1493
+ multisig_pubkey: &Address,
1494
+ signer_pubkeys: &[&Address],
1495
+ m: u8,
1496
+ ) -> Result<Instruction, ProgramError> {
1497
+ check_spl_token_program_account(token_program_id)?;
1498
+ if !is_valid_signer_index(m as usize)
1499
+ || !is_valid_signer_index(signer_pubkeys.len())
1500
+ || m as usize > signer_pubkeys.len()
1501
+ {
1502
+ return Err(ProgramError::MissingRequiredSignature);
1503
+ }
1504
+ let data = TokenInstruction::InitializeMultisig2 { m }.pack();
1505
+
1506
+ let mut accounts = Vec::with_capacity(1 + 1 + signer_pubkeys.len());
1507
+ accounts.push(AccountMeta::new(*multisig_pubkey, false));
1508
+ for signer_pubkey in signer_pubkeys.iter() {
1509
+ accounts.push(AccountMeta::new_readonly(**signer_pubkey, false));
1510
+ }
1511
+
1512
+ Ok(Instruction {
1513
+ program_id: *token_program_id,
1514
+ accounts,
1515
+ data,
1516
+ })
1517
+ }
1518
+
1519
+ /// Creates a `Transfer` instruction.
1520
+ #[deprecated(
1521
+ since = "4.0.0",
1522
+ note = "please use `transfer_checked` or `transfer_checked_with_fee` instead"
1523
+ )]
1524
+ pub fn transfer(
1525
+ token_program_id: &Address,
1526
+ source_pubkey: &Address,
1527
+ destination_pubkey: &Address,
1528
+ authority_pubkey: &Address,
1529
+ signer_pubkeys: &[&Address],
1530
+ amount: u64,
1531
+ ) -> Result<Instruction, ProgramError> {
1532
+ check_spl_token_program_account(token_program_id)?;
1533
+ #[allow(deprecated)]
1534
+ let data = TokenInstruction::Transfer { amount }.pack();
1535
+
1536
+ let mut accounts = Vec::with_capacity(3 + signer_pubkeys.len());
1537
+ accounts.push(AccountMeta::new(*source_pubkey, false));
1538
+ accounts.push(AccountMeta::new(*destination_pubkey, false));
1539
+ accounts.push(AccountMeta::new_readonly(
1540
+ *authority_pubkey,
1541
+ signer_pubkeys.is_empty(),
1542
+ ));
1543
+ for signer_pubkey in signer_pubkeys.iter() {
1544
+ accounts.push(AccountMeta::new_readonly(**signer_pubkey, true));
1545
+ }
1546
+
1547
+ Ok(Instruction {
1548
+ program_id: *token_program_id,
1549
+ accounts,
1550
+ data,
1551
+ })
1552
+ }
1553
+
1554
+ /// Creates an `Approve` instruction.
1555
+ pub fn approve(
1556
+ token_program_id: &Address,
1557
+ source_pubkey: &Address,
1558
+ delegate_pubkey: &Address,
1559
+ owner_pubkey: &Address,
1560
+ signer_pubkeys: &[&Address],
1561
+ amount: u64,
1562
+ ) -> Result<Instruction, ProgramError> {
1563
+ check_spl_token_program_account(token_program_id)?;
1564
+ let data = TokenInstruction::Approve { amount }.pack();
1565
+
1566
+ let mut accounts = Vec::with_capacity(3 + signer_pubkeys.len());
1567
+ accounts.push(AccountMeta::new(*source_pubkey, false));
1568
+ accounts.push(AccountMeta::new_readonly(*delegate_pubkey, false));
1569
+ accounts.push(AccountMeta::new_readonly(
1570
+ *owner_pubkey,
1571
+ signer_pubkeys.is_empty(),
1572
+ ));
1573
+ for signer_pubkey in signer_pubkeys.iter() {
1574
+ accounts.push(AccountMeta::new_readonly(**signer_pubkey, true));
1575
+ }
1576
+
1577
+ Ok(Instruction {
1578
+ program_id: *token_program_id,
1579
+ accounts,
1580
+ data,
1581
+ })
1582
+ }
1583
+
1584
+ /// Creates a `Revoke` instruction.
1585
+ pub fn revoke(
1586
+ token_program_id: &Address,
1587
+ source_pubkey: &Address,
1588
+ owner_pubkey: &Address,
1589
+ signer_pubkeys: &[&Address],
1590
+ ) -> Result<Instruction, ProgramError> {
1591
+ check_spl_token_program_account(token_program_id)?;
1592
+ let data = TokenInstruction::Revoke.pack();
1593
+
1594
+ let mut accounts = Vec::with_capacity(2 + signer_pubkeys.len());
1595
+ accounts.push(AccountMeta::new(*source_pubkey, false));
1596
+ accounts.push(AccountMeta::new_readonly(
1597
+ *owner_pubkey,
1598
+ signer_pubkeys.is_empty(),
1599
+ ));
1600
+ for signer_pubkey in signer_pubkeys.iter() {
1601
+ accounts.push(AccountMeta::new_readonly(**signer_pubkey, true));
1602
+ }
1603
+
1604
+ Ok(Instruction {
1605
+ program_id: *token_program_id,
1606
+ accounts,
1607
+ data,
1608
+ })
1609
+ }
1610
+
1611
+ /// Creates a `SetAuthority` instruction.
1612
+ pub fn set_authority(
1613
+ token_program_id: &Address,
1614
+ owned_pubkey: &Address,
1615
+ new_authority_pubkey: Option<&Address>,
1616
+ authority_type: AuthorityType,
1617
+ owner_pubkey: &Address,
1618
+ signer_pubkeys: &[&Address],
1619
+ ) -> Result<Instruction, ProgramError> {
1620
+ check_spl_token_program_account(token_program_id)?;
1621
+ let new_authority = new_authority_pubkey.cloned().into();
1622
+ let data = TokenInstruction::SetAuthority {
1623
+ authority_type,
1624
+ new_authority,
1625
+ }
1626
+ .pack();
1627
+
1628
+ let mut accounts = Vec::with_capacity(3 + signer_pubkeys.len());
1629
+ accounts.push(AccountMeta::new(*owned_pubkey, false));
1630
+ accounts.push(AccountMeta::new_readonly(
1631
+ *owner_pubkey,
1632
+ signer_pubkeys.is_empty(),
1633
+ ));
1634
+ for signer_pubkey in signer_pubkeys.iter() {
1635
+ accounts.push(AccountMeta::new_readonly(**signer_pubkey, true));
1636
+ }
1637
+
1638
+ Ok(Instruction {
1639
+ program_id: *token_program_id,
1640
+ accounts,
1641
+ data,
1642
+ })
1643
+ }
1644
+
1645
+ /// Creates a `MintTo` instruction.
1646
+ pub fn mint_to(
1647
+ token_program_id: &Address,
1648
+ mint_pubkey: &Address,
1649
+ account_pubkey: &Address,
1650
+ mint_authority_pubkey: &Address,
1651
+ signer_pubkeys: &[&Address],
1652
+ amount: u64,
1653
+ ) -> Result<Instruction, ProgramError> {
1654
+ check_spl_token_program_account(token_program_id)?;
1655
+ let data = TokenInstruction::MintTo { amount }.pack();
1656
+
1657
+ let mut accounts = Vec::with_capacity(3 + signer_pubkeys.len());
1658
+ accounts.push(AccountMeta::new(*mint_pubkey, false));
1659
+ accounts.push(AccountMeta::new(*account_pubkey, false));
1660
+ accounts.push(AccountMeta::new_readonly(
1661
+ *mint_authority_pubkey,
1662
+ signer_pubkeys.is_empty(),
1663
+ ));
1664
+ for signer_pubkey in signer_pubkeys.iter() {
1665
+ accounts.push(AccountMeta::new_readonly(**signer_pubkey, true));
1666
+ }
1667
+
1668
+ Ok(Instruction {
1669
+ program_id: *token_program_id,
1670
+ accounts,
1671
+ data,
1672
+ })
1673
+ }
1674
+
1675
+ /// Creates a `Burn` instruction.
1676
+ pub fn burn(
1677
+ token_program_id: &Address,
1678
+ account_pubkey: &Address,
1679
+ mint_pubkey: &Address,
1680
+ authority_pubkey: &Address,
1681
+ signer_pubkeys: &[&Address],
1682
+ amount: u64,
1683
+ ) -> Result<Instruction, ProgramError> {
1684
+ check_spl_token_program_account(token_program_id)?;
1685
+ let data = TokenInstruction::Burn { amount }.pack();
1686
+
1687
+ let mut accounts = Vec::with_capacity(3 + signer_pubkeys.len());
1688
+ accounts.push(AccountMeta::new(*account_pubkey, false));
1689
+ accounts.push(AccountMeta::new(*mint_pubkey, false));
1690
+ accounts.push(AccountMeta::new_readonly(
1691
+ *authority_pubkey,
1692
+ signer_pubkeys.is_empty(),
1693
+ ));
1694
+ for signer_pubkey in signer_pubkeys.iter() {
1695
+ accounts.push(AccountMeta::new_readonly(**signer_pubkey, true));
1696
+ }
1697
+
1698
+ Ok(Instruction {
1699
+ program_id: *token_program_id,
1700
+ accounts,
1701
+ data,
1702
+ })
1703
+ }
1704
+
1705
+ /// Creates a `CloseAccount` instruction.
1706
+ pub fn close_account(
1707
+ token_program_id: &Address,
1708
+ account_pubkey: &Address,
1709
+ destination_pubkey: &Address,
1710
+ owner_pubkey: &Address,
1711
+ signer_pubkeys: &[&Address],
1712
+ ) -> Result<Instruction, ProgramError> {
1713
+ check_spl_token_program_account(token_program_id)?;
1714
+ let data = TokenInstruction::CloseAccount.pack();
1715
+
1716
+ let mut accounts = Vec::with_capacity(3 + signer_pubkeys.len());
1717
+ accounts.push(AccountMeta::new(*account_pubkey, false));
1718
+ accounts.push(AccountMeta::new(*destination_pubkey, false));
1719
+ accounts.push(AccountMeta::new_readonly(
1720
+ *owner_pubkey,
1721
+ signer_pubkeys.is_empty(),
1722
+ ));
1723
+ for signer_pubkey in signer_pubkeys.iter() {
1724
+ accounts.push(AccountMeta::new_readonly(**signer_pubkey, true));
1725
+ }
1726
+
1727
+ Ok(Instruction {
1728
+ program_id: *token_program_id,
1729
+ accounts,
1730
+ data,
1731
+ })
1732
+ }
1733
+
1734
+ /// Creates a `FreezeAccount` instruction.
1735
+ pub fn freeze_account(
1736
+ token_program_id: &Address,
1737
+ account_pubkey: &Address,
1738
+ mint_pubkey: &Address,
1739
+ freeze_authority_pubkey: &Address,
1740
+ signer_pubkeys: &[&Address],
1741
+ ) -> Result<Instruction, ProgramError> {
1742
+ check_spl_token_program_account(token_program_id)?;
1743
+ let data = TokenInstruction::FreezeAccount.pack();
1744
+
1745
+ let mut accounts = Vec::with_capacity(3 + signer_pubkeys.len());
1746
+ accounts.push(AccountMeta::new(*account_pubkey, false));
1747
+ accounts.push(AccountMeta::new_readonly(*mint_pubkey, false));
1748
+ accounts.push(AccountMeta::new_readonly(
1749
+ *freeze_authority_pubkey,
1750
+ signer_pubkeys.is_empty(),
1751
+ ));
1752
+ for signer_pubkey in signer_pubkeys.iter() {
1753
+ accounts.push(AccountMeta::new_readonly(**signer_pubkey, true));
1754
+ }
1755
+
1756
+ Ok(Instruction {
1757
+ program_id: *token_program_id,
1758
+ accounts,
1759
+ data,
1760
+ })
1761
+ }
1762
+
1763
+ /// Creates a `ThawAccount` instruction.
1764
+ pub fn thaw_account(
1765
+ token_program_id: &Address,
1766
+ account_pubkey: &Address,
1767
+ mint_pubkey: &Address,
1768
+ freeze_authority_pubkey: &Address,
1769
+ signer_pubkeys: &[&Address],
1770
+ ) -> Result<Instruction, ProgramError> {
1771
+ check_spl_token_program_account(token_program_id)?;
1772
+ let data = TokenInstruction::ThawAccount.pack();
1773
+
1774
+ let mut accounts = Vec::with_capacity(3 + signer_pubkeys.len());
1775
+ accounts.push(AccountMeta::new(*account_pubkey, false));
1776
+ accounts.push(AccountMeta::new_readonly(*mint_pubkey, false));
1777
+ accounts.push(AccountMeta::new_readonly(
1778
+ *freeze_authority_pubkey,
1779
+ signer_pubkeys.is_empty(),
1780
+ ));
1781
+ for signer_pubkey in signer_pubkeys.iter() {
1782
+ accounts.push(AccountMeta::new_readonly(**signer_pubkey, true));
1783
+ }
1784
+
1785
+ Ok(Instruction {
1786
+ program_id: *token_program_id,
1787
+ accounts,
1788
+ data,
1789
+ })
1790
+ }
1791
+
1792
+ /// Creates a `TransferChecked` instruction.
1793
+ #[allow(clippy::too_many_arguments)]
1794
+ pub fn transfer_checked(
1795
+ token_program_id: &Address,
1796
+ source_pubkey: &Address,
1797
+ mint_pubkey: &Address,
1798
+ destination_pubkey: &Address,
1799
+ authority_pubkey: &Address,
1800
+ signer_pubkeys: &[&Address],
1801
+ amount: u64,
1802
+ decimals: u8,
1803
+ ) -> Result<Instruction, ProgramError> {
1804
+ check_spl_token_program_account(token_program_id)?;
1805
+ let data = TokenInstruction::TransferChecked { amount, decimals }.pack();
1806
+
1807
+ let mut accounts = Vec::with_capacity(4 + signer_pubkeys.len());
1808
+ accounts.push(AccountMeta::new(*source_pubkey, false));
1809
+ accounts.push(AccountMeta::new_readonly(*mint_pubkey, false));
1810
+ accounts.push(AccountMeta::new(*destination_pubkey, false));
1811
+ accounts.push(AccountMeta::new_readonly(
1812
+ *authority_pubkey,
1813
+ signer_pubkeys.is_empty(),
1814
+ ));
1815
+ for signer_pubkey in signer_pubkeys.iter() {
1816
+ accounts.push(AccountMeta::new_readonly(**signer_pubkey, true));
1817
+ }
1818
+
1819
+ Ok(Instruction {
1820
+ program_id: *token_program_id,
1821
+ accounts,
1822
+ data,
1823
+ })
1824
+ }
1825
+
1826
+ /// Creates an `ApproveChecked` instruction.
1827
+ #[allow(clippy::too_many_arguments)]
1828
+ pub fn approve_checked(
1829
+ token_program_id: &Address,
1830
+ source_pubkey: &Address,
1831
+ mint_pubkey: &Address,
1832
+ delegate_pubkey: &Address,
1833
+ owner_pubkey: &Address,
1834
+ signer_pubkeys: &[&Address],
1835
+ amount: u64,
1836
+ decimals: u8,
1837
+ ) -> Result<Instruction, ProgramError> {
1838
+ check_spl_token_program_account(token_program_id)?;
1839
+ let data = TokenInstruction::ApproveChecked { amount, decimals }.pack();
1840
+
1841
+ let mut accounts = Vec::with_capacity(4 + signer_pubkeys.len());
1842
+ accounts.push(AccountMeta::new(*source_pubkey, false));
1843
+ accounts.push(AccountMeta::new_readonly(*mint_pubkey, false));
1844
+ accounts.push(AccountMeta::new_readonly(*delegate_pubkey, false));
1845
+ accounts.push(AccountMeta::new_readonly(
1846
+ *owner_pubkey,
1847
+ signer_pubkeys.is_empty(),
1848
+ ));
1849
+ for signer_pubkey in signer_pubkeys.iter() {
1850
+ accounts.push(AccountMeta::new_readonly(**signer_pubkey, true));
1851
+ }
1852
+
1853
+ Ok(Instruction {
1854
+ program_id: *token_program_id,
1855
+ accounts,
1856
+ data,
1857
+ })
1858
+ }
1859
+
1860
+ /// Creates a `MintToChecked` instruction.
1861
+ pub fn mint_to_checked(
1862
+ token_program_id: &Address,
1863
+ mint_pubkey: &Address,
1864
+ account_pubkey: &Address,
1865
+ mint_authority_pubkey: &Address,
1866
+ signer_pubkeys: &[&Address],
1867
+ amount: u64,
1868
+ decimals: u8,
1869
+ ) -> Result<Instruction, ProgramError> {
1870
+ check_spl_token_program_account(token_program_id)?;
1871
+ let data = TokenInstruction::MintToChecked { amount, decimals }.pack();
1872
+
1873
+ let mut accounts = Vec::with_capacity(3 + signer_pubkeys.len());
1874
+ accounts.push(AccountMeta::new(*mint_pubkey, false));
1875
+ accounts.push(AccountMeta::new(*account_pubkey, false));
1876
+ accounts.push(AccountMeta::new_readonly(
1877
+ *mint_authority_pubkey,
1878
+ signer_pubkeys.is_empty(),
1879
+ ));
1880
+ for signer_pubkey in signer_pubkeys.iter() {
1881
+ accounts.push(AccountMeta::new_readonly(**signer_pubkey, true));
1882
+ }
1883
+
1884
+ Ok(Instruction {
1885
+ program_id: *token_program_id,
1886
+ accounts,
1887
+ data,
1888
+ })
1889
+ }
1890
+
1891
+ /// Creates a `BurnChecked` instruction.
1892
+ pub fn burn_checked(
1893
+ token_program_id: &Address,
1894
+ account_pubkey: &Address,
1895
+ mint_pubkey: &Address,
1896
+ authority_pubkey: &Address,
1897
+ signer_pubkeys: &[&Address],
1898
+ amount: u64,
1899
+ decimals: u8,
1900
+ ) -> Result<Instruction, ProgramError> {
1901
+ check_spl_token_program_account(token_program_id)?;
1902
+ let data = TokenInstruction::BurnChecked { amount, decimals }.pack();
1903
+
1904
+ let mut accounts = Vec::with_capacity(3 + signer_pubkeys.len());
1905
+ accounts.push(AccountMeta::new(*account_pubkey, false));
1906
+ accounts.push(AccountMeta::new(*mint_pubkey, false));
1907
+ accounts.push(AccountMeta::new_readonly(
1908
+ *authority_pubkey,
1909
+ signer_pubkeys.is_empty(),
1910
+ ));
1911
+ for signer_pubkey in signer_pubkeys.iter() {
1912
+ accounts.push(AccountMeta::new_readonly(**signer_pubkey, true));
1913
+ }
1914
+
1915
+ Ok(Instruction {
1916
+ program_id: *token_program_id,
1917
+ accounts,
1918
+ data,
1919
+ })
1920
+ }
1921
+
1922
+ /// Creates a `SyncNative` instruction
1923
+ pub fn sync_native(
1924
+ token_program_id: &Address,
1925
+ account_pubkey: &Address,
1926
+ ) -> Result<Instruction, ProgramError> {
1927
+ check_spl_token_program_account(token_program_id)?;
1928
+
1929
+ Ok(Instruction {
1930
+ program_id: *token_program_id,
1931
+ accounts: vec![AccountMeta::new(*account_pubkey, false)],
1932
+ data: TokenInstruction::SyncNative.pack(),
1933
+ })
1934
+ }
1935
+
1936
+ /// Creates a `SyncNative` instruction with the Rent sysvar account
1937
+ /// added to the accounts list.
1938
+ pub fn sync_native_with_rent_sysvar(
1939
+ token_program_id: &Address,
1940
+ account_pubkey: &Address,
1941
+ ) -> Result<Instruction, ProgramError> {
1942
+ let mut instruction = sync_native(token_program_id, account_pubkey)?;
1943
+ instruction
1944
+ .accounts
1945
+ .push(AccountMeta::new_readonly(sysvar::rent::id(), false));
1946
+
1947
+ Ok(instruction)
1948
+ }
1949
+
1950
+ /// Creates a `GetAccountDataSize` instruction
1951
+ pub fn get_account_data_size(
1952
+ token_program_id: &Address,
1953
+ mint_pubkey: &Address,
1954
+ extension_types: &[ExtensionType],
1955
+ ) -> Result<Instruction, ProgramError> {
1956
+ check_spl_token_program_account(token_program_id)?;
1957
+ Ok(Instruction {
1958
+ program_id: *token_program_id,
1959
+ accounts: vec![AccountMeta::new_readonly(*mint_pubkey, false)],
1960
+ data: TokenInstruction::GetAccountDataSize {
1961
+ extension_types: extension_types.to_vec(),
1962
+ }
1963
+ .pack(),
1964
+ })
1965
+ }
1966
+
1967
+ /// Creates an `InitializeMintCloseAuthority` instruction
1968
+ pub fn initialize_mint_close_authority(
1969
+ token_program_id: &Address,
1970
+ mint_pubkey: &Address,
1971
+ close_authority: Option<&Address>,
1972
+ ) -> Result<Instruction, ProgramError> {
1973
+ check_program_account(token_program_id)?;
1974
+ let close_authority = close_authority.cloned().into();
1975
+ Ok(Instruction {
1976
+ program_id: *token_program_id,
1977
+ accounts: vec![AccountMeta::new(*mint_pubkey, false)],
1978
+ data: TokenInstruction::InitializeMintCloseAuthority { close_authority }.pack(),
1979
+ })
1980
+ }
1981
+
1982
+ /// Create an `InitializeImmutableOwner` instruction
1983
+ pub fn initialize_immutable_owner(
1984
+ token_program_id: &Address,
1985
+ token_account: &Address,
1986
+ ) -> Result<Instruction, ProgramError> {
1987
+ check_spl_token_program_account(token_program_id)?;
1988
+ Ok(Instruction {
1989
+ program_id: *token_program_id,
1990
+ accounts: vec![AccountMeta::new(*token_account, false)],
1991
+ data: TokenInstruction::InitializeImmutableOwner.pack(),
1992
+ })
1993
+ }
1994
+
1995
+ /// Creates an `AmountToUiAmount` instruction
1996
+ pub fn amount_to_ui_amount(
1997
+ token_program_id: &Address,
1998
+ mint_pubkey: &Address,
1999
+ amount: u64,
2000
+ ) -> Result<Instruction, ProgramError> {
2001
+ check_spl_token_program_account(token_program_id)?;
2002
+
2003
+ Ok(Instruction {
2004
+ program_id: *token_program_id,
2005
+ accounts: vec![AccountMeta::new_readonly(*mint_pubkey, false)],
2006
+ data: TokenInstruction::AmountToUiAmount { amount }.pack(),
2007
+ })
2008
+ }
2009
+
2010
+ /// Creates a `UiAmountToAmount` instruction
2011
+ pub fn ui_amount_to_amount(
2012
+ token_program_id: &Address,
2013
+ mint_pubkey: &Address,
2014
+ ui_amount: &str,
2015
+ ) -> Result<Instruction, ProgramError> {
2016
+ check_spl_token_program_account(token_program_id)?;
2017
+
2018
+ Ok(Instruction {
2019
+ program_id: *token_program_id,
2020
+ accounts: vec![AccountMeta::new_readonly(*mint_pubkey, false)],
2021
+ data: TokenInstruction::UiAmountToAmount { ui_amount }.pack(),
2022
+ })
2023
+ }
2024
+
2025
+ /// Creates a `Reallocate` instruction
2026
+ pub fn reallocate(
2027
+ token_program_id: &Address,
2028
+ account_pubkey: &Address,
2029
+ payer: &Address,
2030
+ owner_pubkey: &Address,
2031
+ signer_pubkeys: &[&Address],
2032
+ extension_types: &[ExtensionType],
2033
+ ) -> Result<Instruction, ProgramError> {
2034
+ check_program_account(token_program_id)?;
2035
+
2036
+ let mut accounts = Vec::with_capacity(4 + signer_pubkeys.len());
2037
+ accounts.push(AccountMeta::new(*account_pubkey, false));
2038
+ accounts.push(AccountMeta::new(*payer, true));
2039
+ accounts.push(AccountMeta::new_readonly(system_program::id(), false));
2040
+ accounts.push(AccountMeta::new_readonly(
2041
+ *owner_pubkey,
2042
+ signer_pubkeys.is_empty(),
2043
+ ));
2044
+ for signer_pubkey in signer_pubkeys.iter() {
2045
+ accounts.push(AccountMeta::new_readonly(**signer_pubkey, true));
2046
+ }
2047
+
2048
+ Ok(Instruction {
2049
+ program_id: *token_program_id,
2050
+ accounts,
2051
+ data: TokenInstruction::Reallocate {
2052
+ extension_types: extension_types.to_vec(),
2053
+ }
2054
+ .pack(),
2055
+ })
2056
+ }
2057
+
2058
+ /// Creates a `CreateNativeMint` instruction
2059
+ pub fn create_native_mint(
2060
+ token_program_id: &Address,
2061
+ payer: &Address,
2062
+ ) -> Result<Instruction, ProgramError> {
2063
+ check_program_account(token_program_id)?;
2064
+
2065
+ Ok(Instruction {
2066
+ program_id: *token_program_id,
2067
+ accounts: vec![
2068
+ AccountMeta::new(*payer, true),
2069
+ AccountMeta::new(crate::native_mint::id(), false),
2070
+ AccountMeta::new_readonly(system_program::id(), false),
2071
+ ],
2072
+ data: TokenInstruction::CreateNativeMint.pack(),
2073
+ })
2074
+ }
2075
+
2076
+ /// Creates an `InitializeNonTransferableMint` instruction
2077
+ pub fn initialize_non_transferable_mint(
2078
+ token_program_id: &Address,
2079
+ mint_pubkey: &Address,
2080
+ ) -> Result<Instruction, ProgramError> {
2081
+ check_program_account(token_program_id)?;
2082
+ Ok(Instruction {
2083
+ program_id: *token_program_id,
2084
+ accounts: vec![AccountMeta::new(*mint_pubkey, false)],
2085
+ data: TokenInstruction::InitializeNonTransferableMint.pack(),
2086
+ })
2087
+ }
2088
+
2089
+ /// Creates an `InitializePermanentDelegate` instruction
2090
+ pub fn initialize_permanent_delegate(
2091
+ token_program_id: &Address,
2092
+ mint_pubkey: &Address,
2093
+ delegate: &Address,
2094
+ ) -> Result<Instruction, ProgramError> {
2095
+ check_program_account(token_program_id)?;
2096
+ Ok(Instruction {
2097
+ program_id: *token_program_id,
2098
+ accounts: vec![AccountMeta::new(*mint_pubkey, false)],
2099
+ data: TokenInstruction::InitializePermanentDelegate {
2100
+ delegate: *delegate,
2101
+ }
2102
+ .pack(),
2103
+ })
2104
+ }
2105
+
2106
+ /// Utility function that checks index is between `MIN_SIGNERS` and
2107
+ /// `MAX_SIGNERS`
2108
+ pub fn is_valid_signer_index(index: usize) -> bool {
2109
+ (MIN_SIGNERS..=MAX_SIGNERS).contains(&index)
2110
+ }
2111
+
2112
+ /// Utility function for decoding just the instruction type
2113
+ pub fn decode_instruction_type<T: TryFrom<u8>>(input: &[u8]) -> Result<T, ProgramError> {
2114
+ if input.is_empty() {
2115
+ Err(ProgramError::InvalidInstructionData)
2116
+ } else {
2117
+ T::try_from(input[0]).map_err(|_| TokenError::InvalidInstruction.into())
2118
+ }
2119
+ }
2120
+
2121
+ /// Utility function for decoding instruction data
2122
+ ///
2123
+ /// Note: This function expects the entire instruction input, including the
2124
+ /// instruction type as the first byte. This makes the code concise and safe
2125
+ /// at the expense of clarity, allowing flows such as:
2126
+ ///
2127
+ /// ```
2128
+ /// use spl_token_2022_interface::instruction::{decode_instruction_data, decode_instruction_type};
2129
+ /// use num_enum::TryFromPrimitive;
2130
+ /// use bytemuck::{Pod, Zeroable};
2131
+ ///
2132
+ /// #[repr(u8)]
2133
+ /// #[derive(Clone, Copy, TryFromPrimitive)]
2134
+ /// enum InstructionType {
2135
+ /// First
2136
+ /// }
2137
+ /// #[derive(Pod, Zeroable, Copy, Clone)]
2138
+ /// #[repr(transparent)]
2139
+ /// struct FirstData {
2140
+ /// a: u8,
2141
+ /// }
2142
+ /// let input = [0, 1];
2143
+ /// match decode_instruction_type(&input).unwrap() {
2144
+ /// InstructionType::First => {
2145
+ /// let FirstData { a } = decode_instruction_data(&input).unwrap();
2146
+ /// assert_eq!(*a, 1);
2147
+ /// }
2148
+ /// }
2149
+ /// ```
2150
+ pub fn decode_instruction_data<T: Pod>(input_with_type: &[u8]) -> Result<&T, ProgramError> {
2151
+ if input_with_type.len() != size_of::<T>().saturating_add(1) {
2152
+ Err(ProgramError::InvalidInstructionData)
2153
+ } else {
2154
+ bytemuck::try_from_bytes(&input_with_type[1..]).map_err(|_| ProgramError::InvalidArgument)
2155
+ }
2156
+ }
2157
+
2158
+ /// Utility function for encoding instruction data
2159
+ pub(crate) fn encode_instruction<T: Into<u8>, D: Pod>(
2160
+ token_program_id: &Address,
2161
+ accounts: Vec<AccountMeta>,
2162
+ token_instruction_type: TokenInstruction,
2163
+ instruction_type: T,
2164
+ instruction_data: &D,
2165
+ ) -> Instruction {
2166
+ let mut data = token_instruction_type.pack();
2167
+ data.push(T::into(instruction_type));
2168
+ data.extend_from_slice(bytemuck::bytes_of(instruction_data));
2169
+ Instruction {
2170
+ program_id: *token_program_id,
2171
+ accounts,
2172
+ data,
2173
+ }
2174
+ }
2175
+
2176
+ /// Creates a `WithdrawExcessLamports` Instruction
2177
+ pub fn withdraw_excess_lamports(
2178
+ token_program_id: &Address,
2179
+ source_account: &Address,
2180
+ destination_account: &Address,
2181
+ authority: &Address,
2182
+ signers: &[&Address],
2183
+ ) -> Result<Instruction, ProgramError> {
2184
+ check_program_account(token_program_id)?;
2185
+
2186
+ let mut accounts = vec![
2187
+ AccountMeta::new(*source_account, false),
2188
+ AccountMeta::new(*destination_account, false),
2189
+ AccountMeta::new_readonly(*authority, signers.is_empty()),
2190
+ ];
2191
+
2192
+ for signer in signers {
2193
+ accounts.push(AccountMeta::new_readonly(**signer, true))
2194
+ }
2195
+
2196
+ Ok(Instruction {
2197
+ program_id: *token_program_id,
2198
+ accounts,
2199
+ data: TokenInstruction::WithdrawExcessLamports.pack(),
2200
+ })
2201
+ }
2202
+
2203
+ /// Creates an `UnwrapLamports` instruction
2204
+ pub fn unwrap_lamports(
2205
+ token_program_id: &Address,
2206
+ source_pubkey: &Address,
2207
+ destination_pubkey: &Address,
2208
+ authority_pubkey: &Address,
2209
+ signer_pubkeys: &[&Address],
2210
+ amount: Option<u64>,
2211
+ ) -> Result<Instruction, ProgramError> {
2212
+ check_spl_token_program_account(token_program_id)?;
2213
+ let amount = amount.into();
2214
+ let data = TokenInstruction::UnwrapLamports { amount }.pack();
2215
+
2216
+ let mut accounts = Vec::with_capacity(3 + signer_pubkeys.len());
2217
+ accounts.push(AccountMeta::new(*source_pubkey, false));
2218
+ accounts.push(AccountMeta::new(*destination_pubkey, false));
2219
+ accounts.push(AccountMeta::new_readonly(
2220
+ *authority_pubkey,
2221
+ signer_pubkeys.is_empty(),
2222
+ ));
2223
+ for signer_pubkey in signer_pubkeys.iter() {
2224
+ accounts.push(AccountMeta::new_readonly(**signer_pubkey, true));
2225
+ }
2226
+
2227
+ Ok(Instruction {
2228
+ program_id: *token_program_id,
2229
+ accounts,
2230
+ data,
2231
+ })
2232
+ }
2233
+
2234
+ #[cfg(test)]
2235
+ mod test {
2236
+ use {super::*, proptest::prelude::*};
2237
+
2238
+ #[test]
2239
+ fn test_initialize_mint_packing() {
2240
+ let decimals = 2;
2241
+ let mint_authority = Address::new_from_array([1u8; 32]);
2242
+ let freeze_authority = COption::None;
2243
+ let check = TokenInstruction::InitializeMint {
2244
+ decimals,
2245
+ mint_authority,
2246
+ freeze_authority,
2247
+ };
2248
+ let packed = check.pack();
2249
+ let mut expect = Vec::from([0u8, 2]);
2250
+ expect.extend_from_slice(&[1u8; 32]);
2251
+ expect.extend_from_slice(&[0]);
2252
+ assert_eq!(packed, expect);
2253
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
2254
+ assert_eq!(unpacked, check);
2255
+
2256
+ let mint_authority = Address::new_from_array([2u8; 32]);
2257
+ let freeze_authority = COption::Some(Address::new_from_array([3u8; 32]));
2258
+ let check = TokenInstruction::InitializeMint {
2259
+ decimals,
2260
+ mint_authority,
2261
+ freeze_authority,
2262
+ };
2263
+ let packed = check.pack();
2264
+ let mut expect = vec![0u8, 2];
2265
+ expect.extend_from_slice(&[2u8; 32]);
2266
+ expect.extend_from_slice(&[1]);
2267
+ expect.extend_from_slice(&[3u8; 32]);
2268
+ assert_eq!(packed, expect);
2269
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
2270
+ assert_eq!(unpacked, check);
2271
+ }
2272
+
2273
+ #[test]
2274
+ fn test_initialize_account_packing() {
2275
+ let check = TokenInstruction::InitializeAccount;
2276
+ let packed = check.pack();
2277
+ let expect = Vec::from([1u8]);
2278
+ assert_eq!(packed, expect);
2279
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
2280
+ assert_eq!(unpacked, check);
2281
+ }
2282
+
2283
+ #[test]
2284
+ fn test_initialize_multisig_packing() {
2285
+ let m = 1;
2286
+ let check = TokenInstruction::InitializeMultisig { m };
2287
+ let packed = check.pack();
2288
+ let expect = Vec::from([2u8, 1]);
2289
+ assert_eq!(packed, expect);
2290
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
2291
+ assert_eq!(unpacked, check);
2292
+ }
2293
+
2294
+ #[test]
2295
+ fn test_transfer_packing() {
2296
+ let amount = 1;
2297
+ #[allow(deprecated)]
2298
+ let check = TokenInstruction::Transfer { amount };
2299
+ let packed = check.pack();
2300
+ let expect = Vec::from([3u8, 1, 0, 0, 0, 0, 0, 0, 0]);
2301
+ assert_eq!(packed, expect);
2302
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
2303
+ assert_eq!(unpacked, check);
2304
+ }
2305
+
2306
+ #[test]
2307
+ fn test_approve_packing() {
2308
+ let amount = 1;
2309
+ let check = TokenInstruction::Approve { amount };
2310
+ let packed = check.pack();
2311
+ let expect = Vec::from([4u8, 1, 0, 0, 0, 0, 0, 0, 0]);
2312
+ assert_eq!(packed, expect);
2313
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
2314
+ assert_eq!(unpacked, check);
2315
+ }
2316
+
2317
+ #[test]
2318
+ fn test_revoke_packing() {
2319
+ let check = TokenInstruction::Revoke;
2320
+ let packed = check.pack();
2321
+ let expect = Vec::from([5u8]);
2322
+ assert_eq!(packed, expect);
2323
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
2324
+ assert_eq!(unpacked, check);
2325
+ }
2326
+
2327
+ #[test]
2328
+ fn test_set_authority_packing() {
2329
+ let authority_type = AuthorityType::FreezeAccount;
2330
+ let new_authority = COption::Some(Address::new_from_array([4u8; 32]));
2331
+ let check = TokenInstruction::SetAuthority {
2332
+ authority_type: authority_type.clone(),
2333
+ new_authority,
2334
+ };
2335
+ let packed = check.pack();
2336
+ let mut expect = Vec::from([6u8, 1]);
2337
+ expect.extend_from_slice(&[1]);
2338
+ expect.extend_from_slice(&[4u8; 32]);
2339
+ assert_eq!(packed, expect);
2340
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
2341
+ assert_eq!(unpacked, check);
2342
+ }
2343
+
2344
+ #[test]
2345
+ fn test_mint_to_packing() {
2346
+ let amount = 1;
2347
+ let check = TokenInstruction::MintTo { amount };
2348
+ let packed = check.pack();
2349
+ let expect = Vec::from([7u8, 1, 0, 0, 0, 0, 0, 0, 0]);
2350
+ assert_eq!(packed, expect);
2351
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
2352
+ assert_eq!(unpacked, check);
2353
+ }
2354
+
2355
+ #[test]
2356
+ fn test_burn_packing() {
2357
+ let amount = 1;
2358
+ let check = TokenInstruction::Burn { amount };
2359
+ let packed = check.pack();
2360
+ let expect = Vec::from([8u8, 1, 0, 0, 0, 0, 0, 0, 0]);
2361
+ assert_eq!(packed, expect);
2362
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
2363
+ assert_eq!(unpacked, check);
2364
+ }
2365
+
2366
+ #[test]
2367
+ fn test_close_account_packing() {
2368
+ let check = TokenInstruction::CloseAccount;
2369
+ let packed = check.pack();
2370
+ let expect = Vec::from([9u8]);
2371
+ assert_eq!(packed, expect);
2372
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
2373
+ assert_eq!(unpacked, check);
2374
+ }
2375
+
2376
+ #[test]
2377
+ fn test_freeze_account_packing() {
2378
+ let check = TokenInstruction::FreezeAccount;
2379
+ let packed = check.pack();
2380
+ let expect = Vec::from([10u8]);
2381
+ assert_eq!(packed, expect);
2382
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
2383
+ assert_eq!(unpacked, check);
2384
+ }
2385
+
2386
+ #[test]
2387
+ fn test_thaw_account_packing() {
2388
+ let check = TokenInstruction::ThawAccount;
2389
+ let packed = check.pack();
2390
+ let expect = Vec::from([11u8]);
2391
+ assert_eq!(packed, expect);
2392
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
2393
+ assert_eq!(unpacked, check);
2394
+ }
2395
+
2396
+ #[test]
2397
+ fn test_transfer_checked_packing() {
2398
+ let amount = 1;
2399
+ let decimals = 2;
2400
+ let check = TokenInstruction::TransferChecked { amount, decimals };
2401
+ let packed = check.pack();
2402
+ let expect = Vec::from([12u8, 1, 0, 0, 0, 0, 0, 0, 0, 2]);
2403
+ assert_eq!(packed, expect);
2404
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
2405
+ assert_eq!(unpacked, check);
2406
+ }
2407
+
2408
+ #[test]
2409
+ fn test_approve_checked_packing() {
2410
+ let amount = 1;
2411
+ let decimals = 2;
2412
+
2413
+ let check = TokenInstruction::ApproveChecked { amount, decimals };
2414
+ let packed = check.pack();
2415
+ let expect = Vec::from([13u8, 1, 0, 0, 0, 0, 0, 0, 0, 2]);
2416
+ assert_eq!(packed, expect);
2417
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
2418
+ assert_eq!(unpacked, check);
2419
+ }
2420
+
2421
+ #[test]
2422
+ fn test_mint_to_checked_packing() {
2423
+ let amount = 1;
2424
+ let decimals = 2;
2425
+ let check = TokenInstruction::MintToChecked { amount, decimals };
2426
+ let packed = check.pack();
2427
+ let expect = Vec::from([14u8, 1, 0, 0, 0, 0, 0, 0, 0, 2]);
2428
+ assert_eq!(packed, expect);
2429
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
2430
+ assert_eq!(unpacked, check);
2431
+ }
2432
+
2433
+ #[test]
2434
+ fn test_burn_checked_packing() {
2435
+ let amount = 1;
2436
+ let decimals = 2;
2437
+ let check = TokenInstruction::BurnChecked { amount, decimals };
2438
+ let packed = check.pack();
2439
+ let expect = Vec::from([15u8, 1, 0, 0, 0, 0, 0, 0, 0, 2]);
2440
+ assert_eq!(packed, expect);
2441
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
2442
+ assert_eq!(unpacked, check);
2443
+ }
2444
+
2445
+ #[test]
2446
+ fn test_initialize_account2_packing() {
2447
+ let owner = Address::new_from_array([2u8; 32]);
2448
+ let check = TokenInstruction::InitializeAccount2 { owner };
2449
+ let packed = check.pack();
2450
+ let mut expect = vec![16u8];
2451
+ expect.extend_from_slice(&[2u8; 32]);
2452
+ assert_eq!(packed, expect);
2453
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
2454
+ assert_eq!(unpacked, check);
2455
+ }
2456
+
2457
+ #[test]
2458
+ fn test_sync_native_packing() {
2459
+ let check = TokenInstruction::SyncNative;
2460
+ let packed = check.pack();
2461
+ let expect = vec![17u8];
2462
+ assert_eq!(packed, expect);
2463
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
2464
+ assert_eq!(unpacked, check);
2465
+ }
2466
+
2467
+ #[test]
2468
+ fn test_initialize_account3_packing() {
2469
+ let owner = Address::new_from_array([2u8; 32]);
2470
+ let check = TokenInstruction::InitializeAccount3 { owner };
2471
+ let packed = check.pack();
2472
+ let mut expect = vec![18u8];
2473
+ expect.extend_from_slice(&[2u8; 32]);
2474
+ assert_eq!(packed, expect);
2475
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
2476
+ assert_eq!(unpacked, check);
2477
+ }
2478
+
2479
+ #[test]
2480
+ fn test_initialize_multisig2_packing() {
2481
+ let m = 1;
2482
+ let check = TokenInstruction::InitializeMultisig2 { m };
2483
+ let packed = check.pack();
2484
+ let expect = Vec::from([19u8, 1]);
2485
+ assert_eq!(packed, expect);
2486
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
2487
+ assert_eq!(unpacked, check);
2488
+ }
2489
+
2490
+ #[test]
2491
+ fn test_initialize_mint2_packing() {
2492
+ let decimals = 2;
2493
+ let mint_authority = Address::new_from_array([1u8; 32]);
2494
+ let freeze_authority = COption::None;
2495
+ let check = TokenInstruction::InitializeMint2 {
2496
+ decimals,
2497
+ mint_authority,
2498
+ freeze_authority,
2499
+ };
2500
+ let packed = check.pack();
2501
+ let mut expect = Vec::from([20u8, 2]);
2502
+ expect.extend_from_slice(&[1u8; 32]);
2503
+ expect.extend_from_slice(&[0]);
2504
+ assert_eq!(packed, expect);
2505
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
2506
+ assert_eq!(unpacked, check);
2507
+
2508
+ let decimals = 2;
2509
+ let mint_authority = Address::new_from_array([2u8; 32]);
2510
+ let freeze_authority = COption::Some(Address::new_from_array([3u8; 32]));
2511
+ let check = TokenInstruction::InitializeMint2 {
2512
+ decimals,
2513
+ mint_authority,
2514
+ freeze_authority,
2515
+ };
2516
+ let packed = check.pack();
2517
+ let mut expect = vec![20u8, 2];
2518
+ expect.extend_from_slice(&[2u8; 32]);
2519
+ expect.extend_from_slice(&[1]);
2520
+ expect.extend_from_slice(&[3u8; 32]);
2521
+ assert_eq!(packed, expect);
2522
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
2523
+ assert_eq!(unpacked, check);
2524
+ }
2525
+
2526
+ #[test]
2527
+ fn test_get_account_data_size_packing() {
2528
+ let extension_types = vec![];
2529
+ let check = TokenInstruction::GetAccountDataSize {
2530
+ extension_types: extension_types.clone(),
2531
+ };
2532
+ let packed = check.pack();
2533
+ let expect = [21u8];
2534
+ assert_eq!(packed, &[21u8]);
2535
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
2536
+ assert_eq!(unpacked, check);
2537
+
2538
+ let extension_types = vec![
2539
+ ExtensionType::TransferFeeConfig,
2540
+ ExtensionType::TransferFeeAmount,
2541
+ ];
2542
+ let check = TokenInstruction::GetAccountDataSize {
2543
+ extension_types: extension_types.clone(),
2544
+ };
2545
+ let packed = check.pack();
2546
+ let expect = [21u8, 1, 0, 2, 0];
2547
+ assert_eq!(packed, &[21u8, 1, 0, 2, 0]);
2548
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
2549
+ assert_eq!(unpacked, check);
2550
+ }
2551
+
2552
+ #[test]
2553
+ fn test_amount_to_ui_amount_packing() {
2554
+ let amount = 42;
2555
+ let check = TokenInstruction::AmountToUiAmount { amount };
2556
+ let packed = check.pack();
2557
+ let expect = vec![23u8, 42, 0, 0, 0, 0, 0, 0, 0];
2558
+ assert_eq!(packed, expect);
2559
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
2560
+ assert_eq!(unpacked, check);
2561
+ }
2562
+
2563
+ #[test]
2564
+ fn test_ui_amount_to_amount_packing() {
2565
+ let ui_amount = "0.42";
2566
+ let check = TokenInstruction::UiAmountToAmount { ui_amount };
2567
+ let packed = check.pack();
2568
+ let expect = vec![24u8, 48, 46, 52, 50];
2569
+ assert_eq!(packed, expect);
2570
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
2571
+ assert_eq!(unpacked, check);
2572
+ }
2573
+
2574
+ #[test]
2575
+ fn test_initialize_mint_close_authority_packing() {
2576
+ let close_authority = COption::Some(Address::new_from_array([10u8; 32]));
2577
+ let check = TokenInstruction::InitializeMintCloseAuthority { close_authority };
2578
+ let packed = check.pack();
2579
+ let mut expect = vec![25u8, 1];
2580
+ expect.extend_from_slice(&[10u8; 32]);
2581
+ assert_eq!(packed, expect);
2582
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
2583
+ assert_eq!(unpacked, check);
2584
+ }
2585
+
2586
+ #[test]
2587
+ fn test_create_native_mint_packing() {
2588
+ let check = TokenInstruction::CreateNativeMint;
2589
+ let packed = check.pack();
2590
+ let expect = vec![31u8];
2591
+ assert_eq!(packed, expect);
2592
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
2593
+ assert_eq!(unpacked, check);
2594
+ }
2595
+
2596
+ #[test]
2597
+ fn test_initialize_permanent_delegate_packing() {
2598
+ let delegate = Address::new_from_array([11u8; 32]);
2599
+ let check = TokenInstruction::InitializePermanentDelegate { delegate };
2600
+ let packed = check.pack();
2601
+ let mut expect = vec![35u8];
2602
+ expect.extend_from_slice(&[11u8; 32]);
2603
+ assert_eq!(packed, expect);
2604
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
2605
+ assert_eq!(unpacked, check);
2606
+ }
2607
+
2608
+ #[test]
2609
+ fn test_unwrap_lamports_packing() {
2610
+ let amount = COption::None;
2611
+ let check = TokenInstruction::UnwrapLamports { amount };
2612
+ let packed = check.pack();
2613
+ let expect = Vec::from([45u8, 0]);
2614
+ assert_eq!(packed, expect);
2615
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
2616
+ assert_eq!(unpacked, check);
2617
+
2618
+ let amount = COption::Some(1);
2619
+ let check = TokenInstruction::UnwrapLamports { amount };
2620
+ let packed = check.pack();
2621
+ let expect = Vec::from([45u8, 1, 1, 0, 0, 0, 0, 0, 0, 0]);
2622
+ assert_eq!(packed, expect);
2623
+ let unpacked = TokenInstruction::unpack(&expect).unwrap();
2624
+ assert_eq!(unpacked, check);
2625
+ }
2626
+
2627
+ macro_rules! test_instruction {
2628
+ ($a:ident($($b:tt)*)) => {
2629
+ let instruction_v3 = spl_token_interface::instruction::$a($($b)*).unwrap();
2630
+ let instruction_2022 = $a($($b)*).unwrap();
2631
+ assert_eq!(instruction_v3, instruction_2022);
2632
+ }
2633
+ }
2634
+
2635
+ #[test]
2636
+ fn test_v3_compatibility() {
2637
+ let token_program_id = spl_token_interface::id();
2638
+ let mint_pubkey = Address::new_unique();
2639
+ let mint_authority_pubkey = Address::new_unique();
2640
+ let freeze_authority_pubkey = Address::new_unique();
2641
+ let decimals = 9u8;
2642
+
2643
+ let account_pubkey = Address::new_unique();
2644
+ let owner_pubkey = Address::new_unique();
2645
+
2646
+ let multisig_pubkey = Address::new_unique();
2647
+ let signer_pubkeys_vec = vec![Address::new_unique(); MAX_SIGNERS];
2648
+ let signer_pubkeys = signer_pubkeys_vec.iter().collect::<Vec<_>>();
2649
+ let m = 10u8;
2650
+
2651
+ let source_pubkey = Address::new_unique();
2652
+ let destination_pubkey = Address::new_unique();
2653
+ let authority_pubkey = Address::new_unique();
2654
+ let amount = 1_000_000_000_000;
2655
+
2656
+ let delegate_pubkey = Address::new_unique();
2657
+ let owned_pubkey = Address::new_unique();
2658
+ let new_authority_pubkey = Address::new_unique();
2659
+
2660
+ let ui_amount = "100000.00";
2661
+
2662
+ test_instruction!(initialize_mint(
2663
+ &token_program_id,
2664
+ &mint_pubkey,
2665
+ &mint_authority_pubkey,
2666
+ None,
2667
+ decimals,
2668
+ ));
2669
+ test_instruction!(initialize_mint2(
2670
+ &token_program_id,
2671
+ &mint_pubkey,
2672
+ &mint_authority_pubkey,
2673
+ Some(&freeze_authority_pubkey),
2674
+ decimals,
2675
+ ));
2676
+
2677
+ test_instruction!(initialize_account(
2678
+ &token_program_id,
2679
+ &account_pubkey,
2680
+ &mint_pubkey,
2681
+ &owner_pubkey,
2682
+ ));
2683
+ test_instruction!(initialize_account2(
2684
+ &token_program_id,
2685
+ &account_pubkey,
2686
+ &mint_pubkey,
2687
+ &owner_pubkey,
2688
+ ));
2689
+ test_instruction!(initialize_account3(
2690
+ &token_program_id,
2691
+ &account_pubkey,
2692
+ &mint_pubkey,
2693
+ &owner_pubkey,
2694
+ ));
2695
+ test_instruction!(initialize_multisig(
2696
+ &token_program_id,
2697
+ &multisig_pubkey,
2698
+ &signer_pubkeys,
2699
+ m,
2700
+ ));
2701
+ test_instruction!(initialize_multisig2(
2702
+ &token_program_id,
2703
+ &multisig_pubkey,
2704
+ &signer_pubkeys,
2705
+ m,
2706
+ ));
2707
+ #[allow(deprecated)]
2708
+ {
2709
+ test_instruction!(transfer(
2710
+ &token_program_id,
2711
+ &source_pubkey,
2712
+ &destination_pubkey,
2713
+ &authority_pubkey,
2714
+ &signer_pubkeys,
2715
+ amount
2716
+ ));
2717
+ }
2718
+ test_instruction!(transfer_checked(
2719
+ &token_program_id,
2720
+ &source_pubkey,
2721
+ &mint_pubkey,
2722
+ &destination_pubkey,
2723
+ &authority_pubkey,
2724
+ &signer_pubkeys,
2725
+ amount,
2726
+ decimals,
2727
+ ));
2728
+ test_instruction!(approve(
2729
+ &token_program_id,
2730
+ &source_pubkey,
2731
+ &delegate_pubkey,
2732
+ &owner_pubkey,
2733
+ &signer_pubkeys,
2734
+ amount
2735
+ ));
2736
+ test_instruction!(approve_checked(
2737
+ &token_program_id,
2738
+ &source_pubkey,
2739
+ &mint_pubkey,
2740
+ &delegate_pubkey,
2741
+ &owner_pubkey,
2742
+ &signer_pubkeys,
2743
+ amount,
2744
+ decimals
2745
+ ));
2746
+ test_instruction!(revoke(
2747
+ &token_program_id,
2748
+ &source_pubkey,
2749
+ &owner_pubkey,
2750
+ &signer_pubkeys,
2751
+ ));
2752
+
2753
+ // set_authority
2754
+ {
2755
+ let instruction_v3 = spl_token_interface::instruction::set_authority(
2756
+ &token_program_id,
2757
+ &owned_pubkey,
2758
+ Some(&new_authority_pubkey),
2759
+ spl_token_interface::instruction::AuthorityType::AccountOwner,
2760
+ &owner_pubkey,
2761
+ &signer_pubkeys,
2762
+ )
2763
+ .unwrap();
2764
+ let instruction_2022 = set_authority(
2765
+ &token_program_id,
2766
+ &owned_pubkey,
2767
+ Some(&new_authority_pubkey),
2768
+ AuthorityType::AccountOwner,
2769
+ &owner_pubkey,
2770
+ &signer_pubkeys,
2771
+ )
2772
+ .unwrap();
2773
+ assert_eq!(instruction_v3, instruction_2022);
2774
+ }
2775
+
2776
+ test_instruction!(mint_to(
2777
+ &token_program_id,
2778
+ &mint_pubkey,
2779
+ &account_pubkey,
2780
+ &owner_pubkey,
2781
+ &signer_pubkeys,
2782
+ amount,
2783
+ ));
2784
+ test_instruction!(mint_to_checked(
2785
+ &token_program_id,
2786
+ &mint_pubkey,
2787
+ &account_pubkey,
2788
+ &owner_pubkey,
2789
+ &signer_pubkeys,
2790
+ amount,
2791
+ decimals,
2792
+ ));
2793
+ test_instruction!(burn(
2794
+ &token_program_id,
2795
+ &account_pubkey,
2796
+ &mint_pubkey,
2797
+ &authority_pubkey,
2798
+ &signer_pubkeys,
2799
+ amount,
2800
+ ));
2801
+ test_instruction!(burn_checked(
2802
+ &token_program_id,
2803
+ &account_pubkey,
2804
+ &mint_pubkey,
2805
+ &authority_pubkey,
2806
+ &signer_pubkeys,
2807
+ amount,
2808
+ decimals,
2809
+ ));
2810
+ test_instruction!(close_account(
2811
+ &token_program_id,
2812
+ &account_pubkey,
2813
+ &destination_pubkey,
2814
+ &owner_pubkey,
2815
+ &signer_pubkeys,
2816
+ ));
2817
+ test_instruction!(freeze_account(
2818
+ &token_program_id,
2819
+ &account_pubkey,
2820
+ &mint_pubkey,
2821
+ &freeze_authority_pubkey,
2822
+ &signer_pubkeys,
2823
+ ));
2824
+ test_instruction!(thaw_account(
2825
+ &token_program_id,
2826
+ &account_pubkey,
2827
+ &mint_pubkey,
2828
+ &freeze_authority_pubkey,
2829
+ &signer_pubkeys,
2830
+ ));
2831
+ test_instruction!(sync_native(&token_program_id, &account_pubkey,));
2832
+
2833
+ // get_account_data_size
2834
+ {
2835
+ let instruction_v3 = spl_token_interface::instruction::get_account_data_size(
2836
+ &token_program_id,
2837
+ &mint_pubkey,
2838
+ )
2839
+ .unwrap();
2840
+ let instruction_2022 =
2841
+ get_account_data_size(&token_program_id, &mint_pubkey, &[]).unwrap();
2842
+ assert_eq!(instruction_v3, instruction_2022);
2843
+ }
2844
+
2845
+ test_instruction!(initialize_immutable_owner(
2846
+ &token_program_id,
2847
+ &account_pubkey,
2848
+ ));
2849
+
2850
+ test_instruction!(amount_to_ui_amount(&token_program_id, &mint_pubkey, amount,));
2851
+
2852
+ test_instruction!(ui_amount_to_amount(
2853
+ &token_program_id,
2854
+ &mint_pubkey,
2855
+ ui_amount,
2856
+ ));
2857
+ }
2858
+
2859
+ proptest! {
2860
+ #![proptest_config(ProptestConfig::with_cases(1024))]
2861
+ #[test]
2862
+ fn test_instruction_unpack_proptest(
2863
+ data in prop::collection::vec(any::<u8>(), 0..255)
2864
+ ) {
2865
+ let _no_panic = TokenInstruction::unpack(&data);
2866
+ }
2867
+ }
2868
+ }