Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion forester-utils/src/instructions/address_batch_update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ pub struct AddressUpdateConfig<R: Rpc> {
pub rpc_pool: Arc<SolanaRpcPool<R>>,
pub merkle_tree_pubkey: Pubkey,
pub prover_url: String,
pub prover_api_key: Option<String>,
pub polling_interval: Duration,
pub max_wait_time: Duration,
pub ixs_per_tx: usize,
Expand All @@ -39,6 +40,7 @@ async fn stream_instruction_data<'a, R: Rpc>(
rpc_pool: Arc<SolanaRpcPool<R>>,
merkle_tree_pubkey: Pubkey,
prover_url: String,
prover_api_key: Option<String>,
polling_interval: Duration,
max_wait_time: Duration,
leaves_hash_chains: Vec<[u8; 32]>,
Expand All @@ -49,7 +51,7 @@ async fn stream_instruction_data<'a, R: Rpc>(
) -> impl Stream<Item = Result<Vec<InstructionDataAddressAppendInputs>, ForesterUtilsError>> + Send + 'a
{
stream! {
let proof_client = Arc::new(ProofClient::with_config(prover_url, polling_interval, max_wait_time));
let proof_client = Arc::new(ProofClient::with_config(prover_url, polling_interval, max_wait_time, prover_api_key));
let max_zkp_batches_per_call = calculate_max_zkp_batches_per_call(zkp_batch_size);
let total_chunks = leaves_hash_chains.len().div_ceil(max_zkp_batches_per_call);

Expand Down Expand Up @@ -324,6 +326,7 @@ pub async fn get_address_update_instruction_stream<'a, R: Rpc>(
config.rpc_pool,
config.merkle_tree_pubkey,
config.prover_url,
config.prover_api_key,
config.polling_interval,
config.max_wait_time,
leaves_hash_chains,
Expand Down
3 changes: 2 additions & 1 deletion forester-utils/src/instructions/state_batch_append.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ pub async fn get_append_instruction_stream<'a, R: Rpc>(
rpc_pool: Arc<SolanaRpcPool<R>>,
merkle_tree_pubkey: Pubkey,
prover_url: String,
prover_api_key: Option<String>,
polling_interval: Duration,
max_wait_time: Duration,
merkle_tree_data: ParsedMerkleTreeData,
Expand Down Expand Up @@ -126,7 +127,7 @@ pub async fn get_append_instruction_stream<'a, R: Rpc>(
}

let mut all_changelogs: Vec<ChangelogEntry<{ DEFAULT_BATCH_STATE_TREE_HEIGHT as usize }>> = Vec::new();
let proof_client = Arc::new(ProofClient::with_config(prover_url.clone(), polling_interval, max_wait_time));
let proof_client = Arc::new(ProofClient::with_config(prover_url.clone(), polling_interval, max_wait_time, prover_api_key.clone()));
let mut futures_ordered = FuturesOrdered::new();
let mut pending_count = 0;

Expand Down
3 changes: 2 additions & 1 deletion forester-utils/src/instructions/state_batch_nullify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ pub async fn get_nullify_instruction_stream<'a, R: Rpc>(
rpc_pool: Arc<SolanaRpcPool<R>>,
merkle_tree_pubkey: Pubkey,
prover_url: String,
prover_api_key: Option<String>,
polling_interval: Duration,
max_wait_time: Duration,
merkle_tree_data: ParsedMerkleTreeData,
Expand Down Expand Up @@ -125,7 +126,7 @@ pub async fn get_nullify_instruction_stream<'a, R: Rpc>(
}

let mut all_changelogs = Vec::new();
let proof_client = Arc::new(ProofClient::with_config(prover_url.clone(), polling_interval, max_wait_time));
let proof_client = Arc::new(ProofClient::with_config(prover_url.clone(), polling_interval, max_wait_time, prover_api_key.clone()));
let mut futures_ordered = FuturesOrdered::new();
let mut pending_count = 0;

