@lightprotocol/compressed-token 0.16.0 → 0.17.1

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.
@@ -1,36 +1,7 @@
1
- import {
2
- getIndexOrAdd,
3
- bn,
4
- padOutputStateMerkleTrees,
5
- useWallet,
6
- confirmConfig,
7
- defaultStaticAccountsStruct,
8
- toArray,
9
- LightSystemProgram,
10
- defaultTestStateTreeAccounts,
11
- sumUpLamports,
12
- validateSufficientBalance,
13
- validateSameOwner,
14
- dedupeSigner,
15
- buildAndSignTx,
16
- sendAndConfirmTx,
17
- } from '@lightprotocol/stateless.js';
18
- import {
19
- PublicKey,
20
- Keypair,
21
- Connection,
22
- SystemProgram,
23
- AddressLookupTableProgram,
24
- ComputeBudgetProgram,
25
- } from '@solana/web3.js';
1
+ import { getIndexOrAdd, bn, padOutputStateMerkleTrees, useWallet, confirmConfig, defaultStaticAccountsStruct, toArray, LightSystemProgram, defaultTestStateTreeAccounts, sumUpLamports, validateSufficientBalance, validateSameOwner, dedupeSigner, buildAndSignTx, sendAndConfirmTx } from '@lightprotocol/stateless.js';
2
+ import { PublicKey, Keypair, Connection, SystemProgram, AddressLookupTableProgram, ComputeBudgetProgram } from '@solana/web3.js';
26
3
  import { AnchorProvider, setProvider, Program, BN } from '@coral-xyz/anchor';
27
- import {
28
- TOKEN_PROGRAM_ID,
29
- MINT_SIZE,
30
- createInitializeMint2Instruction,
31
- createMintToInstruction,
32
- getOrCreateAssociatedTokenAccount,
33
- } from '@solana/spl-token';
4
+ import { MINT_SIZE, createInitializeMint2Instruction, createMintToInstruction, TOKEN_PROGRAM_ID, TOKEN_2022_PROGRAM_ID, getOrCreateAssociatedTokenAccount } from '@solana/spl-token';
34
5
 
