diff --git a/cli/package.json b/cli/package.json index b3d05a95fe..b13ea97860 100644 --- a/cli/package.json +++ b/cli/package.json @@ -42,7 +42,7 @@ "@oclif/plugin-not-found": "^3.1.2", "@oclif/plugin-plugins": "^5.0.7", "@solana-developers/helpers": "^1.5.1", - "@solana/web3.js": "1.95.3", + "@solana/web3.js": "1.98.0", "axios": "^1.6.8", "case-anything": "^2.1.13", "cli-progress": "^3.12.0", diff --git a/examples/browser/nextjs/package.json b/examples/browser/nextjs/package.json index ed13251ad0..c8a55afd72 100644 --- a/examples/browser/nextjs/package.json +++ b/examples/browser/nextjs/package.json @@ -19,7 +19,7 @@ "@solana/wallet-adapter-react": "^0.15.35", "@solana/wallet-adapter-react-ui": "^0.9.35", "@solana/wallet-adapter-unsafe-burner": "^0.1.7", - "@solana/web3.js": "^1.95.3", + "@solana/web3.js": "1.98.0", "next": "15.0.4", "react": "^19", "react-dom": "^19" diff --git a/examples/node/esm/package.json b/examples/node/esm/package.json index 70fcf649b5..0ea2c56039 100644 --- a/examples/node/esm/package.json +++ b/examples/node/esm/package.json @@ -18,7 +18,7 @@ }, "dependencies": { "@coral-xyz/anchor": "^0.30.0", - "@solana/web3.js": "^1.95.3", + "@solana/web3.js": "1.98.0", "@lightprotocol/stateless.js": "workspace:*" } } diff --git a/js/compressed-token/package.json b/js/compressed-token/package.json index c39663e3d2..9d26e45e98 100644 --- a/js/compressed-token/package.json +++ b/js/compressed-token/package.json @@ -1,6 +1,6 @@ { "name": "@lightprotocol/compressed-token", - "version": "0.17.1", + "version": "0.18.0", "description": "JS client to interact with the compressed-token program", "sideEffects": false, "main": "dist/cjs/node/index.cjs", @@ -21,37 +21,6 @@ "files": [ "dist" ], - "scripts": { - "test": "pnpm test:e2e:all", - "test-all": "vitest run", - "test:unit:all": "EXCLUDE_E2E=true vitest run", - "test-all:verbose": "vitest run --reporter=verbose", - "test-validator": "./../../cli/test_bin/run test-validator --prover-run-mode rpc", - "test:e2e:create-mint": "pnpm test-validator && vitest run tests/e2e/create-mint.test.ts", - "test:e2e:create-token-pool": "pnpm test-validator && vitest run tests/e2e/create-token-pool.test.ts", - "test:e2e:mint-to": "pnpm test-validator && vitest run tests/e2e/mint-to.test.ts --reporter=verbose", - "test:e2e:approve-and-mint-to": "pnpm test-validator && vitest run tests/e2e/approve-and-mint-to.test.ts --reporter=verbose", - "test:e2e:merge-token-accounts": "pnpm test-validator && vitest run tests/e2e/merge-token-accounts.test.ts --reporter=verbose", - "test:e2e:transfer": "pnpm test-validator && vitest run tests/e2e/transfer.test.ts --reporter=verbose", - "test:e2e:compress": "pnpm test-validator && vitest run tests/e2e/compress.test.ts --reporter=verbose", - "test:e2e:compress-spl-token-account": "pnpm test-validator && vitest run tests/e2e/compress-spl-token-account.test.ts --reporter=verbose", - "test:e2e:decompress": "pnpm test-validator && vitest run tests/e2e/decompress.test.ts --reporter=verbose", - "test:e2e:rpc-token-interop": "pnpm test-validator && vitest run tests/e2e/rpc-token-interop.test.ts --reporter=verbose", - "test:e2e:custom-program-id": "vitest run tests/e2e/custom-program-id.test.ts --reporter=verbose", - "test:e2e:all": "pnpm test-validator && vitest run tests/e2e/create-mint.test.ts && vitest run tests/e2e/mint-to.test.ts && vitest run tests/e2e/transfer.test.ts && vitest run tests/e2e/compress.test.ts && vitest run tests/e2e/compress-spl-token-account.test.ts && vitest run tests/e2e/decompress.test.ts && vitest run tests/e2e/create-token-pool.test.ts && vitest run tests/e2e/approve-and-mint-to.test.ts && vitest run tests/e2e/rpc-token-interop.test.ts && vitest run tests/e2e/custom-program-id.test.ts", - "pull-idl": "../../scripts/push-compressed-token-idl.sh", - "build": "rimraf dist && pnpm pull-idl && pnpm build:bundle", - "build:bundle": "rollup -c", - "format": "prettier --write .", - "lint": "eslint ." - }, - "keywords": [ - "zk", - "compression", - "light", - "stateless", - "solana" - ], "maintainers": [ { "name": "Light Protocol Maintainers", @@ -60,16 +29,17 @@ ], "license": "Apache-2.0", "peerDependencies": { - "@lightprotocol/stateless.js": "workspace:*" + "@lightprotocol/stateless.js": "workspace:*", + "@solana/spl-token": ">=0.3.9", + "@solana/web3.js": ">=1.73.5" }, "dependencies": { - "@coral-xyz/anchor": "0.29.0", - "@solana/web3.js": "1.95.3", - "@solana/spl-token": "0.4.8", - "buffer": "6.0.3", - "tweetnacl": "1.0.3" + "@coral-xyz/borsh": "^0.29.0", + "bn.js": "^5.2.1", + "buffer": "6.0.3" }, "devDependencies": { + "@coral-xyz/anchor": "^0.29.0", "@esbuild-plugins/node-globals-polyfill": "^0.2.3", "@lightprotocol/hasher.rs": "0.2.1", "@lightprotocol/programs": "workspace:*", @@ -81,6 +51,9 @@ "@rollup/plugin-replace": "^5.0.7", "@rollup/plugin-terser": "^0.4.4", "@rollup/plugin-typescript": "^11.1.6", + "@solana/spl-token": "0.4.8", + "@solana/web3.js": "1.98.0", + "@types/bn.js": "^5.1.5", "@types/node": "^22.5.5", "@typescript-eslint/eslint-plugin": "^7.13.1", "@typescript-eslint/parser": "^7.13.1", @@ -103,6 +76,37 @@ "typescript": "^5.6.2", "vitest": "^2.1.1" }, + "scripts": { + "test": "pnpm test:e2e:all", + "test-all": "vitest run", + "test:unit:all": "EXCLUDE_E2E=true vitest run", + "test-all:verbose": "vitest run --reporter=verbose", + "test-validator": "./../../cli/test_bin/run test-validator --prover-run-mode rpc", + "test:e2e:create-mint": "pnpm test-validator && NODE_OPTIONS='--trace-deprecation' vitest run tests/e2e/create-mint.test.ts --reporter=verbose", + "test:e2e:layout": "vitest run tests/e2e/layout.test.ts --reporter=verbose", + "test:e2e:create-token-pool": "pnpm test-validator && vitest run tests/e2e/create-token-pool.test.ts", + "test:e2e:mint-to": "pnpm test-validator && vitest run tests/e2e/mint-to.test.ts --reporter=verbose", + "test:e2e:approve-and-mint-to": "pnpm test-validator && vitest run tests/e2e/approve-and-mint-to.test.ts --reporter=verbose", + "test:e2e:merge-token-accounts": "pnpm test-validator && vitest run tests/e2e/merge-token-accounts.test.ts --reporter=verbose", + "test:e2e:transfer": "pnpm test-validator && vitest run tests/e2e/transfer.test.ts --reporter=verbose", + "test:e2e:compress": "pnpm test-validator && vitest run tests/e2e/compress.test.ts --reporter=verbose", + "test:e2e:compress-spl-token-account": "pnpm test-validator && vitest run tests/e2e/compress-spl-token-account.test.ts --reporter=verbose", + "test:e2e:decompress": "pnpm test-validator && vitest run tests/e2e/decompress.test.ts --reporter=verbose", + "test:e2e:rpc-token-interop": "pnpm test-validator && vitest run tests/e2e/rpc-token-interop.test.ts --reporter=verbose", + "test:e2e:all": "pnpm test-validator && vitest run tests/e2e/create-mint.test.ts && vitest run tests/e2e/mint-to.test.ts && vitest run tests/e2e/transfer.test.ts && vitest run tests/e2e/compress.test.ts && vitest run tests/e2e/compress-spl-token-account.test.ts && vitest run tests/e2e/decompress.test.ts && vitest run tests/e2e/create-token-pool.test.ts && vitest run tests/e2e/approve-and-mint-to.test.ts && vitest run tests/e2e/rpc-token-interop.test.ts && vitest run tests/e2e/layout.test.ts", + "pull-idl": "../../scripts/push-compressed-token-idl.sh", + "build": "rimraf dist && pnpm build:bundle", + "build:bundle": "rollup -c", + "format": "prettier --write .", + "lint": "eslint ." + }, + "keywords": [ + "zk", + "compression", + "light", + "stateless", + "solana" + ], "nx": { "targets": { "build": { diff --git a/js/compressed-token/rollup.config.js b/js/compressed-token/rollup.config.js index c363738fb1..6f02c4084b 100644 --- a/js/compressed-token/rollup.config.js +++ b/js/compressed-token/rollup.config.js @@ -5,6 +5,7 @@ import resolve from '@rollup/plugin-node-resolve'; import commonjs from '@rollup/plugin-commonjs'; import alias from '@rollup/plugin-alias'; import json from '@rollup/plugin-json'; +import terser from '@rollup/plugin-terser'; const rolls = (fmt, env) => ({ input: 'src/index.ts', @@ -16,10 +17,9 @@ const rolls = (fmt, env) => ({ }, external: [ '@solana/web3.js', - '@coral-xyz/anchor', '@solana/spl-token', + '@coral-xyz/borsh', '@lightprotocol/stateless.js', - 'tweetnacl', ], plugins: [ json(), @@ -45,6 +45,26 @@ const rolls = (fmt, env) => ({ ], }), env === 'browser' ? nodePolyfills() : undefined, + terser({ + compress: { + drop_console: true, + drop_debugger: true, + passes: 3, + pure_funcs: ['console.log', 'console.error', 'console.warn'], + booleans_as_integers: true, + keep_fargs: false, + keep_fnames: false, + keep_infinity: true, + reduce_funcs: true, + reduce_vars: true, + }, + mangle: { + toplevel: true, + }, + output: { + comments: false, + }, + }), ].filter(Boolean), onwarn(warning, warn) { if (warning.code !== 'CIRCULAR_DEPENDENCY') { @@ -61,7 +81,6 @@ const typesConfig = { export default [ rolls('cjs', 'browser'), - rolls('es', 'browser'), rolls('cjs', 'node'), typesConfig, ]; diff --git a/js/compressed-token/src/actions/approve-and-mint-to.ts b/js/compressed-token/src/actions/approve-and-mint-to.ts index 316f79758c..0e3e1f03b3 100644 --- a/js/compressed-token/src/actions/approve-and-mint-to.ts +++ b/js/compressed-token/src/actions/approve-and-mint-to.ts @@ -5,7 +5,7 @@ import { Signer, TransactionSignature, } from '@solana/web3.js'; -import { BN } from '@coral-xyz/anchor'; +import BN from 'bn.js'; import { sendAndConfirmTx, buildAndSignTx, diff --git a/js/compressed-token/src/actions/compress-spl-token-account.ts b/js/compressed-token/src/actions/compress-spl-token-account.ts index b50f09f6f8..b0713cf924 100644 --- a/js/compressed-token/src/actions/compress-spl-token-account.ts +++ b/js/compressed-token/src/actions/compress-spl-token-account.ts @@ -12,7 +12,7 @@ import { dedupeSigner, } from '@lightprotocol/stateless.js'; -import { BN } from '@coral-xyz/anchor'; +import BN from 'bn.js'; import { CompressedTokenProgram } from '../program'; diff --git a/js/compressed-token/src/actions/compress.ts b/js/compressed-token/src/actions/compress.ts index b99ffae64f..cd43e896ac 100644 --- a/js/compressed-token/src/actions/compress.ts +++ b/js/compressed-token/src/actions/compress.ts @@ -12,7 +12,7 @@ import { dedupeSigner, } from '@lightprotocol/stateless.js'; -import { BN } from '@coral-xyz/anchor'; +import BN from 'bn.js'; import { CompressedTokenProgram } from '../program'; diff --git a/js/compressed-token/src/actions/decompress.ts b/js/compressed-token/src/actions/decompress.ts index 45027d388c..8734491800 100644 --- a/js/compressed-token/src/actions/decompress.ts +++ b/js/compressed-token/src/actions/decompress.ts @@ -13,7 +13,7 @@ import { dedupeSigner, } from '@lightprotocol/stateless.js'; -import { BN } from '@coral-xyz/anchor'; +import BN from 'bn.js'; import { CompressedTokenProgram } from '../program'; import { selectMinCompressedTokenAccountsForTransfer } from './transfer'; diff --git a/js/compressed-token/src/actions/mint-to.ts b/js/compressed-token/src/actions/mint-to.ts index f4addc3279..fd4b0c3d59 100644 --- a/js/compressed-token/src/actions/mint-to.ts +++ b/js/compressed-token/src/actions/mint-to.ts @@ -5,7 +5,7 @@ import { Signer, TransactionSignature, } from '@solana/web3.js'; -import { BN } from '@coral-xyz/anchor'; +import BN from 'bn.js'; import { sendAndConfirmTx, buildAndSignTx, diff --git a/js/compressed-token/src/actions/transfer.ts b/js/compressed-token/src/actions/transfer.ts index a70e92eb06..d38f6deff8 100644 --- a/js/compressed-token/src/actions/transfer.ts +++ b/js/compressed-token/src/actions/transfer.ts @@ -14,7 +14,7 @@ import { dedupeSigner, } from '@lightprotocol/stateless.js'; -import { BN } from '@coral-xyz/anchor'; +import BN from 'bn.js'; import { CompressedTokenProgram } from '../program'; diff --git a/js/compressed-token/src/constants.ts b/js/compressed-token/src/constants.ts index 2e741fa86a..74acb9e2ca 100644 --- a/js/compressed-token/src/constants.ts +++ b/js/compressed-token/src/constants.ts @@ -3,3 +3,16 @@ export const POOL_SEED = Buffer.from('pool'); export const CPI_AUTHORITY_SEED = Buffer.from('cpi_authority'); export const SPL_TOKEN_MINT_RENT_EXEMPT_BALANCE = 1461600; + +export const CREATE_TOKEN_POOL_DISCRIMINATOR = Buffer.from([ + 23, 169, 27, 122, 147, 169, 209, 152, +]); +export const MINT_TO_DISCRIMINATOR = Buffer.from([ + 241, 34, 48, 186, 37, 179, 123, 192, +]); +export const TRANSFER_DISCRIMINATOR = Buffer.from([ + 163, 52, 200, 231, 140, 3, 69, 186, +]); +export const COMPRESS_SPL_TOKEN_ACCOUNT_DISCRIMINATOR = Buffer.from([ + 112, 230, 105, 101, 145, 202, 157, 97, +]); diff --git a/js/compressed-token/src/idl/light_compressed_token.ts b/js/compressed-token/src/idl.ts similarity index 100% rename from js/compressed-token/src/idl/light_compressed_token.ts rename to js/compressed-token/src/idl.ts diff --git a/js/compressed-token/src/idl/index.ts b/js/compressed-token/src/idl/index.ts deleted file mode 100644 index fa14d6102c..0000000000 --- a/js/compressed-token/src/idl/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './light_compressed_token'; diff --git a/js/compressed-token/src/index.ts b/js/compressed-token/src/index.ts index 13ce6bee3c..3df507112b 100644 --- a/js/compressed-token/src/index.ts +++ b/js/compressed-token/src/index.ts @@ -1,6 +1,7 @@ -export * from './idl'; export * from './instructions'; export * from './constants'; export * from './program'; export * from './types'; export * from './actions'; +export * from './layout'; +export * from './idl'; diff --git a/js/compressed-token/src/instructions/pack-compressed-token-accounts.ts b/js/compressed-token/src/instructions/pack-compressed-token-accounts.ts index 5e6b279d11..2a15d388ab 100644 --- a/js/compressed-token/src/instructions/pack-compressed-token-accounts.ts +++ b/js/compressed-token/src/instructions/pack-compressed-token-accounts.ts @@ -4,10 +4,12 @@ import { getIndexOrAdd, bn, padOutputStateMerkleTrees, - TokenTransferOutputData, } from '@lightprotocol/stateless.js'; import { PublicKey, AccountMeta } from '@solana/web3.js'; -import { PackedTokenTransferOutputData } from '../types'; +import { + PackedTokenTransferOutputData, + TokenTransferOutputData, +} from '../types'; export type PackCompressedTokenAccountsParams = { /** Input state to be consumed */ diff --git a/js/compressed-token/src/layout.ts b/js/compressed-token/src/layout.ts new file mode 100644 index 0000000000..ed691ab6c8 --- /dev/null +++ b/js/compressed-token/src/layout.ts @@ -0,0 +1,439 @@ +import { + struct, + option, + vec, + bool, + u64, + u8, + publicKey, + array, + u32, + u16, + vecU8, +} from '@coral-xyz/borsh'; +import { Buffer } from 'buffer'; +import { AccountMeta, PublicKey } from '@solana/web3.js'; +import { CompressedTokenProgram } from './program'; +import { + CompressedTokenInstructionDataTransfer, + CompressSplTokenAccountInstructionData, + MintToInstructionData, +} from './types'; +import { + COMPRESS_SPL_TOKEN_ACCOUNT_DISCRIMINATOR, + MINT_TO_DISCRIMINATOR, + TRANSFER_DISCRIMINATOR, +} from './constants'; + +const CompressedProofLayout = struct([ + array(u8(), 32, 'a'), + array(u8(), 64, 'b'), + array(u8(), 32, 'c'), +]); + +const PackedTokenTransferOutputDataLayout = struct([ + publicKey('owner'), + u64('amount'), + option(u64(), 'lamports'), + u8('merkleTreeIndex'), + option(vecU8(), 'tlv'), +]); + +const QueueIndexLayout = struct([u8('queueId'), u16('index')]); + +const InputTokenDataWithContextLayout = struct([ + u64('amount'), + option(u8(), 'delegateIndex'), + struct( + [ + u8('merkleTreePubkeyIndex'), + u8('nullifierQueuePubkeyIndex'), + u32('leafIndex'), + option(QueueIndexLayout, 'queueIndex'), + ], + 'merkleContext', + ), + u16('rootIndex'), + option(u64(), 'lamports'), + option(vecU8(), 'tlv'), +]); + +export const DelegatedTransferLayout = struct([ + publicKey('owner'), + option(u8(), 'delegateChangeAccountIndex'), +]); + +export const CpiContextLayout = struct([ + bool('setContext'), + bool('firstSetContext'), + u8('cpiContextAccountIndex'), +]); + +export const CompressedTokenInstructionDataTransferLayout = struct([ + option(CompressedProofLayout, 'proof'), + publicKey('mint'), + option(DelegatedTransferLayout, 'delegatedTransfer'), + vec(InputTokenDataWithContextLayout, 'inputTokenDataWithContext'), + vec(PackedTokenTransferOutputDataLayout, 'outputCompressedAccounts'), + bool('isCompress'), + option(u64(), 'compressOrDecompressAmount'), + option(CpiContextLayout, 'cpiContext'), + option(u8(), 'lamportsChangeAccountMerkleTreeIndex'), +]); + +export const mintToLayout = struct([ + vec(publicKey(), 'recipients'), + vec(u64(), 'amounts'), + option(u64(), 'lamports'), +]); + +export const compressSplTokenAccountInstructionDataLayout = struct([ + publicKey('owner'), + option(u64(), 'remainingAmount'), + option(CpiContextLayout, 'cpiContext'), +]); + +export function encodeMintToInstructionData( + data: MintToInstructionData, +): Buffer { + const buffer = Buffer.alloc(1000); + const len = mintToLayout.encode( + { + recipients: data.recipients, + amounts: data.amounts, + lamports: data.lamports, + }, + buffer, + ); + + return Buffer.concat([MINT_TO_DISCRIMINATOR, buffer.slice(0, len)]); +} + +export function decodeMintToInstructionData( + buffer: Buffer, +): MintToInstructionData { + const data: any = mintToLayout.decode( + buffer.slice(MINT_TO_DISCRIMINATOR.length), + ); + return { + recipients: data.recipients, + amounts: data.amounts, + lamports: data.lamports, + }; +} + +export function encodeCompressSplTokenAccountInstructionData( + data: CompressSplTokenAccountInstructionData, +): Buffer { + const buffer = Buffer.alloc(1000); + const len = compressSplTokenAccountInstructionDataLayout.encode( + { + owner: data.owner, + remainingAmount: data.remainingAmount, + cpiContext: data.cpiContext, + }, + buffer, + ); + + return Buffer.concat([ + COMPRESS_SPL_TOKEN_ACCOUNT_DISCRIMINATOR, + buffer.slice(0, len), + ]); +} + +export function decodeCompressSplTokenAccountInstructionData( + buffer: Buffer, +): CompressSplTokenAccountInstructionData { + const data: any = compressSplTokenAccountInstructionDataLayout.decode( + buffer.slice(COMPRESS_SPL_TOKEN_ACCOUNT_DISCRIMINATOR.length), + ); + return { + owner: data.owner, + remainingAmount: data.remainingAmount, + cpiContext: data.cpiContext, + }; +} +export function encodeTransferInstructionData( + data: CompressedTokenInstructionDataTransfer, +): Buffer { + const buffer = Buffer.alloc(1000); + + const len = CompressedTokenInstructionDataTransferLayout.encode( + data, + buffer, + ); + + const lengthBuffer = Buffer.alloc(4); + lengthBuffer.writeUInt32LE(len, 0); + + return Buffer.concat([ + TRANSFER_DISCRIMINATOR, + lengthBuffer, + buffer.slice(0, len), + ]); +} + +export function decodeTransferInstructionData( + buffer: Buffer, +): CompressedTokenInstructionDataTransfer { + return CompressedTokenInstructionDataTransferLayout.decode( + buffer.slice(TRANSFER_DISCRIMINATOR.length + 4), + ) as CompressedTokenInstructionDataTransfer; +} + +interface BaseAccountsLayoutParams { + feePayer: PublicKey; + authority: PublicKey; + cpiAuthorityPda: PublicKey; + lightSystemProgram: PublicKey; + registeredProgramPda: PublicKey; + noopProgram: PublicKey; + accountCompressionAuthority: PublicKey; + accountCompressionProgram: PublicKey; + selfProgram: PublicKey; + systemProgram: PublicKey; +} +export type createTokenPoolAccountsLayoutParams = { + feePayer: PublicKey; + tokenPoolPda: PublicKey; + systemProgram: PublicKey; + mint: PublicKey; + tokenProgram: PublicKey; + cpiAuthorityPda: PublicKey; +}; +export type mintToAccountsLayoutParams = BaseAccountsLayoutParams & { + mint: PublicKey; + tokenPoolPda: PublicKey; + tokenProgram: PublicKey; + merkleTree: PublicKey; + solPoolPda: PublicKey | null; +}; +export type transferAccountsLayoutParams = BaseAccountsLayoutParams & { + tokenPoolPda?: PublicKey; + compressOrDecompressTokenAccount?: PublicKey; + tokenProgram?: PublicKey; +}; +export type approveAccountsLayoutParams = BaseAccountsLayoutParams; +export type revokeAccountsLayoutParams = approveAccountsLayoutParams; +export type freezeAccountsLayoutParams = BaseAccountsLayoutParams & { + mint: PublicKey; +}; +export type thawAccountsLayoutParams = freezeAccountsLayoutParams; + +export const createTokenPoolAccountsLayout = ( + accounts: createTokenPoolAccountsLayoutParams, +): AccountMeta[] => { + const { + feePayer, + tokenPoolPda, + systemProgram, + mint, + tokenProgram, + cpiAuthorityPda, + } = accounts; + return [ + { pubkey: feePayer, isSigner: true, isWritable: true }, + { pubkey: tokenPoolPda, isSigner: false, isWritable: true }, + { pubkey: systemProgram, isSigner: false, isWritable: false }, + { pubkey: mint, isSigner: false, isWritable: true }, + { pubkey: tokenProgram, isSigner: false, isWritable: false }, + { pubkey: cpiAuthorityPda, isSigner: false, isWritable: false }, + ]; +}; + +export const mintToAccountsLayout = ( + accounts: mintToAccountsLayoutParams, +): AccountMeta[] => { + const defaultPubkey = CompressedTokenProgram.programId; + const { + feePayer, + authority, + cpiAuthorityPda, + mint, + tokenPoolPda, + tokenProgram, + lightSystemProgram, + registeredProgramPda, + noopProgram, + accountCompressionAuthority, + accountCompressionProgram, + merkleTree, + selfProgram, + systemProgram, + solPoolPda, + } = accounts; + + const accountsList: AccountMeta[] = [ + { pubkey: feePayer, isSigner: true, isWritable: true }, + { pubkey: authority, isSigner: true, isWritable: false }, + { pubkey: cpiAuthorityPda, isSigner: false, isWritable: false }, + { pubkey: mint, isSigner: false, isWritable: true }, + { pubkey: tokenPoolPda, isSigner: false, isWritable: true }, + { pubkey: tokenProgram, isSigner: false, isWritable: false }, + { pubkey: lightSystemProgram, isSigner: false, isWritable: false }, + { pubkey: registeredProgramPda, isSigner: false, isWritable: false }, + { pubkey: noopProgram, isSigner: false, isWritable: false }, + { + pubkey: accountCompressionAuthority, + isSigner: false, + isWritable: false, + }, + { + pubkey: accountCompressionProgram, + isSigner: false, + isWritable: false, + }, + { pubkey: merkleTree, isSigner: false, isWritable: true }, + { pubkey: selfProgram, isSigner: false, isWritable: false }, + { pubkey: systemProgram, isSigner: false, isWritable: false }, + { + pubkey: solPoolPda ?? defaultPubkey, + isSigner: false, + isWritable: true, + }, + ]; + + return accountsList; +}; + +export const transferAccountsLayout = ( + accounts: transferAccountsLayoutParams, +): AccountMeta[] => { + const defaultPubkey = CompressedTokenProgram.programId; + const { + feePayer, + authority, + cpiAuthorityPda, + lightSystemProgram, + registeredProgramPda, + noopProgram, + accountCompressionAuthority, + accountCompressionProgram, + selfProgram, + tokenPoolPda, + compressOrDecompressTokenAccount, + tokenProgram, + systemProgram, + } = accounts; + + const accountsList: AccountMeta[] = [ + { pubkey: feePayer, isSigner: true, isWritable: true }, + { pubkey: authority, isSigner: true, isWritable: false }, + { pubkey: cpiAuthorityPda, isSigner: false, isWritable: false }, + { pubkey: lightSystemProgram, isSigner: false, isWritable: false }, + { pubkey: registeredProgramPda, isSigner: false, isWritable: false }, + { pubkey: noopProgram, isSigner: false, isWritable: false }, + { + pubkey: accountCompressionAuthority, + isSigner: false, + isWritable: false, + }, + { + pubkey: accountCompressionProgram, + isSigner: false, + isWritable: false, + }, + { pubkey: selfProgram, isSigner: false, isWritable: false }, + { + pubkey: tokenPoolPda ?? defaultPubkey, + isSigner: false, + isWritable: true, + }, + { + pubkey: compressOrDecompressTokenAccount ?? defaultPubkey, + isSigner: false, + isWritable: true, + }, + { + pubkey: tokenProgram ?? defaultPubkey, + isSigner: false, + isWritable: false, + }, + { pubkey: systemProgram, isSigner: false, isWritable: false }, + ]; + + return accountsList; +}; + +// TODO: use this layout for approve/revoke/freeze/thaw once we add them +// export const approveAccountsLayout = ( +// accounts: approveAccountsLayoutParams, +// ): AccountMeta[] => { +// const { +// feePayer, +// authority, +// cpiAuthorityPda, +// lightSystemProgram, +// registeredProgramPda, +// noopProgram, +// accountCompressionAuthority, +// accountCompressionProgram, +// selfProgram, +// systemProgram, +// } = accounts; + +// return [ +// { pubkey: feePayer, isSigner: true, isWritable: true }, +// { pubkey: authority, isSigner: true, isWritable: false }, +// { pubkey: cpiAuthorityPda, isSigner: false, isWritable: false }, +// { pubkey: lightSystemProgram, isSigner: false, isWritable: false }, +// { pubkey: registeredProgramPda, isSigner: false, isWritable: false }, +// { pubkey: noopProgram, isSigner: false, isWritable: false }, +// { +// pubkey: accountCompressionAuthority, +// isSigner: false, +// isWritable: false, +// }, +// { +// pubkey: accountCompressionProgram, +// isSigner: false, +// isWritable: false, +// }, +// { pubkey: selfProgram, isSigner: false, isWritable: false }, +// { pubkey: systemProgram, isSigner: false, isWritable: false }, +// ]; +// }; + +// export const revokeAccountsLayout = approveAccountsLayout; + +// export const freezeAccountsLayout = ( +// accounts: freezeAccountsLayoutParams, +// ): AccountMeta[] => { +// const { +// feePayer, +// authority, +// cpiAuthorityPda, +// lightSystemProgram, +// registeredProgramPda, +// noopProgram, +// accountCompressionAuthority, +// accountCompressionProgram, +// selfProgram, +// systemProgram, +// mint, +// } = accounts; + +// return [ +// { pubkey: feePayer, isSigner: true, isWritable: true }, +// { pubkey: authority, isSigner: true, isWritable: false }, +// { pubkey: cpiAuthorityPda, isSigner: false, isWritable: false }, +// { pubkey: lightSystemProgram, isSigner: false, isWritable: false }, +// { pubkey: registeredProgramPda, isSigner: false, isWritable: false }, +// { pubkey: noopProgram, isSigner: false, isWritable: false }, +// { +// pubkey: accountCompressionAuthority, +// isSigner: false, +// isWritable: false, +// }, +// { +// pubkey: accountCompressionProgram, +// isSigner: false, +// isWritable: false, +// }, +// { pubkey: selfProgram, isSigner: false, isWritable: false }, +// { pubkey: systemProgram, isSigner: false, isWritable: false }, +// { pubkey: mint, isSigner: false, isWritable: false }, +// ]; +// }; + +// export const thawAccountsLayout = freezeAccountsLayout; diff --git a/js/compressed-token/src/program.ts b/js/compressed-token/src/program.ts index f92ea299cb..997d225b54 100644 --- a/js/compressed-token/src/program.ts +++ b/js/compressed-token/src/program.ts @@ -1,26 +1,20 @@ import { PublicKey, - Keypair, TransactionInstruction, SystemProgram, Connection, AddressLookupTableProgram, AccountMeta, } from '@solana/web3.js'; -import { BN, Program, AnchorProvider, setProvider } from '@coral-xyz/anchor'; -import { IDL, LightCompressedToken } from './idl/light_compressed_token'; +import BN from 'bn.js'; import { CompressedProof, LightSystemProgram, ParsedTokenAccount, - TokenTransferOutputData, bn, - confirmConfig, - CompressedTokenInstructionDataTransfer, defaultStaticAccountsStruct, sumUpLamports, toArray, - useWallet, validateSameOwner, validateSufficientBalance, defaultTestStateTreeAccounts, @@ -32,8 +26,24 @@ import { createInitializeMint2Instruction, createMintToInstruction, } from '@solana/spl-token'; -import { CPI_AUTHORITY_SEED, POOL_SEED } from './constants'; +import { + CPI_AUTHORITY_SEED, + POOL_SEED, + CREATE_TOKEN_POOL_DISCRIMINATOR, +} from './constants'; import { packCompressedTokenAccounts } from './instructions/pack-compressed-token-accounts'; +import { + encodeTransferInstructionData, + encodeCompressSplTokenAccountInstructionData, + encodeMintToInstructionData, + createTokenPoolAccountsLayout, + mintToAccountsLayout, + transferAccountsLayout, +} from './layout'; +import { + CompressedTokenInstructionDataTransfer, + TokenTransferOutputData, +} from './types'; export type CompressParams = { /** @@ -518,42 +528,6 @@ export class CompressedTokenProgram { typeof programId === 'string' ? new PublicKey(programId) : programId; - // Reset program when programId changes - this._program = null; - } - - private static _program: Program | null = null; - - /** @internal */ - static get program(): Program { - if (!this._program) { - this.initializeProgram(); - } - return this._program!; - } - - /** - * @internal - * Initializes the program statically if not already initialized. - */ - private static initializeProgram() { - if (!this._program) { - /// Note: We can use a mock connection because we're using the - /// program only for serde and building instructions, not for - /// interacting with the network. - const mockKeypair = Keypair.generate(); - const mockConnection = new Connection( - 'http://127.0.0.1:8899', - 'confirmed', - ); - const mockProvider = new AnchorProvider( - mockConnection, - useWallet(mockKeypair), - confirmConfig, - ); - setProvider(mockProvider); - this._program = new Program(IDL, this.programId, mockProvider); - } } /** @internal */ @@ -638,19 +612,20 @@ export class CompressedTokenProgram { const tokenPoolPda = this.deriveTokenPoolPda(mint); - const ix = await this.program.methods - .createTokenPool() - .accounts({ - mint, - feePayer, - tokenPoolPda, - systemProgram: SystemProgram.programId, - tokenProgram, - cpiAuthorityPda: this.deriveCpiAuthorityPda, - }) - .instruction(); - - return ix; + const keys = createTokenPoolAccountsLayout({ + mint, + feePayer, + tokenPoolPda, + tokenProgram, + cpiAuthorityPda: this.deriveCpiAuthorityPda, + systemProgram: SystemProgram.programId, + }); + + return new TransactionInstruction({ + programId: this.programId, + keys, + data: CREATE_TOKEN_POOL_DISCRIMINATOR, + }); } /** @@ -681,29 +656,35 @@ export class CompressedTokenProgram { 'Amount and toPubkey arrays must have the same length', ); } + const keys = mintToAccountsLayout({ + mint, + feePayer, + authority, + cpiAuthorityPda: this.deriveCpiAuthorityPda, + tokenProgram, + tokenPoolPda, + lightSystemProgram: LightSystemProgram.programId, + registeredProgramPda: systemKeys.registeredProgramPda, + noopProgram: systemKeys.noopProgram, + accountCompressionAuthority: systemKeys.accountCompressionAuthority, + accountCompressionProgram: systemKeys.accountCompressionProgram, + merkleTree: merkleTree ?? defaultTestStateTreeAccounts().merkleTree, + selfProgram: this.programId, + systemProgram: SystemProgram.programId, + solPoolPda: null, // TODO: add lamports support + }); - const instruction = await this.program.methods - .mintTo(toPubkeys, amounts, null) - .accounts({ - feePayer, - authority, - cpiAuthorityPda: this.deriveCpiAuthorityPda, - mint, - tokenPoolPda, - tokenProgram, - lightSystemProgram: LightSystemProgram.programId, - registeredProgramPda: systemKeys.registeredProgramPda, - noopProgram: systemKeys.noopProgram, - accountCompressionAuthority: - systemKeys.accountCompressionAuthority, - accountCompressionProgram: systemKeys.accountCompressionProgram, - merkleTree: - merkleTree ?? defaultTestStateTreeAccounts().merkleTree, - selfProgram: this.programId, - solPoolPda: null, - }) - .instruction(); - return instruction; + const data = encodeMintToInstructionData({ + recipients: toPubkeys, + amounts, + lamports: null, + }); + + return new TransactionInstruction({ + programId: this.programId, + keys, + data, + }); } /** @@ -783,7 +764,7 @@ export class CompressedTokenProgram { inputCompressedTokenAccounts, ); - const data: CompressedTokenInstructionDataTransfer = { + const rawData: CompressedTokenInstructionDataTransfer = { proof: recentValidityProof, mint, delegatedTransfer: null, // TODO: implement @@ -794,11 +775,7 @@ export class CompressedTokenProgram { cpiContext: null, lamportsChangeAccountMerkleTreeIndex: null, }; - - const encodedData = this.program.coder.types.encode( - 'CompressedTokenInstructionDataTransfer', - data, - ); + const data = encodeTransferInstructionData(rawData); const { accountCompressionAuthority, @@ -806,27 +783,29 @@ export class CompressedTokenProgram { registeredProgramPda, accountCompressionProgram, } = defaultStaticAccountsStruct(); + const keys = transferAccountsLayout({ + feePayer: payer, + authority: currentOwner, + cpiAuthorityPda: this.deriveCpiAuthorityPda, + lightSystemProgram: LightSystemProgram.programId, + registeredProgramPda: registeredProgramPda, + noopProgram: noopProgram, + accountCompressionAuthority: accountCompressionAuthority, + accountCompressionProgram: accountCompressionProgram, + selfProgram: this.programId, + tokenPoolPda: undefined, + compressOrDecompressTokenAccount: undefined, + tokenProgram: undefined, + systemProgram: SystemProgram.programId, + }); + + keys.push(...remainingAccountMetas); - const instruction = await this.program.methods - .transfer(encodedData) - .accounts({ - feePayer: payer!, - authority: currentOwner!, - cpiAuthorityPda: this.deriveCpiAuthorityPda, - lightSystemProgram: LightSystemProgram.programId, - registeredProgramPda: registeredProgramPda, - noopProgram: noopProgram, - accountCompressionAuthority: accountCompressionAuthority, - accountCompressionProgram: accountCompressionProgram, - selfProgram: this.programId, - tokenPoolPda: null, - compressOrDecompressTokenAccount: null, - tokenProgram: null, - }) - .remainingAccounts(remainingAccountMetas) - .instruction(); - - return instruction; + return new TransactionInstruction({ + programId: this.programId, + keys, + data, + }); } /** @@ -945,7 +924,7 @@ export class CompressedTokenProgram { tokenTransferOutputs, }); - const data: CompressedTokenInstructionDataTransfer = { + const rawData: CompressedTokenInstructionDataTransfer = { proof: null, mint, delegatedTransfer: null, // TODO: implement @@ -960,36 +939,30 @@ export class CompressedTokenProgram { cpiContext: null, lamportsChangeAccountMerkleTreeIndex: null, }; + const data = encodeTransferInstructionData(rawData); - const encodedData = this.program.coder.types.encode( - 'CompressedTokenInstructionDataTransfer', - data, - ); const tokenProgram = tokenProgramId ?? TOKEN_PROGRAM_ID; - const instruction = await this.program.methods - .transfer(encodedData) - .accounts({ - feePayer: payer, - authority: owner, - cpiAuthorityPda: this.deriveCpiAuthorityPda, - lightSystemProgram: LightSystemProgram.programId, - registeredProgramPda: - defaultStaticAccountsStruct().registeredProgramPda, - noopProgram: defaultStaticAccountsStruct().noopProgram, - accountCompressionAuthority: - defaultStaticAccountsStruct().accountCompressionAuthority, - accountCompressionProgram: - defaultStaticAccountsStruct().accountCompressionProgram, - selfProgram: this.programId, - tokenPoolPda: this.deriveTokenPoolPda(mint), - compressOrDecompressTokenAccount: source, // token - tokenProgram, - }) - .remainingAccounts(remainingAccountMetas) - .instruction(); - - return instruction; + const keys = transferAccountsLayout({ + ...defaultStaticAccountsStruct(), + feePayer: payer, + authority: owner, + cpiAuthorityPda: this.deriveCpiAuthorityPda, + lightSystemProgram: LightSystemProgram.programId, + selfProgram: this.programId, + systemProgram: SystemProgram.programId, + tokenPoolPda: this.deriveTokenPoolPda(mint), + compressOrDecompressTokenAccount: source, + tokenProgram, + }); + + keys.push(...remainingAccountMetas); + + return new TransactionInstruction({ + programId: this.programId, + keys, + data, + }); } /** @@ -1030,7 +1003,7 @@ export class CompressedTokenProgram { inputCompressedTokenAccounts, ); - const data: CompressedTokenInstructionDataTransfer = { + const rawData: CompressedTokenInstructionDataTransfer = { proof: recentValidityProof, mint, delegatedTransfer: null, // TODO: implement @@ -1041,12 +1014,8 @@ export class CompressedTokenProgram { cpiContext: null, lamportsChangeAccountMerkleTreeIndex: null, }; - - const encodedData = this.program.coder.types.encode( - 'CompressedTokenInstructionDataTransfer', - data, - ); - + const data = encodeTransferInstructionData(rawData); + const tokenProgram = tokenProgramId ?? TOKEN_PROGRAM_ID; const { accountCompressionAuthority, noopProgram, @@ -1054,28 +1023,29 @@ export class CompressedTokenProgram { accountCompressionProgram, } = defaultStaticAccountsStruct(); - const tokenProgram = tokenProgramId ?? TOKEN_PROGRAM_ID; + const keys = transferAccountsLayout({ + feePayer: payer, + authority: currentOwner, + cpiAuthorityPda: this.deriveCpiAuthorityPda, + lightSystemProgram: LightSystemProgram.programId, + registeredProgramPda: registeredProgramPda, + noopProgram: noopProgram, + accountCompressionAuthority: accountCompressionAuthority, + accountCompressionProgram: accountCompressionProgram, + selfProgram: this.programId, + tokenPoolPda: this.deriveTokenPoolPda(mint), + compressOrDecompressTokenAccount: toAddress, + tokenProgram, + systemProgram: SystemProgram.programId, + }); - const instruction = await this.program.methods - .transfer(encodedData) - .accounts({ - feePayer: payer, - authority: currentOwner, - cpiAuthorityPda: this.deriveCpiAuthorityPda, - lightSystemProgram: LightSystemProgram.programId, - registeredProgramPda: registeredProgramPda, - noopProgram: noopProgram, - accountCompressionAuthority: accountCompressionAuthority, - accountCompressionProgram: accountCompressionProgram, - selfProgram: this.programId, - tokenPoolPda: this.deriveTokenPoolPda(mint), - compressOrDecompressTokenAccount: toAddress, - tokenProgram, - }) - .remainingAccounts(remainingAccountMetas) - .instruction(); - - return instruction; + keys.push(...remainingAccountMetas); + + return new TransactionInstruction({ + programId: this.programId, + keys, + data, + }); } static async mergeTokenAccounts( @@ -1132,30 +1102,40 @@ export class CompressedTokenProgram { }, ]; - const instruction = await this.program.methods - .compressSplTokenAccount(authority, remainingAmount ?? null, null) - .accounts({ - feePayer, - authority, - cpiAuthorityPda: this.deriveCpiAuthorityPda, - lightSystemProgram: LightSystemProgram.programId, - registeredProgramPda: - defaultStaticAccountsStruct().registeredProgramPda, - noopProgram: defaultStaticAccountsStruct().noopProgram, - accountCompressionAuthority: - defaultStaticAccountsStruct().accountCompressionAuthority, - accountCompressionProgram: - defaultStaticAccountsStruct().accountCompressionProgram, - selfProgram: this.programId, - tokenPoolPda: this.deriveTokenPoolPda(mint), - compressOrDecompressTokenAccount: tokenAccount, - tokenProgram, - systemProgram: SystemProgram.programId, - }) - .remainingAccounts(remainingAccountMetas) - .instruction(); - - return instruction; + const data = encodeCompressSplTokenAccountInstructionData({ + owner: authority, + remainingAmount: remainingAmount ?? null, + cpiContext: null, + }); + const { + accountCompressionAuthority, + noopProgram, + registeredProgramPda, + accountCompressionProgram, + } = defaultStaticAccountsStruct(); + const keys = transferAccountsLayout({ + feePayer, + authority, + cpiAuthorityPda: this.deriveCpiAuthorityPda, + lightSystemProgram: LightSystemProgram.programId, + registeredProgramPda: registeredProgramPda, + noopProgram: noopProgram, + accountCompressionAuthority: accountCompressionAuthority, + accountCompressionProgram: accountCompressionProgram, + selfProgram: this.programId, + tokenPoolPda: this.deriveTokenPoolPda(mint), + compressOrDecompressTokenAccount: tokenAccount, + tokenProgram, + systemProgram: SystemProgram.programId, + }); + + keys.push(...remainingAccountMetas); + + return new TransactionInstruction({ + programId: this.programId, + keys, + data, + }); } static async get_mint_program_id( diff --git a/js/compressed-token/src/types.ts b/js/compressed-token/src/types.ts index d5852a6618..a8016585ed 100644 --- a/js/compressed-token/src/types.ts +++ b/js/compressed-token/src/types.ts @@ -1,7 +1,15 @@ import { PublicKey } from '@solana/web3.js'; -import { BN } from '@coral-xyz/anchor'; -import { CompressedProof } from '@lightprotocol/stateless.js'; +import BN from 'bn.js'; +import { + CompressedProof, + PackedMerkleContext, +} from '@lightprotocol/stateless.js'; +export type CompressedCpiContext = { + setContext: boolean; + firstSetContext: boolean; + cpiContextAccountIndex: number; // u8 +}; /// TODO: remove index_mt_account on-chain. passed as part of /// CompressedTokenInstructionDataInvoke export type TokenTransferOutputData = { @@ -47,45 +55,35 @@ export type PackedTokenTransferOutputData = { }; export type InputTokenDataWithContext = { - /** - * The amount of tokens to transfer - */ amount: BN; - /** - * Optional: The index of the delegate in remaining accounts - */ delegateIndex: number | null; - /** - * The index of the merkle tree address in remaining accounts - */ - merkleTreePubkeyIndex: number; - /** - * The index of the nullifier queue address in remaining accounts - */ - nullifierQueuePubkeyIndex: number; - /** - * The index of the leaf in the merkle tree - */ - leafIndex: number; - /** - * Lamports in the input token account. - */ + merkleContext: PackedMerkleContext; + rootIndex: number; lamports: BN | null; - /** - * TokenExtension tlv - */ tlv: Buffer | null; }; -export type CompressedTokenInstructionDataInvoke = { +export type DelegatedTransfer = { + owner: PublicKey; + delegateChangeAccountIndex: number | null; +}; + +export type MintToInstructionData = { + recipients: PublicKey[]; + amounts: BN[]; + lamports: BN | null; +}; +export type CompressSplTokenAccountInstructionData = { + owner: PublicKey; + remainingAmount: BN | null; + cpiContext: CompressedCpiContext | null; +}; + +export type CompressedTokenInstructionDataTransfer = { /** * Validity proof */ proof: CompressedProof | null; - /** - * The root indices of the transfer - */ - rootIndices: number[]; /** * The mint of the transfer */ @@ -94,7 +92,7 @@ export type CompressedTokenInstructionDataInvoke = { * Whether the signer is a delegate * TODO: implement delegated transfer struct */ - delegatedTransfer: null; + delegatedTransfer: DelegatedTransfer | null; /** * Input token data with packed merkle context */ @@ -102,12 +100,20 @@ export type CompressedTokenInstructionDataInvoke = { /** * Data of the output token accounts */ - outputCompressedAccounts: TokenTransferOutputData[]; + outputCompressedAccounts: PackedTokenTransferOutputData[]; + /** + * Whether it's a compress or decompress action if compressOrDecompressAmount is non-null + */ + isCompress: boolean; + /** + * If null, it's a transfer. + * If some, the amount that is being deposited into (compress) or withdrawn from (decompress) the token escrow + */ + compressOrDecompressAmount: BN | null; /** - * The indices of the output state merkle tree accounts in 'remaining - * accounts' + * CPI context if */ - outputStateMerkleTreeAccountIndices: Buffer; + cpiContext: CompressedCpiContext | null; /** * The index of the Merkle tree for a lamport change account. */ diff --git a/js/compressed-token/tests/e2e/approve-and-mint-to.test.ts b/js/compressed-token/tests/e2e/approve-and-mint-to.test.ts index ccce1e68b6..63576b0f3b 100644 --- a/js/compressed-token/tests/e2e/approve-and-mint-to.test.ts +++ b/js/compressed-token/tests/e2e/approve-and-mint-to.test.ts @@ -17,7 +17,7 @@ import { getTestRpc, } from '@lightprotocol/stateless.js'; import { WasmFactory } from '@lightprotocol/hasher.rs'; -import { BN } from '@coral-xyz/anchor'; +import BN from 'bn.js'; async function createTestSplMint( rpc: Rpc, diff --git a/js/compressed-token/tests/e2e/compress.test.ts b/js/compressed-token/tests/e2e/compress.test.ts index 7751db9f04..5ae12b879a 100644 --- a/js/compressed-token/tests/e2e/compress.test.ts +++ b/js/compressed-token/tests/e2e/compress.test.ts @@ -5,7 +5,7 @@ import { Signer, ComputeBudgetProgram, } from '@solana/web3.js'; -import { BN } from '@coral-xyz/anchor'; +import BN from 'bn.js'; import { ParsedTokenAccount, Rpc, diff --git a/js/compressed-token/tests/e2e/create-token-pool.test.ts b/js/compressed-token/tests/e2e/create-token-pool.test.ts index 249af5e38a..1e285a3b66 100644 --- a/js/compressed-token/tests/e2e/create-token-pool.test.ts +++ b/js/compressed-token/tests/e2e/create-token-pool.test.ts @@ -18,6 +18,7 @@ import { getTestRpc, } from '@lightprotocol/stateless.js'; import { WasmFactory } from '@lightprotocol/hasher.rs'; +import { TOKEN_2022_PROGRAM_ID } from '@solana/spl-token'; /** * Assert that createTokenPool() creates system-pool account for external mint, @@ -58,6 +59,7 @@ async function createTestSplMint( payer: Signer, mintKeypair: Signer, mintAuthority: Keypair, + isToken22?: boolean, ) { const rentExemptBalance = await rpc.getMinimumBalanceForRentExemption(MINT_SIZE); @@ -74,7 +76,7 @@ async function createTestSplMint( TEST_TOKEN_DECIMALS, mintAuthority.publicKey, null, - TOKEN_PROGRAM_ID, + isToken22 ? TOKEN_2022_PROGRAM_ID : TOKEN_PROGRAM_ID, ); const { blockhash } = await rpc.getLatestBlockhash(); @@ -136,6 +138,52 @@ describe('createTokenPool', () => { /// Mint already registered await expect(createTokenPool(rpc, payer, mint)).rejects.toThrow(); }); + it('should register existing spl token22 mint', async () => { + const token22MintKeypair = Keypair.generate(); + const token22Mint = token22MintKeypair.publicKey; + const token22MintAuthority = Keypair.generate(); + + /// Create external SPL Token 2022 mint + await createTestSplMint( + rpc, + payer, + token22MintKeypair, + token22MintAuthority, + ); + + const poolAccount = + CompressedTokenProgram.deriveTokenPoolPda(token22Mint); + + assert(token22Mint.equals(token22MintKeypair.publicKey)); + + /// Mint already exists externally + await expect( + createMint( + rpc, + payer, + token22MintAuthority.publicKey, + TEST_TOKEN_DECIMALS, + token22MintKeypair, + undefined, + true, + ), + ).rejects.toThrow(); + + await createTokenPool(rpc, payer, token22Mint); + + await assertRegisterMint( + token22Mint, + token22MintAuthority.publicKey, + rpc, + TEST_TOKEN_DECIMALS, + poolAccount, + ); + + /// Mint already registered + await expect( + createTokenPool(rpc, payer, token22Mint), + ).rejects.toThrow(); + }); it('should create mint with payer as authority', async () => { /// Create new external SPL mint with payer === authority diff --git a/js/compressed-token/tests/e2e/custom-program-id.test.ts b/js/compressed-token/tests/e2e/custom-program-id.test.ts deleted file mode 100644 index 56a1681a9a..0000000000 --- a/js/compressed-token/tests/e2e/custom-program-id.test.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { describe, it, expect } from 'vitest'; -import { CompressedTokenProgram } from '../../src/program'; -import { PublicKey } from '@solana/web3.js'; - -describe('custom programId', () => { - it('should switch programId', async () => { - const defaultProgramId = new PublicKey( - 'cTokenmWW8bLPjZEBAUgYy3zKxQZW6VKi7bqNFEVv3m', - ); - const solMint = new PublicKey( - 'So11111111111111111111111111111111111111112', - ); - const expectedPoolPda = new PublicKey( - '3EJpXEsHL6JxNoPJWjF4QTKuvFvxzsUPbf1xF8iMbnL7', - ); - const newProgramId = new PublicKey( - '2WpGefPmpKMbkyLewupcfb8DuJ1ZMSPkMSu5WEvDMpF4', - ); - - // Check default program ID - expect(CompressedTokenProgram.programId).toEqual(defaultProgramId); - expect(CompressedTokenProgram.deriveTokenPoolPda(solMint)).toEqual( - expectedPoolPda, - ); - expect(CompressedTokenProgram.program.programId).toEqual( - defaultProgramId, - ); - - // Set new program ID - CompressedTokenProgram.setProgramId(newProgramId); - - // Verify program ID was updated - expect(CompressedTokenProgram.programId).toEqual(newProgramId); - expect(CompressedTokenProgram.deriveTokenPoolPda(solMint)).not.toEqual( - expectedPoolPda, - ); - expect(CompressedTokenProgram.program.programId).toEqual(newProgramId); - - // Reset program ID - CompressedTokenProgram.setProgramId(defaultProgramId); - }); -}); diff --git a/js/compressed-token/tests/e2e/decompress.test.ts b/js/compressed-token/tests/e2e/decompress.test.ts index 7d0846dd95..791dc23874 100644 --- a/js/compressed-token/tests/e2e/decompress.test.ts +++ b/js/compressed-token/tests/e2e/decompress.test.ts @@ -1,6 +1,6 @@ import { describe, it, expect, beforeAll } from 'vitest'; import { PublicKey, Keypair, Signer } from '@solana/web3.js'; -import { BN } from '@coral-xyz/anchor'; +import BN from 'bn.js'; import { ParsedTokenAccount, Rpc, diff --git a/js/compressed-token/tests/e2e/layout.test.ts b/js/compressed-token/tests/e2e/layout.test.ts new file mode 100644 index 0000000000..f198509db2 --- /dev/null +++ b/js/compressed-token/tests/e2e/layout.test.ts @@ -0,0 +1,741 @@ +import { describe, it, expect } from 'vitest'; +import { PublicKey } from '@solana/web3.js'; +import { + Program, + AnchorProvider, + setProvider, + Wallet, +} from '@coral-xyz/anchor'; +import BN from 'bn.js'; +import { + encodeMintToInstructionData, + decodeMintToInstructionData, + encodeCompressSplTokenAccountInstructionData, + decodeCompressSplTokenAccountInstructionData, + encodeTransferInstructionData, + decodeTransferInstructionData, + IDL, + LightCompressedToken, + mintToAccountsLayout, + createTokenPoolAccountsLayout, + transferAccountsLayout, + CompressedTokenProgram, +} from '../../src/'; +import { Keypair } from '@solana/web3.js'; +import { Connection } from '@solana/web3.js'; +import { TOKEN_2022_PROGRAM_ID } from '@solana/spl-token'; +import { SystemProgram } from '@solana/web3.js'; +import { + defaultStaticAccountsStruct, + LightSystemProgram, +} from '@lightprotocol/stateless.js'; + +const getTestProgram = (): Program => { + const mockKeypair = Keypair.generate(); + const mockConnection = new Connection('http://127.0.0.1:8899', 'confirmed'); + const mockProvider = new AnchorProvider( + mockConnection, + new Wallet(mockKeypair), + { + commitment: 'confirmed', + }, + ); + setProvider(mockProvider); + return new Program( + IDL, + new PublicKey('cTokenmWW8bLPjZEBAUgYy3zKxQZW6VKi7bqNFEVv3m'), + mockProvider, + ); +}; + +function deepEqual(ref: any, val: any) { + if (typeof ref !== typeof val) { + console.log(`Type mismatch: ${typeof ref} !== ${typeof val}`); + return false; + } + + if (ref instanceof BN && val instanceof BN) { + return ref.eq(val); + } + + if (typeof ref === 'object' && ref !== null && val !== null) { + const refKeys = Object.keys(ref); + const valKeys = Object.keys(val); + + if (refKeys.length !== valKeys.length) { + console.log( + `Key length mismatch: ${refKeys.length} !== ${valKeys.length}`, + ); + return false; + } + + for (const key of refKeys) { + if (!valKeys.includes(key)) { + console.log(`Key ${key} not found in value`); + return false; + } + if (!deepEqual(ref[key], val[key])) { + console.log(`Value mismatch at key ${key}`); + return false; + } + } + return true; + } + + if (ref !== val) { + console.log(`Value mismatch: ${ref} !== ${val}`); + } + + return ref === val; +} + +const IX_DISCRIMINATOR = 8; +const LENGTH_DISCRIMINATOR = 4; + +describe('layout', () => { + const mint = Keypair.generate().publicKey; + const feePayer = Keypair.generate().publicKey; + const authority = Keypair.generate().publicKey; + const cpiAuthorityPda = CompressedTokenProgram.deriveCpiAuthorityPda; + const tokenPoolPda = CompressedTokenProgram.deriveTokenPoolPda(mint); + const tokenProgram = TOKEN_2022_PROGRAM_ID; + const lightSystemProgram = LightSystemProgram.programId; + const registeredProgramPda = + defaultStaticAccountsStruct().registeredProgramPda; + const noopProgram = defaultStaticAccountsStruct().noopProgram; + const accountCompressionAuthority = + defaultStaticAccountsStruct().accountCompressionAuthority; + const accountCompressionProgram = + defaultStaticAccountsStruct().accountCompressionProgram; + const merkleTree = PublicKey.default; + const selfProgram = CompressedTokenProgram.programId; + const systemProgram = SystemProgram.programId; + const solPoolPda = LightSystemProgram.deriveCompressedSolPda(); + describe('encode/decode transfer/compress/decompress', () => { + const testCases = [ + { + description: 'default case', + data: { + proof: { + a: [ + 32, 3, 117, 58, 153, 131, 148, 196, 202, 221, 250, + 146, 196, 209, 8, 192, 211, 235, 57, 47, 234, 98, + 152, 195, 227, 9, 16, 156, 194, 41, 247, 89, + ], + b: [ + 22, 192, 18, 134, 24, 94, 169, 42, 151, 182, 237, + 164, 250, 163, 253, 24, 51, 142, 37, 55, 141, 92, + 198, 146, 177, 23, 113, 12, 122, 27, 143, 64, 26, + 191, 99, 235, 113, 154, 23, 234, 173, 101, 16, 34, + 192, 108, 61, 10, 206, 251, 84, 242, 238, 92, 131, + 107, 252, 227, 70, 181, 35, 236, 195, 209, + ], + c: [ + 166, 160, 56, 185, 41, 239, 140, 4, 255, 144, 213, + 185, 153, 246, 199, 206, 47, 210, 17, 10, 66, 68, + 132, 229, 12, 67, 166, 168, 229, 156, 90, 30, + ], + }, + mint: new PublicKey( + 'Bwuvv7NXd59zXRvWRCXcPLvwZ2dfedyQ9XZyqDghRFxv', + ), + delegatedTransfer: null, + inputTokenDataWithContext: [ + { + amount: new BN('03e8', 16), + delegateIndex: null, + merkleContext: { + merkleTreePubkeyIndex: 0, + nullifierQueuePubkeyIndex: 1, + leafIndex: 10, + queueIndex: null, + }, + rootIndex: 11, + lamports: null, + tlv: null, + }, + ], + outputCompressedAccounts: [ + { + owner: new PublicKey( + 'ARaDUvjovQDvFTMqaNAu9f2j1MpqJ5rhDAnDFrnyKbwg', + ), + amount: new BN('012c', 16), + lamports: null, + merkleTreeIndex: 0, + tlv: null, + }, + { + owner: new PublicKey( + 'GWYLPLzCCAVxq12UvBSpU4F8pcsmmRYQobPxkGz67ZVx', + ), + amount: new BN('02bc', 16), + lamports: null, + merkleTreeIndex: 0, + tlv: null, + }, + ], + compressOrDecompressAmount: null, + isCompress: false, + cpiContext: null, + lamportsChangeAccountMerkleTreeIndex: null, + }, + }, + { + description: 'with compressOrDecompressAmount', + data: { + proof: null, + mint: new PublicKey( + 'Bwuvv7NXd59zXRvWRCXcPLvwZ2dfedyQ9XZyqDghRFxv', + ), + delegatedTransfer: null, + inputTokenDataWithContext: [], + outputCompressedAccounts: [], + compressOrDecompressAmount: new BN(500), + isCompress: true, + cpiContext: null, + lamportsChangeAccountMerkleTreeIndex: null, + }, + }, + { + description: 'with delegatedTransfer', + data: { + proof: null, + mint: new PublicKey( + 'Bwuvv7NXd59zXRvWRCXcPLvwZ2dfedyQ9XZyqDghRFxv', + ), + delegatedTransfer: { + owner: new PublicKey( + 'ARaDUvjovQDvFTMqaNAu9f2j1MpqJ5rhDAnDFrnyKbwg', + ), + delegateChangeAccountIndex: 1, + }, + inputTokenDataWithContext: [], + outputCompressedAccounts: [], + compressOrDecompressAmount: null, + isCompress: false, + cpiContext: null, + lamportsChangeAccountMerkleTreeIndex: null, + }, + }, + { + description: 'with proof none', + data: { + proof: null, + mint: new PublicKey( + 'Bwuvv7NXd59zXRvWRCXcPLvwZ2dfedyQ9XZyqDghRFxv', + ), + delegatedTransfer: null, + inputTokenDataWithContext: [], + outputCompressedAccounts: [], + compressOrDecompressAmount: null, + isCompress: false, + cpiContext: null, + lamportsChangeAccountMerkleTreeIndex: null, + }, + }, + { + description: 'with various inputTokenDataWithContext', + data: { + proof: null, + mint: new PublicKey( + 'Bwuvv7NXd59zXRvWRCXcPLvwZ2dfedyQ9XZyqDghRFxv', + ), + delegatedTransfer: null, + inputTokenDataWithContext: [ + { + amount: new BN(1000), + delegateIndex: 2, + merkleContext: { + merkleTreePubkeyIndex: 1, + nullifierQueuePubkeyIndex: 2, + leafIndex: 3, + queueIndex: { queueId: 0, index: 4 }, + }, + rootIndex: 5, + lamports: new BN(2000), + tlv: Buffer.from([1, 2, 3]), + }, + ], + outputCompressedAccounts: [], + compressOrDecompressAmount: null, + isCompress: false, + cpiContext: null, + lamportsChangeAccountMerkleTreeIndex: null, + }, + }, + { + description: 'with various outputCompressedAccounts', + data: { + proof: null, + mint: new PublicKey( + 'Bwuvv7NXd59zXRvWRCXcPLvwZ2dfedyQ9XZyqDghRFxv', + ), + delegatedTransfer: null, + inputTokenDataWithContext: [], + outputCompressedAccounts: [ + { + owner: new PublicKey( + 'ARaDUvjovQDvFTMqaNAu9f2j1MpqJ5rhDAnDFrnyKbwg', + ), + amount: new BN(3000), + lamports: new BN(4000), + merkleTreeIndex: 1, + tlv: Buffer.from([4, 5, 6]), + }, + ], + compressOrDecompressAmount: null, + isCompress: false, + cpiContext: null, + lamportsChangeAccountMerkleTreeIndex: null, + }, + }, + { + description: 'with isCompress true', + data: { + proof: null, + mint: new PublicKey( + 'Bwuvv7NXd59zXRvWRCXcPLvwZ2dfedyQ9XZyqDghRFxv', + ), + delegatedTransfer: null, + inputTokenDataWithContext: [], + outputCompressedAccounts: [], + compressOrDecompressAmount: null, + isCompress: true, + cpiContext: null, + lamportsChangeAccountMerkleTreeIndex: null, + }, + }, + { + description: 'with lamportsChangeAccountMerkleTreeIndex', + data: { + proof: null, + mint: new PublicKey( + 'Bwuvv7NXd59zXRvWRCXcPLvwZ2dfedyQ9XZyqDghRFxv', + ), + delegatedTransfer: null, + inputTokenDataWithContext: [], + outputCompressedAccounts: [], + compressOrDecompressAmount: null, + isCompress: false, + cpiContext: null, + lamportsChangeAccountMerkleTreeIndex: 5, + }, + }, + { + description: 'with cpiContext', + data: { + proof: null, + mint: new PublicKey( + 'Bwuvv7NXd59zXRvWRCXcPLvwZ2dfedyQ9XZyqDghRFxv', + ), + delegatedTransfer: null, + inputTokenDataWithContext: [], + outputCompressedAccounts: [], + compressOrDecompressAmount: null, + isCompress: false, + cpiContext: { + setContext: true, + firstSetContext: false, + cpiContextAccountIndex: 2, + }, + lamportsChangeAccountMerkleTreeIndex: null, + }, + }, + ]; + + testCases.forEach(({ description, data }) => { + it(`should encode/decode transfer: ${description}`, () => { + const anchorEncodedData = getTestProgram().coder.types.encode( + 'CompressedTokenInstructionDataTransfer', + data, + ); + const encoded = encodeTransferInstructionData(data); + const decoded = decodeTransferInstructionData(encoded); + expect(deepEqual(decoded, data)).toBe(true); + expect(anchorEncodedData).toEqual( + encoded.slice(IX_DISCRIMINATOR + LENGTH_DISCRIMINATOR), + ); + }); + }); + }); + + describe('encode/decode MintToInstructionData', () => { + const testCases = [ + { + description: 'default case', + data: { + recipients: [ + new PublicKey( + '6ASf5EcmmEHTgDJ4X4ZT5vT6iHVJBXPg5AN5YoTCpGWt', + ), + ], + amounts: [new BN(1000)], + lamports: null, + }, + }, + { + description: 'with multiple recipients', + data: { + recipients: [ + new PublicKey( + '6ASf5EcmmEHTgDJ4X4ZT5vT6iHVJBXPg5AN5YoTCpGWt', + ), + new PublicKey( + '8ASf5EcmmEHTgDJ4X4ZT5vT6iHVJBXPg5AN5YoTCpGWs', + ), + ], + amounts: [new BN(1000), new BN(2000)], + lamports: null, + }, + }, + { + description: 'with lamports', + data: { + recipients: [ + new PublicKey( + '6ASf5EcmmEHTgDJ4X4ZT5vT6iHVJBXPg5AN5YoTCpGWt', + ), + ], + amounts: [new BN(1000)], + lamports: new BN(500), + }, + }, + ]; + + testCases.forEach(async ({ description, data }) => { + it(description, async () => { + const encoded = encodeMintToInstructionData(data); + const decoded = decodeMintToInstructionData(encoded); + expect(deepEqual(decoded, data)).toBe(true); + + const instruction = await getTestProgram() + .methods.mintTo( + data.recipients, + data.amounts, + data.lamports, + ) + .accounts({ + feePayer: PublicKey.default, + authority: PublicKey.default, + cpiAuthorityPda: PublicKey.default, + mint: PublicKey.default, + tokenPoolPda: PublicKey.default, + tokenProgram: PublicKey.default, + lightSystemProgram: PublicKey.default, + registeredProgramPda: PublicKey.default, + noopProgram: PublicKey.default, + accountCompressionAuthority: PublicKey.default, + accountCompressionProgram: PublicKey.default, + merkleTree: PublicKey.default, + selfProgram: PublicKey.default, + solPoolPda: null, + }) + .instruction(); + expect(instruction.data).toEqual(encoded); + }); + }); + }); + + describe('encode/decode CompressSplTokenAccountInstructionData', () => { + const testCases = [ + { + description: 'default case', + data: { + owner: new PublicKey( + 'CPMzHV9PsUeb5pFmyrj9nEoDwtL8CcyUKQzJXJxYRnT7', + ), + remainingAmount: new BN(110), + cpiContext: null, + }, + }, + { + description: 'with cpiContext', + data: { + owner: new PublicKey( + 'CPMzHV9PsUeb5pFmyrj9nEoDwtL8CcyUKQzJXJxYRnT7', + ), + remainingAmount: new BN(110), + cpiContext: { + setContext: true, + firstSetContext: true, + cpiContextAccountIndex: 0, + }, + }, + }, + { + description: 'without remainingAmount', + data: { + owner: new PublicKey( + 'CPMzHV9PsUeb5pFmyrj9nEoDwtL8CcyUKQzJXJxYRnT7', + ), + remainingAmount: null, + cpiContext: null, + }, + }, + ]; + + testCases.forEach(async ({ description, data }) => { + it(description, async () => { + const encoded = + encodeCompressSplTokenAccountInstructionData(data); + const decoded = + decodeCompressSplTokenAccountInstructionData(encoded); + expect(deepEqual(decoded, data)).toBe(true); + + const instruction = await getTestProgram() + .methods.compressSplTokenAccount( + data.owner, + data.remainingAmount, + data.cpiContext, + ) + .accounts({ + feePayer: PublicKey.default, + authority: PublicKey.default, + cpiAuthorityPda: PublicKey.default, + lightSystemProgram: PublicKey.default, + registeredProgramPda: PublicKey.default, + noopProgram: PublicKey.default, + accountCompressionAuthority: PublicKey.default, + accountCompressionProgram: PublicKey.default, + selfProgram: PublicKey.default, + tokenPoolPda: PublicKey.default, + compressOrDecompressTokenAccount: PublicKey.default, + tokenProgram: PublicKey.default, + systemProgram: PublicKey.default, + }) + .instruction(); + + expect(instruction.data).toEqual(encoded); + }); + }); + }); + describe('Accounts Layout Helper Functions', () => { + it('createTokenPoolAccountsLayout should return correct AccountMeta array', () => { + const accounts = { + feePayer, + tokenPoolPda, + systemProgram, + mint, + tokenProgram, + cpiAuthorityPda, + }; + + const expected = [ + { pubkey: feePayer, isSigner: true, isWritable: true }, + { + pubkey: tokenPoolPda, + isSigner: false, + isWritable: true, + }, + { + pubkey: systemProgram, + isSigner: false, + isWritable: false, + }, + { + pubkey: mint, + isSigner: false, + isWritable: true, + }, + { + pubkey: tokenProgram, + isSigner: false, + isWritable: false, + }, + { + pubkey: cpiAuthorityPda, + isSigner: false, + isWritable: false, + }, + ]; + + const result = createTokenPoolAccountsLayout(accounts); + expect(result).toEqual(expected); + }); + + it('mintToAccountsLayout should return correct AccountMeta array', () => { + const accounts = { + feePayer, + authority, + cpiAuthorityPda, + mint, + tokenPoolPda, + tokenProgram, + lightSystemProgram, + registeredProgramPda, + noopProgram, + accountCompressionAuthority, + accountCompressionProgram, + merkleTree, + selfProgram, + systemProgram, + solPoolPda, + }; + + const expected = [ + { pubkey: feePayer, isSigner: true, isWritable: true }, + { + pubkey: authority, + isSigner: true, + isWritable: false, + }, + { + pubkey: cpiAuthorityPda, + isSigner: false, + isWritable: false, + }, + { + pubkey: mint, + isSigner: false, + isWritable: true, + }, + { + pubkey: tokenPoolPda, + isSigner: false, + isWritable: true, + }, + { + pubkey: tokenProgram, + isSigner: false, + isWritable: false, + }, + { + pubkey: lightSystemProgram, + isSigner: false, + isWritable: false, + }, + { + pubkey: registeredProgramPda, + isSigner: false, + isWritable: false, + }, + { + pubkey: noopProgram, + isSigner: false, + isWritable: false, + }, + { + pubkey: accountCompressionAuthority, + isSigner: false, + isWritable: false, + }, + { + pubkey: accountCompressionProgram, + isSigner: false, + isWritable: false, + }, + { + pubkey: merkleTree, + isSigner: false, + isWritable: true, + }, + { + pubkey: selfProgram, + isSigner: false, + isWritable: false, + }, + { + pubkey: systemProgram, + isSigner: false, + isWritable: false, + }, + { + pubkey: solPoolPda, + isSigner: false, + isWritable: true, + }, + ]; + + const result = mintToAccountsLayout(accounts); + expect(result).toEqual(expected); + }); + + it('transferAccountsLayout should return correct AccountMeta array', () => { + const compressOrDecompressTokenAccount = + Keypair.generate().publicKey; + const accounts = { + feePayer, + authority, + cpiAuthorityPda, + lightSystemProgram, + registeredProgramPda, + noopProgram, + accountCompressionAuthority, + accountCompressionProgram, + selfProgram, + tokenPoolPda, + compressOrDecompressTokenAccount, + tokenProgram, + systemProgram, + }; + + const expected = [ + { pubkey: feePayer, isSigner: true, isWritable: true }, + { + pubkey: authority, + isSigner: true, + isWritable: false, + }, + { + pubkey: cpiAuthorityPda, + isSigner: false, + isWritable: false, + }, + { + pubkey: lightSystemProgram, + isSigner: false, + isWritable: false, + }, + { + pubkey: registeredProgramPda, + isSigner: false, + isWritable: false, + }, + { + pubkey: noopProgram, + isSigner: false, + isWritable: false, + }, + { + pubkey: accountCompressionAuthority, + isSigner: false, + isWritable: false, + }, + { + pubkey: accountCompressionProgram, + isSigner: false, + isWritable: false, + }, + { + pubkey: selfProgram, + isSigner: false, + isWritable: false, + }, + { + pubkey: tokenPoolPda, + isSigner: false, + isWritable: true, + }, + { + pubkey: compressOrDecompressTokenAccount, + isSigner: false, + isWritable: true, + }, + { + pubkey: tokenProgram, + isSigner: false, + isWritable: false, + }, + { + pubkey: systemProgram, + isSigner: false, + isWritable: false, + }, + ]; + + const result = transferAccountsLayout(accounts); + expect(result).toEqual(expected); + }); + }); +}); diff --git a/js/compressed-token/tests/e2e/mint-to.test.ts b/js/compressed-token/tests/e2e/mint-to.test.ts index 010db22709..28299e5aa4 100644 --- a/js/compressed-token/tests/e2e/mint-to.test.ts +++ b/js/compressed-token/tests/e2e/mint-to.test.ts @@ -5,7 +5,7 @@ import { Keypair, ComputeBudgetProgram, } from '@solana/web3.js'; -import { BN } from '@coral-xyz/anchor'; +import BN from 'bn.js'; import { createMint, createTokenProgramLookupTable, diff --git a/js/compressed-token/tests/e2e/rpc-token-interop.test.ts b/js/compressed-token/tests/e2e/rpc-token-interop.test.ts index e98953d044..37d98f0d76 100644 --- a/js/compressed-token/tests/e2e/rpc-token-interop.test.ts +++ b/js/compressed-token/tests/e2e/rpc-token-interop.test.ts @@ -6,7 +6,6 @@ import { bn, createRpc, getTestRpc, - TestRpc, } from '@lightprotocol/stateless.js'; import { WasmFactory } from '@lightprotocol/hasher.rs'; import { createMint, mintTo, transfer } from '../../src/actions'; @@ -15,7 +14,7 @@ const TEST_TOKEN_DECIMALS = 2; describe('rpc-interop token', () => { let rpc: Rpc; - let testRpc: TestRpc; + let testRpc: Rpc; let payer: Signer; let bob: Signer; let charlie: Signer; diff --git a/js/compressed-token/tests/e2e/transfer.test.ts b/js/compressed-token/tests/e2e/transfer.test.ts index a177f4aff4..c014bd0429 100644 --- a/js/compressed-token/tests/e2e/transfer.test.ts +++ b/js/compressed-token/tests/e2e/transfer.test.ts @@ -1,6 +1,6 @@ import { describe, it, expect, beforeAll, beforeEach, assert } from 'vitest'; import { PublicKey, Keypair, Signer } from '@solana/web3.js'; -import { BN } from '@coral-xyz/anchor'; +import BN from 'bn.js'; import { ParsedTokenAccount, Rpc, diff --git a/js/compressed-token/tsconfig.json b/js/compressed-token/tsconfig.json index 0995cc57fb..f3440f50d0 100644 --- a/js/compressed-token/tsconfig.json +++ b/js/compressed-token/tsconfig.json @@ -12,7 +12,8 @@ "moduleResolution": "Node", "lib": ["ESNext", "DOM"], "types": ["node"], - "skipLibCheck": false + "skipLibCheck": false, + "typeRoots": ["types/", "./node_modules/@types"] }, "include": ["./src/**/*.ts", "rollup.config.js"] } diff --git a/js/compressed-token/types/buffer-layout/index.d.ts b/js/compressed-token/types/buffer-layout/index.d.ts new file mode 100644 index 0000000000..f047cbb1fd --- /dev/null +++ b/js/compressed-token/types/buffer-layout/index.d.ts @@ -0,0 +1,88 @@ +// From https://github.com/coral-xyz/anchor/blob/master/ts/packages/anchor/types/buffer-layout/index.d.ts +declare module 'buffer-layout' { + // TODO: remove `any`. + export class Layout { + span: number; + property?: string; + + constructor(span: number, property?: string); + + decode(b: Buffer | string, offset?: number): T; + encode(src: T, b: Buffer, offset?: number): number; + getSpan(b: Buffer, offset?: number): number; + replicate(name: string): this; + } + // TODO: remove any. + export class Structure extends Layout { + span: any; + } + export function greedy( + elementSpan?: number, + property?: string, + ): Layout; + export function offset( + layout: Layout, + offset?: number, + property?: string, + ): Layout; + export function u8(property?: string): Layout; + export function u16(property?: string): Layout; + export function u24(property?: string): Layout; + export function u32(property?: string): Layout; + export function u40(property?: string): Layout; + export function u48(property?: string): Layout; + export function nu64(property?: string): Layout; + export function u16be(property?: string): Layout; + export function u24be(property?: string): Layout; + export function u32be(property?: string): Layout; + export function u40be(property?: string): Layout; + export function u48be(property?: string): Layout; + export function nu64be(property?: string): Layout; + export function s8(property?: string): Layout; + export function s16(property?: string): Layout; + export function s24(property?: string): Layout; + export function s32(property?: string): Layout; + export function s40(property?: string): Layout; + export function s48(property?: string): Layout; + export function ns64(property?: string): Layout; + export function s16be(property?: string): Layout; + export function s24be(property?: string): Layout; + export function s32be(property?: string): Layout; + export function s40be(property?: string): Layout; + export function s48be(property?: string): Layout; + export function ns64be(property?: string): Layout; + export function f32(property?: string): Layout; + export function f32be(property?: string): Layout; + export function f64(property?: string): Layout; + export function f64be(property?: string): Layout; + export function struct( + fields: Layout[], + property?: string, + decodePrefixes?: boolean, + ): Layout; + export function bits( + word: Layout, + msb?: boolean, + property?: string, + ): any; + export function seq( + elementLayout: Layout, + count: number | Layout, + property?: string, + ): Layout; + export function union( + discr: Layout, + defaultLayout?: any, + property?: string, + ): any; + export function unionLayoutDiscriminator( + layout: Layout, + property?: string, + ): any; + export function blob( + length: number | Layout, + property?: string, + ): Layout; + export function cstr(property?: string): Layout; + export function utf8(maxSpan: number, property?: string): Layout; +} diff --git a/js/stateless.js/README.md b/js/stateless.js/README.md index a0a65b7bf3..bf72b20d1c 100644 --- a/js/stateless.js/README.md +++ b/js/stateless.js/README.md @@ -45,6 +45,14 @@ Feel free to ask in the [Light](https://discord.gg/CYvjBgzRFP) and [Helius](http - A code example that we can use to test and debug (if possible). Use [CodeSandbox](https://codesandbox.io/p/sandbox/vanilla-ts) or any other live environment provider. - A description or context of any errors you are encountering with stacktraces if available. +### Source Maps + +We provide `index.js.map` for debugging. Exclude in production: + +**Webpack:** Set `devtool` to `false`. +**Rollup:** Set `sourcemap` to `false`. +**TypeScript:** Set `sourceMap` to `false`. + ## Contributing Light and ZK Compression are open source protocols and very much welcome contributions. If you have a contribution, do not hesitate to send a PR to the respective repository or discuss in the linked developer Discord servers. diff --git a/js/stateless.js/package.json b/js/stateless.js/package.json index e56ea3d363..59898a3d0b 100644 --- a/js/stateless.js/package.json +++ b/js/stateless.js/package.json @@ -1,7 +1,7 @@ { "name": "@lightprotocol/stateless.js", - "version": "0.17.1", - "description": "JavaScript API for Light and ZK Compression", + "version": "0.18.0", + "description": "JavaScript API for Light & ZK Compression", "sideEffects": false, "main": "dist/cjs/node/index.cjs", "type": "module", @@ -34,17 +34,23 @@ } ], "license": "Apache-2.0", + "peerDependencies": { + "@solana/web3.js": ">=1.73.5" + }, "dependencies": { - "@coral-xyz/anchor": "0.29.0", - "@solana/web3.js": "1.95.3", + "@coral-xyz/borsh": "^0.29.0", "@noble/hashes": "1.5.0", + "bn.js": "^5.2.1", + "bs58": "^6.0.0", "buffer": "6.0.3", - "superstruct": "2.0.2", - "tweetnacl": "1.0.3" + "buffer-layout": "^1.2.2", + "camelcase": "^8.0.0", + "superstruct": "2.0.2" }, "devDependencies": { - "@lightprotocol/hasher.rs": "0.2.1", + "@coral-xyz/anchor": "0.29.0", "@esbuild-plugins/node-globals-polyfill": "^0.2.3", + "@lightprotocol/hasher.rs": "0.2.1", "@lightprotocol/programs": "workspace:*", "@playwright/test": "^1.47.1", "@rollup/plugin-babel": "^6.0.4", @@ -54,6 +60,7 @@ "@rollup/plugin-replace": "^5.0.7", "@rollup/plugin-terser": "^0.4.4", "@rollup/plugin-typescript": "^11.1.6", + "@solana/web3.js": "1.98.0", "@types/bn.js": "^5.1.5", "@types/node": "^22.5.5", "@typescript-eslint/eslint-plugin": "^7.13.1", @@ -71,26 +78,27 @@ "rollup-plugin-polyfill-node": "^0.13.0", "ts-node": "^10.9.2", "tslib": "^2.7.0", + "tweetnacl": "1.0.3", "typescript": "^5.6.2", "vitest": "^2.1.1" }, "scripts": { "test": "pnpm test:unit:all && pnpm test:e2e:all", "test-all": "vitest run", - "test:unit:all": "vitest run tests/unit", + "test:unit:all": "vitest run tests/unit --reporter=verbose", "test-validator": "./../../cli/test_bin/run test-validator --prover-run-mode rpc", "test:e2e:transfer": "pnpm test-validator && vitest run tests/e2e/transfer.test.ts --reporter=verbose", "test:e2e:compress": "pnpm test-validator && vitest run tests/e2e/compress.test.ts --reporter=verbose", "test:e2e:test-rpc": "pnpm test-validator && vitest run tests/e2e/test-rpc.test.ts", "test:e2e:rpc-interop": "pnpm test-validator && vitest run tests/e2e/rpc-interop.test.ts", "test:e2e:browser": "pnpm playwright test", - "test:e2e:all": "pnpm test-validator && vitest run tests/e2e/test-rpc.test.ts && vitest run tests/e2e/compress.test.ts && vitest run tests/e2e/transfer.test.ts && vitest run tests/e2e/rpc-interop.test.ts", + "test:e2e:all": "pnpm test-validator && vitest run tests/e2e/test-rpc.test.ts && vitest run tests/e2e/compress.test.ts && vitest run tests/e2e/transfer.test.ts && vitest run tests/e2e/rpc-interop.test.ts && vitest run tests/e2e/layout.test.ts", "test:index": "vitest run tests/e2e/program.test.ts", - "test:e2e:serde": "vitest run tests/e2e/serde.test.ts", + "test:e2e:layout": "vitest run tests/e2e/layout.test.ts --reporter=verbose", "test:verbose": "vitest run --reporter=verbose", "test:testnet": "vitest run tests/e2e/testnet.test.ts --reporter=verbose", "pull-idls": "../../scripts/push-stateless-js-idls.sh && ../../scripts/push-compressed-token-idl.sh", - "build": "rimraf dist && pnpm pull-idls && pnpm build:bundle", + "build": "rimraf dist && pnpm build:bundle", "build:bundle": "rollup -c", "format": "prettier --write .", "lint": "eslint ." diff --git a/js/stateless.js/rollup.config.js b/js/stateless.js/rollup.config.js index 94f7a61391..72140f365f 100644 --- a/js/stateless.js/rollup.config.js +++ b/js/stateless.js/rollup.config.js @@ -3,7 +3,9 @@ import nodePolyfills from 'rollup-plugin-polyfill-node'; import dts from 'rollup-plugin-dts'; import resolve from '@rollup/plugin-node-resolve'; import commonjs from '@rollup/plugin-commonjs'; +import terser from '@rollup/plugin-terser'; +import json from '@rollup/plugin-json'; const rolls = (fmt, env) => ({ input: 'src/index.ts', output: { @@ -12,14 +14,7 @@ const rolls = (fmt, env) => ({ entryFileNames: `[name].${fmt === 'cjs' ? 'cjs' : 'js'}`, sourcemap: true, }, - external: [ - '@coral-xyz/anchor', - '@solana/web3.js', - '@noble/hashes', - 'buffer', - 'superstruct', - 'tweetnacl', - ], + external: ['@solana/web3.js'], plugins: [ typescript({ target: fmt === 'es' ? 'ES2022' : 'ES2017', @@ -32,6 +27,27 @@ const rolls = (fmt, env) => ({ preferBuiltins: env === 'node', }), env === 'browser' ? nodePolyfills() : undefined, + json(), + terser({ + compress: { + drop_console: true, + drop_debugger: true, + passes: 3, + pure_funcs: ['console.log', 'console.error', 'console.warn'], + booleans_as_integers: true, + keep_fargs: false, + keep_fnames: false, + keep_infinity: true, + reduce_funcs: true, + reduce_vars: true, + }, + mangle: { + toplevel: true, + }, + output: { + comments: false, + }, + }), ].filter(Boolean), onwarn(warning, warn) { if (warning.code !== 'CIRCULAR_DEPENDENCY') { @@ -48,7 +64,6 @@ const typesConfig = { export default [ rolls('cjs', 'browser'), - rolls('es', 'browser'), rolls('cjs', 'node'), typesConfig, ]; diff --git a/js/stateless.js/src/actions/compress.ts b/js/stateless.js/src/actions/compress.ts index 40f0a4fa83..982d1131b2 100644 --- a/js/stateless.js/src/actions/compress.ts +++ b/js/stateless.js/src/actions/compress.ts @@ -9,7 +9,7 @@ import { import { LightSystemProgram } from '../programs'; import { Rpc } from '../rpc'; import { buildAndSignTx, sendAndConfirmTx } from '../utils'; -import { BN } from '@coral-xyz/anchor'; +import BN from 'bn.js'; import { defaultTestStateTreeAccounts } from '../constants'; /** diff --git a/js/stateless.js/src/actions/create-account.ts b/js/stateless.js/src/actions/create-account.ts index 5e423c22ee..a1b94e7ebf 100644 --- a/js/stateless.js/src/actions/create-account.ts +++ b/js/stateless.js/src/actions/create-account.ts @@ -19,7 +19,7 @@ import { } from '../utils'; import { defaultTestStateTreeAccounts } from '../constants'; import { bn } from '../state'; -import { BN } from '@coral-xyz/anchor'; +import BN from 'bn.js'; /** * Create compressed account with address diff --git a/js/stateless.js/src/actions/decompress.ts b/js/stateless.js/src/actions/decompress.ts index 5de8036abf..ca848c4ce0 100644 --- a/js/stateless.js/src/actions/decompress.ts +++ b/js/stateless.js/src/actions/decompress.ts @@ -8,7 +8,7 @@ import { import { LightSystemProgram, sumUpLamports } from '../programs'; import { Rpc } from '../rpc'; import { buildAndSignTx, sendAndConfirmTx } from '../utils'; -import { BN } from '@coral-xyz/anchor'; +import BN from 'bn.js'; import { CompressedAccountWithMerkleContext, bn } from '../state'; /** diff --git a/js/stateless.js/src/actions/transfer.ts b/js/stateless.js/src/actions/transfer.ts index 551f9b6540..d43eded3c6 100644 --- a/js/stateless.js/src/actions/transfer.ts +++ b/js/stateless.js/src/actions/transfer.ts @@ -6,7 +6,7 @@ import { TransactionSignature, } from '@solana/web3.js'; -import { BN } from '@coral-xyz/anchor'; +import BN from 'bn.js'; import { LightSystemProgram, selectMinCompressedSolAccountsForTransfer, diff --git a/js/stateless.js/src/constants.ts b/js/stateless.js/src/constants.ts index ca4eabe452..83185b6007 100644 --- a/js/stateless.js/src/constants.ts +++ b/js/stateless.js/src/constants.ts @@ -1,4 +1,4 @@ -import { BN } from '@coral-xyz/anchor'; +import BN from 'bn.js'; import { Buffer } from 'buffer'; import { ConfirmOptions, PublicKey } from '@solana/web3.js'; @@ -9,6 +9,10 @@ export const HIGHEST_ADDRESS_PLUS_ONE = new BN( '452312848583266388373324160190187140051835877600158453279131187530910662655', ); +export const INVOKE_DISCRIMINATOR = Buffer.from([ + 26, 16, 169, 7, 21, 202, 242, 25, +]); + // TODO: implement properly export const noopProgram = 'noopb9bkMVfRPU8AsbpTUg8AQkHtKwMYZiFUjNRtMmV'; export const lightProgram = 'SySTEM1eSU2p4BGQfQpimFEWWSC1XDFeun3Nqzz3rT7'; diff --git a/js/stateless.js/src/idls/light_system_program.ts b/js/stateless.js/src/idl.ts similarity index 100% rename from js/stateless.js/src/idls/light_system_program.ts rename to js/stateless.js/src/idl.ts diff --git a/js/stateless.js/src/idls/account_compression.ts b/js/stateless.js/src/idls/account_compression.ts deleted file mode 100644 index f90f8a4ad2..0000000000 --- a/js/stateless.js/src/idls/account_compression.ts +++ /dev/null @@ -1,2797 +0,0 @@ -export type AccountCompression = { - version: '1.2.0'; - name: 'account_compression'; - constants: [ - { - name: 'CPI_AUTHORITY_PDA_SEED'; - type: 'bytes'; - value: '[99, 112, 105, 95, 97, 117, 116, 104, 111, 114, 105, 116, 121]'; - }, - { - name: 'GROUP_AUTHORITY_SEED'; - type: 'bytes'; - value: '[103, 114, 111, 117, 112, 95, 97, 117, 116, 104, 111, 114, 105, 116, 121]'; - }, - { - name: 'STATE_MERKLE_TREE_HEIGHT'; - type: 'u64'; - value: '26'; - }, - { - name: 'STATE_MERKLE_TREE_CHANGELOG'; - type: 'u64'; - value: '1400'; - }, - { - name: 'STATE_MERKLE_TREE_ROOTS'; - type: 'u64'; - value: '2400'; - }, - { - name: 'STATE_MERKLE_TREE_CANOPY_DEPTH'; - type: 'u64'; - value: '10'; - }, - { - name: 'STATE_NULLIFIER_QUEUE_VALUES'; - type: 'u16'; - value: '28_807'; - }, - { - name: 'STATE_NULLIFIER_QUEUE_SEQUENCE_THRESHOLD'; - type: 'u64'; - value: '2400'; - }, - { - name: 'ADDRESS_MERKLE_TREE_HEIGHT'; - type: 'u64'; - value: '26'; - }, - { - name: 'ADDRESS_MERKLE_TREE_CHANGELOG'; - type: 'u64'; - value: '1400'; - }, - { - name: 'ADDRESS_MERKLE_TREE_ROOTS'; - type: 'u64'; - value: '2400'; - }, - { - name: 'ADDRESS_MERKLE_TREE_CANOPY_DEPTH'; - type: 'u64'; - value: '10'; - }, - { - name: 'ADDRESS_MERKLE_TREE_INDEXED_CHANGELOG'; - type: 'u64'; - value: '1400'; - }, - { - name: 'ADDRESS_QUEUE_VALUES'; - type: 'u16'; - value: '28_807'; - }, - { - name: 'ADDRESS_QUEUE_SEQUENCE_THRESHOLD'; - type: 'u64'; - value: '2400'; - }, - { - name: 'NOOP_PUBKEY'; - type: { - array: ['u8', 32]; - }; - value: '[11 , 188 , 15 , 192 , 187 , 71 , 202 , 47 , 116 , 196 , 17 , 46 , 148 , 171 , 19 , 207 , 163 , 198 , 52 , 229 , 220 , 23 , 234 , 203 , 3 , 205 , 26 , 35 , 205 , 126 , 120 , 124 ,]'; - }, - ]; - instructions: [ - { - name: 'initializeBatchedStateMerkleTree'; - accounts: [ - { - name: 'authority'; - isMut: true; - isSigner: true; - }, - { - name: 'merkleTree'; - isMut: true; - isSigner: false; - }, - { - name: 'queue'; - isMut: true; - isSigner: false; - }, - { - name: 'registeredProgramPda'; - isMut: false; - isSigner: false; - isOptional: true; - }, - ]; - args: [ - { - name: 'bytes'; - type: 'bytes'; - }, - ]; - }, - { - name: 'initializeAddressMerkleTreeAndQueue'; - accounts: [ - { - name: 'authority'; - isMut: true; - isSigner: true; - }, - { - name: 'merkleTree'; - isMut: true; - isSigner: false; - }, - { - name: 'queue'; - isMut: true; - isSigner: false; - }, - { - name: 'registeredProgramPda'; - isMut: false; - isSigner: false; - isOptional: true; - }, - ]; - args: [ - { - name: 'index'; - type: 'u64'; - }, - { - name: 'programOwner'; - type: { - option: 'publicKey'; - }; - }, - { - name: 'forester'; - type: { - option: 'publicKey'; - }; - }, - { - name: 'addressMerkleTreeConfig'; - type: { - defined: 'AddressMerkleTreeConfig'; - }; - }, - { - name: 'addressQueueConfig'; - type: { - defined: 'AddressQueueConfig'; - }; - }, - ]; - }, - { - name: 'insertAddresses'; - accounts: [ - { - name: 'feePayer'; - isMut: true; - isSigner: true; - docs: ['Fee payer pays rollover fee.']; - }, - { - name: 'authority'; - isMut: false; - isSigner: true; - }, - { - name: 'registeredProgramPda'; - isMut: false; - isSigner: false; - isOptional: true; - }, - { - name: 'systemProgram'; - isMut: false; - isSigner: false; - }, - ]; - args: [ - { - name: 'addresses'; - type: { - vec: { - array: ['u8', 32]; - }; - }; - }, - ]; - }, - { - name: 'updateAddressMerkleTree'; - docs: ['Updates the address Merkle tree with a new address.']; - accounts: [ - { - name: 'authority'; - isMut: false; - isSigner: true; - }, - { - name: 'registeredProgramPda'; - isMut: false; - isSigner: false; - isOptional: true; - }, - { - name: 'queue'; - isMut: true; - isSigner: false; - }, - { - name: 'merkleTree'; - isMut: true; - isSigner: false; - }, - { - name: 'logWrapper'; - isMut: false; - isSigner: false; - }, - ]; - args: [ - { - name: 'changelogIndex'; - type: 'u16'; - }, - { - name: 'indexedChangelogIndex'; - type: 'u16'; - }, - { - name: 'value'; - type: 'u16'; - }, - { - name: 'lowAddressIndex'; - type: 'u64'; - }, - { - name: 'lowAddressValue'; - type: { - array: ['u8', 32]; - }; - }, - { - name: 'lowAddressNextIndex'; - type: 'u64'; - }, - { - name: 'lowAddressNextValue'; - type: { - array: ['u8', 32]; - }; - }, - { - name: 'lowAddressProof'; - type: { - array: [ - { - array: ['u8', 32]; - }, - 16, - ]; - }; - }, - ]; - }, - { - name: 'rolloverAddressMerkleTreeAndQueue'; - accounts: [ - { - name: 'feePayer'; - isMut: true; - isSigner: true; - docs: [ - 'Signer used to receive rollover accounts rentexemption reimbursement.', - ]; - }, - { - name: 'authority'; - isMut: false; - isSigner: true; - }, - { - name: 'registeredProgramPda'; - isMut: false; - isSigner: false; - isOptional: true; - }, - { - name: 'newAddressMerkleTree'; - isMut: true; - isSigner: false; - }, - { - name: 'newQueue'; - isMut: true; - isSigner: false; - }, - { - name: 'oldAddressMerkleTree'; - isMut: true; - isSigner: false; - }, - { - name: 'oldQueue'; - isMut: true; - isSigner: false; - }, - ]; - args: []; - }, - { - name: 'initializeGroupAuthority'; - docs: [ - 'initialize group (a group can be used to give multiple programs access', - 'to the same Merkle trees by registering the programs to the group)', - ]; - accounts: [ - { - name: 'authority'; - isMut: true; - isSigner: true; - }, - { - name: 'seed'; - isMut: false; - isSigner: true; - docs: [ - 'Seed public key used to derive the group authority.', - ]; - }, - { - name: 'groupAuthority'; - isMut: true; - isSigner: false; - }, - { - name: 'systemProgram'; - isMut: false; - isSigner: false; - }, - ]; - args: [ - { - name: 'authority'; - type: 'publicKey'; - }, - ]; - }, - { - name: 'updateGroupAuthority'; - accounts: [ - { - name: 'authority'; - isMut: false; - isSigner: true; - }, - { - name: 'groupAuthority'; - isMut: true; - isSigner: false; - }, - ]; - args: [ - { - name: 'authority'; - type: 'publicKey'; - }, - ]; - }, - { - name: 'registerProgramToGroup'; - accounts: [ - { - name: 'authority'; - isMut: true; - isSigner: true; - }, - { - name: 'programToBeRegistered'; - isMut: false; - isSigner: true; - }, - { - name: 'registeredProgramPda'; - isMut: true; - isSigner: false; - }, - { - name: 'groupAuthorityPda'; - isMut: false; - isSigner: false; - }, - { - name: 'systemProgram'; - isMut: false; - isSigner: false; - }, - ]; - args: []; - }, - { - name: 'deregisterProgram'; - accounts: [ - { - name: 'authority'; - isMut: true; - isSigner: true; - }, - { - name: 'registeredProgramPda'; - isMut: true; - isSigner: false; - }, - { - name: 'groupAuthorityPda'; - isMut: false; - isSigner: false; - }, - { - name: 'closeRecipient'; - isMut: true; - isSigner: false; - }, - ]; - args: []; - }, - { - name: 'initializeStateMerkleTreeAndNullifierQueue'; - docs: [ - 'Initializes a new Merkle tree from config bytes.', - 'Index is an optional identifier and not checked by the program.', - ]; - accounts: [ - { - name: 'authority'; - isMut: true; - isSigner: true; - }, - { - name: 'merkleTree'; - isMut: true; - isSigner: false; - }, - { - name: 'nullifierQueue'; - isMut: true; - isSigner: false; - }, - { - name: 'registeredProgramPda'; - isMut: false; - isSigner: false; - isOptional: true; - }, - ]; - args: [ - { - name: 'index'; - type: 'u64'; - }, - { - name: 'programOwner'; - type: { - option: 'publicKey'; - }; - }, - { - name: 'forester'; - type: { - option: 'publicKey'; - }; - }, - { - name: 'stateMerkleTreeConfig'; - type: { - defined: 'StateMerkleTreeConfig'; - }; - }, - { - name: 'nullifierQueueConfig'; - type: { - defined: 'NullifierQueueConfig'; - }; - }, - { - name: 'additionalBytes'; - type: 'u64'; - }, - ]; - }, - { - name: 'appendLeavesToMerkleTrees'; - accounts: [ - { - name: 'feePayer'; - isMut: true; - isSigner: true; - docs: ['Fee payer pays rollover fee.']; - }, - { - name: 'authority'; - isMut: false; - isSigner: true; - docs: [ - 'Checked whether instruction is accessed by a registered program or owner = authority.', - ]; - }, - { - name: 'registeredProgramPda'; - isMut: false; - isSigner: false; - isOptional: true; - docs: [ - 'Some assumes that the Merkle trees are accessed by a registered program.', - 'None assumes that the Merkle trees are accessed by its owner.', - ]; - }, - { - name: 'systemProgram'; - isMut: false; - isSigner: false; - }, - ]; - args: [ - { - name: 'leaves'; - type: { - vec: { - defined: '(u8,[u8;32])'; - }; - }; - }, - ]; - }, - { - name: 'nullifyLeaves'; - accounts: [ - { - name: 'authority'; - isMut: false; - isSigner: true; - }, - { - name: 'registeredProgramPda'; - isMut: false; - isSigner: false; - isOptional: true; - }, - { - name: 'logWrapper'; - isMut: false; - isSigner: false; - }, - { - name: 'merkleTree'; - isMut: true; - isSigner: false; - }, - { - name: 'nullifierQueue'; - isMut: true; - isSigner: false; - }, - ]; - args: [ - { - name: 'changeLogIndices'; - type: { - vec: 'u64'; - }; - }, - { - name: 'leavesQueueIndices'; - type: { - vec: 'u16'; - }; - }, - { - name: 'leafIndices'; - type: { - vec: 'u64'; - }; - }, - { - name: 'proofs'; - type: { - vec: { - vec: { - array: ['u8', 32]; - }; - }; - }; - }, - ]; - }, - { - name: 'insertIntoNullifierQueues'; - accounts: [ - { - name: 'feePayer'; - isMut: true; - isSigner: true; - docs: ['Fee payer pays rollover fee.']; - }, - { - name: 'authority'; - isMut: false; - isSigner: true; - }, - { - name: 'registeredProgramPda'; - isMut: false; - isSigner: false; - isOptional: true; - }, - { - name: 'systemProgram'; - isMut: false; - isSigner: false; - }, - ]; - args: [ - { - name: 'nullifiers'; - type: { - vec: { - array: ['u8', 32]; - }; - }; - }, - { - name: 'leafIndices'; - type: { - vec: 'u32'; - }; - }, - { - name: 'txHash'; - type: { - option: { - array: ['u8', 32]; - }; - }; - }, - ]; - }, - { - name: 'rolloverStateMerkleTreeAndNullifierQueue'; - accounts: [ - { - name: 'feePayer'; - isMut: true; - isSigner: true; - docs: [ - 'Signer used to receive rollover accounts rentexemption reimbursement.', - ]; - }, - { - name: 'authority'; - isMut: false; - isSigner: true; - }, - { - name: 'registeredProgramPda'; - isMut: false; - isSigner: false; - isOptional: true; - }, - { - name: 'newStateMerkleTree'; - isMut: true; - isSigner: false; - }, - { - name: 'newNullifierQueue'; - isMut: true; - isSigner: false; - }, - { - name: 'oldStateMerkleTree'; - isMut: true; - isSigner: false; - }, - { - name: 'oldNullifierQueue'; - isMut: true; - isSigner: false; - }, - ]; - args: []; - }, - { - name: 'batchNullify'; - accounts: [ - { - name: 'authority'; - isMut: false; - isSigner: true; - }, - { - name: 'registeredProgramPda'; - isMut: false; - isSigner: false; - isOptional: true; - }, - { - name: 'logWrapper'; - isMut: false; - isSigner: false; - }, - { - name: 'merkleTree'; - isMut: true; - isSigner: false; - }, - ]; - args: [ - { - name: 'data'; - type: 'bytes'; - }, - ]; - }, - { - name: 'batchAppend'; - accounts: [ - { - name: 'authority'; - isMut: false; - isSigner: true; - }, - { - name: 'registeredProgramPda'; - isMut: false; - isSigner: false; - isOptional: true; - }, - { - name: 'logWrapper'; - isMut: false; - isSigner: false; - }, - { - name: 'merkleTree'; - isMut: true; - isSigner: false; - }, - { - name: 'outputQueue'; - isMut: true; - isSigner: false; - }, - ]; - args: [ - { - name: 'data'; - type: 'bytes'; - }, - ]; - }, - { - name: 'batchUpdateAddressTree'; - accounts: [ - { - name: 'authority'; - isMut: false; - isSigner: true; - }, - { - name: 'registeredProgramPda'; - isMut: false; - isSigner: false; - isOptional: true; - }, - { - name: 'logWrapper'; - isMut: false; - isSigner: false; - }, - { - name: 'merkleTree'; - isMut: true; - isSigner: false; - }, - ]; - args: [ - { - name: 'data'; - type: 'bytes'; - }, - ]; - }, - { - name: 'intializeBatchedAddressMerkleTree'; - accounts: [ - { - name: 'authority'; - isMut: true; - isSigner: true; - }, - { - name: 'merkleTree'; - isMut: true; - isSigner: false; - }, - { - name: 'registeredProgramPda'; - isMut: false; - isSigner: false; - isOptional: true; - }, - ]; - args: [ - { - name: 'bytes'; - type: 'bytes'; - }, - ]; - }, - { - name: 'rolloverBatchAddressMerkleTree'; - accounts: [ - { - name: 'feePayer'; - isMut: true; - isSigner: true; - docs: [ - 'Signer used to receive rollover accounts rentexemption reimbursement.', - ]; - }, - { - name: 'authority'; - isMut: false; - isSigner: true; - }, - { - name: 'registeredProgramPda'; - isMut: false; - isSigner: false; - isOptional: true; - }, - { - name: 'newAddressMerkleTree'; - isMut: true; - isSigner: false; - }, - { - name: 'oldAddressMerkleTree'; - isMut: true; - isSigner: false; - }, - ]; - args: [ - { - name: 'networkFee'; - type: { - option: 'u64'; - }; - }, - ]; - }, - { - name: 'rolloverBatchStateMerkleTree'; - accounts: [ - { - name: 'feePayer'; - isMut: true; - isSigner: true; - docs: [ - 'Signer used to receive rollover accounts rentexemption reimbursement.', - ]; - }, - { - name: 'authority'; - isMut: false; - isSigner: true; - }, - { - name: 'registeredProgramPda'; - isMut: false; - isSigner: false; - isOptional: true; - }, - { - name: 'newStateMerkleTree'; - isMut: true; - isSigner: false; - }, - { - name: 'oldStateMerkleTree'; - isMut: true; - isSigner: false; - }, - { - name: 'newOutputQueue'; - isMut: true; - isSigner: false; - }, - { - name: 'oldOutputQueue'; - isMut: true; - isSigner: false; - }, - ]; - args: [ - { - name: 'additionalBytes'; - type: 'u64'; - }, - { - name: 'networkFee'; - type: { - option: 'u64'; - }; - }, - ]; - }, - { - name: 'migrateState'; - accounts: [ - { - name: 'authority'; - isMut: false; - isSigner: true; - }, - { - name: 'registeredProgramPda'; - isMut: false; - isSigner: false; - isOptional: true; - }, - { - name: 'logWrapper'; - isMut: false; - isSigner: false; - }, - { - name: 'merkleTree'; - isMut: true; - isSigner: false; - }, - { - name: 'outputQueue'; - isMut: true; - isSigner: false; - }, - ]; - args: [ - { - name: 'input'; - type: { - defined: 'MigrateLeafParams'; - }; - }, - ]; - }, - ]; - accounts: [ - { - name: 'registeredProgram'; - type: { - kind: 'struct'; - fields: [ - { - name: 'registeredProgramId'; - type: 'publicKey'; - }, - { - name: 'groupAuthorityPda'; - type: 'publicKey'; - }, - ]; - }; - }, - { - name: 'addressMerkleTreeAccount'; - type: { - kind: 'struct'; - fields: [ - { - name: 'metadata'; - type: { - defined: 'MerkleTreeMetadata'; - }; - }, - ]; - }; - }, - { - name: 'groupAuthority'; - type: { - kind: 'struct'; - fields: [ - { - name: 'authority'; - type: 'publicKey'; - }, - { - name: 'seed'; - type: 'publicKey'; - }, - ]; - }; - }, - { - name: 'stateMerkleTreeAccount'; - docs: [ - 'Concurrent state Merkle tree used for public compressed transactions.', - ]; - type: { - kind: 'struct'; - fields: [ - { - name: 'metadata'; - type: { - defined: 'MerkleTreeMetadata'; - }; - }, - ]; - }; - }, - { - name: 'queueAccount'; - type: { - kind: 'struct'; - fields: [ - { - name: 'metadata'; - type: { - defined: 'QueueMetadata'; - }; - }, - ]; - }; - }, - ]; - types: [ - { - name: 'ZeroOutLeafIndex'; - type: { - kind: 'struct'; - fields: [ - { - name: 'treeIndex'; - type: 'u8'; - }, - { - name: 'batchIndex'; - type: 'u8'; - }, - { - name: 'leafIndex'; - type: 'u16'; - }, - ]; - }; - }, - { - name: 'AddressMerkleTreeConfig'; - type: { - kind: 'struct'; - fields: [ - { - name: 'height'; - type: 'u32'; - }, - { - name: 'changelogSize'; - type: 'u64'; - }, - { - name: 'rootsSize'; - type: 'u64'; - }, - { - name: 'canopyDepth'; - type: 'u64'; - }, - { - name: 'addressChangelogSize'; - type: 'u64'; - }, - { - name: 'networkFee'; - type: { - option: 'u64'; - }; - }, - { - name: 'rolloverThreshold'; - type: { - option: 'u64'; - }; - }, - { - name: 'closeThreshold'; - type: { - option: 'u64'; - }; - }, - ]; - }; - }, - { - name: 'StateMerkleTreeConfig'; - type: { - kind: 'struct'; - fields: [ - { - name: 'height'; - type: 'u32'; - }, - { - name: 'changelogSize'; - type: 'u64'; - }, - { - name: 'rootsSize'; - type: 'u64'; - }, - { - name: 'canopyDepth'; - type: 'u64'; - }, - { - name: 'networkFee'; - type: { - option: 'u64'; - }; - }, - { - name: 'rolloverThreshold'; - type: { - option: 'u64'; - }; - }, - { - name: 'closeThreshold'; - type: { - option: 'u64'; - }; - }, - ]; - }; - }, - { - name: 'NullifierQueueConfig'; - type: { - kind: 'struct'; - fields: [ - { - name: 'capacity'; - type: 'u16'; - }, - { - name: 'sequenceThreshold'; - type: 'u64'; - }, - { - name: 'networkFee'; - type: { - option: 'u64'; - }; - }, - ]; - }; - }, - { - name: 'MigrateLeafParams'; - type: { - kind: 'struct'; - fields: [ - { - name: 'changeLogIndex'; - type: 'u64'; - }, - { - name: 'leaf'; - type: { - array: ['u8', 32]; - }; - }, - { - name: 'leafIndex'; - type: 'u64'; - }, - { - name: 'proof'; - type: { - array: [ - { - array: ['u8', 32]; - }, - 16, - ]; - }; - }, - ]; - }; - }, - { - name: 'AddressQueueConfig'; - type: { - kind: 'alias'; - value: { - defined: 'NullifierQueueConfig'; - }; - }; - }, - ]; - errors: [ - { - code: 6000; - name: 'IntegerOverflow'; - msg: 'Integer overflow'; - }, - { - code: 6001; - name: 'InvalidAuthority'; - msg: 'InvalidAuthority'; - }, - { - code: 6002; - name: 'NumberOfLeavesMismatch'; - msg: 'Leaves <> remaining accounts mismatch. The number of remaining accounts must match the number of leaves.'; - }, - { - code: 6003; - name: 'InvalidNoopPubkey'; - msg: 'Provided noop program public key is invalid'; - }, - { - code: 6004; - name: 'NumberOfChangeLogIndicesMismatch'; - msg: 'Number of change log indices mismatch'; - }, - { - code: 6005; - name: 'NumberOfIndicesMismatch'; - msg: 'Number of indices mismatch'; - }, - { - code: 6006; - name: 'NumberOfProofsMismatch'; - msg: 'NumberOfProofsMismatch'; - }, - { - code: 6007; - name: 'InvalidMerkleProof'; - msg: 'InvalidMerkleProof'; - }, - { - code: 6008; - name: 'LeafNotFound'; - msg: 'Could not find the leaf in the queue'; - }, - { - code: 6009; - name: 'MerkleTreeAndQueueNotAssociated'; - msg: 'MerkleTreeAndQueueNotAssociated'; - }, - { - code: 6010; - name: 'MerkleTreeAlreadyRolledOver'; - msg: 'MerkleTreeAlreadyRolledOver'; - }, - { - code: 6011; - name: 'NotReadyForRollover'; - msg: 'NotReadyForRollover'; - }, - { - code: 6012; - name: 'RolloverNotConfigured'; - msg: 'RolloverNotConfigured'; - }, - { - code: 6013; - name: 'NotAllLeavesProcessed'; - msg: 'NotAllLeavesProcessed'; - }, - { - code: 6014; - name: 'InvalidQueueType'; - msg: 'InvalidQueueType'; - }, - { - code: 6015; - name: 'InputElementsEmpty'; - msg: 'InputElementsEmpty'; - }, - { - code: 6016; - name: 'NoLeavesForMerkleTree'; - msg: 'NoLeavesForMerkleTree'; - }, - { - code: 6017; - name: 'InvalidAccountSize'; - msg: 'InvalidAccountSize'; - }, - { - code: 6018; - name: 'InsufficientRolloverFee'; - msg: 'InsufficientRolloverFee'; - }, - { - code: 6019; - name: 'UnsupportedHeight'; - msg: 'Unsupported Merkle tree height'; - }, - { - code: 6020; - name: 'UnsupportedCanopyDepth'; - msg: 'Unsupported canopy depth'; - }, - { - code: 6021; - name: 'InvalidSequenceThreshold'; - msg: 'Invalid sequence threshold'; - }, - { - code: 6022; - name: 'UnsupportedCloseThreshold'; - msg: 'Unsupported close threshold'; - }, - { - code: 6023; - name: 'InvalidAccountBalance'; - msg: 'InvalidAccountBalance'; - }, - { - code: 6024; - name: 'UnsupportedAdditionalBytes'; - }, - { - code: 6025; - name: 'InvalidGroup'; - }, - { - code: 6026; - name: 'ProofLengthMismatch'; - }, - { - code: 6027; - name: 'TxHashUndefined'; - }, - { - code: 6028; - name: 'InputDeserializationFailed'; - }, - { - code: 6029; - name: 'UnsupportedParameters'; - }, - { - code: 6030; - name: 'AddressMerkleTreeAccountDiscriminatorMismatch'; - }, - { - code: 6031; - name: 'StateMerkleTreeAccountDiscriminatorMismatch'; - }, - { - code: 6032; - name: 'RegistryProgramIsNone'; - }, - { - code: 6033; - name: 'EmptyLeaf'; - }, - ]; -}; - -export const IDL: AccountCompression = { - version: '1.2.0', - name: 'account_compression', - constants: [ - { - name: 'CPI_AUTHORITY_PDA_SEED', - type: 'bytes', - value: '[99, 112, 105, 95, 97, 117, 116, 104, 111, 114, 105, 116, 121]', - }, - { - name: 'GROUP_AUTHORITY_SEED', - type: 'bytes', - value: '[103, 114, 111, 117, 112, 95, 97, 117, 116, 104, 111, 114, 105, 116, 121]', - }, - { - name: 'STATE_MERKLE_TREE_HEIGHT', - type: 'u64', - value: '26', - }, - { - name: 'STATE_MERKLE_TREE_CHANGELOG', - type: 'u64', - value: '1400', - }, - { - name: 'STATE_MERKLE_TREE_ROOTS', - type: 'u64', - value: '2400', - }, - { - name: 'STATE_MERKLE_TREE_CANOPY_DEPTH', - type: 'u64', - value: '10', - }, - { - name: 'STATE_NULLIFIER_QUEUE_VALUES', - type: 'u16', - value: '28_807', - }, - { - name: 'STATE_NULLIFIER_QUEUE_SEQUENCE_THRESHOLD', - type: 'u64', - value: '2400', - }, - { - name: 'ADDRESS_MERKLE_TREE_HEIGHT', - type: 'u64', - value: '26', - }, - { - name: 'ADDRESS_MERKLE_TREE_CHANGELOG', - type: 'u64', - value: '1400', - }, - { - name: 'ADDRESS_MERKLE_TREE_ROOTS', - type: 'u64', - value: '2400', - }, - { - name: 'ADDRESS_MERKLE_TREE_CANOPY_DEPTH', - type: 'u64', - value: '10', - }, - { - name: 'ADDRESS_MERKLE_TREE_INDEXED_CHANGELOG', - type: 'u64', - value: '1400', - }, - { - name: 'ADDRESS_QUEUE_VALUES', - type: 'u16', - value: '28_807', - }, - { - name: 'ADDRESS_QUEUE_SEQUENCE_THRESHOLD', - type: 'u64', - value: '2400', - }, - { - name: 'NOOP_PUBKEY', - type: { - array: ['u8', 32], - }, - value: '[11 , 188 , 15 , 192 , 187 , 71 , 202 , 47 , 116 , 196 , 17 , 46 , 148 , 171 , 19 , 207 , 163 , 198 , 52 , 229 , 220 , 23 , 234 , 203 , 3 , 205 , 26 , 35 , 205 , 126 , 120 , 124 ,]', - }, - ], - instructions: [ - { - name: 'initializeBatchedStateMerkleTree', - accounts: [ - { - name: 'authority', - isMut: true, - isSigner: true, - }, - { - name: 'merkleTree', - isMut: true, - isSigner: false, - }, - { - name: 'queue', - isMut: true, - isSigner: false, - }, - { - name: 'registeredProgramPda', - isMut: false, - isSigner: false, - isOptional: true, - }, - ], - args: [ - { - name: 'bytes', - type: 'bytes', - }, - ], - }, - { - name: 'initializeAddressMerkleTreeAndQueue', - accounts: [ - { - name: 'authority', - isMut: true, - isSigner: true, - }, - { - name: 'merkleTree', - isMut: true, - isSigner: false, - }, - { - name: 'queue', - isMut: true, - isSigner: false, - }, - { - name: 'registeredProgramPda', - isMut: false, - isSigner: false, - isOptional: true, - }, - ], - args: [ - { - name: 'index', - type: 'u64', - }, - { - name: 'programOwner', - type: { - option: 'publicKey', - }, - }, - { - name: 'forester', - type: { - option: 'publicKey', - }, - }, - { - name: 'addressMerkleTreeConfig', - type: { - defined: 'AddressMerkleTreeConfig', - }, - }, - { - name: 'addressQueueConfig', - type: { - defined: 'AddressQueueConfig', - }, - }, - ], - }, - { - name: 'insertAddresses', - accounts: [ - { - name: 'feePayer', - isMut: true, - isSigner: true, - docs: ['Fee payer pays rollover fee.'], - }, - { - name: 'authority', - isMut: false, - isSigner: true, - }, - { - name: 'registeredProgramPda', - isMut: false, - isSigner: false, - isOptional: true, - }, - { - name: 'systemProgram', - isMut: false, - isSigner: false, - }, - ], - args: [ - { - name: 'addresses', - type: { - vec: { - array: ['u8', 32], - }, - }, - }, - ], - }, - { - name: 'updateAddressMerkleTree', - docs: ['Updates the address Merkle tree with a new address.'], - accounts: [ - { - name: 'authority', - isMut: false, - isSigner: true, - }, - { - name: 'registeredProgramPda', - isMut: false, - isSigner: false, - isOptional: true, - }, - { - name: 'queue', - isMut: true, - isSigner: false, - }, - { - name: 'merkleTree', - isMut: true, - isSigner: false, - }, - { - name: 'logWrapper', - isMut: false, - isSigner: false, - }, - ], - args: [ - { - name: 'changelogIndex', - type: 'u16', - }, - { - name: 'indexedChangelogIndex', - type: 'u16', - }, - { - name: 'value', - type: 'u16', - }, - { - name: 'lowAddressIndex', - type: 'u64', - }, - { - name: 'lowAddressValue', - type: { - array: ['u8', 32], - }, - }, - { - name: 'lowAddressNextIndex', - type: 'u64', - }, - { - name: 'lowAddressNextValue', - type: { - array: ['u8', 32], - }, - }, - { - name: 'lowAddressProof', - type: { - array: [ - { - array: ['u8', 32], - }, - 16, - ], - }, - }, - ], - }, - { - name: 'rolloverAddressMerkleTreeAndQueue', - accounts: [ - { - name: 'feePayer', - isMut: true, - isSigner: true, - docs: [ - 'Signer used to receive rollover accounts rentexemption reimbursement.', - ], - }, - { - name: 'authority', - isMut: false, - isSigner: true, - }, - { - name: 'registeredProgramPda', - isMut: false, - isSigner: false, - isOptional: true, - }, - { - name: 'newAddressMerkleTree', - isMut: true, - isSigner: false, - }, - { - name: 'newQueue', - isMut: true, - isSigner: false, - }, - { - name: 'oldAddressMerkleTree', - isMut: true, - isSigner: false, - }, - { - name: 'oldQueue', - isMut: true, - isSigner: false, - }, - ], - args: [], - }, - { - name: 'initializeGroupAuthority', - docs: [ - 'initialize group (a group can be used to give multiple programs access', - 'to the same Merkle trees by registering the programs to the group)', - ], - accounts: [ - { - name: 'authority', - isMut: true, - isSigner: true, - }, - { - name: 'seed', - isMut: false, - isSigner: true, - docs: [ - 'Seed public key used to derive the group authority.', - ], - }, - { - name: 'groupAuthority', - isMut: true, - isSigner: false, - }, - { - name: 'systemProgram', - isMut: false, - isSigner: false, - }, - ], - args: [ - { - name: 'authority', - type: 'publicKey', - }, - ], - }, - { - name: 'updateGroupAuthority', - accounts: [ - { - name: 'authority', - isMut: false, - isSigner: true, - }, - { - name: 'groupAuthority', - isMut: true, - isSigner: false, - }, - ], - args: [ - { - name: 'authority', - type: 'publicKey', - }, - ], - }, - { - name: 'registerProgramToGroup', - accounts: [ - { - name: 'authority', - isMut: true, - isSigner: true, - }, - { - name: 'programToBeRegistered', - isMut: false, - isSigner: true, - }, - { - name: 'registeredProgramPda', - isMut: true, - isSigner: false, - }, - { - name: 'groupAuthorityPda', - isMut: false, - isSigner: false, - }, - { - name: 'systemProgram', - isMut: false, - isSigner: false, - }, - ], - args: [], - }, - { - name: 'deregisterProgram', - accounts: [ - { - name: 'authority', - isMut: true, - isSigner: true, - }, - { - name: 'registeredProgramPda', - isMut: true, - isSigner: false, - }, - { - name: 'groupAuthorityPda', - isMut: false, - isSigner: false, - }, - { - name: 'closeRecipient', - isMut: true, - isSigner: false, - }, - ], - args: [], - }, - { - name: 'initializeStateMerkleTreeAndNullifierQueue', - docs: [ - 'Initializes a new Merkle tree from config bytes.', - 'Index is an optional identifier and not checked by the program.', - ], - accounts: [ - { - name: 'authority', - isMut: true, - isSigner: true, - }, - { - name: 'merkleTree', - isMut: true, - isSigner: false, - }, - { - name: 'nullifierQueue', - isMut: true, - isSigner: false, - }, - { - name: 'registeredProgramPda', - isMut: false, - isSigner: false, - isOptional: true, - }, - ], - args: [ - { - name: 'index', - type: 'u64', - }, - { - name: 'programOwner', - type: { - option: 'publicKey', - }, - }, - { - name: 'forester', - type: { - option: 'publicKey', - }, - }, - { - name: 'stateMerkleTreeConfig', - type: { - defined: 'StateMerkleTreeConfig', - }, - }, - { - name: 'nullifierQueueConfig', - type: { - defined: 'NullifierQueueConfig', - }, - }, - { - name: 'additionalBytes', - type: 'u64', - }, - ], - }, - { - name: 'appendLeavesToMerkleTrees', - accounts: [ - { - name: 'feePayer', - isMut: true, - isSigner: true, - docs: ['Fee payer pays rollover fee.'], - }, - { - name: 'authority', - isMut: false, - isSigner: true, - docs: [ - 'Checked whether instruction is accessed by a registered program or owner = authority.', - ], - }, - { - name: 'registeredProgramPda', - isMut: false, - isSigner: false, - isOptional: true, - docs: [ - 'Some assumes that the Merkle trees are accessed by a registered program.', - 'None assumes that the Merkle trees are accessed by its owner.', - ], - }, - { - name: 'systemProgram', - isMut: false, - isSigner: false, - }, - ], - args: [ - { - name: 'leaves', - type: { - vec: { - defined: '(u8,[u8;32])', - }, - }, - }, - ], - }, - { - name: 'nullifyLeaves', - accounts: [ - { - name: 'authority', - isMut: false, - isSigner: true, - }, - { - name: 'registeredProgramPda', - isMut: false, - isSigner: false, - isOptional: true, - }, - { - name: 'logWrapper', - isMut: false, - isSigner: false, - }, - { - name: 'merkleTree', - isMut: true, - isSigner: false, - }, - { - name: 'nullifierQueue', - isMut: true, - isSigner: false, - }, - ], - args: [ - { - name: 'changeLogIndices', - type: { - vec: 'u64', - }, - }, - { - name: 'leavesQueueIndices', - type: { - vec: 'u16', - }, - }, - { - name: 'leafIndices', - type: { - vec: 'u64', - }, - }, - { - name: 'proofs', - type: { - vec: { - vec: { - array: ['u8', 32], - }, - }, - }, - }, - ], - }, - { - name: 'insertIntoNullifierQueues', - accounts: [ - { - name: 'feePayer', - isMut: true, - isSigner: true, - docs: ['Fee payer pays rollover fee.'], - }, - { - name: 'authority', - isMut: false, - isSigner: true, - }, - { - name: 'registeredProgramPda', - isMut: false, - isSigner: false, - isOptional: true, - }, - { - name: 'systemProgram', - isMut: false, - isSigner: false, - }, - ], - args: [ - { - name: 'nullifiers', - type: { - vec: { - array: ['u8', 32], - }, - }, - }, - { - name: 'leafIndices', - type: { - vec: 'u32', - }, - }, - { - name: 'txHash', - type: { - option: { - array: ['u8', 32], - }, - }, - }, - ], - }, - { - name: 'rolloverStateMerkleTreeAndNullifierQueue', - accounts: [ - { - name: 'feePayer', - isMut: true, - isSigner: true, - docs: [ - 'Signer used to receive rollover accounts rentexemption reimbursement.', - ], - }, - { - name: 'authority', - isMut: false, - isSigner: true, - }, - { - name: 'registeredProgramPda', - isMut: false, - isSigner: false, - isOptional: true, - }, - { - name: 'newStateMerkleTree', - isMut: true, - isSigner: false, - }, - { - name: 'newNullifierQueue', - isMut: true, - isSigner: false, - }, - { - name: 'oldStateMerkleTree', - isMut: true, - isSigner: false, - }, - { - name: 'oldNullifierQueue', - isMut: true, - isSigner: false, - }, - ], - args: [], - }, - { - name: 'batchNullify', - accounts: [ - { - name: 'authority', - isMut: false, - isSigner: true, - }, - { - name: 'registeredProgramPda', - isMut: false, - isSigner: false, - isOptional: true, - }, - { - name: 'logWrapper', - isMut: false, - isSigner: false, - }, - { - name: 'merkleTree', - isMut: true, - isSigner: false, - }, - ], - args: [ - { - name: 'data', - type: 'bytes', - }, - ], - }, - { - name: 'batchAppend', - accounts: [ - { - name: 'authority', - isMut: false, - isSigner: true, - }, - { - name: 'registeredProgramPda', - isMut: false, - isSigner: false, - isOptional: true, - }, - { - name: 'logWrapper', - isMut: false, - isSigner: false, - }, - { - name: 'merkleTree', - isMut: true, - isSigner: false, - }, - { - name: 'outputQueue', - isMut: true, - isSigner: false, - }, - ], - args: [ - { - name: 'data', - type: 'bytes', - }, - ], - }, - { - name: 'batchUpdateAddressTree', - accounts: [ - { - name: 'authority', - isMut: false, - isSigner: true, - }, - { - name: 'registeredProgramPda', - isMut: false, - isSigner: false, - isOptional: true, - }, - { - name: 'logWrapper', - isMut: false, - isSigner: false, - }, - { - name: 'merkleTree', - isMut: true, - isSigner: false, - }, - ], - args: [ - { - name: 'data', - type: 'bytes', - }, - ], - }, - { - name: 'intializeBatchedAddressMerkleTree', - accounts: [ - { - name: 'authority', - isMut: true, - isSigner: true, - }, - { - name: 'merkleTree', - isMut: true, - isSigner: false, - }, - { - name: 'registeredProgramPda', - isMut: false, - isSigner: false, - isOptional: true, - }, - ], - args: [ - { - name: 'bytes', - type: 'bytes', - }, - ], - }, - { - name: 'rolloverBatchAddressMerkleTree', - accounts: [ - { - name: 'feePayer', - isMut: true, - isSigner: true, - docs: [ - 'Signer used to receive rollover accounts rentexemption reimbursement.', - ], - }, - { - name: 'authority', - isMut: false, - isSigner: true, - }, - { - name: 'registeredProgramPda', - isMut: false, - isSigner: false, - isOptional: true, - }, - { - name: 'newAddressMerkleTree', - isMut: true, - isSigner: false, - }, - { - name: 'oldAddressMerkleTree', - isMut: true, - isSigner: false, - }, - ], - args: [ - { - name: 'networkFee', - type: { - option: 'u64', - }, - }, - ], - }, - { - name: 'rolloverBatchStateMerkleTree', - accounts: [ - { - name: 'feePayer', - isMut: true, - isSigner: true, - docs: [ - 'Signer used to receive rollover accounts rentexemption reimbursement.', - ], - }, - { - name: 'authority', - isMut: false, - isSigner: true, - }, - { - name: 'registeredProgramPda', - isMut: false, - isSigner: false, - isOptional: true, - }, - { - name: 'newStateMerkleTree', - isMut: true, - isSigner: false, - }, - { - name: 'oldStateMerkleTree', - isMut: true, - isSigner: false, - }, - { - name: 'newOutputQueue', - isMut: true, - isSigner: false, - }, - { - name: 'oldOutputQueue', - isMut: true, - isSigner: false, - }, - ], - args: [ - { - name: 'additionalBytes', - type: 'u64', - }, - { - name: 'networkFee', - type: { - option: 'u64', - }, - }, - ], - }, - { - name: 'migrateState', - accounts: [ - { - name: 'authority', - isMut: false, - isSigner: true, - }, - { - name: 'registeredProgramPda', - isMut: false, - isSigner: false, - isOptional: true, - }, - { - name: 'logWrapper', - isMut: false, - isSigner: false, - }, - { - name: 'merkleTree', - isMut: true, - isSigner: false, - }, - { - name: 'outputQueue', - isMut: true, - isSigner: false, - }, - ], - args: [ - { - name: 'input', - type: { - defined: 'MigrateLeafParams', - }, - }, - ], - }, - ], - accounts: [ - { - name: 'registeredProgram', - type: { - kind: 'struct', - fields: [ - { - name: 'registeredProgramId', - type: 'publicKey', - }, - { - name: 'groupAuthorityPda', - type: 'publicKey', - }, - ], - }, - }, - { - name: 'addressMerkleTreeAccount', - type: { - kind: 'struct', - fields: [ - { - name: 'metadata', - type: { - defined: 'MerkleTreeMetadata', - }, - }, - ], - }, - }, - { - name: 'groupAuthority', - type: { - kind: 'struct', - fields: [ - { - name: 'authority', - type: 'publicKey', - }, - { - name: 'seed', - type: 'publicKey', - }, - ], - }, - }, - { - name: 'stateMerkleTreeAccount', - docs: [ - 'Concurrent state Merkle tree used for public compressed transactions.', - ], - type: { - kind: 'struct', - fields: [ - { - name: 'metadata', - type: { - defined: 'MerkleTreeMetadata', - }, - }, - ], - }, - }, - { - name: 'queueAccount', - type: { - kind: 'struct', - fields: [ - { - name: 'metadata', - type: { - defined: 'QueueMetadata', - }, - }, - ], - }, - }, - ], - types: [ - { - name: 'ZeroOutLeafIndex', - type: { - kind: 'struct', - fields: [ - { - name: 'treeIndex', - type: 'u8', - }, - { - name: 'batchIndex', - type: 'u8', - }, - { - name: 'leafIndex', - type: 'u16', - }, - ], - }, - }, - { - name: 'AddressMerkleTreeConfig', - type: { - kind: 'struct', - fields: [ - { - name: 'height', - type: 'u32', - }, - { - name: 'changelogSize', - type: 'u64', - }, - { - name: 'rootsSize', - type: 'u64', - }, - { - name: 'canopyDepth', - type: 'u64', - }, - { - name: 'addressChangelogSize', - type: 'u64', - }, - { - name: 'networkFee', - type: { - option: 'u64', - }, - }, - { - name: 'rolloverThreshold', - type: { - option: 'u64', - }, - }, - { - name: 'closeThreshold', - type: { - option: 'u64', - }, - }, - ], - }, - }, - { - name: 'StateMerkleTreeConfig', - type: { - kind: 'struct', - fields: [ - { - name: 'height', - type: 'u32', - }, - { - name: 'changelogSize', - type: 'u64', - }, - { - name: 'rootsSize', - type: 'u64', - }, - { - name: 'canopyDepth', - type: 'u64', - }, - { - name: 'networkFee', - type: { - option: 'u64', - }, - }, - { - name: 'rolloverThreshold', - type: { - option: 'u64', - }, - }, - { - name: 'closeThreshold', - type: { - option: 'u64', - }, - }, - ], - }, - }, - { - name: 'NullifierQueueConfig', - type: { - kind: 'struct', - fields: [ - { - name: 'capacity', - type: 'u16', - }, - { - name: 'sequenceThreshold', - type: 'u64', - }, - { - name: 'networkFee', - type: { - option: 'u64', - }, - }, - ], - }, - }, - { - name: 'MigrateLeafParams', - type: { - kind: 'struct', - fields: [ - { - name: 'changeLogIndex', - type: 'u64', - }, - { - name: 'leaf', - type: { - array: ['u8', 32], - }, - }, - { - name: 'leafIndex', - type: 'u64', - }, - { - name: 'proof', - type: { - array: [ - { - array: ['u8', 32], - }, - 16, - ], - }, - }, - ], - }, - }, - { - name: 'AddressQueueConfig', - type: { - kind: 'alias', - value: { - defined: 'NullifierQueueConfig', - }, - }, - }, - ], - errors: [ - { - code: 6000, - name: 'IntegerOverflow', - msg: 'Integer overflow', - }, - { - code: 6001, - name: 'InvalidAuthority', - msg: 'InvalidAuthority', - }, - { - code: 6002, - name: 'NumberOfLeavesMismatch', - msg: 'Leaves <> remaining accounts mismatch. The number of remaining accounts must match the number of leaves.', - }, - { - code: 6003, - name: 'InvalidNoopPubkey', - msg: 'Provided noop program public key is invalid', - }, - { - code: 6004, - name: 'NumberOfChangeLogIndicesMismatch', - msg: 'Number of change log indices mismatch', - }, - { - code: 6005, - name: 'NumberOfIndicesMismatch', - msg: 'Number of indices mismatch', - }, - { - code: 6006, - name: 'NumberOfProofsMismatch', - msg: 'NumberOfProofsMismatch', - }, - { - code: 6007, - name: 'InvalidMerkleProof', - msg: 'InvalidMerkleProof', - }, - { - code: 6008, - name: 'LeafNotFound', - msg: 'Could not find the leaf in the queue', - }, - { - code: 6009, - name: 'MerkleTreeAndQueueNotAssociated', - msg: 'MerkleTreeAndQueueNotAssociated', - }, - { - code: 6010, - name: 'MerkleTreeAlreadyRolledOver', - msg: 'MerkleTreeAlreadyRolledOver', - }, - { - code: 6011, - name: 'NotReadyForRollover', - msg: 'NotReadyForRollover', - }, - { - code: 6012, - name: 'RolloverNotConfigured', - msg: 'RolloverNotConfigured', - }, - { - code: 6013, - name: 'NotAllLeavesProcessed', - msg: 'NotAllLeavesProcessed', - }, - { - code: 6014, - name: 'InvalidQueueType', - msg: 'InvalidQueueType', - }, - { - code: 6015, - name: 'InputElementsEmpty', - msg: 'InputElementsEmpty', - }, - { - code: 6016, - name: 'NoLeavesForMerkleTree', - msg: 'NoLeavesForMerkleTree', - }, - { - code: 6017, - name: 'InvalidAccountSize', - msg: 'InvalidAccountSize', - }, - { - code: 6018, - name: 'InsufficientRolloverFee', - msg: 'InsufficientRolloverFee', - }, - { - code: 6019, - name: 'UnsupportedHeight', - msg: 'Unsupported Merkle tree height', - }, - { - code: 6020, - name: 'UnsupportedCanopyDepth', - msg: 'Unsupported canopy depth', - }, - { - code: 6021, - name: 'InvalidSequenceThreshold', - msg: 'Invalid sequence threshold', - }, - { - code: 6022, - name: 'UnsupportedCloseThreshold', - msg: 'Unsupported close threshold', - }, - { - code: 6023, - name: 'InvalidAccountBalance', - msg: 'InvalidAccountBalance', - }, - { - code: 6024, - name: 'UnsupportedAdditionalBytes', - }, - { - code: 6025, - name: 'InvalidGroup', - }, - { - code: 6026, - name: 'ProofLengthMismatch', - }, - { - code: 6027, - name: 'TxHashUndefined', - }, - { - code: 6028, - name: 'InputDeserializationFailed', - }, - { - code: 6029, - name: 'UnsupportedParameters', - }, - { - code: 6030, - name: 'AddressMerkleTreeAccountDiscriminatorMismatch', - }, - { - code: 6031, - name: 'StateMerkleTreeAccountDiscriminatorMismatch', - }, - { - code: 6032, - name: 'RegistryProgramIsNone', - }, - { - code: 6033, - name: 'EmptyLeaf', - }, - ], -}; diff --git a/js/stateless.js/src/idls/index.ts b/js/stateless.js/src/idls/index.ts deleted file mode 100644 index a4c0de64e8..0000000000 --- a/js/stateless.js/src/idls/index.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { - IDL as AccountCompressionIDL, - AccountCompression, -} from './account_compression'; - -import { IDL as LightRegistryIDL, LightRegistry } from './light_registry'; -import { - IDL as LightSystemIDL, - LightSystemProgram as LightSystem, -} from './light_system_program'; - -import { - IDL as LightCompressedTokenIDL, - LightCompressedToken, -} from './light_compressed_token'; - -export { - AccountCompressionIDL, - AccountCompression, - LightRegistryIDL, - LightRegistry, - LightSystemIDL, - LightSystem, - LightCompressedTokenIDL, - LightCompressedToken, -}; diff --git a/js/stateless.js/src/idls/light_compressed_token.ts b/js/stateless.js/src/idls/light_compressed_token.ts deleted file mode 100644 index 3dc084e1b3..0000000000 --- a/js/stateless.js/src/idls/light_compressed_token.ts +++ /dev/null @@ -1,3481 +0,0 @@ -export type LightCompressedToken = { - version: '1.2.0'; - name: 'light_compressed_token'; - instructions: [ - { - name: 'createTokenPool'; - docs: [ - 'This instruction creates a token pool for a given mint. Every spl mint', - 'can have one token pool. When a token is compressed the tokens are', - 'transferrred to the token pool, and their compressed equivalent is', - 'minted into a Merkle tree.', - ]; - accounts: [ - { - name: 'feePayer'; - isMut: true; - isSigner: true; - docs: ['UNCHECKED: only pays fees.']; - }, - { - name: 'tokenPoolPda'; - isMut: true; - isSigner: false; - }, - { - name: 'systemProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'mint'; - isMut: true; - isSigner: false; - }, - { - name: 'tokenProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'cpiAuthorityPda'; - isMut: false; - isSigner: false; - }, - ]; - args: []; - }, - { - name: 'addTokenPool'; - docs: [ - 'This instruction creates an additional token pool for a given mint.', - 'The maximum number of token pools per mint is 5.', - ]; - accounts: [ - { - name: 'feePayer'; - isMut: true; - isSigner: true; - docs: ['UNCHECKED: only pays fees.']; - }, - { - name: 'tokenPoolPda'; - isMut: true; - isSigner: false; - }, - { - name: 'existingTokenPoolPda'; - isMut: false; - isSigner: false; - }, - { - name: 'systemProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'mint'; - isMut: true; - isSigner: false; - }, - { - name: 'tokenProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'cpiAuthorityPda'; - isMut: false; - isSigner: false; - }, - ]; - args: [ - { - name: 'tokenPoolBump'; - type: 'u8'; - }, - ]; - }, - { - name: 'mintTo'; - docs: [ - 'Mints tokens from an spl token mint to a list of compressed accounts.', - 'Minted tokens are transferred to a pool account owned by the compressed', - 'token program. The instruction creates one compressed output account for', - 'every amount and pubkey input pair. A constant amount of lamports can be', - 'transferred to each output account to enable. A use case to add lamports', - 'to a compressed token account is to prevent spam. This is the only way', - 'to add lamports to a compressed token account.', - ]; - accounts: [ - { - name: 'feePayer'; - isMut: true; - isSigner: true; - docs: ['UNCHECKED: only pays fees.']; - }, - { - name: 'authority'; - isMut: false; - isSigner: true; - }, - { - name: 'cpiAuthorityPda'; - isMut: false; - isSigner: false; - }, - { - name: 'mint'; - isMut: true; - isSigner: false; - }, - { - name: 'tokenPoolPda'; - isMut: true; - isSigner: false; - }, - { - name: 'tokenProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'lightSystemProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'registeredProgramPda'; - isMut: false; - isSigner: false; - }, - { - name: 'noopProgram'; - isMut: false; - isSigner: false; - docs: ['programs']; - }, - { - name: 'accountCompressionAuthority'; - isMut: false; - isSigner: false; - }, - { - name: 'accountCompressionProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'merkleTree'; - isMut: true; - isSigner: false; - }, - { - name: 'selfProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'systemProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'solPoolPda'; - isMut: true; - isSigner: false; - isOptional: true; - }, - ]; - args: [ - { - name: 'publicKeys'; - type: { - vec: 'publicKey'; - }; - }, - { - name: 'amounts'; - type: { - vec: 'u64'; - }; - }, - { - name: 'lamports'; - type: { - option: 'u64'; - }; - }, - ]; - }, - { - name: 'compressSplTokenAccount'; - docs: [ - 'Compresses the balance of an spl token account sub an optional remaining', - 'amount. This instruction does not close the spl token account. To close', - 'the account bundle a close spl account instruction in your transaction.', - ]; - accounts: [ - { - name: 'feePayer'; - isMut: true; - isSigner: true; - docs: ['UNCHECKED: only pays fees.']; - }, - { - name: 'authority'; - isMut: false; - isSigner: true; - docs: [ - 'Authority is verified through proof since both owner and delegate', - 'are included in the token data hash, which is a public input to the', - 'validity proof.', - ]; - }, - { - name: 'cpiAuthorityPda'; - isMut: false; - isSigner: false; - }, - { - name: 'lightSystemProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'registeredProgramPda'; - isMut: false; - isSigner: false; - }, - { - name: 'noopProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'accountCompressionAuthority'; - isMut: false; - isSigner: false; - }, - { - name: 'accountCompressionProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'selfProgram'; - isMut: false; - isSigner: false; - docs: ['this program is the signer of the cpi.']; - }, - { - name: 'tokenPoolPda'; - isMut: true; - isSigner: false; - isOptional: true; - }, - { - name: 'compressOrDecompressTokenAccount'; - isMut: true; - isSigner: false; - isOptional: true; - }, - { - name: 'tokenProgram'; - isMut: false; - isSigner: false; - isOptional: true; - }, - { - name: 'systemProgram'; - isMut: false; - isSigner: false; - }, - ]; - args: [ - { - name: 'owner'; - type: 'publicKey'; - }, - { - name: 'remainingAmount'; - type: { - option: 'u64'; - }; - }, - { - name: 'cpiContext'; - type: { - option: { - defined: 'CompressedCpiContext'; - }; - }; - }, - ]; - }, - { - name: 'transfer'; - docs: [ - 'Transfers compressed tokens from one account to another. All accounts', - 'must be of the same mint. Additional spl tokens can be compressed or', - 'decompressed. In one transaction only compression or decompression is', - 'possible. Lamports can be transferred alongside tokens. If output token', - 'accounts specify less lamports than inputs the remaining lamports are', - 'transferred to an output compressed account. Signer must be owner or', - 'delegate. If a delegated token account is transferred the delegate is', - 'not preserved.', - ]; - accounts: [ - { - name: 'feePayer'; - isMut: true; - isSigner: true; - docs: ['UNCHECKED: only pays fees.']; - }, - { - name: 'authority'; - isMut: false; - isSigner: true; - docs: [ - 'Authority is verified through proof since both owner and delegate', - 'are included in the token data hash, which is a public input to the', - 'validity proof.', - ]; - }, - { - name: 'cpiAuthorityPda'; - isMut: false; - isSigner: false; - }, - { - name: 'lightSystemProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'registeredProgramPda'; - isMut: false; - isSigner: false; - }, - { - name: 'noopProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'accountCompressionAuthority'; - isMut: false; - isSigner: false; - }, - { - name: 'accountCompressionProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'selfProgram'; - isMut: false; - isSigner: false; - docs: ['this program is the signer of the cpi.']; - }, - { - name: 'tokenPoolPda'; - isMut: true; - isSigner: false; - isOptional: true; - }, - { - name: 'compressOrDecompressTokenAccount'; - isMut: true; - isSigner: false; - isOptional: true; - }, - { - name: 'tokenProgram'; - isMut: false; - isSigner: false; - isOptional: true; - }, - { - name: 'systemProgram'; - isMut: false; - isSigner: false; - }, - ]; - args: [ - { - name: 'inputs'; - type: 'bytes'; - }, - ]; - }, - { - name: 'approve'; - docs: [ - 'Delegates an amount to a delegate. A compressed token account is either', - 'completely delegated or not. Prior delegates are not preserved. Cannot', - 'be called by a delegate.', - 'The instruction creates two output accounts:', - '1. one account with delegated amount', - '2. one account with remaining(change) amount', - ]; - accounts: [ - { - name: 'feePayer'; - isMut: true; - isSigner: true; - docs: ['UNCHECKED: only pays fees.']; - }, - { - name: 'authority'; - isMut: false; - isSigner: true; - docs: [ - 'Authority is verified through proof since both owner and delegate', - 'are included in the token data hash, which is a public input to the', - 'validity proof.', - ]; - }, - { - name: 'cpiAuthorityPda'; - isMut: false; - isSigner: false; - }, - { - name: 'lightSystemProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'registeredProgramPda'; - isMut: false; - isSigner: false; - }, - { - name: 'noopProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'accountCompressionAuthority'; - isMut: false; - isSigner: false; - }, - { - name: 'accountCompressionProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'selfProgram'; - isMut: false; - isSigner: false; - docs: ['this program is the signer of the cpi.']; - }, - { - name: 'systemProgram'; - isMut: false; - isSigner: false; - }, - ]; - args: [ - { - name: 'inputs'; - type: 'bytes'; - }, - ]; - }, - { - name: 'revoke'; - docs: [ - 'Revokes a delegation. The instruction merges all inputs into one output', - 'account. Cannot be called by a delegate. Delegates are not preserved.', - ]; - accounts: [ - { - name: 'feePayer'; - isMut: true; - isSigner: true; - docs: ['UNCHECKED: only pays fees.']; - }, - { - name: 'authority'; - isMut: false; - isSigner: true; - docs: [ - 'Authority is verified through proof since both owner and delegate', - 'are included in the token data hash, which is a public input to the', - 'validity proof.', - ]; - }, - { - name: 'cpiAuthorityPda'; - isMut: false; - isSigner: false; - }, - { - name: 'lightSystemProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'registeredProgramPda'; - isMut: false; - isSigner: false; - }, - { - name: 'noopProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'accountCompressionAuthority'; - isMut: false; - isSigner: false; - }, - { - name: 'accountCompressionProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'selfProgram'; - isMut: false; - isSigner: false; - docs: ['this program is the signer of the cpi.']; - }, - { - name: 'systemProgram'; - isMut: false; - isSigner: false; - }, - ]; - args: [ - { - name: 'inputs'; - type: 'bytes'; - }, - ]; - }, - { - name: 'freeze'; - docs: [ - 'Freezes compressed token accounts. Inputs must not be frozen. Creates as', - 'many outputs as inputs. Balances and delegates are preserved.', - ]; - accounts: [ - { - name: 'feePayer'; - isMut: true; - isSigner: true; - docs: ['UNCHECKED: only pays fees.']; - }, - { - name: 'authority'; - isMut: false; - isSigner: true; - }, - { - name: 'cpiAuthorityPda'; - isMut: false; - isSigner: false; - }, - { - name: 'lightSystemProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'registeredProgramPda'; - isMut: false; - isSigner: false; - }, - { - name: 'noopProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'accountCompressionAuthority'; - isMut: false; - isSigner: false; - }, - { - name: 'accountCompressionProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'selfProgram'; - isMut: false; - isSigner: false; - docs: ['that this program is the signer of the cpi.']; - }, - { - name: 'systemProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'mint'; - isMut: false; - isSigner: false; - }, - ]; - args: [ - { - name: 'inputs'; - type: 'bytes'; - }, - ]; - }, - { - name: 'thaw'; - docs: [ - 'Thaws frozen compressed token accounts. Inputs must be frozen. Creates', - 'as many outputs as inputs. Balances and delegates are preserved.', - ]; - accounts: [ - { - name: 'feePayer'; - isMut: true; - isSigner: true; - docs: ['UNCHECKED: only pays fees.']; - }, - { - name: 'authority'; - isMut: false; - isSigner: true; - }, - { - name: 'cpiAuthorityPda'; - isMut: false; - isSigner: false; - }, - { - name: 'lightSystemProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'registeredProgramPda'; - isMut: false; - isSigner: false; - }, - { - name: 'noopProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'accountCompressionAuthority'; - isMut: false; - isSigner: false; - }, - { - name: 'accountCompressionProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'selfProgram'; - isMut: false; - isSigner: false; - docs: ['that this program is the signer of the cpi.']; - }, - { - name: 'systemProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'mint'; - isMut: false; - isSigner: false; - }, - ]; - args: [ - { - name: 'inputs'; - type: 'bytes'; - }, - ]; - }, - { - name: 'burn'; - docs: [ - 'Burns compressed tokens and spl tokens from the pool account. Delegates', - 'can burn tokens. The output compressed token account remains delegated.', - 'Creates one output compressed token account.', - ]; - accounts: [ - { - name: 'feePayer'; - isMut: true; - isSigner: true; - docs: ['UNCHECKED: only pays fees.']; - }, - { - name: 'authority'; - isMut: false; - isSigner: true; - docs: [ - 'Authority is verified through proof since both owner and delegate', - 'are included in the token data hash, which is a public input to the', - 'validity proof.', - ]; - }, - { - name: 'cpiAuthorityPda'; - isMut: false; - isSigner: false; - }, - { - name: 'mint'; - isMut: true; - isSigner: false; - }, - { - name: 'tokenPoolPda'; - isMut: true; - isSigner: false; - }, - { - name: 'tokenProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'lightSystemProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'registeredProgramPda'; - isMut: false; - isSigner: false; - }, - { - name: 'noopProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'accountCompressionAuthority'; - isMut: false; - isSigner: false; - }, - { - name: 'accountCompressionProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'selfProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'systemProgram'; - isMut: false; - isSigner: false; - }, - ]; - args: [ - { - name: 'inputs'; - type: 'bytes'; - }, - ]; - }, - { - name: 'stubIdlBuild'; - docs: [ - 'This function is a stub to allow Anchor to include the input types in', - 'the IDL. It should not be included in production builds nor be called in', - 'practice.', - ]; - accounts: [ - { - name: 'feePayer'; - isMut: true; - isSigner: true; - docs: ['UNCHECKED: only pays fees.']; - }, - { - name: 'authority'; - isMut: false; - isSigner: true; - docs: [ - 'Authority is verified through proof since both owner and delegate', - 'are included in the token data hash, which is a public input to the', - 'validity proof.', - ]; - }, - { - name: 'cpiAuthorityPda'; - isMut: false; - isSigner: false; - }, - { - name: 'lightSystemProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'registeredProgramPda'; - isMut: false; - isSigner: false; - }, - { - name: 'noopProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'accountCompressionAuthority'; - isMut: false; - isSigner: false; - }, - { - name: 'accountCompressionProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'selfProgram'; - isMut: false; - isSigner: false; - docs: ['this program is the signer of the cpi.']; - }, - { - name: 'tokenPoolPda'; - isMut: true; - isSigner: false; - isOptional: true; - }, - { - name: 'compressOrDecompressTokenAccount'; - isMut: true; - isSigner: false; - isOptional: true; - }, - { - name: 'tokenProgram'; - isMut: false; - isSigner: false; - isOptional: true; - }, - { - name: 'systemProgram'; - isMut: false; - isSigner: false; - }, - ]; - args: [ - { - name: 'inputs1'; - type: { - defined: 'CompressedTokenInstructionDataTransfer'; - }; - }, - { - name: 'inputs2'; - type: { - defined: 'TokenData'; - }; - }, - ]; - }, - ]; - types: [ - { - name: 'AccountState'; - type: { - kind: 'enum'; - variants: [ - { - name: 'Initialized'; - }, - { - name: 'Frozen'; - }, - ]; - }; - }, - { - name: 'CompressedAccount'; - type: { - kind: 'struct'; - fields: [ - { - name: 'owner'; - type: 'publicKey'; - }, - { - name: 'lamports'; - type: 'u64'; - }, - { - name: 'address'; - type: { - option: { - array: ['u8', 32]; - }; - }; - }, - { - name: 'data'; - type: { - option: { - defined: 'CompressedAccountData'; - }; - }; - }, - ]; - }; - }, - { - name: 'CompressedAccountData'; - type: { - kind: 'struct'; - fields: [ - { - name: 'discriminator'; - type: { - array: ['u8', 8]; - }; - }, - { - name: 'data'; - type: 'bytes'; - }, - { - name: 'dataHash'; - type: { - array: ['u8', 32]; - }; - }, - ]; - }; - }, - { - name: 'CompressedCpiContext'; - type: { - kind: 'struct'; - fields: [ - { - name: 'setContext'; - docs: [ - 'Is set by the program that is invoking the CPI to signal that is should', - 'set the cpi context.', - ]; - type: 'bool'; - }, - { - name: 'firstSetContext'; - docs: [ - 'Is set to wipe the cpi context since someone could have set it before', - 'with unrelated data.', - ]; - type: 'bool'; - }, - { - name: 'cpiContextAccountIndex'; - docs: [ - 'Index of cpi context account in remaining accounts.', - ]; - type: 'u8'; - }, - ]; - }; - }, - { - name: 'CompressedProof'; - type: { - kind: 'struct'; - fields: [ - { - name: 'a'; - type: { - array: ['u8', 32]; - }; - }, - { - name: 'b'; - type: { - array: ['u8', 64]; - }; - }, - { - name: 'c'; - type: { - array: ['u8', 32]; - }; - }, - ]; - }; - }, - { - name: 'CompressedTokenInstructionDataTransfer'; - type: { - kind: 'struct'; - fields: [ - { - name: 'proof'; - type: { - option: { - defined: 'CompressedProof'; - }; - }; - }, - { - name: 'mint'; - type: 'publicKey'; - }, - { - name: 'delegatedTransfer'; - docs: [ - 'Is required if the signer is delegate,', - '-> delegate is authority account,', - 'owner = Some(owner) is the owner of the token account.', - ]; - type: { - option: { - defined: 'DelegatedTransfer'; - }; - }; - }, - { - name: 'inputTokenDataWithContext'; - type: { - vec: { - defined: 'InputTokenDataWithContext'; - }; - }; - }, - { - name: 'outputCompressedAccounts'; - type: { - vec: { - defined: 'PackedTokenTransferOutputData'; - }; - }; - }, - { - name: 'isCompress'; - type: 'bool'; - }, - { - name: 'compressOrDecompressAmount'; - type: { - option: 'u64'; - }; - }, - { - name: 'cpiContext'; - type: { - option: { - defined: 'CompressedCpiContext'; - }; - }; - }, - { - name: 'lamportsChangeAccountMerkleTreeIndex'; - type: { - option: 'u8'; - }; - }, - ]; - }; - }, - { - name: 'DelegatedTransfer'; - docs: [ - 'Struct to provide the owner when the delegate is signer of the transaction.', - ]; - type: { - kind: 'struct'; - fields: [ - { - name: 'owner'; - type: 'publicKey'; - }, - { - name: 'delegateChangeAccountIndex'; - docs: [ - 'Index of change compressed account in output compressed accounts. In', - "case that the delegate didn't spend the complete delegated compressed", - 'account balance the change compressed account will be delegated to her', - 'as well.', - ]; - type: { - option: 'u8'; - }; - }, - ]; - }; - }, - { - name: 'InputTokenDataWithContext'; - type: { - kind: 'struct'; - fields: [ - { - name: 'amount'; - type: 'u64'; - }, - { - name: 'delegateIndex'; - type: { - option: 'u8'; - }; - }, - { - name: 'merkleContext'; - type: { - defined: 'PackedMerkleContext'; - }; - }, - { - name: 'rootIndex'; - type: 'u16'; - }, - { - name: 'lamports'; - type: { - option: 'u64'; - }; - }, - { - name: 'tlv'; - docs: [ - 'Placeholder for TokenExtension tlv data (unimplemented)', - ]; - type: { - option: 'bytes'; - }; - }, - ]; - }; - }, - { - name: 'InstructionDataInvoke'; - type: { - kind: 'struct'; - fields: [ - { - name: 'proof'; - type: { - option: { - defined: 'CompressedProof'; - }; - }; - }, - { - name: 'inputCompressedAccountsWithMerkleContext'; - type: { - vec: { - defined: 'PackedCompressedAccountWithMerkleContext'; - }; - }; - }, - { - name: 'outputCompressedAccounts'; - type: { - vec: { - defined: 'OutputCompressedAccountWithPackedContext'; - }; - }; - }, - { - name: 'relayFee'; - type: { - option: 'u64'; - }; - }, - { - name: 'newAddressParams'; - type: { - vec: { - defined: 'NewAddressParamsPacked'; - }; - }; - }, - { - name: 'compressOrDecompressLamports'; - type: { - option: 'u64'; - }; - }, - { - name: 'isCompress'; - type: 'bool'; - }, - ]; - }; - }, - { - name: 'InstructionDataInvokeCpi'; - type: { - kind: 'struct'; - fields: [ - { - name: 'proof'; - type: { - option: { - defined: 'CompressedProof'; - }; - }; - }, - { - name: 'newAddressParams'; - type: { - vec: { - defined: 'NewAddressParamsPacked'; - }; - }; - }, - { - name: 'inputCompressedAccountsWithMerkleContext'; - type: { - vec: { - defined: 'PackedCompressedAccountWithMerkleContext'; - }; - }; - }, - { - name: 'outputCompressedAccounts'; - type: { - vec: { - defined: 'OutputCompressedAccountWithPackedContext'; - }; - }; - }, - { - name: 'relayFee'; - type: { - option: 'u64'; - }; - }, - { - name: 'compressOrDecompressLamports'; - type: { - option: 'u64'; - }; - }, - { - name: 'isCompress'; - type: 'bool'; - }, - { - name: 'cpiContext'; - type: { - option: { - defined: 'CompressedCpiContext'; - }; - }; - }, - ]; - }; - }, - { - name: 'MerkleTreeSequenceNumber'; - type: { - kind: 'struct'; - fields: [ - { - name: 'pubkey'; - type: 'publicKey'; - }, - { - name: 'seq'; - type: 'u64'; - }, - ]; - }; - }, - { - name: 'NewAddressParamsPacked'; - type: { - kind: 'struct'; - fields: [ - { - name: 'seed'; - type: { - array: ['u8', 32]; - }; - }, - { - name: 'addressQueueAccountIndex'; - type: 'u8'; - }, - { - name: 'addressMerkleTreeAccountIndex'; - type: 'u8'; - }, - { - name: 'addressMerkleTreeRootIndex'; - type: 'u16'; - }, - ]; - }; - }, - { - name: 'OutputCompressedAccountWithPackedContext'; - type: { - kind: 'struct'; - fields: [ - { - name: 'compressedAccount'; - type: { - defined: 'CompressedAccount'; - }; - }, - { - name: 'merkleTreeIndex'; - type: 'u8'; - }, - ]; - }; - }, - { - name: 'PackedCompressedAccountWithMerkleContext'; - type: { - kind: 'struct'; - fields: [ - { - name: 'compressedAccount'; - type: { - defined: 'CompressedAccount'; - }; - }, - { - name: 'merkleContext'; - type: { - defined: 'PackedMerkleContext'; - }; - }, - { - name: 'rootIndex'; - docs: [ - 'Index of root used in inclusion validity proof.', - ]; - type: 'u16'; - }, - { - name: 'readOnly'; - docs: [ - 'Placeholder to mark accounts read-only unimplemented set to false.', - ]; - type: 'bool'; - }, - ]; - }; - }, - { - name: 'PackedMerkleContext'; - type: { - kind: 'struct'; - fields: [ - { - name: 'merkleTreePubkeyIndex'; - type: 'u8'; - }, - { - name: 'nullifierQueuePubkeyIndex'; - type: 'u8'; - }, - { - name: 'leafIndex'; - type: 'u32'; - }, - { - name: 'queueIndex'; - type: { - option: { - defined: 'QueueIndex'; - }; - }; - }, - ]; - }; - }, - { - name: 'PackedTokenTransferOutputData'; - type: { - kind: 'struct'; - fields: [ - { - name: 'owner'; - type: 'publicKey'; - }, - { - name: 'amount'; - type: 'u64'; - }, - { - name: 'lamports'; - type: { - option: 'u64'; - }; - }, - { - name: 'merkleTreeIndex'; - type: 'u8'; - }, - { - name: 'tlv'; - docs: [ - 'Placeholder for TokenExtension tlv data (unimplemented)', - ]; - type: { - option: 'bytes'; - }; - }, - ]; - }; - }, - { - name: 'PublicTransactionEvent'; - type: { - kind: 'struct'; - fields: [ - { - name: 'inputCompressedAccountHashes'; - type: { - vec: { - array: ['u8', 32]; - }; - }; - }, - { - name: 'outputCompressedAccountHashes'; - type: { - vec: { - array: ['u8', 32]; - }; - }; - }, - { - name: 'outputCompressedAccounts'; - type: { - vec: { - defined: 'OutputCompressedAccountWithPackedContext'; - }; - }; - }, - { - name: 'outputLeafIndices'; - type: { - vec: 'u32'; - }; - }, - { - name: 'sequenceNumbers'; - type: { - vec: { - defined: 'MerkleTreeSequenceNumber'; - }; - }; - }, - { - name: 'relayFee'; - type: { - option: 'u64'; - }; - }, - { - name: 'isCompress'; - type: 'bool'; - }, - { - name: 'compressOrDecompressLamports'; - type: { - option: 'u64'; - }; - }, - { - name: 'pubkeyArray'; - type: { - vec: 'publicKey'; - }; - }, - { - name: 'message'; - type: { - option: 'bytes'; - }; - }, - ]; - }; - }, - { - name: 'QueueIndex'; - type: { - kind: 'struct'; - fields: [ - { - name: 'queueId'; - docs: ['Id of queue in queue account.']; - type: 'u8'; - }, - { - name: 'index'; - docs: ['Index of compressed account hash in queue.']; - type: 'u16'; - }, - ]; - }; - }, - { - name: 'TokenData'; - type: { - kind: 'struct'; - fields: [ - { - name: 'mint'; - docs: ['The mint associated with this account']; - type: 'publicKey'; - }, - { - name: 'owner'; - docs: ['The owner of this account.']; - type: 'publicKey'; - }, - { - name: 'amount'; - docs: ['The amount of tokens this account holds.']; - type: 'u64'; - }, - { - name: 'delegate'; - docs: [ - 'If `delegate` is `Some` then `delegated_amount` represents', - 'the amount authorized by the delegate', - ]; - type: { - option: 'publicKey'; - }; - }, - { - name: 'state'; - docs: ["The account's state"]; - type: { - defined: 'AccountState'; - }; - }, - { - name: 'tlv'; - docs: [ - 'Placeholder for TokenExtension tlv data (unimplemented)', - ]; - type: { - option: 'bytes'; - }; - }, - ]; - }; - }, - ]; - errors: [ - { - code: 6000; - name: 'PublicKeyAmountMissmatch'; - msg: 'public keys and amounts must be of same length'; - }, - { - code: 6001; - name: 'ComputeInputSumFailed'; - msg: 'ComputeInputSumFailed'; - }, - { - code: 6002; - name: 'ComputeOutputSumFailed'; - msg: 'ComputeOutputSumFailed'; - }, - { - code: 6003; - name: 'ComputeCompressSumFailed'; - msg: 'ComputeCompressSumFailed'; - }, - { - code: 6004; - name: 'ComputeDecompressSumFailed'; - msg: 'ComputeDecompressSumFailed'; - }, - { - code: 6005; - name: 'SumCheckFailed'; - msg: 'SumCheckFailed'; - }, - { - code: 6006; - name: 'DecompressRecipientUndefinedForDecompress'; - msg: 'DecompressRecipientUndefinedForDecompress'; - }, - { - code: 6007; - name: 'CompressedPdaUndefinedForDecompress'; - msg: 'CompressedPdaUndefinedForDecompress'; - }, - { - code: 6008; - name: 'DeCompressAmountUndefinedForDecompress'; - msg: 'DeCompressAmountUndefinedForDecompress'; - }, - { - code: 6009; - name: 'CompressedPdaUndefinedForCompress'; - msg: 'CompressedPdaUndefinedForCompress'; - }, - { - code: 6010; - name: 'DeCompressAmountUndefinedForCompress'; - msg: 'DeCompressAmountUndefinedForCompress'; - }, - { - code: 6011; - name: 'DelegateSignerCheckFailed'; - msg: 'DelegateSignerCheckFailed'; - }, - { - code: 6012; - name: 'MintTooLarge'; - msg: 'Minted amount greater than u64::MAX'; - }, - { - code: 6013; - name: 'SplTokenSupplyMismatch'; - msg: 'SplTokenSupplyMismatch'; - }, - { - code: 6014; - name: 'HeapMemoryCheckFailed'; - msg: 'HeapMemoryCheckFailed'; - }, - { - code: 6015; - name: 'InstructionNotCallable'; - msg: 'The instruction is not callable'; - }, - { - code: 6016; - name: 'ArithmeticUnderflow'; - msg: 'ArithmeticUnderflow'; - }, - { - code: 6017; - name: 'HashToFieldError'; - msg: 'HashToFieldError'; - }, - { - code: 6018; - name: 'InvalidAuthorityMint'; - msg: 'Expected the authority to be also a mint authority'; - }, - { - code: 6019; - name: 'InvalidFreezeAuthority'; - msg: 'Provided authority is not the freeze authority'; - }, - { - code: 6020; - name: 'InvalidDelegateIndex'; - }, - { - code: 6021; - name: 'TokenPoolPdaUndefined'; - }, - { - code: 6022; - name: 'IsTokenPoolPda'; - msg: 'Compress or decompress recipient is the same account as the token pool pda.'; - }, - { - code: 6023; - name: 'InvalidTokenPoolPda'; - }, - { - code: 6024; - name: 'NoInputTokenAccountsProvided'; - }, - { - code: 6025; - name: 'NoInputsProvided'; - }, - { - code: 6026; - name: 'MintHasNoFreezeAuthority'; - }, - { - code: 6027; - name: 'MintWithInvalidExtension'; - }, - { - code: 6028; - name: 'InsufficientTokenAccountBalance'; - msg: 'The token account balance is less than the remaining amount.'; - }, - { - code: 6029; - name: 'InvalidTokenPoolBump'; - msg: 'Max number of token pools reached.'; - }, - { - code: 6030; - name: 'FailedToDecompress'; - }, - { - code: 6031; - name: 'FailedToBurnSplTokensFromTokenPool'; - }, - { - code: 6032; - name: 'NoMatchingBumpFound'; - }, - ]; -}; -export const IDL: LightCompressedToken = { - version: '1.2.0', - name: 'light_compressed_token', - instructions: [ - { - name: 'createTokenPool', - docs: [ - 'This instruction creates a token pool for a given mint. Every spl mint', - 'can have one token pool. When a token is compressed the tokens are', - 'transferrred to the token pool, and their compressed equivalent is', - 'minted into a Merkle tree.', - ], - accounts: [ - { - name: 'feePayer', - isMut: true, - isSigner: true, - docs: ['UNCHECKED: only pays fees.'], - }, - { - name: 'tokenPoolPda', - isMut: true, - isSigner: false, - }, - { - name: 'systemProgram', - isMut: false, - isSigner: false, - }, - { - name: 'mint', - isMut: true, - isSigner: false, - }, - { - name: 'tokenProgram', - isMut: false, - isSigner: false, - }, - { - name: 'cpiAuthorityPda', - isMut: false, - isSigner: false, - }, - ], - args: [], - }, - { - name: 'addTokenPool', - docs: [ - 'This instruction creates an additional token pool for a given mint.', - 'The maximum number of token pools per mint is 5.', - ], - accounts: [ - { - name: 'feePayer', - isMut: true, - isSigner: true, - docs: ['UNCHECKED: only pays fees.'], - }, - { - name: 'tokenPoolPda', - isMut: true, - isSigner: false, - }, - { - name: 'existingTokenPoolPda', - isMut: false, - isSigner: false, - }, - { - name: 'systemProgram', - isMut: false, - isSigner: false, - }, - { - name: 'mint', - isMut: true, - isSigner: false, - }, - { - name: 'tokenProgram', - isMut: false, - isSigner: false, - }, - { - name: 'cpiAuthorityPda', - isMut: false, - isSigner: false, - }, - ], - args: [ - { - name: 'tokenPoolBump', - type: 'u8', - }, - ], - }, - { - name: 'mintTo', - docs: [ - 'Mints tokens from an spl token mint to a list of compressed accounts.', - 'Minted tokens are transferred to a pool account owned by the compressed', - 'token program. The instruction creates one compressed output account for', - 'every amount and pubkey input pair. A constant amount of lamports can be', - 'transferred to each output account to enable. A use case to add lamports', - 'to a compressed token account is to prevent spam. This is the only way', - 'to add lamports to a compressed token account.', - ], - accounts: [ - { - name: 'feePayer', - isMut: true, - isSigner: true, - docs: ['UNCHECKED: only pays fees.'], - }, - { - name: 'authority', - isMut: false, - isSigner: true, - }, - { - name: 'cpiAuthorityPda', - isMut: false, - isSigner: false, - }, - { - name: 'mint', - isMut: true, - isSigner: false, - }, - { - name: 'tokenPoolPda', - isMut: true, - isSigner: false, - }, - { - name: 'tokenProgram', - isMut: false, - isSigner: false, - }, - { - name: 'lightSystemProgram', - isMut: false, - isSigner: false, - }, - { - name: 'registeredProgramPda', - isMut: false, - isSigner: false, - }, - { - name: 'noopProgram', - isMut: false, - isSigner: false, - docs: ['programs'], - }, - { - name: 'accountCompressionAuthority', - isMut: false, - isSigner: false, - }, - { - name: 'accountCompressionProgram', - isMut: false, - isSigner: false, - }, - { - name: 'merkleTree', - isMut: true, - isSigner: false, - }, - { - name: 'selfProgram', - isMut: false, - isSigner: false, - }, - { - name: 'systemProgram', - isMut: false, - isSigner: false, - }, - { - name: 'solPoolPda', - isMut: true, - isSigner: false, - isOptional: true, - }, - ], - args: [ - { - name: 'publicKeys', - type: { - vec: 'publicKey', - }, - }, - { - name: 'amounts', - type: { - vec: 'u64', - }, - }, - { - name: 'lamports', - type: { - option: 'u64', - }, - }, - ], - }, - { - name: 'compressSplTokenAccount', - docs: [ - 'Compresses the balance of an spl token account sub an optional remaining', - 'amount. This instruction does not close the spl token account. To close', - 'the account bundle a close spl account instruction in your transaction.', - ], - accounts: [ - { - name: 'feePayer', - isMut: true, - isSigner: true, - docs: ['UNCHECKED: only pays fees.'], - }, - { - name: 'authority', - isMut: false, - isSigner: true, - docs: [ - 'Authority is verified through proof since both owner and delegate', - 'are included in the token data hash, which is a public input to the', - 'validity proof.', - ], - }, - { - name: 'cpiAuthorityPda', - isMut: false, - isSigner: false, - }, - { - name: 'lightSystemProgram', - isMut: false, - isSigner: false, - }, - { - name: 'registeredProgramPda', - isMut: false, - isSigner: false, - }, - { - name: 'noopProgram', - isMut: false, - isSigner: false, - }, - { - name: 'accountCompressionAuthority', - isMut: false, - isSigner: false, - }, - { - name: 'accountCompressionProgram', - isMut: false, - isSigner: false, - }, - { - name: 'selfProgram', - isMut: false, - isSigner: false, - docs: ['this program is the signer of the cpi.'], - }, - { - name: 'tokenPoolPda', - isMut: true, - isSigner: false, - isOptional: true, - }, - { - name: 'compressOrDecompressTokenAccount', - isMut: true, - isSigner: false, - isOptional: true, - }, - { - name: 'tokenProgram', - isMut: false, - isSigner: false, - isOptional: true, - }, - { - name: 'systemProgram', - isMut: false, - isSigner: false, - }, - ], - args: [ - { - name: 'owner', - type: 'publicKey', - }, - { - name: 'remainingAmount', - type: { - option: 'u64', - }, - }, - { - name: 'cpiContext', - type: { - option: { - defined: 'CompressedCpiContext', - }, - }, - }, - ], - }, - { - name: 'transfer', - docs: [ - 'Transfers compressed tokens from one account to another. All accounts', - 'must be of the same mint. Additional spl tokens can be compressed or', - 'decompressed. In one transaction only compression or decompression is', - 'possible. Lamports can be transferred alongside tokens. If output token', - 'accounts specify less lamports than inputs the remaining lamports are', - 'transferred to an output compressed account. Signer must be owner or', - 'delegate. If a delegated token account is transferred the delegate is', - 'not preserved.', - ], - accounts: [ - { - name: 'feePayer', - isMut: true, - isSigner: true, - docs: ['UNCHECKED: only pays fees.'], - }, - { - name: 'authority', - isMut: false, - isSigner: true, - docs: [ - 'Authority is verified through proof since both owner and delegate', - 'are included in the token data hash, which is a public input to the', - 'validity proof.', - ], - }, - { - name: 'cpiAuthorityPda', - isMut: false, - isSigner: false, - }, - { - name: 'lightSystemProgram', - isMut: false, - isSigner: false, - }, - { - name: 'registeredProgramPda', - isMut: false, - isSigner: false, - }, - { - name: 'noopProgram', - isMut: false, - isSigner: false, - }, - { - name: 'accountCompressionAuthority', - isMut: false, - isSigner: false, - }, - { - name: 'accountCompressionProgram', - isMut: false, - isSigner: false, - }, - { - name: 'selfProgram', - isMut: false, - isSigner: false, - docs: ['this program is the signer of the cpi.'], - }, - { - name: 'tokenPoolPda', - isMut: true, - isSigner: false, - isOptional: true, - }, - { - name: 'compressOrDecompressTokenAccount', - isMut: true, - isSigner: false, - isOptional: true, - }, - { - name: 'tokenProgram', - isMut: false, - isSigner: false, - isOptional: true, - }, - { - name: 'systemProgram', - isMut: false, - isSigner: false, - }, - ], - args: [ - { - name: 'inputs', - type: 'bytes', - }, - ], - }, - { - name: 'approve', - docs: [ - 'Delegates an amount to a delegate. A compressed token account is either', - 'completely delegated or not. Prior delegates are not preserved. Cannot', - 'be called by a delegate.', - 'The instruction creates two output accounts:', - '1. one account with delegated amount', - '2. one account with remaining(change) amount', - ], - accounts: [ - { - name: 'feePayer', - isMut: true, - isSigner: true, - docs: ['UNCHECKED: only pays fees.'], - }, - { - name: 'authority', - isMut: false, - isSigner: true, - docs: [ - 'Authority is verified through proof since both owner and delegate', - 'are included in the token data hash, which is a public input to the', - 'validity proof.', - ], - }, - { - name: 'cpiAuthorityPda', - isMut: false, - isSigner: false, - }, - { - name: 'lightSystemProgram', - isMut: false, - isSigner: false, - }, - { - name: 'registeredProgramPda', - isMut: false, - isSigner: false, - }, - { - name: 'noopProgram', - isMut: false, - isSigner: false, - }, - { - name: 'accountCompressionAuthority', - isMut: false, - isSigner: false, - }, - { - name: 'accountCompressionProgram', - isMut: false, - isSigner: false, - }, - { - name: 'selfProgram', - isMut: false, - isSigner: false, - docs: ['this program is the signer of the cpi.'], - }, - { - name: 'systemProgram', - isMut: false, - isSigner: false, - }, - ], - args: [ - { - name: 'inputs', - type: 'bytes', - }, - ], - }, - { - name: 'revoke', - docs: [ - 'Revokes a delegation. The instruction merges all inputs into one output', - 'account. Cannot be called by a delegate. Delegates are not preserved.', - ], - accounts: [ - { - name: 'feePayer', - isMut: true, - isSigner: true, - docs: ['UNCHECKED: only pays fees.'], - }, - { - name: 'authority', - isMut: false, - isSigner: true, - docs: [ - 'Authority is verified through proof since both owner and delegate', - 'are included in the token data hash, which is a public input to the', - 'validity proof.', - ], - }, - { - name: 'cpiAuthorityPda', - isMut: false, - isSigner: false, - }, - { - name: 'lightSystemProgram', - isMut: false, - isSigner: false, - }, - { - name: 'registeredProgramPda', - isMut: false, - isSigner: false, - }, - { - name: 'noopProgram', - isMut: false, - isSigner: false, - }, - { - name: 'accountCompressionAuthority', - isMut: false, - isSigner: false, - }, - { - name: 'accountCompressionProgram', - isMut: false, - isSigner: false, - }, - { - name: 'selfProgram', - isMut: false, - isSigner: false, - docs: ['this program is the signer of the cpi.'], - }, - { - name: 'systemProgram', - isMut: false, - isSigner: false, - }, - ], - args: [ - { - name: 'inputs', - type: 'bytes', - }, - ], - }, - { - name: 'freeze', - docs: [ - 'Freezes compressed token accounts. Inputs must not be frozen. Creates as', - 'many outputs as inputs. Balances and delegates are preserved.', - ], - accounts: [ - { - name: 'feePayer', - isMut: true, - isSigner: true, - docs: ['UNCHECKED: only pays fees.'], - }, - { - name: 'authority', - isMut: false, - isSigner: true, - }, - { - name: 'cpiAuthorityPda', - isMut: false, - isSigner: false, - }, - { - name: 'lightSystemProgram', - isMut: false, - isSigner: false, - }, - { - name: 'registeredProgramPda', - isMut: false, - isSigner: false, - }, - { - name: 'noopProgram', - isMut: false, - isSigner: false, - }, - { - name: 'accountCompressionAuthority', - isMut: false, - isSigner: false, - }, - { - name: 'accountCompressionProgram', - isMut: false, - isSigner: false, - }, - { - name: 'selfProgram', - isMut: false, - isSigner: false, - docs: ['that this program is the signer of the cpi.'], - }, - { - name: 'systemProgram', - isMut: false, - isSigner: false, - }, - { - name: 'mint', - isMut: false, - isSigner: false, - }, - ], - args: [ - { - name: 'inputs', - type: 'bytes', - }, - ], - }, - { - name: 'thaw', - docs: [ - 'Thaws frozen compressed token accounts. Inputs must be frozen. Creates', - 'as many outputs as inputs. Balances and delegates are preserved.', - ], - accounts: [ - { - name: 'feePayer', - isMut: true, - isSigner: true, - docs: ['UNCHECKED: only pays fees.'], - }, - { - name: 'authority', - isMut: false, - isSigner: true, - }, - { - name: 'cpiAuthorityPda', - isMut: false, - isSigner: false, - }, - { - name: 'lightSystemProgram', - isMut: false, - isSigner: false, - }, - { - name: 'registeredProgramPda', - isMut: false, - isSigner: false, - }, - { - name: 'noopProgram', - isMut: false, - isSigner: false, - }, - { - name: 'accountCompressionAuthority', - isMut: false, - isSigner: false, - }, - { - name: 'accountCompressionProgram', - isMut: false, - isSigner: false, - }, - { - name: 'selfProgram', - isMut: false, - isSigner: false, - docs: ['that this program is the signer of the cpi.'], - }, - { - name: 'systemProgram', - isMut: false, - isSigner: false, - }, - { - name: 'mint', - isMut: false, - isSigner: false, - }, - ], - args: [ - { - name: 'inputs', - type: 'bytes', - }, - ], - }, - { - name: 'burn', - docs: [ - 'Burns compressed tokens and spl tokens from the pool account. Delegates', - 'can burn tokens. The output compressed token account remains delegated.', - 'Creates one output compressed token account.', - ], - accounts: [ - { - name: 'feePayer', - isMut: true, - isSigner: true, - docs: ['UNCHECKED: only pays fees.'], - }, - { - name: 'authority', - isMut: false, - isSigner: true, - docs: [ - 'Authority is verified through proof since both owner and delegate', - 'are included in the token data hash, which is a public input to the', - 'validity proof.', - ], - }, - { - name: 'cpiAuthorityPda', - isMut: false, - isSigner: false, - }, - { - name: 'mint', - isMut: true, - isSigner: false, - }, - { - name: 'tokenPoolPda', - isMut: true, - isSigner: false, - }, - { - name: 'tokenProgram', - isMut: false, - isSigner: false, - }, - { - name: 'lightSystemProgram', - isMut: false, - isSigner: false, - }, - { - name: 'registeredProgramPda', - isMut: false, - isSigner: false, - }, - { - name: 'noopProgram', - isMut: false, - isSigner: false, - }, - { - name: 'accountCompressionAuthority', - isMut: false, - isSigner: false, - }, - { - name: 'accountCompressionProgram', - isMut: false, - isSigner: false, - }, - { - name: 'selfProgram', - isMut: false, - isSigner: false, - }, - { - name: 'systemProgram', - isMut: false, - isSigner: false, - }, - ], - args: [ - { - name: 'inputs', - type: 'bytes', - }, - ], - }, - { - name: 'stubIdlBuild', - docs: [ - 'This function is a stub to allow Anchor to include the input types in', - 'the IDL. It should not be included in production builds nor be called in', - 'practice.', - ], - accounts: [ - { - name: 'feePayer', - isMut: true, - isSigner: true, - docs: ['UNCHECKED: only pays fees.'], - }, - { - name: 'authority', - isMut: false, - isSigner: true, - docs: [ - 'Authority is verified through proof since both owner and delegate', - 'are included in the token data hash, which is a public input to the', - 'validity proof.', - ], - }, - { - name: 'cpiAuthorityPda', - isMut: false, - isSigner: false, - }, - { - name: 'lightSystemProgram', - isMut: false, - isSigner: false, - }, - { - name: 'registeredProgramPda', - isMut: false, - isSigner: false, - }, - { - name: 'noopProgram', - isMut: false, - isSigner: false, - }, - { - name: 'accountCompressionAuthority', - isMut: false, - isSigner: false, - }, - { - name: 'accountCompressionProgram', - isMut: false, - isSigner: false, - }, - { - name: 'selfProgram', - isMut: false, - isSigner: false, - docs: ['this program is the signer of the cpi.'], - }, - { - name: 'tokenPoolPda', - isMut: true, - isSigner: false, - isOptional: true, - }, - { - name: 'compressOrDecompressTokenAccount', - isMut: true, - isSigner: false, - isOptional: true, - }, - { - name: 'tokenProgram', - isMut: false, - isSigner: false, - isOptional: true, - }, - { - name: 'systemProgram', - isMut: false, - isSigner: false, - }, - ], - args: [ - { - name: 'inputs1', - type: { - defined: 'CompressedTokenInstructionDataTransfer', - }, - }, - { - name: 'inputs2', - type: { - defined: 'TokenData', - }, - }, - ], - }, - ], - types: [ - { - name: 'AccountState', - type: { - kind: 'enum', - variants: [ - { - name: 'Initialized', - }, - { - name: 'Frozen', - }, - ], - }, - }, - { - name: 'CompressedAccount', - type: { - kind: 'struct', - fields: [ - { - name: 'owner', - type: 'publicKey', - }, - { - name: 'lamports', - type: 'u64', - }, - { - name: 'address', - type: { - option: { - array: ['u8', 32], - }, - }, - }, - { - name: 'data', - type: { - option: { - defined: 'CompressedAccountData', - }, - }, - }, - ], - }, - }, - { - name: 'CompressedAccountData', - type: { - kind: 'struct', - fields: [ - { - name: 'discriminator', - type: { - array: ['u8', 8], - }, - }, - { - name: 'data', - type: 'bytes', - }, - { - name: 'dataHash', - type: { - array: ['u8', 32], - }, - }, - ], - }, - }, - { - name: 'CompressedCpiContext', - type: { - kind: 'struct', - fields: [ - { - name: 'setContext', - docs: [ - 'Is set by the program that is invoking the CPI to signal that is should', - 'set the cpi context.', - ], - type: 'bool', - }, - { - name: 'firstSetContext', - docs: [ - 'Is set to wipe the cpi context since someone could have set it before', - 'with unrelated data.', - ], - type: 'bool', - }, - { - name: 'cpiContextAccountIndex', - docs: [ - 'Index of cpi context account in remaining accounts.', - ], - type: 'u8', - }, - ], - }, - }, - { - name: 'CompressedProof', - type: { - kind: 'struct', - fields: [ - { - name: 'a', - type: { - array: ['u8', 32], - }, - }, - { - name: 'b', - type: { - array: ['u8', 64], - }, - }, - { - name: 'c', - type: { - array: ['u8', 32], - }, - }, - ], - }, - }, - { - name: 'CompressedTokenInstructionDataTransfer', - type: { - kind: 'struct', - fields: [ - { - name: 'proof', - type: { - option: { - defined: 'CompressedProof', - }, - }, - }, - { - name: 'mint', - type: 'publicKey', - }, - { - name: 'delegatedTransfer', - docs: [ - 'Is required if the signer is delegate,', - '-> delegate is authority account,', - 'owner = Some(owner) is the owner of the token account.', - ], - type: { - option: { - defined: 'DelegatedTransfer', - }, - }, - }, - { - name: 'inputTokenDataWithContext', - type: { - vec: { - defined: 'InputTokenDataWithContext', - }, - }, - }, - { - name: 'outputCompressedAccounts', - type: { - vec: { - defined: 'PackedTokenTransferOutputData', - }, - }, - }, - { - name: 'isCompress', - type: 'bool', - }, - { - name: 'compressOrDecompressAmount', - type: { - option: 'u64', - }, - }, - { - name: 'cpiContext', - type: { - option: { - defined: 'CompressedCpiContext', - }, - }, - }, - { - name: 'lamportsChangeAccountMerkleTreeIndex', - type: { - option: 'u8', - }, - }, - ], - }, - }, - { - name: 'DelegatedTransfer', - docs: [ - 'Struct to provide the owner when the delegate is signer of the transaction.', - ], - type: { - kind: 'struct', - fields: [ - { - name: 'owner', - type: 'publicKey', - }, - { - name: 'delegateChangeAccountIndex', - docs: [ - 'Index of change compressed account in output compressed accounts. In', - "case that the delegate didn't spend the complete delegated compressed", - 'account balance the change compressed account will be delegated to her', - 'as well.', - ], - type: { - option: 'u8', - }, - }, - ], - }, - }, - { - name: 'InputTokenDataWithContext', - type: { - kind: 'struct', - fields: [ - { - name: 'amount', - type: 'u64', - }, - { - name: 'delegateIndex', - type: { - option: 'u8', - }, - }, - { - name: 'merkleContext', - type: { - defined: 'PackedMerkleContext', - }, - }, - { - name: 'rootIndex', - type: 'u16', - }, - { - name: 'lamports', - type: { - option: 'u64', - }, - }, - { - name: 'tlv', - docs: [ - 'Placeholder for TokenExtension tlv data (unimplemented)', - ], - type: { - option: 'bytes', - }, - }, - ], - }, - }, - { - name: 'InstructionDataInvoke', - type: { - kind: 'struct', - fields: [ - { - name: 'proof', - type: { - option: { - defined: 'CompressedProof', - }, - }, - }, - { - name: 'inputCompressedAccountsWithMerkleContext', - type: { - vec: { - defined: - 'PackedCompressedAccountWithMerkleContext', - }, - }, - }, - { - name: 'outputCompressedAccounts', - type: { - vec: { - defined: - 'OutputCompressedAccountWithPackedContext', - }, - }, - }, - { - name: 'relayFee', - type: { - option: 'u64', - }, - }, - { - name: 'newAddressParams', - type: { - vec: { - defined: 'NewAddressParamsPacked', - }, - }, - }, - { - name: 'compressOrDecompressLamports', - type: { - option: 'u64', - }, - }, - { - name: 'isCompress', - type: 'bool', - }, - ], - }, - }, - { - name: 'InstructionDataInvokeCpi', - type: { - kind: 'struct', - fields: [ - { - name: 'proof', - type: { - option: { - defined: 'CompressedProof', - }, - }, - }, - { - name: 'newAddressParams', - type: { - vec: { - defined: 'NewAddressParamsPacked', - }, - }, - }, - { - name: 'inputCompressedAccountsWithMerkleContext', - type: { - vec: { - defined: - 'PackedCompressedAccountWithMerkleContext', - }, - }, - }, - { - name: 'outputCompressedAccounts', - type: { - vec: { - defined: - 'OutputCompressedAccountWithPackedContext', - }, - }, - }, - { - name: 'relayFee', - type: { - option: 'u64', - }, - }, - { - name: 'compressOrDecompressLamports', - type: { - option: 'u64', - }, - }, - { - name: 'isCompress', - type: 'bool', - }, - { - name: 'cpiContext', - type: { - option: { - defined: 'CompressedCpiContext', - }, - }, - }, - ], - }, - }, - { - name: 'MerkleTreeSequenceNumber', - type: { - kind: 'struct', - fields: [ - { - name: 'pubkey', - type: 'publicKey', - }, - { - name: 'seq', - type: 'u64', - }, - ], - }, - }, - { - name: 'NewAddressParamsPacked', - type: { - kind: 'struct', - fields: [ - { - name: 'seed', - type: { - array: ['u8', 32], - }, - }, - { - name: 'addressQueueAccountIndex', - type: 'u8', - }, - { - name: 'addressMerkleTreeAccountIndex', - type: 'u8', - }, - { - name: 'addressMerkleTreeRootIndex', - type: 'u16', - }, - ], - }, - }, - { - name: 'OutputCompressedAccountWithPackedContext', - type: { - kind: 'struct', - fields: [ - { - name: 'compressedAccount', - type: { - defined: 'CompressedAccount', - }, - }, - { - name: 'merkleTreeIndex', - type: 'u8', - }, - ], - }, - }, - { - name: 'PackedCompressedAccountWithMerkleContext', - type: { - kind: 'struct', - fields: [ - { - name: 'compressedAccount', - type: { - defined: 'CompressedAccount', - }, - }, - { - name: 'merkleContext', - type: { - defined: 'PackedMerkleContext', - }, - }, - { - name: 'rootIndex', - docs: [ - 'Index of root used in inclusion validity proof.', - ], - type: 'u16', - }, - { - name: 'readOnly', - docs: [ - 'Placeholder to mark accounts read-only unimplemented set to false.', - ], - type: 'bool', - }, - ], - }, - }, - { - name: 'PackedMerkleContext', - type: { - kind: 'struct', - fields: [ - { - name: 'merkleTreePubkeyIndex', - type: 'u8', - }, - { - name: 'nullifierQueuePubkeyIndex', - type: 'u8', - }, - { - name: 'leafIndex', - type: 'u32', - }, - { - name: 'queueIndex', - type: { - option: { - defined: 'QueueIndex', - }, - }, - }, - ], - }, - }, - { - name: 'PackedTokenTransferOutputData', - type: { - kind: 'struct', - fields: [ - { - name: 'owner', - type: 'publicKey', - }, - { - name: 'amount', - type: 'u64', - }, - { - name: 'lamports', - type: { - option: 'u64', - }, - }, - { - name: 'merkleTreeIndex', - type: 'u8', - }, - { - name: 'tlv', - docs: [ - 'Placeholder for TokenExtension tlv data (unimplemented)', - ], - type: { - option: 'bytes', - }, - }, - ], - }, - }, - { - name: 'PublicTransactionEvent', - type: { - kind: 'struct', - fields: [ - { - name: 'inputCompressedAccountHashes', - type: { - vec: { - array: ['u8', 32], - }, - }, - }, - { - name: 'outputCompressedAccountHashes', - type: { - vec: { - array: ['u8', 32], - }, - }, - }, - { - name: 'outputCompressedAccounts', - type: { - vec: { - defined: - 'OutputCompressedAccountWithPackedContext', - }, - }, - }, - { - name: 'outputLeafIndices', - type: { - vec: 'u32', - }, - }, - { - name: 'sequenceNumbers', - type: { - vec: { - defined: 'MerkleTreeSequenceNumber', - }, - }, - }, - { - name: 'relayFee', - type: { - option: 'u64', - }, - }, - { - name: 'isCompress', - type: 'bool', - }, - { - name: 'compressOrDecompressLamports', - type: { - option: 'u64', - }, - }, - { - name: 'pubkeyArray', - type: { - vec: 'publicKey', - }, - }, - { - name: 'message', - type: { - option: 'bytes', - }, - }, - ], - }, - }, - { - name: 'QueueIndex', - type: { - kind: 'struct', - fields: [ - { - name: 'queueId', - docs: ['Id of queue in queue account.'], - type: 'u8', - }, - { - name: 'index', - docs: ['Index of compressed account hash in queue.'], - type: 'u16', - }, - ], - }, - }, - { - name: 'TokenData', - type: { - kind: 'struct', - fields: [ - { - name: 'mint', - docs: ['The mint associated with this account'], - type: 'publicKey', - }, - { - name: 'owner', - docs: ['The owner of this account.'], - type: 'publicKey', - }, - { - name: 'amount', - docs: ['The amount of tokens this account holds.'], - type: 'u64', - }, - { - name: 'delegate', - docs: [ - 'If `delegate` is `Some` then `delegated_amount` represents', - 'the amount authorized by the delegate', - ], - type: { - option: 'publicKey', - }, - }, - { - name: 'state', - docs: ["The account's state"], - type: { - defined: 'AccountState', - }, - }, - { - name: 'tlv', - docs: [ - 'Placeholder for TokenExtension tlv data (unimplemented)', - ], - type: { - option: 'bytes', - }, - }, - ], - }, - }, - ], - errors: [ - { - code: 6000, - name: 'PublicKeyAmountMissmatch', - msg: 'public keys and amounts must be of same length', - }, - { - code: 6001, - name: 'ComputeInputSumFailed', - msg: 'ComputeInputSumFailed', - }, - { - code: 6002, - name: 'ComputeOutputSumFailed', - msg: 'ComputeOutputSumFailed', - }, - { - code: 6003, - name: 'ComputeCompressSumFailed', - msg: 'ComputeCompressSumFailed', - }, - { - code: 6004, - name: 'ComputeDecompressSumFailed', - msg: 'ComputeDecompressSumFailed', - }, - { - code: 6005, - name: 'SumCheckFailed', - msg: 'SumCheckFailed', - }, - { - code: 6006, - name: 'DecompressRecipientUndefinedForDecompress', - msg: 'DecompressRecipientUndefinedForDecompress', - }, - { - code: 6007, - name: 'CompressedPdaUndefinedForDecompress', - msg: 'CompressedPdaUndefinedForDecompress', - }, - { - code: 6008, - name: 'DeCompressAmountUndefinedForDecompress', - msg: 'DeCompressAmountUndefinedForDecompress', - }, - { - code: 6009, - name: 'CompressedPdaUndefinedForCompress', - msg: 'CompressedPdaUndefinedForCompress', - }, - { - code: 6010, - name: 'DeCompressAmountUndefinedForCompress', - msg: 'DeCompressAmountUndefinedForCompress', - }, - { - code: 6011, - name: 'DelegateSignerCheckFailed', - msg: 'DelegateSignerCheckFailed', - }, - { - code: 6012, - name: 'MintTooLarge', - msg: 'Minted amount greater than u64::MAX', - }, - { - code: 6013, - name: 'SplTokenSupplyMismatch', - msg: 'SplTokenSupplyMismatch', - }, - { - code: 6014, - name: 'HeapMemoryCheckFailed', - msg: 'HeapMemoryCheckFailed', - }, - { - code: 6015, - name: 'InstructionNotCallable', - msg: 'The instruction is not callable', - }, - { - code: 6016, - name: 'ArithmeticUnderflow', - msg: 'ArithmeticUnderflow', - }, - { - code: 6017, - name: 'HashToFieldError', - msg: 'HashToFieldError', - }, - { - code: 6018, - name: 'InvalidAuthorityMint', - msg: 'Expected the authority to be also a mint authority', - }, - { - code: 6019, - name: 'InvalidFreezeAuthority', - msg: 'Provided authority is not the freeze authority', - }, - { - code: 6020, - name: 'InvalidDelegateIndex', - }, - { - code: 6021, - name: 'TokenPoolPdaUndefined', - }, - { - code: 6022, - name: 'IsTokenPoolPda', - msg: 'Compress or decompress recipient is the same account as the token pool pda.', - }, - { - code: 6023, - name: 'InvalidTokenPoolPda', - }, - { - code: 6024, - name: 'NoInputTokenAccountsProvided', - }, - { - code: 6025, - name: 'NoInputsProvided', - }, - { - code: 6026, - name: 'MintHasNoFreezeAuthority', - }, - { - code: 6027, - name: 'MintWithInvalidExtension', - }, - { - code: 6028, - name: 'InsufficientTokenAccountBalance', - msg: 'The token account balance is less than the remaining amount.', - }, - { - code: 6029, - name: 'InvalidTokenPoolBump', - msg: 'Max number of token pools reached.', - }, - { - code: 6030, - name: 'FailedToDecompress', - }, - { - code: 6031, - name: 'FailedToBurnSplTokensFromTokenPool', - }, - { - code: 6032, - name: 'NoMatchingBumpFound', - }, - ], -}; diff --git a/js/stateless.js/src/idls/light_registry.ts b/js/stateless.js/src/idls/light_registry.ts deleted file mode 100644 index 05d9e23e78..0000000000 --- a/js/stateless.js/src/idls/light_registry.ts +++ /dev/null @@ -1,3483 +0,0 @@ -export type LightRegistry = { - version: '1.2.0'; - name: 'light_registry'; - constants: [ - { - name: 'FORESTER_SEED'; - type: 'bytes'; - value: '[102, 111, 114, 101, 115, 116, 101, 114]'; - }, - { - name: 'FORESTER_EPOCH_SEED'; - type: 'bytes'; - value: '[102, 111, 114, 101, 115, 116, 101, 114, 95, 101, 112, 111, 99, 104]'; - }, - { - name: 'PROTOCOL_CONFIG_PDA_SEED'; - type: 'bytes'; - value: '[97, 117, 116, 104, 111, 114, 105, 116, 121]'; - }, - { - name: 'DEFAULT_WORK_V1'; - type: 'u64'; - value: '1'; - }, - ]; - instructions: [ - { - name: 'initializeProtocolConfig'; - docs: [ - 'Initializes the protocol config pda. Can only be called once by the', - 'program account keypair.', - ]; - accounts: [ - { - name: 'feePayer'; - isMut: true; - isSigner: true; - }, - { - name: 'authority'; - isMut: false; - isSigner: true; - }, - { - name: 'protocolConfigPda'; - isMut: true; - isSigner: false; - }, - { - name: 'systemProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'selfProgram'; - isMut: false; - isSigner: false; - }, - ]; - args: [ - { - name: 'bump'; - type: 'u8'; - }, - { - name: 'protocolConfig'; - type: { - defined: 'ProtocolConfig'; - }; - }, - ]; - }, - { - name: 'updateProtocolConfig'; - accounts: [ - { - name: 'feePayer'; - isMut: false; - isSigner: true; - }, - { - name: 'authority'; - isMut: false; - isSigner: true; - }, - { - name: 'protocolConfigPda'; - isMut: true; - isSigner: false; - }, - { - name: 'newAuthority'; - isMut: false; - isSigner: true; - isOptional: true; - }, - ]; - args: [ - { - name: 'protocolConfig'; - type: { - option: { - defined: 'ProtocolConfig'; - }; - }; - }, - ]; - }, - { - name: 'registerSystemProgram'; - accounts: [ - { - name: 'authority'; - isMut: true; - isSigner: true; - }, - { - name: 'protocolConfigPda'; - isMut: true; - isSigner: false; - }, - { - name: 'cpiAuthority'; - isMut: true; - isSigner: false; - }, - { - name: 'groupPda'; - isMut: true; - isSigner: false; - }, - { - name: 'accountCompressionProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'systemProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'registeredProgramPda'; - isMut: true; - isSigner: false; - }, - { - name: 'programToBeRegistered'; - isMut: false; - isSigner: true; - docs: [ - '- is signer so that only the program deployer can register a program.', - ]; - }, - ]; - args: [ - { - name: 'bump'; - type: 'u8'; - }, - ]; - }, - { - name: 'deregisterSystemProgram'; - accounts: [ - { - name: 'authority'; - isMut: true; - isSigner: true; - }, - { - name: 'protocolConfigPda'; - isMut: true; - isSigner: false; - }, - { - name: 'cpiAuthority'; - isMut: true; - isSigner: false; - }, - { - name: 'groupPda'; - isMut: true; - isSigner: false; - }, - { - name: 'accountCompressionProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'registeredProgramPda'; - isMut: true; - isSigner: false; - }, - ]; - args: [ - { - name: 'bump'; - type: 'u8'; - }, - ]; - }, - { - name: 'registerForester'; - accounts: [ - { - name: 'feePayer'; - isMut: true; - isSigner: true; - }, - { - name: 'authority'; - isMut: false; - isSigner: true; - }, - { - name: 'protocolConfigPda'; - isMut: false; - isSigner: false; - }, - { - name: 'foresterPda'; - isMut: true; - isSigner: false; - }, - { - name: 'systemProgram'; - isMut: false; - isSigner: false; - }, - ]; - args: [ - { - name: 'bump'; - type: 'u8'; - }, - { - name: 'authority'; - type: 'publicKey'; - }, - { - name: 'config'; - type: { - defined: 'ForesterConfig'; - }; - }, - { - name: 'weight'; - type: { - option: 'u64'; - }; - }, - ]; - }, - { - name: 'updateForesterPda'; - accounts: [ - { - name: 'authority'; - isMut: false; - isSigner: true; - }, - { - name: 'foresterPda'; - isMut: true; - isSigner: false; - }, - { - name: 'newAuthority'; - isMut: false; - isSigner: true; - isOptional: true; - }, - ]; - args: [ - { - name: 'config'; - type: { - option: { - defined: 'ForesterConfig'; - }; - }; - }, - ]; - }, - { - name: 'updateForesterPdaWeight'; - accounts: [ - { - name: 'authority'; - isMut: false; - isSigner: true; - }, - { - name: 'protocolConfigPda'; - isMut: false; - isSigner: false; - }, - { - name: 'foresterPda'; - isMut: true; - isSigner: false; - }, - ]; - args: [ - { - name: 'newWeight'; - type: 'u64'; - }, - ]; - }, - { - name: 'registerForesterEpoch'; - docs: [ - 'Registers the forester for the epoch.', - '1. Only the forester can register herself for the epoch.', - '2. Protocol config is copied.', - '3. Epoch account is created if needed.', - ]; - accounts: [ - { - name: 'feePayer'; - isMut: true; - isSigner: true; - }, - { - name: 'authority'; - isMut: false; - isSigner: true; - }, - { - name: 'foresterPda'; - isMut: false; - isSigner: false; - }, - { - name: 'foresterEpochPda'; - isMut: true; - isSigner: false; - docs: [ - 'Instruction checks that current_epoch is the the current epoch and that', - 'the epoch is in registration phase.', - ]; - }, - { - name: 'protocolConfig'; - isMut: false; - isSigner: false; - }, - { - name: 'epochPda'; - isMut: true; - isSigner: false; - }, - { - name: 'systemProgram'; - isMut: false; - isSigner: false; - }, - ]; - args: [ - { - name: 'epoch'; - type: 'u64'; - }, - ]; - }, - { - name: 'finalizeRegistration'; - docs: [ - 'This transaction can be included as additional instruction in the first', - 'work instructions during the active phase.', - 'Registration Period must be over.', - ]; - accounts: [ - { - name: 'authority'; - isMut: false; - isSigner: true; - }, - { - name: 'foresterEpochPda'; - isMut: true; - isSigner: false; - }, - { - name: 'epochPda'; - isMut: false; - isSigner: false; - }, - ]; - args: []; - }, - { - name: 'reportWork'; - accounts: [ - { - name: 'authority'; - isMut: false; - isSigner: true; - }, - { - name: 'foresterEpochPda'; - isMut: true; - isSigner: false; - }, - { - name: 'epochPda'; - isMut: true; - isSigner: false; - }, - ]; - args: []; - }, - { - name: 'initializeAddressMerkleTree'; - accounts: [ - { - name: 'authority'; - isMut: true; - isSigner: true; - docs: [ - 'Anyone can create new trees just the fees cannot be set arbitrarily.', - ]; - }, - { - name: 'merkleTree'; - isMut: true; - isSigner: false; - }, - { - name: 'queue'; - isMut: true; - isSigner: false; - }, - { - name: 'registeredProgramPda'; - isMut: false; - isSigner: false; - }, - { - name: 'cpiAuthority'; - isMut: true; - isSigner: false; - }, - { - name: 'accountCompressionProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'protocolConfigPda'; - isMut: false; - isSigner: false; - }, - { - name: 'cpiContextAccount'; - isMut: false; - isSigner: false; - isOptional: true; - }, - { - name: 'lightSystemProgram'; - isMut: false; - isSigner: false; - isOptional: true; - }, - ]; - args: [ - { - name: 'bump'; - type: 'u8'; - }, - { - name: 'programOwner'; - type: { - option: 'publicKey'; - }; - }, - { - name: 'forester'; - type: { - option: 'publicKey'; - }; - }, - { - name: 'merkleTreeConfig'; - type: { - defined: 'AddressMerkleTreeConfig'; - }; - }, - { - name: 'queueConfig'; - type: { - defined: 'AddressQueueConfig'; - }; - }, - ]; - }, - { - name: 'initializeStateMerkleTree'; - accounts: [ - { - name: 'authority'; - isMut: true; - isSigner: true; - docs: [ - 'Anyone can create new trees just the fees cannot be set arbitrarily.', - ]; - }, - { - name: 'merkleTree'; - isMut: true; - isSigner: false; - }, - { - name: 'queue'; - isMut: true; - isSigner: false; - }, - { - name: 'registeredProgramPda'; - isMut: false; - isSigner: false; - }, - { - name: 'cpiAuthority'; - isMut: true; - isSigner: false; - }, - { - name: 'accountCompressionProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'protocolConfigPda'; - isMut: false; - isSigner: false; - }, - { - name: 'cpiContextAccount'; - isMut: false; - isSigner: false; - isOptional: true; - }, - { - name: 'lightSystemProgram'; - isMut: false; - isSigner: false; - isOptional: true; - }, - ]; - args: [ - { - name: 'bump'; - type: 'u8'; - }, - { - name: 'programOwner'; - type: { - option: 'publicKey'; - }; - }, - { - name: 'forester'; - type: { - option: 'publicKey'; - }; - }, - { - name: 'merkleTreeConfig'; - type: { - defined: 'StateMerkleTreeConfig'; - }; - }, - { - name: 'queueConfig'; - type: { - defined: 'NullifierQueueConfig'; - }; - }, - ]; - }, - { - name: 'nullify'; - accounts: [ - { - name: 'registeredForesterPda'; - isMut: true; - isSigner: false; - isOptional: true; - }, - { - name: 'authority'; - isMut: false; - isSigner: true; - }, - { - name: 'cpiAuthority'; - isMut: false; - isSigner: false; - }, - { - name: 'registeredProgramPda'; - isMut: false; - isSigner: false; - }, - { - name: 'accountCompressionProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'logWrapper'; - isMut: false; - isSigner: false; - }, - { - name: 'merkleTree'; - isMut: true; - isSigner: false; - }, - { - name: 'nullifierQueue'; - isMut: true; - isSigner: false; - }, - ]; - args: [ - { - name: 'bump'; - type: 'u8'; - }, - { - name: 'changeLogIndices'; - type: { - vec: 'u64'; - }; - }, - { - name: 'leavesQueueIndices'; - type: { - vec: 'u16'; - }; - }, - { - name: 'indices'; - type: { - vec: 'u64'; - }; - }, - { - name: 'proofs'; - type: { - vec: { - vec: { - array: ['u8', 32]; - }; - }; - }; - }, - ]; - }, - { - name: 'updateAddressMerkleTree'; - accounts: [ - { - name: 'registeredForesterPda'; - isMut: true; - isSigner: false; - isOptional: true; - }, - { - name: 'authority'; - isMut: false; - isSigner: true; - }, - { - name: 'cpiAuthority'; - isMut: false; - isSigner: false; - }, - { - name: 'registeredProgramPda'; - isMut: false; - isSigner: false; - }, - { - name: 'accountCompressionProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'queue'; - isMut: true; - isSigner: false; - }, - { - name: 'merkleTree'; - isMut: true; - isSigner: false; - }, - { - name: 'logWrapper'; - isMut: false; - isSigner: false; - }, - ]; - args: [ - { - name: 'bump'; - type: 'u8'; - }, - { - name: 'changelogIndex'; - type: 'u16'; - }, - { - name: 'indexedChangelogIndex'; - type: 'u16'; - }, - { - name: 'value'; - type: 'u16'; - }, - { - name: 'lowAddressIndex'; - type: 'u64'; - }, - { - name: 'lowAddressValue'; - type: { - array: ['u8', 32]; - }; - }, - { - name: 'lowAddressNextIndex'; - type: 'u64'; - }, - { - name: 'lowAddressNextValue'; - type: { - array: ['u8', 32]; - }; - }, - { - name: 'lowAddressProof'; - type: { - array: [ - { - array: ['u8', 32]; - }, - 16, - ]; - }; - }, - ]; - }, - { - name: 'rolloverAddressMerkleTreeAndQueue'; - accounts: [ - { - name: 'registeredForesterPda'; - isMut: true; - isSigner: false; - isOptional: true; - }, - { - name: 'authority'; - isMut: true; - isSigner: true; - }, - { - name: 'cpiAuthority'; - isMut: false; - isSigner: false; - }, - { - name: 'registeredProgramPda'; - isMut: false; - isSigner: false; - }, - { - name: 'accountCompressionProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'newMerkleTree'; - isMut: true; - isSigner: false; - }, - { - name: 'newQueue'; - isMut: true; - isSigner: false; - }, - { - name: 'oldMerkleTree'; - isMut: true; - isSigner: false; - }, - { - name: 'oldQueue'; - isMut: true; - isSigner: false; - }, - ]; - args: [ - { - name: 'bump'; - type: 'u8'; - }, - ]; - }, - { - name: 'rolloverStateMerkleTreeAndQueue'; - accounts: [ - { - name: 'registeredForesterPda'; - isMut: true; - isSigner: false; - isOptional: true; - }, - { - name: 'authority'; - isMut: true; - isSigner: true; - }, - { - name: 'cpiAuthority'; - isMut: false; - isSigner: false; - }, - { - name: 'registeredProgramPda'; - isMut: false; - isSigner: false; - }, - { - name: 'accountCompressionProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'newMerkleTree'; - isMut: true; - isSigner: false; - }, - { - name: 'newQueue'; - isMut: true; - isSigner: false; - }, - { - name: 'oldMerkleTree'; - isMut: true; - isSigner: false; - }, - { - name: 'oldQueue'; - isMut: true; - isSigner: false; - }, - { - name: 'cpiContextAccount'; - isMut: false; - isSigner: false; - }, - { - name: 'lightSystemProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'protocolConfigPda'; - isMut: false; - isSigner: false; - }, - ]; - args: [ - { - name: 'bump'; - type: 'u8'; - }, - ]; - }, - { - name: 'initializeBatchedStateMerkleTree'; - accounts: [ - { - name: 'authority'; - isMut: true; - isSigner: true; - }, - { - name: 'merkleTree'; - isMut: true; - isSigner: false; - }, - { - name: 'queue'; - isMut: true; - isSigner: false; - }, - { - name: 'registeredProgramPda'; - isMut: false; - isSigner: false; - }, - { - name: 'cpiAuthority'; - isMut: true; - isSigner: false; - }, - { - name: 'accountCompressionProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'protocolConfigPda'; - isMut: false; - isSigner: false; - }, - { - name: 'cpiContextAccount'; - isMut: false; - isSigner: false; - }, - { - name: 'lightSystemProgram'; - isMut: false; - isSigner: false; - }, - ]; - args: [ - { - name: 'bump'; - type: 'u8'; - }, - { - name: 'params'; - type: 'bytes'; - }, - ]; - }, - { - name: 'batchNullify'; - accounts: [ - { - name: 'registeredForesterPda'; - isMut: true; - isSigner: false; - isOptional: true; - }, - { - name: 'authority'; - isMut: false; - isSigner: true; - }, - { - name: 'cpiAuthority'; - isMut: false; - isSigner: false; - }, - { - name: 'registeredProgramPda'; - isMut: false; - isSigner: false; - }, - { - name: 'accountCompressionProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'logWrapper'; - isMut: false; - isSigner: false; - }, - { - name: 'merkleTree'; - isMut: true; - isSigner: false; - }, - ]; - args: [ - { - name: 'bump'; - type: 'u8'; - }, - { - name: 'data'; - type: 'bytes'; - }, - ]; - }, - { - name: 'batchAppend'; - accounts: [ - { - name: 'registeredForesterPda'; - isMut: true; - isSigner: false; - isOptional: true; - }, - { - name: 'authority'; - isMut: false; - isSigner: true; - }, - { - name: 'cpiAuthority'; - isMut: false; - isSigner: false; - }, - { - name: 'registeredProgramPda'; - isMut: false; - isSigner: false; - }, - { - name: 'accountCompressionProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'logWrapper'; - isMut: false; - isSigner: false; - }, - { - name: 'merkleTree'; - isMut: true; - isSigner: false; - }, - { - name: 'outputQueue'; - isMut: true; - isSigner: false; - }, - ]; - args: [ - { - name: 'bump'; - type: 'u8'; - }, - { - name: 'data'; - type: 'bytes'; - }, - ]; - }, - { - name: 'initializeBatchedAddressMerkleTree'; - accounts: [ - { - name: 'authority'; - isMut: true; - isSigner: true; - }, - { - name: 'merkleTree'; - isMut: true; - isSigner: false; - }, - { - name: 'registeredProgramPda'; - isMut: false; - isSigner: false; - }, - { - name: 'cpiAuthority'; - isMut: true; - isSigner: false; - }, - { - name: 'accountCompressionProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'protocolConfigPda'; - isMut: false; - isSigner: false; - }, - ]; - args: [ - { - name: 'bump'; - type: 'u8'; - }, - { - name: 'params'; - type: 'bytes'; - }, - ]; - }, - { - name: 'batchUpdateAddressTree'; - accounts: [ - { - name: 'registeredForesterPda'; - isMut: true; - isSigner: false; - isOptional: true; - }, - { - name: 'authority'; - isMut: false; - isSigner: true; - }, - { - name: 'cpiAuthority'; - isMut: false; - isSigner: false; - }, - { - name: 'registeredProgramPda'; - isMut: false; - isSigner: false; - }, - { - name: 'accountCompressionProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'logWrapper'; - isMut: false; - isSigner: false; - }, - { - name: 'merkleTree'; - isMut: true; - isSigner: false; - }, - ]; - args: [ - { - name: 'bump'; - type: 'u8'; - }, - { - name: 'data'; - type: 'bytes'; - }, - ]; - }, - { - name: 'rolloverBatchAddressMerkleTree'; - accounts: [ - { - name: 'registeredForesterPda'; - isMut: true; - isSigner: false; - isOptional: true; - }, - { - name: 'authority'; - isMut: true; - isSigner: true; - }, - { - name: 'newAddressMerkleTree'; - isMut: true; - isSigner: false; - }, - { - name: 'oldAddressMerkleTree'; - isMut: true; - isSigner: false; - }, - { - name: 'registeredProgramPda'; - isMut: false; - isSigner: false; - }, - { - name: 'cpiAuthority'; - isMut: true; - isSigner: false; - }, - { - name: 'accountCompressionProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'protocolConfigPda'; - isMut: false; - isSigner: false; - }, - ]; - args: [ - { - name: 'bump'; - type: 'u8'; - }, - ]; - }, - { - name: 'rolloverBatchStateMerkleTree'; - accounts: [ - { - name: 'registeredForesterPda'; - isMut: true; - isSigner: false; - isOptional: true; - }, - { - name: 'authority'; - isMut: true; - isSigner: true; - }, - { - name: 'newStateMerkleTree'; - isMut: true; - isSigner: false; - }, - { - name: 'oldStateMerkleTree'; - isMut: true; - isSigner: false; - }, - { - name: 'newOutputQueue'; - isMut: true; - isSigner: false; - }, - { - name: 'oldOutputQueue'; - isMut: true; - isSigner: false; - }, - { - name: 'cpiContextAccount'; - isMut: false; - isSigner: false; - }, - { - name: 'registeredProgramPda'; - isMut: false; - isSigner: false; - }, - { - name: 'cpiAuthority'; - isMut: true; - isSigner: false; - }, - { - name: 'accountCompressionProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'protocolConfigPda'; - isMut: false; - isSigner: false; - }, - { - name: 'lightSystemProgram'; - isMut: false; - isSigner: false; - }, - ]; - args: [ - { - name: 'bump'; - type: 'u8'; - }, - ]; - }, - { - name: 'migrateState'; - accounts: [ - { - name: 'registeredForesterPda'; - isMut: true; - isSigner: false; - }, - { - name: 'authority'; - isMut: false; - isSigner: true; - }, - { - name: 'cpiAuthority'; - isMut: false; - isSigner: false; - }, - { - name: 'registeredProgramPda'; - isMut: false; - isSigner: false; - }, - { - name: 'accountCompressionProgram'; - isMut: false; - isSigner: false; - }, - { - name: 'logWrapper'; - isMut: false; - isSigner: false; - }, - { - name: 'merkleTree'; - isMut: true; - isSigner: false; - }, - { - name: 'outputQueue'; - isMut: true; - isSigner: false; - }, - ]; - args: [ - { - name: 'bump'; - type: 'u8'; - }, - { - name: 'inputs'; - type: { - defined: 'MigrateLeafParams'; - }; - }, - ]; - }, - ]; - accounts: [ - { - name: 'epochPda'; - docs: ['Is used for tallying and rewards calculation']; - type: { - kind: 'struct'; - fields: [ - { - name: 'epoch'; - type: 'u64'; - }, - { - name: 'protocolConfig'; - type: { - defined: 'ProtocolConfig'; - }; - }, - { - name: 'totalWork'; - type: 'u64'; - }, - { - name: 'registeredWeight'; - type: 'u64'; - }, - ]; - }; - }, - { - name: 'foresterEpochPda'; - type: { - kind: 'struct'; - fields: [ - { - name: 'authority'; - type: 'publicKey'; - }, - { - name: 'config'; - type: { - defined: 'ForesterConfig'; - }; - }, - { - name: 'epoch'; - type: 'u64'; - }, - { - name: 'weight'; - type: 'u64'; - }, - { - name: 'workCounter'; - type: 'u64'; - }, - { - name: 'hasReportedWork'; - docs: [ - 'Work can be reported in an extra round to earn extra performance based', - 'rewards.', - ]; - type: 'bool'; - }, - { - name: 'foresterIndex'; - docs: [ - 'Start index of the range that determines when the forester is eligible to perform work.', - 'End index is forester_start_index + weight', - ]; - type: 'u64'; - }, - { - name: 'epochActivePhaseStartSlot'; - type: 'u64'; - }, - { - name: 'totalEpochWeight'; - docs: [ - 'Total epoch weight is registered weight of the epoch account after', - 'registration is concluded and active epoch period starts.', - ]; - type: { - option: 'u64'; - }; - }, - { - name: 'protocolConfig'; - type: { - defined: 'ProtocolConfig'; - }; - }, - { - name: 'finalizeCounter'; - docs: [ - 'Incremented every time finalize registration is called.', - ]; - type: 'u64'; - }, - ]; - }; - }, - { - name: 'protocolConfigPda'; - type: { - kind: 'struct'; - fields: [ - { - name: 'authority'; - type: 'publicKey'; - }, - { - name: 'bump'; - type: 'u8'; - }, - { - name: 'config'; - type: { - defined: 'ProtocolConfig'; - }; - }, - ]; - }; - }, - { - name: 'foresterPda'; - type: { - kind: 'struct'; - fields: [ - { - name: 'authority'; - type: 'publicKey'; - }, - { - name: 'config'; - type: { - defined: 'ForesterConfig'; - }; - }, - { - name: 'activeWeight'; - type: 'u64'; - }, - { - name: 'pendingWeight'; - docs: [ - 'Pending weight which will get active once the next epoch starts.', - ]; - type: 'u64'; - }, - { - name: 'currentEpoch'; - type: 'u64'; - }, - { - name: 'lastCompressedForesterEpochPdaHash'; - docs: [ - 'Link to previous compressed forester epoch account hash.', - ]; - type: { - array: ['u8', 32]; - }; - }, - { - name: 'lastRegisteredEpoch'; - type: 'u64'; - }, - ]; - }; - }, - ]; - types: [ - { - name: 'ProtocolConfig'; - docs: [ - 'Epoch Phases:', - '1. Registration', - '2. Active', - '3. Report Work', - '4. Post (Epoch has ended, and rewards can be claimed.)', - '- There is always an active phase in progress, registration and report work', - 'phases run in parallel to a currently active phase.', - ]; - type: { - kind: 'struct'; - fields: [ - { - name: 'genesisSlot'; - docs: [ - 'Solana slot when the protocol starts operating.', - ]; - type: 'u64'; - }, - { - name: 'minWeight'; - docs: [ - 'Minimum weight required for a forester to register to an epoch.', - ]; - type: 'u64'; - }, - { - name: 'slotLength'; - docs: ['Light protocol slot length.']; - type: 'u64'; - }, - { - name: 'registrationPhaseLength'; - docs: ['Foresters can register for this phase.']; - type: 'u64'; - }, - { - name: 'activePhaseLength'; - docs: ['Foresters can perform work in this phase.']; - type: 'u64'; - }, - { - name: 'reportWorkPhaseLength'; - docs: [ - 'Foresters can report work to receive performance based rewards in this', - 'phase.', - ]; - type: 'u64'; - }, - { - name: 'networkFee'; - type: 'u64'; - }, - { - name: 'cpiContextSize'; - type: 'u64'; - }, - { - name: 'finalizeCounterLimit'; - type: 'u64'; - }, - { - name: 'placeHolder'; - docs: ['Placeholder for future protocol updates.']; - type: 'publicKey'; - }, - { - name: 'placeHolderA'; - type: 'u64'; - }, - { - name: 'placeHolderB'; - type: 'u64'; - }, - { - name: 'placeHolderC'; - type: 'u64'; - }, - { - name: 'placeHolderD'; - type: 'u64'; - }, - { - name: 'placeHolderE'; - type: 'u64'; - }, - { - name: 'placeHolderF'; - type: 'u64'; - }, - ]; - }; - }, - { - name: 'ForesterConfig'; - type: { - kind: 'struct'; - fields: [ - { - name: 'fee'; - docs: ['Fee in percentage points.']; - type: 'u64'; - }, - ]; - }; - }, - { - name: 'EpochState'; - type: { - kind: 'enum'; - variants: [ - { - name: 'Registration'; - }, - { - name: 'Active'; - }, - { - name: 'ReportWork'; - }, - { - name: 'Post'; - }, - { - name: 'Pre'; - }, - ]; - }; - }, - ]; - errors: [ - { - code: 6000; - name: 'InvalidForester'; - msg: 'InvalidForester'; - }, - { - code: 6001; - name: 'NotInReportWorkPhase'; - }, - { - code: 6002; - name: 'StakeAccountAlreadySynced'; - }, - { - code: 6003; - name: 'EpochEnded'; - }, - { - code: 6004; - name: 'ForesterNotEligible'; - }, - { - code: 6005; - name: 'NotInRegistrationPeriod'; - }, - { - code: 6006; - name: 'WeightInsuffient'; - }, - { - code: 6007; - name: 'ForesterAlreadyRegistered'; - }, - { - code: 6008; - name: 'InvalidEpochAccount'; - }, - { - code: 6009; - name: 'InvalidEpoch'; - }, - { - code: 6010; - name: 'EpochStillInProgress'; - }, - { - code: 6011; - name: 'NotInActivePhase'; - }, - { - code: 6012; - name: 'ForesterAlreadyReportedWork'; - }, - { - code: 6013; - name: 'InvalidNetworkFee'; - }, - { - code: 6014; - name: 'FinalizeCounterExceeded'; - }, - { - code: 6015; - name: 'CpiContextAccountMissing'; - }, - { - code: 6016; - name: 'ArithmeticUnderflow'; - }, - { - code: 6017; - name: 'RegistrationNotFinalized'; - }, - { - code: 6018; - name: 'CpiContextAccountInvalidDataLen'; - }, - { - code: 6019; - name: 'InvalidConfigUpdate'; - }, - { - code: 6020; - name: 'InvalidSigner'; - }, - { - code: 6021; - name: 'GetLatestRegisterEpochFailed'; - }, - { - code: 6022; - name: 'GetCurrentActiveEpochFailed'; - }, - { - code: 6023; - name: 'ForesterUndefined'; - }, - { - code: 6024; - name: 'ForesterDefined'; - }, - ]; -}; - -export const IDL: LightRegistry = { - version: '1.2.0', - name: 'light_registry', - constants: [ - { - name: 'FORESTER_SEED', - type: 'bytes', - value: '[102, 111, 114, 101, 115, 116, 101, 114]', - }, - { - name: 'FORESTER_EPOCH_SEED', - type: 'bytes', - value: '[102, 111, 114, 101, 115, 116, 101, 114, 95, 101, 112, 111, 99, 104]', - }, - { - name: 'PROTOCOL_CONFIG_PDA_SEED', - type: 'bytes', - value: '[97, 117, 116, 104, 111, 114, 105, 116, 121]', - }, - { - name: 'DEFAULT_WORK_V1', - type: 'u64', - value: '1', - }, - ], - instructions: [ - { - name: 'initializeProtocolConfig', - docs: [ - 'Initializes the protocol config pda. Can only be called once by the', - 'program account keypair.', - ], - accounts: [ - { - name: 'feePayer', - isMut: true, - isSigner: true, - }, - { - name: 'authority', - isMut: false, - isSigner: true, - }, - { - name: 'protocolConfigPda', - isMut: true, - isSigner: false, - }, - { - name: 'systemProgram', - isMut: false, - isSigner: false, - }, - { - name: 'selfProgram', - isMut: false, - isSigner: false, - }, - ], - args: [ - { - name: 'bump', - type: 'u8', - }, - { - name: 'protocolConfig', - type: { - defined: 'ProtocolConfig', - }, - }, - ], - }, - { - name: 'updateProtocolConfig', - accounts: [ - { - name: 'feePayer', - isMut: false, - isSigner: true, - }, - { - name: 'authority', - isMut: false, - isSigner: true, - }, - { - name: 'protocolConfigPda', - isMut: true, - isSigner: false, - }, - { - name: 'newAuthority', - isMut: false, - isSigner: true, - isOptional: true, - }, - ], - args: [ - { - name: 'protocolConfig', - type: { - option: { - defined: 'ProtocolConfig', - }, - }, - }, - ], - }, - { - name: 'registerSystemProgram', - accounts: [ - { - name: 'authority', - isMut: true, - isSigner: true, - }, - { - name: 'protocolConfigPda', - isMut: true, - isSigner: false, - }, - { - name: 'cpiAuthority', - isMut: true, - isSigner: false, - }, - { - name: 'groupPda', - isMut: true, - isSigner: false, - }, - { - name: 'accountCompressionProgram', - isMut: false, - isSigner: false, - }, - { - name: 'systemProgram', - isMut: false, - isSigner: false, - }, - { - name: 'registeredProgramPda', - isMut: true, - isSigner: false, - }, - { - name: 'programToBeRegistered', - isMut: false, - isSigner: true, - docs: [ - '- is signer so that only the program deployer can register a program.', - ], - }, - ], - args: [ - { - name: 'bump', - type: 'u8', - }, - ], - }, - { - name: 'deregisterSystemProgram', - accounts: [ - { - name: 'authority', - isMut: true, - isSigner: true, - }, - { - name: 'protocolConfigPda', - isMut: true, - isSigner: false, - }, - { - name: 'cpiAuthority', - isMut: true, - isSigner: false, - }, - { - name: 'groupPda', - isMut: true, - isSigner: false, - }, - { - name: 'accountCompressionProgram', - isMut: false, - isSigner: false, - }, - { - name: 'registeredProgramPda', - isMut: true, - isSigner: false, - }, - ], - args: [ - { - name: 'bump', - type: 'u8', - }, - ], - }, - { - name: 'registerForester', - accounts: [ - { - name: 'feePayer', - isMut: true, - isSigner: true, - }, - { - name: 'authority', - isMut: false, - isSigner: true, - }, - { - name: 'protocolConfigPda', - isMut: false, - isSigner: false, - }, - { - name: 'foresterPda', - isMut: true, - isSigner: false, - }, - { - name: 'systemProgram', - isMut: false, - isSigner: false, - }, - ], - args: [ - { - name: 'bump', - type: 'u8', - }, - { - name: 'authority', - type: 'publicKey', - }, - { - name: 'config', - type: { - defined: 'ForesterConfig', - }, - }, - { - name: 'weight', - type: { - option: 'u64', - }, - }, - ], - }, - { - name: 'updateForesterPda', - accounts: [ - { - name: 'authority', - isMut: false, - isSigner: true, - }, - { - name: 'foresterPda', - isMut: true, - isSigner: false, - }, - { - name: 'newAuthority', - isMut: false, - isSigner: true, - isOptional: true, - }, - ], - args: [ - { - name: 'config', - type: { - option: { - defined: 'ForesterConfig', - }, - }, - }, - ], - }, - { - name: 'updateForesterPdaWeight', - accounts: [ - { - name: 'authority', - isMut: false, - isSigner: true, - }, - { - name: 'protocolConfigPda', - isMut: false, - isSigner: false, - }, - { - name: 'foresterPda', - isMut: true, - isSigner: false, - }, - ], - args: [ - { - name: 'newWeight', - type: 'u64', - }, - ], - }, - { - name: 'registerForesterEpoch', - docs: [ - 'Registers the forester for the epoch.', - '1. Only the forester can register herself for the epoch.', - '2. Protocol config is copied.', - '3. Epoch account is created if needed.', - ], - accounts: [ - { - name: 'feePayer', - isMut: true, - isSigner: true, - }, - { - name: 'authority', - isMut: false, - isSigner: true, - }, - { - name: 'foresterPda', - isMut: false, - isSigner: false, - }, - { - name: 'foresterEpochPda', - isMut: true, - isSigner: false, - docs: [ - 'Instruction checks that current_epoch is the the current epoch and that', - 'the epoch is in registration phase.', - ], - }, - { - name: 'protocolConfig', - isMut: false, - isSigner: false, - }, - { - name: 'epochPda', - isMut: true, - isSigner: false, - }, - { - name: 'systemProgram', - isMut: false, - isSigner: false, - }, - ], - args: [ - { - name: 'epoch', - type: 'u64', - }, - ], - }, - { - name: 'finalizeRegistration', - docs: [ - 'This transaction can be included as additional instruction in the first', - 'work instructions during the active phase.', - 'Registration Period must be over.', - ], - accounts: [ - { - name: 'authority', - isMut: false, - isSigner: true, - }, - { - name: 'foresterEpochPda', - isMut: true, - isSigner: false, - }, - { - name: 'epochPda', - isMut: false, - isSigner: false, - }, - ], - args: [], - }, - { - name: 'reportWork', - accounts: [ - { - name: 'authority', - isMut: false, - isSigner: true, - }, - { - name: 'foresterEpochPda', - isMut: true, - isSigner: false, - }, - { - name: 'epochPda', - isMut: true, - isSigner: false, - }, - ], - args: [], - }, - { - name: 'initializeAddressMerkleTree', - accounts: [ - { - name: 'authority', - isMut: true, - isSigner: true, - docs: [ - 'Anyone can create new trees just the fees cannot be set arbitrarily.', - ], - }, - { - name: 'merkleTree', - isMut: true, - isSigner: false, - }, - { - name: 'queue', - isMut: true, - isSigner: false, - }, - { - name: 'registeredProgramPda', - isMut: false, - isSigner: false, - }, - { - name: 'cpiAuthority', - isMut: true, - isSigner: false, - }, - { - name: 'accountCompressionProgram', - isMut: false, - isSigner: false, - }, - { - name: 'protocolConfigPda', - isMut: false, - isSigner: false, - }, - { - name: 'cpiContextAccount', - isMut: false, - isSigner: false, - isOptional: true, - }, - { - name: 'lightSystemProgram', - isMut: false, - isSigner: false, - isOptional: true, - }, - ], - args: [ - { - name: 'bump', - type: 'u8', - }, - { - name: 'programOwner', - type: { - option: 'publicKey', - }, - }, - { - name: 'forester', - type: { - option: 'publicKey', - }, - }, - { - name: 'merkleTreeConfig', - type: { - defined: 'AddressMerkleTreeConfig', - }, - }, - { - name: 'queueConfig', - type: { - defined: 'AddressQueueConfig', - }, - }, - ], - }, - { - name: 'initializeStateMerkleTree', - accounts: [ - { - name: 'authority', - isMut: true, - isSigner: true, - docs: [ - 'Anyone can create new trees just the fees cannot be set arbitrarily.', - ], - }, - { - name: 'merkleTree', - isMut: true, - isSigner: false, - }, - { - name: 'queue', - isMut: true, - isSigner: false, - }, - { - name: 'registeredProgramPda', - isMut: false, - isSigner: false, - }, - { - name: 'cpiAuthority', - isMut: true, - isSigner: false, - }, - { - name: 'accountCompressionProgram', - isMut: false, - isSigner: false, - }, - { - name: 'protocolConfigPda', - isMut: false, - isSigner: false, - }, - { - name: 'cpiContextAccount', - isMut: false, - isSigner: false, - isOptional: true, - }, - { - name: 'lightSystemProgram', - isMut: false, - isSigner: false, - isOptional: true, - }, - ], - args: [ - { - name: 'bump', - type: 'u8', - }, - { - name: 'programOwner', - type: { - option: 'publicKey', - }, - }, - { - name: 'forester', - type: { - option: 'publicKey', - }, - }, - { - name: 'merkleTreeConfig', - type: { - defined: 'StateMerkleTreeConfig', - }, - }, - { - name: 'queueConfig', - type: { - defined: 'NullifierQueueConfig', - }, - }, - ], - }, - { - name: 'nullify', - accounts: [ - { - name: 'registeredForesterPda', - isMut: true, - isSigner: false, - isOptional: true, - }, - { - name: 'authority', - isMut: false, - isSigner: true, - }, - { - name: 'cpiAuthority', - isMut: false, - isSigner: false, - }, - { - name: 'registeredProgramPda', - isMut: false, - isSigner: false, - }, - { - name: 'accountCompressionProgram', - isMut: false, - isSigner: false, - }, - { - name: 'logWrapper', - isMut: false, - isSigner: false, - }, - { - name: 'merkleTree', - isMut: true, - isSigner: false, - }, - { - name: 'nullifierQueue', - isMut: true, - isSigner: false, - }, - ], - args: [ - { - name: 'bump', - type: 'u8', - }, - { - name: 'changeLogIndices', - type: { - vec: 'u64', - }, - }, - { - name: 'leavesQueueIndices', - type: { - vec: 'u16', - }, - }, - { - name: 'indices', - type: { - vec: 'u64', - }, - }, - { - name: 'proofs', - type: { - vec: { - vec: { - array: ['u8', 32], - }, - }, - }, - }, - ], - }, - { - name: 'updateAddressMerkleTree', - accounts: [ - { - name: 'registeredForesterPda', - isMut: true, - isSigner: false, - isOptional: true, - }, - { - name: 'authority', - isMut: false, - isSigner: true, - }, - { - name: 'cpiAuthority', - isMut: false, - isSigner: false, - }, - { - name: 'registeredProgramPda', - isMut: false, - isSigner: false, - }, - { - name: 'accountCompressionProgram', - isMut: false, - isSigner: false, - }, - { - name: 'queue', - isMut: true, - isSigner: false, - }, - { - name: 'merkleTree', - isMut: true, - isSigner: false, - }, - { - name: 'logWrapper', - isMut: false, - isSigner: false, - }, - ], - args: [ - { - name: 'bump', - type: 'u8', - }, - { - name: 'changelogIndex', - type: 'u16', - }, - { - name: 'indexedChangelogIndex', - type: 'u16', - }, - { - name: 'value', - type: 'u16', - }, - { - name: 'lowAddressIndex', - type: 'u64', - }, - { - name: 'lowAddressValue', - type: { - array: ['u8', 32], - }, - }, - { - name: 'lowAddressNextIndex', - type: 'u64', - }, - { - name: 'lowAddressNextValue', - type: { - array: ['u8', 32], - }, - }, - { - name: 'lowAddressProof', - type: { - array: [ - { - array: ['u8', 32], - }, - 16, - ], - }, - }, - ], - }, - { - name: 'rolloverAddressMerkleTreeAndQueue', - accounts: [ - { - name: 'registeredForesterPda', - isMut: true, - isSigner: false, - isOptional: true, - }, - { - name: 'authority', - isMut: true, - isSigner: true, - }, - { - name: 'cpiAuthority', - isMut: false, - isSigner: false, - }, - { - name: 'registeredProgramPda', - isMut: false, - isSigner: false, - }, - { - name: 'accountCompressionProgram', - isMut: false, - isSigner: false, - }, - { - name: 'newMerkleTree', - isMut: true, - isSigner: false, - }, - { - name: 'newQueue', - isMut: true, - isSigner: false, - }, - { - name: 'oldMerkleTree', - isMut: true, - isSigner: false, - }, - { - name: 'oldQueue', - isMut: true, - isSigner: false, - }, - ], - args: [ - { - name: 'bump', - type: 'u8', - }, - ], - }, - { - name: 'rolloverStateMerkleTreeAndQueue', - accounts: [ - { - name: 'registeredForesterPda', - isMut: true, - isSigner: false, - isOptional: true, - }, - { - name: 'authority', - isMut: true, - isSigner: true, - }, - { - name: 'cpiAuthority', - isMut: false, - isSigner: false, - }, - { - name: 'registeredProgramPda', - isMut: false, - isSigner: false, - }, - { - name: 'accountCompressionProgram', - isMut: false, - isSigner: false, - }, - { - name: 'newMerkleTree', - isMut: true, - isSigner: false, - }, - { - name: 'newQueue', - isMut: true, - isSigner: false, - }, - { - name: 'oldMerkleTree', - isMut: true, - isSigner: false, - }, - { - name: 'oldQueue', - isMut: true, - isSigner: false, - }, - { - name: 'cpiContextAccount', - isMut: false, - isSigner: false, - }, - { - name: 'lightSystemProgram', - isMut: false, - isSigner: false, - }, - { - name: 'protocolConfigPda', - isMut: false, - isSigner: false, - }, - ], - args: [ - { - name: 'bump', - type: 'u8', - }, - ], - }, - { - name: 'initializeBatchedStateMerkleTree', - accounts: [ - { - name: 'authority', - isMut: true, - isSigner: true, - }, - { - name: 'merkleTree', - isMut: true, - isSigner: false, - }, - { - name: 'queue', - isMut: true, - isSigner: false, - }, - { - name: 'registeredProgramPda', - isMut: false, - isSigner: false, - }, - { - name: 'cpiAuthority', - isMut: true, - isSigner: false, - }, - { - name: 'accountCompressionProgram', - isMut: false, - isSigner: false, - }, - { - name: 'protocolConfigPda', - isMut: false, - isSigner: false, - }, - { - name: 'cpiContextAccount', - isMut: false, - isSigner: false, - }, - { - name: 'lightSystemProgram', - isMut: false, - isSigner: false, - }, - ], - args: [ - { - name: 'bump', - type: 'u8', - }, - { - name: 'params', - type: 'bytes', - }, - ], - }, - { - name: 'batchNullify', - accounts: [ - { - name: 'registeredForesterPda', - isMut: true, - isSigner: false, - isOptional: true, - }, - { - name: 'authority', - isMut: false, - isSigner: true, - }, - { - name: 'cpiAuthority', - isMut: false, - isSigner: false, - }, - { - name: 'registeredProgramPda', - isMut: false, - isSigner: false, - }, - { - name: 'accountCompressionProgram', - isMut: false, - isSigner: false, - }, - { - name: 'logWrapper', - isMut: false, - isSigner: false, - }, - { - name: 'merkleTree', - isMut: true, - isSigner: false, - }, - ], - args: [ - { - name: 'bump', - type: 'u8', - }, - { - name: 'data', - type: 'bytes', - }, - ], - }, - { - name: 'batchAppend', - accounts: [ - { - name: 'registeredForesterPda', - isMut: true, - isSigner: false, - isOptional: true, - }, - { - name: 'authority', - isMut: false, - isSigner: true, - }, - { - name: 'cpiAuthority', - isMut: false, - isSigner: false, - }, - { - name: 'registeredProgramPda', - isMut: false, - isSigner: false, - }, - { - name: 'accountCompressionProgram', - isMut: false, - isSigner: false, - }, - { - name: 'logWrapper', - isMut: false, - isSigner: false, - }, - { - name: 'merkleTree', - isMut: true, - isSigner: false, - }, - { - name: 'outputQueue', - isMut: true, - isSigner: false, - }, - ], - args: [ - { - name: 'bump', - type: 'u8', - }, - { - name: 'data', - type: 'bytes', - }, - ], - }, - { - name: 'initializeBatchedAddressMerkleTree', - accounts: [ - { - name: 'authority', - isMut: true, - isSigner: true, - }, - { - name: 'merkleTree', - isMut: true, - isSigner: false, - }, - { - name: 'registeredProgramPda', - isMut: false, - isSigner: false, - }, - { - name: 'cpiAuthority', - isMut: true, - isSigner: false, - }, - { - name: 'accountCompressionProgram', - isMut: false, - isSigner: false, - }, - { - name: 'protocolConfigPda', - isMut: false, - isSigner: false, - }, - ], - args: [ - { - name: 'bump', - type: 'u8', - }, - { - name: 'params', - type: 'bytes', - }, - ], - }, - { - name: 'batchUpdateAddressTree', - accounts: [ - { - name: 'registeredForesterPda', - isMut: true, - isSigner: false, - isOptional: true, - }, - { - name: 'authority', - isMut: false, - isSigner: true, - }, - { - name: 'cpiAuthority', - isMut: false, - isSigner: false, - }, - { - name: 'registeredProgramPda', - isMut: false, - isSigner: false, - }, - { - name: 'accountCompressionProgram', - isMut: false, - isSigner: false, - }, - { - name: 'logWrapper', - isMut: false, - isSigner: false, - }, - { - name: 'merkleTree', - isMut: true, - isSigner: false, - }, - ], - args: [ - { - name: 'bump', - type: 'u8', - }, - { - name: 'data', - type: 'bytes', - }, - ], - }, - { - name: 'rolloverBatchAddressMerkleTree', - accounts: [ - { - name: 'registeredForesterPda', - isMut: true, - isSigner: false, - isOptional: true, - }, - { - name: 'authority', - isMut: true, - isSigner: true, - }, - { - name: 'newAddressMerkleTree', - isMut: true, - isSigner: false, - }, - { - name: 'oldAddressMerkleTree', - isMut: true, - isSigner: false, - }, - { - name: 'registeredProgramPda', - isMut: false, - isSigner: false, - }, - { - name: 'cpiAuthority', - isMut: true, - isSigner: false, - }, - { - name: 'accountCompressionProgram', - isMut: false, - isSigner: false, - }, - { - name: 'protocolConfigPda', - isMut: false, - isSigner: false, - }, - ], - args: [ - { - name: 'bump', - type: 'u8', - }, - ], - }, - { - name: 'rolloverBatchStateMerkleTree', - accounts: [ - { - name: 'registeredForesterPda', - isMut: true, - isSigner: false, - isOptional: true, - }, - { - name: 'authority', - isMut: true, - isSigner: true, - }, - { - name: 'newStateMerkleTree', - isMut: true, - isSigner: false, - }, - { - name: 'oldStateMerkleTree', - isMut: true, - isSigner: false, - }, - { - name: 'newOutputQueue', - isMut: true, - isSigner: false, - }, - { - name: 'oldOutputQueue', - isMut: true, - isSigner: false, - }, - { - name: 'cpiContextAccount', - isMut: false, - isSigner: false, - }, - { - name: 'registeredProgramPda', - isMut: false, - isSigner: false, - }, - { - name: 'cpiAuthority', - isMut: true, - isSigner: false, - }, - { - name: 'accountCompressionProgram', - isMut: false, - isSigner: false, - }, - { - name: 'protocolConfigPda', - isMut: false, - isSigner: false, - }, - { - name: 'lightSystemProgram', - isMut: false, - isSigner: false, - }, - ], - args: [ - { - name: 'bump', - type: 'u8', - }, - ], - }, - { - name: 'migrateState', - accounts: [ - { - name: 'registeredForesterPda', - isMut: true, - isSigner: false, - }, - { - name: 'authority', - isMut: false, - isSigner: true, - }, - { - name: 'cpiAuthority', - isMut: false, - isSigner: false, - }, - { - name: 'registeredProgramPda', - isMut: false, - isSigner: false, - }, - { - name: 'accountCompressionProgram', - isMut: false, - isSigner: false, - }, - { - name: 'logWrapper', - isMut: false, - isSigner: false, - }, - { - name: 'merkleTree', - isMut: true, - isSigner: false, - }, - { - name: 'outputQueue', - isMut: true, - isSigner: false, - }, - ], - args: [ - { - name: 'bump', - type: 'u8', - }, - { - name: 'inputs', - type: { - defined: 'MigrateLeafParams', - }, - }, - ], - }, - ], - accounts: [ - { - name: 'epochPda', - docs: ['Is used for tallying and rewards calculation'], - type: { - kind: 'struct', - fields: [ - { - name: 'epoch', - type: 'u64', - }, - { - name: 'protocolConfig', - type: { - defined: 'ProtocolConfig', - }, - }, - { - name: 'totalWork', - type: 'u64', - }, - { - name: 'registeredWeight', - type: 'u64', - }, - ], - }, - }, - { - name: 'foresterEpochPda', - type: { - kind: 'struct', - fields: [ - { - name: 'authority', - type: 'publicKey', - }, - { - name: 'config', - type: { - defined: 'ForesterConfig', - }, - }, - { - name: 'epoch', - type: 'u64', - }, - { - name: 'weight', - type: 'u64', - }, - { - name: 'workCounter', - type: 'u64', - }, - { - name: 'hasReportedWork', - docs: [ - 'Work can be reported in an extra round to earn extra performance based', - 'rewards.', - ], - type: 'bool', - }, - { - name: 'foresterIndex', - docs: [ - 'Start index of the range that determines when the forester is eligible to perform work.', - 'End index is forester_start_index + weight', - ], - type: 'u64', - }, - { - name: 'epochActivePhaseStartSlot', - type: 'u64', - }, - { - name: 'totalEpochWeight', - docs: [ - 'Total epoch weight is registered weight of the epoch account after', - 'registration is concluded and active epoch period starts.', - ], - type: { - option: 'u64', - }, - }, - { - name: 'protocolConfig', - type: { - defined: 'ProtocolConfig', - }, - }, - { - name: 'finalizeCounter', - docs: [ - 'Incremented every time finalize registration is called.', - ], - type: 'u64', - }, - ], - }, - }, - { - name: 'protocolConfigPda', - type: { - kind: 'struct', - fields: [ - { - name: 'authority', - type: 'publicKey', - }, - { - name: 'bump', - type: 'u8', - }, - { - name: 'config', - type: { - defined: 'ProtocolConfig', - }, - }, - ], - }, - }, - { - name: 'foresterPda', - type: { - kind: 'struct', - fields: [ - { - name: 'authority', - type: 'publicKey', - }, - { - name: 'config', - type: { - defined: 'ForesterConfig', - }, - }, - { - name: 'activeWeight', - type: 'u64', - }, - { - name: 'pendingWeight', - docs: [ - 'Pending weight which will get active once the next epoch starts.', - ], - type: 'u64', - }, - { - name: 'currentEpoch', - type: 'u64', - }, - { - name: 'lastCompressedForesterEpochPdaHash', - docs: [ - 'Link to previous compressed forester epoch account hash.', - ], - type: { - array: ['u8', 32], - }, - }, - { - name: 'lastRegisteredEpoch', - type: 'u64', - }, - ], - }, - }, - ], - types: [ - { - name: 'ProtocolConfig', - docs: [ - 'Epoch Phases:', - '1. Registration', - '2. Active', - '3. Report Work', - '4. Post (Epoch has ended, and rewards can be claimed.)', - '- There is always an active phase in progress, registration and report work', - 'phases run in parallel to a currently active phase.', - ], - type: { - kind: 'struct', - fields: [ - { - name: 'genesisSlot', - docs: [ - 'Solana slot when the protocol starts operating.', - ], - type: 'u64', - }, - { - name: 'minWeight', - docs: [ - 'Minimum weight required for a forester to register to an epoch.', - ], - type: 'u64', - }, - { - name: 'slotLength', - docs: ['Light protocol slot length.'], - type: 'u64', - }, - { - name: 'registrationPhaseLength', - docs: ['Foresters can register for this phase.'], - type: 'u64', - }, - { - name: 'activePhaseLength', - docs: ['Foresters can perform work in this phase.'], - type: 'u64', - }, - { - name: 'reportWorkPhaseLength', - docs: [ - 'Foresters can report work to receive performance based rewards in this', - 'phase.', - ], - type: 'u64', - }, - { - name: 'networkFee', - type: 'u64', - }, - { - name: 'cpiContextSize', - type: 'u64', - }, - { - name: 'finalizeCounterLimit', - type: 'u64', - }, - { - name: 'placeHolder', - docs: ['Placeholder for future protocol updates.'], - type: 'publicKey', - }, - { - name: 'placeHolderA', - type: 'u64', - }, - { - name: 'placeHolderB', - type: 'u64', - }, - { - name: 'placeHolderC', - type: 'u64', - }, - { - name: 'placeHolderD', - type: 'u64', - }, - { - name: 'placeHolderE', - type: 'u64', - }, - { - name: 'placeHolderF', - type: 'u64', - }, - ], - }, - }, - { - name: 'ForesterConfig', - type: { - kind: 'struct', - fields: [ - { - name: 'fee', - docs: ['Fee in percentage points.'], - type: 'u64', - }, - ], - }, - }, - { - name: 'EpochState', - type: { - kind: 'enum', - variants: [ - { - name: 'Registration', - }, - { - name: 'Active', - }, - { - name: 'ReportWork', - }, - { - name: 'Post', - }, - { - name: 'Pre', - }, - ], - }, - }, - ], - errors: [ - { - code: 6000, - name: 'InvalidForester', - msg: 'InvalidForester', - }, - { - code: 6001, - name: 'NotInReportWorkPhase', - }, - { - code: 6002, - name: 'StakeAccountAlreadySynced', - }, - { - code: 6003, - name: 'EpochEnded', - }, - { - code: 6004, - name: 'ForesterNotEligible', - }, - { - code: 6005, - name: 'NotInRegistrationPeriod', - }, - { - code: 6006, - name: 'WeightInsuffient', - }, - { - code: 6007, - name: 'ForesterAlreadyRegistered', - }, - { - code: 6008, - name: 'InvalidEpochAccount', - }, - { - code: 6009, - name: 'InvalidEpoch', - }, - { - code: 6010, - name: 'EpochStillInProgress', - }, - { - code: 6011, - name: 'NotInActivePhase', - }, - { - code: 6012, - name: 'ForesterAlreadyReportedWork', - }, - { - code: 6013, - name: 'InvalidNetworkFee', - }, - { - code: 6014, - name: 'FinalizeCounterExceeded', - }, - { - code: 6015, - name: 'CpiContextAccountMissing', - }, - { - code: 6016, - name: 'ArithmeticUnderflow', - }, - { - code: 6017, - name: 'RegistrationNotFinalized', - }, - { - code: 6018, - name: 'CpiContextAccountInvalidDataLen', - }, - { - code: 6019, - name: 'InvalidConfigUpdate', - }, - { - code: 6020, - name: 'InvalidSigner', - }, - { - code: 6021, - name: 'GetLatestRegisterEpochFailed', - }, - { - code: 6022, - name: 'GetCurrentActiveEpochFailed', - }, - { - code: 6023, - name: 'ForesterUndefined', - }, - { - code: 6024, - name: 'ForesterDefined', - }, - ], -}; diff --git a/js/stateless.js/src/index.ts b/js/stateless.js/src/index.ts index 17f3c3e12a..e6c43e9623 100644 --- a/js/stateless.js/src/index.ts +++ b/js/stateless.js/src/index.ts @@ -1,12 +1,11 @@ export * from './actions'; -export * from './idls'; export * from './instruction'; export * from './programs'; export * from './state'; export * from './utils'; -export * from './wallet'; export * from './constants'; export * from './errors'; export * from './rpc-interface'; export * from './rpc'; export * from './test-helpers'; +export { LightSystemProgram as LightSystemProgramIDL, IDL } from './idl'; diff --git a/js/stateless.js/src/programs/index.ts b/js/stateless.js/src/programs/index.ts index 4b58cda615..6d5d8dd768 100644 --- a/js/stateless.js/src/programs/index.ts +++ b/js/stateless.js/src/programs/index.ts @@ -1 +1,2 @@ export * from './system'; +export * from './layout'; diff --git a/js/stateless.js/src/programs/layout.ts b/js/stateless.js/src/programs/layout.ts new file mode 100644 index 0000000000..883bf4f5fb --- /dev/null +++ b/js/stateless.js/src/programs/layout.ts @@ -0,0 +1,212 @@ +import { Buffer } from 'buffer'; +import { PublicKey, AccountMeta } from '@solana/web3.js'; +import { + struct, + u8, + u64, + bool, + vec, + option, + publicKey, + array, + u16, + u32, + Layout, + vecU8, +} from '@coral-xyz/borsh'; +import { InstructionDataInvoke, PublicTransactionEvent } from '../state'; +import { LightSystemProgram } from './system'; +import { INVOKE_DISCRIMINATOR } from '../constants'; +export const CompressedAccountLayout = struct( + [ + publicKey('owner'), + u64('lamports'), + option(array(u8(), 32), 'address'), + option( + struct([ + array(u8(), 8, 'discriminator'), + vecU8('data'), + array(u8(), 32, 'dataHash'), + ]), + 'data', + ), + ], + 'compressedAccount', +); + +export const MerkleContextLayout = struct( + [ + u8('merkleTreePubkeyIndex'), + u8('nullifierQueuePubkeyIndex'), + u32('leafIndex'), + option(struct([u8('queueId'), u16('index')]), 'queueIndex'), + ], + 'merkleContext', +); + +export const NewAddressParamsLayout = struct( + [ + array(u8(), 32, 'seed'), + u8('addressQueueAccountIndex'), + u8('addressMerkleTreeAccountIndex'), + u16('addressMerkleTreeRootIndex'), + ], + 'newAddressParams', +); + +export const InstructionDataInvokeLayout: Layout = + struct([ + option( + struct([ + array(u8(), 32, 'a'), + array(u8(), 64, 'b'), + array(u8(), 32, 'c'), + ]), + 'proof', + ), + vec( + struct([ + CompressedAccountLayout, + MerkleContextLayout, + u16('rootIndex'), + bool('readOnly'), + ]), + 'inputCompressedAccountsWithMerkleContext', + ), + vec( + struct([CompressedAccountLayout, u8('merkleTreeIndex')]), + 'outputCompressedAccounts', + ), + option(u64(), 'relayFee'), + vec(NewAddressParamsLayout, 'newAddressParams'), + option(u64(), 'compressOrDecompressLamports'), + bool('isCompress'), + ]); + +export function encodeInstructionDataInvoke( + data: InstructionDataInvoke, +): Buffer { + const buffer = Buffer.alloc(1000); + const len = InstructionDataInvokeLayout.encode(data, buffer); + const dataBuffer = Buffer.from(buffer.slice(0, len)); + + const lengthBuffer = Buffer.alloc(4); + lengthBuffer.writeUInt32LE(len, 0); + + return Buffer.concat([INVOKE_DISCRIMINATOR, lengthBuffer, dataBuffer]); +} + +export function decodeInstructionDataInvoke( + buffer: Buffer, +): InstructionDataInvoke { + return InstructionDataInvokeLayout.decode( + buffer.slice(INVOKE_DISCRIMINATOR.length + 4), + ); +} + +export type invokeAccountsLayoutParams = { + feePayer: PublicKey; + authority: PublicKey; + registeredProgramPda: PublicKey; + noopProgram: PublicKey; + accountCompressionAuthority: PublicKey; + accountCompressionProgram: PublicKey; + solPoolPda: PublicKey | null; + decompressionRecipient: PublicKey | null; + systemProgram: PublicKey; +}; + +export const invokeAccountsLayout = ( + accounts: invokeAccountsLayoutParams, +): AccountMeta[] => { + const defaultPubkey = LightSystemProgram.programId; + const { + feePayer, + authority, + registeredProgramPda, + noopProgram, + accountCompressionAuthority, + accountCompressionProgram, + solPoolPda, + decompressionRecipient, + systemProgram, + } = accounts; + + return [ + { pubkey: feePayer, isSigner: true, isWritable: true }, + { pubkey: authority, isSigner: true, isWritable: false }, + { pubkey: registeredProgramPda, isSigner: false, isWritable: false }, + { pubkey: noopProgram, isSigner: false, isWritable: false }, + { + pubkey: accountCompressionAuthority, + isSigner: false, + isWritable: false, + }, + { + pubkey: accountCompressionProgram, + isSigner: false, + isWritable: false, + }, + { + pubkey: solPoolPda ?? defaultPubkey, + isSigner: false, + isWritable: solPoolPda !== null, + }, + { + pubkey: decompressionRecipient ?? defaultPubkey, + isSigner: false, + isWritable: true, + }, + { pubkey: systemProgram, isSigner: false, isWritable: false }, + ]; +}; + +export const PublicTransactionEventLayout: Layout = + struct([ + vec(array(u8(), 32), 'inputCompressedAccountHashes'), + vec(array(u8(), 32), 'outputCompressedAccountHashes'), + vec( + struct([ + struct( + [ + publicKey('owner'), + u64('lamports'), + option(array(u8(), 32), 'address'), + option( + struct([ + array(u8(), 8, 'discriminator'), + vecU8('data'), + array(u8(), 32, 'dataHash'), + ]), + 'data', + ), + ], + 'compressedAccount', + ), + u8('merkleTreeIndex'), + ]), + 'outputCompressedAccounts', + ), + vec(u32(), 'outputLeafIndices'), + vec(struct([publicKey('pubkey'), u64('seq')]), 'sequenceNumbers'), + option(u64(), 'relayFee'), + bool('isCompress'), + option(u64(), 'compressOrDecompressLamports'), + vec(publicKey(), 'pubkeyArray'), + option(vecU8(), 'message'), + ]); + +export function encodePublicTransactionEvent( + data: PublicTransactionEvent, +): Buffer { + const buffer = Buffer.alloc(1000); + const len = PublicTransactionEventLayout.encode(data, buffer); + + return buffer.slice(0, len); +} + +export function decodePublicTransactionEvent( + buffer: Buffer, +): PublicTransactionEvent { + return PublicTransactionEventLayout.decode(buffer); +} diff --git a/js/stateless.js/src/programs/system.ts b/js/stateless.js/src/programs/system.ts index bc019faf5d..6b9594474b 100644 --- a/js/stateless.js/src/programs/system.ts +++ b/js/stateless.js/src/programs/system.ts @@ -1,18 +1,10 @@ -import { Program, AnchorProvider, setProvider, BN } from '@coral-xyz/anchor'; +import BN from 'bn.js'; import { PublicKey, - Keypair, - Connection, TransactionInstruction, SystemProgram, } from '@solana/web3.js'; import { Buffer } from 'buffer'; - -import { - IDL, - LightSystemProgram as LightSystemProgramIDL, -} from '../idls/light_system_program'; -import { useWallet } from '../wallet'; import { CompressedAccount, CompressedAccountWithMerkleContext, @@ -22,15 +14,13 @@ import { createCompressedAccount, } from '../state'; import { packCompressedAccounts, toAccountMetas } from '../instruction'; -import { - defaultStaticAccountsStruct, - defaultTestStateTreeAccounts, -} from '../constants'; +import { defaultStaticAccountsStruct } from '../constants'; import { validateSameOwner, validateSufficientBalance, } from '../utils/validation'; import { packNewAddressParams, NewAddressParams } from '../utils'; +import { encodeInstructionDataInvoke, invokeAccountsLayout } from './layout'; export const sumUpLamports = ( accounts: CompressedAccountWithMerkleContext[], @@ -201,19 +191,9 @@ export class LightSystemProgram { * Public key that identifies the CompressedPda program */ static programId: PublicKey = new PublicKey( - // TODO: can add check to ensure its consistent with the idl 'SySTEM1eSU2p4BGQfQpimFEWWSC1XDFeun3Nqzz3rT7', ); - private static _program: Program | null = null; - - static get program(): Program { - if (!this._program) { - this.initializeProgram(); - } - return this._program!; - } - /** * @internal * Cwct1kQLwJm8Z3HetLu8m4SXkhD6FZ5fXbJQCxTxPnGY @@ -228,29 +208,6 @@ export class LightSystemProgram { return address; } - /** - * Initializes the program statically if not already initialized. - */ - private static initializeProgram() { - if (!this._program) { - const mockKeypair = Keypair.generate(); - const mockConnection = new Connection( - 'http://127.0.0.1:8899', - 'confirmed', - ); - const mockProvider = new AnchorProvider( - mockConnection, - useWallet(mockKeypair), - { - commitment: 'confirmed', - preflightCommitment: 'confirmed', - }, - ); - setProvider(mockProvider); - this._program = new Program(IDL, this.programId, mockProvider); - } - } - static createTransferOutputState( inputCompressedAccounts: CompressedAccountWithMerkleContext[], toAddress: PublicKey, @@ -384,28 +341,23 @@ export class LightSystemProgram { compressOrDecompressLamports: null, isCompress: false, }; + const data = encodeInstructionDataInvoke(rawData); + + const accounts = invokeAccountsLayout({ + ...defaultStaticAccountsStruct(), + feePayer: payer, + authority: payer, + solPoolPda: null, + decompressionRecipient: null, + systemProgram: SystemProgram.programId, + }); + const keys = [...accounts, ...toAccountMetas(remainingAccounts)]; - /// Encode instruction data - const ixData = this.program.coder.types.encode( - 'InstructionDataInvoke', - rawData, - ); - - /// Build anchor instruction - const instruction = await this.program.methods - .invoke(ixData) - .accounts({ - ...defaultStaticAccountsStruct(), - feePayer: payer, - authority: payer, - solPoolPda: null, - decompressionRecipient: null, - systemProgram: SystemProgram.programId, - }) - .remainingAccounts(toAccountMetas(remainingAccounts)) - .instruction(); - - return instruction; + return new TransactionInstruction({ + programId: this.programId, + keys, + data, + }); } /** @@ -439,33 +391,33 @@ export class LightSystemProgram { outputStateTrees, ); /// Encode instruction data - const data = this.program.coder.types.encode('InstructionDataInvoke', { + const rawInputs: InstructionDataInvoke = { proof: recentValidityProof, inputCompressedAccountsWithMerkleContext: packedInputCompressedAccounts, outputCompressedAccounts: packedOutputCompressedAccounts, relayFee: null, - /// TODO: here and on-chain: option or similar. newAddressParams: [], compressOrDecompressLamports: null, isCompress: false, + }; + const data = encodeInstructionDataInvoke(rawInputs); + + const accounts = invokeAccountsLayout({ + ...defaultStaticAccountsStruct(), + feePayer: payer, + authority: payer, + solPoolPda: null, + decompressionRecipient: null, + systemProgram: SystemProgram.programId, }); + const keys = [...accounts, ...toAccountMetas(remainingAccounts)]; - /// Build anchor instruction - const instruction = await this.program.methods - .invoke(data) - .accounts({ - ...defaultStaticAccountsStruct(), - feePayer: payer, - authority: payer, - solPoolPda: null, - decompressionRecipient: null, - systemProgram: SystemProgram.programId, - }) - .remainingAccounts(toAccountMetas(remainingAccounts)) - .instruction(); - - return instruction; + return new TransactionInstruction({ + programId: this.programId, + keys, + data, + }); } /** @@ -512,26 +464,23 @@ export class LightSystemProgram { isCompress: true, }; - const data = this.program.coder.types.encode( - 'InstructionDataInvoke', - rawInputs, - ); + const data = encodeInstructionDataInvoke(rawInputs); - /// Build anchor instruction - const instruction = await this.program.methods - .invoke(data) - .accounts({ - ...defaultStaticAccountsStruct(), - feePayer: payer, - authority: payer, - solPoolPda: this.deriveCompressedSolPda(), - decompressionRecipient: null, - systemProgram: SystemProgram.programId, - }) - .remainingAccounts(toAccountMetas(remainingAccounts)) - .instruction(); - - return instruction; + const accounts = invokeAccountsLayout({ + ...defaultStaticAccountsStruct(), + feePayer: payer, + authority: payer, + solPoolPda: this.deriveCompressedSolPda(), + decompressionRecipient: null, + systemProgram: SystemProgram.programId, + }); + const keys = [...accounts, ...toAccountMetas(remainingAccounts)]; + + return new TransactionInstruction({ + programId: this.programId, + keys, + data, + }); } /** @@ -567,33 +516,33 @@ export class LightSystemProgram { outputStateTree, ); /// Encode instruction data - const data = this.program.coder.types.encode('InstructionDataInvoke', { + const rawInputs: InstructionDataInvoke = { proof: recentValidityProof, inputCompressedAccountsWithMerkleContext: packedInputCompressedAccounts, outputCompressedAccounts: packedOutputCompressedAccounts, relayFee: null, - /// TODO: here and on-chain: option or similar. newAddressParams: [], compressOrDecompressLamports: lamports, isCompress: false, + }; + const data = encodeInstructionDataInvoke(rawInputs); + + const accounts = invokeAccountsLayout({ + ...defaultStaticAccountsStruct(), + feePayer: payer, + authority: payer, + solPoolPda: this.deriveCompressedSolPda(), + decompressionRecipient: toAddress, + systemProgram: SystemProgram.programId, }); + const keys = [...accounts, ...toAccountMetas(remainingAccounts)]; - /// Build anchor instruction - const instruction = await this.program.methods - .invoke(data) - .accounts({ - ...defaultStaticAccountsStruct(), - feePayer: payer, - authority: payer, - solPoolPda: this.deriveCompressedSolPda(), - decompressionRecipient: toAddress, - systemProgram: SystemProgram.programId, - }) - .remainingAccounts(toAccountMetas(remainingAccounts)) - .instruction(); - - return instruction; + return new TransactionInstruction({ + programId: this.programId, + keys, + data, + }); } } diff --git a/js/stateless.js/src/rpc-interface.ts b/js/stateless.js/src/rpc-interface.ts index 0e5455378a..9b49901c8e 100644 --- a/js/stateless.js/src/rpc-interface.ts +++ b/js/stateless.js/src/rpc-interface.ts @@ -23,7 +23,7 @@ import { bn, TokenData, } from './state'; -import { BN } from '@coral-xyz/anchor'; +import BN from 'bn.js'; export interface LatestNonVotingSignatures { context: { slot: number }; diff --git a/js/stateless.js/src/rpc.ts b/js/stateless.js/src/rpc.ts index b5b11fe5ce..2304634473 100644 --- a/js/stateless.js/src/rpc.ts +++ b/js/stateless.js/src/rpc.ts @@ -1,8 +1,8 @@ import { Connection, ConnectionConfig, - SolanaJSONRPCError, PublicKey, + SolanaJSONRPCError, } from '@solana/web3.js'; import { Buffer } from 'buffer'; import { @@ -58,9 +58,8 @@ import { } from './state'; import { array, create, nullable } from 'superstruct'; import { defaultTestStateTreeAccounts } from './constants'; -import { BN } from '@coral-xyz/anchor'; +import BN from 'bn.js'; import { toCamelCase, toHex } from './utils/conversion'; -import { WasmFactory } from '@lightprotocol/hasher.rs'; import { proofFromJsonStruct, @@ -514,6 +513,7 @@ export class Rpc extends Connection implements CompressionApiInterface { config?: ConnectionConfig, ) { super(endpoint, config || 'confirmed'); + this.compressionApiEndpoint = compressionApiEndpoint; this.proverEndpoint = proverEndpoint; } diff --git a/js/stateless.js/src/state/BN254.ts b/js/stateless.js/src/state/BN254.ts index 908f5d2ebd..78c33dff06 100644 --- a/js/stateless.js/src/state/BN254.ts +++ b/js/stateless.js/src/state/BN254.ts @@ -4,8 +4,8 @@ import { FIELD_SIZE } from '../constants'; import { PublicKey } from '@solana/web3.js'; -import { BN } from '@coral-xyz/anchor'; -import { bs58 } from '@coral-xyz/anchor/dist/esm/utils/bytes'; +import BN from 'bn.js'; +import bs58 from 'bs58'; import { Buffer } from 'buffer'; /** diff --git a/js/stateless.js/src/state/compressed-account.ts b/js/stateless.js/src/state/compressed-account.ts index e2c9f50fa6..6ba72eb262 100644 --- a/js/stateless.js/src/state/compressed-account.ts +++ b/js/stateless.js/src/state/compressed-account.ts @@ -1,4 +1,4 @@ -import { BN } from '@coral-xyz/anchor'; +import BN from 'bn.js'; import { PublicKey } from '@solana/web3.js'; import { CompressedAccount, CompressedAccountData } from './types'; import { BN254, bn } from './BN254'; diff --git a/js/stateless.js/src/state/types.ts b/js/stateless.js/src/state/types.ts index 2764c5c68e..67b615a2ec 100644 --- a/js/stateless.js/src/state/types.ts +++ b/js/stateless.js/src/state/types.ts @@ -1,4 +1,4 @@ -import { BN } from '@coral-xyz/anchor'; +import BN from 'bn.js'; import { PublicKey } from '@solana/web3.js'; import { Buffer } from 'buffer'; import { NewAddressParamsPacked } from '../utils'; @@ -54,12 +54,17 @@ export interface CompressedAccountData { data: Buffer; // bytes dataHash: number[]; // [u8; 32] } +export interface MerkleTreeSequenceNumber { + pubkey: PublicKey; + seq: BN; +} export interface PublicTransactionEvent { inputCompressedAccountHashes: number[][]; // Vec<[u8; 32]> outputCompressedAccountHashes: number[][]; // Vec<[u8; 32]> outputCompressedAccounts: OutputCompressedAccountWithPackedContext[]; outputLeafIndices: number[]; // Vec + sequenceNumbers: MerkleTreeSequenceNumber[]; // Vec relayFee: BN | null; // Option isCompress: boolean; // bool compressOrDecompressLamports: BN | null; // Option @@ -83,32 +88,6 @@ export interface CompressedProof { c: number[]; // [u8; 32] } -/** - * Compressed-token types - * - * TODO: Token-related code should ideally not have to go into stateless.js. - * Find a better altnerative way to extend the RPC. - * - */ -export type TokenTransferOutputData = { - owner: PublicKey; - amount: BN; - lamports: BN | null; - tlv: Buffer | null; -}; - -export type CompressedTokenInstructionDataTransfer = { - proof: CompressedProof | null; - mint: PublicKey; - delegatedTransfer: null; - inputTokenDataWithContext: InputTokenDataWithContext[]; - outputCompressedAccounts: TokenTransferOutputData[]; - isCompress: boolean; - compressOrDecompressAmount: BN | null; - cpiContext: null; - lamportsChangeAccountMerkleTreeIndex: number | null; -}; - export interface InputTokenDataWithContext { amount: BN; delegateIndex: number | null; // Option diff --git a/js/stateless.js/src/test-helpers/merkle-tree/indexed-array.ts b/js/stateless.js/src/test-helpers/merkle-tree/indexed-array.ts index ef6d6f5fa3..d27b7b662d 100644 --- a/js/stateless.js/src/test-helpers/merkle-tree/indexed-array.ts +++ b/js/stateless.js/src/test-helpers/merkle-tree/indexed-array.ts @@ -1,5 +1,5 @@ import { LightWasm } from '../test-rpc/test-rpc'; -import { BN } from '@coral-xyz/anchor'; +import BN from 'bn.js'; import { bn } from '../../state'; import { HIGHEST_ADDRESS_PLUS_ONE } from '../../constants'; diff --git a/js/stateless.js/src/test-helpers/test-rpc/get-compressed-accounts.ts b/js/stateless.js/src/test-helpers/test-rpc/get-compressed-accounts.ts index df52f35871..d87be0d809 100644 --- a/js/stateless.js/src/test-helpers/test-rpc/get-compressed-accounts.ts +++ b/js/stateless.js/src/test-helpers/test-rpc/get-compressed-accounts.ts @@ -1,6 +1,6 @@ import { PublicKey } from '@solana/web3.js'; -import { BN } from '@coral-xyz/anchor'; +import BN from 'bn.js'; import { getParsedEvents } from './get-parsed-events'; import { defaultTestStateTreeAccounts } from '../../constants'; import { Rpc } from '../../rpc'; diff --git a/js/stateless.js/src/test-helpers/test-rpc/get-compressed-token-accounts.ts b/js/stateless.js/src/test-helpers/test-rpc/get-compressed-token-accounts.ts index 38eaec6366..a6a72ee5f9 100644 --- a/js/stateless.js/src/test-helpers/test-rpc/get-compressed-token-accounts.ts +++ b/js/stateless.js/src/test-helpers/test-rpc/get-compressed-token-accounts.ts @@ -1,8 +1,6 @@ import { PublicKey } from '@solana/web3.js'; import { getParsedEvents } from './get-parsed-events'; -import { BN, BorshCoder } from '@coral-xyz/anchor'; - -import { IDL } from '../../idls/light_compressed_token'; +import BN from 'bn.js'; import { defaultTestStateTreeAccounts } from '../../constants'; import { Rpc } from '../../rpc'; import { ParsedTokenAccount, WithCursor } from '../../rpc-interface'; @@ -13,9 +11,17 @@ import { createCompressedAccountWithMerkleContext, bn, } from '../../state'; +import { + struct, + publicKey, + u64, + option, + vecU8, + u8, + Layout, +} from '@coral-xyz/borsh'; const tokenProgramId: PublicKey = new PublicKey( - // TODO: can add check to ensure its consistent with the idl 'cTokenmWW8bLPjZEBAUgYy3zKxQZW6VKi7bqNFEVv3m', ); @@ -28,6 +34,16 @@ type TokenData = { tlv: Buffer | null; }; +// for test-rpc +export const TokenDataLayout: Layout = struct([ + publicKey('mint'), + publicKey('owner'), + u64('amount'), + option(publicKey(), 'delegate'), + u8('state'), + option(vecU8(), 'tlv'), +]); + export type EventWithParsedTokenTlvData = { inputCompressedAccountHashes: number[][]; outputCompressedAccounts: ParsedTokenAccount[]; @@ -51,12 +67,7 @@ export function parseTokenLayoutWithIdl( `Invalid owner ${compressedAccount.owner.toBase58()} for token layout`, ); } - const decodedLayout = new BorshCoder(IDL).types.decode( - 'TokenData', - Buffer.from(data), - ); - - return decodedLayout; + return TokenDataLayout.decode(Buffer.from(data)); } /** diff --git a/js/stateless.js/src/test-helpers/test-rpc/get-parsed-events.ts b/js/stateless.js/src/test-helpers/test-rpc/get-parsed-events.ts index dae297dee8..bf4aefd5cb 100644 --- a/js/stateless.js/src/test-helpers/test-rpc/get-parsed-events.ts +++ b/js/stateless.js/src/test-helpers/test-rpc/get-parsed-events.ts @@ -2,11 +2,12 @@ import { ParsedMessageAccount, ParsedTransactionWithMeta, } from '@solana/web3.js'; -import { bs58 } from '@coral-xyz/anchor/dist/cjs/utils/bytes'; +import bs58 from 'bs58'; import { defaultStaticAccountsStruct } from '../../constants'; import { LightSystemProgram } from '../../programs'; import { Rpc } from '../../rpc'; import { PublicTransactionEvent } from '../../state'; +import { decodePublicTransactionEvent } from '../../programs/layout'; type Deserializer = (data: Buffer, tx: ParsedTransactionWithMeta) => T; @@ -116,10 +117,7 @@ export const parsePublicTransactionEventWithIdl = ( const numericData = Buffer.from(data.map(byte => byte)); try { - return LightSystemProgram.program.coder.types.decode( - 'PublicTransactionEvent', - numericData, - ); + return decodePublicTransactionEvent(numericData); } catch (error) { console.error('Error deserializing event:', error); return null; diff --git a/js/stateless.js/src/test-helpers/test-rpc/test-rpc.ts b/js/stateless.js/src/test-helpers/test-rpc/test-rpc.ts index 86c170d0a1..aaf95d0c77 100644 --- a/js/stateless.js/src/test-helpers/test-rpc/test-rpc.ts +++ b/js/stateless.js/src/test-helpers/test-rpc/test-rpc.ts @@ -1,5 +1,5 @@ import { Connection, ConnectionConfig, PublicKey } from '@solana/web3.js'; -import { BN } from '@coral-xyz/anchor'; +import BN from 'bn.js'; import { getCompressedAccountByHashTest, getCompressedAccountsByOwnerTest, @@ -44,9 +44,9 @@ import { import { IndexedArray } from '../merkle-tree'; import { MerkleContextWithNewAddressProof, + Rpc, convertMerkleProofsWithContextToHex, convertNonInclusionMerkleProofInputsToHex, - getPublicInputHash, proverRequest, } from '../../rpc'; @@ -79,6 +79,7 @@ export interface TestRpcConfig { addressQueueAddress?: PublicKey; } +export type ClientSubscriptionId = number; export interface LightWasm { blakeHash(input: string | Uint8Array, hashLength: number): Uint8Array; poseidonHash(input: string[] | BN[]): Uint8Array; @@ -169,6 +170,7 @@ export class TestRpc extends Connection implements CompressionApiInterface { testRpcConfig?: TestRpcConfig, ) { super(endpoint, connectionConfig || 'confirmed'); + this.compressionApiEndpoint = compressionApiEndpoint; this.proverEndpoint = proverEndpoint; @@ -211,6 +213,7 @@ export class TestRpc extends Connection implements CompressionApiInterface { if (!hash) { throw new Error('hash is required'); } + const account = await getCompressedAccountByHashTest(this, hash); return account ?? null; } @@ -225,6 +228,7 @@ export class TestRpc extends Connection implements CompressionApiInterface { if (!hash) { throw new Error('hash is required'); } + const account = await getCompressedAccountByHashTest(this, hash); if (!account) { throw new Error('Account not found'); @@ -343,13 +347,6 @@ export class TestRpc extends Connection implements CompressionApiInterface { owner: PublicKey, _config?: GetCompressedAccountsByOwnerConfig, ): Promise> { - // TODO(swen): revisit - // if (_config) { - // throw new Error( - // 'dataSlice or filters are not supported in test-rpc. Please use rpc.ts instead.', - // ); - // } - const accounts = await getCompressedAccountsByOwnerTest(this, owner); return { items: accounts, diff --git a/js/stateless.js/src/utils/conversion.ts b/js/stateless.js/src/utils/conversion.ts index 57f2fa19b5..b32eda3a72 100644 --- a/js/stateless.js/src/utils/conversion.ts +++ b/js/stateless.js/src/utils/conversion.ts @@ -3,7 +3,7 @@ import { bn, createBN254 } from '../state/BN254'; import { FIELD_SIZE } from '../constants'; import { keccak_256 } from '@noble/hashes/sha3'; import { Keypair } from '@solana/web3.js'; -import { BN } from '@coral-xyz/anchor'; +import BN from 'bn.js'; export function byteArrayToKeypair(byteArray: number[]): Keypair { return Keypair.fromSecretKey(Uint8Array.from(byteArray)); diff --git a/js/stateless.js/src/utils/parse-validity-proof.ts b/js/stateless.js/src/utils/parse-validity-proof.ts index 5ed1b92f09..3bce8ef4e2 100644 --- a/js/stateless.js/src/utils/parse-validity-proof.ts +++ b/js/stateless.js/src/utils/parse-validity-proof.ts @@ -1,4 +1,4 @@ -import { BN } from '@coral-xyz/anchor'; +import BN from 'bn.js'; import { FIELD_SIZE } from '../constants'; import { CompressedProof } from '../state'; diff --git a/js/stateless.js/src/utils/test-utils.ts b/js/stateless.js/src/utils/test-utils.ts index 2a081763ed..ae6d4cbcfc 100644 --- a/js/stateless.js/src/utils/test-utils.ts +++ b/js/stateless.js/src/utils/test-utils.ts @@ -1,6 +1,7 @@ import { Connection, Keypair, Signer } from '@solana/web3.js'; import { confirmTx } from '../utils/send-and-confirm'; import { Rpc } from '../rpc'; +import BN from 'bn.js'; let c = 1; @@ -9,6 +10,54 @@ export const BOB = getTestKeypair(254); export const CHARLIE = getTestKeypair(253); export const DAVE = getTestKeypair(252); +/** + * Deep comparison of two objects. Handles BN comparison correctly. + * + * @param ref - The reference object to compare. + * @param val - The value object to compare. + * @returns True if the objects are deeply equal, false otherwise. + */ +export function deepEqual(ref: any, val: any) { + if (typeof ref !== typeof val) { + console.log(`Type mismatch: ${typeof ref} !== ${typeof val}`); + return false; + } + + if (ref instanceof BN && val instanceof BN) { + return ref.eq(val); + } + + if (typeof ref === 'object' && ref !== null && val !== null) { + const refKeys = Object.keys(ref); + const valKeys = Object.keys(val); + + if (refKeys.length !== valKeys.length) { + console.log( + `Key length mismatch: ${refKeys.length} !== ${valKeys.length}`, + ); + return false; + } + + for (const key of refKeys) { + if (!valKeys.includes(key)) { + console.log(`Key ${key} not found in value`); + return false; + } + if (!deepEqual(ref[key], val[key])) { + console.log(`Value mismatch at key ${key}`); + return false; + } + } + return true; + } + + if (ref !== val) { + console.log(`Value mismatch: ${ref} !== ${val}`); + } + + return ref === val; +} + /** * Create a new account and airdrop lamports to it * diff --git a/js/stateless.js/src/utils/validation.ts b/js/stateless.js/src/utils/validation.ts index 94d2f5cb6b..1289d4a5a0 100644 --- a/js/stateless.js/src/utils/validation.ts +++ b/js/stateless.js/src/utils/validation.ts @@ -1,4 +1,4 @@ -import { BN } from '@coral-xyz/anchor'; +import BN from 'bn.js'; import { CompressedAccount, CompressedAccountWithMerkleContext, diff --git a/js/stateless.js/src/wallet/index.ts b/js/stateless.js/src/wallet/index.ts deleted file mode 100644 index aa9f5f581c..0000000000 --- a/js/stateless.js/src/wallet/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './use-wallet'; diff --git a/js/stateless.js/src/wallet/interface.ts b/js/stateless.js/src/wallet/interface.ts deleted file mode 100644 index 0ed0a21a6b..0000000000 --- a/js/stateless.js/src/wallet/interface.ts +++ /dev/null @@ -1,85 +0,0 @@ -/// TODO: extract wallet into its own npm package -import { - Commitment, - Connection, - Keypair, - VersionedTransaction, - sendAndConfirmTransaction, -} from '@solana/web3.js'; -import { PublicKey, Transaction } from '@solana/web3.js'; -import nacl from 'tweetnacl'; -const { sign } = nacl; - -export type InclusionProofPublicInputs = { - root: string; - leaf: string; -}; -export type InclusionProofPrivateInputs = { - merkleProof: string[]; - leaf: string; - leafIndex: string; -}; - -/// On the system level, we're proving simple inclusion proofs in a -/// state tree, for each utxo used as input into a transaction. -export type InclusionProofInputs = (InclusionProofPublicInputs & - InclusionProofPrivateInputs)[]; - -/// Mock Solana web3 library -export class Wallet { - _publicKey: PublicKey; - _keypair: Keypair; - _connection: Connection; - _url: string; - _commitment: Commitment; - - constructor(keypair: Keypair, url: string, commitment: Commitment) { - this._publicKey = keypair.publicKey; - this._keypair = keypair; - this._connection = new Connection(url); - this._url = url; - this._commitment = commitment; - } - - signTransaction = async (tx: any): Promise => { - await tx.sign([this._keypair!]); - return tx; - }; - - sendTransaction = async ( - transaction: VersionedTransaction, - ): Promise => { - const signature = await this._connection.sendTransaction(transaction); - return signature; - }; - - signAllTransactions = async ( - transactions: T[], - ): Promise => { - const signedTxs = await Promise.all( - transactions.map(async tx => { - return await this.signTransaction(tx); - }), - ); - return signedTxs; - }; - - signMessage = async (message: Uint8Array): Promise => { - return sign.detached(message, this._keypair.secretKey); - }; - - sendAndConfirmTransaction = async ( - transaction: Transaction, - signers = [], - ): Promise => { - const response = await sendAndConfirmTransaction( - this._connection, - transaction, - [this._keypair, ...signers], - { - commitment: this._commitment, - }, - ); - return response; - }; -} diff --git a/js/stateless.js/src/wallet/use-wallet.ts b/js/stateless.js/src/wallet/use-wallet.ts deleted file mode 100644 index 88b0841767..0000000000 --- a/js/stateless.js/src/wallet/use-wallet.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Keypair, Commitment } from '@solana/web3.js'; -import { Wallet } from './interface'; - -// TODO consider adding isNodeWallet -export const useWallet = ( - keypair: Keypair, - url: string = 'http://127.0.0.1:8899', - commitment: Commitment = 'confirmed', -) => { - url = url !== 'mock' ? url : 'http://127.0.0.1:8899'; - const wallet = new Wallet(keypair, url, commitment); - return { - publicKey: wallet._publicKey, - sendAndConfirmTransaction: wallet.sendAndConfirmTransaction, - signMessage: wallet.signMessage, - signTransaction: wallet.signTransaction, - signAllTransactions: wallet.signAllTransactions, - sendTransaction: wallet.sendTransaction, - }; -}; diff --git a/js/stateless.js/tests/e2e/layout.test.ts b/js/stateless.js/tests/e2e/layout.test.ts new file mode 100644 index 0000000000..1ccd832ad5 --- /dev/null +++ b/js/stateless.js/tests/e2e/layout.test.ts @@ -0,0 +1,420 @@ +import { describe, it, expect } from 'vitest'; +import { Connection, Keypair, PublicKey, SystemProgram } from '@solana/web3.js'; +import BN from 'bn.js'; +import { + Program, + AnchorProvider, + setProvider, + Wallet, +} from '@coral-xyz/anchor'; +import { + encodeInstructionDataInvoke, + decodeInstructionDataInvoke, + encodePublicTransactionEvent, + decodePublicTransactionEvent, + invokeAccountsLayout, +} from '../../src/programs/layout'; +import { InstructionDataInvoke, PublicTransactionEvent } from '../../src/state'; +import { Buffer } from 'buffer'; +import { + defaultStaticAccountsStruct, + IDL, + LightSystemProgram, + LightSystemProgramIDL, +} from '../../src'; + +const getTestProgram = (): Program => { + const mockKeypair = Keypair.generate(); + const mockConnection = new Connection('http://127.0.0.1:8899', 'confirmed'); + const mockProvider = new AnchorProvider( + mockConnection, + new Wallet(mockKeypair), + { + commitment: 'confirmed', + }, + ); + setProvider(mockProvider); + return new Program( + IDL, + new PublicKey('cTokenmWW8bLPjZEBAUgYy3zKxQZW6VKi7bqNFEVv3m'), + mockProvider, + ); +}; + +function deepEqual(ref: any, val: any) { + if (typeof ref !== typeof val) { + console.log(`Type mismatch: ${typeof ref} !== ${typeof val}`); + return false; + } + + if (ref instanceof BN && val instanceof BN) { + return ref.eq(val); + } + + if (typeof ref === 'object' && ref !== null && val !== null) { + const refKeys = Object.keys(ref); + const valKeys = Object.keys(val); + + if (refKeys.length !== valKeys.length) { + console.log( + `Key length mismatch: ${refKeys.length} !== ${valKeys.length}`, + ); + return false; + } + + for (const key of refKeys) { + if (!valKeys.includes(key)) { + console.log(`Key ${key} not found in value`); + return false; + } + if (!deepEqual(ref[key], val[key])) { + console.log(`Value mismatch at key ${key}`); + return false; + } + } + return true; + } + + if (ref !== val) { + console.log(`Value mismatch: ${ref} !== ${val}`); + } + + return ref === val; +} + +describe('layout', () => { + describe('encode/decode InstructionDataInvoke', () => { + const testCases = [ + { + description: 'default case', + data: { + proof: null, + inputCompressedAccountsWithMerkleContext: [], + outputCompressedAccounts: [], + relayFee: null, + newAddressParams: [], + compressOrDecompressLamports: null, + isCompress: true, + }, + }, + { + description: 'with proof', + data: { + proof: { + a: [ + 32, 3, 117, 58, 153, 131, 148, 196, 202, 221, 250, + 146, 196, 209, 8, 192, 211, 235, 57, 47, 234, 98, + 152, 195, 227, 9, 16, 156, 194, 41, 247, 89, + ], + b: [ + 22, 192, 18, 134, 24, 94, 169, 42, 151, 182, 237, + 164, 250, 163, 253, 24, 51, 142, 37, 55, 141, 92, + 198, 146, 177, 23, 113, 12, 122, 27, 143, 64, 26, + 191, 99, 235, 113, 154, 23, 234, 173, 101, 16, 34, + 192, 108, 61, 10, 206, 251, 84, 242, 238, 92, 131, + 107, 252, 227, 70, 181, 35, 236, 195, 209, + ], + c: [ + 166, 160, 56, 185, 41, 239, 140, 4, 255, 144, 213, + 185, 153, 246, 199, 206, 47, 210, 17, 10, 66, 68, + 132, 229, 12, 67, 166, 168, 229, 156, 90, 30, + ], + }, + inputCompressedAccountsWithMerkleContext: [], + outputCompressedAccounts: [], + relayFee: null, + newAddressParams: [], + compressOrDecompressLamports: null, + isCompress: true, + }, + }, + { + description: 'with inputCompressedAccountsWithMerkleContext', + data: { + proof: null, + inputCompressedAccountsWithMerkleContext: [ + { + compressedAccount: { + owner: new PublicKey( + '6ASf5EcmmEHTgDJ4X4ZT5vT6iHVJBXPg5AN5YoTCpGWt', + ), + lamports: new BN(0), + address: null, + data: null, + }, + merkleContext: { + merkleTreePubkeyIndex: 0, + nullifierQueuePubkeyIndex: 1, + leafIndex: 10, + queueIndex: null, + }, + rootIndex: 0, + readOnly: false, + }, + ], + outputCompressedAccounts: [], + relayFee: null, + newAddressParams: [], + compressOrDecompressLamports: null, + isCompress: true, + }, + }, + { + description: 'with outputCompressedAccounts', + data: { + proof: null, + inputCompressedAccountsWithMerkleContext: [], + outputCompressedAccounts: [ + { + compressedAccount: { + owner: new PublicKey( + 'ARaDUvjovQDvFTMqaNAu9f2j1MpqJ5rhDAnDFrnyKbwg', + ), + lamports: new BN(0), + address: null, + data: null, + }, + merkleTreeIndex: 0, + }, + ], + relayFee: null, + newAddressParams: [], + compressOrDecompressLamports: null, + isCompress: true, + }, + }, + { + description: 'with relayFee', + data: { + proof: null, + inputCompressedAccountsWithMerkleContext: [], + outputCompressedAccounts: [], + relayFee: new BN(500), + newAddressParams: [], + compressOrDecompressLamports: null, + isCompress: true, + }, + }, + { + description: 'with newAddressParams', + data: { + proof: null, + inputCompressedAccountsWithMerkleContext: [], + outputCompressedAccounts: [], + relayFee: null, + newAddressParams: [ + { + seed: Array.from({ length: 32 }, () => + Math.floor(Math.random() * 256), + ), + addressQueueAccountIndex: 0, + addressMerkleTreeAccountIndex: 0, + addressMerkleTreeRootIndex: 0, + }, + ], + compressOrDecompressLamports: null, + isCompress: true, + }, + }, + ]; + + testCases.forEach(({ description, data }) => { + it(`should encode/decode InstructionDataInvoke: ${description}`, () => { + const encoded = encodeInstructionDataInvoke(data); + const decoded = decodeInstructionDataInvoke(encoded); + + expect(deepEqual(decoded, data)).toBe(true); + + const anchordata = getTestProgram().coder.types.encode( + 'InstructionDataInvoke', + data, + ); + expect(anchordata).toEqual(encoded.slice(12)); + }); + }); + }); + + describe('encode/decode PublicTransactionEvent', () => { + it('should encode and decode PublicTransactionEvent correctly', () => { + const data: PublicTransactionEvent = { + inputCompressedAccountHashes: [], + outputCompressedAccountHashes: [], + outputCompressedAccounts: [], + outputLeafIndices: [], + sequenceNumbers: [], + relayFee: null, + isCompress: true, + compressOrDecompressLamports: null, + pubkeyArray: [], + message: null, + }; + + const encoded = encodePublicTransactionEvent(data); + + const decoded = decodePublicTransactionEvent(encoded); + + const anchordata = getTestProgram().coder.types.encode( + 'PublicTransactionEvent', + data, + ); + expect(anchordata).toEqual(encoded); + + expect(deepEqual(decoded, data)).toBe(true); + }); + }); + + describe('invokeAccountsLayout', () => { + const feePayer = new Keypair().publicKey; + const authority = new Keypair().publicKey; + const registeredProgramPda = + defaultStaticAccountsStruct().registeredProgramPda; + const noopProgram = defaultStaticAccountsStruct().noopProgram; + const accountCompressionAuthority = + defaultStaticAccountsStruct().accountCompressionAuthority; + const accountCompressionProgram = + defaultStaticAccountsStruct().accountCompressionProgram; + const solPoolPda = LightSystemProgram.deriveCompressedSolPda(); + const decompressionRecipient = + LightSystemProgram.deriveCompressedSolPda(); + const systemProgram = SystemProgram.programId; + + it('should return correct AccountMeta array with null solPoodPda', () => { + const accounts = { + feePayer, + authority, + registeredProgramPda, + noopProgram, + accountCompressionAuthority, + accountCompressionProgram, + solPoolPda: null, + decompressionRecipient, + systemProgram, + }; + + const expected = [ + { pubkey: feePayer, isSigner: true, isWritable: true }, + { pubkey: authority, isSigner: true, isWritable: false }, + { + pubkey: registeredProgramPda, + isSigner: false, + isWritable: false, + }, + { pubkey: noopProgram, isSigner: false, isWritable: false }, + { + pubkey: accountCompressionAuthority, + isSigner: false, + isWritable: false, + }, + { + pubkey: accountCompressionProgram, + isSigner: false, + isWritable: false, + }, + { + pubkey: LightSystemProgram.programId, + isSigner: false, + isWritable: false, + }, + { + pubkey: decompressionRecipient, + isSigner: false, + isWritable: true, + }, + { pubkey: systemProgram, isSigner: false, isWritable: false }, + ]; + + const result = invokeAccountsLayout(accounts); + expect(result).toEqual(expected); + }); + + it('should return correct AccountMeta array with non-null solPoolPda', () => { + const accounts = { + feePayer, + authority, + registeredProgramPda, + noopProgram, + accountCompressionAuthority, + accountCompressionProgram, + solPoolPda, + decompressionRecipient, + systemProgram, + }; + + const expected = [ + { pubkey: feePayer, isSigner: true, isWritable: true }, + { pubkey: authority, isSigner: true, isWritable: false }, + { + pubkey: registeredProgramPda, + isSigner: false, + isWritable: false, + }, + { pubkey: noopProgram, isSigner: false, isWritable: false }, + { + pubkey: accountCompressionAuthority, + isSigner: false, + isWritable: false, + }, + { + pubkey: accountCompressionProgram, + isSigner: false, + isWritable: false, + }, + { pubkey: solPoolPda, isSigner: false, isWritable: true }, + { + pubkey: decompressionRecipient, + isSigner: false, + isWritable: true, + }, + { pubkey: systemProgram, isSigner: false, isWritable: false }, + ]; + + const result = invokeAccountsLayout(accounts); + expect(result).toEqual(expected); + }); + + it('should return correct AccountMeta array with null decompressionRecipient', () => { + const accounts = { + feePayer, + authority, + registeredProgramPda, + noopProgram, + accountCompressionAuthority, + accountCompressionProgram, + solPoolPda, + decompressionRecipient: null, + systemProgram, + }; + + const expected = [ + { pubkey: feePayer, isSigner: true, isWritable: true }, + { pubkey: authority, isSigner: true, isWritable: false }, + { + pubkey: registeredProgramPda, + isSigner: false, + isWritable: false, + }, + { pubkey: noopProgram, isSigner: false, isWritable: false }, + { + pubkey: accountCompressionAuthority, + isSigner: false, + isWritable: false, + }, + { + pubkey: accountCompressionProgram, + isSigner: false, + isWritable: false, + }, + { pubkey: solPoolPda, isSigner: false, isWritable: true }, + { + pubkey: LightSystemProgram.programId, + isSigner: false, + isWritable: true, + }, + { pubkey: systemProgram, isSigner: false, isWritable: false }, + ]; + + const result = invokeAccountsLayout(accounts); + expect(result).toEqual(expected); + }); + }); +}); diff --git a/js/stateless.js/tests/e2e/serde.test.ts b/js/stateless.js/tests/e2e/serde.test.ts deleted file mode 100644 index 35583771fe..0000000000 --- a/js/stateless.js/tests/e2e/serde.test.ts +++ /dev/null @@ -1,87 +0,0 @@ -import { describe, it, expect } from 'vitest'; -import { LightSystemProgram } from '../../src/programs'; -import { - CompressedAccount, - PublicTransactionEvent, - bn, - useWallet, -} from '../../src'; -import { Connection, Keypair, PublicKey } from '@solana/web3.js'; -import { AnchorProvider, Program, setProvider } from '@coral-xyz/anchor'; -import { IDL } from '../../src/idls/account_compression'; - -describe('account compression program', () => { - it('instantiate using IDL', async () => { - const mockKeypair = Keypair.generate(); - const mockConnection = new Connection( - 'http://127.0.0.1:8899', - 'confirmed', - ); - const mockProvider = new AnchorProvider( - mockConnection, - useWallet(mockKeypair), - { - commitment: 'confirmed', - preflightCommitment: 'confirmed', - }, - ); - setProvider(mockProvider); - const program = new Program( - IDL, - new PublicKey('5QPEJ5zDsVou9FQS3KCauKswM3VwBEBu4dpL9xTqkWwN'), - mockProvider, - ); - - expect(program).toBeDefined(); - }); -}); - -describe('serde', () => { - it('decode output compressed account ', async () => { - const compressedAccount = [ - 88, 8, 48, 185, 124, 227, 14, 195, 230, 152, 61, 39, 56, 191, 13, - 126, 54, 43, 47, 131, 175, 16, 52, 167, 129, 174, 200, 118, 174, 9, - 254, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ]; - - const deserializedCompressedAccount: CompressedAccount = - LightSystemProgram.program.coder.types.decode( - 'CompressedAccount', - Buffer.from(compressedAccount), - ); - - expect(deserializedCompressedAccount.data).toBe(null); - expect(deserializedCompressedAccount.address).toBe(null); - expect(deserializedCompressedAccount.lamports.eq(bn(0))).toBe(true); - }); - - it('decode event ', async () => { - const data = [ - 0, 0, 0, 0, 1, 0, 0, 0, 33, 32, 204, 221, 5, 83, 170, 139, 228, 191, - 81, 173, 10, 116, 229, 191, 155, 209, 23, 164, 28, 64, 188, 34, 248, - 127, 110, 97, 26, 188, 139, 164, 0, 0, 0, 0, 1, 0, 0, 0, 22, 143, - 135, 215, 254, 121, 58, 95, 241, 202, 91, 53, 255, 47, 224, 255, 67, - 218, 48, 172, 51, 208, 29, 102, 177, 187, 207, 73, 108, 18, 59, 255, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1, 0, 0, 0, 68, 77, 125, 32, 76, 128, 61, 180, 1, 207, 69, - 44, 121, 118, 153, 17, 179, 183, 115, 34, 163, 127, 102, 214, 1, 87, - 175, 177, 95, 49, 65, 69, 0, - ]; - const event: PublicTransactionEvent = - LightSystemProgram.program.coder.types.decode( - 'PublicTransactionEvent', - Buffer.from(data), - ); - - const refOutputCompressedAccountHash = [ - 33, 32, 204, 221, 5, 83, 170, 139, 228, 191, 81, 173, 10, 116, 229, - 191, 155, 209, 23, 164, 28, 64, 188, 34, 248, 127, 110, 97, 26, 188, - 139, 164, - ]; - expect( - bn(event.outputCompressedAccountHashes[0]).eq( - bn(refOutputCompressedAccountHash), - ), - ).toBe(true); - }); -}); diff --git a/js/stateless.js/tsconfig.json b/js/stateless.js/tsconfig.json index c661b81dfd..7b54864442 100644 --- a/js/stateless.js/tsconfig.json +++ b/js/stateless.js/tsconfig.json @@ -12,7 +12,8 @@ "moduleResolution": "Node", "lib": ["ESNext", "DOM"], "types": ["node"], - "skipLibCheck": false + "skipLibCheck": false, + "typeRoots": ["types/", "./node_modules/@types"] }, "include": ["./src/**/*.ts", "playwright.config.ts", "rollup.config.js"] } diff --git a/js/stateless.js/types/buffer-layout/index.d.ts b/js/stateless.js/types/buffer-layout/index.d.ts new file mode 100644 index 0000000000..f047cbb1fd --- /dev/null +++ b/js/stateless.js/types/buffer-layout/index.d.ts @@ -0,0 +1,88 @@ +// From https://github.com/coral-xyz/anchor/blob/master/ts/packages/anchor/types/buffer-layout/index.d.ts +declare module 'buffer-layout' { + // TODO: remove `any`. + export class Layout { + span: number; + property?: string; + + constructor(span: number, property?: string); + + decode(b: Buffer | string, offset?: number): T; + encode(src: T, b: Buffer, offset?: number): number; + getSpan(b: Buffer, offset?: number): number; + replicate(name: string): this; + } + // TODO: remove any. + export class Structure extends Layout { + span: any; + } + export function greedy( + elementSpan?: number, + property?: string, + ): Layout; + export function offset( + layout: Layout, + offset?: number, + property?: string, + ): Layout; + export function u8(property?: string): Layout; + export function u16(property?: string): Layout; + export function u24(property?: string): Layout; + export function u32(property?: string): Layout; + export function u40(property?: string): Layout; + export function u48(property?: string): Layout; + export function nu64(property?: string): Layout; + export function u16be(property?: string): Layout; + export function u24be(property?: string): Layout; + export function u32be(property?: string): Layout; + export function u40be(property?: string): Layout; + export function u48be(property?: string): Layout; + export function nu64be(property?: string): Layout; + export function s8(property?: string): Layout; + export function s16(property?: string): Layout; + export function s24(property?: string): Layout; + export function s32(property?: string): Layout; + export function s40(property?: string): Layout; + export function s48(property?: string): Layout; + export function ns64(property?: string): Layout; + export function s16be(property?: string): Layout; + export function s24be(property?: string): Layout; + export function s32be(property?: string): Layout; + export function s40be(property?: string): Layout; + export function s48be(property?: string): Layout; + export function ns64be(property?: string): Layout; + export function f32(property?: string): Layout; + export function f32be(property?: string): Layout; + export function f64(property?: string): Layout; + export function f64be(property?: string): Layout; + export function struct( + fields: Layout[], + property?: string, + decodePrefixes?: boolean, + ): Layout; + export function bits( + word: Layout, + msb?: boolean, + property?: string, + ): any; + export function seq( + elementLayout: Layout, + count: number | Layout, + property?: string, + ): Layout; + export function union( + discr: Layout, + defaultLayout?: any, + property?: string, + ): any; + export function unionLayoutDiscriminator( + layout: Layout, + property?: string, + ): any; + export function blob( + length: number | Layout, + property?: string, + ): Layout; + export function cstr(property?: string): Layout; + export function utf8(maxSpan: number, property?: string): Layout; +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 30d5ca4e29..c3c9081a08 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -63,8 +63,8 @@ importers: specifier: ^1.5.1 version: 1.5.1(bufferutil@4.0.8)(utf-8-validate@5.0.10) '@solana/web3.js': - specifier: 1.95.3 - version: 1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10) + specifier: 1.98.0 + version: 1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) axios: specifier: ^1.6.8 version: 1.6.8 @@ -113,7 +113,7 @@ importers: version: 2.3.9(@types/node@20.12.11)(typescript@5.5.3) '@solana/spl-token': specifier: ^0.3.11 - version: 0.3.11(@solana/web3.js@1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10))(bufferutil@4.0.8)(fastestsmallesttextencoderdecoder@1.0.22)(utf-8-validate@5.0.10) + version: 0.3.11(@solana/web3.js@1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))(bufferutil@4.0.8)(fastestsmallesttextencoderdecoder@1.0.22)(utf-8-validate@5.0.10) '@types/bn.js': specifier: ^5.1.5 version: 5.1.5 @@ -194,19 +194,19 @@ importers: version: link:../../../js/stateless.js '@solana/wallet-adapter-base': specifier: ^0.9.23 - version: 0.9.23(@solana/web3.js@1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10)) + version: 0.9.23(@solana/web3.js@1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10)) '@solana/wallet-adapter-react': specifier: ^0.15.35 - version: 0.15.35(@solana/web3.js@1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10))(bs58@6.0.0)(react-native@0.72.14(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) + version: 0.15.35(@solana/web3.js@1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))(bs58@6.0.0)(react-native@0.72.14(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) '@solana/wallet-adapter-react-ui': specifier: ^0.9.35 - version: 0.9.35(@solana/web3.js@1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10))(bs58@6.0.0)(react-dom@19.0.0(react@19.0.0))(react-native@0.72.14(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) + version: 0.9.35(@solana/web3.js@1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))(bs58@6.0.0)(react-dom@19.0.0(react@19.0.0))(react-native@0.72.14(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) '@solana/wallet-adapter-unsafe-burner': specifier: ^0.1.7 - version: 0.1.7(@solana/web3.js@1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10)) + version: 0.1.7(@solana/web3.js@1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10)) '@solana/web3.js': - specifier: ^1.95.3 - version: 1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10) + specifier: 1.98.0 + version: 1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) bs58: specifier: ^6.0.0 version: 6.0.0 @@ -282,8 +282,8 @@ importers: specifier: workspace:* version: link:../../../js/stateless.js '@solana/web3.js': - specifier: ^1.95.3 - version: 1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10) + specifier: 1.98.0 + version: 1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) devDependencies: '@types/node': specifier: ^22.10.2 @@ -331,25 +331,22 @@ importers: js/compressed-token: dependencies: - '@coral-xyz/anchor': - specifier: 0.29.0 - version: 0.29.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) + '@coral-xyz/borsh': + specifier: ^0.29.0 + version: 0.29.0(@solana/web3.js@1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10)) '@lightprotocol/stateless.js': specifier: workspace:* version: link:../stateless.js - '@solana/spl-token': - specifier: 0.4.8 - version: 0.4.8(@solana/web3.js@1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10))(bufferutil@4.0.8)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.2)(utf-8-validate@5.0.10) - '@solana/web3.js': - specifier: 1.95.3 - version: 1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10) + bn.js: + specifier: ^5.2.1 + version: 5.2.1 buffer: specifier: 6.0.3 version: 6.0.3 - tweetnacl: - specifier: 1.0.3 - version: 1.0.3 devDependencies: + '@coral-xyz/anchor': + specifier: ^0.29.0 + version: 0.29.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) '@esbuild-plugins/node-globals-polyfill': specifier: ^0.2.3 version: 0.2.3(esbuild@0.21.1) @@ -383,6 +380,15 @@ importers: '@rollup/plugin-typescript': specifier: ^11.1.6 version: 11.1.6(rollup@4.21.3)(tslib@2.7.0)(typescript@5.6.2) + '@solana/spl-token': + specifier: 0.4.8 + version: 0.4.8(@solana/web3.js@1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))(bufferutil@4.0.8)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.2)(utf-8-validate@5.0.10) + '@solana/web3.js': + specifier: 1.98.0 + version: 1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) + '@types/bn.js': + specifier: ^5.1.5 + version: 5.1.5 '@types/node': specifier: ^22.5.5 version: 22.5.5 @@ -449,25 +455,34 @@ importers: js/stateless.js: dependencies: - '@coral-xyz/anchor': - specifier: 0.29.0 - version: 0.29.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) + '@coral-xyz/borsh': + specifier: ^0.29.0 + version: 0.29.0(@solana/web3.js@1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10)) '@noble/hashes': specifier: 1.5.0 version: 1.5.0 - '@solana/web3.js': - specifier: 1.95.3 - version: 1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10) + bn.js: + specifier: ^5.2.1 + version: 5.2.1 + bs58: + specifier: ^6.0.0 + version: 6.0.0 buffer: specifier: 6.0.3 version: 6.0.3 + buffer-layout: + specifier: ^1.2.2 + version: 1.2.2 + camelcase: + specifier: ^8.0.0 + version: 8.0.0 superstruct: specifier: 2.0.2 version: 2.0.2 - tweetnacl: - specifier: 1.0.3 - version: 1.0.3 devDependencies: + '@coral-xyz/anchor': + specifier: 0.29.0 + version: 0.29.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) '@esbuild-plugins/node-globals-polyfill': specifier: ^0.2.3 version: 0.2.3(esbuild@0.21.1) @@ -501,6 +516,9 @@ importers: '@rollup/plugin-typescript': specifier: ^11.1.6 version: 11.1.6(rollup@4.21.3)(tslib@2.7.0)(typescript@5.6.2) + '@solana/web3.js': + specifier: 1.98.0 + version: 1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) '@types/bn.js': specifier: ^5.1.5 version: 5.1.5 @@ -552,6 +570,9 @@ importers: tslib: specifier: ^2.7.0 version: 2.7.0 + tweetnacl: + specifier: 1.0.3 + version: 1.0.3 typescript: specifier: ^5.6.2 version: 5.6.2 @@ -559,8 +580,6 @@ importers: specifier: ^2.1.1 version: 2.1.1(@types/node@22.5.5)(terser@5.31.0) - programs: {} - program-tests: {} program-tests/sdk-test-program: @@ -597,6 +616,8 @@ importers: specifier: ^5.7.2 version: 5.7.2 + programs: {} + tsconfig: {} packages: @@ -1521,8 +1542,8 @@ packages: peerDependencies: '@solana/web3.js': ^1.68.0 - '@coral-xyz/borsh@0.30.0': - resolution: {integrity: sha512-OrcV+7N10cChhgDRUxM4iEIuwxUHHs52XD85R8cFCUqE0vbLYrcoPPPs+VF6kZ9DhdJGVW2I6DHJOp5TykyZog==} + '@coral-xyz/borsh@0.30.1': + resolution: {integrity: sha512-aaxswpPrCFKl8vZTbxLssA2RvwX2zmKLlRCIktJOwW+VpVwYtXRtlWiIP+c2pPRKneiTiWCN2GEMSH9j1zTlWQ==} engines: {node: '>=10'} peerDependencies: '@solana/web3.js': ^1.68.0 @@ -2976,15 +2997,12 @@ packages: '@solana/wallet-adapter-base': '*' react: '*' - '@solana/web3.js@1.95.3': - resolution: {integrity: sha512-O6rPUN0w2fkNqx/Z3QJMB9L225Ex10PRDH8bTaIUPZXMPV0QP8ZpPvjQnXK+upUczlRgzHzd6SjKIha1p+I6og==} + '@solana/web3.js@1.98.0': + resolution: {integrity: sha512-nz3Q5OeyGFpFCR+erX2f6JPt3sKhzhYcSycBCSPkWjzSVDh/Rr1FqTVMRe58FKO16/ivTUcuJjeS5MyBvpkbzA==} '@swc/counter@0.1.3': resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} - '@swc/helpers@0.5.11': - resolution: {integrity: sha512-YNlnKRWF2sVojTpIyzwou9XoTNbzbzONwRhOoniEioF1AtaitTvVZblaQRrAzChWQ1bLYyYSWzM18y4WwgzJ+A==} - '@swc/helpers@0.5.13': resolution: {integrity: sha512-UoKGxQ3r5kYI9dALKJapMmuK+1zWM/H17Z1+iwnNmzcJRnfFuevZs375TA5rW31pu4BS4NoSy1fRsexDXfWn5w==} @@ -3805,6 +3823,10 @@ packages: resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} engines: {node: '>=10'} + camelcase@8.0.0: + resolution: {integrity: sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==} + engines: {node: '>=16'} + caniuse-lite@1.0.30001617: resolution: {integrity: sha512-mLyjzNI9I+Pix8zwcrpxEbGlfqOkF9kM3ptzmKNw5tizSyYwMe+nGLTqMK9cO+0E+Bh6TsBxNAaHWEM8xwSsmA==} @@ -9427,9 +9449,9 @@ snapshots: '@coral-xyz/anchor@0.29.0(bufferutil@4.0.8)(utf-8-validate@5.0.10)': dependencies: - '@coral-xyz/borsh': 0.29.0(@solana/web3.js@1.95.3) - '@noble/hashes': 1.4.0 - '@solana/web3.js': 1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10) + '@coral-xyz/borsh': 0.29.0(@solana/web3.js@1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10)) + '@noble/hashes': 1.5.0 + '@solana/web3.js': 1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) bn.js: 5.2.1 bs58: 4.0.1 buffer-layout: 1.2.2 @@ -9448,9 +9470,9 @@ snapshots: '@coral-xyz/anchor@0.30.0(bufferutil@4.0.8)(utf-8-validate@5.0.10)': dependencies: - '@coral-xyz/borsh': 0.30.0(@solana/web3.js@1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10)) - '@noble/hashes': 1.4.0 - '@solana/web3.js': 1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10) + '@coral-xyz/borsh': 0.30.1(@solana/web3.js@1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10)) + '@noble/hashes': 1.5.0 + '@solana/web3.js': 1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) bn.js: 5.2.1 bs58: 4.0.1 buffer-layout: 1.2.2 @@ -9467,15 +9489,15 @@ snapshots: - encoding - utf-8-validate - '@coral-xyz/borsh@0.29.0(@solana/web3.js@1.95.3)': + '@coral-xyz/borsh@0.29.0(@solana/web3.js@1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))': dependencies: - '@solana/web3.js': 1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10) + '@solana/web3.js': 1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) bn.js: 5.2.1 buffer-layout: 1.2.2 - '@coral-xyz/borsh@0.30.0(@solana/web3.js@1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10))': + '@coral-xyz/borsh@0.30.1(@solana/web3.js@1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))': dependencies: - '@solana/web3.js': 1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10) + '@solana/web3.js': 1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) bn.js: 5.2.1 buffer-layout: 1.2.2 @@ -10845,7 +10867,7 @@ snapshots: '@solana-developers/helpers@1.5.1(bufferutil@4.0.8)(utf-8-validate@5.0.10)': dependencies: - '@solana/web3.js': 1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10) + '@solana/web3.js': 1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) bs58: 5.0.0 dotenv: 16.4.5 prettier: 3.3.3 @@ -10855,10 +10877,10 @@ snapshots: - encoding - utf-8-validate - '@solana-mobile/mobile-wallet-adapter-protocol-web3js@2.0.2(@solana/web3.js@1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10))(react-native@0.72.14(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))': + '@solana-mobile/mobile-wallet-adapter-protocol-web3js@2.0.2(@solana/web3.js@1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))(react-native@0.72.14(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))': dependencies: '@solana-mobile/mobile-wallet-adapter-protocol': 2.0.1(react-native@0.72.14(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)) - '@solana/web3.js': 1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10) + '@solana/web3.js': 1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) bs58: 5.0.0 js-base64: 3.7.5 transitivePeerDependencies: @@ -10868,12 +10890,12 @@ snapshots: dependencies: react-native: 0.72.14(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10) - '@solana-mobile/wallet-adapter-mobile@2.0.1(@solana/web3.js@1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10))(react-native@0.72.14(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))': + '@solana-mobile/wallet-adapter-mobile@2.0.1(@solana/web3.js@1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))(react-native@0.72.14(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))': dependencies: '@react-native-async-storage/async-storage': 1.19.5(react-native@0.72.14(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)) - '@solana-mobile/mobile-wallet-adapter-protocol-web3js': 2.0.2(@solana/web3.js@1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10))(react-native@0.72.14(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)) - '@solana/wallet-adapter-base': 0.9.23(@solana/web3.js@1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10)) - '@solana/web3.js': 1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10) + '@solana-mobile/mobile-wallet-adapter-protocol-web3js': 2.0.2(@solana/web3.js@1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))(react-native@0.72.14(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)) + '@solana/wallet-adapter-base': 0.9.23(@solana/web3.js@1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10)) + '@solana/web3.js': 1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) js-base64: 3.7.5 transitivePeerDependencies: - react-native @@ -10881,7 +10903,7 @@ snapshots: '@solana/buffer-layout-utils@0.2.0(bufferutil@4.0.8)(utf-8-validate@5.0.10)': dependencies: '@solana/buffer-layout': 4.0.1 - '@solana/web3.js': 1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10) + '@solana/web3.js': 1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) bigint-buffer: 1.1.5 bignumber.js: 9.1.2 transitivePeerDependencies: @@ -11023,16 +11045,16 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/spl-token-group@0.0.5(@solana/web3.js@1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10))(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.2)': + '@solana/spl-token-group@0.0.5(@solana/web3.js@1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.2)': dependencies: '@solana/codecs': 2.0.0-preview.4(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.2) '@solana/spl-type-length-value': 0.1.0 - '@solana/web3.js': 1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10) + '@solana/web3.js': 1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) transitivePeerDependencies: - fastestsmallesttextencoderdecoder - typescript - '@solana/spl-token-metadata@0.1.2(@solana/web3.js@1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10))(fastestsmallesttextencoderdecoder@1.0.22)': + '@solana/spl-token-metadata@0.1.2(@solana/web3.js@1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))(fastestsmallesttextencoderdecoder@1.0.22)': dependencies: '@solana/codecs-core': 2.0.0-experimental.8618508 '@solana/codecs-data-structures': 2.0.0-experimental.8618508 @@ -11040,25 +11062,25 @@ snapshots: '@solana/codecs-strings': 2.0.0-experimental.8618508(fastestsmallesttextencoderdecoder@1.0.22) '@solana/options': 2.0.0-experimental.8618508 '@solana/spl-type-length-value': 0.1.0 - '@solana/web3.js': 1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10) + '@solana/web3.js': 1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/spl-token-metadata@0.1.5(@solana/web3.js@1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10))(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.2)': + '@solana/spl-token-metadata@0.1.5(@solana/web3.js@1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.2)': dependencies: '@solana/codecs': 2.0.0-rc.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.2) '@solana/spl-type-length-value': 0.1.0 - '@solana/web3.js': 1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10) + '@solana/web3.js': 1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) transitivePeerDependencies: - fastestsmallesttextencoderdecoder - typescript - '@solana/spl-token@0.3.11(@solana/web3.js@1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10))(bufferutil@4.0.8)(fastestsmallesttextencoderdecoder@1.0.22)(utf-8-validate@5.0.10)': + '@solana/spl-token@0.3.11(@solana/web3.js@1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))(bufferutil@4.0.8)(fastestsmallesttextencoderdecoder@1.0.22)(utf-8-validate@5.0.10)': dependencies: '@solana/buffer-layout': 4.0.1 '@solana/buffer-layout-utils': 0.2.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) - '@solana/spl-token-metadata': 0.1.2(@solana/web3.js@1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10))(fastestsmallesttextencoderdecoder@1.0.22) - '@solana/web3.js': 1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10) + '@solana/spl-token-metadata': 0.1.2(@solana/web3.js@1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))(fastestsmallesttextencoderdecoder@1.0.22) + '@solana/web3.js': 1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) buffer: 6.0.3 transitivePeerDependencies: - bufferutil @@ -11066,13 +11088,13 @@ snapshots: - fastestsmallesttextencoderdecoder - utf-8-validate - '@solana/spl-token@0.4.8(@solana/web3.js@1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10))(bufferutil@4.0.8)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.2)(utf-8-validate@5.0.10)': + '@solana/spl-token@0.4.8(@solana/web3.js@1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))(bufferutil@4.0.8)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.2)(utf-8-validate@5.0.10)': dependencies: '@solana/buffer-layout': 4.0.1 '@solana/buffer-layout-utils': 0.2.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) - '@solana/spl-token-group': 0.0.5(@solana/web3.js@1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10))(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.2) - '@solana/spl-token-metadata': 0.1.5(@solana/web3.js@1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10))(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.2) - '@solana/web3.js': 1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10) + '@solana/spl-token-group': 0.0.5(@solana/web3.js@1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.2) + '@solana/spl-token-metadata': 0.1.5(@solana/web3.js@1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.2) + '@solana/web3.js': 1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) buffer: 6.0.3 transitivePeerDependencies: - bufferutil @@ -11085,53 +11107,53 @@ snapshots: dependencies: buffer: 6.0.3 - '@solana/wallet-adapter-base-ui@0.1.2(@solana/web3.js@1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10))(bs58@6.0.0)(react-native@0.72.14(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)': + '@solana/wallet-adapter-base-ui@0.1.2(@solana/web3.js@1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))(bs58@6.0.0)(react-native@0.72.14(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)': dependencies: - '@solana/wallet-adapter-react': 0.15.35(@solana/web3.js@1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10))(bs58@6.0.0)(react-native@0.72.14(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) - '@solana/web3.js': 1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10) + '@solana/wallet-adapter-react': 0.15.35(@solana/web3.js@1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))(bs58@6.0.0)(react-native@0.72.14(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) + '@solana/web3.js': 1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) react: 19.0.0 transitivePeerDependencies: - bs58 - react-native - '@solana/wallet-adapter-base@0.9.23(@solana/web3.js@1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10))': + '@solana/wallet-adapter-base@0.9.23(@solana/web3.js@1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))': dependencies: '@solana/wallet-standard-features': 1.1.0 - '@solana/web3.js': 1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10) + '@solana/web3.js': 1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) '@wallet-standard/base': 1.0.1 '@wallet-standard/features': 1.0.3 eventemitter3: 4.0.7 - '@solana/wallet-adapter-react-ui@0.9.35(@solana/web3.js@1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10))(bs58@6.0.0)(react-dom@19.0.0(react@19.0.0))(react-native@0.72.14(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)': + '@solana/wallet-adapter-react-ui@0.9.35(@solana/web3.js@1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))(bs58@6.0.0)(react-dom@19.0.0(react@19.0.0))(react-native@0.72.14(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)': dependencies: - '@solana/wallet-adapter-base': 0.9.23(@solana/web3.js@1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10)) - '@solana/wallet-adapter-base-ui': 0.1.2(@solana/web3.js@1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10))(bs58@6.0.0)(react-native@0.72.14(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) - '@solana/wallet-adapter-react': 0.15.35(@solana/web3.js@1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10))(bs58@6.0.0)(react-native@0.72.14(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) - '@solana/web3.js': 1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10) + '@solana/wallet-adapter-base': 0.9.23(@solana/web3.js@1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10)) + '@solana/wallet-adapter-base-ui': 0.1.2(@solana/web3.js@1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))(bs58@6.0.0)(react-native@0.72.14(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) + '@solana/wallet-adapter-react': 0.15.35(@solana/web3.js@1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))(bs58@6.0.0)(react-native@0.72.14(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0) + '@solana/web3.js': 1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) react: 19.0.0 react-dom: 19.0.0(react@19.0.0) transitivePeerDependencies: - bs58 - react-native - '@solana/wallet-adapter-react@0.15.35(@solana/web3.js@1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10))(bs58@6.0.0)(react-native@0.72.14(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)': + '@solana/wallet-adapter-react@0.15.35(@solana/web3.js@1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))(bs58@6.0.0)(react-native@0.72.14(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10))(react@19.0.0)': dependencies: - '@solana-mobile/wallet-adapter-mobile': 2.0.1(@solana/web3.js@1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10))(react-native@0.72.14(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)) - '@solana/wallet-adapter-base': 0.9.23(@solana/web3.js@1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10)) - '@solana/wallet-standard-wallet-adapter-react': 1.1.1(@solana/wallet-adapter-base@0.9.23(@solana/web3.js@1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10)))(@solana/web3.js@1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10))(bs58@6.0.0)(react@19.0.0) - '@solana/web3.js': 1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10) + '@solana-mobile/wallet-adapter-mobile': 2.0.1(@solana/web3.js@1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))(react-native@0.72.14(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(bufferutil@4.0.8)(react@19.0.0)(utf-8-validate@5.0.10)) + '@solana/wallet-adapter-base': 0.9.23(@solana/web3.js@1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10)) + '@solana/wallet-standard-wallet-adapter-react': 1.1.1(@solana/wallet-adapter-base@0.9.23(@solana/web3.js@1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10)))(@solana/web3.js@1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))(bs58@6.0.0)(react@19.0.0) + '@solana/web3.js': 1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) react: 19.0.0 transitivePeerDependencies: - bs58 - react-native - '@solana/wallet-adapter-unsafe-burner@0.1.7(@solana/web3.js@1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10))': + '@solana/wallet-adapter-unsafe-burner@0.1.7(@solana/web3.js@1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))': dependencies: '@noble/curves': 1.4.0 - '@solana/wallet-adapter-base': 0.9.23(@solana/web3.js@1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10)) + '@solana/wallet-adapter-base': 0.9.23(@solana/web3.js@1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10)) '@solana/wallet-standard-features': 1.1.0 '@solana/wallet-standard-util': 1.1.0 - '@solana/web3.js': 1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10) + '@solana/web3.js': 1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) '@solana/wallet-standard-chains@1.1.0': dependencies: @@ -11148,23 +11170,23 @@ snapshots: '@solana/wallet-standard-chains': 1.1.0 '@solana/wallet-standard-features': 1.1.0 - '@solana/wallet-standard-wallet-adapter-base@1.1.1(@solana/web3.js@1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10))(bs58@6.0.0)': + '@solana/wallet-standard-wallet-adapter-base@1.1.1(@solana/web3.js@1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))(bs58@6.0.0)': dependencies: - '@solana/wallet-adapter-base': 0.9.23(@solana/web3.js@1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10)) + '@solana/wallet-adapter-base': 0.9.23(@solana/web3.js@1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10)) '@solana/wallet-standard-chains': 1.1.0 '@solana/wallet-standard-features': 1.1.0 '@solana/wallet-standard-util': 1.1.0 - '@solana/web3.js': 1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10) + '@solana/web3.js': 1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) '@wallet-standard/app': 1.0.1 '@wallet-standard/base': 1.0.1 '@wallet-standard/features': 1.0.3 '@wallet-standard/wallet': 1.0.1 bs58: 6.0.0 - '@solana/wallet-standard-wallet-adapter-react@1.1.1(@solana/wallet-adapter-base@0.9.23(@solana/web3.js@1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10)))(@solana/web3.js@1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10))(bs58@6.0.0)(react@19.0.0)': + '@solana/wallet-standard-wallet-adapter-react@1.1.1(@solana/wallet-adapter-base@0.9.23(@solana/web3.js@1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10)))(@solana/web3.js@1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))(bs58@6.0.0)(react@19.0.0)': dependencies: - '@solana/wallet-adapter-base': 0.9.23(@solana/web3.js@1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10)) - '@solana/wallet-standard-wallet-adapter-base': 1.1.1(@solana/web3.js@1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10))(bs58@6.0.0) + '@solana/wallet-adapter-base': 0.9.23(@solana/web3.js@1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10)) + '@solana/wallet-standard-wallet-adapter-base': 1.1.1(@solana/web3.js@1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))(bs58@6.0.0) '@wallet-standard/app': 1.0.1 '@wallet-standard/base': 1.0.1 react: 19.0.0 @@ -11172,7 +11194,7 @@ snapshots: - '@solana/web3.js' - bs58 - '@solana/web3.js@1.95.3(bufferutil@4.0.8)(utf-8-validate@5.0.10)': + '@solana/web3.js@1.98.0(bufferutil@4.0.8)(utf-8-validate@5.0.10)': dependencies: '@babel/runtime': 7.25.6 '@noble/curves': 1.4.2 @@ -11196,10 +11218,6 @@ snapshots: '@swc/counter@0.1.3': {} - '@swc/helpers@0.5.11': - dependencies: - tslib: 2.7.0 - '@swc/helpers@0.5.13': dependencies: tslib: 2.7.0 @@ -12360,6 +12378,8 @@ snapshots: camelcase@6.3.0: {} + camelcase@8.0.0: {} + caniuse-lite@1.0.30001617: {} capital-case@1.0.4: @@ -14602,7 +14622,7 @@ snapshots: isobject@3.0.1: {} - isomorphic-ws@4.0.1(ws@7.5.10): + isomorphic-ws@4.0.1(ws@7.5.10(bufferutil@4.0.8)(utf-8-validate@5.0.10)): dependencies: ws: 7.5.10(bufferutil@4.0.8)(utf-8-validate@5.0.10) @@ -14644,7 +14664,7 @@ snapshots: delay: 5.0.0 es6-promisify: 5.0.0 eyes: 0.1.8 - isomorphic-ws: 4.0.1(ws@7.5.10) + isomorphic-ws: 4.0.1(ws@7.5.10(bufferutil@4.0.8)(utf-8-validate@5.0.10)) json-stringify-safe: 5.0.1 uuid: 8.3.2 ws: 7.5.10(bufferutil@4.0.8)(utf-8-validate@5.0.10) @@ -16278,7 +16298,7 @@ snapshots: rpc-websockets@9.0.2: dependencies: - '@swc/helpers': 0.5.11 + '@swc/helpers': 0.5.13 '@types/uuid': 8.3.4 '@types/ws': 8.5.10 buffer: 6.0.3 diff --git a/programs/package.json b/programs/package.json index dbd3c18f70..bd54cfd7fb 100644 --- a/programs/package.json +++ b/programs/package.json @@ -3,9 +3,7 @@ "version": "0.3.0", "license": "Apache-2.0", "scripts": { - "push-idls": "../scripts/push-stateless-js-idls.sh && ../scripts/push-compressed-token-idl.sh", "build": "anchor build", - "build-idls": "anchor build && pnpm build-system && pnpm build-compressed-token && pnpm push-idls", "build-system": "anchor build --program-name light_system_program -- --features idl-build custom-heap", "build-compressed-token": "anchor build --program-name light_compressed_token -- --features idl-build custom-heap", "test": "pnpm test-account-compression && pnpm test-system && pnpm test-compressed-token && pnpm test-registry", diff --git a/scripts/bump-versions-and-publish-npm.sh b/scripts/bump-versions-and-publish-npm.sh index b84a3b7db9..a0a622e962 100755 --- a/scripts/bump-versions-and-publish-npm.sh +++ b/scripts/bump-versions-and-publish-npm.sh @@ -1,4 +1,8 @@ #!/usr/bin/env bash +# Examples: +# ./scripts/bump-versions-and-publish-npm.sh minor +# ./scripts/bump-versions-and-publish-npm.sh patch @lightprotocol/stateless.js @lightprotocol/compressed-token +# ./scripts/bump-versions-and-publish-npm.sh alpha @lightprotocol/stateless.js cd "$(git rev-parse --show-toplevel)" @@ -32,9 +36,16 @@ publish_package() { find "cli/bin" -type f -exec chmod +x {} + sleep 5 - if ! (cd "${package_dir}" && pnpm version "${version_type}" && pnpm publish --access public --no-git-checks); then - echo "Error occurred while publishing ${package_name}." - return 1 + if [ "$version_type" == "alpha" ]; then + if ! (cd "${package_dir}" && pnpm version prerelease --preid alpha && pnpm publish --tag alpha --access private --no-git-checks); then + echo "Error occurred while publishing ${package_name}." + return 1 + fi + else + if ! (cd "${package_dir}" && pnpm version "${version_type}" && pnpm publish --access public --no-git-checks); then + echo "Error occurred while publishing ${package_name}." + return 1 + fi fi } @@ -46,9 +57,16 @@ error_occurred=0 if [ "$#" -eq 0 ]; then echo "Bumping ${version_type} version for all packages..." - if ! pnpm -r exec -- pnpm version "${version_type}" || ! pnpm -r exec -- pnpm publish --access public; then - echo "Error occurred during bulk version bump and publish." - error_occurred=1 + if [ "$version_type" == "alpha" ]; then + if ! pnpm -r exec -- pnpm version prerelease --preid alpha || ! pnpm -r exec -- pnpm publish --tag alpha --access private; then + echo "Error occurred during bulk version bump and publish." + error_occurred=1 + fi + else + if ! pnpm -r exec -- pnpm version "${version_type}" || ! pnpm -r exec -- pnpm publish --access public; then + echo "Error occurred during bulk version bump and publish." + error_occurred=1 + fi fi else # If specific packages are provided, bump version for those packages