Expand Down
24 changes: 24 additions & 0 deletions forester/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,30 @@ pub struct StartArgs {
#[arg(long, env = "FORESTER_PROVER_URL")]
pub prover_url: Option<String>,

#[arg(
long,
env = "FORESTER_PROVER_APPEND_URL",
help = "Prover URL for append operations. If not specified, uses prover_url"
)]
pub prover_append_url: Option<String>,

#[arg(
long,
env = "FORESTER_PROVER_UPDATE_URL",
help = "Prover URL for update operations. If not specified, uses prover_url"
)]
pub prover_update_url: Option<String>,

#[arg(
long,
env = "FORESTER_PROVER_ADDRESS_APPEND_URL",
help = "Prover URL for address-append operations. If not specified, uses prover_url"
)]
pub prover_address_append_url: Option<String>,

#[arg(long, env = "FORESTER_PROVER_API_KEY")]
pub prover_api_key: Option<String>,

Comment on lines +58 to +60
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Avoid leaking prover_api_key in logs/debug output.

StartArgs derives Debug, which can unintentionally log the API key. Redact the value and hide env values in help/error output.

Apply this diff to avoid exposing the key in Clap output and improve UX:

-    #[arg(long, env = "FORESTER_PROVER_API_KEY")]
+    #[arg(long, env = "FORESTER_PROVER_API_KEY", hide_env_values = true, value_name = "PROVER_API_KEY")]
     pub prover_api_key: Option<String>,

Additionally, consider replacing the auto-derived Debug for StartArgs with a manual Debug that redacts secrets (outside the shown hunk). Example:

impl std::fmt::Debug for StartArgs {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("StartArgs")
            .field("rpc_url", &self.rpc_url)
            .field("push_gateway_url", &self.push_gateway_url)
            .field("pagerduty_routing_key", &self.pagerduty_routing_key.as_ref().map(|_| "<redacted>"))
            .field("ws_rpc_url", &self.ws_rpc_url)
            .field("indexer_url", &self.indexer_url)
            .field("prover_url", &self.prover_url)
            .field("prover_append_url", &self.prover_append_url)
            .field("prover_update_url", &self.prover_update_url)
            .field("prover_address_append_url", &self.prover_address_append_url)
            .field("prover_api_key", &self.prover_api_key.as_ref().map(|_| "<redacted>"))
            // ... add remaining fields as needed
            .finish()
    }
}

Or use a secret wrapper type to enforce redaction at the type level.

🤖 Prompt for AI Agents
In forester/src/cli.rs around lines 58–60, the prover_api_key field is declared
with #[arg(long, env = "FORESTER_PROVER_API_KEY")] which can expose the secret
via Clap help/error output and the auto-derived Debug; update the arg attribute
to hide environment values (e.g., add hide_env_values = true) so the env value
is not printed, and replace the auto-derived Debug for StartArgs with a manual
Debug implementation that redacts prover_api_key (e.g., display "<redacted>"
when Some) or use a secret wrapper type so the API key is never shown in logs or
help output.

#[arg(long, env = "FORESTER_PAYER")]
pub payer: Option<String>,