35
6
  const IDL = {
36
7
  version: '1.2.0',
@@ -116,9 +87,6 @@ const IDL = {
116
87
  name: 'tokenPoolPda',
117
88
  isMut: true,
118
89
  isSigner: false,
119
- docs: [
120
- 'account to a token account of a different mint will fail',
121
- ],
122
90
  },
123
91
  {
124
92
  name: 'tokenProgram',
@@ -196,6 +164,11 @@ const IDL = {
196
164
  },
197
165
  {
198
166
  name: 'compressSplTokenAccount',
167
+ docs: [
168
+ 'Compresses the balance of an spl token account sub an optional remaining',
169
+ 'amount. This instruction does not close the spl token account. To close',
170
+ 'the account bundle a close spl account instruction in your transaction.',
171
+ ],
199
172
  accounts: [
200
173
  {
201
174
  name: 'feePayer',
@@ -1189,8 +1162,7 @@ const IDL = {
1189
1162
  name: 'inputCompressedAccountsWithMerkleContext',
1190
1163
  type: {
1191
1164
  vec: {
1192
- defined:
1193
- 'PackedCompressedAccountWithMerkleContext',
1165
+ defined: 'PackedCompressedAccountWithMerkleContext',
1194
1166
  },
1195
1167
  },
1196
1168
  },
@@ -1198,8 +1170,7 @@ const IDL = {
1198
1170
  name: 'outputCompressedAccounts',
1199
1171
  type: {
1200
1172
  vec: {
1201
- defined:
1202
- 'OutputCompressedAccountWithPackedContext',
1173
+ defined: 'OutputCompressedAccountWithPackedContext',
1203
1174
  },
1204
1175
  },
1205
1176
  },
@@ -1255,8 +1226,7 @@ const IDL = {
1255
1226
  name: 'inputCompressedAccountsWithMerkleContext',
1256
1227
  type: {
1257
1228
  vec: {
1258
- defined:
1259
- 'PackedCompressedAccountWithMerkleContext',
1229
+ defined: 'PackedCompressedAccountWithMerkleContext',
1260
1230
  },
1261
1231
  },
1262
1232
  },
@@ -1264,8 +1234,7 @@ const IDL = {
1264
1234
  name: 'outputCompressedAccounts',
1265
1235
  type: {
1266
1236
  vec: {
1267
- defined:
1268
- 'OutputCompressedAccountWithPackedContext',
1237
+ defined: 'OutputCompressedAccountWithPackedContext',
1269
1238
  },
1270
1239
  },
1271
1240
  },
@@ -1510,8 +1479,7 @@ const IDL = {
1510
1479
  name: 'outputCompressedAccounts',
1511
1480
  type: {
1512
1481
  vec: {
1513
- defined:
1514
- 'OutputCompressedAccountWithPackedContext',
1482
+ defined: 'OutputCompressedAccountWithPackedContext',
1515
1483
  },
1516
1484
  },
1517
1485
  },
@@ -1688,23 +1656,141 @@ const IDL = {
1688
1656
  errors: [
1689
1657
  {
1690
1658
  code: 6000,
1691
- name: 'SignerCheckFailed',
1692
- msg: 'Signer check failed',
1659
+ name: 'PublicKeyAmountMissmatch',
1660
+ msg: 'public keys and amounts must be of same length',
1693
1661
  },
1694
1662
  {
1695
1663
  code: 6001,
1696
- name: 'CreateTransferInstructionFailed',
1697
- msg: 'Create transfer instruction failed',
1664
+ name: 'ComputeInputSumFailed',
1665
+ msg: 'ComputeInputSumFailed',
1698
1666
  },
1699
1667
  {
1700
1668
  code: 6002,
1701
- name: 'AccountNotFound',
1702
- msg: 'Account not found',
1669
+ name: 'ComputeOutputSumFailed',
1670
+ msg: 'ComputeOutputSumFailed',
1703
1671
  },
1704
1672
  {
1705
1673
  code: 6003,
1706
- name: 'SerializationError',
1707
- msg: 'Serialization error',
1674
+ name: 'ComputeCompressSumFailed',
1675
+ msg: 'ComputeCompressSumFailed',
1676
+ },
1677
+ {
1678
+ code: 6004,
1679
+ name: 'ComputeDecompressSumFailed',
1680
+ msg: 'ComputeDecompressSumFailed',
1681
+ },
1682
+ {
1683
+ code: 6005,
1684
+ name: 'SumCheckFailed',
1685
+ msg: 'SumCheckFailed',
1686
+ },
1687
+ {
1688
+ code: 6006,
1689
+ name: 'DecompressRecipientUndefinedForDecompress',
1690
+ msg: 'DecompressRecipientUndefinedForDecompress',
1691
+ },
1692
+ {
1693
+ code: 6007,
1694
+ name: 'CompressedPdaUndefinedForDecompress',
1695
+ msg: 'CompressedPdaUndefinedForDecompress',
1696
+ },
1697
+ {
1698
+ code: 6008,
1699
+ name: 'DeCompressAmountUndefinedForDecompress',
1700
+ msg: 'DeCompressAmountUndefinedForDecompress',
1701
+ },
1702
+ {
1703
+ code: 6009,
1704
+ name: 'CompressedPdaUndefinedForCompress',
1705
+ msg: 'CompressedPdaUndefinedForCompress',
1706
+ },
1707
+ {
1708
+ code: 6010,
1709
+ name: 'DeCompressAmountUndefinedForCompress',
1710
+ msg: 'DeCompressAmountUndefinedForCompress',
1711
+ },
1712
+ {
1713
+ code: 6011,
1714
+ name: 'DelegateSignerCheckFailed',
1715
+ msg: 'DelegateSignerCheckFailed',
1716
+ },
1717
+ {
1718
+ code: 6012,
1719
+ name: 'MintTooLarge',
1720
+ msg: 'Minted amount greater than u64::MAX',
1721
+ },
1722
+ {
1723
+ code: 6013,
1724
+ name: 'SplTokenSupplyMismatch',
1725
+ msg: 'SplTokenSupplyMismatch',
1726
+ },
1727
+ {
1728
+ code: 6014,
1729
+ name: 'HeapMemoryCheckFailed',
1730
+ msg: 'HeapMemoryCheckFailed',
1731
+ },
1732
+ {
1733
+ code: 6015,
1734
+ name: 'InstructionNotCallable',
1735
+ msg: 'The instruction is not callable',
1736
+ },
1737
+ {
1738
+ code: 6016,
1739
+ name: 'ArithmeticUnderflow',
1740
+ msg: 'ArithmeticUnderflow',
1741
+ },
1742
+ {
1743
+ code: 6017,
1744
+ name: 'HashToFieldError',
1745
+ msg: 'HashToFieldError',
1746
+ },
1747
+ {
1748
+ code: 6018,
1749
+ name: 'InvalidAuthorityMint',
1750
+ msg: 'Expected the authority to be also a mint authority',
1751
+ },
1752
+ {
1753
+ code: 6019,
1754
+ name: 'InvalidFreezeAuthority',
1755
+ msg: 'Provided authority is not the freeze authority',
1756
+ },
1757
+ {
1758
+ code: 6020,
1759
+ name: 'InvalidDelegateIndex',
1760
+ },
1761
+ {
1762
+ code: 6021,
1763
+ name: 'TokenPoolPdaUndefined',
1764
+ },
1765
+ {
1766
+ code: 6022,
1767
+ name: 'IsTokenPoolPda',
1768
+ msg: 'Compress or decompress recipient is the same account as the token pool pda.',
1769
+ },
1770
+ {
1771
+ code: 6023,
1772
+ name: 'InvalidTokenPoolPda',
1773
+ },
1774
+ {
1775
+ code: 6024,
1776
+ name: 'NoInputTokenAccountsProvided',
1777
+ },
1778
+ {
1779
+ code: 6025,
1780
+ name: 'NoInputsProvided',
1781
+ },
1782
+ {
1783
+ code: 6026,
1784
+ name: 'MintHasNoFreezeAuthority',
1785
+ },
1786
+ {
1787
+ code: 6027,
1788
+ name: 'MintWithInvalidExtension',
1789
+ },
1790
+ {
1791
+ code: 6028,
1792
+ name: 'InsufficientTokenAccountBalance',
1793
+ msg: 'The token account balance is less than the remaining amount.',
1708
1794
  },
1709
1795
  ],
1710
1796
  };
@@ -1714,37 +1800,20 @@ const IDL = {
1714
1800
  * Packs Compressed Token Accounts.
1715
1801
  */
1716
1802
  function packCompressedTokenAccounts(params) {
1717
- const {
1718
- inputCompressedTokenAccounts,
1719
- outputStateTrees,
1720
- remainingAccounts = [],
1721
- rootIndices,
1722
- tokenTransferOutputs,
1723
- } = params;
1803
+ const { inputCompressedTokenAccounts, outputStateTrees, remainingAccounts = [], rootIndices, tokenTransferOutputs, } = params;
1724
1804
  const _remainingAccounts = remainingAccounts.slice();
1725
1805
  let delegateIndex = null;
1726
- if (
1727
- inputCompressedTokenAccounts.length > 0 &&
1728
- inputCompressedTokenAccounts[0].parsed.delegate
1729
- ) {
1730
- delegateIndex = getIndexOrAdd(
1731
- _remainingAccounts,
1732
- inputCompressedTokenAccounts[0].parsed.delegate,
1733
- );
1806
+ if (inputCompressedTokenAccounts.length > 0 &&
1807
+ inputCompressedTokenAccounts[0].parsed.delegate) {
1808
+ delegateIndex = getIndexOrAdd(_remainingAccounts, inputCompressedTokenAccounts[0].parsed.delegate);
1734
1809
  }
1735
1810
  /// TODO: move pubkeyArray to remainingAccounts
1736
1811
  /// Currently just packs 'delegate' to pubkeyArray
1737
1812
  const packedInputTokenData = [];
1738
1813
  /// pack inputs
1739
1814
  inputCompressedTokenAccounts.forEach((account, index) => {
1740
- const merkleTreePubkeyIndex = getIndexOrAdd(
1741
- _remainingAccounts,
1742
- account.compressedAccount.merkleTree,
1743
- );
1744
- const nullifierQueuePubkeyIndex = getIndexOrAdd(
1745
- _remainingAccounts,
1746
- account.compressedAccount.nullifierQueue,
1747
- );
1815
+ const merkleTreePubkeyIndex = getIndexOrAdd(_remainingAccounts, account.compressedAccount.merkleTree);
1816
+ const nullifierQueuePubkeyIndex = getIndexOrAdd(_remainingAccounts, account.compressedAccount.nullifierQueue);
1748
1817
  packedInputTokenData.push({
1749
1818
  amount: account.parsed.amount,
1750
1819
  delegateIndex,
@@ -1762,11 +1831,7 @@ function packCompressedTokenAccounts(params) {
1762
1831
  });
1763
1832
  });
1764
1833
  /// pack output state trees
1765
- const paddedOutputStateMerkleTrees = padOutputStateMerkleTrees(
1766
- outputStateTrees,
1767
- tokenTransferOutputs.length,
1768
- inputCompressedTokenAccounts.map(acc => acc.compressedAccount),
1769
- );
1834
+ const paddedOutputStateMerkleTrees = padOutputStateMerkleTrees(outputStateTrees, tokenTransferOutputs.length, inputCompressedTokenAccounts.map(acc => acc.compressedAccount));
1770
1835
  const packedOutputTokenData = [];
1771
1836
  paddedOutputStateMerkleTrees.forEach((account, index) => {
1772
1837
  const merkleTreeIndex = getIndexOrAdd(_remainingAccounts, account);
@@ -1781,7 +1846,7 @@ function packCompressedTokenAccounts(params) {
1781
1846
  });
1782
1847
  });
1783
1848
  // to meta
1784
- const remainingAccountMetas = _remainingAccounts.map(account => ({
1849
+ const remainingAccountMetas = _remainingAccounts.map((account) => ({
1785
1850
  pubkey: account,
1786
1851
  isWritable: true,
1787
1852
  isSigner: false,
@@ -1800,16 +1865,13 @@ const SPL_TOKEN_MINT_RENT_EXEMPT_BALANCE = 1461600;
1800
1865
  /**
1801
1866
  * Sum up the token amounts of the compressed token accounts
1802
1867
  */
1803
- const sumUpTokenAmount = accounts => {
1804
- return accounts.reduce(
1805
- (acc, account) => acc.add(account.parsed.amount),
1806
- bn(0),
1807
- );
1868
+ const sumUpTokenAmount = (accounts) => {
1869
+ return accounts.reduce((acc, account) => acc.add(account.parsed.amount), bn(0));
1808
1870
  };
1809
1871
  /**
1810
1872
  * Validate that all the compressed token accounts are owned by the same owner.
1811
1873
  */
1812
- const validateSameTokenOwner = accounts => {
1874
+ const validateSameTokenOwner = (accounts) => {
1813
1875
  const owner = accounts[0].parsed.owner;
1814
1876
  accounts.forEach(acc => {
1815
1877
  if (!acc.parsed.owner.equals(owner)) {
@@ -1820,7 +1882,7 @@ const validateSameTokenOwner = accounts => {
1820
1882
  /**
1821
1883
  * Parse compressed token accounts to get the mint, current owner and delegate.
1822
1884
  */
1823
- const parseTokenData = compressedTokenAccounts => {
1885
+ const parseTokenData = (compressedTokenAccounts) => {
1824
1886
  const mint = compressedTokenAccounts[0].parsed.mint;
1825
1887
  const currentOwner = compressedTokenAccounts[0].parsed.owner;
1826
1888
  const delegate = compressedTokenAccounts[0].parsed.delegate;
@@ -1834,16 +1896,10 @@ const parseTokenData = compressedTokenAccounts => {
1834
1896
  * @returns Output token data for the transfer
1835
1897
  * instruction
1836
1898
  */
1837
- function createTransferOutputState(
1838
- inputCompressedTokenAccounts,
1839
- toAddress,
1840
- amount,
1841
- ) {
1899
+ function createTransferOutputState(inputCompressedTokenAccounts, toAddress, amount) {
1842
1900
  amount = bn(amount);
1843
1901
  const inputAmount = sumUpTokenAmount(inputCompressedTokenAccounts);
1844
- const inputLamports = sumUpLamports(
1845
- inputCompressedTokenAccounts.map(acc => acc.compressedAccount),
1846
- );
1902
+ const inputLamports = sumUpLamports(inputCompressedTokenAccounts.map(acc => acc.compressedAccount));
1847
1903
  const changeAmount = inputAmount.sub(amount);
1848
1904
  validateSufficientBalance(changeAmount);
1849
1905
  if (changeAmount.eq(bn(0)) && inputLamports.eq(bn(0))) {
@@ -1857,9 +1913,7 @@ function createTransferOutputState(
1857
1913
  ];
1858
1914
  }
1859
1915
  /// validates token program
1860
- validateSameOwner(
1861
- inputCompressedTokenAccounts.map(acc => acc.compressedAccount),
1862
- );
1916
+ validateSameOwner(inputCompressedTokenAccounts.map(acc => acc.compressedAccount));
1863
1917
  validateSameTokenOwner(inputCompressedTokenAccounts);
1864
1918
  const outputCompressedAccounts = [
1865
1919
  {
@@ -1886,9 +1940,7 @@ function createTransferOutputState(
1886
1940
  */
1887
1941
  function createDecompressOutputState(inputCompressedTokenAccounts, amount) {
1888
1942
  amount = bn(amount);
1889
- const inputLamports = sumUpLamports(
1890
- inputCompressedTokenAccounts.map(acc => acc.compressedAccount),
1891
- );
1943
+ const inputLamports = sumUpLamports(inputCompressedTokenAccounts.map(acc => acc.compressedAccount));
1892
1944
  const inputAmount = sumUpTokenAmount(inputCompressedTokenAccounts);
1893
1945
  const changeAmount = inputAmount.sub(amount);
1894
1946
  validateSufficientBalance(changeAmount);
@@ -1896,9 +1948,7 @@ function createDecompressOutputState(inputCompressedTokenAccounts, amount) {
1896
1948
  if (changeAmount.eq(bn(0)) && inputLamports.eq(bn(0))) {
1897
1949
  return [];
1898
1950
  }
1899
- validateSameOwner(
1900
- inputCompressedTokenAccounts.map(acc => acc.compressedAccount),
1901
- );
1951
+ validateSameOwner(inputCompressedTokenAccounts.map(acc => acc.compressedAccount));
1902
1952
  validateSameTokenOwner(inputCompressedTokenAccounts);
1903
1953
  const tokenTransferOutputs = [
1904
1954
  {
@@ -1914,13 +1964,11 @@ class CompressedTokenProgram {
1914
1964
  /**
1915
1965
  * @internal
1916
1966
  */
1917
- constructor() {}
1967
+ constructor() { }
1918
1968
  /**
1919
1969
  * Public key that identifies the CompressedPda program
1920
1970
  */
1921
- static programId = new PublicKey(
1922
- 'cTokenmWW8bLPjZEBAUgYy3zKxQZW6VKi7bqNFEVv3m',
1923
- );
1971
+ static programId = new PublicKey('cTokenmWW8bLPjZEBAUgYy3zKxQZW6VKi7bqNFEVv3m');
1924
1972
  /**
1925
1973
  * Set a custom programId via PublicKey or base58 encoded string.
1926
1974
  * This method is not required for regular usage.
@@ -1953,15 +2001,8 @@ class CompressedTokenProgram {
1953
2001
  /// program only for serde and building instructions, not for
1954
2002
  /// interacting with the network.
1955
2003
  const mockKeypair = Keypair.generate();
1956
- const mockConnection = new Connection(
1957
- 'http://127.0.0.1:8899',
1958
- 'confirmed',
1959
- );
1960
- const mockProvider = new AnchorProvider(
1961
- mockConnection,
1962
- useWallet(mockKeypair),
1963
- confirmConfig,
1964
- );
2004
+ const mockConnection = new Connection('http://127.0.0.1:8899', 'confirmed');
2005
+ const mockProvider = new AnchorProvider(mockConnection, useWallet(mockKeypair), confirmConfig);
1965
2006
  setProvider(mockProvider);
1966
2007
  this._program = new Program(IDL, this.programId, mockProvider);
1967
2008
  }
@@ -1969,63 +2010,61 @@ class CompressedTokenProgram {
1969
2010
  /** @internal */
1970
2011
  static deriveTokenPoolPda(mint) {
1971
2012
  const seeds = [POOL_SEED, mint.toBuffer()];
1972
- const [address, _] = PublicKey.findProgramAddressSync(
1973
- seeds,
1974
- this.programId,
1975
- );
2013
+ const [address, _] = PublicKey.findProgramAddressSync(seeds, this.programId);
1976
2014
  return address;
1977
2015
  }
1978
2016
  /** @internal */
1979
2017
  static get deriveCpiAuthorityPda() {
1980
- const [address, _] = PublicKey.findProgramAddressSync(
1981
- [CPI_AUTHORITY_SEED],
1982
- this.programId,
1983
- );
2018
+ const [address, _] = PublicKey.findProgramAddressSync([CPI_AUTHORITY_SEED], this.programId);
1984
2019
  return address;
1985
2020
  }
1986
2021
  /**
1987
- * Construct createMint instruction for compressed tokens
2022
+ * Construct createMint instruction for compressed tokens.
2023
+ * @returns [createMintAccountInstruction, initializeMintInstruction, createTokenPoolInstruction]
2024
+ *
2025
+ * Note that `createTokenPoolInstruction` must be executed after `initializeMintInstruction`.
1988
2026
  */
1989
2027
  static async createMint(params) {
1990
- const { mint, authority, feePayer, rentExemptBalance } = params;
2028
+ const { mint, authority, feePayer, rentExemptBalance, tokenProgramId, freezeAuthority, mintSize, } = params;
2029
+ const tokenProgram = tokenProgramId ?? TOKEN_PROGRAM_ID;
1991
2030
  /// Create and initialize SPL Mint account
1992
2031
  const createMintAccountInstruction = SystemProgram.createAccount({
1993
2032
  fromPubkey: feePayer,
1994
2033
  lamports: rentExemptBalance,
1995
2034
  newAccountPubkey: mint,
1996
- programId: TOKEN_PROGRAM_ID,
1997
- space: MINT_SIZE,
2035
+ programId: tokenProgram,
2036
+ space: mintSize ?? MINT_SIZE,
1998
2037
  });
1999
- const initializeMintInstruction = createInitializeMint2Instruction(
2000
- mint,
2001
- params.decimals,
2002
- authority,
2003
- params.freezeAuthority,
2004
- TOKEN_PROGRAM_ID,
2005
- );
2006
- const ix = await this.createTokenPool({
2038
+ const initializeMintInstruction = createInitializeMint2Instruction(mint, params.decimals, authority, freezeAuthority, tokenProgram);
2039
+ const createTokenPoolInstruction = await this.createTokenPool({
2007
2040
  feePayer,
2008
2041
  mint,
2042
+ tokenProgramId: tokenProgram,
2009
2043
  });
2010
- return [createMintAccountInstruction, initializeMintInstruction, ix];
2044
+ return [
2045
+ createMintAccountInstruction,
2046
+ initializeMintInstruction,
2047
+ createTokenPoolInstruction,
2048
+ ];
2011
2049
  }
2012
2050
  /**
2013
2051
  * Enable compression for an existing SPL mint, creating an omnibus account.
2014
2052
  * For new mints, use `CompressedTokenProgram.createMint`.
2015
2053
  */
2016
2054
  static async createTokenPool(params) {
2017
- const { mint, feePayer } = params;
2055
+ const { mint, feePayer, tokenProgramId } = params;
2056
+ const tokenProgram = tokenProgramId ?? TOKEN_PROGRAM_ID;
2018
2057
  const tokenPoolPda = this.deriveTokenPoolPda(mint);
2019
2058
  const ix = await this.program.methods
2020
2059
  .createTokenPool()
2021
2060
  .accounts({
2022
- mint,
2023
- feePayer,
2024
- tokenPoolPda,
2025
- systemProgram: SystemProgram.programId,
2026
- tokenProgram: TOKEN_PROGRAM_ID,
2027
- cpiAuthorityPda: this.deriveCpiAuthorityPda,
2028
- })
2061
+ mint,
2062
+ feePayer,
2063
+ tokenPoolPda,
2064
+ systemProgram: SystemProgram.programId,
2065
+ tokenProgram,
2066
+ cpiAuthorityPda: this.deriveCpiAuthorityPda,
2067
+ })
2029
2068
  .instruction();
2030
2069
  return ix;
2031
2070
  }
@@ -2034,60 +2073,43 @@ class CompressedTokenProgram {
2034
2073
  */
2035
2074
  static async mintTo(params) {
2036
2075
  const systemKeys = defaultStaticAccountsStruct();
2037
- const { mint, feePayer, authority, merkleTree, toPubkey, amount } =
2038
- params;
2076
+ const { mint, feePayer, authority, merkleTree, toPubkey, amount, tokenProgramId, } = params;
2077
+ const tokenProgram = tokenProgramId ?? TOKEN_PROGRAM_ID;
2039
2078
  const tokenPoolPda = this.deriveTokenPoolPda(mint);
2040
2079
  const amounts = toArray(amount).map(amount => bn(amount));
2041
2080
  const toPubkeys = toArray(toPubkey);
2042
2081
  if (amounts.length !== toPubkeys.length) {
2043
- throw new Error(
2044
- 'Amount and toPubkey arrays must have the same length',
2045
- );
2082
+ throw new Error('Amount and toPubkey arrays must have the same length');
2046
2083
  }
2047
2084
  const instruction = await this.program.methods
2048
2085
  .mintTo(toPubkeys, amounts, null)
2049
2086
  .accounts({
2050
- feePayer,
2051
- authority,
2052
- cpiAuthorityPda: this.deriveCpiAuthorityPda,
2053
- mint,
2054
- tokenPoolPda,
2055
- tokenProgram: TOKEN_PROGRAM_ID,
2056
- lightSystemProgram: LightSystemProgram.programId,
2057
- registeredProgramPda: systemKeys.registeredProgramPda,
2058
- noopProgram: systemKeys.noopProgram,
2059
- accountCompressionAuthority:
2060
- systemKeys.accountCompressionAuthority,
2061
- accountCompressionProgram: systemKeys.accountCompressionProgram,
2062
- merkleTree:
2063
- merkleTree ?? defaultTestStateTreeAccounts().merkleTree,
2064
- selfProgram: this.programId,
2065
- solPoolPda: null,
2066
- })
2087
+ feePayer,
2088
+ authority,
2089
+ cpiAuthorityPda: this.deriveCpiAuthorityPda,
2090
+ mint,
2091
+ tokenPoolPda,
2092
+ tokenProgram,
2093
+ lightSystemProgram: LightSystemProgram.programId,
2094
+ registeredProgramPda: systemKeys.registeredProgramPda,
2095
+ noopProgram: systemKeys.noopProgram,
2096
+ accountCompressionAuthority: systemKeys.accountCompressionAuthority,
2097
+ accountCompressionProgram: systemKeys.accountCompressionProgram,
2098
+ merkleTree: merkleTree ?? defaultTestStateTreeAccounts().merkleTree,
2099
+ selfProgram: this.programId,
2100
+ solPoolPda: null,
2101
+ })
2067
2102
  .instruction();
2068
2103
  return instruction;
2069
2104
  }
2070
- /// TODO: add compressBatch functionality for batch minting
2071
2105
  /**
2072
- * Mint tokens from registed SPL mint account to a compressed account
2106
+ * Mint tokens from registered SPL mint account to a compressed account
2073
2107
  */
2074
2108
  static async approveAndMintTo(params) {
2075
- const {
2076
- mint,
2077
- feePayer,
2078
- authorityTokenAccount,
2079
- authority,
2080
- merkleTree,
2081
- toPubkey,
2082
- } = params;
2109
+ const { mint, feePayer, authorityTokenAccount, authority, merkleTree, toPubkey, tokenProgramId, } = params;
2083
2110
  const amount = BigInt(params.amount.toString());
2084
2111
  /// 1. Mint to existing ATA of mintAuthority.
2085
- const splMintToInstruction = createMintToInstruction(
2086
- mint,
2087
- authorityTokenAccount,
2088
- authority,
2089
- amount,
2090
- );
2112
+ const splMintToInstruction = createMintToInstruction(mint, authorityTokenAccount, authority, amount, [], tokenProgramId);
2091
2113
  /// 2. Compress from mint authority ATA to recipient compressed account
2092
2114
  const compressInstruction = await this.compress({
2093
2115
  payer: feePayer,
@@ -2097,6 +2119,7 @@ class CompressedTokenProgram {
2097
2119
  mint,
2098
2120
  amount: params.amount,
2099
2121
  outputStateTree: merkleTree,
2122
+ tokenProgramId,
2100
2123
  });
2101
2124
  return [splMintToInstruction, compressInstruction];
2102
2125
  }
@@ -2104,33 +2127,15 @@ class CompressedTokenProgram {
2104
2127
  * Construct transfer instruction for compressed tokens
2105
2128
  */
2106
2129
  static async transfer(params) {
2107
- const {
2108
- payer,
2109
- inputCompressedTokenAccounts,
2110
- recentInputStateRootIndices,
2111
- recentValidityProof,
2112
- amount,
2113
- outputStateTrees,
2114
- toAddress,
2115
- } = params;
2116
- const tokenTransferOutputs = createTransferOutputState(
2117
- inputCompressedTokenAccounts,
2118
- toAddress,
2119
- amount,
2120
- );
2121
- const {
2122
- inputTokenDataWithContext,
2123
- packedOutputTokenData,
2124
- remainingAccountMetas,
2125
- } = packCompressedTokenAccounts({
2130
+ const { payer, inputCompressedTokenAccounts, recentInputStateRootIndices, recentValidityProof, amount, outputStateTrees, toAddress, } = params;
2131
+ const tokenTransferOutputs = createTransferOutputState(inputCompressedTokenAccounts, toAddress, amount);
2132
+ const { inputTokenDataWithContext, packedOutputTokenData, remainingAccountMetas, } = packCompressedTokenAccounts({
2126
2133
  inputCompressedTokenAccounts,
2127
2134
  outputStateTrees,
2128
2135
  rootIndices: recentInputStateRootIndices,
2129
2136
  tokenTransferOutputs,
2130
2137
  });
2131
- const { mint, currentOwner } = parseTokenData(
2132
- inputCompressedTokenAccounts,
2133
- );
2138
+ const { mint, currentOwner } = parseTokenData(inputCompressedTokenAccounts);
2134
2139
  const data = {
2135
2140
  proof: recentValidityProof,
2136
2141
  mint,
@@ -2142,32 +2147,24 @@ class CompressedTokenProgram {
2142
2147
  cpiContext: null,
2143
2148
  lamportsChangeAccountMerkleTreeIndex: null,
2144
2149
  };
2145
- const encodedData = this.program.coder.types.encode(
2146
- 'CompressedTokenInstructionDataTransfer',
2147
- data,
2148
- );
2149
- const {
2150
- accountCompressionAuthority,
2151
- noopProgram,
2152
- registeredProgramPda,
2153
- accountCompressionProgram,
2154
- } = defaultStaticAccountsStruct();
2150
+ const encodedData = this.program.coder.types.encode('CompressedTokenInstructionDataTransfer', data);
2151
+ const { accountCompressionAuthority, noopProgram, registeredProgramPda, accountCompressionProgram, } = defaultStaticAccountsStruct();
2155
2152
  const instruction = await this.program.methods
2156
2153
  .transfer(encodedData)
2157
2154
  .accounts({
2158
- feePayer: payer,
2159
- authority: currentOwner,
2160
- cpiAuthorityPda: this.deriveCpiAuthorityPda,
2161
- lightSystemProgram: LightSystemProgram.programId,
2162
- registeredProgramPda: registeredProgramPda,
2163
- noopProgram: noopProgram,
2164
- accountCompressionAuthority: accountCompressionAuthority,
2165
- accountCompressionProgram: accountCompressionProgram,
2166
- selfProgram: this.programId,
2167
- tokenPoolPda: null,
2168
- compressOrDecompressTokenAccount: null,
2169
- tokenProgram: null,
2170
- })
2155
+ feePayer: payer,
2156
+ authority: currentOwner,
2157
+ cpiAuthorityPda: this.deriveCpiAuthorityPda,
2158
+ lightSystemProgram: LightSystemProgram.programId,
2159
+ registeredProgramPda: registeredProgramPda,
2160
+ noopProgram: noopProgram,
2161
+ accountCompressionAuthority: accountCompressionAuthority,
2162
+ accountCompressionProgram: accountCompressionProgram,
2163
+ selfProgram: this.programId,
2164
+ tokenPoolPda: null,
2165
+ compressOrDecompressTokenAccount: null,
2166
+ tokenProgram: null,
2167
+ })
2171
2168
  .remainingAccounts(remainingAccountMetas)
2172
2169
  .instruction();
2173
2170
  return instruction;
@@ -2176,14 +2173,12 @@ class CompressedTokenProgram {
2176
2173
  * Create lookup table instructions for the token program's default accounts.
2177
2174
  */
2178
2175
  static async createTokenProgramLookupTable(params) {
2179
- const { authority, mints, recentSlot, payer, remainingAccounts } =
2180
- params;
2181
- const [createInstruction, lookupTableAddress] =
2182
- AddressLookupTableProgram.createLookupTable({
2183
- authority,
2184
- payer: authority,
2185
- recentSlot,
2186
- });
2176
+ const { authority, mints, recentSlot, payer, remainingAccounts } = params;
2177
+ const [createInstruction, lookupTableAddress] = AddressLookupTableProgram.createLookupTable({
2178
+ authority,
2179
+ payer: authority,
2180
+ recentSlot,
2181
+ });
2187
2182
  let optionalMintKeys = [];
2188
2183
  if (mints) {
2189
2184
  optionalMintKeys = [
@@ -2208,6 +2203,7 @@ class CompressedTokenProgram {
2208
2203
  defaultTestStateTreeAccounts().addressQueue,
2209
2204
  this.programId,
2210
2205
  TOKEN_PROGRAM_ID,
2206
+ TOKEN_2022_PROGRAM_ID,
2211
2207
  authority,
2212
2208
  ...optionalMintKeys,
2213
2209
  ...(remainingAccounts ?? []),
@@ -2223,19 +2219,14 @@ class CompressedTokenProgram {
2223
2219
  * @returns compressInstruction
2224
2220
  */
2225
2221
  static async compress(params) {
2226
- const { payer, owner, source, toAddress, mint, outputStateTree } =
2227
- params;
2222
+ const { payer, owner, source, toAddress, mint, outputStateTree, tokenProgramId, } = params;
2228
2223
  if (Array.isArray(params.amount) !== Array.isArray(params.toAddress)) {
2229
- throw new Error(
2230
- 'Both amount and toAddress must be arrays or both must be single values',
2231
- );
2224
+ throw new Error('Both amount and toAddress must be arrays or both must be single values');
2232
2225
  }
2233
2226
  let tokenTransferOutputs;
2234
2227
  if (Array.isArray(params.amount) && Array.isArray(params.toAddress)) {
2235
2228
  if (params.amount.length !== params.toAddress.length) {
2236
- throw new Error(
2237
- 'Amount and toAddress arrays must have the same length',
2238
- );
2229
+ throw new Error('Amount and toAddress arrays must have the same length');
2239
2230
  }
2240
2231
  tokenTransferOutputs = params.amount.map((amt, index) => {
2241
2232
  const amount = bn(amt);
@@ -2246,7 +2237,8 @@ class CompressedTokenProgram {
2246
2237
  tlv: null,
2247
2238
  };
2248
2239
  });
2249
- } else {
2240
+ }
2241
+ else {
2250
2242
  tokenTransferOutputs = [
2251
2243
  {
2252
2244
  owner: toAddress,
@@ -2256,11 +2248,7 @@ class CompressedTokenProgram {
2256
2248
  },
2257
2249
  ];
2258
2250
  }
2259
- const {
2260
- inputTokenDataWithContext,
2261
- packedOutputTokenData,
2262
- remainingAccountMetas,
2263
- } = packCompressedTokenAccounts({
2251
+ const { inputTokenDataWithContext, packedOutputTokenData, remainingAccountMetas, } = packCompressedTokenAccounts({
2264
2252
  inputCompressedTokenAccounts: [],
2265
2253
  outputStateTrees: outputStateTree,
2266
2254
  rootIndices: [],
@@ -2274,36 +2262,31 @@ class CompressedTokenProgram {
2274
2262
  outputCompressedAccounts: packedOutputTokenData,
2275
2263
  compressOrDecompressAmount: Array.isArray(params.amount)
2276
2264
  ? params.amount
2277
- .map(amt => new BN(amt))
2278
- .reduce((sum, amt) => sum.add(amt), new BN(0))
2265
+ .map(amt => new BN(amt))
2266
+ .reduce((sum, amt) => sum.add(amt), new BN(0))
2279
2267
  : new BN(params.amount),
2280
2268
  isCompress: true,
2281
2269
  cpiContext: null,
2282
2270
  lamportsChangeAccountMerkleTreeIndex: null,
2283
2271
  };
2284
- const encodedData = this.program.coder.types.encode(
2285
- 'CompressedTokenInstructionDataTransfer',
2286
- data,
2287
- );
2272
+ const encodedData = this.program.coder.types.encode('CompressedTokenInstructionDataTransfer', data);
2273
+ const tokenProgram = tokenProgramId ?? TOKEN_PROGRAM_ID;
2288
2274
  const instruction = await this.program.methods
2289
2275
  .transfer(encodedData)
2290
2276
  .accounts({
2291
- feePayer: payer,
2292
- authority: owner,
2293
- cpiAuthorityPda: this.deriveCpiAuthorityPda,
2294
- lightSystemProgram: LightSystemProgram.programId,
2295
- registeredProgramPda:
2296
- defaultStaticAccountsStruct().registeredProgramPda,
2297
- noopProgram: defaultStaticAccountsStruct().noopProgram,
2298
- accountCompressionAuthority:
2299
- defaultStaticAccountsStruct().accountCompressionAuthority,
2300
- accountCompressionProgram:
2301
- defaultStaticAccountsStruct().accountCompressionProgram,
2302
- selfProgram: this.programId,
2303
- tokenPoolPda: this.deriveTokenPoolPda(mint),
2304
- compressOrDecompressTokenAccount: source, // token
2305
- tokenProgram: TOKEN_PROGRAM_ID,
2306
- })
2277
+ feePayer: payer,
2278
+ authority: owner,
2279
+ cpiAuthorityPda: this.deriveCpiAuthorityPda,
2280
+ lightSystemProgram: LightSystemProgram.programId,
2281
+ registeredProgramPda: defaultStaticAccountsStruct().registeredProgramPda,
2282
+ noopProgram: defaultStaticAccountsStruct().noopProgram,
2283
+ accountCompressionAuthority: defaultStaticAccountsStruct().accountCompressionAuthority,
2284
+ accountCompressionProgram: defaultStaticAccountsStruct().accountCompressionProgram,
2285
+ selfProgram: this.programId,
2286
+ tokenPoolPda: this.deriveTokenPoolPda(mint),
2287
+ compressOrDecompressTokenAccount: source, // token
2288
+ tokenProgram,
2289
+ })
2307
2290
  .remainingAccounts(remainingAccountMetas)
2308
2291
  .instruction();
2309
2292
  return instruction;
@@ -2312,33 +2295,17 @@ class CompressedTokenProgram {
2312
2295
  * Construct decompress instruction
2313
2296
  */
2314
2297
  static async decompress(params) {
2315
- const {
2316
- payer,
2317
- inputCompressedTokenAccounts,
2318
- toAddress,
2319
- outputStateTree,
2320
- recentValidityProof,
2321
- recentInputStateRootIndices,
2322
- } = params;
2298
+ const { payer, inputCompressedTokenAccounts, toAddress, outputStateTree, recentValidityProof, recentInputStateRootIndices, tokenProgramId, } = params;
2323
2299
  const amount = bn(params.amount);
2324
- const tokenTransferOutputs = createDecompressOutputState(
2325
- inputCompressedTokenAccounts,
2326
- amount,
2327
- );
2300
+ const tokenTransferOutputs = createDecompressOutputState(inputCompressedTokenAccounts, amount);
2328
2301
  /// Pack
2329
- const {
2330
- inputTokenDataWithContext,
2331
- packedOutputTokenData,
2332
- remainingAccountMetas,
2333
- } = packCompressedTokenAccounts({
2302
+ const { inputTokenDataWithContext, packedOutputTokenData, remainingAccountMetas, } = packCompressedTokenAccounts({
2334
2303
  inputCompressedTokenAccounts,
2335
2304
  outputStateTrees: outputStateTree,
2336
2305
  rootIndices: recentInputStateRootIndices,
2337
2306
  tokenTransferOutputs: tokenTransferOutputs,
2338
2307
  });
2339
- const { mint, currentOwner } = parseTokenData(
2340
- inputCompressedTokenAccounts,
2341
- );
2308
+ const { mint, currentOwner } = parseTokenData(inputCompressedTokenAccounts);
2342
2309
  const data = {
2343
2310
  proof: recentValidityProof,
2344
2311
  mint,
@@ -2350,45 +2317,31 @@ class CompressedTokenProgram {
2350
2317
  cpiContext: null,
2351
2318
  lamportsChangeAccountMerkleTreeIndex: null,
2352
2319
  };
2353
- const encodedData = this.program.coder.types.encode(
2354
- 'CompressedTokenInstructionDataTransfer',
2355
- data,
2356
- );
2357
- const {
2358
- accountCompressionAuthority,
2359
- noopProgram,
2360
- registeredProgramPda,
2361
- accountCompressionProgram,
2362
- } = defaultStaticAccountsStruct();
2320
+ const encodedData = this.program.coder.types.encode('CompressedTokenInstructionDataTransfer', data);
2321
+ const { accountCompressionAuthority, noopProgram, registeredProgramPda, accountCompressionProgram, } = defaultStaticAccountsStruct();
2322
+ const tokenProgram = tokenProgramId ?? TOKEN_PROGRAM_ID;
2363
2323
  const instruction = await this.program.methods
2364
2324
  .transfer(encodedData)
2365
2325
  .accounts({
2366
- feePayer: payer,
2367
- authority: currentOwner,
2368
- cpiAuthorityPda: this.deriveCpiAuthorityPda,
2369
- lightSystemProgram: LightSystemProgram.programId,
2370
- registeredProgramPda: registeredProgramPda,
2371
- noopProgram: noopProgram,
2372
- accountCompressionAuthority: accountCompressionAuthority,
2373
- accountCompressionProgram: accountCompressionProgram,
2374
- selfProgram: this.programId,
2375
- tokenPoolPda: this.deriveTokenPoolPda(mint),
2376
- compressOrDecompressTokenAccount: toAddress,
2377
- tokenProgram: TOKEN_PROGRAM_ID,
2378
- })
2326
+ feePayer: payer,
2327
+ authority: currentOwner,
2328
+ cpiAuthorityPda: this.deriveCpiAuthorityPda,
2329
+ lightSystemProgram: LightSystemProgram.programId,
2330
+ registeredProgramPda: registeredProgramPda,
2331
+ noopProgram: noopProgram,
2332
+ accountCompressionAuthority: accountCompressionAuthority,
2333
+ accountCompressionProgram: accountCompressionProgram,
2334
+ selfProgram: this.programId,
2335
+ tokenPoolPda: this.deriveTokenPoolPda(mint),
2336
+ compressOrDecompressTokenAccount: toAddress,
2337
+ tokenProgram,
2338
+ })
2379
2339
  .remainingAccounts(remainingAccountMetas)
2380
2340
  .instruction();
2381
2341
  return instruction;
2382
2342
  }
2383
2343
  static async mergeTokenAccounts(params) {
2384
- const {
2385
- payer,
2386
- owner,
2387
- inputCompressedTokenAccounts,
2388
- outputStateTree,
2389
- recentValidityProof,
2390
- recentInputStateRootIndices,
2391
- } = params;
2344
+ const { payer, owner, inputCompressedTokenAccounts, outputStateTree, recentValidityProof, recentInputStateRootIndices, } = params;
2392
2345
  if (inputCompressedTokenAccounts.length > 3) {
2393
2346
  throw new Error('Cannot merge more than 3 token accounts at once');
2394
2347
  }
@@ -2396,10 +2349,7 @@ class CompressedTokenProgram {
2396
2349
  payer,
2397
2350
  inputCompressedTokenAccounts,
2398
2351
  toAddress: owner,
2399
- amount: inputCompressedTokenAccounts.reduce(
2400
- (sum, account) => sum.add(account.parsed.amount),
2401
- new BN(0),
2402
- ),
2352
+ amount: inputCompressedTokenAccounts.reduce((sum, account) => sum.add(account.parsed.amount), new BN(0)),
2403
2353
  outputStateTrees: outputStateTree,
2404
2354
  recentInputStateRootIndices,
2405
2355
  recentValidityProof,
@@ -2407,14 +2357,8 @@ class CompressedTokenProgram {
2407
2357
  return [ix];
2408
2358
  }
2409
2359
  static async compressSplTokenAccount(params) {
2410
- const {
2411
- feePayer,
2412
- authority,
2413
- tokenAccount,
2414
- mint,
2415
- remainingAmount,
2416
- outputStateTree,
2417
- } = params;
2360
+ const { feePayer, authority, tokenAccount, mint, remainingAmount, outputStateTree, tokenProgramId, } = params;
2361
+ const tokenProgram = tokenProgramId ?? TOKEN_PROGRAM_ID;
2418
2362
  const remainingAccountMetas = [
2419
2363
  {
2420
2364
  pubkey: outputStateTree,
@@ -2425,27 +2369,27 @@ class CompressedTokenProgram {
2425
2369
  const instruction = await this.program.methods
2426
2370
  .compressSplTokenAccount(authority, remainingAmount ?? null, null)
2427
2371
  .accounts({
2428
- feePayer,
2429
- authority,
2430
- cpiAuthorityPda: this.deriveCpiAuthorityPda,
2431
- lightSystemProgram: LightSystemProgram.programId,
2432
- registeredProgramPda:
2433
- defaultStaticAccountsStruct().registeredProgramPda,
2434
- noopProgram: defaultStaticAccountsStruct().noopProgram,
2435
- accountCompressionAuthority:
2436
- defaultStaticAccountsStruct().accountCompressionAuthority,
2437
- accountCompressionProgram:
2438
- defaultStaticAccountsStruct().accountCompressionProgram,
2439
- selfProgram: this.programId,
2440
- tokenPoolPda: this.deriveTokenPoolPda(mint),
2441
- compressOrDecompressTokenAccount: tokenAccount,
2442
- tokenProgram: TOKEN_PROGRAM_ID,
2443
- systemProgram: SystemProgram.programId,
2444
- })
2372
+ feePayer,
2373
+ authority,
2374
+ cpiAuthorityPda: this.deriveCpiAuthorityPda,
2375
+ lightSystemProgram: LightSystemProgram.programId,
2376
+ registeredProgramPda: defaultStaticAccountsStruct().registeredProgramPda,
2377
+ noopProgram: defaultStaticAccountsStruct().noopProgram,
2378
+ accountCompressionAuthority: defaultStaticAccountsStruct().accountCompressionAuthority,
2379
+ accountCompressionProgram: defaultStaticAccountsStruct().accountCompressionProgram,
2380
+ selfProgram: this.programId,
2381
+ tokenPoolPda: this.deriveTokenPoolPda(mint),
2382
+ compressOrDecompressTokenAccount: tokenAccount,
2383
+ tokenProgram,
2384
+ systemProgram: SystemProgram.programId,
2385
+ })
2445
2386
  .remainingAccounts(remainingAccountMetas)
2446
2387
  .instruction();
2447
2388
  return instruction;
2448
2389
  }
2390
+ static async get_mint_program_id(mint, connection) {
2391
+ return (await connection.getAccountInfo(mint))?.owner;
2392
+ }
2449
2393
  }
2450
2394
 
2451
2395
  /**
@@ -2463,22 +2407,11 @@ class CompressedTokenProgram {
2463
2407
  *
2464
2408
  * @return Signature of the confirmed transaction
2465
2409
  */
2466
- async function approveAndMintTo(
2467
- rpc,
2468
- payer,
2469
- mint,
2470
- destination,
2471
- authority,
2472
- amount,
2473
- merkleTree,
2474
- confirmOptions,
2475
- ) {
2476
- const authorityTokenAccount = await getOrCreateAssociatedTokenAccount(
2477
- rpc,
2478
- payer,
2479
- mint,
2480
- authority.publicKey,
2481
- );
2410
+ async function approveAndMintTo(rpc, payer, mint, destination, authority, amount, merkleTree, confirmOptions, tokenProgramId) {
2411
+ tokenProgramId = tokenProgramId
2412
+ ? tokenProgramId
2413
+ : await CompressedTokenProgram.get_mint_program_id(mint, rpc);
2414
+ const authorityTokenAccount = await getOrCreateAssociatedTokenAccount(rpc, payer, mint, authority.publicKey, undefined, undefined, confirmOptions, tokenProgramId);
2482
2415
  const ixs = await CompressedTokenProgram.approveAndMintTo({
2483
2416
  feePayer: payer.publicKey,
2484
2417
  mint,
@@ -2487,18 +2420,14 @@ async function approveAndMintTo(
2487
2420
  amount,
2488
2421
  toPubkey: destination,
2489
2422
  merkleTree,
2423
+ tokenProgramId,
2490
2424
  });
2491
2425
  const { blockhash } = await rpc.getLatestBlockhash();
2492
2426
  const additionalSigners = dedupeSigner(payer, [authority]);
2493
- const tx = buildAndSignTx(
2494
- [
2495
- ComputeBudgetProgram.setComputeUnitLimit({ units: 1_000_000 }),
2496
- ...ixs,
2497
- ],
2498
- payer,
2499
- blockhash,
2500
- additionalSigners,
2501
- );
2427
+ const tx = buildAndSignTx([
2428
+ ComputeBudgetProgram.setComputeUnitLimit({ units: 1_000_000 }),
2429
+ ...ixs,
2430
+ ], payer, blockhash, additionalSigners);
2502
2431
  const txId = await sendAndConfirmTx(rpc, tx, confirmOptions);
2503
2432
  return txId;
2504
2433
  }
@@ -2521,17 +2450,10 @@ async function approveAndMintTo(
2521
2450
  *
2522
2451
  * @return Signature of the confirmed transaction
2523
2452
  */
2524
- async function compress(
2525
- rpc,
2526
- payer,
2527
- mint,
2528
- amount,
2529
- owner,
2530
- sourceTokenAccount,
2531
- toAddress,
2532
- merkleTree,
2533
- confirmOptions,
2534
- ) {
2453
+ async function compress(rpc, payer, mint, amount, owner, sourceTokenAccount, toAddress, merkleTree, confirmOptions, tokenProgramId) {
2454
+ tokenProgramId = tokenProgramId
2455
+ ? tokenProgramId
2456
+ : await CompressedTokenProgram.get_mint_program_id(mint, rpc);
2535
2457
  const compressIx = await CompressedTokenProgram.compress({
2536
2458
  payer: payer.publicKey,
2537
2459
  owner: owner.publicKey,
@@ -2540,26 +2462,17 @@ async function compress(
2540
2462
  amount,
2541
2463
  mint,
2542
2464
  outputStateTree: merkleTree,
2465
+ tokenProgramId,
2543
2466
  });
2544
2467
  const blockhashCtx = await rpc.getLatestBlockhash();
2545
2468
  const additionalSigners = dedupeSigner(payer, [owner]);
2546
- const signedTx = buildAndSignTx(
2547
- [
2548
- ComputeBudgetProgram.setComputeUnitLimit({
2549
- units: 1_000_000,
2550
- }),
2551
- compressIx,
2552
- ],
2553
- payer,
2554
- blockhashCtx.blockhash,
2555
- additionalSigners,
2556
- );
2557
- const txId = await sendAndConfirmTx(
2558
- rpc,
2559
- signedTx,
2560
- confirmOptions,
2561
- blockhashCtx,
2562
- );
2469
+ const signedTx = buildAndSignTx([
2470
+ ComputeBudgetProgram.setComputeUnitLimit({
2471
+ units: 1_000_000,
2472
+ }),
2473
+ compressIx,
2474
+ ], payer, blockhashCtx.blockhash, additionalSigners);
2475
+ const txId = await sendAndConfirmTx(rpc, signedTx, confirmOptions, blockhashCtx);
2563
2476
  return txId;
2564
2477
  }
2565
2478
 
@@ -2580,31 +2493,15 @@ async function compress(
2580
2493
  *
2581
2494
  * @return Signature of the confirmed transaction
2582
2495
  */
2583
- async function transfer(
2584
- rpc,
2585
- payer,
2586
- mint,
2587
- amount,
2588
- owner,
2589
- toAddress,
2590
- /// TODO: allow multiple
2591
- merkleTree,
2592
- confirmOptions,
2593
- ) {
2496
+ async function transfer(rpc, payer, mint, amount, owner, toAddress,
2497
+ /// TODO: allow multiple
2498
+ merkleTree, confirmOptions) {
2594
2499
  amount = bn(amount);
2595
- const compressedTokenAccounts = await rpc.getCompressedTokenAccountsByOwner(
2596
- owner.publicKey,
2597
- {
2598
- mint,
2599
- },
2600
- );
2601
- const [inputAccounts] = selectMinCompressedTokenAccountsForTransfer(
2602
- compressedTokenAccounts.items,
2603
- amount,
2604
- );
2605
- const proof = await rpc.getValidityProof(
2606
- inputAccounts.map(account => bn(account.compressedAccount.hash)),
2607
- );
2500
+ const compressedTokenAccounts = await rpc.getCompressedTokenAccountsByOwner(owner.publicKey, {
2501
+ mint,
2502
+ });
2503
+ const [inputAccounts] = selectMinCompressedTokenAccountsForTransfer(compressedTokenAccounts.items, amount);
2504
+ const proof = await rpc.getValidityProof(inputAccounts.map(account => bn(account.compressedAccount.hash)));
2608
2505
  const ix = await CompressedTokenProgram.transfer({
2609
2506
  payer: payer.publicKey,
2610
2507
  inputCompressedTokenAccounts: inputAccounts,
@@ -2616,12 +2513,7 @@ async function transfer(
2616
2513
  });
2617
2514
  const { blockhash } = await rpc.getLatestBlockhash();
2618
2515
  const additionalSigners = dedupeSigner(payer, [owner]);
2619
- const signedTx = buildAndSignTx(
2620
- [ComputeBudgetProgram.setComputeUnitLimit({ units: 1_000_000 }), ix],
2621
- payer,
2622
- blockhash,
2623
- additionalSigners,
2624
- );
2516
+ const signedTx = buildAndSignTx([ComputeBudgetProgram.setComputeUnitLimit({ units: 1_000_000 }), ix], payer, blockhash, additionalSigners);
2625
2517
  const txId = await sendAndConfirmTx(rpc, signedTx, confirmOptions);
2626
2518
  return txId;
2627
2519
  }
@@ -2638,17 +2530,14 @@ function selectMinCompressedTokenAccountsForTransfer(accounts, transferAmount) {
2638
2530
  const selectedAccounts = [];
2639
2531
  accounts.sort((a, b) => b.parsed.amount.cmp(a.parsed.amount));
2640
2532
  for (const account of accounts) {
2641
- if (accumulatedAmount.gte(bn(transferAmount))) break;
2533
+ if (accumulatedAmount.gte(bn(transferAmount)))
2534
+ break;
2642
2535
  accumulatedAmount = accumulatedAmount.add(account.parsed.amount);
2643
- accumulatedLamports = accumulatedLamports.add(
2644
- account.compressedAccount.lamports,
2645
- );
2536
+ accumulatedLamports = accumulatedLamports.add(account.compressedAccount.lamports);
2646
2537
  selectedAccounts.push(account);
2647
2538
  }
2648
2539
  if (accumulatedAmount.lt(bn(transferAmount))) {
2649
- throw new Error(
2650
- `Not enough balance for transfer. Required: ${transferAmount.toString()}, available: ${accumulatedAmount.toString()}`,
2651
- );
2540
+ throw new Error(`Not enough balance for transfer. Required: ${transferAmount.toString()}, available: ${accumulatedAmount.toString()}`);
2652
2541
  }
2653
2542
  return [
2654
2543
  selectedAccounts,
@@ -2675,32 +2564,19 @@ function selectMinCompressedTokenAccountsForTransfer(accounts, transferAmount) {
2675
2564
  *
2676
2565
  * @return Signature of the confirmed transaction
2677
2566
  */
2678
- async function decompress(
2679
- rpc,
2680
- payer,
2681
- mint,
2682
- amount,
2683
- owner,
2684
- toAddress,
2685
- /// TODO: allow multiple
2686
- merkleTree,
2687
- confirmOptions,
2688
- ) {
2567
+ async function decompress(rpc, payer, mint, amount, owner, toAddress,
2568
+ /// TODO: allow multiple
2569
+ merkleTree, confirmOptions, tokenProgramId) {
2570
+ tokenProgramId = tokenProgramId
2571
+ ? tokenProgramId
2572
+ : await CompressedTokenProgram.get_mint_program_id(mint, rpc);
2689
2573
  amount = bn(amount);
2690
- const compressedTokenAccounts = await rpc.getCompressedTokenAccountsByOwner(
2691
- owner.publicKey,
2692
- {
2693
- mint,
2694
- },
2695
- );
2574
+ const compressedTokenAccounts = await rpc.getCompressedTokenAccountsByOwner(owner.publicKey, {
2575
+ mint,
2576
+ });
2696
2577
  /// TODO: consider using a different selection algorithm
2697
- const [inputAccounts] = selectMinCompressedTokenAccountsForTransfer(
2698
- compressedTokenAccounts.items,
2699
- amount,
2700
- );
2701
- const proof = await rpc.getValidityProof(
2702
- inputAccounts.map(account => bn(account.compressedAccount.hash)),
2703
- );
2578
+ const [inputAccounts] = selectMinCompressedTokenAccountsForTransfer(compressedTokenAccounts.items, amount);
2579
+ const proof = await rpc.getValidityProof(inputAccounts.map(account => bn(account.compressedAccount.hash)));
2704
2580
  const ix = await CompressedTokenProgram.decompress({
2705
2581
  payer: payer.publicKey,
2706
2582
  inputCompressedTokenAccounts: inputAccounts,
@@ -2709,15 +2585,11 @@ async function decompress(
2709
2585
  outputStateTree: merkleTree,
2710
2586
  recentInputStateRootIndices: proof.rootIndices,
2711
2587
  recentValidityProof: proof.compressedProof,
2588
+ tokenProgramId,
2712
2589
  });
2713
2590
  const { blockhash } = await rpc.getLatestBlockhash();
2714
2591
  const additionalSigners = dedupeSigner(payer, [owner]);
2715
- const signedTx = buildAndSignTx(
2716
- [ComputeBudgetProgram.setComputeUnitLimit({ units: 1_000_000 }), ix],
2717
- payer,
2718
- blockhash,
2719
- additionalSigners,
2720
- );
2592
+ const signedTx = buildAndSignTx([ComputeBudgetProgram.setComputeUnitLimit({ units: 1_000_000 }), ix], payer, blockhash, additionalSigners);
2721
2593
  const txId = await sendAndConfirmTx(rpc, signedTx, confirmOptions);
2722
2594
  return txId;
2723
2595
  }
@@ -2731,19 +2603,13 @@ async function decompress(
2731
2603
  * @param decimals Location of the decimal place
2732
2604
  * @param keypair Optional keypair, defaulting to a new random one
2733
2605
  * @param confirmOptions Options for confirming the transaction
2606
+ * @param isToken22 Whether to create a Token 2022 mint. Defaults to false.
2734
2607
  *
2735
2608
  * @return Address of the new mint and the transaction signature
2736
2609
  */
2737
- async function createMint(
2738
- rpc,
2739
- payer,
2740
- mintAuthority,
2741
- decimals,
2742
- keypair = Keypair.generate(),
2743
- confirmOptions,
2744
- ) {
2745
- const rentExemptBalance =
2746
- await rpc.getMinimumBalanceForRentExemption(MINT_SIZE);
2610
+ async function createMint(rpc, payer, mintAuthority, decimals, keypair = Keypair.generate(), confirmOptions, isToken22 = false) {
2611
+ const rentExemptBalance = await rpc.getMinimumBalanceForRentExemption(MINT_SIZE);
2612
+ const tokenProgramId = isToken22 ? TOKEN_2022_PROGRAM_ID : TOKEN_PROGRAM_ID;
2747
2613
  const ixs = await CompressedTokenProgram.createMint({
2748
2614
  feePayer: payer.publicKey,
2749
2615
  mint: keypair.publicKey,
@@ -2751,6 +2617,7 @@ async function createMint(
2751
2617
  authority: mintAuthority,
2752
2618
  freezeAuthority: null, // TODO: add feature
2753
2619
  rentExemptBalance,
2620
+ tokenProgramId,
2754
2621
  });
2755
2622
  const { blockhash } = await rpc.getLatestBlockhash();
2756
2623
  const additionalSigners = dedupeSigner(payer, [keypair]);
@@ -2776,16 +2643,10 @@ async function createMint(
2776
2643
  *
2777
2644
  * @return Signature of the confirmed transaction
2778
2645
  */
2779
- async function mintTo(
2780
- rpc,
2781
- payer,
2782
- mint,
2783
- destination,
2784
- authority,
2785
- amount,
2786
- merkleTree,
2787
- confirmOptions,
2788
- ) {
2646
+ async function mintTo(rpc, payer, mint, destination, authority, amount, merkleTree, confirmOptions, tokenProgramId) {
2647
+ tokenProgramId = tokenProgramId
2648
+ ? tokenProgramId
2649
+ : await CompressedTokenProgram.get_mint_program_id(mint, rpc);
2789
2650
  const additionalSigners = dedupeSigner(payer, [authority]);
2790
2651
  const ix = await CompressedTokenProgram.mintTo({
2791
2652
  feePayer: payer.publicKey,
@@ -2794,14 +2655,10 @@ async function mintTo(
2794
2655
  amount: amount,
2795
2656
  toPubkey: destination,
2796
2657
  merkleTree,
2658
+ tokenProgramId,
2797
2659
  });
2798
2660
  const { blockhash } = await rpc.getLatestBlockhash();
2799
- const tx = buildAndSignTx(
2800
- [ComputeBudgetProgram.setComputeUnitLimit({ units: 1_000_000 }), ix],
2801
- payer,
2802
- blockhash,
2803
- additionalSigners,
2804
- );
2661
+ const tx = buildAndSignTx([ComputeBudgetProgram.setComputeUnitLimit({ units: 1_000_000 }), ix], payer, blockhash, additionalSigners);
2805
2662
  const txId = await sendAndConfirmTx(rpc, tx, confirmOptions);
2806
2663
  return txId;
2807
2664
  }
@@ -2819,60 +2676,34 @@ async function mintTo(
2819
2676
  *
2820
2677
  * @return Array of transaction signatures
2821
2678
  */
2822
- async function mergeTokenAccounts(
2823
- rpc,
2824
- payer,
2825
- mint,
2826
- owner,
2827
- merkleTree,
2828
- confirmOptions,
2829
- ) {
2830
- const compressedTokenAccounts = await rpc.getCompressedTokenAccountsByOwner(
2831
- owner.publicKey,
2832
- { mint },
2833
- );
2679
+ async function mergeTokenAccounts(rpc, payer, mint, owner, merkleTree, confirmOptions) {
2680
+ const compressedTokenAccounts = await rpc.getCompressedTokenAccountsByOwner(owner.publicKey, { mint });
2834
2681
  if (compressedTokenAccounts.items.length === 0) {
2835
- throw new Error(
2836
- `No compressed token accounts found for mint ${mint.toBase58()}`,
2837
- );
2682
+ throw new Error(`No compressed token accounts found for mint ${mint.toBase58()}`);
2838
2683
  }
2839
2684
  if (compressedTokenAccounts.items.length >= 6) {
2840
- throw new Error(
2841
- `Too many compressed token accounts used for mint ${mint.toBase58()}`,
2842
- );
2685
+ throw new Error(`Too many compressed token accounts used for mint ${mint.toBase58()}`);
2843
2686
  }
2844
2687
  const instructions = [
2845
2688
  ComputeBudgetProgram.setComputeUnitLimit({ units: 1_000_000 }),
2846
2689
  ];
2847
- for (
2848
- let i = 0;
2849
- i < compressedTokenAccounts.items.slice(0, 6).length;
2850
- i += 3
2851
- ) {
2690
+ for (let i = 0; i < compressedTokenAccounts.items.slice(0, 6).length; i += 3) {
2852
2691
  const batch = compressedTokenAccounts.items.slice(i, i + 3);
2853
- const proof = await rpc.getValidityProof(
2854
- batch.map(account => bn(account.compressedAccount.hash)),
2855
- );
2856
- const batchInstructions =
2857
- await CompressedTokenProgram.mergeTokenAccounts({
2858
- payer: payer.publicKey,
2859
- owner: owner.publicKey,
2860
- mint,
2861
- inputCompressedTokenAccounts: batch,
2862
- outputStateTree: merkleTree,
2863
- recentValidityProof: proof.compressedProof,
2864
- recentInputStateRootIndices: proof.rootIndices,
2865
- });
2692
+ const proof = await rpc.getValidityProof(batch.map(account => bn(account.compressedAccount.hash)));
2693
+ const batchInstructions = await CompressedTokenProgram.mergeTokenAccounts({
2694
+ payer: payer.publicKey,
2695
+ owner: owner.publicKey,
2696
+ mint,
2697
+ inputCompressedTokenAccounts: batch,
2698
+ outputStateTree: merkleTree,
2699
+ recentValidityProof: proof.compressedProof,
2700
+ recentInputStateRootIndices: proof.rootIndices,
2701
+ });
2866
2702
  instructions.push(...batchInstructions);
2867
2703
  }
2868
2704
  const { blockhash } = await rpc.getLatestBlockhash();
2869
2705
  const additionalSigners = dedupeSigner(payer, [owner]);
2870
- const signedTx = buildAndSignTx(
2871
- instructions,
2872
- payer,
2873
- blockhash,
2874
- additionalSigners,
2875
- );
2706
+ const signedTx = buildAndSignTx(instructions, payer, blockhash, additionalSigners);
2876
2707
  const txId = await sendAndConfirmTx(rpc, signedTx, confirmOptions);
2877
2708
  return txId;
2878
2709
  }
@@ -2888,10 +2719,14 @@ async function mergeTokenAccounts(
2888
2719
  *
2889
2720
  * @return transaction signature
2890
2721
  */
2891
- async function createTokenPool(rpc, payer, mintAddress, confirmOptions) {
2722
+ async function createTokenPool(rpc, payer, mint, confirmOptions, tokenProgramId) {
2723
+ tokenProgramId = tokenProgramId
2724
+ ? tokenProgramId
2725
+ : await CompressedTokenProgram.get_mint_program_id(mint, rpc);
2892
2726
  const ix = await CompressedTokenProgram.createTokenPool({
2893
2727
  feePayer: payer.publicKey,
2894
- mint: mintAddress,
2728
+ mint,
2729
+ tokenProgramId,
2895
2730
  });
2896
2731
  const { blockhash } = await rpc.getLatestBlockhash();
2897
2732
  const tx = buildAndSignTx([ix], payer, blockhash);
@@ -2912,50 +2747,23 @@ async function createTokenPool(rpc, payer, mintAddress, confirmOptions) {
2912
2747
  *
2913
2748
  * @return Transaction signatures and the address of the created lookup table
2914
2749
  */
2915
- async function createTokenProgramLookupTable(
2916
- rpc,
2917
- payer,
2918
- authority,
2919
- mints,
2920
- additionalAccounts,
2921
- ) {
2750
+ async function createTokenProgramLookupTable(rpc, payer, authority, mints, additionalAccounts) {
2922
2751
  const recentSlot = await rpc.getSlot('finalized');
2923
- const { instructions, address } =
2924
- await CompressedTokenProgram.createTokenProgramLookupTable({
2925
- payer: payer.publicKey,
2926
- authority: authority.publicKey,
2927
- mints,
2928
- remainingAccounts: additionalAccounts,
2929
- recentSlot,
2930
- });
2752
+ const { instructions, address } = await CompressedTokenProgram.createTokenProgramLookupTable({
2753
+ payer: payer.publicKey,
2754
+ authority: authority.publicKey,
2755
+ mints,
2756
+ remainingAccounts: additionalAccounts,
2757
+ recentSlot,
2758
+ });
2931
2759
  const additionalSigners = dedupeSigner(payer, [authority]);
2932
2760
  const blockhashCtx = await rpc.getLatestBlockhash();
2933
- const signedTx = buildAndSignTx(
2934
- [instructions[0]],
2935
- payer,
2936
- blockhashCtx.blockhash,
2937
- additionalSigners,
2938
- );
2761
+ const signedTx = buildAndSignTx([instructions[0]], payer, blockhashCtx.blockhash, additionalSigners);
2939
2762
  /// Must wait for the first instruction to be finalized.
2940
- const txId = await sendAndConfirmTx(
2941
- rpc,
2942
- signedTx,
2943
- { commitment: 'finalized' },
2944
- blockhashCtx,
2945
- );
2763
+ const txId = await sendAndConfirmTx(rpc, signedTx, { commitment: 'finalized' }, blockhashCtx);
2946
2764
  const blockhashCtx2 = await rpc.getLatestBlockhash();
2947
- const signedTx2 = buildAndSignTx(
2948
- [instructions[1]],
2949
- payer,
2950
- blockhashCtx2.blockhash,
2951
- additionalSigners,
2952
- );
2953
- const txId2 = await sendAndConfirmTx(
2954
- rpc,
2955
- signedTx2,
2956
- { commitment: 'finalized' },
2957
- blockhashCtx2,
2958
- );
2765
+ const signedTx2 = buildAndSignTx([instructions[1]], payer, blockhashCtx2.blockhash, additionalSigners);
2766
+ const txId2 = await sendAndConfirmTx(rpc, signedTx2, { commitment: 'finalized' }, blockhashCtx2);
2959
2767
  return { txIds: [txId, txId2], address };
2960
2768
  }
2961
2769
 
@@ -2973,16 +2781,10 @@ async function createTokenProgramLookupTable(
2973
2781
  *
2974
2782
  * @return Signature of the confirmed transaction
2975
2783
  */
2976
- async function compressSplTokenAccount(
2977
- rpc,
2978
- payer,
2979
- mint,
2980
- owner,
2981
- tokenAccount,
2982
- outputStateTree,
2983
- remainingAmount,
2984
- confirmOptions,
2985
- ) {
2784
+ async function compressSplTokenAccount(rpc, payer, mint, owner, tokenAccount, outputStateTree, remainingAmount, confirmOptions, tokenProgramId) {
2785
+ tokenProgramId = tokenProgramId
2786
+ ? tokenProgramId
2787
+ : await CompressedTokenProgram.get_mint_program_id(mint, rpc);
2986
2788
  const compressIx = await CompressedTokenProgram.compressSplTokenAccount({
2987
2789
  feePayer: payer.publicKey,
2988
2790
  authority: owner.publicKey,
@@ -2990,51 +2792,19 @@ async function compressSplTokenAccount(
2990
2792
  mint,
2991
2793
  remainingAmount,
2992
2794
  outputStateTree,
2795
+ tokenProgramId,
2993
2796
  });
2994
2797
  const blockhashCtx = await rpc.getLatestBlockhash();
2995
2798
  const additionalSigners = dedupeSigner(payer, [owner]);
2996
- const signedTx = buildAndSignTx(
2997
- [
2998
- ComputeBudgetProgram.setComputeUnitLimit({
2999
- units: 1_000_000,
3000
- }),
3001
- compressIx,
3002
- ],
3003
- payer,
3004
- blockhashCtx.blockhash,
3005
- additionalSigners,
3006
- );
3007
- const txId = await sendAndConfirmTx(
3008
- rpc,
3009
- signedTx,
3010
- confirmOptions,
3011
- blockhashCtx,
3012
- );
2799
+ const signedTx = buildAndSignTx([
2800
+ ComputeBudgetProgram.setComputeUnitLimit({
2801
+ units: 1_000_000,
2802
+ }),
2803
+ compressIx,
2804
+ ], payer, blockhashCtx.blockhash, additionalSigners);
2805
+ const txId = await sendAndConfirmTx(rpc, signedTx, confirmOptions, blockhashCtx);
3013
2806
  return txId;
3014
2807
  }
3015
2808
 
3016
- export {
3017
- CPI_AUTHORITY_SEED,
3018
- CompressedTokenProgram,
3019
- IDL,
3020
- POOL_SEED,
3021
- SPL_TOKEN_MINT_RENT_EXEMPT_BALANCE,
3022
- approveAndMintTo,
3023
- compress,
3024
- compressSplTokenAccount,
3025
- createDecompressOutputState,
3026
- createMint,
3027
- createTokenPool,
3028
- createTokenProgramLookupTable,
3029
- createTransferOutputState,
3030
- decompress,
3031
- mergeTokenAccounts,
3032
- mintTo,
3033
- packCompressedTokenAccounts,
3034
- parseTokenData,
3035
- selectMinCompressedTokenAccountsForTransfer,
3036
- sumUpTokenAmount,
3037
- transfer,
3038
- validateSameTokenOwner,
3039
- };
2809
+ export { CPI_AUTHORITY_SEED, CompressedTokenProgram, IDL, POOL_SEED, SPL_TOKEN_MINT_RENT_EXEMPT_BALANCE, approveAndMintTo, compress, compressSplTokenAccount, createDecompressOutputState, createMint, createTokenPool, createTokenProgramLookupTable, createTransferOutputState, decompress, mergeTokenAccounts, mintTo, packCompressedTokenAccounts, parseTokenData, selectMinCompressedTokenAccountsForTransfer, sumUpTokenAmount, transfer, validateSameTokenOwner };
3040
2810
  //# sourceMappingURL=index.js.map