@lightprotocol/compressed-token 0.16.0 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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,43 +2010,33 @@ 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
2022
  * Construct createMint instruction for compressed tokens
1988
2023
  */
1989
2024
  static async createMint(params) {
1990
- const { mint, authority, feePayer, rentExemptBalance } = params;
2025
+ const { mint, authority, feePayer, rentExemptBalance, tokenProgramId, freezeAuthority, mintSize, } = params;
2026
+ const tokenProgram = tokenProgramId ?? TOKEN_PROGRAM_ID;
1991
2027
  /// Create and initialize SPL Mint account
1992
2028
  const createMintAccountInstruction = SystemProgram.createAccount({
1993
2029
  fromPubkey: feePayer,
1994
2030
  lamports: rentExemptBalance,
1995
2031
  newAccountPubkey: mint,
1996
- programId: TOKEN_PROGRAM_ID,
1997
- space: MINT_SIZE,
2032
+ programId: tokenProgram,
2033
+ space: mintSize ?? MINT_SIZE,
1998
2034
  });
1999
- const initializeMintInstruction = createInitializeMint2Instruction(
2000
- mint,
2001
- params.decimals,
2002
- authority,
2003
- params.freezeAuthority,
2004
- TOKEN_PROGRAM_ID,
2005
- );
2035
+ const initializeMintInstruction = createInitializeMint2Instruction(mint, params.decimals, authority, freezeAuthority, tokenProgram);
2006
2036
  const ix = await this.createTokenPool({
2007
2037
  feePayer,
2008
2038
  mint,
2039
+ tokenProgramId: tokenProgram,
2009
2040
  });
2010
2041
  return [createMintAccountInstruction, initializeMintInstruction, ix];
2011
2042
  }
@@ -2014,18 +2045,19 @@ class CompressedTokenProgram {
2014
2045
  * For new mints, use `CompressedTokenProgram.createMint`.
2015
2046
  */
2016
2047
  static async createTokenPool(params) {
2017
- const { mint, feePayer } = params;
2048
+ const { mint, feePayer, tokenProgramId } = params;
2049
+ const tokenProgram = tokenProgramId ?? TOKEN_PROGRAM_ID;
2018
2050
  const tokenPoolPda = this.deriveTokenPoolPda(mint);
2019
2051
  const ix = await this.program.methods
2020
2052
  .createTokenPool()
2021
2053
  .accounts({
2022
- mint,
2023
- feePayer,
2024
- tokenPoolPda,
2025
- systemProgram: SystemProgram.programId,
2026
- tokenProgram: TOKEN_PROGRAM_ID,
2027
- cpiAuthorityPda: this.deriveCpiAuthorityPda,
2028
- })
2054
+ mint,
2055
+ feePayer,
2056
+ tokenPoolPda,
2057
+ systemProgram: SystemProgram.programId,
2058
+ tokenProgram,
2059
+ cpiAuthorityPda: this.deriveCpiAuthorityPda,
2060
+ })
2029
2061
  .instruction();
2030
2062
  return ix;
2031
2063
  }
@@ -2034,60 +2066,43 @@ class CompressedTokenProgram {
2034
2066
  */
2035
2067
  static async mintTo(params) {
2036
2068
  const systemKeys = defaultStaticAccountsStruct();
2037
- const { mint, feePayer, authority, merkleTree, toPubkey, amount } =
2038
- params;
2069
+ const { mint, feePayer, authority, merkleTree, toPubkey, amount, tokenProgramId, } = params;
2070
+ const tokenProgram = tokenProgramId ?? TOKEN_PROGRAM_ID;
2039
2071
  const tokenPoolPda = this.deriveTokenPoolPda(mint);
2040
2072
  const amounts = toArray(amount).map(amount => bn(amount));
2041
2073
  const toPubkeys = toArray(toPubkey);
2042
2074
  if (amounts.length !== toPubkeys.length) {
2043
- throw new Error(
2044
- 'Amount and toPubkey arrays must have the same length',
2045
- );
2075
+ throw new Error('Amount and toPubkey arrays must have the same length');
2046
2076
  }
2047
2077
  const instruction = await this.program.methods
2048
2078
  .mintTo(toPubkeys, amounts, null)
2049
2079
  .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
- })
2080
+ feePayer,
2081
+ authority,
2082
+ cpiAuthorityPda: this.deriveCpiAuthorityPda,
2083
+ mint,
2084
+ tokenPoolPda,
2085
+ tokenProgram,
2086
+ lightSystemProgram: LightSystemProgram.programId,
2087
+ registeredProgramPda: systemKeys.registeredProgramPda,
2088
+ noopProgram: systemKeys.noopProgram,
2089
+ accountCompressionAuthority: systemKeys.accountCompressionAuthority,
2090
+ accountCompressionProgram: systemKeys.accountCompressionProgram,
2091
+ merkleTree: merkleTree ?? defaultTestStateTreeAccounts().merkleTree,
2092
+ selfProgram: this.programId,
2093
+ solPoolPda: null,
2094
+ })
2067
2095
  .instruction();
2068
2096
  return instruction;
2069
2097
  }