Expand Down
21 changes: 21 additions & 0 deletions forester/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ pub struct ExternalServicesConfig {
pub ws_rpc_url: Option<String>,
pub indexer_url: Option<String>,
pub prover_url: Option<String>,
pub prover_append_url: Option<String>,
pub prover_update_url: Option<String>,
pub prover_address_append_url: Option<String>,
pub prover_api_key: Option<String>,
pub photon_api_key: Option<String>,
Comment on lines +38 to 42
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Security: ExternalServicesConfig derives Debug and now includes secrets — redact or remove.

ExternalServicesConfig derives Debug while holding prover_api_key and photon_api_key. Any accidental debug log will leak credentials. Redact these in Debug or stop deriving Debug.

Apply a custom Debug impl that redacts secrets:

// Replace: #[derive(Debug, Clone)]
#[derive(Clone)]
pub struct ExternalServicesConfig {
    // ... fields unchanged ...
}

// Add this impl nearby
impl std::fmt::Debug for ExternalServicesConfig {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("ExternalServicesConfig")
            .field("rpc_url", &self.rpc_url)
            .field("ws_rpc_url", &self.ws_rpc_url)
            .field("indexer_url", &self.indexer_url)
            .field("prover_url", &self.prover_url)
            .field("prover_append_url", &self.prover_append_url)
            .field("prover_update_url", &self.prover_update_url)
            .field("prover_address_append_url", &self.prover_address_append_url)
            .field("prover_api_key", &"<REDACTED>")
            .field("photon_api_key", &"<REDACTED>")
            .field("pushgateway_url", &self.pushgateway_url)
            .field("pagerduty_routing_key", &self.pagerduty_routing_key)
            .field("rpc_rate_limit", &self.rpc_rate_limit)
            .field("photon_rate_limit", &self.photon_rate_limit)
            .field("send_tx_rate_limit", &self.send_tx_rate_limit)
            .finish()
    }
}

Alternatively, use a secrecy type (e.g., secrecy::SecretString) for keys, which redacts Debug output by default.

🤖 Prompt for AI Agents
In forester/src/config.rs around lines 38-42, ExternalServicesConfig currently
derives Debug while containing prover_api_key and photon_api_key; remove the
Debug derive and either implement a custom std::fmt::Debug that prints all
non-secret fields but replaces prover_api_key and photon_api_key with
"<REDACTED>", or change those two fields to a secrecy wrapper type (e.g.,
secrecy::SecretString) which already redacts Debug output; update the struct
attribute to #[derive(Clone)] and add the custom Debug impl (or change types)
nearby, ensuring any existing uses that relied on the derived Debug are updated
accordingly.

