Enable base58 and base64 encoding parameters for Memcmp filters (#26437)

* Minor refactoring of client RpcProgramAccountsConfig handling

* Enable explicit base58/base64 encoding of Memcmp filters, including client backward compatibility with nodes on old software

* Deprecate Memcmp::Encoding

* Remove deprecation warnings in rpc

* Remove deprecation warnings in cli

* Update docs

* Make variants self-documenting
This commit is contained in:
Tyera Eulberg 2022-07-06 22:39:03 -06:00 committed by GitHub
parent e2e3c31250
commit f2abbcaf9c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 207 additions and 194 deletions

View File

@ -1776,32 +1776,24 @@ pub fn process_show_stakes(
if vote_account_pubkeys.len() == 1 {
program_accounts_config.filters = Some(vec![
// Filter by `StakeState::Stake(_, _)`
rpc_filter::RpcFilterType::Memcmp(rpc_filter::Memcmp {
offset: 0,
bytes: rpc_filter::MemcmpEncodedBytes::Base58(
bs58::encode([2, 0, 0, 0]).into_string(),
),
encoding: Some(rpc_filter::MemcmpEncoding::Binary),
}),
rpc_filter::RpcFilterType::Memcmp(rpc_filter::Memcmp::new_base58_encoded(
0,
&[2, 0, 0, 0],
)),
// Filter by `Delegation::voter_pubkey`, which begins at byte offset 124
rpc_filter::RpcFilterType::Memcmp(rpc_filter::Memcmp {
offset: 124,
bytes: rpc_filter::MemcmpEncodedBytes::Base58(
vote_account_pubkeys[0].to_string(),
),
encoding: Some(rpc_filter::MemcmpEncoding::Binary),
}),
rpc_filter::RpcFilterType::Memcmp(rpc_filter::Memcmp::new_base58_encoded(
124,
vote_account_pubkeys[0].as_ref(),
)),
]);
}
}
if let Some(withdraw_authority_pubkey) = withdraw_authority_pubkey {
// withdrawer filter
let withdrawer_filter = rpc_filter::RpcFilterType::Memcmp(rpc_filter::Memcmp {
offset: 44,
bytes: rpc_filter::MemcmpEncodedBytes::Base58(withdraw_authority_pubkey.to_string()),
encoding: Some(rpc_filter::MemcmpEncoding::Binary),
});
let withdrawer_filter = rpc_filter::RpcFilterType::Memcmp(
rpc_filter::Memcmp::new_base58_encoded(44, withdraw_authority_pubkey.as_ref()),
);
let filters = program_accounts_config.filters.get_or_insert(vec![]);
filters.push(withdrawer_filter);

View File

@ -22,7 +22,7 @@ use {
connection_cache::ConnectionCache,
rpc_client::RpcClient,
rpc_config::{RpcAccountInfoConfig, RpcProgramAccountsConfig, RpcSendTransactionConfig},
rpc_filter::{Memcmp, MemcmpEncodedBytes, RpcFilterType},
rpc_filter::{Memcmp, RpcFilterType},
tpu_client::{TpuClient, TpuClientConfig},
},
solana_program_runtime::invoke_context::InvokeContext,
@ -1203,24 +1203,19 @@ fn get_buffers(
authority_pubkey: Option<Pubkey>,
use_lamports_unit: bool,
) -> Result<CliUpgradeableBuffers, Box<dyn std::error::Error>> {
let mut filters = vec![RpcFilterType::Memcmp(Memcmp {
offset: 0,
bytes: MemcmpEncodedBytes::Base58(bs58::encode(vec![1, 0, 0, 0]).into_string()),
encoding: None,
})];
let mut filters = vec![RpcFilterType::Memcmp(Memcmp::new_base58_encoded(
0,
&[1, 0, 0, 0],
))];
if let Some(authority_pubkey) = authority_pubkey {
filters.push(RpcFilterType::Memcmp(Memcmp {
offset: ACCOUNT_TYPE_SIZE,
bytes: MemcmpEncodedBytes::Base58(bs58::encode(vec![1]).into_string()),
encoding: None,
}));
filters.push(RpcFilterType::Memcmp(Memcmp {
offset: ACCOUNT_TYPE_SIZE + OPTION_SIZE,
bytes: MemcmpEncodedBytes::Base58(
bs58::encode(authority_pubkey.as_ref()).into_string(),
),
encoding: None,
}));
filters.push(RpcFilterType::Memcmp(Memcmp::new_base58_encoded(
ACCOUNT_TYPE_SIZE,
&[1],
)));
filters.push(RpcFilterType::Memcmp(Memcmp::new_base58_encoded(
ACCOUNT_TYPE_SIZE + OPTION_SIZE,
authority_pubkey.as_ref(),
)));
}
let results = get_accounts_with_filter(
@ -1256,24 +1251,19 @@ fn get_programs(
authority_pubkey: Option<Pubkey>,
use_lamports_unit: bool,
) -> Result<CliUpgradeablePrograms, Box<dyn std::error::Error>> {
let mut filters = vec![RpcFilterType::Memcmp(Memcmp {
offset: 0,
bytes: MemcmpEncodedBytes::Base58(bs58::encode(vec![3, 0, 0, 0]).into_string()),
encoding: None,
})];
let mut filters = vec![RpcFilterType::Memcmp(Memcmp::new_base58_encoded(
0,
&[3, 0, 0, 0],
))];
if let Some(authority_pubkey) = authority_pubkey {
filters.push(RpcFilterType::Memcmp(Memcmp {
offset: ACCOUNT_TYPE_SIZE + SLOT_SIZE,
bytes: MemcmpEncodedBytes::Base58(bs58::encode(vec![1]).into_string()),
encoding: None,
}));
filters.push(RpcFilterType::Memcmp(Memcmp {
offset: ACCOUNT_TYPE_SIZE + SLOT_SIZE + OPTION_SIZE,
bytes: MemcmpEncodedBytes::Base58(
bs58::encode(authority_pubkey.as_ref()).into_string(),
),
encoding: None,
}));
filters.push(RpcFilterType::Memcmp(Memcmp::new_base58_encoded(
ACCOUNT_TYPE_SIZE + SLOT_SIZE,
&[1],
)));
filters.push(RpcFilterType::Memcmp(Memcmp::new_base58_encoded(
ACCOUNT_TYPE_SIZE + SLOT_SIZE + OPTION_SIZE,
authority_pubkey.as_ref(),
)));
}
let results = get_accounts_with_filter(
@ -1291,11 +1281,7 @@ fn get_programs(
{
let mut bytes = vec![2, 0, 0, 0];
bytes.extend_from_slice(programdata_address.as_ref());
let filters = vec![RpcFilterType::Memcmp(Memcmp {
offset: 0,
bytes: MemcmpEncodedBytes::Base58(bs58::encode(bytes).into_string()),
encoding: None,
})];
let filters = vec![RpcFilterType::Memcmp(Memcmp::new_base58_encoded(0, &bytes))];
let results = get_accounts_with_filter(rpc_client, filters, 0)?;
if results.len() != 1 {

View File

@ -19,6 +19,7 @@ use {
mock_sender::MockSender,
rpc_client::{GetConfirmedSignaturesForAddress2Config, RpcClientConfig},
rpc_config::{RpcAccountInfoConfig, *},
rpc_filter::{MemcmpEncodedBytes, RpcFilterType},
rpc_request::{RpcError, RpcRequest, RpcResponseErrorData, TokenAccountsFilter},
rpc_response::*,
rpc_sender::*,
@ -580,6 +581,33 @@ impl RpcClient {
Ok(request)
}
#[allow(deprecated)]
async fn maybe_map_filters(
&self,
mut filters: Vec<RpcFilterType>,
) -> Result<Vec<RpcFilterType>, RpcError> {
let node_version = self.get_node_version().await?;
if node_version < semver::Version::new(1, 11, 2) {
for filter in filters.iter_mut() {
if let RpcFilterType::Memcmp(memcmp) = filter {
match &memcmp.bytes {
MemcmpEncodedBytes::Base58(string) => {
memcmp.bytes = MemcmpEncodedBytes::Binary(string.clone());
}
MemcmpEncodedBytes::Base64(_) => {
return Err(RpcError::RpcRequestError(format!(
"RPC node on old version {} does not support base64 encoding for memcmp filters",
node_version
)));
}
_ => {}
}
}
}
}
Ok(filters)
}
/// Submit a transaction and wait for confirmation.
///
/// Once this function returns successfully, the given transaction is
@ -4490,21 +4518,17 @@ impl RpcClient {
pub async fn get_program_accounts_with_config(
&self,
pubkey: &Pubkey,
config: RpcProgramAccountsConfig,
mut config: RpcProgramAccountsConfig,
) -> ClientResult<Vec<(Pubkey, Account)>> {
let commitment = config
.account_config
.commitment
.unwrap_or_else(|| self.commitment());
let commitment = self.maybe_map_commitment(commitment).await?;
let account_config = RpcAccountInfoConfig {
commitment: Some(commitment),
..config.account_config
};
let config = RpcProgramAccountsConfig {
account_config,
..config
};
config.account_config.commitment = Some(commitment);
if let Some(filters) = config.filters {
config.filters = Some(self.maybe_map_filters(filters).await?);
}
let accounts: Vec<RpcKeyedAccount> = self
.send(
RpcRequest::GetProgramAccounts,

View File

@ -129,16 +129,37 @@ pub enum MemcmpEncodedBytes {
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(into = "RpcMemcmp", from = "RpcMemcmp")]
pub struct Memcmp {
/// Data offset to begin match
pub offset: usize,
/// Bytes, encoded with specified encoding, or default Binary
pub bytes: MemcmpEncodedBytes,
/// Optional encoding specification
#[deprecated(
since = "1.11.2",
note = "Field has no server-side effect. Specify encoding with `MemcmpEncodedBytes` variant instead."
)]
pub encoding: Option<MemcmpEncoding>,
}
impl Memcmp {
pub fn new_raw_bytes(offset: usize, bytes: Vec<u8>) -> Self {
Self {
offset,
bytes: MemcmpEncodedBytes::Bytes(bytes),
encoding: None,
}
}
pub fn new_base58_encoded(offset: usize, bytes: &[u8]) -> Self {
Self {
offset,
bytes: MemcmpEncodedBytes::Base58(bs58::encode(bytes).into_string()),
encoding: None,
}
}
pub fn bytes(&self) -> Option<Cow<Vec<u8>>> {
use MemcmpEncodedBytes::*;
match &self.bytes {
@ -164,6 +185,80 @@ impl Memcmp {
}
}
// Internal struct to hold Memcmp filter data as either encoded String or raw Bytes
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(untagged)]
enum DataType {
Encoded(String),
Raw(Vec<u8>),
}
// Internal struct used to specify explicit Base58 and Base64 encoding
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
enum RpcMemcmpEncoding {
Base58,
Base64,
// This variant exists only to preserve backward compatibility with generic `Memcmp` serde
#[serde(other)]
Binary,
}
// Internal struct to enable Memcmp filters with explicit Base58 and Base64 encoding. The From
// implementations emulate `#[serde(tag = "encoding", content = "bytes")]` for
// `MemcmpEncodedBytes`. On the next major version, all these internal elements should be removed
// and replaced with adjacent tagging of `MemcmpEncodedBytes`.
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
struct RpcMemcmp {
offset: usize,
bytes: DataType,
encoding: Option<RpcMemcmpEncoding>,
}
impl From<Memcmp> for RpcMemcmp {
fn from(memcmp: Memcmp) -> RpcMemcmp {
let (bytes, encoding) = match memcmp.bytes {
MemcmpEncodedBytes::Binary(string) => {
(DataType::Encoded(string), Some(RpcMemcmpEncoding::Binary))
}
MemcmpEncodedBytes::Base58(string) => {
(DataType::Encoded(string), Some(RpcMemcmpEncoding::Base58))
}
MemcmpEncodedBytes::Base64(string) => {
(DataType::Encoded(string), Some(RpcMemcmpEncoding::Base64))
}
MemcmpEncodedBytes::Bytes(vector) => (DataType::Raw(vector), None),
};
RpcMemcmp {
offset: memcmp.offset,
bytes,
encoding,
}
}
}
impl From<RpcMemcmp> for Memcmp {
fn from(memcmp: RpcMemcmp) -> Memcmp {
let encoding = memcmp.encoding.unwrap_or(RpcMemcmpEncoding::Binary);
let bytes = match (encoding, memcmp.bytes) {
(RpcMemcmpEncoding::Binary, DataType::Encoded(string))
| (RpcMemcmpEncoding::Base58, DataType::Encoded(string)) => {
MemcmpEncodedBytes::Base58(string)
}
(RpcMemcmpEncoding::Binary, DataType::Raw(vector)) => MemcmpEncodedBytes::Bytes(vector),
(RpcMemcmpEncoding::Base64, DataType::Encoded(string)) => {
MemcmpEncodedBytes::Base64(string)
}
_ => unreachable!(),
};
Memcmp {
offset: memcmp.offset,
bytes,
encoding: None,
}
}
}
#[cfg(test)]
mod tests {
use super::*;

View File

@ -1906,7 +1906,9 @@ Returns all accounts owned by the provided program Pubkey
- `memcmp: <object>` - compares a provided series of bytes with program account data at a particular offset. Fields:
- `offset: <usize>` - offset into program account data to start comparison
- `bytes: <string>` - data to match, as base-58 encoded string and limited to less than 129 bytes
- `bytes: <string>` - data to match, as encoded string
- `encoding: <string>` - encoding for filter `bytes` data, either "base58" or "base64". Data is limited in size to 128 or fewer decoded bytes.
**NEW: This field, and base64 support generally, is only available in solana-core v1.11.2 or newer. Please omit when querying nodes on earlier versions**
- `dataSize: <u64>` - compares the program account data length with the provided data size

View File

@ -1899,11 +1899,10 @@ impl JsonRpcRequestProcessor {
let mut filters = vec![];
if let Some(mint) = mint {
// Optional filter on Mint address
filters.push(RpcFilterType::Memcmp(Memcmp {
offset: 0,
bytes: MemcmpEncodedBytes::Bytes(mint.to_bytes().into()),
encoding: None,
}));
filters.push(RpcFilterType::Memcmp(Memcmp::new_raw_bytes(
0,
mint.to_bytes().into(),
)));
}
let keyed_accounts = self.get_filtered_spl_token_accounts_by_owner(
@ -1950,17 +1949,12 @@ impl JsonRpcRequestProcessor {
let mut filters = vec![
// Filter on Delegate is_some()
RpcFilterType::Memcmp(Memcmp {
offset: 72,
bytes: MemcmpEncodedBytes::Bytes(bincode::serialize(&1u32).unwrap()),
encoding: None,
}),
RpcFilterType::Memcmp(Memcmp::new_raw_bytes(
72,
bincode::serialize(&1u32).unwrap(),
)),
// Filter on Delegate address
RpcFilterType::Memcmp(Memcmp {
offset: 76,
bytes: MemcmpEncodedBytes::Bytes(delegate.to_bytes().into()),
encoding: None,
}),
RpcFilterType::Memcmp(Memcmp::new_raw_bytes(76, delegate.to_bytes().into())),
];
// Optional filter on Mint address, uses mint account index for scan
let keyed_accounts = if let Some(mint) = mint {
@ -2052,11 +2046,10 @@ impl JsonRpcRequestProcessor {
// Filter on Token Account state
filters.push(RpcFilterType::TokenAccountState);
// Filter on Owner address
filters.push(RpcFilterType::Memcmp(Memcmp {
offset: SPL_TOKEN_ACCOUNT_OWNER_OFFSET,
bytes: MemcmpEncodedBytes::Bytes(owner_key.to_bytes().into()),
encoding: None,
}));
filters.push(RpcFilterType::Memcmp(Memcmp::new_raw_bytes(
SPL_TOKEN_ACCOUNT_OWNER_OFFSET,
owner_key.to_bytes().into(),
)));
if self
.config
@ -2104,11 +2097,10 @@ impl JsonRpcRequestProcessor {
// Filter on Token Account state
filters.push(RpcFilterType::TokenAccountState);
// Filter on Mint address
filters.push(RpcFilterType::Memcmp(Memcmp {
offset: SPL_TOKEN_ACCOUNT_MINT_OFFSET,
bytes: MemcmpEncodedBytes::Bytes(mint_key.to_bytes().into()),
encoding: None,
}));
filters.push(RpcFilterType::Memcmp(Memcmp::new_raw_bytes(
SPL_TOKEN_ACCOUNT_MINT_OFFSET,
mint_key.to_bytes().into(),
)));
if self
.config
.account_indexes
@ -6402,6 +6394,7 @@ pub mod tests {
#[test]
fn test_rpc_verify_filter() {
#[allow(deprecated)]
let filter = RpcFilterType::Memcmp(Memcmp {
offset: 0,
bytes: MemcmpEncodedBytes::Base58(
@ -6411,6 +6404,7 @@ pub mod tests {
});
assert_eq!(verify_filter(&filter), Ok(()));
// Invalid base-58
#[allow(deprecated)]
let filter = RpcFilterType::Memcmp(Memcmp {
offset: 0,
bytes: MemcmpEncodedBytes::Base58("III".to_string()),
@ -7967,11 +7961,7 @@ pub mod tests {
get_spl_token_owner_filter(
&Pubkey::from_str("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA").unwrap(),
&[
RpcFilterType::Memcmp(Memcmp {
offset: 32,
bytes: MemcmpEncodedBytes::Bytes(owner.to_bytes().to_vec()),
encoding: None
}),
RpcFilterType::Memcmp(Memcmp::new_raw_bytes(32, owner.to_bytes().to_vec())),
RpcFilterType::DataSize(165)
],
)
@ -7984,16 +7974,8 @@ pub mod tests {
get_spl_token_owner_filter(
&Pubkey::from_str("TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb").unwrap(),
&[
RpcFilterType::Memcmp(Memcmp {
offset: 32,
bytes: MemcmpEncodedBytes::Bytes(owner.to_bytes().to_vec()),
encoding: None
}),
RpcFilterType::Memcmp(Memcmp {
offset: 165,
bytes: MemcmpEncodedBytes::Bytes(vec![ACCOUNTTYPE_ACCOUNT]),
encoding: None
})
RpcFilterType::Memcmp(Memcmp::new_raw_bytes(32, owner.to_bytes().to_vec())),
RpcFilterType::Memcmp(Memcmp::new_raw_bytes(165, vec![ACCOUNTTYPE_ACCOUNT])),
],
)
.unwrap(),
@ -8005,11 +7987,7 @@ pub mod tests {
get_spl_token_owner_filter(
&Pubkey::from_str("TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb").unwrap(),
&[
RpcFilterType::Memcmp(Memcmp {
offset: 32,
bytes: MemcmpEncodedBytes::Bytes(owner.to_bytes().to_vec()),
encoding: None
}),
RpcFilterType::Memcmp(Memcmp::new_raw_bytes(32, owner.to_bytes().to_vec())),
RpcFilterType::TokenAccountState,
],
)
@ -8021,16 +7999,8 @@ pub mod tests {
assert!(get_spl_token_owner_filter(
&Pubkey::from_str("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA").unwrap(),
&[
RpcFilterType::Memcmp(Memcmp {
offset: 32,
bytes: MemcmpEncodedBytes::Bytes(owner.to_bytes().to_vec()),
encoding: None
}),
RpcFilterType::Memcmp(Memcmp {
offset: 165,
bytes: MemcmpEncodedBytes::Bytes(vec![ACCOUNTTYPE_ACCOUNT]),
encoding: None
})
RpcFilterType::Memcmp(Memcmp::new_raw_bytes(32, owner.to_bytes().to_vec())),
RpcFilterType::Memcmp(Memcmp::new_raw_bytes(165, vec![ACCOUNTTYPE_ACCOUNT])),
],
)
.is_none());
@ -8039,11 +8009,7 @@ pub mod tests {
assert!(get_spl_token_owner_filter(
&Pubkey::from_str("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA").unwrap(),
&[
RpcFilterType::Memcmp(Memcmp {
offset: 0,
bytes: MemcmpEncodedBytes::Bytes(owner.to_bytes().to_vec()),
encoding: None
}),
RpcFilterType::Memcmp(Memcmp::new_raw_bytes(0, owner.to_bytes().to_vec())),
RpcFilterType::DataSize(165)
],
)
@ -8053,11 +8019,7 @@ pub mod tests {
assert!(get_spl_token_owner_filter(
&Pubkey::new_unique(),
&[
RpcFilterType::Memcmp(Memcmp {
offset: 32,
bytes: MemcmpEncodedBytes::Bytes(owner.to_bytes().to_vec()),
encoding: None
}),
RpcFilterType::Memcmp(Memcmp::new_raw_bytes(32, owner.to_bytes().to_vec())),
RpcFilterType::DataSize(165)
],
)
@ -8065,16 +8027,8 @@ pub mod tests {
assert!(get_spl_token_owner_filter(
&Pubkey::new_unique(),
&[
RpcFilterType::Memcmp(Memcmp {
offset: 32,
bytes: MemcmpEncodedBytes::Bytes(owner.to_bytes().to_vec()),
encoding: None
}),
RpcFilterType::Memcmp(Memcmp {
offset: 165,
bytes: MemcmpEncodedBytes::Bytes(vec![ACCOUNTTYPE_ACCOUNT]),
encoding: None
})
RpcFilterType::Memcmp(Memcmp::new_raw_bytes(32, owner.to_bytes().to_vec())),
RpcFilterType::Memcmp(Memcmp::new_raw_bytes(165, vec![ACCOUNTTYPE_ACCOUNT])),
],
)
.is_none());
@ -8088,11 +8042,7 @@ pub mod tests {
get_spl_token_mint_filter(
&Pubkey::from_str("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA").unwrap(),
&[
RpcFilterType::Memcmp(Memcmp {
offset: 0,
bytes: MemcmpEncodedBytes::Bytes(mint.to_bytes().to_vec()),
encoding: None
}),
RpcFilterType::Memcmp(Memcmp::new_raw_bytes(0, mint.to_bytes().to_vec())),
RpcFilterType::DataSize(165)
],
)
@ -8105,16 +8055,8 @@ pub mod tests {
get_spl_token_mint_filter(
&Pubkey::from_str("TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb").unwrap(),
&[
RpcFilterType::Memcmp(Memcmp {
offset: 0,
bytes: MemcmpEncodedBytes::Bytes(mint.to_bytes().to_vec()),
encoding: None
}),
RpcFilterType::Memcmp(Memcmp {
offset: 165,
bytes: MemcmpEncodedBytes::Bytes(vec![ACCOUNTTYPE_ACCOUNT]),
encoding: None
})
RpcFilterType::Memcmp(Memcmp::new_raw_bytes(0, mint.to_bytes().to_vec())),
RpcFilterType::Memcmp(Memcmp::new_raw_bytes(165, vec![ACCOUNTTYPE_ACCOUNT])),
],
)
.unwrap(),
@ -8126,11 +8068,7 @@ pub mod tests {
get_spl_token_mint_filter(
&Pubkey::from_str("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA").unwrap(),
&[
RpcFilterType::Memcmp(Memcmp {
offset: 0,
bytes: MemcmpEncodedBytes::Bytes(mint.to_bytes().to_vec()),
encoding: None
}),
RpcFilterType::Memcmp(Memcmp::new_raw_bytes(0, mint.to_bytes().to_vec())),
RpcFilterType::TokenAccountState,
],
)
@ -8142,16 +8080,8 @@ pub mod tests {
assert!(get_spl_token_mint_filter(
&Pubkey::from_str("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA").unwrap(),
&[
RpcFilterType::Memcmp(Memcmp {
offset: 0,
bytes: MemcmpEncodedBytes::Bytes(mint.to_bytes().to_vec()),
encoding: None
}),
RpcFilterType::Memcmp(Memcmp {
offset: 165,
bytes: MemcmpEncodedBytes::Bytes(vec![ACCOUNTTYPE_ACCOUNT]),
encoding: None
})
RpcFilterType::Memcmp(Memcmp::new_raw_bytes(0, mint.to_bytes().to_vec())),
RpcFilterType::Memcmp(Memcmp::new_raw_bytes(165, vec![ACCOUNTTYPE_ACCOUNT])),
],
)
.is_none());
@ -8160,11 +8090,7 @@ pub mod tests {
assert!(get_spl_token_mint_filter(
&Pubkey::from_str("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA").unwrap(),
&[
RpcFilterType::Memcmp(Memcmp {
offset: 32,
bytes: MemcmpEncodedBytes::Bytes(mint.to_bytes().to_vec()),
encoding: None
}),
RpcFilterType::Memcmp(Memcmp::new_raw_bytes(32, mint.to_bytes().to_vec())),
RpcFilterType::DataSize(165)
],
)
@ -8174,11 +8100,7 @@ pub mod tests {
assert!(get_spl_token_mint_filter(
&Pubkey::new_unique(),
&[
RpcFilterType::Memcmp(Memcmp {
offset: 0,
bytes: MemcmpEncodedBytes::Bytes(mint.to_bytes().to_vec()),
encoding: None
}),
RpcFilterType::Memcmp(Memcmp::new_raw_bytes(0, mint.to_bytes().to_vec())),
RpcFilterType::DataSize(165)
],
)
@ -8186,16 +8108,8 @@ pub mod tests {
assert!(get_spl_token_mint_filter(
&Pubkey::new_unique(),
&[
RpcFilterType::Memcmp(Memcmp {
offset: 0,
bytes: MemcmpEncodedBytes::Bytes(mint.to_bytes().to_vec()),
encoding: None
}),
RpcFilterType::Memcmp(Memcmp {
offset: 165,
bytes: MemcmpEncodedBytes::Bytes(vec![ACCOUNTTYPE_ACCOUNT]),
encoding: None
})
RpcFilterType::Memcmp(Memcmp::new_raw_bytes(0, mint.to_bytes().to_vec())),
RpcFilterType::Memcmp(Memcmp::new_raw_bytes(165, vec![ACCOUNTTYPE_ACCOUNT])),
],
)
.is_none());