2070
- /// TODO: add compressBatch functionality for batch minting
2071
2098
  /**
2072
- * Mint tokens from registed SPL mint account to a compressed account
2099
+ * Mint tokens from registered SPL mint account to a compressed account
2073
2100
  */
2074
2101
  static async approveAndMintTo(params) {
2075
- const {
2076
- mint,
2077
- feePayer,
2078
- authorityTokenAccount,
2079
- authority,
2080
- merkleTree,
2081
- toPubkey,
2082
- } = params;
2102
+ const { mint, feePayer, authorityTokenAccount, authority, merkleTree, toPubkey, tokenProgramId, } = params;
2083
2103
  const amount = BigInt(params.amount.toString());
2084
2104
  /// 1. Mint to existing ATA of mintAuthority.
2085
- const splMintToInstruction = createMintToInstruction(
2086
- mint,
2087
- authorityTokenAccount,
2088
- authority,
2089
- amount,
2090
- );
2105
+ const splMintToInstruction = createMintToInstruction(mint, authorityTokenAccount, authority, amount, [], tokenProgramId);
2091
2106
  /// 2. Compress from mint authority ATA to recipient compressed account
2092
2107
  const compressInstruction = await this.compress({
2093
2108
  payer: feePayer,
@@ -2097,6 +2112,7 @@ class CompressedTokenProgram {
2097
2112
  mint,
2098
2113
  amount: params.amount,
2099
2114
  outputStateTree: merkleTree,
2115
+ tokenProgramId,
2100
2116
  });
2101
2117
  return [splMintToInstruction, compressInstruction];
2102
2118
  }
@@ -2104,33 +2120,15 @@ class CompressedTokenProgram {
2104
2120
  * Construct transfer instruction for compressed tokens
2105
2121
  */
2106
2122
  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({
2123
+ const { payer, inputCompressedTokenAccounts, recentInputStateRootIndices, recentValidityProof, amount, outputStateTrees, toAddress, } = params;
2124
+ const tokenTransferOutputs = createTransferOutputState(inputCompressedTokenAccounts, toAddress, amount);
2125
+ const { inputTokenDataWithContext, packedOutputTokenData, remainingAccountMetas, } = packCompressedTokenAccounts({
2126
2126
  inputCompressedTokenAccounts,
2127
2127
  outputStateTrees,
2128
2128
  rootIndices: recentInputStateRootIndices,
2129
2129
  tokenTransferOutputs,
2130
2130
  });
2131
- const { mint, currentOwner } = parseTokenData(
2132
- inputCompressedTokenAccounts,
2133
- );
2131
+ const { mint, currentOwner } = parseTokenData(inputCompressedTokenAccounts);
2134
2132
  const data = {
2135
2133
  proof: recentValidityProof,
2136
2134
  mint,
@@ -2142,32 +2140,24 @@ class CompressedTokenProgram {
2142
2140
  cpiContext: null,
2143
2141
  lamportsChangeAccountMerkleTreeIndex: null,
2144
2142
  };
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();
2143
+ const encodedData = this.program.coder.types.encode('CompressedTokenInstructionDataTransfer', data);
2144
+ const { accountCompressionAuthority, noopProgram, registeredProgramPda, accountCompressionProgram, } = defaultStaticAccountsStruct();
2155
2145
  const instruction = await this.program.methods
2156
2146
  .transfer(encodedData)
2157
2147
  .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
- })
2148
+ feePayer: payer,
2149
+ authority: currentOwner,
2150
+ cpiAuthorityPda: this.deriveCpiAuthorityPda,
2151
+ lightSystemProgram: LightSystemProgram.programId,
2152
+ registeredProgramPda: registeredProgramPda,
2153
+ noopProgram: noopProgram,
2154
+ accountCompressionAuthority: accountCompressionAuthority,
2155
+ accountCompressionProgram: accountCompressionProgram,
2156
+ selfProgram: this.programId,
2157
+ tokenPoolPda: null,
2158
+ compressOrDecompressTokenAccount: null,
2159
+ tokenProgram: null,
2160
+ })
2171
2161
  .remainingAccounts(remainingAccountMetas)
2172
2162
  .instruction();
2173
2163
  return instruction;
@@ -2176,14 +2166,12 @@ class CompressedTokenProgram {
2176
2166
  * Create lookup table instructions for the token program's default accounts.
2177
2167
  */
2178
2168
  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
- });
2169
+ const { authority, mints, recentSlot, payer, remainingAccounts } = params;
2170
+ const [createInstruction, lookupTableAddress] = AddressLookupTableProgram.createLookupTable({
2171
+ authority,
2172
+ payer: authority,
2173
+ recentSlot,
2174
+ });
2187
2175
  let optionalMintKeys = [];