pub pushgateway_url: Option<String>,
pub pagerduty_routing_key: Option<String>,
Expand Down Expand Up @@ -210,6 +214,19 @@ impl ForesterConfig {
ws_rpc_url: args.ws_rpc_url.clone(),
indexer_url: args.indexer_url.clone(),
prover_url: args.prover_url.clone(),
prover_append_url: args
.prover_append_url
.clone()
.or_else(|| args.prover_url.clone()),
prover_update_url: args
.prover_update_url
.clone()
.or_else(|| args.prover_url.clone()),
prover_address_append_url: args
.prover_address_append_url
.clone()
.or_else(|| args.prover_url.clone()),
prover_api_key: args.prover_api_key.clone(),
photon_api_key: args.photon_api_key.clone(),
pushgateway_url: args.push_gateway_url.clone(),
pagerduty_routing_key: args.pagerduty_routing_key.clone(),
Expand Down Expand Up @@ -280,6 +297,10 @@ impl ForesterConfig {
ws_rpc_url: None,
indexer_url: None,
prover_url: None,
prover_append_url: None,
prover_update_url: None,
prover_address_append_url: None,
prover_api_key: None,
photon_api_key: None,
pushgateway_url: args.push_gateway_url.clone(),
pagerduty_routing_key: args.pagerduty_routing_key.clone(),
Expand Down
20 changes: 17 additions & 3 deletions forester/src/epoch_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1185,6 +1185,7 @@ impl<R: Rpc> EpochManager<R> {
}

async fn process_v2(&self, epoch_info: &Epoch, tree_accounts: &TreeAccounts) -> Result<usize> {
let default_prover_url = "http://127.0.0.1:3001".to_string();
let batch_context = BatchContext {
rpc_pool: self.rpc_pool.clone(),
authority: self.config.payer_keypair.insecure_clone(),
Expand All @@ -1193,12 +1194,25 @@ impl<R: Rpc> EpochManager<R> {
merkle_tree: tree_accounts.merkle_tree,
output_queue: tree_accounts.queue,
ixs_per_tx: self.config.transaction_config.batch_ixs_per_tx,
prover_url: self
prover_append_url: self
.config
.external_services
.prover_url
.prover_append_url
.clone()
.unwrap_or_else(|| "http://127.0.0.1:3001".to_string()),
.unwrap_or_else(|| default_prover_url.clone()),
prover_update_url: self
.config
.external_services
.prover_update_url
.clone()
.unwrap_or_else(|| default_prover_url.clone()),
prover_address_append_url: self
.config
.external_services
.prover_address_append_url
.clone()
.unwrap_or_else(|| default_prover_url.clone()),
prover_api_key: self.config.external_services.prover_api_key.clone(),
prover_polling_interval: Duration::from_secs(1),
prover_max_wait_time: Duration::from_secs(120),
ops_cache: self.ops_cache.clone(),
Expand Down
3 changes: 2 additions & 1 deletion forester/src/processor/v2/address.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ where
let config = AddressUpdateConfig {
rpc_pool: ctx.rpc_pool.clone(),
merkle_tree_pubkey: ctx.merkle_tree,
prover_url: ctx.prover_url.clone(),
prover_url: ctx.prover_address_append_url.clone(),
prover_api_key: ctx.prover_api_key.clone(),
polling_interval: ctx.prover_polling_interval,
max_wait_time: ctx.prover_max_wait_time,
ixs_per_tx: ctx.ixs_per_tx,
Expand Down
5 changes: 4 additions & 1 deletion forester/src/processor/v2/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,10 @@ pub struct BatchContext<R: Rpc> {
pub merkle_tree: Pubkey,
pub output_queue: Pubkey,
pub ixs_per_tx: usize,
pub prover_url: String,
pub prover_append_url: String,
pub prover_update_url: String,
pub prover_address_append_url: String,
pub prover_api_key: Option<String>,
pub prover_polling_interval: Duration,
pub prover_max_wait_time: Duration,
pub ops_cache: Arc<Mutex<ProcessedHashCache>>,
Expand Down
6 changes: 4 additions & 2 deletions forester/src/processor/v2/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ where
let (stream, size) = get_nullify_instruction_stream(
ctx.rpc_pool.clone(),
ctx.merkle_tree,
ctx.prover_url.clone(),
ctx.prover_update_url.clone(),
ctx.prover_api_key.clone(),
ctx.prover_polling_interval,
ctx.prover_max_wait_time,
merkle_tree_data,
Expand All @@ -58,7 +59,8 @@ where
let (stream, size) = get_append_instruction_stream(
ctx.rpc_pool.clone(),
ctx.merkle_tree,
ctx.prover_url.clone(),
ctx.prover_append_url.clone(),
ctx.prover_api_key.clone(),
ctx.prover_polling_interval,
ctx.prover_max_wait_time,
merkle_tree_data,
Expand Down
17 changes: 14 additions & 3 deletions forester/tests/e2e_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,13 +114,20 @@ fn get_prover_url() -> String {
}
}

fn get_api_key() -> Option<String> {
fn get_photon_api_key() -> Option<String> {
match TestMode::from_env() {
TestMode::Local => None,
TestMode::Devnet => Some(get_env_var("PHOTON_API_KEY")),
}
}

fn get_prover_api_key() -> Option<String> {
match TestMode::from_env() {
TestMode::Local => None,
TestMode::Devnet => Some(get_env_var("PROVER_API_KEY")),
}
}
Comment on lines +124 to +129
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Potential env var naming drift: PROVER_API_KEY vs FORESTER_PROVER_API_KEY.

This test uses PROVER_API_KEY, while other parts of the repo/PR (and prior notes) mention FORESTER_PROVER_API_KEY. Inconsistent naming will cause CI/test flakiness across environments.

Run this script to inventory usages and confirm a single, consistent env var name:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Env var references (PROVER_API_KEY | FORESTER_PROVER_API_KEY | PHOTON_API_KEY):"
rg -n -C1 -P 'env::var\("(PROVER_API_KEY|FORESTER_PROVER_API_KEY|PHOTON_API_KEY)"\)'

echo
echo "All occurrences of prover_api_key symbol:"
rg -n -C2 '\bprover_api_key\b'

echo
echo "StartArgs definition and field list (to confirm CLI wiring):"
rg -n -C3 -U 'struct\s+StartArgs\b.*?{' || true

echo
echo "Look for any docs or README references to prover API key to ensure consistency:"
rg -n -C2 -i 'prover api key|PROVER_API_KEY|FORESTER_PROVER_API_KEY|photon api key|PHOTON_API_KEY' || true

Length of output: 27268


Align env var names for prover API key across code, tests, and docs
The CLI is wired to FORESTER_PROVER_API_KEY, but in forester/tests/e2e_test.rs we still call get_env_var("PROVER_API_KEY"). This mismatch (and the equivalent one for PHOTON_API_KEY) will break in CI when only the FORESTER_… vars are set. Update as follows:

• In forester/tests/e2e_test.rs, change get_prover_api_key to use "FORESTER_PROVER_API_KEY":

 fn get_prover_api_key() -> Option<String> {
     match TestMode::from_env() {
         TestMode::Local => None,
-        TestMode::Devnet => Some(get_env_var("PROVER_API_KEY")),
+        TestMode::Devnet => Some(get_env_var("FORESTER_PROVER_API_KEY")),
     }
 }

• Likewise, in the same file update get_photon_api_key to "FORESTER_PHOTON_API_KEY":

 fn get_photon_api_key() -> Option<String> {
     match TestMode::from_env() {
         TestMode::Local => None,
-        TestMode::Devnet => Some(get_env_var("PHOTON_API_KEY")),
+        TestMode::Devnet => Some(get_env_var("FORESTER_PHOTON_API_KEY")),
     }
 }

• Update forester/README.md examples to consistently reference FORESTER_PROVER_API_KEY and FORESTER_PHOTON_API_KEY instead of the unprefixed names.

These fixes will ensure the env-var wiring is uniform and tests won’t silently fail in CI.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
fn get_prover_api_key() -> Option<String> {
match TestMode::from_env() {
TestMode::Local => None,
TestMode::Devnet => Some(get_env_var("PROVER_API_KEY")),
}
}
// forester/tests/e2e_test.rs
fn get_prover_api_key() -> Option<String> {
match TestMode::from_env() {
TestMode::Local => None,
TestMode::Devnet => Some(get_env_var("FORESTER_PROVER_API_KEY")),
}
}
fn get_photon_api_key() -> Option<String> {
match TestMode::from_env() {
TestMode::Local => None,
TestMode::Devnet => Some(get_env_var("FORESTER_PHOTON_API_KEY")),
}
}
🤖 Prompt for AI Agents
In forester/tests/e2e_test.rs around lines 124 to 129, the test helper uses the
unprefixed env var names ("PROVER_API_KEY" and similarly "PHOTON_API_KEY") while
the CLI and CI expect the FORESTER_ prefixed names, causing CI failures; update
get_prover_api_key to call get_env_var("FORESTER_PROVER_API_KEY") and update
get_photon_api_key to call get_env_var("FORESTER_PHOTON_API_KEY") accordingly,
then also update forester/README.md examples to reference
FORESTER_PROVER_API_KEY and FORESTER_PHOTON_API_KEY so docs, tests, and CLI use
the same env var names.


fn get_forester_keypair() -> Keypair {
match TestMode::from_env() {
TestMode::Local => Keypair::new(),
Expand Down Expand Up @@ -189,7 +196,11 @@ async fn e2e_test() {
ws_rpc_url: Some(get_ws_rpc_url()),
indexer_url: Some(get_indexer_url()),
prover_url: Some(get_prover_url()),
photon_api_key: get_api_key(),
prover_append_url: None,
prover_update_url: None,
prover_address_append_url: None,
prover_api_key: get_prover_api_key(),
photon_api_key: get_photon_api_key(),
pushgateway_url: None,
pagerduty_routing_key: None,
rpc_rate_limit: None,
Expand Down Expand Up @@ -453,7 +464,7 @@ async fn setup_rpc_connection(forester: &Keypair) -> LightClient {
let mut rpc = LightClient::new(if TestMode::from_env() == TestMode::Local {
LightClientConfig::local()
} else {
LightClientConfig::new(get_rpc_url(), Some(get_indexer_url()), get_api_key())
LightClientConfig::new(get_rpc_url(), Some(get_indexer_url()), get_photon_api_key())
})
.await
.unwrap();
Expand Down
4 changes: 4 additions & 0 deletions forester/tests/priority_fee_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ async fn test_priority_fee_request() {
std::env::var("FORESTER_PROVER_URL")
.expect("FORESTER_PROVER_URL must be set in environment"),
),
prover_append_url: None,
prover_update_url: None,
prover_address_append_url: None,
prover_api_key: None,
payer: Some(
std::env::var("FORESTER_PAYER").expect("FORESTER_PAYER must be set in environment"),
),
Expand Down
4 changes: 4 additions & 0 deletions forester/tests/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ pub fn forester_config() -> ForesterConfig {
ws_rpc_url: Some("ws://localhost:8900".to_string()),
indexer_url: Some("http://localhost:8784".to_string()),
prover_url: Some("http://localhost:3001".to_string()),
prover_append_url: None,
prover_update_url: None,
prover_address_append_url: None,
prover_api_key: None,
photon_api_key: None,
pushgateway_url: None,
pagerduty_routing_key: None,
Expand Down
64 changes: 31 additions & 33 deletions js/compressed-token/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
## [0.22.0]

- `CreateMint` action now allows passing a non-payer mint and freeze authority.
- More efficient computebudgets for actions.
- Better DX: Parameter lookup in call signatures of CompressedTokenProgram instructions
- QoL: improved typedocs.
- `CreateMint` action now allows passing a non-payer mint and freeze authority.
- More efficient computebudgets for actions.
- Better DX: Parameter lookup in call signatures of CompressedTokenProgram instructions
- QoL: improved typedocs.
Comment on lines +3 to +6
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix minor wording/typos

  • “computebudgets” → “compute budgets”
  • “typedocs” → “TypeDoc comments”

Apply this diff:

-- More efficient computebudgets for actions.
-— QoL: improved typedocs.
+- More efficient compute budgets for actions.
+- QoL: improved TypeDoc comments.

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 LanguageTool

[grammar] ~3-~3: There might be a mistake here.
Context: ...g a non-payer mint and freeze authority. - More efficient computebudgets for action...

(QB_NEW_EN)


[grammar] ~4-~4: There might be a mistake here.
Context: ...re efficient computebudgets for actions. - Better DX: Parameter lookup in call sign...

(QB_NEW_EN)

🤖 Prompt for AI Agents
In js/compressed-token/CHANGELOG.md around lines 3 to 6, fix the minor
wording/typos: change “computebudgets” to “compute budgets” and change
“typedocs” to “TypeDoc comments” so the bullet list reads with the corrected
terms; update only those words preserving the rest of the lines and punctuation.


## [0.21.0]

Expand Down Expand Up @@ -58,25 +58,23 @@ const ix = await CompressedTokenProgram.decompress({

### Overview

- new type: TokenPoolInfo
- Instruction Changes:
- new type: TokenPoolInfo
- Instruction Changes:
- `compress`, `mintTo`, `approveAndMintTo`, `compressSplTokenAccount` now require valid TokenPoolInfo
- `decompress` now requires an array of one or more TokenPoolInfos.
- `decompress`, `transfer` now do not allow state tree overrides.

- `compress`, `mintTo`, `approveAndMintTo`, `compressSplTokenAccount` now require valid TokenPoolInfo
- `decompress` now requires an array of one or more TokenPoolInfos.
- `decompress`, `transfer` now do not allow state tree overrides.
- Action Changes:
- Removed optional tokenProgramId: PublicKey
- removed optional merkleTree: PublicKey
- removed optional outputStateTree: PublicKey
- added optional stateTreeInfo: StateTreeInfo
- added optional tokenPoolInfo: TokenPoolInfo

- Action Changes:

- Removed optional tokenProgramId: PublicKey
- removed optional merkleTree: PublicKey
- removed optional outputStateTree: PublicKey
- added optional stateTreeInfo: StateTreeInfo
- added optional tokenPoolInfo: TokenPoolInfo

- new instructions:
- `approve`, `revoke`: delegated transfer support.
- `addTokenPools`: you can now register additional token pool pdas. Use
this if you need very high concurrency.
- new instructions:
- `approve`, `revoke`: delegated transfer support.
- `addTokenPools`: you can now register additional token pool pdas. Use
this if you need very high concurrency.

### Why the Changes are helpful

Expand All @@ -96,32 +94,32 @@ accounts.

### Changed

- improved documentation and error messages.
- improved documentation and error messages.

## [0.20.4] - 2025-02-19

### Breaking Changes

- `selectMinCompressedTokenAccountsForTransfer` and
`selectSmartCompressedTokenAccountsForTransfer` now throw an error
if not enough accounts are found. In most cases this is not a breaking
change, because a proof request would fail anyway. This just makes the error
message more informative.
- `selectMinCompressedTokenAccountsForTransfer` and
`selectSmartCompressedTokenAccountsForTransfer` now throw an error
if not enough accounts are found. In most cases this is not a breaking
change, because a proof request would fail anyway. This just makes the error
message more informative.

### Added

- `selectSmartCompressedTokenAccountsForTransfer` and
`selectSmartCompressedTokenAccountsForTransferOrPartial`
- `selectSmartCompressedTokenAccountsForTransfer` and
`selectSmartCompressedTokenAccountsForTransferOrPartial`

### Changed

- `selectMinCompressedTokenAccountsForTransfer` and
`selectMinCompressedTokenAccountsForTransferorPartial` now accept an optional
`maxInputs` parameter, defaulting to 4.
- `selectMinCompressedTokenAccountsForTransfer` and
`selectMinCompressedTokenAccountsForTransferorPartial` now accept an optional
`maxInputs` parameter, defaulting to 4.

Comment on lines +116 to 119
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Typo: method name casing

Looks like a stray typo in the method name (“TransferorPartial”). Should be TransferOrPartial to match the casing used elsewhere.

Apply this diff:

-  `selectMinCompressedTokenAccountsForTransferorPartial` now accept an optional
+  `selectMinCompressedTokenAccountsForTransferOrPartial` now accept an optional
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- `selectMinCompressedTokenAccountsForTransfer` and
`selectMinCompressedTokenAccountsForTransferorPartial` now accept an optional
`maxInputs` parameter, defaulting to 4.
- `selectMinCompressedTokenAccountsForTransfer` and
`selectMinCompressedTokenAccountsForTransferOrPartial` now accept an optional
`maxInputs` parameter, defaulting to 4.
🤖 Prompt for AI Agents
In js/compressed-token/CHANGELOG.md around lines 116 to 119, the method name
casing contains a typo "TransferorPartial"; update the text to use the correct
casing "TransferOrPartial" so it matches the rest of the codebase and other
references, i.e., replace "selectMinCompressedTokenAccountsForTransferorPartial"
with "selectMinCompressedTokenAccountsForTransferOrPartial".

### Security

- N/A
- N/A

For previous release notes, check:
https://www.zkcompression.com/release-notes/1.0.0-mainnet-beta
Loading
Loading