2188
2176
  if (mints) {
2189
2177
  optionalMintKeys = [
@@ -2208,6 +2196,7 @@ class CompressedTokenProgram {
2208
2196
  defaultTestStateTreeAccounts().addressQueue,
2209
2197
  this.programId,
2210
2198
  TOKEN_PROGRAM_ID,
2199
+ TOKEN_2022_PROGRAM_ID,
2211
2200
  authority,
2212
2201
  ...optionalMintKeys,
2213
2202
  ...(remainingAccounts ?? []),
@@ -2223,19 +2212,14 @@ class CompressedTokenProgram {
2223
2212
  * @returns compressInstruction
2224
2213
  */
2225
2214
  static async compress(params) {
2226
- const { payer, owner, source, toAddress, mint, outputStateTree } =
2227
- params;
2215
+ const { payer, owner, source, toAddress, mint, outputStateTree, tokenProgramId, } = params;
2228
2216
  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
- );
2217
+ throw new Error('Both amount and toAddress must be arrays or both must be single values');
2232
2218
  }
2233
2219
  let tokenTransferOutputs;
2234
2220
  if (Array.isArray(params.amount) && Array.isArray(params.toAddress)) {
2235
2221
  if (params.amount.length !== params.toAddress.length) {
2236
- throw new Error(
2237
- 'Amount and toAddress arrays must have the same length',
2238
- );
2222
+ throw new Error('Amount and toAddress arrays must have the same length');
2239
2223
  }
2240
2224
  tokenTransferOutputs = params.amount.map((amt, index) => {
2241
2225
  const amount = bn(amt);
@@ -2246,7 +2230,8 @@ class CompressedTokenProgram {
2246
2230
  tlv: null,
2247
2231
  };
2248
2232
  });
2249
- } else {
2233
+ }
2234
+ else {
2250
2235
  tokenTransferOutputs = [
2251
2236
  {
2252
2237
  owner: toAddress,
@@ -2256,11 +2241,7 @@ class CompressedTokenProgram {
2256
2241
  },
2257
2242
  ];
2258
2243
  }
2259
- const {
2260
- inputTokenDataWithContext,
2261
- packedOutputTokenData,
2262
- remainingAccountMetas,
2263
- } = packCompressedTokenAccounts({
2244
+ const { inputTokenDataWithContext, packedOutputTokenData, remainingAccountMetas, } = packCompressedTokenAccounts({
2264
2245
  inputCompressedTokenAccounts: [],
2265
2246
  outputStateTrees: outputStateTree,
2266
2247
  rootIndices: [],
@@ -2274,36 +2255,31 @@ class CompressedTokenProgram {
2274
2255
  outputCompressedAccounts: packedOutputTokenData,
2275
2256
  compressOrDecompressAmount: Array.isArray(params.amount)
2276
2257
  ? params.amount
2277
- .map(amt => new BN(amt))
2278
- .reduce((sum, amt) => sum.add(amt), new BN(0))
2258
+ .map(amt => new BN(amt))
2259
+ .reduce((sum, amt) => sum.add(amt), new BN(0))
2279
2260
  : new BN(params.amount),
2280
2261
  isCompress: true,
2281
2262
  cpiContext: null,
2282
2263
  lamportsChangeAccountMerkleTreeIndex: null,
2283
2264
  };
2284
- const encodedData = this.program.coder.types.encode(
2285
- 'CompressedTokenInstructionDataTransfer',
2286
- data,
2287
- );
2265
+ const encodedData = this.program.coder.types.encode('CompressedTokenInstructionDataTransfer', data);
2266
+ const tokenProgram = tokenProgramId ?? TOKEN_PROGRAM_ID;
2288
2267
  const instruction = await this.program.methods
2289
2268
  .transfer(encodedData)
2290
2269
  .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
- })
2270
+ feePayer: payer,
2271
+ authority: owner,
2272
+ cpiAuthorityPda: this.deriveCpiAuthorityPda,
2273
+ lightSystemProgram: LightSystemProgram.programId,
2274
+ registeredProgramPda: defaultStaticAccountsStruct().registeredProgramPda,
2275
+ noopProgram: defaultStaticAccountsStruct().noopProgram,
2276
+ accountCompressionAuthority: defaultStaticAccountsStruct().accountCompressionAuthority,
2277
+ accountCompressionProgram: defaultStaticAccountsStruct().accountCompressionProgram,
2278
+ selfProgram: this.programId,
2279
+ tokenPoolPda: this.deriveTokenPoolPda(mint),
2280
+ compressOrDecompressTokenAccount: source, // token
2281
+ tokenProgram,
2282
+ })
2307
2283
  .remainingAccounts(remainingAccountMetas)
2308
2284
  .instruction();
2309
2285
  return instruction;
@@ -2312,33 +2288,17 @@ class CompressedTokenProgram {
2312
2288
  * Construct decompress instruction
2313
2289
  */
2314
2290
  static async decompress(params) {
2315
- const {
2316
- payer,
2317
- inputCompressedTokenAccounts,
2318
- toAddress,
2319
- outputStateTree,
2320
- recentValidityProof,
2321
- recentInputStateRootIndices,
2322
- } = params;
2291
+ const { payer, inputCompressedTokenAccounts, toAddress, outputStateTree, recentValidityProof, recentInputStateRootIndices, tokenProgramId, } = params;
2323
2292
  const amount = bn(params.amount);
2324
- const tokenTransferOutputs = createDecompressOutputState(
2325
- inputCompressedTokenAccounts,
2326
- amount,
2327
- );
2293
+ const tokenTransferOutputs = createDecompressOutputState(inputCompressedTokenAccounts, amount);
2328
2294
  /// Pack
2329
- const {
2330
- inputTokenDataWithContext,
2331
- packedOutputTokenData,
2332
- remainingAccountMetas,
2333
- } = packCompressedTokenAccounts({
2295
+ const { inputTokenDataWithContext, packedOutputTokenData, remainingAccountMetas, } = packCompressedTokenAccounts({
2334
2296
  inputCompressedTokenAccounts,
2335
2297
  outputStateTrees: outputStateTree,
2336
2298
  rootIndices: recentInputStateRootIndices,
2337
2299
  tokenTransferOutputs: tokenTransferOutputs,
2338
2300
  });
2339
- const { mint, currentOwner } = parseTokenData(
2340
- inputCompressedTokenAccounts,
2341
- );
2301
+ const { mint, currentOwner } = parseTokenData(inputCompressedTokenAccounts);
2342
2302
  const data = {
2343
2303
  proof: recentValidityProof,
2344
2304
  mint,
@@ -2350,45 +2310,31 @@ class CompressedTokenProgram {
2350
2310
  cpiContext: null,
2351
2311
  lamportsChangeAccountMerkleTreeIndex: null,
2352
2312
  };
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();
2313
+ const encodedData = this.program.coder.types.encode('CompressedTokenInstructionDataTransfer', data);
2314
+ const { accountCompressionAuthority, noopProgram, registeredProgramPda, accountCompressionProgram, } = defaultStaticAccountsStruct();
2315
+ const tokenProgram = tokenProgramId ?? TOKEN_PROGRAM_ID;
2363
2316
  const instruction = await this.program.methods
2364
2317
  .transfer(encodedData)
2365
2318
  .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
- })
2319
+ feePayer: payer,
2320
+ authority: currentOwner,
2321
+ cpiAuthorityPda: this.deriveCpiAuthorityPda,
2322
+ lightSystemProgram: LightSystemProgram.programId,
2323
+ registeredProgramPda: registeredProgramPda,
2324
+ noopProgram: noopProgram,
2325
+ accountCompressionAuthority: accountCompressionAuthority,
2326
+ accountCompressionProgram: accountCompressionProgram,
2327
+ selfProgram: this.programId,
2328
+ tokenPoolPda: this.deriveTokenPoolPda(mint),
2329
+ compressOrDecompressTokenAccount: toAddress,
2330
+ tokenProgram,
2331
+ })
2379
2332
  .remainingAccounts(remainingAccountMetas)
2380
2333
  .instruction();
2381
2334
  return instruction;
2382
2335
  }
2383
2336
  static async mergeTokenAccounts(params) {
2384
- const {
2385
- payer,
2386
- owner,
2387
- inputCompressedTokenAccounts,
2388
- outputStateTree,
2389
- recentValidityProof,
2390
- recentInputStateRootIndices,
2391
- } = params;
2337
+ const { payer, owner, inputCompressedTokenAccounts, outputStateTree, recentValidityProof, recentInputStateRootIndices, } = params;
2392
2338
  if (inputCompressedTokenAccounts.length > 3) {
2393
2339
  throw new Error('Cannot merge more than 3 token accounts at once');
2394
2340
  }
@@ -2396,10 +2342,7 @@ class CompressedTokenProgram {
2396
2342
  payer,
2397
2343
  inputCompressedTokenAccounts,
2398
2344
  toAddress: owner,
2399
- amount: inputCompressedTokenAccounts.reduce(
2400
- (sum, account) => sum.add(account.parsed.amount),
2401
- new BN(0),
2402
- ),
2345
+ amount: inputCompressedTokenAccounts.reduce((sum, account) => sum.add(account.parsed.amount), new BN(0)),
2403
2346
  outputStateTrees: outputStateTree,
2404
2347
  recentInputStateRootIndices,
2405
2348
  recentValidityProof,
@@ -2407,14 +2350,8 @@ class CompressedTokenProgram {
2407
2350
  return [ix];
2408
2351
  }
2409
2352
  static async compressSplTokenAccount(params) {
2410
- const {
2411
- feePayer,
2412
- authority,
2413
- tokenAccount,
2414
- mint,
2415
- remainingAmount,
2416
- outputStateTree,
2417
- } = params;
2353
+ const { feePayer, authority, tokenAccount, mint, remainingAmount, outputStateTree, tokenProgramId, } = params;
2354
+ const tokenProgram = tokenProgramId ?? TOKEN_PROGRAM_ID;
2418
2355
  const remainingAccountMetas = [
2419
2356
  {
2420
2357
  pubkey: outputStateTree,
@@ -2425,27 +2362,27 @@ class CompressedTokenProgram {
2425
2362
  const instruction = await this.program.methods
2426
2363
  .compressSplTokenAccount(authority, remainingAmount ?? null, null)
2427
2364
  .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
- })
2365
+ feePayer,
2366
+ authority,
2367
+ cpiAuthorityPda: this.deriveCpiAuthorityPda,
2368
+ lightSystemProgram: LightSystemProgram.programId,
2369
+ registeredProgramPda: defaultStaticAccountsStruct().registeredProgramPda,
2370
+ noopProgram: defaultStaticAccountsStruct().noopProgram,
2371
+ accountCompressionAuthority: defaultStaticAccountsStruct().accountCompressionAuthority,
2372
+ accountCompressionProgram: defaultStaticAccountsStruct().accountCompressionProgram,
2373
+ selfProgram: this.programId,
2374
+ tokenPoolPda: this.deriveTokenPoolPda(mint),
2375
+ compressOrDecompressTokenAccount: tokenAccount,
2376
+ tokenProgram,
2377
+ systemProgram: SystemProgram.programId,
2378
+ })
2445
2379
  .remainingAccounts(remainingAccountMetas)
2446
2380
  .instruction();
2447
2381
  return instruction;
2448
2382
  }
2383
+ static async get_mint_program_id(mint, connection) {
2384
+ return (await connection.getAccountInfo(mint))?.owner;
2385
+ }
2449
2386
  }
2450
2387
 
2451
2388
  /**
@@ -2463,22 +2400,11 @@ class CompressedTokenProgram {
2463
2400
  *
2464
2401
  * @return Signature of the confirmed transaction
2465
2402
  */
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
- );
2403
+ async function approveAndMintTo(rpc, payer, mint, destination, authority, amount, merkleTree, confirmOptions, tokenProgramId) {
2404
+ tokenProgramId = tokenProgramId
2405
+ ? tokenProgramId
2406
+ : await CompressedTokenProgram.get_mint_program_id(mint, rpc);
2407
+ const authorityTokenAccount = await getOrCreateAssociatedTokenAccount(rpc, payer, mint, authority.publicKey, undefined, undefined, confirmOptions, tokenProgramId);
2482
2408
  const ixs = await CompressedTokenProgram.approveAndMintTo({
2483
2409
  feePayer: payer.publicKey,
2484
2410
  mint,
@@ -2487,18 +2413,14 @@ async function approveAndMintTo(
2487
2413
  amount,
2488
2414
  toPubkey: destination,
2489
2415
  merkleTree,
2416
+ tokenProgramId,
2490
2417
  });
2491
2418
  const { blockhash } = await rpc.getLatestBlockhash();
2492
2419
  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
- );
2420
+ const tx = buildAndSignTx([
2421
+ ComputeBudgetProgram.setComputeUnitLimit({ units: 1_000_000 }),
2422
+ ...ixs,
2423
+ ], payer, blockhash, additionalSigners);
2502
2424
  const txId = await sendAndConfirmTx(rpc, tx, confirmOptions);
2503
2425
  return txId;
2504
2426
  }
@@ -2521,17 +2443,10 @@ async function approveAndMintTo(
2521
2443
  *
2522
2444
  * @return Signature of the confirmed transaction
2523
2445
  */
2524
- async function compress(
2525
- rpc,
2526
- payer,
2527
- mint,
2528
- amount,
2529
- owner,
2530
- sourceTokenAccount,
2531
- toAddress,
2532
- merkleTree,
2533
- confirmOptions,
2534
- ) {
2446
+ async function compress(rpc, payer, mint, amount, owner, sourceTokenAccount, toAddress, merkleTree, confirmOptions, tokenProgramId) {
2447
+ tokenProgramId = tokenProgramId
2448
+ ? tokenProgramId
2449
+ : await CompressedTokenProgram.get_mint_program_id(mint, rpc);
2535
2450
  const compressIx = await CompressedTokenProgram.compress({
2536
2451
  payer: payer.publicKey,
2537
2452
  owner: owner.publicKey,
@@ -2540,26 +2455,17 @@ async function compress(
2540
2455
  amount,
2541
2456
  mint,
2542
2457
  outputStateTree: merkleTree,
2458
+ tokenProgramId,
2543
2459
  });
2544
2460
  const blockhashCtx = await rpc.getLatestBlockhash();
2545
2461
  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
- );
2462
+ const signedTx = buildAndSignTx([
2463
+ ComputeBudgetProgram.setComputeUnitLimit({
2464
+ units: 1_000_000,
2465
+ }),
2466
+ compressIx,
2467
+ ], payer, blockhashCtx.blockhash, additionalSigners);
2468
+ const txId = await sendAndConfirmTx(rpc, signedTx, confirmOptions, blockhashCtx);
2563
2469
  return txId;
2564
2470
  }
2565
2471
 
@@ -2580,31 +2486,15 @@ async function compress(
2580
2486
  *
2581
2487
  * @return Signature of the confirmed transaction
2582
2488
  */
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
- ) {
2489
+ async function transfer(rpc, payer, mint, amount, owner, toAddress,
2490
+ /// TODO: allow multiple
2491
+ merkleTree, confirmOptions) {
2594
2492
  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
- );
2493
+ const compressedTokenAccounts = await rpc.getCompressedTokenAccountsByOwner(owner.publicKey, {
2494
+ mint,
2495
+ });
2496
+ const [inputAccounts] = selectMinCompressedTokenAccountsForTransfer(compressedTokenAccounts.items, amount);
2497
+ const proof = await rpc.getValidityProof(inputAccounts.map(account => bn(account.compressedAccount.hash)));
2608
2498
  const ix = await CompressedTokenProgram.transfer({
2609
2499
  payer: payer.publicKey,
2610
2500
  inputCompressedTokenAccounts: inputAccounts,
@@ -2616,12 +2506,7 @@ async function transfer(
2616
2506
  });
2617
2507
  const { blockhash } = await rpc.getLatestBlockhash();
2618
2508
  const additionalSigners = dedupeSigner(payer, [owner]);
2619
- const signedTx = buildAndSignTx(
2620
- [ComputeBudgetProgram.setComputeUnitLimit({ units: 1_000_000 }), ix],
2621
- payer,
2622
- blockhash,
2623
- additionalSigners,
2624
- );
2509
+ const signedTx = buildAndSignTx([ComputeBudgetProgram.setComputeUnitLimit({ units: 1_000_000 }), ix], payer, blockhash, additionalSigners);
2625
2510
  const txId = await sendAndConfirmTx(rpc, signedTx, confirmOptions);
2626
2511
  return txId;
2627
2512
  }
@@ -2638,17 +2523,14 @@ function selectMinCompressedTokenAccountsForTransfer(accounts, transferAmount) {
2638
2523
  const selectedAccounts = [];
2639
2524
  accounts.sort((a, b) => b.parsed.amount.cmp(a.parsed.amount));
2640
2525
  for (const account of accounts) {
2641
- if (accumulatedAmount.gte(bn(transferAmount))) break;
2526
+ if (accumulatedAmount.gte(bn(transferAmount)))
2527
+ break;
2642
2528
  accumulatedAmount = accumulatedAmount.add(account.parsed.amount);
2643
- accumulatedLamports = accumulatedLamports.add(
2644
- account.compressedAccount.lamports,
2645
- );
2529
+ accumulatedLamports = accumulatedLamports.add(account.compressedAccount.lamports);
2646
2530
  selectedAccounts.push(account);
2647
2531
  }
2648
2532
  if (accumulatedAmount.lt(bn(transferAmount))) {
2649
- throw new Error(
2650
- `Not enough balance for transfer. Required: ${transferAmount.toString()}, available: ${accumulatedAmount.toString()}`,
2651
- );
2533
+ throw new Error(`Not enough balance for transfer. Required: ${transferAmount.toString()}, available: ${accumulatedAmount.toString()}`);
2652
2534
  }
2653
2535
  return [
2654
2536
  selectedAccounts,
@@ -2675,32 +2557,19 @@ function selectMinCompressedTokenAccountsForTransfer(accounts, transferAmount) {
2675
2557
  *
2676
2558
  * @return Signature of the confirmed transaction
2677
2559
  */
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
- ) {
2560
+ async function decompress(rpc, payer, mint, amount, owner, toAddress,
2561
+ /// TODO: allow multiple
2562
+ merkleTree, confirmOptions, tokenProgramId) {
2563
+ tokenProgramId = tokenProgramId
2564
+ ? tokenProgramId
2565
+ : await CompressedTokenProgram.get_mint_program_id(mint, rpc);
2689
2566
  amount = bn(amount);
2690
- const compressedTokenAccounts = await rpc.getCompressedTokenAccountsByOwner(
2691
- owner.publicKey,
2692
- {
2693
- mint,
2694
- },
2695
- );
2567
+ const compressedTokenAccounts = await rpc.getCompressedTokenAccountsByOwner(owner.publicKey, {
2568
+ mint,
2569
+ });
2696
2570
  /// 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
- );
2571
+ const [inputAccounts] = selectMinCompressedTokenAccountsForTransfer(compressedTokenAccounts.items, amount);
2572
+ const proof = await rpc.getValidityProof(inputAccounts.map(account => bn(account.compressedAccount.hash)));
2704
2573
  const ix = await CompressedTokenProgram.decompress({
2705
2574
  payer: payer.publicKey,
2706
2575
  inputCompressedTokenAccounts: inputAccounts,
@@ -2709,15 +2578,11 @@ async function decompress(
2709
2578
  outputStateTree: merkleTree,
2710
2579
  recentInputStateRootIndices: proof.rootIndices,
2711
2580
  recentValidityProof: proof.compressedProof,
2581
+ tokenProgramId,
2712
2582
  });
2713
2583
  const { blockhash } = await rpc.getLatestBlockhash();
2714
2584
  const additionalSigners = dedupeSigner(payer, [owner]);
2715
- const signedTx = buildAndSignTx(
2716
- [ComputeBudgetProgram.setComputeUnitLimit({ units: 1_000_000 }), ix],
2717
- payer,
2718
- blockhash,
2719
- additionalSigners,
2720
- );
2585
+ const signedTx = buildAndSignTx([ComputeBudgetProgram.setComputeUnitLimit({ units: 1_000_000 }), ix], payer, blockhash, additionalSigners);
2721
2586
  const txId = await sendAndConfirmTx(rpc, signedTx, confirmOptions);
2722
2587
  return txId;
2723
2588
  }
@@ -2731,19 +2596,13 @@ async function decompress(
2731
2596
  * @param decimals Location of the decimal place
2732
2597
  * @param keypair Optional keypair, defaulting to a new random one
2733
2598
  * @param confirmOptions Options for confirming the transaction
2599
+ * @param isToken22 Whether to create a Token 2022 mint. Defaults to false.
2734
2600
  *
2735
2601
  * @return Address of the new mint and the transaction signature
2736
2602
  */
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);
2603
+ async function createMint(rpc, payer, mintAuthority, decimals, keypair = Keypair.generate(), confirmOptions, isToken22 = false) {
2604
+ const rentExemptBalance = await rpc.getMinimumBalanceForRentExemption(MINT_SIZE);
2605
+ const tokenProgramId = isToken22 ? TOKEN_2022_PROGRAM_ID : TOKEN_PROGRAM_ID;
2747
2606
  const ixs = await CompressedTokenProgram.createMint({
2748
2607
  feePayer: payer.publicKey,
2749
2608
  mint: keypair.publicKey,
@@ -2751,6 +2610,7 @@ async function createMint(
2751
2610
  authority: mintAuthority,
2752
2611
  freezeAuthority: null, // TODO: add feature
2753
2612
  rentExemptBalance,
2613
+ tokenProgramId,
2754
2614
  });
2755
2615
  const { blockhash } = await rpc.getLatestBlockhash();
2756
2616
  const additionalSigners = dedupeSigner(payer, [keypair]);
@@ -2776,16 +2636,10 @@ async function createMint(
2776
2636
  *
2777
2637
  * @return Signature of the confirmed transaction
2778
2638
  */
2779
- async function mintTo(
2780
- rpc,
2781
- payer,
2782
- mint,
2783
- destination,
2784
- authority,
2785
- amount,
2786
- merkleTree,
2787
- confirmOptions,
2788
- ) {
2639
+ async function mintTo(rpc, payer, mint, destination, authority, amount, merkleTree, confirmOptions, tokenProgramId) {
2640
+ tokenProgramId = tokenProgramId
2641
+ ? tokenProgramId
2642
+ : await CompressedTokenProgram.get_mint_program_id(mint, rpc);
2789
2643
  const additionalSigners = dedupeSigner(payer, [authority]);
2790
2644
  const ix = await CompressedTokenProgram.mintTo({
2791
2645
  feePayer: payer.publicKey,
@@ -2794,14 +2648,10 @@ async function mintTo(
2794
2648
  amount: amount,
2795
2649
  toPubkey: destination,
2796
2650
  merkleTree,
2651
+ tokenProgramId,
2797
2652
  });
2798
2653
  const { blockhash } = await rpc.getLatestBlockhash();
2799
- const tx = buildAndSignTx(
2800
- [ComputeBudgetProgram.setComputeUnitLimit({ units: 1_000_000 }), ix],
2801
- payer,
2802
- blockhash,
2803
- additionalSigners,
2804
- );
2654
+ const tx = buildAndSignTx([ComputeBudgetProgram.setComputeUnitLimit({ units: 1_000_000 }), ix], payer, blockhash, additionalSigners);
2805
2655
  const txId = await sendAndConfirmTx(rpc, tx, confirmOptions);
2806
2656
  return txId;
2807
2657
  }
@@ -2819,60 +2669,34 @@ async function mintTo(
2819
2669
  *
2820
2670
  * @return Array of transaction signatures
2821
2671
  */
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
- );
2672
+ async function mergeTokenAccounts(rpc, payer, mint, owner, merkleTree, confirmOptions) {
2673
+ const compressedTokenAccounts = await rpc.getCompressedTokenAccountsByOwner(owner.publicKey, { mint });
2834
2674
  if (compressedTokenAccounts.items.length === 0) {
2835
- throw new Error(
2836
- `No compressed token accounts found for mint ${mint.toBase58()}`,
2837
- );
2675
+ throw new Error(`No compressed token accounts found for mint ${mint.toBase58()}`);
2838
2676
  }
2839
2677
  if (compressedTokenAccounts.items.length >= 6) {
2840
- throw new Error(
2841
- `Too many compressed token accounts used for mint ${mint.toBase58()}`,
2842
- );
2678
+ throw new Error(`Too many compressed token accounts used for mint ${mint.toBase58()}`);
2843
2679
  }
2844
2680
  const instructions = [
2845
2681
  ComputeBudgetProgram.setComputeUnitLimit({ units: 1_000_000 }),
2846
2682
  ];
2847
- for (
2848
- let i = 0;
2849
- i < compressedTokenAccounts.items.slice(0, 6).length;
2850
- i += 3
2851
- ) {
2683
+ for (let i = 0; i < compressedTokenAccounts.items.slice(0, 6).length; i += 3) {
2852
2684
  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
- });
2685
+ const proof = await rpc.getValidityProof(batch.map(account => bn(account.compressedAccount.hash)));
2686
+ const batchInstructions = await CompressedTokenProgram.mergeTokenAccounts({
2687
+ payer: payer.publicKey,
2688
+ owner: owner.publicKey,
2689
+ mint,
2690
+ inputCompressedTokenAccounts: batch,
2691
+ outputStateTree: merkleTree,
2692
+ recentValidityProof: proof.compressedProof,
2693
+ recentInputStateRootIndices: proof.rootIndices,
2694
+ });
2866
2695
  instructions.push(...batchInstructions);
2867
2696
  }
2868
2697
  const { blockhash } = await rpc.getLatestBlockhash();
2869
2698
  const additionalSigners = dedupeSigner(payer, [owner]);
2870
- const signedTx = buildAndSignTx(
2871
- instructions,
2872
- payer,
2873
- blockhash,
2874
- additionalSigners,
2875
- );
2699
+ const signedTx = buildAndSignTx(instructions, payer, blockhash, additionalSigners);
2876
2700
  const txId = await sendAndConfirmTx(rpc, signedTx, confirmOptions);
2877
2701
  return txId;
2878
2702
  }
@@ -2888,10 +2712,14 @@ async function mergeTokenAccounts(
2888
2712
  *
2889
2713
  * @return transaction signature
2890
2714
  */
2891
- async function createTokenPool(rpc, payer, mintAddress, confirmOptions) {
2715
+ async function createTokenPool(rpc, payer, mint, confirmOptions, tokenProgramId) {
2716
+ tokenProgramId = tokenProgramId
2717
+ ? tokenProgramId
2718
+ : await CompressedTokenProgram.get_mint_program_id(mint, rpc);
2892
2719
  const ix = await CompressedTokenProgram.createTokenPool({
2893
2720
  feePayer: payer.publicKey,
2894
- mint: mintAddress,
2721
+ mint,
2722
+ tokenProgramId,
2895
2723
  });
2896
2724
  const { blockhash } = await rpc.getLatestBlockhash();
2897
2725
  const tx = buildAndSignTx([ix], payer, blockhash);
@@ -2912,50 +2740,23 @@ async function createTokenPool(rpc, payer, mintAddress, confirmOptions) {
2912
2740
  *
2913
2741
  * @return Transaction signatures and the address of the created lookup table
2914
2742
  */
2915
- async function createTokenProgramLookupTable(
2916
- rpc,
2917
- payer,
2918
- authority,
2919
- mints,
2920
- additionalAccounts,
2921
- ) {
2743
+ async function createTokenProgramLookupTable(rpc, payer, authority, mints, additionalAccounts) {
2922
2744
  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
- });
2745
+ const { instructions, address } = await CompressedTokenProgram.createTokenProgramLookupTable({
2746
+ payer: payer.publicKey,
2747
+ authority: authority.publicKey,
2748
+ mints,
2749
+ remainingAccounts: additionalAccounts,
2750
+ recentSlot,
2751
+ });
2931
2752
  const additionalSigners = dedupeSigner(payer, [authority]);
2932
2753
  const blockhashCtx = await rpc.getLatestBlockhash();
2933
- const signedTx = buildAndSignTx(
2934
- [instructions[0]],
2935
- payer,
2936
- blockhashCtx.blockhash,
2937
- additionalSigners,
2938
- );
2754
+ const signedTx = buildAndSignTx([instructions[0]], payer, blockhashCtx.blockhash, additionalSigners);
2939
2755
  /// Must wait for the first instruction to be finalized.
2940
- const txId = await sendAndConfirmTx(
2941
- rpc,
2942
- signedTx,
2943
- { commitment: 'finalized' },
2944
- blockhashCtx,
2945
- );
2756
+ const txId = await sendAndConfirmTx(rpc, signedTx, { commitment: 'finalized' }, blockhashCtx);
2946
2757
  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
- );
2758
+ const signedTx2 = buildAndSignTx([instructions[1]], payer, blockhashCtx2.blockhash, additionalSigners);
2759
+ const txId2 = await sendAndConfirmTx(rpc, signedTx2, { commitment: 'finalized' }, blockhashCtx2);
2959
2760
  return { txIds: [txId, txId2], address };
2960
2761
  }
2961
2762
 
@@ -2973,16 +2774,10 @@ async function createTokenProgramLookupTable(
2973
2774
  *
2974
2775
  * @return Signature of the confirmed transaction
2975
2776
  */
2976
- async function compressSplTokenAccount(
2977
- rpc,
2978
- payer,
2979
- mint,
2980
- owner,
2981
- tokenAccount,
2982
- outputStateTree,
2983
- remainingAmount,
2984
- confirmOptions,
2985
- ) {
2777
+ async function compressSplTokenAccount(rpc, payer, mint, owner, tokenAccount, outputStateTree, remainingAmount, confirmOptions, tokenProgramId) {
2778
+ tokenProgramId = tokenProgramId
2779
+ ? tokenProgramId
2780
+ : await CompressedTokenProgram.get_mint_program_id(mint, rpc);
2986
2781
  const compressIx = await CompressedTokenProgram.compressSplTokenAccount({
2987
2782
  feePayer: payer.publicKey,
2988
2783
  authority: owner.publicKey,
@@ -2990,51 +2785,19 @@ async function compressSplTokenAccount(
2990
2785
  mint,
2991
2786
  remainingAmount,
2992
2787
  outputStateTree,
2788
+ tokenProgramId,
2993
2789
  });
2994
2790
  const blockhashCtx = await rpc.getLatestBlockhash();
2995
2791
  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
- );
2792
+ const signedTx = buildAndSignTx([
2793
+ ComputeBudgetProgram.setComputeUnitLimit({
2794
+ units: 1_000_000,
2795
+ }),
2796
+ compressIx,
2797
+ ], payer, blockhashCtx.blockhash, additionalSigners);
2798
+ const txId = await sendAndConfirmTx(rpc, signedTx, confirmOptions, blockhashCtx);
3013
2799
  return txId;
3014
2800
  }
3015
2801
 
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
- };
2802
+ 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
2803
  //# sourceMappingURL=index.js.map