From 652eecad33d01ee60d2527661ea3bccc2cc2e9ec Mon Sep 17 00:00:00 2001 From: Kirill Fomichev Date: Sun, 19 Nov 2023 21:31:02 -0500 Subject: [PATCH 01/23] fmt --- .../src/dao/generated/cl_audits.rs | 4 ++-- digital_asset_types/src/dao/scopes/asset.rs | 6 +++--- digital_asset_types/src/dapi/common/asset.rs | 14 +++----------- nft_ingester/src/account_updates.rs | 6 +++++- nft_ingester/src/database.rs | 16 ++++++++++------ nft_ingester/src/main.rs | 4 ++-- nft_ingester/src/metrics.rs | 9 ++------- nft_ingester/src/stream.rs | 6 ++---- nft_ingester/src/transaction_notifications.rs | 10 ++++++---- rust-toolchain.toml | 2 +- tools/acc_forwarder/src/main.rs | 6 +++++- 11 files changed, 41 insertions(+), 42 deletions(-) diff --git a/digital_asset_types/src/dao/generated/cl_audits.rs b/digital_asset_types/src/dao/generated/cl_audits.rs index a07714202..d3c553f0d 100644 --- a/digital_asset_types/src/dao/generated/cl_audits.rs +++ b/digital_asset_types/src/dao/generated/cl_audits.rs @@ -89,6 +89,6 @@ impl From for ActiveModel { seq: item.seq, leaf_idx: item.leaf_idx, ..Default::default() - } + }; } -} \ No newline at end of file +} diff --git a/digital_asset_types/src/dao/scopes/asset.rs b/digital_asset_types/src/dao/scopes/asset.rs index cd9db02ba..09a42bec0 100644 --- a/digital_asset_types/src/dao/scopes/asset.rs +++ b/digital_asset_types/src/dao/scopes/asset.rs @@ -1,11 +1,11 @@ use crate::{ dao::{ asset::{self, Entity}, - asset_authority, asset_creators, asset_data, asset_grouping, FullAsset, - GroupingSize, Pagination, + asset_authority, asset_creators, asset_data, asset_grouping, FullAsset, GroupingSize, + Pagination, }, dapi::common::safe_select, - rpc::{response::AssetList}, + rpc::response::AssetList, }; use indexmap::IndexMap; diff --git a/digital_asset_types/src/dapi/common/asset.rs b/digital_asset_types/src/dapi/common/asset.rs index 007e927b6..6c7c187f5 100644 --- a/digital_asset_types/src/dapi/common/asset.rs +++ b/digital_asset_types/src/dapi/common/asset.rs @@ -221,7 +221,6 @@ pub fn v1_content_from_json(asset_data: &asset_data::Model) -> Result Ordering::Equal, }); - Ok(Content { schema: "https://schema.metaplex.com/nft1.0.json".to_string(), json_uri, @@ -231,10 +230,7 @@ pub fn v1_content_from_json(asset_data: &asset_data::Model) -> Result Result { +pub fn get_content(asset: &asset::Model, data: &asset_data::Model) -> Result { match asset.specification_version { Some(SpecificationVersions::V1) | Some(SpecificationVersions::V0) => { v1_content_from_json(data) @@ -297,9 +293,7 @@ pub fn get_interface(asset: &asset::Model) -> Result { } //TODO -> impl custom error type -pub fn asset_to_rpc( - asset: FullAsset -) -> Result { +pub fn asset_to_rpc(asset: FullAsset) -> Result { let FullAsset { asset, data, @@ -389,9 +383,7 @@ pub fn asset_to_rpc( }) } -pub fn asset_list_to_rpc( - asset_list: Vec -) -> (Vec, Vec) { +pub fn asset_list_to_rpc(asset_list: Vec) -> (Vec, Vec) { asset_list .into_iter() .fold((vec![], vec![]), |(mut assets, mut errors), asset| { diff --git a/nft_ingester/src/account_updates.rs b/nft_ingester/src/account_updates.rs index 9791b7500..644b37756 100644 --- a/nft_ingester/src/account_updates.rs +++ b/nft_ingester/src/account_updates.rs @@ -65,7 +65,11 @@ pub fn account_worker( }) } -async fn handle_account(manager: Arc, item: RecvData, stream_key: &'static str) -> Option { +async fn handle_account( + manager: Arc, + item: RecvData, + stream_key: &'static str, +) -> Option { let id = item.id; let mut ret_id = None; let data = item.data; diff --git a/nft_ingester/src/database.rs b/nft_ingester/src/database.rs index 578f58cbc..77f8dd2c5 100644 --- a/nft_ingester/src/database.rs +++ b/nft_ingester/src/database.rs @@ -1,8 +1,9 @@ -use sqlx::{postgres::{PgPoolOptions, PgConnectOptions}, PgPool, ConnectOptions}; - -use crate::{ - config::{IngesterConfig, IngesterRole}, +use sqlx::{ + postgres::{PgConnectOptions, PgPoolOptions}, + ConnectOptions, PgPool, }; + +use crate::config::{IngesterConfig, IngesterRole}; const BARE_MINIMUM_CONNECTIONS: u32 = 5; const DEFAULT_MAX: u32 = 125; pub async fn setup_database(config: IngesterConfig) -> PgPool { @@ -19,8 +20,11 @@ pub async fn setup_database(config: IngesterConfig) -> PgPool { let mut options: PgConnectOptions = url.parse().unwrap(); options.log_statements(log::LevelFilter::Trace); - options.log_slow_statements(log::LevelFilter::Debug, std::time::Duration::from_millis(500)); - + options.log_slow_statements( + log::LevelFilter::Debug, + std::time::Duration::from_millis(500), + ); + let pool = PgPoolOptions::new() .min_connections(BARE_MINIMUM_CONNECTIONS) .max_connections(max) diff --git a/nft_ingester/src/main.rs b/nft_ingester/src/main.rs index 3d08cafb1..6ae64a15e 100644 --- a/nft_ingester/src/main.rs +++ b/nft_ingester/src/main.rs @@ -27,7 +27,8 @@ use chrono::Duration; use clap::{arg, command, value_parser}; use log::{error, info}; use plerkle_messenger::{ - redis_messenger::RedisMessenger, ConsumptionType, ACCOUNT_STREAM, ACCOUNT_BACKFILL_STREAM, TRANSACTION_STREAM, TRANSACTION_BACKFILL_STREAM + redis_messenger::RedisMessenger, ConsumptionType, ACCOUNT_BACKFILL_STREAM, ACCOUNT_STREAM, + TRANSACTION_BACKFILL_STREAM, TRANSACTION_STREAM, }; use std::{path::PathBuf, time}; use tokio::{signal, task::JoinSet}; @@ -118,7 +119,6 @@ pub async fn main() -> Result<(), IngesterError> { TRANSACTION_BACKFILL_STREAM, )?; - if let Some(t) = timer_acc.start::().await { tasks.spawn(t); } diff --git a/nft_ingester/src/metrics.rs b/nft_ingester/src/metrics.rs index 0e44d69c7..a8b5006ae 100644 --- a/nft_ingester/src/metrics.rs +++ b/nft_ingester/src/metrics.rs @@ -5,10 +5,7 @@ use cadence_macros::{is_global_default_set, set_global_default, statsd_count, st use log::{error, warn}; use tokio::time::Instant; -use crate::{ - config::IngesterConfig, - error::IngesterError, -}; +use crate::{config::IngesterConfig, error::IngesterError}; #[macro_export] macro_rules! metric { @@ -32,9 +29,7 @@ pub fn setup_metrics(config: &IngesterConfig) { let udp_sink = BufferedUdpMetricSink::from(host, socket).unwrap(); let queuing_sink = QueuingMetricSink::from(udp_sink); let builder = StatsdClient::builder("das_ingester", queuing_sink); - let client = builder - .with_tag("env", env) - .build(); + let client = builder.with_tag("env", env).build(); set_global_default(client); } } diff --git a/nft_ingester/src/stream.rs b/nft_ingester/src/stream.rs index 3b36397b3..e5db78d33 100644 --- a/nft_ingester/src/stream.rs +++ b/nft_ingester/src/stream.rs @@ -1,15 +1,13 @@ - use crate::{error::IngesterError, metric}; use cadence_macros::{is_global_default_set, statsd_count, statsd_gauge}; -use log::{error}; +use log::error; use plerkle_messenger::{Messenger, MessengerConfig}; use tokio::{ - task::{JoinHandle}, + task::JoinHandle, time::{self, Duration}, }; - pub struct StreamSizeTimer { interval: tokio::time::Duration, messenger_config: MessengerConfig, diff --git a/nft_ingester/src/transaction_notifications.rs b/nft_ingester/src/transaction_notifications.rs index 6ca7cc5f4..c00cbec25 100644 --- a/nft_ingester/src/transaction_notifications.rs +++ b/nft_ingester/src/transaction_notifications.rs @@ -6,9 +6,7 @@ use crate::{ use cadence_macros::{is_global_default_set, statsd_count, statsd_time}; use chrono::Utc; use log::{debug, error}; -use plerkle_messenger::{ - ConsumptionType, Messenger, MessengerConfig, RecvData, -}; +use plerkle_messenger::{ConsumptionType, Messenger, MessengerConfig, RecvData}; use plerkle_serialization::root_as_transaction_info; use sqlx::{Pool, Postgres}; @@ -69,7 +67,11 @@ pub fn transaction_worker( }) } -async fn handle_transaction(manager: Arc, item: RecvData, stream_key: &'static str) -> Option { +async fn handle_transaction( + manager: Arc, + item: RecvData, + stream_key: &'static str, +) -> Option { let mut ret_id = None; if item.tries > 0 { metric! { diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 469626eac..22048ac5b 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,2 +1,2 @@ [toolchain] -channel = "1.70.0" \ No newline at end of file +channel = "1.70.0" diff --git a/tools/acc_forwarder/src/main.rs b/tools/acc_forwarder/src/main.rs index 61349a8fb..cffb4e1ae 100644 --- a/tools/acc_forwarder/src/main.rs +++ b/tools/acc_forwarder/src/main.rs @@ -416,7 +416,11 @@ async fn send_account( let fbb = serialize_account(fbb, &account_info, slot, is_startup); let bytes = fbb.finished_data(); - messenger.lock().await.send(ACCOUNT_BACKFILL_STREAM, bytes).await?; + messenger + .lock() + .await + .send(ACCOUNT_BACKFILL_STREAM, bytes) + .await?; info!("sent account {} to stream", pubkey); ACC_FORWARDER_SENT.inc(); From 524dce55eec1167a77323b6906ac8856cb7e9429 Mon Sep 17 00:00:00 2001 From: Kirill Fomichev Date: Sun, 19 Nov 2023 22:04:45 -0500 Subject: [PATCH 02/23] clippy --- .../src/dao/generated/cl_audits.rs | 4 +- digital_asset_types/src/dao/mod.rs | 2 +- digital_asset_types/src/dao/scopes/asset.rs | 16 +++----- .../src/dapi/assets_by_creator.rs | 1 + .../src/dapi/assets_by_group.rs | 2 + digital_asset_types/src/dapi/change_logs.rs | 2 +- digital_asset_types/src/dapi/common/asset.rs | 11 ++---- digital_asset_types/src/rpc/asset.rs | 10 +++-- digital_asset_types/src/rpc/filter.rs | 9 +---- digital_asset_types/tests/common.rs | 4 +- digital_asset_types/tests/json_parsing.rs | 2 - metaplex-rpc-proxy/src/lib.rs | 7 ++-- nft_ingester/src/account_updates.rs | 10 ++--- nft_ingester/src/ack.rs | 2 +- nft_ingester/src/backfiller.rs | 12 +++--- nft_ingester/src/config.rs | 13 ++----- nft_ingester/src/database.rs | 5 +-- nft_ingester/src/metrics.rs | 37 +++++++++---------- .../bubblegum/collection_verification.rs | 6 +-- .../src/program_transformers/bubblegum/db.rs | 5 +-- .../program_transformers/bubblegum/mint_v1.rs | 1 - nft_ingester/src/program_transformers/mod.rs | 12 +++--- .../src/program_transformers/token/mod.rs | 8 +--- .../token_metadata/v1_asset.rs | 4 +- nft_ingester/src/stream.rs | 8 ++-- nft_ingester/src/tasks/mod.rs | 5 ++- nft_ingester/src/transaction_notifications.rs | 10 ++--- tools/acc_forwarder/src/main.rs | 2 +- 28 files changed, 92 insertions(+), 118 deletions(-) diff --git a/digital_asset_types/src/dao/generated/cl_audits.rs b/digital_asset_types/src/dao/generated/cl_audits.rs index d3c553f0d..73a743c26 100644 --- a/digital_asset_types/src/dao/generated/cl_audits.rs +++ b/digital_asset_types/src/dao/generated/cl_audits.rs @@ -81,7 +81,7 @@ impl ActiveModelBehavior for ActiveModel {} impl From for ActiveModel { fn from(item: crate::dao::cl_items::ActiveModel) -> Self { - return ActiveModel { + ActiveModel { tree: item.tree, level: item.level, node_idx: item.node_idx, @@ -89,6 +89,6 @@ impl From for ActiveModel { seq: item.seq, leaf_idx: item.leaf_idx, ..Default::default() - }; + } } } diff --git a/digital_asset_types/src/dao/mod.rs b/digital_asset_types/src/dao/mod.rs index e30c92755..889f57771 100644 --- a/digital_asset_types/src/dao/mod.rs +++ b/digital_asset_types/src/dao/mod.rs @@ -203,7 +203,7 @@ impl SearchAssetsQuery { } if let Some(a) = self.authority_address.to_owned() { - conditions = conditions.add(asset_authority::Column::Authority.eq(a.clone())); + conditions = conditions.add(asset_authority::Column::Authority.eq(a)); let rel = asset_authority::Relation::Asset .def() .rev() diff --git a/digital_asset_types/src/dao/scopes/asset.rs b/digital_asset_types/src/dao/scopes/asset.rs index 09a42bec0..330ce0cfe 100644 --- a/digital_asset_types/src/dao/scopes/asset.rs +++ b/digital_asset_types/src/dao/scopes/asset.rs @@ -1,18 +1,12 @@ -use crate::{ - dao::{ - asset::{self, Entity}, - asset_authority, asset_creators, asset_data, asset_grouping, FullAsset, GroupingSize, - Pagination, - }, - dapi::common::safe_select, - rpc::response::AssetList, +use crate::dao::{ + asset, asset_authority, asset_creators, asset_data, asset_grouping, FullAsset, GroupingSize, + Pagination, }; - use indexmap::IndexMap; use sea_orm::{entity::*, query::*, ConnectionTrait, DbErr, Order}; -use std::collections::{HashMap, HashSet}; +use std::collections::HashMap; -pub fn paginate<'db, T>(pagination: &Pagination, limit: u64, stmt: T) -> T +pub fn paginate(pagination: &Pagination, limit: u64, stmt: T) -> T where T: QueryFilter + QuerySelect, { diff --git a/digital_asset_types/src/dapi/assets_by_creator.rs b/digital_asset_types/src/dapi/assets_by_creator.rs index e69a12f92..1bdfe4f4c 100644 --- a/digital_asset_types/src/dapi/assets_by_creator.rs +++ b/digital_asset_types/src/dapi/assets_by_creator.rs @@ -6,6 +6,7 @@ use sea_orm::DbErr; use super::common::{build_asset_response, create_pagination, create_sorting}; +#[allow(clippy::too_many_arguments)] pub async fn get_assets_by_creator( db: &DatabaseConnection, creator: Vec, diff --git a/digital_asset_types/src/dapi/assets_by_group.rs b/digital_asset_types/src/dapi/assets_by_group.rs index 1e655b6ab..7e9a5ef04 100644 --- a/digital_asset_types/src/dapi/assets_by_group.rs +++ b/digital_asset_types/src/dapi/assets_by_group.rs @@ -5,6 +5,8 @@ use sea_orm::DatabaseConnection; use sea_orm::DbErr; use super::common::{build_asset_response, create_pagination, create_sorting}; + +#[allow(clippy::too_many_arguments)] pub async fn get_assets_by_group( db: &DatabaseConnection, group_key: String, diff --git a/digital_asset_types/src/dapi/change_logs.rs b/digital_asset_types/src/dapi/change_logs.rs index a710c0a5a..3aeab838e 100644 --- a/digital_asset_types/src/dapi/change_logs.rs +++ b/digital_asset_types/src/dapi/change_logs.rs @@ -118,5 +118,5 @@ pub fn get_required_nodes_for_proof(index: i64) -> Vec { idx >>= 1 } indexes.push(1); - return indexes; + indexes } diff --git a/digital_asset_types/src/dapi/common/asset.rs b/digital_asset_types/src/dapi/common/asset.rs index 6c7c187f5..ed7a2582a 100644 --- a/digital_asset_types/src/dapi/common/asset.rs +++ b/digital_asset_types/src/dapi/common/asset.rs @@ -20,7 +20,7 @@ use std::path::Path; use url::Url; pub fn to_uri(uri: String) -> Option { - Url::parse(&*uri).ok() + Url::parse(&uri).ok() } pub fn get_mime(url: Url) -> Option { @@ -90,10 +90,7 @@ pub fn create_pagination( page: Option, ) -> Result { match (&before, &after, &page) { - (_, _, None) => Ok(Pagination::Keyset { - before: before.map(|x| x.into()), - after: after.map(|x| x.into()), - }), + (_, _, None) => Ok(Pagination::Keyset { before, after }), (None, None, Some(p)) => Ok(Pagination::Page { page: *p }), _ => Err(DbErr::Custom("Invalid Pagination".to_string())), } @@ -322,8 +319,8 @@ pub fn asset_to_rpc(asset: FullAsset) -> Result { compression: Some(Compression { eligible: asset.compressible, compressed: asset.compressed, - leaf_id: asset.nonce.unwrap_or(0 as i64), - seq: asset.seq.unwrap_or(0 as i64), + leaf_id: asset.nonce.unwrap_or(0), + seq: asset.seq.unwrap_or(0), tree: asset .tree_id .map(|s| bs58::encode(s).into_string()) diff --git a/digital_asset_types/src/rpc/asset.rs b/digital_asset_types/src/rpc/asset.rs index ea365e4b1..850b92d01 100644 --- a/digital_asset_types/src/rpc/asset.rs +++ b/digital_asset_types/src/rpc/asset.rs @@ -27,6 +27,8 @@ pub enum Interface { #[serde(rename = "V1_PRINT")] V1PRINT, #[serde(rename = "LEGACY_NFT")] + // TODO: change on version bump + #[allow(non_camel_case_types)] LEGACY_NFT, #[serde(rename = "V2_NFT")] Nft, @@ -56,9 +58,9 @@ impl From<(&SpecificationVersions, &SpecificationAssetClass)> for Interface { } } -impl Into<(SpecificationVersions, SpecificationAssetClass)> for Interface { - fn into(self) -> (SpecificationVersions, SpecificationAssetClass) { - match self { +impl From for (SpecificationVersions, SpecificationAssetClass) { + fn from(interface: Interface) -> (SpecificationVersions, SpecificationAssetClass) { + match interface { Interface::V1NFT => (SpecificationVersions::V1, SpecificationAssetClass::Nft), Interface::LEGACY_NFT => (SpecificationVersions::V0, SpecificationAssetClass::Nft), Interface::ProgrammableNFT => ( @@ -115,7 +117,7 @@ pub struct File { pub type Files = Vec; -#[derive(PartialEq, Eq, Debug, Clone, Deserialize, Serialize, JsonSchema)] +#[derive(Debug, Default, Clone, PartialEq, Eq, Deserialize, Serialize, JsonSchema)] pub struct MetadataMap(BTreeMap); impl MetadataMap { diff --git a/digital_asset_types/src/rpc/filter.rs b/digital_asset_types/src/rpc/filter.rs index f6aa010f8..ef5030b43 100644 --- a/digital_asset_types/src/rpc/filter.rs +++ b/digital_asset_types/src/rpc/filter.rs @@ -31,20 +31,15 @@ pub enum AssetSortBy { None, } -#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)] +#[derive(Debug, Default, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)] pub enum AssetSortDirection { #[serde(rename = "asc")] Asc, #[serde(rename = "desc")] + #[default] Desc, } -impl Default for AssetSortDirection { - fn default() -> AssetSortDirection { - AssetSortDirection::Desc - } -} - #[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema)] pub enum SearchConditionType { #[serde(rename = "all")] diff --git a/digital_asset_types/tests/common.rs b/digital_asset_types/tests/common.rs index bbe3cf509..17ef752dc 100644 --- a/digital_asset_types/tests/common.rs +++ b/digital_asset_types/tests/common.rs @@ -83,8 +83,8 @@ pub fn create_asset_data( metadata: JsonValue::String("processing".to_string()), slot_updated: 0, reindex: None, - raw_name: metadata.name.into_bytes().to_vec().clone(), - raw_symbol: metadata.symbol.into_bytes().to_vec().clone(), + raw_name: metadata.name.into_bytes().to_vec(), + raw_symbol: metadata.symbol.into_bytes().to_vec(), }, ) } diff --git a/digital_asset_types/tests/json_parsing.rs b/digital_asset_types/tests/json_parsing.rs index 765f14bc6..85681cf6a 100644 --- a/digital_asset_types/tests/json_parsing.rs +++ b/digital_asset_types/tests/json_parsing.rs @@ -79,7 +79,6 @@ async fn simple_content() { ); assert_eq!( parsed - .clone() .links .unwrap() .get("external_url") @@ -130,7 +129,6 @@ async fn complex_content() { ); assert_eq!( parsed - .clone() .links .unwrap() .get("animation_url") diff --git a/metaplex-rpc-proxy/src/lib.rs b/metaplex-rpc-proxy/src/lib.rs index 625ffa460..24f60437e 100644 --- a/metaplex-rpc-proxy/src/lib.rs +++ b/metaplex-rpc-proxy/src/lib.rs @@ -3,7 +3,6 @@ use log::info; use proxy_wasm::traits::*; use proxy_wasm::types::*; use regex::{Regex, RegexBuilder}; -use std::env; use std::time::Duration; proxy_wasm::main! {{ @@ -35,9 +34,9 @@ struct RpcProxy { impl RpcProxy { fn new(path: Option) -> Self { - return Self { + Self { rpc_url_path: path.unwrap_or("/".to_string()), - }; + } } } @@ -103,7 +102,7 @@ impl HttpContext for RpcProxy { } else { let res = upstream_rpc_call(self, body); return match res { - Ok(res) => Action::Pause, + Ok(_) => Action::Pause, Err(e) => { info!("Error: {:?}", e); Action::Continue diff --git a/nft_ingester/src/account_updates.rs b/nft_ingester/src/account_updates.rs index 644b37756..68b6c83a0 100644 --- a/nft_ingester/src/account_updates.rs +++ b/nft_ingester/src/account_updates.rs @@ -48,14 +48,12 @@ pub fn account_worker( } } while let Some(res) = tasks.join_next().await { - if let Ok(id) = res { - if let Some(id) = id { - let send = ack_channel.send((stream_key, id)); - if let Err(err) = send { - metric! { + if let Ok(Some(id)) = res { + let send = ack_channel.send((stream_key, id)); + if let Err(err) = send { + metric! { error!("Account stream ack error: {}", err); statsd_count!("ingester.stream.ack_error", 1, "stream" => stream_key); - } } } } diff --git a/nft_ingester/src/ack.rs b/nft_ingester/src/ack.rs index 9c0f0c91b..0b64fa12d 100644 --- a/nft_ingester/src/ack.rs +++ b/nft_ingester/src/ack.rs @@ -29,7 +29,7 @@ pub fn ack_worker( } let len = acks.len(); for (stream, msgs) in acks.iter_mut() { - if let Err(e) = msg.ack_msg(&stream, &msgs).await { + if let Err(e) = msg.ack_msg(stream, msgs).await { error!("Error acking message: {}", e); } metric! { diff --git a/nft_ingester/src/backfiller.rs b/nft_ingester/src/backfiller.rs index eabd47710..6a9b1a4c3 100644 --- a/nft_ingester/src/backfiller.rs +++ b/nft_ingester/src/backfiller.rs @@ -142,6 +142,7 @@ struct MissingTree { struct BackfillTree { unique_tree: UniqueTree, backfill_from_seq_1: bool, + #[allow(dead_code)] slot: u64, } @@ -513,7 +514,7 @@ impl<'a, T: Messenger> Backfiller<'a, T> { .into_iter() .map(|(k, s)| MissingTree { tree: k, slot: s.0 }) .collect::>(); - if missing_trees.len() > 0 { + if !missing_trees.is_empty() { info!("Number of Missing local trees: {}", missing_trees.len()); } else { debug!("No missing trees"); @@ -627,7 +628,7 @@ impl<'a, T: Messenger> Backfiller<'a, T> { &mut self, btree: &BackfillTree, ) -> Result, IngesterError> { - let address = Pubkey::new(btree.unique_tree.tree.as_slice()); + let address = Pubkey::try_from(btree.unique_tree.tree.as_slice()).expect("valid pubkey"); let slots = self.find_slots_via_address(&address).await?; let address = btree.unique_tree.tree.clone(); for slot in slots { @@ -692,6 +693,7 @@ impl<'a, T: Messenger> Backfiller<'a, T> { Ok(Vec::from_iter(slots)) } + #[allow(dead_code)] async fn get_max_seq(&self, tree: &[u8]) -> Result, DbErr> { let query = backfill_items::Entity::find() .select_only() @@ -734,11 +736,11 @@ impl<'a, T: Messenger> Backfiller<'a, T> { let mut list = HashMap::with_capacity(results.len()); for r in results.into_iter() { let (pubkey, mut account) = r; - let (mut header_bytes, rest) = account + let (header_bytes, rest) = account .data .split_at_mut(CONCURRENT_MERKLE_TREE_HEADER_SIZE_V1); let header: ConcurrentMerkleTreeHeader = - ConcurrentMerkleTreeHeader::try_from_slice(&mut header_bytes) + ConcurrentMerkleTreeHeader::try_from_slice(header_bytes) .map_err(|e| IngesterError::RpcGetDataError(e.to_string()))?; let auth = Pubkey::find_program_address(&[pubkey.as_ref()], &mpl_bubblegum::ID).0; @@ -870,7 +872,7 @@ impl<'a, T: Messenger> Backfiller<'a, T> { debug!("Fetching block {} from RPC", slot); let block = EncodedConfirmedBlock::from( self.rpc_client - .get_block_with_config(slot as u64, self.rpc_block_config) + .get_block_with_config(slot, self.rpc_block_config) .await .map_err(|e| IngesterError::RpcGetDataError(e.to_string()))?, ); diff --git a/nft_ingester/src/config.rs b/nft_ingester/src/config.rs index 6e11fb539..3063d3a3a 100644 --- a/nft_ingester/src/config.rs +++ b/nft_ingester/src/config.rs @@ -95,20 +95,15 @@ pub const RPC_URL_KEY: &str = "url"; pub const RPC_COMMITMENT_KEY: &str = "commitment"; pub const CODE_VERSION: &str = env!("CARGO_PKG_VERSION"); -#[derive(Deserialize, PartialEq, Eq, Debug, Clone)] +#[derive(Deserialize, Default, PartialEq, Eq, Debug, Clone)] pub enum IngesterRole { + #[default] All, Backfiller, BackgroundTaskRunner, Ingester, } -impl Default for IngesterRole { - fn default() -> Self { - IngesterRole::All - } -} - impl Display for IngesterRole { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { @@ -146,9 +141,7 @@ pub fn setup_config(config_file: Option<&PathBuf>) -> IngesterConfig { } pub fn init_logger() { - let env_filter = env::var("RUST_LOG") - .or::>(Ok("info".to_string())) - .unwrap(); + let env_filter = env::var("RUST_LOG").unwrap_or("info".to_string()); let t = tracing_subscriber::fmt().with_env_filter(env_filter); t.event_format(fmt::format::json()).init(); } diff --git a/nft_ingester/src/database.rs b/nft_ingester/src/database.rs index 77f8dd2c5..242573369 100644 --- a/nft_ingester/src/database.rs +++ b/nft_ingester/src/database.rs @@ -25,11 +25,10 @@ pub async fn setup_database(config: IngesterConfig) -> PgPool { std::time::Duration::from_millis(500), ); - let pool = PgPoolOptions::new() + PgPoolOptions::new() .min_connections(BARE_MINIMUM_CONNECTIONS) .max_connections(max) .connect_with(options) .await - .unwrap(); - pool + .unwrap() } diff --git a/nft_ingester/src/metrics.rs b/nft_ingester/src/metrics.rs index a8b5006ae..2f5dde2b3 100644 --- a/nft_ingester/src/metrics.rs +++ b/nft_ingester/src/metrics.rs @@ -36,8 +36,9 @@ pub fn setup_metrics(config: &IngesterConfig) { // Returns a boolean indicating whether the redis message should be ACK'd. // If the message is not ACK'd, it will be retried as long as it is under the retry limit. +#[allow(clippy::too_many_arguments)] pub fn capture_result( - id: String, + _id: String, stream: &str, label: (&str, &str), tries: usize, @@ -46,32 +47,31 @@ pub fn capture_result( txn_sig: Option<&str>, account: Option, ) -> bool { - let mut should_ack = false; match res { Ok(_) => { metric! { - statsd_time!("ingester.proc_time", proc.elapsed().as_millis() as u64, label.0 => &label.1, "stream" => stream); + statsd_time!("ingester.proc_time", proc.elapsed().as_millis() as u64, label.0 => label.1, "stream" => stream); } if tries == 0 { metric! { - statsd_count!("ingester.ingest_success", 1, label.0 => &label.1, "stream" => stream); + statsd_count!("ingester.ingest_success", 1, label.0 => label.1, "stream" => stream); } } else { metric! { - statsd_count!("ingester.redeliver_success", 1, label.0 => &label.1, "stream" => stream); + statsd_count!("ingester.redeliver_success", 1, label.0 => label.1, "stream" => stream); } } - should_ack = true; + true } Err(err) if err == IngesterError::NotImplemented => { metric! { - statsd_count!("ingester.not_implemented", 1, label.0 => &label.1, "stream" => stream, "error" => "ni"); + statsd_count!("ingester.not_implemented", 1, label.0 => label.1, "stream" => stream, "error" => "ni"); } - should_ack = true; + true } Err(IngesterError::DeserializationError(e)) => { metric! { - statsd_count!("ingester.ingest_error", 1, label.0 => &label.1, "stream" => stream, "error" => "de"); + statsd_count!("ingester.ingest_error", 1, label.0 => label.1, "stream" => stream, "error" => "de"); } if let Some(sig) = txn_sig { warn!("Error deserializing txn {}: {:?}", sig, e); @@ -81,11 +81,11 @@ pub fn capture_result( warn!("{}", e); } // Non-retryable error. - should_ack = true; + true } Err(IngesterError::ParsingError(e)) => { metric! { - statsd_count!("ingester.ingest_error", 1, label.0 => &label.1, "stream" => stream, "error" => "parse"); + statsd_count!("ingester.ingest_error", 1, label.0 => label.1, "stream" => stream, "error" => "parse"); } if let Some(sig) = txn_sig { warn!("Error parsing txn {}: {:?}", sig, e); @@ -95,29 +95,29 @@ pub fn capture_result( warn!("{}", e); } // Non-retryable error. - should_ack = true; + true } Err(IngesterError::DatabaseError(e)) => { metric! { - statsd_count!("ingester.database_error", 1, label.0 => &label.1, "stream" => stream, "error" => "db"); + statsd_count!("ingester.database_error", 1, label.0 => label.1, "stream" => stream, "error" => "db"); } if let Some(sig) = txn_sig { warn!("Error database txn {}: {:?}", sig, e); } else { warn!("{}", e); } - should_ack = false; + false } Err(IngesterError::AssetIndexError(e)) => { metric! { - statsd_count!("ingester.index_error", 1, label.0 => &label.1, "stream" => stream, "error" => "index"); + statsd_count!("ingester.index_error", 1, label.0 => label.1, "stream" => stream, "error" => "index"); } if let Some(sig) = txn_sig { warn!("Error indexing transaction {}: {:?}", sig, e); } else { warn!("Error indexing account: {:?}", e); } - should_ack = false; + false } Err(err) => { if let Some(sig) = txn_sig { @@ -128,10 +128,9 @@ pub fn capture_result( error!("Error handling update: {:?}", err); } metric! { - statsd_count!("ingester.ingest_update_error", 1, label.0 => &label.1, "stream" => stream, "error" => "u"); + statsd_count!("ingester.ingest_update_error", 1, label.0 => label.1, "stream" => stream, "error" => "u"); } - should_ack = false; + false } } - should_ack } diff --git a/nft_ingester/src/program_transformers/bubblegum/collection_verification.rs b/nft_ingester/src/program_transformers/bubblegum/collection_verification.rs index 7517f1544..2db92cd60 100644 --- a/nft_ingester/src/program_transformers/bubblegum/collection_verification.rs +++ b/nft_ingester/src/program_transformers/bubblegum/collection_verification.rs @@ -26,7 +26,7 @@ where let (collection, verify) = match payload { Payload::CollectionVerification { collection, verify, .. - } => (collection.clone(), verify.clone()), + } => (*collection, verify), _ => { return Err(IngesterError::ParsingError( "Ix not parsed correctly".to_string(), @@ -64,8 +64,8 @@ where txn, id_bytes.to_vec(), Some(Collection { - key: collection.clone(), - verified: verify, + key: collection, + verified: *verify, }), bundle.slot as i64, seq as i64, diff --git a/nft_ingester/src/program_transformers/bubblegum/db.rs b/nft_ingester/src/program_transformers/bubblegum/db.rs index 7e930abdc..c562be2be 100644 --- a/nft_ingester/src/program_transformers/bubblegum/db.rs +++ b/nft_ingester/src/program_transformers/bubblegum/db.rs @@ -9,8 +9,6 @@ use sea_orm::{ }; use spl_account_compression::events::ChangeLogEventV1; -use std::convert::From; - pub async fn save_changelog_event<'c, T>( change_log_event: &ChangeLogEventV1, slot: u64, @@ -68,7 +66,7 @@ where ..Default::default() }; - let mut audit_item: Option = if (cl_audits) { + let audit_item: Option = if cl_audits { let mut ai: cl_audits::ActiveModel = item.clone().into(); ai.tx = Set(txn_id.to_string()); Some(ai) @@ -135,6 +133,7 @@ where //TODO -> set maximum size of path and break into multiple statements } +#[allow(clippy::too_many_arguments)] pub async fn upsert_asset_with_leaf_info( txn: &T, id: Vec, diff --git a/nft_ingester/src/program_transformers/bubblegum/mint_v1.rs b/nft_ingester/src/program_transformers/bubblegum/mint_v1.rs index 752ed6a3c..685649f79 100644 --- a/nft_ingester/src/program_transformers/bubblegum/mint_v1.rs +++ b/nft_ingester/src/program_transformers/bubblegum/mint_v1.rs @@ -97,7 +97,6 @@ where reindex: Set(Some(true)), raw_name: Set(name.to_vec()), raw_symbol: Set(symbol.to_vec()), - ..Default::default() }; let mut query = asset_data::Entity::insert(data) diff --git a/nft_ingester/src/program_transformers/mod.rs b/nft_ingester/src/program_transformers/mod.rs index ff052756e..fc555829d 100644 --- a/nft_ingester/src/program_transformers/mod.rs +++ b/nft_ingester/src/program_transformers/mod.rs @@ -51,7 +51,7 @@ impl ProgramTransformer { task_sender, matchers, key_set: hs, - cl_audits: cl_audits, + cl_audits, } } @@ -63,8 +63,10 @@ impl ProgramTransformer { order_instructions(ref_set, tx) } + #[allow(clippy::borrowed_box)] pub fn match_program(&self, key: &FBPubkey) -> Option<&Box> { - self.matchers.get(&Pubkey::new(key.0.as_slice())) + self.matchers + .get(&Pubkey::try_from(key.0.as_slice()).expect("valid key from FlatBuffer")) } pub async fn handle_transaction<'a>( @@ -73,7 +75,7 @@ impl ProgramTransformer { ) -> Result<(), IngesterError> { let sig: Option<&str> = tx.signature(); info!("Handling Transaction: {:?}", sig); - let instructions = self.break_transaction(&tx); + let instructions = self.break_transaction(tx); let accounts = tx.account_keys().unwrap_or_default(); let slot = tx.slot(); let txn_id = tx.signature().unwrap_or(""); @@ -108,7 +110,7 @@ impl ProgramTransformer { acc }); let ix = InstructionBundle { - txn_id: txn_id, + txn_id, program, instruction: Some(instruction), inner_ix, @@ -135,7 +137,7 @@ impl ProgramTransformer { "Failed to handle bubblegum instruction for txn {:?}: {:?}", sig, err ); - return err; + err })?; } _ => { diff --git a/nft_ingester/src/program_transformers/token/mod.rs b/nft_ingester/src/program_transformers/token/mod.rs index 47f1d70b6..c32cad020 100644 --- a/nft_ingester/src/program_transformers/token/mod.rs +++ b/nft_ingester/src/program_transformers/token/mod.rs @@ -1,6 +1,5 @@ -use crate::{error::IngesterError, metric, tasks::TaskData}; +use crate::{error::IngesterError, tasks::TaskData}; use blockbuster::programs::token_account::TokenProgramAccount; -use cadence_macros::{is_global_default_set, statsd_count}; use digital_asset_types::dao::{asset, token_accounts, tokens}; use plerkle_serialization::AccountInfo; use sea_orm::{ @@ -27,10 +26,7 @@ pub async fn handle_token_program_account<'a, 'b, 'c>( COption::Some(d) => Some(d.to_bytes().to_vec()), COption::None => None, }; - let frozen = match ta.state { - AccountState::Frozen => true, - _ => false, - }; + let frozen = matches!(ta.state, AccountState::Frozen); let owner = ta.owner.to_bytes().to_vec(); let model = token_accounts::ActiveModel { pubkey: Set(key_bytes), diff --git a/nft_ingester/src/program_transformers/token_metadata/v1_asset.rs b/nft_ingester/src/program_transformers/token_metadata/v1_asset.rs index 061a2ac9b..4f81a4636 100644 --- a/nft_ingester/src/program_transformers/token_metadata/v1_asset.rs +++ b/nft_ingester/src/program_transformers/token_metadata/v1_asset.rs @@ -23,7 +23,7 @@ use num_traits::FromPrimitive; use plerkle_serialization::Pubkey as FBPubkey; use sea_orm::{ entity::*, query::*, sea_query::OnConflict, ActiveValue::Set, ConnectionTrait, DbBackend, - DbErr, EntityTrait, FromQueryResult, JoinType, JsonValue, + DbErr, EntityTrait, JsonValue, }; use std::collections::HashSet; @@ -346,7 +346,7 @@ pub async fn save_v1_asset( ) .exec(&txn) .await?; - if db_creators.len() > 0 { + if !db_creators.is_empty() { let mut query = asset_creators::Entity::insert_many(db_creators) .on_conflict( OnConflict::columns([ diff --git a/nft_ingester/src/stream.rs b/nft_ingester/src/stream.rs index e5db78d33..46afbf5b4 100644 --- a/nft_ingester/src/stream.rs +++ b/nft_ingester/src/stream.rs @@ -16,20 +16,20 @@ pub struct StreamSizeTimer { impl StreamSizeTimer { pub fn new( - interval_time: Duration, + interval: Duration, messenger_config: MessengerConfig, stream: &'static str, ) -> Result { Ok(Self { - interval: interval_time, + interval, stream, - messenger_config: messenger_config, + messenger_config, }) } pub async fn start(&mut self) -> Option> { metric! { - let i = self.interval.clone(); + let i = self.interval; let messenger_config = self.messenger_config.clone(); let stream = self.stream; diff --git a/nft_ingester/src/tasks/mod.rs b/nft_ingester/src/tasks/mod.rs index eebcd1eb9..d7b5ceaef 100644 --- a/nft_ingester/src/tasks/mod.rs +++ b/nft_ingester/src/tasks/mod.rs @@ -102,6 +102,7 @@ pub struct TaskManager { } impl TaskManager { + #[allow(clippy::borrowed_box)] async fn execute_task( db: &DatabaseConnection, task_def: &Box, @@ -123,7 +124,7 @@ impl TaskManager { }?; let start = Utc::now(); - let res = task_def.task(&db, *data_json).await; + let res = task_def.task(db, *data_json).await; let end = Utc::now(); task.duration = Set(Some( ((end.timestamp_millis() - start.timestamp_millis()) / 1000) as i32, @@ -343,7 +344,7 @@ impl TaskManager { continue; } metric! { - statsd_count!("ingester.bgtask.new", 1, "type" => &task.name); + statsd_count!("ingester.bgtask.new", 1, "type" => task.name); } TaskManager::new_task_handler( pool.clone(), diff --git a/nft_ingester/src/transaction_notifications.rs b/nft_ingester/src/transaction_notifications.rs index c00cbec25..02aa5d971 100644 --- a/nft_ingester/src/transaction_notifications.rs +++ b/nft_ingester/src/transaction_notifications.rs @@ -50,14 +50,12 @@ pub fn transaction_worker( } } while let Some(res) = tasks.join_next().await { - if let Ok(id) = res { - if let Some(id) = id { - let send = ack_channel.send((stream_key, id)); - if let Err(err) = send { - metric! { + if let Ok(Some(id)) = res { + let send = ack_channel.send((stream_key, id)); + if let Err(err) = send { + metric! { error!("Txn stream ack error: {}", err); statsd_count!("ingester.stream.ack_error", 1, "stream" => stream_key); - } } } } diff --git a/tools/acc_forwarder/src/main.rs b/tools/acc_forwarder/src/main.rs index cffb4e1ae..f90655c16 100644 --- a/tools/acc_forwarder/src/main.rs +++ b/tools/acc_forwarder/src/main.rs @@ -19,7 +19,7 @@ use { }, solana_sdk::{ account::Account, - borsh::try_from_slice_unchecked, + borsh0_10::try_from_slice_unchecked, commitment_config::{CommitmentConfig, CommitmentLevel}, pubkey::Pubkey, signature::Signature, From b79cc4ea4df51348071b438407e4dcb2eb7bd7eb Mon Sep 17 00:00:00 2001 From: Kirill Fomichev Date: Mon, 20 Nov 2023 12:41:19 -0500 Subject: [PATCH 03/23] ci: add lock, fmt, clippy checks --- .github/workflows/build-api.yml | 121 +++++++++++++++++++++++++++++++ .github/workflows/test.yml | 122 +++++++++++--------------------- Cargo.toml | 2 - 3 files changed, 161 insertions(+), 84 deletions(-) create mode 100644 .github/workflows/build-api.yml diff --git a/.github/workflows/build-api.yml b/.github/workflows/build-api.yml new file mode 100644 index 000000000..03dfd81ca --- /dev/null +++ b/.github/workflows/build-api.yml @@ -0,0 +1,121 @@ +name: Build das api components +# This workflow uses github runners. +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +# This may be adjusted to whatever suits best your runners config. +# Current config will build on manual trigger or pull-request (each push) +on: + # pull_request can be removed, to save minutes on github runners + pull_request: + workflow_dispatch: + push: + branches: + - 'main' + +env: + CARGO_TERM_COLOR: always + +jobs: + build-api: + strategy: + matrix: + os: [ubuntu-20.04, ubuntu-22.04] + # This can be also be runned on self-hosted github runners + runs-on: ["${{ matrix.os }}"] + + steps: + - name: checkout repo + uses: actions/checkout@v3 + # This step can be omited, to save storage space on the organization account + # Build process will take longer + - name: set build cache + uses: actions/cache@v3 + with: + path: | + ~/.cargo/bin/ + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ + digital-asset-rpc-infrastructure/target/ + key: ${{ matrix.os }}_digital-asset-rpc-infrastructure_${{ hashFiles('digital-asset-rpc-infrastructure/Cargo.lock') }} + restore-keys: | + ${{ matrix.os }}_digital-asset-rpc-infrastructure + + - name: build digital asset rpc infra + run: cargo build --verbose --release + + - name: build das_api + working-directory: das_api + run: cargo build --verbose --release + + - name: build migration + working-directory: migration + run: cargo build --verbose --release + + - name: rename binaries for ubuntu22 release + if: matrix.os == 'ubuntu-22.04' + run: | + mv target/release/nft_ingester target/release/nft_ingester22 + mv target/release/fetch_trees target/release/fetch_trees22 + mv das_api/target/release/das_api das_api/target/release/das_api22 + mv migration/target/release/migration migration/target/release/migration22 + + # This steps can be omited to save space, are mostly in place to validate binaries (manually) and path to them + # Omiting this will save on storage consumption on the account + - name: Publish artifact + if: matrix.os == 'ubuntu-22.04' + uses: actions/upload-artifact@v3.1.1 + with: + name: nft_ingester22 + path: target/release/nft_ingester22 + + - name: Publish artifact + if: matrix.os == 'ubuntu-22.04' + uses: actions/upload-artifact@v3.1.1 + with: + name: das_api22 + path: das_api/target/release/das_api22 + + - name: Publish artifact + if: matrix.os == 'ubuntu-22.04' + uses: actions/upload-artifact@v3.1.1 + with: + name: migration22 + path: migration/target/release/migration22 + + - name: Publish artifact + if: matrix.os == 'ubuntu-22.04' + uses: actions/upload-artifact@v3.1.1 + with: + name: fetch-trees22 + path: migration/target/release/fetch_trees22 + + - name: Publish artifact + if: matrix.os == 'ubuntu-20.04' + uses: actions/upload-artifact@v3.1.1 + with: + name: nft_ingester + path: target/release/nft_ingester + + - name: Publish artifact + if: matrix.os == 'ubuntu-20.04' + uses: actions/upload-artifact@v3.1.1 + with: + name: das_api + path: das_api/target/release/das_api + + - name: Publish artifact + if: matrix.os == 'ubuntu-20.04' + uses: actions/upload-artifact@v3.1.1 + with: + name: migration + path: migration/target/release/migration + + - name: Publish artifact + if: matrix.os == 'ubuntu-20.04' + uses: actions/upload-artifact@v3.1.1 + with: + name: fetch-trees + path: target/release/fetch_trees diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 03dfd81ca..6d73b212c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,35 +1,27 @@ -name: Build das api components -# This workflow uses github runners. +name: Check lock file, fmt, clippy + concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true -# This may be adjusted to whatever suits best your runners config. -# Current config will build on manual trigger or pull-request (each push) on: - # pull_request can be removed, to save minutes on github runners pull_request: - workflow_dispatch: push: branches: - 'main' + workflow_dispatch: env: CARGO_TERM_COLOR: always jobs: - build-api: - strategy: - matrix: - os: [ubuntu-20.04, ubuntu-22.04] - # This can be also be runned on self-hosted github runners - runs-on: ["${{ matrix.os }}"] + test: + runs-on: ubuntu-22.04 steps: - name: checkout repo uses: actions/checkout@v3 - # This step can be omited, to save storage space on the organization account - # Build process will take longer + - name: set build cache uses: actions/cache@v3 with: @@ -39,83 +31,49 @@ jobs: ~/.cargo/registry/cache/ ~/.cargo/git/db/ digital-asset-rpc-infrastructure/target/ - key: ${{ matrix.os }}_digital-asset-rpc-infrastructure_${{ hashFiles('digital-asset-rpc-infrastructure/Cargo.lock') }} - restore-keys: | - ${{ matrix.os }}_digital-asset-rpc-infrastructure + key: cargo-${{ hashFiles('**/Cargo.lock') }}-0001 - - name: build digital asset rpc infra - run: cargo build --verbose --release + # Cargo.lock + - name: Check lock file + run: | + cargo tree + git checkout Cargo.lock + cargo tree --frozen - - name: build das_api + - name: Check lock file for `das_api` working-directory: das_api - run: cargo build --verbose --release + run: | + cargo tree + git checkout Cargo.lock + cargo tree --frozen - - name: build migration + - name: Check lock file for `migration` working-directory: migration - run: cargo build --verbose --release - - - name: rename binaries for ubuntu22 release - if: matrix.os == 'ubuntu-22.04' run: | - mv target/release/nft_ingester target/release/nft_ingester22 - mv target/release/fetch_trees target/release/fetch_trees22 - mv das_api/target/release/das_api das_api/target/release/das_api22 - mv migration/target/release/migration migration/target/release/migration22 + cargo tree + git checkout Cargo.lock + cargo tree --frozen - # This steps can be omited to save space, are mostly in place to validate binaries (manually) and path to them - # Omiting this will save on storage consumption on the account - - name: Publish artifact - if: matrix.os == 'ubuntu-22.04' - uses: actions/upload-artifact@v3.1.1 - with: - name: nft_ingester22 - path: target/release/nft_ingester22 + # fmt + - name: Check fmt + run: cargo fmt --all -- --check - - name: Publish artifact - if: matrix.os == 'ubuntu-22.04' - uses: actions/upload-artifact@v3.1.1 - with: - name: das_api22 - path: das_api/target/release/das_api22 - - - name: Publish artifact - if: matrix.os == 'ubuntu-22.04' - uses: actions/upload-artifact@v3.1.1 - with: - name: migration22 - path: migration/target/release/migration22 - - - name: Publish artifact - if: matrix.os == 'ubuntu-22.04' - uses: actions/upload-artifact@v3.1.1 - with: - name: fetch-trees22 - path: migration/target/release/fetch_trees22 + - name: Check fmt `das_api` + working-directory: das_api + run: cargo fmt --all -- --check - - name: Publish artifact - if: matrix.os == 'ubuntu-20.04' - uses: actions/upload-artifact@v3.1.1 - with: - name: nft_ingester - path: target/release/nft_ingester + - name: Check fmt `migration` + working-directory: migration + run: cargo fmt --all -- --check - - name: Publish artifact - if: matrix.os == 'ubuntu-20.04' - uses: actions/upload-artifact@v3.1.1 - with: - name: das_api - path: das_api/target/release/das_api + # clippy + - name: Check clippy + run: cargo clippy --all-targets --tests - - name: Publish artifact - if: matrix.os == 'ubuntu-20.04' - uses: actions/upload-artifact@v3.1.1 - with: - name: migration - path: migration/target/release/migration + - name: Check clippy `das_api` + working-directory: das_api + run: cargo clippy --all-targets --tests - - name: Publish artifact - if: matrix.os == 'ubuntu-20.04' - uses: actions/upload-artifact@v3.1.1 - with: - name: fetch-trees - path: target/release/fetch_trees + - name: Check clippy `migration` + working-directory: migration + run: cargo clippy --all-targets --tests diff --git a/Cargo.toml b/Cargo.toml index f4b7545b3..e335b5f99 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,8 +13,6 @@ members = [ exclude = [ "das_api", "migration", - "metaplex_program_library", - "solana_program_library", ] [profile.release] From bb2eb9c6fd6434231592aaac28a184af717a1028 Mon Sep 17 00:00:00 2001 From: Kirill Fomichev Date: Mon, 20 Nov 2023 12:57:28 -0500 Subject: [PATCH 04/23] include migration to workspace --- .github/workflows/build-api.yml | 12 +- .github/workflows/test.yml | 15 - .gitignore | 3 - Cargo.lock | 212 +- Cargo.toml | 2 +- migration/Cargo.lock | 5767 ----------------- .../src/m20221026_155220_add_bg_tasks.rs | 8 +- .../src/m20230106_051135_unique_groupings.rs | 2 +- ...131_140613_change_token_account_indexes.rs | 2 + .../m20230203_205959_improve_upsert_perf.rs | 4 +- ...0230224_093722_performance_improvements.rs | 1 - .../src/m20230310_162227_add_indexes_to_bg.rs | 11 +- ...20230317_121944_remove_indexes_for_perf.rs | 4 +- .../m20230918_182123_add_raw_name_symbol.rs | 1 + migration/src/m20230919_072154_cl_audits.rs | 15 +- 15 files changed, 242 insertions(+), 5817 deletions(-) delete mode 100644 migration/Cargo.lock diff --git a/.github/workflows/build-api.yml b/.github/workflows/build-api.yml index 03dfd81ca..3c2e972a1 100644 --- a/.github/workflows/build-api.yml +++ b/.github/workflows/build-api.yml @@ -50,17 +50,13 @@ jobs: working-directory: das_api run: cargo build --verbose --release - - name: build migration - working-directory: migration - run: cargo build --verbose --release - - name: rename binaries for ubuntu22 release if: matrix.os == 'ubuntu-22.04' run: | mv target/release/nft_ingester target/release/nft_ingester22 mv target/release/fetch_trees target/release/fetch_trees22 + mv target/release/migration target/target/release/migration22 mv das_api/target/release/das_api das_api/target/release/das_api22 - mv migration/target/release/migration migration/target/release/migration22 # This steps can be omited to save space, are mostly in place to validate binaries (manually) and path to them # Omiting this will save on storage consumption on the account @@ -83,14 +79,14 @@ jobs: uses: actions/upload-artifact@v3.1.1 with: name: migration22 - path: migration/target/release/migration22 + path: target/release/migration22 - name: Publish artifact if: matrix.os == 'ubuntu-22.04' uses: actions/upload-artifact@v3.1.1 with: name: fetch-trees22 - path: migration/target/release/fetch_trees22 + path: target/release/fetch_trees22 - name: Publish artifact if: matrix.os == 'ubuntu-20.04' @@ -111,7 +107,7 @@ jobs: uses: actions/upload-artifact@v3.1.1 with: name: migration - path: migration/target/release/migration + path: target/release/migration - name: Publish artifact if: matrix.os == 'ubuntu-20.04' diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6d73b212c..65d5164ae 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -47,13 +47,6 @@ jobs: git checkout Cargo.lock cargo tree --frozen - - name: Check lock file for `migration` - working-directory: migration - run: | - cargo tree - git checkout Cargo.lock - cargo tree --frozen - # fmt - name: Check fmt run: cargo fmt --all -- --check @@ -62,10 +55,6 @@ jobs: working-directory: das_api run: cargo fmt --all -- --check - - name: Check fmt `migration` - working-directory: migration - run: cargo fmt --all -- --check - # clippy - name: Check clippy run: cargo clippy --all-targets --tests @@ -73,7 +62,3 @@ jobs: - name: Check clippy `das_api` working-directory: das_api run: cargo clippy --all-targets --tests - - - name: Check clippy `migration` - working-directory: migration - run: cargo clippy --all-targets --tests diff --git a/.gitignore b/.gitignore index b168f6bbc..c5f666e71 100644 --- a/.gitignore +++ b/.gitignore @@ -26,7 +26,4 @@ test-programs # Rust build dirs /das_api/target -/migration/target -/tests/*/target -/*/target /target diff --git a/Cargo.lock b/Cargo.lock index 7e33acdb9..3e575c039 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -583,6 +583,16 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" +[[package]] +name = "async-attributes" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3203e79f4dd9bdda415ed03cf14dae5a2bf775c683a00f94e9cd1faf0f596e5" +dependencies = [ + "quote 1.0.33", + "syn 1.0.109", +] + [[package]] name = "async-channel" version = "1.9.0" @@ -608,6 +618,36 @@ dependencies = [ "tokio", ] +[[package]] +name = "async-executor" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b0c4a4f319e45986f347ee47fef8bf5e81c9abc3f6f58dc2391439f30df65f0" +dependencies = [ + "async-lock", + "async-task", + "concurrent-queue", + "fastrand 2.0.1", + "futures-lite", + "slab", +] + +[[package]] +name = "async-global-executor" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1b6f5d7df27bd294849f8eec66ecfc63d11814df7a4f5d74168a2394467b776" +dependencies = [ + "async-channel", + "async-executor", + "async-io", + "async-lock", + "blocking", + "futures-lite", + "once_cell", + "tokio", +] + [[package]] name = "async-io" version = "1.13.0" @@ -646,6 +686,33 @@ dependencies = [ "event-listener", ] +[[package]] +name = "async-std" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d" +dependencies = [ + "async-attributes", + "async-channel", + "async-global-executor", + "async-io", + "async-lock", + "crossbeam-utils", + "futures-channel", + "futures-core", + "futures-io", + "futures-lite", + "gloo-timers", + "kv-log-macro", + "log", + "memchr", + "once_cell", + "pin-project-lite", + "pin-utils", + "slab", + "wasm-bindgen-futures", +] + [[package]] name = "async-stream" version = "0.3.5" @@ -668,6 +735,12 @@ dependencies = [ "syn 2.0.38", ] +[[package]] +name = "async-task" +version = "4.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4eb2cdb97421e01129ccb49169d8279ed21e829929144f4a22a6e54ac549ca1" + [[package]] name = "async-trait" version = "0.1.73" @@ -904,6 +977,22 @@ dependencies = [ "thiserror", ] +[[package]] +name = "blocking" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c36a4d0d48574b3dd360b4b7d95cc651d2b6557b6402848a27d4b228a473e2a" +dependencies = [ + "async-channel", + "async-lock", + "async-task", + "fastrand 2.0.1", + "futures-io", + "futures-lite", + "piper", + "tracing", +] + [[package]] name = "borsh" version = "0.9.3" @@ -1191,6 +1280,7 @@ checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" dependencies = [ "atty", "bitflags 1.3.2", + "clap_derive 3.2.25", "clap_lex 0.2.4", "indexmap 1.9.3", "once_cell", @@ -1206,7 +1296,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d04704f56c2cde07f43e8e2c154b43f216dc5c92fc98ada720177362f953b956" dependencies = [ "clap_builder", - "clap_derive", + "clap_derive 4.4.2", ] [[package]] @@ -1221,6 +1311,19 @@ dependencies = [ "strsim 0.10.0", ] +[[package]] +name = "clap_derive" +version = "3.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae6371b8bdc8b7d3959e9cf7b22d4435ef3e79e138688421ec654acf8c81b008" +dependencies = [ + "heck 0.4.1", + "proc-macro-error", + "proc-macro2 1.0.69", + "quote 1.0.33", + "syn 1.0.109", +] + [[package]] name = "clap_derive" version = "4.4.2" @@ -2182,6 +2285,18 @@ version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" +[[package]] +name = "gloo-timers" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" +dependencies = [ + "futures-channel", + "futures-core", + "js-sys", + "wasm-bindgen", +] + [[package]] name = "goblin" version = "0.5.4" @@ -2659,6 +2774,15 @@ dependencies = [ "cpufeatures", ] +[[package]] +name = "kv-log-macro" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" +dependencies = [ + "log", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -2761,6 +2885,9 @@ name = "log" version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +dependencies = [ + "value-bag", +] [[package]] name = "matchers" @@ -2838,6 +2965,17 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "migration" +version = "0.7.2" +dependencies = [ + "async-std", + "digital_asset_types", + "enum-iterator", + "enum-iterator-derive", + "sea-orm-migration", +] + [[package]] name = "mime" version = "0.3.17" @@ -3571,6 +3709,17 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "piper" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "668d31b1c4eba19242f2088b2bf3316b82ca31082a8335764db4e083db7485d4" +dependencies = [ + "atomic-waker", + "fastrand 2.0.1", + "futures-io", +] + [[package]] name = "pkcs8" version = "0.8.0" @@ -4571,6 +4720,22 @@ dependencies = [ "uuid", ] +[[package]] +name = "sea-orm-cli" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ebe1f820fe8949cf6a57272ba9ebd0be766e47c9b85c04b3cabea40ab9459b3" +dependencies = [ + "chrono", + "clap 3.2.25", + "dotenvy", + "regex", + "sea-schema", + "tracing", + "tracing-subscriber", + "url", +] + [[package]] name = "sea-orm-macros" version = "0.10.7" @@ -4584,6 +4749,22 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "sea-orm-migration" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ed3cdfa669e4c385922f902b9a58e0c2128782a4d0fe79c6c34f3b927565e5b" +dependencies = [ + "async-trait", + "clap 3.2.25", + "dotenvy", + "sea-orm", + "sea-orm-cli", + "sea-schema", + "tracing", + "tracing-subscriber", +] + [[package]] name = "sea-query" version = "0.27.2" @@ -4648,6 +4829,29 @@ dependencies = [ "thiserror", ] +[[package]] +name = "sea-schema" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d5fda574d980e9352b6c7abd6fc75697436fe0078cac2b548559b52643ad3b" +dependencies = [ + "futures", + "sea-query 0.27.2", + "sea-schema-derive", +] + +[[package]] +name = "sea-schema-derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56821b7076f5096b8f726e2791ad255a99c82498e08ec477a65a96c461ff1927" +dependencies = [ + "heck 0.3.3", + "proc-macro2 1.0.69", + "quote 1.0.33", + "syn 1.0.109", +] + [[package]] name = "sea-strum" version = "0.23.0" @@ -6998,6 +7202,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +[[package]] +name = "value-bag" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a72e1902dde2bd6441347de2b70b7f5d59bf157c6c62f0c44572607a1d55bbe" + [[package]] name = "vcpkg" version = "0.2.15" diff --git a/Cargo.toml b/Cargo.toml index e335b5f99..1bef11472 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,7 @@ members = [ "digital_asset_types", "metaplex-rpc-proxy", + "migration", "nft_ingester", "tools/acc_forwarder", "tools/bgtask_creator", @@ -12,7 +13,6 @@ members = [ ] exclude = [ "das_api", - "migration", ] [profile.release] diff --git a/migration/Cargo.lock b/migration/Cargo.lock deleted file mode 100644 index 172118165..000000000 --- a/migration/Cargo.lock +++ /dev/null @@ -1,5767 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "Inflector" -version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" -dependencies = [ - "lazy_static", - "regex", -] - -[[package]] -name = "addr2line" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "aead" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877" -dependencies = [ - "generic-array", -] - -[[package]] -name = "aes" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" -dependencies = [ - "cfg-if", - "cipher", - "cpufeatures", - "opaque-debug", -] - -[[package]] -name = "aes-gcm-siv" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589c637f0e68c877bbd59a4599bbe849cac8e5f3e4b5a3ebae8f528cd218dcdc" -dependencies = [ - "aead", - "aes", - "cipher", - "ctr", - "polyval", - "subtle", - "zeroize", -] - -[[package]] -name = "ahash" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" -dependencies = [ - "getrandom 0.2.10", - "once_cell", - "version_check", -] - -[[package]] -name = "ahash" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" -dependencies = [ - "cfg-if", - "getrandom 0.2.10", - "once_cell", - "version_check", -] - -[[package]] -name = "aho-corasick" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" -dependencies = [ - "memchr", -] - -[[package]] -name = "aliasable" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fd" - -[[package]] -name = "alloc-no-stdlib" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" - -[[package]] -name = "alloc-stdlib" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" -dependencies = [ - "alloc-no-stdlib", -] - -[[package]] -name = "allocator-api2" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" - -[[package]] -name = "anchor-attribute-access-control" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "faa5be5b72abea167f87c868379ba3c2be356bfca9e6f474fd055fa0f7eeb4f2" -dependencies = [ - "anchor-syn", - "anyhow", - "proc-macro2", - "quote", - "regex", - "syn 1.0.109", -] - -[[package]] -name = "anchor-attribute-account" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f468970344c7c9f9d03b4da854fd7c54f21305059f53789d0045c1dd803f0018" -dependencies = [ - "anchor-syn", - "anyhow", - "bs58 0.5.0", - "proc-macro2", - "quote", - "rustversion", - "syn 1.0.109", -] - -[[package]] -name = "anchor-attribute-constant" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59948e7f9ef8144c2aefb3f32a40c5fce2798baeec765ba038389e82301017ef" -dependencies = [ - "anchor-syn", - "proc-macro2", - "syn 1.0.109", -] - -[[package]] -name = "anchor-attribute-error" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc753c9d1c7981cb8948cf7e162fb0f64558999c0413058e2d43df1df5448086" -dependencies = [ - "anchor-syn", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "anchor-attribute-event" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f38b4e172ba1b52078f53fdc9f11e3dc0668ad27997838a0aad2d148afac8c97" -dependencies = [ - "anchor-syn", - "anyhow", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "anchor-attribute-program" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eebd21543606ab61e2d83d9da37d24d3886a49f390f9c43a1964735e8c0f0d5" -dependencies = [ - "anchor-syn", - "anyhow", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "anchor-derive-accounts" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec4720d899b3686396cced9508f23dab420f1308344456ec78ef76f98fda42af" -dependencies = [ - "anchor-syn", - "anyhow", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "anchor-derive-space" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f495e85480bd96ddeb77b71d499247c7d4e8b501e75ecb234e9ef7ae7bd6552a" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "anchor-lang" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d2d4b20100f1310a774aba3471ef268e5c4ba4d5c28c0bbe663c2658acbc414" -dependencies = [ - "anchor-attribute-access-control", - "anchor-attribute-account", - "anchor-attribute-constant", - "anchor-attribute-error", - "anchor-attribute-event", - "anchor-attribute-program", - "anchor-derive-accounts", - "anchor-derive-space", - "arrayref", - "base64 0.13.1", - "bincode", - "borsh 0.10.3", - "bytemuck", - "getrandom 0.2.10", - "solana-program", - "thiserror", -] - -[[package]] -name = "anchor-syn" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a125e4b0cc046cfec58f5aa25038e34cf440151d58f0db3afc55308251fe936d" -dependencies = [ - "anyhow", - "bs58 0.5.0", - "heck 0.3.3", - "proc-macro2", - "quote", - "serde", - "serde_json", - "sha2 0.10.8", - "syn 1.0.109", - "thiserror", -] - -[[package]] -name = "android-tzdata" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" - -[[package]] -name = "android_system_properties" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" -dependencies = [ - "libc", -] - -[[package]] -name = "anyhow" -version = "1.0.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" - -[[package]] -name = "ark-bn254" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a22f4561524cd949590d78d7d4c5df8f592430d221f7f3c9497bbafd8972120f" -dependencies = [ - "ark-ec", - "ark-ff", - "ark-std", -] - -[[package]] -name = "ark-ec" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "defd9a439d56ac24968cca0571f598a61bc8c55f71d50a89cda591cb750670ba" -dependencies = [ - "ark-ff", - "ark-poly", - "ark-serialize", - "ark-std", - "derivative", - "hashbrown 0.13.2", - "itertools 0.10.5", - "num-traits", - "zeroize", -] - -[[package]] -name = "ark-ff" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" -dependencies = [ - "ark-ff-asm", - "ark-ff-macros", - "ark-serialize", - "ark-std", - "derivative", - "digest 0.10.7", - "itertools 0.10.5", - "num-bigint 0.4.4", - "num-traits", - "paste", - "rustc_version", - "zeroize", -] - -[[package]] -name = "ark-ff-asm" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" -dependencies = [ - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ark-ff-macros" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" -dependencies = [ - "num-bigint 0.4.4", - "num-traits", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ark-poly" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d320bfc44ee185d899ccbadfa8bc31aab923ce1558716e1997a1e74057fe86bf" -dependencies = [ - "ark-ff", - "ark-serialize", - "ark-std", - "derivative", - "hashbrown 0.13.2", -] - -[[package]] -name = "ark-serialize" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" -dependencies = [ - "ark-serialize-derive", - "ark-std", - "digest 0.10.7", - "num-bigint 0.4.4", -] - -[[package]] -name = "ark-serialize-derive" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae3281bc6d0fd7e549af32b52511e1302185bd688fd3359fa36423346ff682ea" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ark-std" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" -dependencies = [ - "num-traits", - "rand 0.8.5", -] - -[[package]] -name = "array-bytes" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ad284aeb45c13f2fb4f084de4a420ebf447423bdf9386c0540ce33cb3ef4b8c" - -[[package]] -name = "arrayref" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" - -[[package]] -name = "arrayvec" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" - -[[package]] -name = "ascii" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eab1c04a571841102f5345a8fc0f6bb3d31c315dec879b5c6e42e40ce7ffa34e" - -[[package]] -name = "assert_matches" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" - -[[package]] -name = "async-attributes" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3203e79f4dd9bdda415ed03cf14dae5a2bf775c683a00f94e9cd1faf0f596e5" -dependencies = [ - "quote", - "syn 1.0.109", -] - -[[package]] -name = "async-channel" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" -dependencies = [ - "concurrent-queue", - "event-listener", - "futures-core", -] - -[[package]] -name = "async-compression" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb42b2197bf15ccb092b62c74515dbd8b86d0effd934795f6687c93b6e679a2c" -dependencies = [ - "brotli", - "flate2", - "futures-core", - "memchr", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "async-executor" -version = "1.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c1da3ae8dabd9c00f453a329dfe1fb28da3c0a72e2478cdcd93171740c20499" -dependencies = [ - "async-lock", - "async-task", - "concurrent-queue", - "fastrand 2.0.1", - "futures-lite", - "slab", -] - -[[package]] -name = "async-global-executor" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1b6f5d7df27bd294849f8eec66ecfc63d11814df7a4f5d74168a2394467b776" -dependencies = [ - "async-channel", - "async-executor", - "async-io", - "async-lock", - "blocking", - "futures-lite", - "once_cell", - "tokio", -] - -[[package]] -name = "async-io" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" -dependencies = [ - "async-lock", - "autocfg", - "cfg-if", - "concurrent-queue", - "futures-lite", - "log", - "parking", - "polling", - "rustix 0.37.24", - "slab", - "socket2 0.4.9", - "waker-fn", -] - -[[package]] -name = "async-lock" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" -dependencies = [ - "event-listener", -] - -[[package]] -name = "async-std" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d" -dependencies = [ - "async-attributes", - "async-channel", - "async-global-executor", - "async-io", - "async-lock", - "crossbeam-utils", - "futures-channel", - "futures-core", - "futures-io", - "futures-lite", - "gloo-timers", - "kv-log-macro", - "log", - "memchr", - "once_cell", - "pin-project-lite", - "pin-utils", - "slab", - "wasm-bindgen-futures", -] - -[[package]] -name = "async-stream" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" -dependencies = [ - "async-stream-impl", - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "async-stream-impl" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.38", -] - -[[package]] -name = "async-task" -version = "4.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9441c6b2fe128a7c2bf680a44c34d0df31ce09e5b7e401fcca3faa483dbc921" - -[[package]] -name = "async-trait" -version = "0.1.73" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.38", -] - -[[package]] -name = "atoi" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7c57d12312ff59c811c0643f4d80830505833c9ffaebd193d819392b265be8e" -dependencies = [ - "num-traits", -] - -[[package]] -name = "atomic-waker" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" - -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi 0.1.19", - "libc", - "winapi", -] - -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - -[[package]] -name = "backtrace" -version = "0.3.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - -[[package]] -name = "bae" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33b8de67cc41132507eeece2584804efcb15f85ba516e34c944b7667f480397a" -dependencies = [ - "heck 0.3.3", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "base64" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" - -[[package]] -name = "base64" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" - -[[package]] -name = "base64" -version = "0.21.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2" - -[[package]] -name = "bincode" -version = "1.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" -dependencies = [ - "serde", -] - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" - -[[package]] -name = "bitmaps" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2" -dependencies = [ - "typenum", -] - -[[package]] -name = "bitvec" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" -dependencies = [ - "funty", - "radium", - "tap", - "wyz", -] - -[[package]] -name = "blake3" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0231f06152bf547e9c2b5194f247cd97aacf6dcd8b15d8e5ec0663f64580da87" -dependencies = [ - "arrayref", - "arrayvec", - "cc", - "cfg-if", - "constant_time_eq", - "digest 0.10.7", -] - -[[package]] -name = "block-buffer" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" -dependencies = [ - "block-padding", - "generic-array", -] - -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - -[[package]] -name = "block-padding" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" - -[[package]] -name = "blockbuster" -version = "0.9.0-beta.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e0240c1218958c0d51284d783fa055f551d769bb8b7a4abf635b17fa9620dc" -dependencies = [ - "anchor-lang", - "async-trait", - "borsh 0.10.3", - "bs58 0.4.0", - "flatbuffers", - "lazy_static", - "log", - "mpl-bubblegum", - "mpl-candy-guard", - "mpl-candy-machine-core", - "mpl-token-metadata", - "plerkle_serialization", - "solana-sdk", - "spl-account-compression", - "spl-noop", - "spl-token 4.0.0", - "thiserror", -] - -[[package]] -name = "blocking" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c36a4d0d48574b3dd360b4b7d95cc651d2b6557b6402848a27d4b228a473e2a" -dependencies = [ - "async-channel", - "async-lock", - "async-task", - "fastrand 2.0.1", - "futures-io", - "futures-lite", - "piper", - "tracing", -] - -[[package]] -name = "borsh" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15bf3650200d8bffa99015595e10f1fbd17de07abbc25bb067da79e769939bfa" -dependencies = [ - "borsh-derive 0.9.3", - "hashbrown 0.11.2", -] - -[[package]] -name = "borsh" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4114279215a005bc675e386011e594e1d9b800918cea18fcadadcce864a2046b" -dependencies = [ - "borsh-derive 0.10.3", - "hashbrown 0.13.2", -] - -[[package]] -name = "borsh-derive" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6441c552f230375d18e3cc377677914d2ca2b0d36e52129fe15450a2dce46775" -dependencies = [ - "borsh-derive-internal 0.9.3", - "borsh-schema-derive-internal 0.9.3", - "proc-macro-crate 0.1.5", - "proc-macro2", - "syn 1.0.109", -] - -[[package]] -name = "borsh-derive" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0754613691538d51f329cce9af41d7b7ca150bc973056f1156611489475f54f7" -dependencies = [ - "borsh-derive-internal 0.10.3", - "borsh-schema-derive-internal 0.10.3", - "proc-macro-crate 0.1.5", - "proc-macro2", - "syn 1.0.109", -] - -[[package]] -name = "borsh-derive-internal" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5449c28a7b352f2d1e592a8a28bf139bc71afb0764a14f3c02500935d8c44065" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "borsh-derive-internal" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afb438156919598d2c7bad7e1c0adf3d26ed3840dbc010db1a882a65583ca2fb" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "borsh-schema-derive-internal" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdbd5696d8bfa21d53d9fe39a714a18538bad11492a42d066dbbc395fb1951c0" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "borsh-schema-derive-internal" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634205cc43f74a1b9046ef87c4540ebda95696ec0f315024860cad7c5b0f5ccd" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "brotli" -version = "3.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "516074a47ef4bce09577a3b379392300159ce5b1ba2e501ff1c819950066100f" -dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", - "brotli-decompressor", -] - -[[package]] -name = "brotli-decompressor" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da74e2b81409b1b743f8f0c62cc6254afefb8b8e50bbfe3735550f7aeefa3448" -dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", -] - -[[package]] -name = "bs58" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" - -[[package]] -name = "bs58" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5353f36341f7451062466f0b755b96ac3a9547e4d7f6b70d603fc721a7d7896" -dependencies = [ - "tinyvec", -] - -[[package]] -name = "bumpalo" -version = "3.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" - -[[package]] -name = "bv" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8834bb1d8ee5dc048ee3124f2c7c1afcc6bc9aed03f11e9dfd8c69470a5db340" -dependencies = [ - "feature-probe", - "serde", -] - -[[package]] -name = "bytecheck" -version = "0.6.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6372023ac861f6e6dc89c8344a8f398fb42aaba2b5dbc649ca0c0e9dbcb627" -dependencies = [ - "bytecheck_derive", - "ptr_meta", - "simdutf8", -] - -[[package]] -name = "bytecheck_derive" -version = "0.6.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7ec4c6f261935ad534c0c22dbef2201b45918860eb1c574b972bd213a76af61" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "bytemuck" -version = "1.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" -dependencies = [ - "bytemuck_derive", -] - -[[package]] -name = "bytemuck_derive" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "965ab7eb5f8f97d2a083c799f3a1b994fc397b2fe2da5d1da1626ce15a39f2b1" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.38", -] - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - -[[package]] -name = "bytes" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" - -[[package]] -name = "cc" -version = "1.0.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" -dependencies = [ - "jobserver", - "libc", -] - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "chrono" -version = "0.4.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" -dependencies = [ - "android-tzdata", - "iana-time-zone", - "js-sys", - "num-traits", - "serde", - "wasm-bindgen", - "windows-targets", -] - -[[package]] -name = "cipher" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" -dependencies = [ - "generic-array", -] - -[[package]] -name = "clap" -version = "3.2.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" -dependencies = [ - "atty", - "bitflags 1.3.2", - "clap_derive", - "clap_lex", - "indexmap 1.9.3", - "once_cell", - "strsim", - "termcolor", - "textwrap", -] - -[[package]] -name = "clap_derive" -version = "3.2.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae6371b8bdc8b7d3959e9cf7b22d4435ef3e79e138688421ec654acf8c81b008" -dependencies = [ - "heck 0.4.1", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "clap_lex" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" -dependencies = [ - "os_str_bytes", -] - -[[package]] -name = "combine" -version = "3.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da3da6baa321ec19e1cc41d31bf599f00c783d0517095cdaf0332e3fe8d20680" -dependencies = [ - "ascii", - "byteorder", - "either", - "memchr", - "unreachable", -] - -[[package]] -name = "concurrent-queue" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f057a694a54f12365049b0958a1685bb52d567f5593b355fbf685838e873d400" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "console_error_panic_hook" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" -dependencies = [ - "cfg-if", - "wasm-bindgen", -] - -[[package]] -name = "console_log" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89f72f65e8501878b8a004d5a1afb780987e2ce2b4532c562e367a72c57499f" -dependencies = [ - "log", - "web-sys", -] - -[[package]] -name = "constant_time_eq" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" - -[[package]] -name = "core-foundation" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" - -[[package]] -name = "cpufeatures" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" -dependencies = [ - "libc", -] - -[[package]] -name = "crc" -version = "3.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86ec7a15cbe22e59248fc7eadb1907dab5ba09372595da4d73dd805ed4417dfe" -dependencies = [ - "crc-catalog", -] - -[[package]] -name = "crc-catalog" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cace84e55f07e7301bae1c519df89cdad8cc3cd868413d3fdbdeca9ff3db484" - -[[package]] -name = "crc32fast" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "crossbeam-channel" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" -dependencies = [ - "cfg-if", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" -dependencies = [ - "cfg-if", - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" -dependencies = [ - "autocfg", - "cfg-if", - "crossbeam-utils", - "memoffset", - "scopeguard", -] - -[[package]] -name = "crossbeam-queue" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add" -dependencies = [ - "cfg-if", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "crunchy" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "crypto-mac" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" -dependencies = [ - "generic-array", - "subtle", -] - -[[package]] -name = "ctr" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "049bb91fb4aaf0e3c7efa6cd5ef877dbbbd15b39dad06d9948de4ec8a75761ea" -dependencies = [ - "cipher", -] - -[[package]] -name = "curve25519-dalek" -version = "3.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90f9d052967f590a76e62eb387bd0bbb1b000182c3cefe5364db6b7211651bc0" -dependencies = [ - "byteorder", - "digest 0.9.0", - "rand_core 0.5.1", - "serde", - "subtle", - "zeroize", -] - -[[package]] -name = "darling" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" -dependencies = [ - "darling_core 0.13.4", - "darling_macro 0.13.4", -] - -[[package]] -name = "darling" -version = "0.20.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" -dependencies = [ - "darling_core 0.20.3", - "darling_macro 0.20.3", -] - -[[package]] -name = "darling_core" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn 1.0.109", -] - -[[package]] -name = "darling_core" -version = "0.20.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn 2.0.38", -] - -[[package]] -name = "darling_macro" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" -dependencies = [ - "darling_core 0.13.4", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "darling_macro" -version = "0.20.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" -dependencies = [ - "darling_core 0.20.3", - "quote", - "syn 2.0.38", -] - -[[package]] -name = "deranged" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2696e8a945f658fd14dc3b87242e6b80cd0f36ff04ea560fa39082368847946" -dependencies = [ - "serde", -] - -[[package]] -name = "derivation-path" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e5c37193a1db1d8ed868c03ec7b152175f26160a5b740e5e484143877e0adf0" - -[[package]] -name = "derivative" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "digest" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" -dependencies = [ - "generic-array", -] - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer 0.10.4", - "crypto-common", - "subtle", -] - -[[package]] -name = "digital_asset_types" -version = "0.7.2" -dependencies = [ - "async-trait", - "blockbuster", - "bs58 0.4.0", - "futures", - "indexmap 1.9.3", - "jsonpath_lib", - "log", - "mime_guess", - "num-derive 0.3.3", - "num-traits", - "reqwest", - "schemars", - "schemars_derive", - "sea-orm", - "sea-query 0.28.5", - "serde", - "serde_json", - "solana-sdk", - "spl-concurrent-merkle-tree", - "thiserror", - "tokio", - "url", -] - -[[package]] -name = "dirs" -version = "4.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" -dependencies = [ - "dirs-sys", -] - -[[package]] -name = "dirs-sys" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" -dependencies = [ - "libc", - "redox_users", - "winapi", -] - -[[package]] -name = "dotenvy" -version = "0.15.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" - -[[package]] -name = "dyn-clone" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23d2f3407d9a573d666de4b5bdf10569d73ca9478087346697dcbae6244bfbcd" - -[[package]] -name = "eager" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abe71d579d1812060163dff96056261deb5bf6729b100fa2e36a68b9649ba3d3" - -[[package]] -name = "ed25519" -version = "1.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7" -dependencies = [ - "signature", -] - -[[package]] -name = "ed25519-dalek" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" -dependencies = [ - "curve25519-dalek", - "ed25519", - "rand 0.7.3", - "serde", - "sha2 0.9.9", - "zeroize", -] - -[[package]] -name = "ed25519-dalek-bip32" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d2be62a4061b872c8c0873ee4fc6f101ce7b889d039f019c5fa2af471a59908" -dependencies = [ - "derivation-path", - "ed25519-dalek", - "hmac 0.12.1", - "sha2 0.10.8", -] - -[[package]] -name = "either" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" - -[[package]] -name = "encoding_rs" -version = "0.8.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "enum-iterator" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7add3873b5dd076766ee79c8e406ad1a472c385476b9e38849f8eec24f1be689" -dependencies = [ - "enum-iterator-derive", -] - -[[package]] -name = "enum-iterator-derive" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eecf8589574ce9b895052fa12d69af7a233f99e6107f5cb8dd1044f2a17bfdcb" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.38", -] - -[[package]] -name = "env_logger" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" -dependencies = [ - "atty", - "humantime", - "log", - "regex", - "termcolor", -] - -[[package]] -name = "equivalent" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" - -[[package]] -name = "errno" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860" -dependencies = [ - "libc", - "windows-sys", -] - -[[package]] -name = "event-listener" -version = "2.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" - -[[package]] -name = "fastrand" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] - -[[package]] -name = "fastrand" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" - -[[package]] -name = "feature-probe" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "835a3dc7d1ec9e75e2b5fb4ba75396837112d2060b03f7d43bc1897c7f7211da" - -[[package]] -name = "finl_unicode" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fcfdc7a0362c9f4444381a9e697c79d435fe65b52a37466fc2c1184cee9edc6" - -[[package]] -name = "flatbuffers" -version = "23.5.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dac53e22462d78c16d64a1cd22371b54cc3fe94aa15e7886a2fa6e5d1ab8640" -dependencies = [ - "bitflags 1.3.2", - "rustc_version", -] - -[[package]] -name = "flate2" -version = "1.0.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6c98ee8095e9d1dcbf2fcc6d95acccb90d1c81db1e44725c6a984b1dbdfb010" -dependencies = [ - "crc32fast", - "miniz_oxide", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - -[[package]] -name = "form_urlencoded" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "funty" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" - -[[package]] -name = "futures" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" - -[[package]] -name = "futures-executor" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-intrusive" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a604f7a68fbf8103337523b1fadc8ade7361ee3f112f7c680ad179651616aed5" -dependencies = [ - "futures-core", - "lock_api", - "parking_lot 0.11.2", -] - -[[package]] -name = "futures-io" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" - -[[package]] -name = "futures-lite" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" -dependencies = [ - "fastrand 1.9.0", - "futures-core", - "futures-io", - "memchr", - "parking", - "pin-project-lite", - "waker-fn", -] - -[[package]] -name = "futures-macro" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.38", -] - -[[package]] -name = "futures-sink" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" - -[[package]] -name = "futures-task" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" - -[[package]] -name = "futures-util" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "slab", -] - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "serde", - "typenum", - "version_check", -] - -[[package]] -name = "gethostname" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1ebd34e35c46e00bb73e81363248d627782724609fe1b6396f553f68fe3862e" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "getrandom" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" -dependencies = [ - "cfg-if", - "js-sys", - "libc", - "wasi 0.9.0+wasi-snapshot-preview1", - "wasm-bindgen", -] - -[[package]] -name = "getrandom" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" -dependencies = [ - "cfg-if", - "js-sys", - "libc", - "wasi 0.11.0+wasi-snapshot-preview1", - "wasm-bindgen", -] - -[[package]] -name = "gimli" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" - -[[package]] -name = "gloo-timers" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" -dependencies = [ - "futures-channel", - "futures-core", - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "goblin" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7666983ed0dd8d21a6f6576ee00053ca0926fb281a5522577a4dbd0f1b54143" -dependencies = [ - "log", - "plain", - "scroll", -] - -[[package]] -name = "h2" -version = "0.3.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91fc23aa11be92976ef4729127f1a74adf36d8436f7816b185d18df956790833" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http", - "indexmap 1.9.3", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "hash32" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" -dependencies = [ - "byteorder", -] - -[[package]] -name = "hashbrown" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" -dependencies = [ - "ahash 0.7.6", -] - -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" -dependencies = [ - "ahash 0.7.6", -] - -[[package]] -name = "hashbrown" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" -dependencies = [ - "ahash 0.8.3", -] - -[[package]] -name = "hashbrown" -version = "0.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dfda62a12f55daeae5015f81b0baea145391cb4520f86c248fc615d72640d12" -dependencies = [ - "ahash 0.8.3", - "allocator-api2", -] - -[[package]] -name = "hashlink" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" -dependencies = [ - "hashbrown 0.14.1", -] - -[[package]] -name = "heck" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" -dependencies = [ - "unicode-segmentation", -] - -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" -dependencies = [ - "unicode-segmentation", -] - -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - -[[package]] -name = "hermit-abi" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "hkdf" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437" -dependencies = [ - "hmac 0.12.1", -] - -[[package]] -name = "hmac" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840" -dependencies = [ - "crypto-mac", - "digest 0.9.0", -] - -[[package]] -name = "hmac" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" -dependencies = [ - "digest 0.10.7", -] - -[[package]] -name = "hmac-drbg" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17ea0a1394df5b6574da6e0c1ade9e78868c9fb0a4e5ef4428e32da4676b85b1" -dependencies = [ - "digest 0.9.0", - "generic-array", - "hmac 0.8.1", -] - -[[package]] -name = "http" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "http-body" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" -dependencies = [ - "bytes", - "http", - "pin-project-lite", -] - -[[package]] -name = "httparse" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" - -[[package]] -name = "httpdate" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" - -[[package]] -name = "humantime" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" - -[[package]] -name = "hyper" -version = "0.14.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" -dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "socket2 0.4.9", - "tokio", - "tower-service", - "tracing", - "want", -] - -[[package]] -name = "hyper-rustls" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d78e1e73ec14cf7375674f74d7dde185c8206fd9dea6fb6295e8a98098aaa97" -dependencies = [ - "futures-util", - "http", - "hyper", - "rustls 0.21.7", - "tokio", - "tokio-rustls 0.24.1", -] - -[[package]] -name = "hyper-tls" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" -dependencies = [ - "bytes", - "hyper", - "native-tls", - "tokio", - "tokio-native-tls", -] - -[[package]] -name = "iana-time-zone" -version = "0.1.57" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "wasm-bindgen", - "windows", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" -dependencies = [ - "cc", -] - -[[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - -[[package]] -name = "idna" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "im" -version = "15.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0acd33ff0285af998aaf9b57342af478078f53492322fafc47450e09397e0e9" -dependencies = [ - "bitmaps", - "rand_core 0.6.4", - "rand_xoshiro", - "rayon", - "serde", - "sized-chunks", - "typenum", - "version_check", -] - -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", -] - -[[package]] -name = "indexmap" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897" -dependencies = [ - "equivalent", - "hashbrown 0.14.1", -] - -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "io-lifetimes" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" -dependencies = [ - "hermit-abi 0.3.3", - "libc", - "windows-sys", -] - -[[package]] -name = "ipnet" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" - -[[package]] -name = "itertools" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" -dependencies = [ - "either", -] - -[[package]] -name = "itertools" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" - -[[package]] -name = "jobserver" -version = "0.1.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2" -dependencies = [ - "libc", -] - -[[package]] -name = "js-sys" -version = "0.3.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "jsonpath_lib" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaa63191d68230cccb81c5aa23abd53ed64d83337cacbb25a7b8c7979523774f" -dependencies = [ - "log", - "serde", - "serde_json", -] - -[[package]] -name = "kaigan" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a26f49495f94a283312e7ef45a243540ef20c9356bb01c8d84a61ac8ba5339b" -dependencies = [ - "borsh 0.10.3", -] - -[[package]] -name = "keccak" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" -dependencies = [ - "cpufeatures", -] - -[[package]] -name = "kv-log-macro" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" -dependencies = [ - "log", -] - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "libc" -version = "0.2.149" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" - -[[package]] -name = "libsecp256k1" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9d220bc1feda2ac231cb78c3d26f27676b8cf82c96971f7aeef3d0cf2797c73" -dependencies = [ - "arrayref", - "base64 0.12.3", - "digest 0.9.0", - "hmac-drbg", - "libsecp256k1-core", - "libsecp256k1-gen-ecmult", - "libsecp256k1-gen-genmult", - "rand 0.7.3", - "serde", - "sha2 0.9.9", - "typenum", -] - -[[package]] -name = "libsecp256k1-core" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0f6ab710cec28cef759c5f18671a27dae2a5f952cdaaee1d8e2908cb2478a80" -dependencies = [ - "crunchy", - "digest 0.9.0", - "subtle", -] - -[[package]] -name = "libsecp256k1-gen-ecmult" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccab96b584d38fac86a83f07e659f0deafd0253dc096dab5a36d53efe653c5c3" -dependencies = [ - "libsecp256k1-core", -] - -[[package]] -name = "libsecp256k1-gen-genmult" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67abfe149395e3aa1c48a2beb32b068e2334402df8181f818d3aee2b304c4f5d" -dependencies = [ - "libsecp256k1-core", -] - -[[package]] -name = "linux-raw-sys" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" - -[[package]] -name = "linux-raw-sys" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" - -[[package]] -name = "lock_api" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" -dependencies = [ - "value-bag", -] - -[[package]] -name = "matchers" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" -dependencies = [ - "regex-automata 0.1.10", -] - -[[package]] -name = "md-5" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" -dependencies = [ - "cfg-if", - "digest 0.10.7", -] - -[[package]] -name = "memchr" -version = "2.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" - -[[package]] -name = "memmap2" -version = "0.5.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" -dependencies = [ - "libc", -] - -[[package]] -name = "memoffset" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" -dependencies = [ - "autocfg", -] - -[[package]] -name = "merlin" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58c38e2799fc0978b65dfff8023ec7843e2330bb462f19198840b34b6582397d" -dependencies = [ - "byteorder", - "keccak", - "rand_core 0.6.4", - "zeroize", -] - -[[package]] -name = "migration" -version = "0.7.2" -dependencies = [ - "async-std", - "digital_asset_types", - "enum-iterator", - "enum-iterator-derive", - "sea-orm-migration", -] - -[[package]] -name = "mime" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" - -[[package]] -name = "mime_guess" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" -dependencies = [ - "mime", - "unicase", -] - -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - -[[package]] -name = "miniz_oxide" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" -dependencies = [ - "adler", -] - -[[package]] -name = "mio" -version = "0.8.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" -dependencies = [ - "libc", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys", -] - -[[package]] -name = "mpl-bubblegum" -version = "1.0.1-beta.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29346f26192bb7f73330196fde4c8cfb35675bf1a4b026cd088f7ca8fda69f3f" -dependencies = [ - "borsh 0.10.3", - "kaigan", - "num-derive 0.3.3", - "num-traits", - "solana-program", - "thiserror", -] - -[[package]] -name = "mpl-candy-guard" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59c5c2ffb233226e0c531f1cf800909e46120e98722eeb53dae68b0996303a38" -dependencies = [ - "anchor-lang", - "arrayref", - "mpl-candy-guard-derive", - "mpl-candy-machine-core", - "mpl-token-auth-rules", - "mpl-token-metadata", - "solana-gateway", - "solana-program", - "spl-associated-token-account", - "spl-token 4.0.0", - "spl-token-2022 0.9.0", -] - -[[package]] -name = "mpl-candy-guard-derive" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18e4d3002ea881e94a238798faf87a006a687297a24bd4b3f810fbb63611173d" -dependencies = [ - "quote", - "syn 1.0.109", -] - -[[package]] -name = "mpl-candy-machine-core" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4db99e1aac3bdebf907338aec5f1785701b8a82e6bdac5f42a270750d37c5264" -dependencies = [ - "anchor-lang", - "arrayref", - "mpl-token-auth-rules", - "mpl-token-metadata", - "solana-program", - "spl-associated-token-account", - "spl-token 4.0.0", -] - -[[package]] -name = "mpl-token-auth-rules" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66b1ec5ee0570f688cc84ff4624c5c50732f1a2bfc789f6b34af5b563428d971" -dependencies = [ - "borsh 0.10.3", - "bytemuck", - "mpl-token-metadata-context-derive 0.2.1", - "num-derive 0.3.3", - "num-traits", - "rmp-serde", - "serde", - "shank", - "solana-program", - "solana-zk-token-sdk", - "thiserror", -] - -[[package]] -name = "mpl-token-metadata" -version = "2.0.0-beta.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3545bd5fe73416f6514cd93899612e0e138619e72df8bc7d19906a12688c69e" -dependencies = [ - "arrayref", - "borsh 0.10.3", - "mpl-token-auth-rules", - "mpl-token-metadata-context-derive 0.3.0", - "mpl-utils", - "num-derive 0.3.3", - "num-traits", - "serde", - "serde_with 1.14.0", - "shank", - "solana-program", - "spl-associated-token-account", - "spl-token 4.0.0", - "thiserror", -] - -[[package]] -name = "mpl-token-metadata-context-derive" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12989bc45715b0ee91944855130131479f9c772e198a910c3eb0ea327d5bffc3" -dependencies = [ - "quote", - "syn 1.0.109", -] - -[[package]] -name = "mpl-token-metadata-context-derive" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5a739019e11d93661a64ef5fe108ab17c79b35961e944442ff6efdd460ad01a" -dependencies = [ - "quote", - "syn 1.0.109", -] - -[[package]] -name = "mpl-utils" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f2e4f92aec317d5853c0cc4c03c55f5178511c45bb3dbb441aea63117bf3dc9" -dependencies = [ - "arrayref", - "solana-program", - "spl-token-2022 0.6.1", -] - -[[package]] -name = "native-tls" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" -dependencies = [ - "lazy_static", - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - -[[package]] -name = "nu-ansi-term" -version = "0.46.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" -dependencies = [ - "overload", - "winapi", -] - -[[package]] -name = "num" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8536030f9fea7127f841b45bb6243b27255787fb4eb83958aa1ef9d2fdc0c36" -dependencies = [ - "num-bigint 0.2.6", - "num-complex", - "num-integer", - "num-iter", - "num-rational", - "num-traits", -] - -[[package]] -name = "num-bigint" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-bigint" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-complex" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6b19411a9719e753aff12e5187b74d60d3dc449ec3f4dc21e3989c3f554bc95" -dependencies = [ - "autocfg", - "num-traits", -] - -[[package]] -name = "num-derive" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "num-derive" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfb77679af88f8b125209d354a202862602672222e7f2313fdd6dc349bad4712" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.38", -] - -[[package]] -name = "num-integer" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" -dependencies = [ - "autocfg", - "num-traits", -] - -[[package]] -name = "num-iter" -version = "0.1.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef" -dependencies = [ - "autocfg", - "num-bigint 0.2.6", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" -dependencies = [ - "autocfg", -] - -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi 0.3.3", - "libc", -] - -[[package]] -name = "num_enum" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9" -dependencies = [ - "num_enum_derive 0.5.11", -] - -[[package]] -name = "num_enum" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a015b430d3c108a207fd776d2e2196aaf8b1cf8cf93253e3a097ff3085076a1" -dependencies = [ - "num_enum_derive 0.6.1", -] - -[[package]] -name = "num_enum" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70bf6736f74634d299d00086f02986875b3c2d924781a6a2cb6c201e73da0ceb" -dependencies = [ - "num_enum_derive 0.7.0", -] - -[[package]] -name = "num_enum_derive" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799" -dependencies = [ - "proc-macro-crate 1.3.1", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "num_enum_derive" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96667db765a921f7b295ffee8b60472b686a51d4f21c2ee4ffdb94c7013b65a6" -dependencies = [ - "proc-macro-crate 1.3.1", - "proc-macro2", - "quote", - "syn 2.0.38", -] - -[[package]] -name = "num_enum_derive" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56ea360eafe1022f7cc56cd7b869ed57330fb2453d0c7831d99b74c65d2f5597" -dependencies = [ - "proc-macro-crate 1.3.1", - "proc-macro2", - "quote", - "syn 2.0.38", -] - -[[package]] -name = "object" -version = "0.32.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" -dependencies = [ - "memchr", -] - -[[package]] -name = "once_cell" -version = "1.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" - -[[package]] -name = "opaque-debug" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" - -[[package]] -name = "openssl" -version = "0.10.57" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bac25ee399abb46215765b1cb35bc0212377e58a061560d8b29b024fd0430e7c" -dependencies = [ - "bitflags 2.4.0", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.38", -] - -[[package]] -name = "openssl-probe" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" - -[[package]] -name = "openssl-sys" -version = "0.9.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db4d56a4c0478783083cfafcc42493dd4a981d41669da64b4572a2a089b51b1d" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "os_str_bytes" -version = "6.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d5d9eb14b174ee9aa2ef96dc2b94637a2d4b6e7cb873c7e171f0c20c6cf3eac" - -[[package]] -name = "ouroboros" -version = "0.15.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1358bd1558bd2a083fed428ffeda486fbfb323e698cdda7794259d592ca72db" -dependencies = [ - "aliasable", - "ouroboros_macro", -] - -[[package]] -name = "ouroboros_macro" -version = "0.15.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f7d21ccd03305a674437ee1248f3ab5d4b1db095cf1caf49f1713ddf61956b7" -dependencies = [ - "Inflector", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "overload" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" - -[[package]] -name = "parking" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e52c774a4c39359c1d1c52e43f73dd91a75a614652c825408eec30c95a9b2067" - -[[package]] -name = "parking_lot" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" -dependencies = [ - "instant", - "lock_api", - "parking_lot_core 0.8.6", -] - -[[package]] -name = "parking_lot" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" -dependencies = [ - "lock_api", - "parking_lot_core 0.9.8", -] - -[[package]] -name = "parking_lot_core" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" -dependencies = [ - "cfg-if", - "instant", - "libc", - "redox_syscall 0.2.16", - "smallvec", - "winapi", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall 0.3.5", - "smallvec", - "windows-targets", -] - -[[package]] -name = "paste" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" - -[[package]] -name = "pbkdf2" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "216eaa586a190f0a738f2f918511eecfa90f13295abec0e457cdebcceda80cbd" -dependencies = [ - "crypto-mac", -] - -[[package]] -name = "pbkdf2" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" -dependencies = [ - "digest 0.10.7", -] - -[[package]] -name = "percent-encoding" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" - -[[package]] -name = "percentage" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fd23b938276f14057220b707937bcb42fa76dda7560e57a2da30cb52d557937" -dependencies = [ - "num", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "piper" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "668d31b1c4eba19242f2088b2bf3316b82ca31082a8335764db4e083db7485d4" -dependencies = [ - "atomic-waker", - "fastrand 2.0.1", - "futures-io", -] - -[[package]] -name = "pkg-config" -version = "0.3.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" - -[[package]] -name = "plain" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" - -[[package]] -name = "plerkle_serialization" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f021e409a6a1ec8b7a325db27254e7fa3942e845cfe96f5f8f494977f2646a8" -dependencies = [ - "bs58 0.4.0", - "chrono", - "flatbuffers", - "serde", - "solana-sdk", - "solana-transaction-status", - "thiserror", -] - -[[package]] -name = "polling" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" -dependencies = [ - "autocfg", - "bitflags 1.3.2", - "cfg-if", - "concurrent-queue", - "libc", - "log", - "pin-project-lite", - "windows-sys", -] - -[[package]] -name = "polyval" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8419d2b623c7c0896ff2d5d96e2cb4ede590fed28fcc34934f4c33c036e620a1" -dependencies = [ - "cfg-if", - "cpufeatures", - "opaque-debug", - "universal-hash", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" - -[[package]] -name = "proc-macro-crate" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" -dependencies = [ - "toml", -] - -[[package]] -name = "proc-macro-crate" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" -dependencies = [ - "once_cell", - "toml_edit", -] - -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn 1.0.109", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - -[[package]] -name = "proc-macro2" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "ptr_meta" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1" -dependencies = [ - "ptr_meta_derive", -] - -[[package]] -name = "ptr_meta_derive" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "qstring" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d464fae65fff2680baf48019211ce37aaec0c78e9264c84a3e484717f965104e" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "quote" -version = "1.0.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "radium" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" - -[[package]] -name = "rand" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "getrandom 0.1.16", - "libc", - "rand_chacha 0.2.2", - "rand_core 0.5.1", - "rand_hc", -] - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_chacha" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" -dependencies = [ - "ppv-lite86", - "rand_core 0.5.1", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -dependencies = [ - "getrandom 0.1.16", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom 0.2.10", -] - -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core 0.5.1", -] - -[[package]] -name = "rand_xoshiro" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" -dependencies = [ - "rand_core 0.6.4", -] - -[[package]] -name = "rayon" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" -dependencies = [ - "crossbeam-deque", - "crossbeam-utils", -] - -[[package]] -name = "redox_syscall" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "redox_syscall" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "redox_users" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" -dependencies = [ - "getrandom 0.2.10", - "redox_syscall 0.2.16", - "thiserror", -] - -[[package]] -name = "regex" -version = "1.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebee201405406dbf528b8b672104ae6d6d63e6d118cb10e4d51abbc7b58044ff" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata 0.3.9", - "regex-syntax 0.7.5", -] - -[[package]] -name = "regex-automata" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" -dependencies = [ - "regex-syntax 0.6.29", -] - -[[package]] -name = "regex-automata" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59b23e92ee4318893fa3fe3e6fb365258efbfe6ac6ab30f090cdcbb7aa37efa9" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax 0.7.5", -] - -[[package]] -name = "regex-syntax" -version = "0.6.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" - -[[package]] -name = "regex-syntax" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" - -[[package]] -name = "rend" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2571463863a6bd50c32f94402933f03457a3fbaf697a707c5be741e459f08fd" -dependencies = [ - "bytecheck", -] - -[[package]] -name = "reqwest" -version = "0.11.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" -dependencies = [ - "async-compression", - "base64 0.21.4", - "bytes", - "encoding_rs", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "hyper", - "hyper-rustls", - "hyper-tls", - "ipnet", - "js-sys", - "log", - "mime", - "native-tls", - "once_cell", - "percent-encoding", - "pin-project-lite", - "rustls 0.21.7", - "rustls-pemfile", - "serde", - "serde_json", - "serde_urlencoded", - "system-configuration", - "tokio", - "tokio-native-tls", - "tokio-rustls 0.24.1", - "tokio-util", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "webpki-roots 0.25.2", - "winreg", -] - -[[package]] -name = "ring" -version = "0.16.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" -dependencies = [ - "cc", - "libc", - "once_cell", - "spin 0.5.2", - "untrusted 0.7.1", - "web-sys", - "winapi", -] - -[[package]] -name = "ring" -version = "0.17.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "911b295d2d302948838c8ac142da1ee09fa7863163b44e6715bc9357905878b8" -dependencies = [ - "cc", - "getrandom 0.2.10", - "libc", - "spin 0.9.8", - "untrusted 0.9.0", - "windows-sys", -] - -[[package]] -name = "rkyv" -version = "0.7.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0200c8230b013893c0b2d6213d6ec64ed2b9be2e0e016682b7224ff82cff5c58" -dependencies = [ - "bitvec", - "bytecheck", - "hashbrown 0.12.3", - "ptr_meta", - "rend", - "rkyv_derive", - "seahash", - "tinyvec", - "uuid", -] - -[[package]] -name = "rkyv_derive" -version = "0.7.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2e06b915b5c230a17d7a736d1e2e63ee753c256a8614ef3f5147b13a4f5541d" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "rmp" -version = "0.8.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f9860a6cc38ed1da53456442089b4dfa35e7cedaa326df63017af88385e6b20" -dependencies = [ - "byteorder", - "num-traits", - "paste", -] - -[[package]] -name = "rmp-serde" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bffea85eea980d8a74453e5d02a8d93028f3c34725de143085a844ebe953258a" -dependencies = [ - "byteorder", - "rmp", - "serde", -] - -[[package]] -name = "rust_decimal" -version = "1.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4c4216490d5a413bc6d10fa4742bd7d4955941d062c0ef873141d6b0e7b30fd" -dependencies = [ - "arrayvec", - "borsh 0.10.3", - "bytes", - "num-traits", - "rand 0.8.5", - "rkyv", - "serde", - "serde_json", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" - -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - -[[package]] -name = "rustc_version" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" -dependencies = [ - "semver", -] - -[[package]] -name = "rustix" -version = "0.37.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4279d76516df406a8bd37e7dff53fd37d1a093f997a3c34a5c21658c126db06d" -dependencies = [ - "bitflags 1.3.2", - "errno", - "io-lifetimes", - "libc", - "linux-raw-sys 0.3.8", - "windows-sys", -] - -[[package]] -name = "rustix" -version = "0.38.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a74ee2d7c2581cd139b42447d7d9389b889bdaad3a73f1ebb16f2a3237bb19c" -dependencies = [ - "bitflags 2.4.0", - "errno", - "libc", - "linux-raw-sys 0.4.10", - "windows-sys", -] - -[[package]] -name = "rustls" -version = "0.20.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b80e3dec595989ea8510028f30c408a4630db12c9cbb8de34203b89d6577e99" -dependencies = [ - "log", - "ring 0.16.20", - "sct", - "webpki", -] - -[[package]] -name = "rustls" -version = "0.21.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd8d6c9f025a446bc4d18ad9632e69aec8f287aa84499ee335599fabd20c3fd8" -dependencies = [ - "log", - "ring 0.16.20", - "rustls-webpki", - "sct", -] - -[[package]] -name = "rustls-pemfile" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" -dependencies = [ - "base64 0.21.4", -] - -[[package]] -name = "rustls-webpki" -version = "0.101.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c7d5dece342910d9ba34d259310cae3e0154b873b35408b787b59bce53d34fe" -dependencies = [ - "ring 0.16.20", - "untrusted 0.7.1", -] - -[[package]] -name = "rustversion" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" - -[[package]] -name = "ryu" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" - -[[package]] -name = "schannel" -version = "0.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" -dependencies = [ - "windows-sys", -] - -[[package]] -name = "schemars" -version = "0.8.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f7b0ce13155372a76ee2e1c5ffba1fe61ede73fbea5630d61eee6fac4929c0c" -dependencies = [ - "dyn-clone", - "schemars_derive", - "serde", - "serde_json", -] - -[[package]] -name = "schemars_derive" -version = "0.8.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e85e2a16b12bdb763244c69ab79363d71db2b4b918a2def53f80b02e0574b13c" -dependencies = [ - "proc-macro2", - "quote", - "serde_derive_internals", - "syn 1.0.109", -] - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "scroll" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04c565b551bafbef4157586fa379538366e4385d42082f255bfd96e4fe8519da" -dependencies = [ - "scroll_derive", -] - -[[package]] -name = "scroll_derive" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1db149f81d46d2deba7cd3c50772474707729550221e69588478ebf9ada425ae" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.38", -] - -[[package]] -name = "sct" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" -dependencies = [ - "ring 0.16.20", - "untrusted 0.7.1", -] - -[[package]] -name = "sea-orm" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88694d01b528a94f90ad87f8d2f546d060d070eee180315c67d158cb69476034" -dependencies = [ - "async-stream", - "async-trait", - "chrono", - "futures", - "futures-util", - "log", - "ouroboros", - "rust_decimal", - "sea-orm-macros", - "sea-query 0.27.2", - "sea-query-binder", - "sea-strum", - "serde", - "serde_json", - "sqlx", - "thiserror", - "time", - "tracing", - "url", - "uuid", -] - -[[package]] -name = "sea-orm-cli" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ebe1f820fe8949cf6a57272ba9ebd0be766e47c9b85c04b3cabea40ab9459b3" -dependencies = [ - "chrono", - "clap", - "dotenvy", - "regex", - "sea-schema", - "tracing", - "tracing-subscriber", - "url", -] - -[[package]] -name = "sea-orm-macros" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7216195de9c6b2474fd0efab486173dccd0eff21f28cc54aa4c0205d52fb3af0" -dependencies = [ - "bae", - "heck 0.3.3", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "sea-orm-migration" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ed3cdfa669e4c385922f902b9a58e0c2128782a4d0fe79c6c34f3b927565e5b" -dependencies = [ - "async-trait", - "clap", - "dotenvy", - "sea-orm", - "sea-orm-cli", - "sea-schema", - "tracing", - "tracing-subscriber", -] - -[[package]] -name = "sea-query" -version = "0.27.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4f0fc4d8e44e1d51c739a68d336252a18bc59553778075d5e32649be6ec92ed" -dependencies = [ - "chrono", - "rust_decimal", - "sea-query-derive 0.2.0", - "serde_json", - "time", - "uuid", -] - -[[package]] -name = "sea-query" -version = "0.28.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbab99b8cd878ab7786157b7eb8df96333a6807cc6e45e8888c85b51534b401a" -dependencies = [ - "sea-query-derive 0.3.0", -] - -[[package]] -name = "sea-query-binder" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c2585b89c985cfacfe0ec9fc9e7bb055b776c1a2581c4e3c6185af2b8bf8865" -dependencies = [ - "chrono", - "rust_decimal", - "sea-query 0.27.2", - "serde_json", - "sqlx", - "time", - "uuid", -] - -[[package]] -name = "sea-query-derive" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34cdc022b4f606353fe5dc85b09713a04e433323b70163e81513b141c6ae6eb5" -dependencies = [ - "heck 0.3.3", - "proc-macro2", - "quote", - "syn 1.0.109", - "thiserror", -] - -[[package]] -name = "sea-query-derive" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63f62030c60f3a691f5fe251713b4e220b306e50a71e1d6f9cce1f24bb781978" -dependencies = [ - "heck 0.4.1", - "proc-macro2", - "quote", - "syn 1.0.109", - "thiserror", -] - -[[package]] -name = "sea-schema" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d5fda574d980e9352b6c7abd6fc75697436fe0078cac2b548559b52643ad3b" -dependencies = [ - "futures", - "sea-query 0.27.2", - "sea-schema-derive", -] - -[[package]] -name = "sea-schema-derive" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56821b7076f5096b8f726e2791ad255a99c82498e08ec477a65a96c461ff1927" -dependencies = [ - "heck 0.3.3", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "sea-strum" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "391d06a6007842cfe79ac6f7f53911b76dfd69fc9a6769f1cf6569d12ce20e1b" -dependencies = [ - "sea-strum_macros", -] - -[[package]] -name = "sea-strum_macros" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69b4397b825df6ccf1e98bcdabef3bbcfc47ff5853983467850eeab878384f21" -dependencies = [ - "heck 0.3.3", - "proc-macro2", - "quote", - "rustversion", - "syn 1.0.109", -] - -[[package]] -name = "seahash" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" - -[[package]] -name = "security-framework" -version = "2.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "semver" -version = "1.0.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad977052201c6de01a8ef2aa3378c4bd23217a056337d1d6da40468d267a4fb0" - -[[package]] -name = "serde" -version = "1.0.188" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_bytes" -version = "0.11.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab33ec92f677585af6d88c65593ae2375adde54efdbf16d597f2cbc7a6d368ff" -dependencies = [ - "serde", -] - -[[package]] -name = "serde_derive" -version = "1.0.188" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.38", -] - -[[package]] -name = "serde_derive_internals" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "serde_json" -version = "1.0.107" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" -dependencies = [ - "indexmap 2.0.2", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "serde_with" -version = "1.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678b5a069e50bf00ecd22d0cd8ddf7c236f68581b03db652061ed5eb13a312ff" -dependencies = [ - "serde", - "serde_with_macros 1.5.2", -] - -[[package]] -name = "serde_with" -version = "2.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07ff71d2c147a7b57362cead5e22f772cd52f6ab31cfcd9edcd7f6aeb2a0afbe" -dependencies = [ - "serde", - "serde_with_macros 2.3.3", -] - -[[package]] -name = "serde_with_macros" -version = "1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e182d6ec6f05393cc0e5ed1bf81ad6db3a8feedf8ee515ecdd369809bcce8082" -dependencies = [ - "darling 0.13.4", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "serde_with_macros" -version = "2.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "881b6f881b17d13214e5d494c939ebab463d01264ce1811e9d4ac3a882e7695f" -dependencies = [ - "darling 0.20.3", - "proc-macro2", - "quote", - "syn 2.0.38", -] - -[[package]] -name = "sha1" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.10.7", -] - -[[package]] -name = "sha2" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" -dependencies = [ - "block-buffer 0.9.0", - "cfg-if", - "cpufeatures", - "digest 0.9.0", - "opaque-debug", -] - -[[package]] -name = "sha2" -version = "0.10.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.10.7", -] - -[[package]] -name = "sha3" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809" -dependencies = [ - "block-buffer 0.9.0", - "digest 0.9.0", - "keccak", - "opaque-debug", -] - -[[package]] -name = "sha3" -version = "0.10.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" -dependencies = [ - "digest 0.10.7", - "keccak", -] - -[[package]] -name = "shank" -version = "0.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b63e565b5e95ad88ab38f312e89444c749360641c509ef2de0093b49f55974a5" -dependencies = [ - "shank_macro", -] - -[[package]] -name = "shank_macro" -version = "0.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63927d22a1e8b74bda98cc6e151fcdf178b7abb0dc6c4f81e0bbf5ffe2fc4ec8" -dependencies = [ - "proc-macro2", - "quote", - "shank_macro_impl", - "syn 1.0.109", -] - -[[package]] -name = "shank_macro_impl" -version = "0.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ce03403df682f80f4dc1efafa87a4d0cb89b03726d0565e6364bdca5b9a441" -dependencies = [ - "anyhow", - "proc-macro2", - "quote", - "serde", - "syn 1.0.109", -] - -[[package]] -name = "sharded-slab" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" -dependencies = [ - "lazy_static", -] - -[[package]] -name = "signal-hook-registry" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" -dependencies = [ - "libc", -] - -[[package]] -name = "signature" -version = "1.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" - -[[package]] -name = "simdutf8" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a" - -[[package]] -name = "sized-chunks" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16d69225bde7a69b235da73377861095455d298f2b970996eec25ddbb42b3d1e" -dependencies = [ - "bitmaps", - "typenum", -] - -[[package]] -name = "slab" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] - -[[package]] -name = "smallvec" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" - -[[package]] -name = "socket2" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "socket2" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e" -dependencies = [ - "libc", - "windows-sys", -] - -[[package]] -name = "solana-account-decoder" -version = "1.16.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f52aec62a85932e26d1085864b0f7b99b31934aec8dd132429bfef6d7fb1d3a6" -dependencies = [ - "Inflector", - "base64 0.21.4", - "bincode", - "bs58 0.4.0", - "bv", - "lazy_static", - "serde", - "serde_derive", - "serde_json", - "solana-address-lookup-table-program", - "solana-config-program", - "solana-sdk", - "spl-token 4.0.0", - "spl-token-2022 0.9.0", - "spl-token-metadata-interface", - "thiserror", - "zstd", -] - -[[package]] -name = "solana-address-lookup-table-program" -version = "1.16.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee0bd25f4ba0a15fc16c57b41b1e1b14f5271b83214fda158fdedb58758d394e" -dependencies = [ - "bincode", - "bytemuck", - "log", - "num-derive 0.3.3", - "num-traits", - "rustc_version", - "serde", - "solana-frozen-abi", - "solana-frozen-abi-macro", - "solana-program", - "solana-program-runtime", - "solana-sdk", - "thiserror", -] - -[[package]] -name = "solana-config-program" -version = "1.16.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fd0fc1efb91a1661aeb1ff6a691156c3b1bffdaed0aa096589499dd83f9e50b" -dependencies = [ - "bincode", - "chrono", - "serde", - "serde_derive", - "solana-program-runtime", - "solana-sdk", -] - -[[package]] -name = "solana-frozen-abi" -version = "1.16.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02eb4f0ed3eade20f4abdcc0031167344237cd6e16808bd0f33945f9db7861fe" -dependencies = [ - "ahash 0.8.3", - "blake3", - "block-buffer 0.10.4", - "bs58 0.4.0", - "bv", - "byteorder", - "cc", - "either", - "generic-array", - "getrandom 0.1.16", - "im", - "lazy_static", - "log", - "memmap2", - "once_cell", - "rand_core 0.6.4", - "rustc_version", - "serde", - "serde_bytes", - "serde_derive", - "serde_json", - "sha2 0.10.8", - "solana-frozen-abi-macro", - "subtle", - "thiserror", -] - -[[package]] -name = "solana-frozen-abi-macro" -version = "1.16.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28514761a285944cbad5b3d7930546369b80a713ba37d84bcf6ed2753611765" -dependencies = [ - "proc-macro2", - "quote", - "rustc_version", - "syn 2.0.38", -] - -[[package]] -name = "solana-gateway" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d148eb75d0799f6825dc2a840b85c065e3d6d12212845add3e059163f98770e" -dependencies = [ - "borsh 0.10.3", - "num-derive 0.4.1", - "num-traits", - "solana-program", - "thiserror", -] - -[[package]] -name = "solana-logger" -version = "1.16.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c310c6749435ce1ea25a9ae3edfb2fd2c2aed2aa4d4f7e0487a8077a0b1ee30" -dependencies = [ - "env_logger", - "lazy_static", - "log", -] - -[[package]] -name = "solana-measure" -version = "1.16.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d171357580e62aa4ca19c780e25f4e74de064e2780cb8b9f6b6901d986fcd23" -dependencies = [ - "log", - "solana-sdk", -] - -[[package]] -name = "solana-metrics" -version = "1.16.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "013cbb3c82588278d2be18d3317ece5286cb54a3a06d5d38fc31e2a76a6d5e2d" -dependencies = [ - "crossbeam-channel", - "gethostname", - "lazy_static", - "log", - "reqwest", - "solana-sdk", -] - -[[package]] -name = "solana-program" -version = "1.16.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cff2aa5434a77413e9d43e971ceb47bdb003f2e8bbc0365a25b684aca2605c25" -dependencies = [ - "ark-bn254", - "ark-ec", - "ark-ff", - "ark-serialize", - "array-bytes", - "base64 0.21.4", - "bincode", - "bitflags 1.3.2", - "blake3", - "borsh 0.10.3", - "borsh 0.9.3", - "bs58 0.4.0", - "bv", - "bytemuck", - "cc", - "console_error_panic_hook", - "console_log", - "curve25519-dalek", - "getrandom 0.2.10", - "itertools 0.10.5", - "js-sys", - "lazy_static", - "libc", - "libsecp256k1", - "log", - "memoffset", - "num-bigint 0.4.4", - "num-derive 0.3.3", - "num-traits", - "parking_lot 0.12.1", - "rand 0.7.3", - "rand_chacha 0.2.2", - "rustc_version", - "rustversion", - "serde", - "serde_bytes", - "serde_derive", - "serde_json", - "sha2 0.10.8", - "sha3 0.10.8", - "solana-frozen-abi", - "solana-frozen-abi-macro", - "solana-sdk-macro", - "thiserror", - "tiny-bip39", - "wasm-bindgen", - "zeroize", -] - -[[package]] -name = "solana-program-runtime" -version = "1.16.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d1832fefc2187142dac169812518ec20da68b09abad86e4a78f8ae1787e4f56" -dependencies = [ - "base64 0.21.4", - "bincode", - "eager", - "enum-iterator", - "itertools 0.10.5", - "libc", - "log", - "num-derive 0.3.3", - "num-traits", - "percentage", - "rand 0.7.3", - "rustc_version", - "serde", - "solana-frozen-abi", - "solana-frozen-abi-macro", - "solana-measure", - "solana-metrics", - "solana-sdk", - "solana_rbpf", - "thiserror", -] - -[[package]] -name = "solana-sdk" -version = "1.16.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b1002048941cedbd7dd6a96fdaa3dc5238b998aaa70b81946b1e3ec108cc2be" -dependencies = [ - "assert_matches", - "base64 0.21.4", - "bincode", - "bitflags 1.3.2", - "borsh 0.10.3", - "bs58 0.4.0", - "bytemuck", - "byteorder", - "chrono", - "derivation-path", - "digest 0.10.7", - "ed25519-dalek", - "ed25519-dalek-bip32", - "generic-array", - "hmac 0.12.1", - "itertools 0.10.5", - "js-sys", - "lazy_static", - "libsecp256k1", - "log", - "memmap2", - "num-derive 0.3.3", - "num-traits", - "num_enum 0.6.1", - "pbkdf2 0.11.0", - "qstring", - "rand 0.7.3", - "rand_chacha 0.2.2", - "rustc_version", - "rustversion", - "serde", - "serde_bytes", - "serde_derive", - "serde_json", - "serde_with 2.3.3", - "sha2 0.10.8", - "sha3 0.10.8", - "solana-frozen-abi", - "solana-frozen-abi-macro", - "solana-logger", - "solana-program", - "solana-sdk-macro", - "thiserror", - "uriparse", - "wasm-bindgen", -] - -[[package]] -name = "solana-sdk-macro" -version = "1.16.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b41b63b2da4a37ce323aba108db21f4c7bfa638dd1bf58fdc870f83bdce48ba" -dependencies = [ - "bs58 0.4.0", - "proc-macro2", - "quote", - "rustversion", - "syn 2.0.38", -] - -[[package]] -name = "solana-transaction-status" -version = "1.16.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db0b811793e78a908119cc02edca3ff8b54d5660104ebd06cc0e2e7e2f66900b" -dependencies = [ - "Inflector", - "base64 0.21.4", - "bincode", - "borsh 0.10.3", - "bs58 0.4.0", - "lazy_static", - "log", - "serde", - "serde_derive", - "serde_json", - "solana-account-decoder", - "solana-address-lookup-table-program", - "solana-sdk", - "spl-associated-token-account", - "spl-memo 4.0.0", - "spl-token 4.0.0", - "spl-token-2022 0.9.0", - "thiserror", -] - -[[package]] -name = "solana-zk-token-sdk" -version = "1.16.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d1fe77918563768a65fd5d6cd2fa06cf0aeb11e529a1ef8c230b0fe018600e3" -dependencies = [ - "aes-gcm-siv", - "base64 0.21.4", - "bincode", - "bytemuck", - "byteorder", - "curve25519-dalek", - "getrandom 0.1.16", - "itertools 0.10.5", - "lazy_static", - "merlin", - "num-derive 0.3.3", - "num-traits", - "rand 0.7.3", - "serde", - "serde_json", - "sha3 0.9.1", - "solana-program", - "solana-sdk", - "subtle", - "thiserror", - "zeroize", -] - -[[package]] -name = "solana_rbpf" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17d4ba1e58947346e360fabde0697029d36ba83c42f669199b16a8931313cf29" -dependencies = [ - "byteorder", - "combine", - "goblin", - "hash32", - "libc", - "log", - "rand 0.8.5", - "rustc-demangle", - "scroll", - "thiserror", - "winapi", -] - -[[package]] -name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" - -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" - -[[package]] -name = "spl-account-compression" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df052fd79e45c75c84ef20f5f2dcf037aeed230d0f2400bf68fa388cc0ece240" -dependencies = [ - "anchor-lang", - "bytemuck", - "spl-concurrent-merkle-tree", - "spl-noop", -] - -[[package]] -name = "spl-associated-token-account" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "385e31c29981488f2820b2022d8e731aae3b02e6e18e2fd854e4c9a94dc44fc3" -dependencies = [ - "assert_matches", - "borsh 0.10.3", - "num-derive 0.4.1", - "num-traits", - "solana-program", - "spl-token 4.0.0", - "spl-token-2022 0.9.0", - "thiserror", -] - -[[package]] -name = "spl-concurrent-merkle-tree" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "141eaea58588beae81b71d101373a53f096737739873de42d6b1368bc2b8fc30" -dependencies = [ - "bytemuck", - "solana-program", - "thiserror", -] - -[[package]] -name = "spl-discriminator" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cce5d563b58ef1bb2cdbbfe0dfb9ffdc24903b10ae6a4df2d8f425ece375033f" -dependencies = [ - "bytemuck", - "solana-program", - "spl-discriminator-derive", -] - -[[package]] -name = "spl-discriminator-derive" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fadbefec4f3c678215ca72bd71862697bb06b41fd77c0088902dd3203354387b" -dependencies = [ - "quote", - "spl-discriminator-syn", - "syn 2.0.38", -] - -[[package]] -name = "spl-discriminator-syn" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e5f2044ca42c8938d54d1255ce599c79a1ffd86b677dfab695caa20f9ffc3f2" -dependencies = [ - "proc-macro2", - "quote", - "sha2 0.10.8", - "syn 2.0.38", - "thiserror", -] - -[[package]] -name = "spl-memo" -version = "3.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd0dc6f70db6bacea7ff25870b016a65ba1d1b6013536f08e4fd79a8f9005325" -dependencies = [ - "solana-program", -] - -[[package]] -name = "spl-memo" -version = "4.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f180b03318c3dbab3ef4e1e4d46d5211ae3c780940dd0a28695aba4b59a75a" -dependencies = [ - "solana-program", -] - -[[package]] -name = "spl-noop" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dd67ea3d0070a12ff141f5da46f9695f49384a03bce1203a5608f5739437950" -dependencies = [ - "solana-program", -] - -[[package]] -name = "spl-pod" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2881dddfca792737c0706fa0175345ab282b1b0879c7d877bad129645737c079" -dependencies = [ - "borsh 0.10.3", - "bytemuck", - "solana-program", - "solana-zk-token-sdk", - "spl-program-error", -] - -[[package]] -name = "spl-program-error" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "249e0318493b6bcf27ae9902600566c689b7dfba9f1bdff5893e92253374e78c" -dependencies = [ - "num-derive 0.4.1", - "num-traits", - "solana-program", - "spl-program-error-derive", - "thiserror", -] - -[[package]] -name = "spl-program-error-derive" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5269c8e868da17b6552ef35a51355a017bd8e0eae269c201fef830d35fa52c" -dependencies = [ - "proc-macro2", - "quote", - "sha2 0.10.8", - "syn 2.0.38", -] - -[[package]] -name = "spl-tlv-account-resolution" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "062e148d3eab7b165582757453632ffeef490c02c86a48bfdb4988f63eefb3b9" -dependencies = [ - "bytemuck", - "solana-program", - "spl-discriminator", - "spl-pod", - "spl-program-error", - "spl-type-length-value", -] - -[[package]] -name = "spl-token" -version = "3.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e85e168a785e82564160dcb87b2a8e04cee9bfd1f4d488c729d53d6a4bd300d" -dependencies = [ - "arrayref", - "bytemuck", - "num-derive 0.3.3", - "num-traits", - "num_enum 0.5.11", - "solana-program", - "thiserror", -] - -[[package]] -name = "spl-token" -version = "4.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08459ba1b8f7c1020b4582c4edf0f5c7511a5e099a7a97570c9698d4f2337060" -dependencies = [ - "arrayref", - "bytemuck", - "num-derive 0.3.3", - "num-traits", - "num_enum 0.6.1", - "solana-program", - "thiserror", -] - -[[package]] -name = "spl-token-2022" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0043b590232c400bad5ee9eb983ced003d15163c4c5d56b090ac6d9a57457b47" -dependencies = [ - "arrayref", - "bytemuck", - "num-derive 0.3.3", - "num-traits", - "num_enum 0.5.11", - "solana-program", - "solana-zk-token-sdk", - "spl-memo 3.0.1", - "spl-token 3.5.0", - "thiserror", -] - -[[package]] -name = "spl-token-2022" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4abf34a65ba420584a0c35f3903f8d727d1f13ababbdc3f714c6b065a686e86" -dependencies = [ - "arrayref", - "bytemuck", - "num-derive 0.4.1", - "num-traits", - "num_enum 0.7.0", - "solana-program", - "solana-zk-token-sdk", - "spl-memo 4.0.0", - "spl-pod", - "spl-token 4.0.0", - "spl-token-metadata-interface", - "spl-transfer-hook-interface", - "spl-type-length-value", - "thiserror", -] - -[[package]] -name = "spl-token-metadata-interface" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c16ce3ba6979645fb7627aa1e435576172dd63088dc7848cb09aa331fa1fe4f" -dependencies = [ - "borsh 0.10.3", - "solana-program", - "spl-discriminator", - "spl-pod", - "spl-program-error", - "spl-type-length-value", -] - -[[package]] -name = "spl-transfer-hook-interface" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "051d31803f873cabe71aec3c1b849f35248beae5d19a347d93a5c9cccc5d5a9b" -dependencies = [ - "arrayref", - "bytemuck", - "solana-program", - "spl-discriminator", - "spl-pod", - "spl-program-error", - "spl-tlv-account-resolution", - "spl-type-length-value", -] - -[[package]] -name = "spl-type-length-value" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a468e6f6371f9c69aae760186ea9f1a01c2908351b06a5e0026d21cfc4d7ecac" -dependencies = [ - "bytemuck", - "solana-program", - "spl-discriminator", - "spl-pod", - "spl-program-error", -] - -[[package]] -name = "sqlformat" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b7b278788e7be4d0d29c0f39497a0eef3fba6bbc8e70d8bf7fde46edeaa9e85" -dependencies = [ - "itertools 0.11.0", - "nom", - "unicode_categories", -] - -[[package]] -name = "sqlx" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8de3b03a925878ed54a954f621e64bf55a3c1bd29652d0d1a17830405350188" -dependencies = [ - "sqlx-core", - "sqlx-macros", -] - -[[package]] -name = "sqlx-core" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa8241483a83a3f33aa5fff7e7d9def398ff9990b2752b6c6112b83c6d246029" -dependencies = [ - "ahash 0.7.6", - "atoi", - "base64 0.13.1", - "bitflags 1.3.2", - "byteorder", - "bytes", - "chrono", - "crc", - "crossbeam-queue", - "dirs", - "dotenvy", - "either", - "event-listener", - "futures-channel", - "futures-core", - "futures-intrusive", - "futures-util", - "hashlink", - "hex", - "hkdf", - "hmac 0.12.1", - "indexmap 1.9.3", - "itoa", - "libc", - "log", - "md-5", - "memchr", - "num-bigint 0.4.4", - "once_cell", - "paste", - "percent-encoding", - "rand 0.8.5", - "rust_decimal", - "rustls 0.20.9", - "rustls-pemfile", - "serde", - "serde_json", - "sha1", - "sha2 0.10.8", - "smallvec", - "sqlformat", - "sqlx-rt", - "stringprep", - "thiserror", - "time", - "tokio-stream", - "url", - "uuid", - "webpki-roots 0.22.6", - "whoami", -] - -[[package]] -name = "sqlx-macros" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9966e64ae989e7e575b19d7265cb79d7fc3cbbdf179835cb0d716f294c2049c9" -dependencies = [ - "dotenvy", - "either", - "heck 0.4.1", - "once_cell", - "proc-macro2", - "quote", - "serde_json", - "sha2 0.10.8", - "sqlx-core", - "sqlx-rt", - "syn 1.0.109", - "url", -] - -[[package]] -name = "sqlx-rt" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "804d3f245f894e61b1e6263c84b23ca675d96753b5abfd5cc8597d86806e8024" -dependencies = [ - "once_cell", - "tokio", - "tokio-rustls 0.23.4", -] - -[[package]] -name = "stringprep" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb41d74e231a107a1b4ee36bd1214b11285b77768d2e3824aedafa988fd36ee6" -dependencies = [ - "finl_unicode", - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - -[[package]] -name = "subtle" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" - -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.38" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "system-configuration" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "system-configuration-sys", -] - -[[package]] -name = "system-configuration-sys" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "tap" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" - -[[package]] -name = "tempfile" -version = "3.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" -dependencies = [ - "cfg-if", - "fastrand 2.0.1", - "redox_syscall 0.3.5", - "rustix 0.38.18", - "windows-sys", -] - -[[package]] -name = "termcolor" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "textwrap" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" - -[[package]] -name = "thiserror" -version = "1.0.49" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.49" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.38", -] - -[[package]] -name = "thread_local" -version = "1.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" -dependencies = [ - "cfg-if", - "once_cell", -] - -[[package]] -name = "time" -version = "0.3.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "426f806f4089c493dcac0d24c29c01e2c38baf8e30f1b716ee37e83d200b18fe" -dependencies = [ - "deranged", - "itoa", - "serde", - "time-core", - "time-macros", -] - -[[package]] -name = "time-core" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" - -[[package]] -name = "time-macros" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20" -dependencies = [ - "time-core", -] - -[[package]] -name = "tiny-bip39" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffc59cb9dfc85bb312c3a78fd6aa8a8582e310b0fa885d5bb877f6dcc601839d" -dependencies = [ - "anyhow", - "hmac 0.8.1", - "once_cell", - "pbkdf2 0.4.0", - "rand 0.7.3", - "rustc-hash", - "sha2 0.9.9", - "thiserror", - "unicode-normalization", - "wasm-bindgen", - "zeroize", -] - -[[package]] -name = "tinyvec" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - -[[package]] -name = "tokio" -version = "1.33.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f38200e3ef7995e5ef13baec2f432a6da0aa9ac495b2c0e8f3b7eec2c92d653" -dependencies = [ - "backtrace", - "bytes", - "libc", - "mio", - "num_cpus", - "parking_lot 0.12.1", - "pin-project-lite", - "signal-hook-registry", - "socket2 0.5.4", - "tokio-macros", - "windows-sys", -] - -[[package]] -name = "tokio-macros" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.38", -] - -[[package]] -name = "tokio-native-tls" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" -dependencies = [ - "native-tls", - "tokio", -] - -[[package]] -name = "tokio-rustls" -version = "0.23.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" -dependencies = [ - "rustls 0.20.9", - "tokio", - "webpki", -] - -[[package]] -name = "tokio-rustls" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" -dependencies = [ - "rustls 0.21.7", - "tokio", -] - -[[package]] -name = "tokio-stream" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" -dependencies = [ - "futures-core", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "tokio-util" -version = "0.7.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d68074620f57a0b21594d9735eb2e98ab38b17f80d3fcb189fca266771ca60d" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "pin-project-lite", - "tokio", - "tracing", -] - -[[package]] -name = "toml" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" -dependencies = [ - "serde", -] - -[[package]] -name = "toml_datetime" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" - -[[package]] -name = "toml_edit" -version = "0.19.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" -dependencies = [ - "indexmap 2.0.2", - "toml_datetime", - "winnow", -] - -[[package]] -name = "tower-service" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" - -[[package]] -name = "tracing" -version = "0.1.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" -dependencies = [ - "cfg-if", - "log", - "pin-project-lite", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.38", -] - -[[package]] -name = "tracing-core" -version = "0.1.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" -dependencies = [ - "once_cell", - "valuable", -] - -[[package]] -name = "tracing-log" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" -dependencies = [ - "lazy_static", - "log", - "tracing-core", -] - -[[package]] -name = "tracing-subscriber" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77" -dependencies = [ - "matchers", - "nu-ansi-term", - "once_cell", - "regex", - "sharded-slab", - "smallvec", - "thread_local", - "tracing", - "tracing-core", - "tracing-log", -] - -[[package]] -name = "try-lock" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" - -[[package]] -name = "typenum" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" - -[[package]] -name = "unicase" -version = "2.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" -dependencies = [ - "version_check", -] - -[[package]] -name = "unicode-bidi" -version = "0.3.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" - -[[package]] -name = "unicode-ident" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "unicode-normalization" -version = "0.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" -dependencies = [ - "tinyvec", -] - -[[package]] -name = "unicode-segmentation" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" - -[[package]] -name = "unicode_categories" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" - -[[package]] -name = "universal-hash" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05" -dependencies = [ - "generic-array", - "subtle", -] - -[[package]] -name = "unreachable" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" -dependencies = [ - "void", -] - -[[package]] -name = "untrusted" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" - -[[package]] -name = "untrusted" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" - -[[package]] -name = "uriparse" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0200d0fc04d809396c2ad43f3c95da3582a2556eba8d453c1087f4120ee352ff" -dependencies = [ - "fnv", - "lazy_static", -] - -[[package]] -name = "url" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", -] - -[[package]] -name = "uuid" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d" -dependencies = [ - "getrandom 0.2.10", - "serde", -] - -[[package]] -name = "valuable" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" - -[[package]] -name = "value-bag" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d92ccd67fb88503048c01b59152a04effd0782d035a83a6d256ce6085f08f4a3" - -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "void" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" - -[[package]] -name = "waker-fn" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c4517f54858c779bbcbf228f4fca63d121bf85fbecb2dc578cdf4a39395690" - -[[package]] -name = "want" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" -dependencies = [ - "try-lock", -] - -[[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "wasm-bindgen" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" -dependencies = [ - "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" -dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn 2.0.38", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.38", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" - -[[package]] -name = "web-sys" -version = "0.3.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "webpki" -version = "0.22.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed63aea5ce73d0ff405984102c42de94fc55a6b75765d621c65262469b3c9b53" -dependencies = [ - "ring 0.17.2", - "untrusted 0.9.0", -] - -[[package]] -name = "webpki-roots" -version = "0.22.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87" -dependencies = [ - "webpki", -] - -[[package]] -name = "webpki-roots" -version = "0.25.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14247bb57be4f377dfb94c72830b8ce8fc6beac03cf4bf7b9732eadd414123fc" - -[[package]] -name = "whoami" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22fc3756b8a9133049b26c7f61ab35416c130e8c09b660f5b3958b446f52cc50" -dependencies = [ - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-util" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" -dependencies = [ - "winapi", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - -[[package]] -name = "winnow" -version = "0.5.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "037711d82167854aff2018dfd193aa0fef5370f456732f0d5a0c59b0f1b4b907" -dependencies = [ - "memchr", -] - -[[package]] -name = "winreg" -version = "0.50.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" -dependencies = [ - "cfg-if", - "windows-sys", -] - -[[package]] -name = "wyz" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" -dependencies = [ - "tap", -] - -[[package]] -name = "zeroize" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd" -dependencies = [ - "zeroize_derive", -] - -[[package]] -name = "zeroize_derive" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.38", -] - -[[package]] -name = "zstd" -version = "0.11.2+zstd.1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" -dependencies = [ - "zstd-safe", -] - -[[package]] -name = "zstd-safe" -version = "5.0.2+zstd.1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" -dependencies = [ - "libc", - "zstd-sys", -] - -[[package]] -name = "zstd-sys" -version = "2.0.8+zstd.1.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5556e6ee25d32df2586c098bbfa278803692a20d0ab9565e049480d52707ec8c" -dependencies = [ - "cc", - "libc", - "pkg-config", -] diff --git a/migration/src/m20221026_155220_add_bg_tasks.rs b/migration/src/m20221026_155220_add_bg_tasks.rs index 3debeaf9b..8586a6013 100644 --- a/migration/src/m20221026_155220_add_bg_tasks.rs +++ b/migration/src/m20221026_155220_add_bg_tasks.rs @@ -1,4 +1,3 @@ - use enum_iterator::{all, Sequence}; use sea_orm_migration::prelude::extension::postgres::Type; use sea_orm_migration::prelude::*; @@ -32,12 +31,7 @@ impl MigrationTrait for Migration { .col(ColumnDef::new(Tasks::Data).json_binary().not_null()) .col( ColumnDef::new(Tasks::Status) - .enumeration( - Tasks::TaskStatus, - all::() - .map(|e| e) - .collect::>(), - ) + .enumeration(Tasks::TaskStatus, all::().collect::>()) .not_null(), ) .col(ColumnDef::new(Tasks::CreatedAt).date_time().not_null()) diff --git a/migration/src/m20230106_051135_unique_groupings.rs b/migration/src/m20230106_051135_unique_groupings.rs index 5caa14c5c..2dc0d4663 100644 --- a/migration/src/m20230106_051135_unique_groupings.rs +++ b/migration/src/m20230106_051135_unique_groupings.rs @@ -38,7 +38,7 @@ impl MigrationTrait for Migration { .to_owned(), ) .await?; - + manager .create_index( sea_query::Index::create() diff --git a/migration/src/m20230131_140613_change_token_account_indexes.rs b/migration/src/m20230131_140613_change_token_account_indexes.rs index 81a6925af..2ee601c62 100644 --- a/migration/src/m20230131_140613_change_token_account_indexes.rs +++ b/migration/src/m20230131_140613_change_token_account_indexes.rs @@ -90,6 +90,8 @@ impl MigrationTrait for Migration { } /// Learn more at https://docs.rs/sea-query#iden +#[allow(dead_code)] +#[allow(clippy::upper_case_acronyms)] #[derive(Iden)] enum Index { BRIN, diff --git a/migration/src/m20230203_205959_improve_upsert_perf.rs b/migration/src/m20230203_205959_improve_upsert_perf.rs index 1e3272689..02ae33dd0 100644 --- a/migration/src/m20230203_205959_improve_upsert_perf.rs +++ b/migration/src/m20230203_205959_improve_upsert_perf.rs @@ -52,13 +52,13 @@ impl MigrationTrait for Migration { )) .await?; - manager + manager .get_connection() .execute(Statement::from_string( DatabaseBackend::Postgres, "ALTER TABLE asset SET (fillfactor = 85);".to_string(), )) - .await?; + .await?; manager .drop_index( diff --git a/migration/src/m20230224_093722_performance_improvements.rs b/migration/src/m20230224_093722_performance_improvements.rs index a577d9223..18320dfdc 100644 --- a/migration/src/m20230224_093722_performance_improvements.rs +++ b/migration/src/m20230224_093722_performance_improvements.rs @@ -1,4 +1,3 @@ - use sea_orm_migration::{ prelude::*, sea_orm::{ConnectionTrait, DatabaseBackend, Statement}, diff --git a/migration/src/m20230310_162227_add_indexes_to_bg.rs b/migration/src/m20230310_162227_add_indexes_to_bg.rs index b8f9a501f..5dcdc9bfd 100644 --- a/migration/src/m20230310_162227_add_indexes_to_bg.rs +++ b/migration/src/m20230310_162227_add_indexes_to_bg.rs @@ -15,7 +15,7 @@ impl MigrationTrait for Migration { .execute(Statement::from_string( DatabaseBackend::Postgres, "CREATE INDEX IF NOT EXISTS tasks_created_at ON tasks USING BRIN(created_at);" - .to_string(), + .to_string(), )) .await?; manager @@ -23,7 +23,7 @@ impl MigrationTrait for Migration { .execute(Statement::from_string( DatabaseBackend::Postgres, "CREATE INDEX IF NOT EXISTS tasks_locked_until ON tasks USING BRIN(locked_until);" - .to_string(), + .to_string(), )) .await?; manager @@ -31,15 +31,14 @@ impl MigrationTrait for Migration { .execute(Statement::from_string( DatabaseBackend::Postgres, "CREATE INDEX IF NOT EXISTS task_attempts ON tasks USING BRIN(attempts);" - .to_string(), + .to_string(), )) .await?; manager .get_connection() .execute(Statement::from_string( DatabaseBackend::Postgres, - "CREATE INDEX IF NOT EXISTS task_status ON tasks (status);" - .to_string(), + "CREATE INDEX IF NOT EXISTS task_status ON tasks (status);".to_string(), )) .await?; Ok(()) @@ -81,4 +80,4 @@ impl MigrationTrait for Migration { .await?; Ok(()) } -} \ No newline at end of file +} diff --git a/migration/src/m20230317_121944_remove_indexes_for_perf.rs b/migration/src/m20230317_121944_remove_indexes_for_perf.rs index 1643b8cea..bda6d757f 100644 --- a/migration/src/m20230317_121944_remove_indexes_for_perf.rs +++ b/migration/src/m20230317_121944_remove_indexes_for_perf.rs @@ -1,7 +1,5 @@ use sea_orm_migration::prelude::*; -use sea_orm_migration::{ - sea_orm::{ConnectionTrait, DatabaseBackend, Statement}, -}; +use sea_orm_migration::sea_orm::{ConnectionTrait, DatabaseBackend, Statement}; #[derive(DeriveMigrationName)] pub struct Migration; diff --git a/migration/src/m20230918_182123_add_raw_name_symbol.rs b/migration/src/m20230918_182123_add_raw_name_symbol.rs index 6851e871e..86f019543 100644 --- a/migration/src/m20230918_182123_add_raw_name_symbol.rs +++ b/migration/src/m20230918_182123_add_raw_name_symbol.rs @@ -49,6 +49,7 @@ impl MigrationTrait for Migration { } /// Learn more at https://docs.rs/sea-query#iden +#[allow(dead_code)] #[derive(Iden)] enum Post { Table, diff --git a/migration/src/m20230919_072154_cl_audits.rs b/migration/src/m20230919_072154_cl_audits.rs index b9fd6e214..a2a75e338 100644 --- a/migration/src/m20230919_072154_cl_audits.rs +++ b/migration/src/m20230919_072154_cl_audits.rs @@ -11,14 +11,25 @@ impl MigrationTrait for Migration { Table::create() .table(ClAudits::Table) .if_not_exists() - .col(ColumnDef::new(ClAudits::Id).big_integer().not_null().primary_key().auto_increment()) + .col( + ColumnDef::new(ClAudits::Id) + .big_integer() + .not_null() + .primary_key() + .auto_increment(), + ) .col(ColumnDef::new(ClAudits::Tree).binary().not_null()) .col(ColumnDef::new(ClAudits::NodeIdx).big_integer().not_null()) .col(ColumnDef::new(ClAudits::LeafIdx).big_integer()) .col(ColumnDef::new(ClAudits::Seq).big_integer().not_null()) .col(ColumnDef::new(ClAudits::Level).big_integer().not_null()) .col(ColumnDef::new(ClAudits::Hash).binary().not_null()) - .col(ColumnDef::new(ClAudits::CreatedAt).date_time().default(SimpleExpr::Keyword(Keyword::CurrentTimestamp)).not_null()) + .col( + ColumnDef::new(ClAudits::CreatedAt) + .date_time() + .default(SimpleExpr::Keyword(Keyword::CurrentTimestamp)) + .not_null(), + ) .col(ColumnDef::new(ClAudits::Tx).string().not_null()) .to_owned(), ) From 6173f2bb227f7632f12a744364982430b36e5671 Mon Sep 17 00:00:00 2001 From: Kirill Fomichev Date: Mon, 20 Nov 2023 13:16:22 -0500 Subject: [PATCH 05/23] include das_api to workspace --- .github/workflows/build-api.yml | 10 +- .github/workflows/test.yml | 15 - .gitignore | 4 - Cargo.lock | 366 +- Cargo.toml | 4 +- das_api/Cargo.lock | 5864 ------------------------------- das_api/src/error.rs | 15 +- 7 files changed, 375 insertions(+), 5903 deletions(-) delete mode 100644 das_api/Cargo.lock diff --git a/.github/workflows/build-api.yml b/.github/workflows/build-api.yml index 3c2e972a1..802e82e4d 100644 --- a/.github/workflows/build-api.yml +++ b/.github/workflows/build-api.yml @@ -46,17 +46,13 @@ jobs: - name: build digital asset rpc infra run: cargo build --verbose --release - - name: build das_api - working-directory: das_api - run: cargo build --verbose --release - - name: rename binaries for ubuntu22 release if: matrix.os == 'ubuntu-22.04' run: | mv target/release/nft_ingester target/release/nft_ingester22 mv target/release/fetch_trees target/release/fetch_trees22 mv target/release/migration target/target/release/migration22 - mv das_api/target/release/das_api das_api/target/release/das_api22 + mv target/release/das_api target/release/das_api22 # This steps can be omited to save space, are mostly in place to validate binaries (manually) and path to them # Omiting this will save on storage consumption on the account @@ -72,7 +68,7 @@ jobs: uses: actions/upload-artifact@v3.1.1 with: name: das_api22 - path: das_api/target/release/das_api22 + path: target/release/das_api22 - name: Publish artifact if: matrix.os == 'ubuntu-22.04' @@ -100,7 +96,7 @@ jobs: uses: actions/upload-artifact@v3.1.1 with: name: das_api - path: das_api/target/release/das_api + path: target/release/das_api - name: Publish artifact if: matrix.os == 'ubuntu-20.04' diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 65d5164ae..1fb299094 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -40,25 +40,10 @@ jobs: git checkout Cargo.lock cargo tree --frozen - - name: Check lock file for `das_api` - working-directory: das_api - run: | - cargo tree - git checkout Cargo.lock - cargo tree --frozen - # fmt - name: Check fmt run: cargo fmt --all -- --check - - name: Check fmt `das_api` - working-directory: das_api - run: cargo fmt --all -- --check - # clippy - name: Check clippy run: cargo clippy --all-targets --tests - - - name: Check clippy `das_api` - working-directory: das_api - run: cargo clippy --all-targets --tests diff --git a/.gitignore b/.gitignore index c5f666e71..c396adfb8 100644 --- a/.gitignore +++ b/.gitignore @@ -23,7 +23,3 @@ programs *.iml skaffold-state.json test-programs - -# Rust build dirs -/das_api/target -/target diff --git a/Cargo.lock b/Cargo.lock index 3e575c039..2f025fb6e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -604,6 +604,20 @@ dependencies = [ "futures-core", ] +[[package]] +name = "async-compression" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "942c7cd7ae39e91bde4820d74132e9862e62c2f386c3aa90ccf55949f5bad63a" +dependencies = [ + "brotli", + "flate2", + "futures-core", + "memchr", + "pin-project-lite", + "tokio", +] + [[package]] name = "async-compression" version = "0.4.3" @@ -851,6 +865,15 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +[[package]] +name = "beef" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" +dependencies = [ + "serde", +] + [[package]] name = "bgtask_creator" version = "0.7.12" @@ -1119,6 +1142,16 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "bstr" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "542f33a8835a0884b006a0c3df3dadd99c0c3f296ed26c2fdc8028e01ad6230c" +dependencies = [ + "memchr", + "serde", +] + [[package]] name = "bumpalo" version = "3.14.0" @@ -1659,6 +1692,45 @@ dependencies = [ "syn 2.0.38", ] +[[package]] +name = "das_api" +version = "0.7.2" +dependencies = [ + "anchor-lang", + "async-trait", + "blockbuster", + "bs58 0.4.0", + "cadence", + "cadence-macros", + "digital_asset_types", + "env_logger 0.10.0", + "figment", + "hyper", + "jsonrpsee", + "jsonrpsee-core", + "log", + "metrics", + "mpl-bubblegum", + "mpl-candy-guard", + "mpl-candy-machine-core", + "mpl-token-metadata", + "open-rpc-derive", + "open-rpc-schema", + "schemars", + "schemars_derive", + "sea-orm", + "serde", + "serde_json", + "solana-sdk", + "sqlx", + "thiserror", + "tokio", + "tokio-postgres", + "tower", + "tower-http", + "tracing", +] + [[package]] name = "data-encoding" version = "2.4.0" @@ -2285,6 +2357,19 @@ version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" +[[package]] +name = "globset" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "759c97c1e17c55525b57192c06a267cda0ac5210b222d6b82189a2338fa1c13d" +dependencies = [ + "aho-corasick", + "bstr", + "fnv", + "log", + "regex", +] + [[package]] name = "gloo-timers" version = "0.2.6" @@ -2382,6 +2467,16 @@ dependencies = [ "hashbrown 0.14.1", ] +[[package]] +name = "hdrhistogram" +version = "7.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "765c9198f173dd59ce26ff9f95ef0aafd0a0fe01fb9d72841bc5066a4c06511d" +dependencies = [ + "byteorder", + "num-traits", +] + [[package]] name = "heck" version = "0.3.3" @@ -2488,6 +2583,12 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "http-range-header" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "add0ab9360ddbd88cfeb3bd9574a1d85cfdfa14db10b3e21d3700dbc4328758f" + [[package]] name = "httparse" version = "1.8.0" @@ -2641,7 +2742,7 @@ dependencies = [ "console", "instant", "number_prefix", - "portable-atomic", + "portable-atomic 1.4.3", "unicode-width", ] @@ -2677,6 +2778,15 @@ version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" +[[package]] +name = "iri-string" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f0f7638c1e223529f1bfdc48c8b133b9e0b434094d1d28473161ee48b235f78" +dependencies = [ + "nom", +] + [[package]] name = "is-terminal" version = "0.4.9" @@ -2756,6 +2866,94 @@ dependencies = [ "serde_json", ] +[[package]] +name = "jsonrpsee" +version = "0.16.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "367a292944c07385839818bb71c8d76611138e2dedb0677d035b8da21d29c78b" +dependencies = [ + "jsonrpsee-core", + "jsonrpsee-proc-macros", + "jsonrpsee-server", + "jsonrpsee-types", + "tracing", +] + +[[package]] +name = "jsonrpsee-core" +version = "0.16.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b5dde66c53d6dcdc8caea1874a45632ec0fcf5b437789f1e45766a1512ce803" +dependencies = [ + "anyhow", + "arrayvec", + "async-trait", + "beef", + "futures-channel", + "futures-util", + "globset", + "hyper", + "jsonrpsee-types", + "parking_lot 0.12.1", + "rand 0.8.5", + "rustc-hash", + "serde", + "serde_json", + "soketto", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "jsonrpsee-proc-macros" +version = "0.16.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44e8ab85614a08792b9bff6c8feee23be78c98d0182d4c622c05256ab553892a" +dependencies = [ + "heck 0.4.1", + "proc-macro-crate 1.3.1", + "proc-macro2 1.0.69", + "quote 1.0.33", + "syn 1.0.109", +] + +[[package]] +name = "jsonrpsee-server" +version = "0.16.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4d945a6008c9b03db3354fb3c83ee02d2faa9f2e755ec1dfb69c3551b8f4ba" +dependencies = [ + "futures-channel", + "futures-util", + "http", + "hyper", + "jsonrpsee-core", + "jsonrpsee-types", + "serde", + "serde_json", + "soketto", + "tokio", + "tokio-stream", + "tokio-util", + "tower", + "tracing", +] + +[[package]] +name = "jsonrpsee-types" +version = "0.16.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "245ba8e5aa633dd1c1e4fae72bce06e71f42d34c14a2767c6b4d173b57bee5e5" +dependencies = [ + "anyhow", + "beef", + "serde", + "serde_json", + "thiserror", + "tracing", +] + [[package]] name = "kaigan" version = "0.2.2" @@ -2965,6 +3163,28 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "metrics" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b9b8653cec6897f73b519a43fba5ee3d50f62fe9af80b428accdcc093b4a849" +dependencies = [ + "ahash 0.7.6", + "metrics-macros", + "portable-atomic 0.3.20", +] + +[[package]] +name = "metrics-macros" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "731f8ecebd9f3a4aa847dfe75455e4757a45da40a7793d2f0b1f9b6ed18b23f3" +dependencies = [ + "proc-macro2 1.0.69", + "quote 1.0.33", + "syn 1.0.109", +] + [[package]] name = "migration" version = "0.7.2" @@ -3475,6 +3695,30 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +[[package]] +name = "open-rpc-derive" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae3de03a56750973a83c76a40fb4b81969d42fad152cd0e787e25c79dcf54e3f" +dependencies = [ + "open-rpc-schema", + "proc-macro2 1.0.69", + "quote 1.0.33", + "syn 1.0.109", +] + +[[package]] +name = "open-rpc-schema" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6919654a78166b8d8f266f702ce763c0880c11a2e75e1de9cc3e51704abf620" +dependencies = [ + "schemars", + "schemars_derive", + "serde", + "serde_json", +] + [[package]] name = "openssl" version = "0.10.57" @@ -3697,6 +3941,26 @@ dependencies = [ "siphasher", ] +[[package]] +name = "pin-project" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" +dependencies = [ + "proc-macro2 1.0.69", + "quote 1.0.33", + "syn 2.0.38", +] + [[package]] name = "pin-project-lite" version = "0.2.13" @@ -3805,6 +4069,15 @@ dependencies = [ "universal-hash", ] +[[package]] +name = "portable-atomic" +version = "0.3.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e30165d31df606f5726b090ec7592c308a0eaf61721ff64c9a3018e344a8753e" +dependencies = [ + "portable-atomic 1.4.3", +] + [[package]] name = "portable-atomic" version = "1.4.3" @@ -4325,7 +4598,7 @@ version = "0.11.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" dependencies = [ - "async-compression", + "async-compression 0.4.3", "base64 0.21.4", "bytes", "encoding_rs", @@ -5039,6 +5312,19 @@ dependencies = [ "unsafe-libyaml", ] +[[package]] +name = "sha-1" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", +] + [[package]] name = "sha-1" version = "0.10.1" @@ -5234,6 +5520,22 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "soketto" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d1c5305e39e09653383c2c7244f2f78b3bcae37cf50c64cb4789c9f5096ec2" +dependencies = [ + "base64 0.13.1", + "bytes", + "futures", + "http", + "httparse", + "log", + "rand 0.8.5", + "sha-1 0.9.8", +] + [[package]] name = "solana-account-decoder" version = "1.16.16" @@ -6801,6 +7103,7 @@ checksum = "1d68074620f57a0b21594d9735eb2e98ab38b17f80d3fcb189fca266771ca60d" dependencies = [ "bytes", "futures-core", + "futures-io", "futures-sink", "pin-project-lite", "tokio", @@ -6861,6 +7164,63 @@ dependencies = [ "winnow", ] +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "hdrhistogram", + "indexmap 1.9.3", + "pin-project", + "pin-project-lite", + "rand 0.8.5", + "slab", + "tokio", + "tokio-util", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-http" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f873044bf02dd1e8239e9c1293ea39dad76dc594ec16185d0a1bf31d8dc8d858" +dependencies = [ + "async-compression 0.3.15", + "base64 0.13.1", + "bitflags 1.3.2", + "bytes", + "futures-core", + "futures-util", + "http", + "http-body", + "http-range-header", + "httpdate", + "iri-string", + "mime", + "mime_guess", + "percent-encoding", + "pin-project-lite", + "tokio", + "tokio-util", + "tower", + "tower-layer", + "tower-service", + "tracing", + "uuid", +] + +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + [[package]] name = "tower-service" version = "0.3.2" @@ -7002,7 +7362,7 @@ dependencies = [ "log", "rand 0.8.5", "rustls 0.20.9", - "sha-1", + "sha-1 0.10.1", "thiserror", "url", "utf-8", diff --git a/Cargo.toml b/Cargo.toml index 1bef11472..6a94be4ef 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,6 @@ [workspace] members = [ + "das_api", "digital_asset_types", "metaplex-rpc-proxy", "migration", @@ -11,9 +12,6 @@ members = [ "tools/tree-status", "tools/txn_forwarder", ] -exclude = [ - "das_api", -] [profile.release] lto = true diff --git a/das_api/Cargo.lock b/das_api/Cargo.lock deleted file mode 100644 index 3b4aea3fe..000000000 --- a/das_api/Cargo.lock +++ /dev/null @@ -1,5864 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "Inflector" -version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" -dependencies = [ - "lazy_static", - "regex", -] - -[[package]] -name = "addr2line" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "aead" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877" -dependencies = [ - "generic-array", -] - -[[package]] -name = "aes" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" -dependencies = [ - "cfg-if", - "cipher", - "cpufeatures", - "opaque-debug", -] - -[[package]] -name = "aes-gcm-siv" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589c637f0e68c877bbd59a4599bbe849cac8e5f3e4b5a3ebae8f528cd218dcdc" -dependencies = [ - "aead", - "aes", - "cipher", - "ctr", - "polyval", - "subtle", - "zeroize", -] - -[[package]] -name = "ahash" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" -dependencies = [ - "getrandom 0.2.10", - "once_cell", - "version_check", -] - -[[package]] -name = "ahash" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" -dependencies = [ - "cfg-if", - "getrandom 0.2.10", - "once_cell", - "version_check", -] - -[[package]] -name = "aho-corasick" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" -dependencies = [ - "memchr", -] - -[[package]] -name = "aliasable" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fd" - -[[package]] -name = "alloc-no-stdlib" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" - -[[package]] -name = "alloc-stdlib" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" -dependencies = [ - "alloc-no-stdlib", -] - -[[package]] -name = "allocator-api2" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" - -[[package]] -name = "anchor-attribute-access-control" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "faa5be5b72abea167f87c868379ba3c2be356bfca9e6f474fd055fa0f7eeb4f2" -dependencies = [ - "anchor-syn", - "anyhow", - "proc-macro2", - "quote", - "regex", - "syn 1.0.109", -] - -[[package]] -name = "anchor-attribute-account" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f468970344c7c9f9d03b4da854fd7c54f21305059f53789d0045c1dd803f0018" -dependencies = [ - "anchor-syn", - "anyhow", - "bs58 0.5.0", - "proc-macro2", - "quote", - "rustversion", - "syn 1.0.109", -] - -[[package]] -name = "anchor-attribute-constant" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59948e7f9ef8144c2aefb3f32a40c5fce2798baeec765ba038389e82301017ef" -dependencies = [ - "anchor-syn", - "proc-macro2", - "syn 1.0.109", -] - -[[package]] -name = "anchor-attribute-error" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc753c9d1c7981cb8948cf7e162fb0f64558999c0413058e2d43df1df5448086" -dependencies = [ - "anchor-syn", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "anchor-attribute-event" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f38b4e172ba1b52078f53fdc9f11e3dc0668ad27997838a0aad2d148afac8c97" -dependencies = [ - "anchor-syn", - "anyhow", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "anchor-attribute-program" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eebd21543606ab61e2d83d9da37d24d3886a49f390f9c43a1964735e8c0f0d5" -dependencies = [ - "anchor-syn", - "anyhow", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "anchor-derive-accounts" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec4720d899b3686396cced9508f23dab420f1308344456ec78ef76f98fda42af" -dependencies = [ - "anchor-syn", - "anyhow", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "anchor-derive-space" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f495e85480bd96ddeb77b71d499247c7d4e8b501e75ecb234e9ef7ae7bd6552a" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "anchor-lang" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d2d4b20100f1310a774aba3471ef268e5c4ba4d5c28c0bbe663c2658acbc414" -dependencies = [ - "anchor-attribute-access-control", - "anchor-attribute-account", - "anchor-attribute-constant", - "anchor-attribute-error", - "anchor-attribute-event", - "anchor-attribute-program", - "anchor-derive-accounts", - "anchor-derive-space", - "arrayref", - "base64 0.13.1", - "bincode", - "borsh 0.10.3", - "bytemuck", - "getrandom 0.2.10", - "solana-program", - "thiserror", -] - -[[package]] -name = "anchor-syn" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a125e4b0cc046cfec58f5aa25038e34cf440151d58f0db3afc55308251fe936d" -dependencies = [ - "anyhow", - "bs58 0.5.0", - "heck 0.3.3", - "proc-macro2", - "quote", - "serde", - "serde_json", - "sha2 0.10.8", - "syn 1.0.109", - "thiserror", -] - -[[package]] -name = "android-tzdata" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" - -[[package]] -name = "android_system_properties" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" -dependencies = [ - "libc", -] - -[[package]] -name = "anyhow" -version = "1.0.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" - -[[package]] -name = "ark-bn254" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a22f4561524cd949590d78d7d4c5df8f592430d221f7f3c9497bbafd8972120f" -dependencies = [ - "ark-ec", - "ark-ff", - "ark-std", -] - -[[package]] -name = "ark-ec" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "defd9a439d56ac24968cca0571f598a61bc8c55f71d50a89cda591cb750670ba" -dependencies = [ - "ark-ff", - "ark-poly", - "ark-serialize", - "ark-std", - "derivative", - "hashbrown 0.13.2", - "itertools 0.10.5", - "num-traits", - "zeroize", -] - -[[package]] -name = "ark-ff" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" -dependencies = [ - "ark-ff-asm", - "ark-ff-macros", - "ark-serialize", - "ark-std", - "derivative", - "digest 0.10.7", - "itertools 0.10.5", - "num-bigint 0.4.4", - "num-traits", - "paste", - "rustc_version", - "zeroize", -] - -[[package]] -name = "ark-ff-asm" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" -dependencies = [ - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ark-ff-macros" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" -dependencies = [ - "num-bigint 0.4.4", - "num-traits", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ark-poly" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d320bfc44ee185d899ccbadfa8bc31aab923ce1558716e1997a1e74057fe86bf" -dependencies = [ - "ark-ff", - "ark-serialize", - "ark-std", - "derivative", - "hashbrown 0.13.2", -] - -[[package]] -name = "ark-serialize" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" -dependencies = [ - "ark-serialize-derive", - "ark-std", - "digest 0.10.7", - "num-bigint 0.4.4", -] - -[[package]] -name = "ark-serialize-derive" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae3281bc6d0fd7e549af32b52511e1302185bd688fd3359fa36423346ff682ea" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ark-std" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" -dependencies = [ - "num-traits", - "rand 0.8.5", -] - -[[package]] -name = "array-bytes" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ad284aeb45c13f2fb4f084de4a420ebf447423bdf9386c0540ce33cb3ef4b8c" - -[[package]] -name = "arrayref" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" - -[[package]] -name = "arrayvec" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" - -[[package]] -name = "ascii" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eab1c04a571841102f5345a8fc0f6bb3d31c315dec879b5c6e42e40ce7ffa34e" - -[[package]] -name = "assert_matches" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" - -[[package]] -name = "async-compression" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "942c7cd7ae39e91bde4820d74132e9862e62c2f386c3aa90ccf55949f5bad63a" -dependencies = [ - "brotli", - "flate2", - "futures-core", - "memchr", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "async-compression" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb42b2197bf15ccb092b62c74515dbd8b86d0effd934795f6687c93b6e679a2c" -dependencies = [ - "brotli", - "flate2", - "futures-core", - "memchr", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "async-stream" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" -dependencies = [ - "async-stream-impl", - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "async-stream-impl" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.38", -] - -[[package]] -name = "async-trait" -version = "0.1.73" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.38", -] - -[[package]] -name = "atoi" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7c57d12312ff59c811c0643f4d80830505833c9ffaebd193d819392b265be8e" -dependencies = [ - "num-traits", -] - -[[package]] -name = "atomic" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d818003e740b63afc82337e3160717f4f63078720a810b7b903e70a5d1d2994" -dependencies = [ - "bytemuck", -] - -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi 0.1.19", - "libc", - "winapi", -] - -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - -[[package]] -name = "backtrace" -version = "0.3.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - -[[package]] -name = "bae" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33b8de67cc41132507eeece2584804efcb15f85ba516e34c944b7667f480397a" -dependencies = [ - "heck 0.3.3", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "base64" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" - -[[package]] -name = "base64" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" - -[[package]] -name = "base64" -version = "0.21.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2" - -[[package]] -name = "beef" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" -dependencies = [ - "serde", -] - -[[package]] -name = "bincode" -version = "1.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" -dependencies = [ - "serde", -] - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" - -[[package]] -name = "bitmaps" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2" -dependencies = [ - "typenum", -] - -[[package]] -name = "bitvec" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" -dependencies = [ - "funty", - "radium", - "tap", - "wyz", -] - -[[package]] -name = "blake3" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0231f06152bf547e9c2b5194f247cd97aacf6dcd8b15d8e5ec0663f64580da87" -dependencies = [ - "arrayref", - "arrayvec", - "cc", - "cfg-if", - "constant_time_eq", - "digest 0.10.7", -] - -[[package]] -name = "block-buffer" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" -dependencies = [ - "block-padding", - "generic-array", -] - -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - -[[package]] -name = "block-padding" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" - -[[package]] -name = "blockbuster" -version = "0.9.0-beta.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e0240c1218958c0d51284d783fa055f551d769bb8b7a4abf635b17fa9620dc" -dependencies = [ - "anchor-lang", - "async-trait", - "borsh 0.10.3", - "bs58 0.4.0", - "flatbuffers", - "lazy_static", - "log", - "mpl-bubblegum", - "mpl-candy-guard", - "mpl-candy-machine-core", - "mpl-token-metadata", - "plerkle_serialization", - "solana-sdk", - "spl-account-compression", - "spl-noop", - "spl-token 4.0.0", - "thiserror", -] - -[[package]] -name = "borsh" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15bf3650200d8bffa99015595e10f1fbd17de07abbc25bb067da79e769939bfa" -dependencies = [ - "borsh-derive 0.9.3", - "hashbrown 0.11.2", -] - -[[package]] -name = "borsh" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4114279215a005bc675e386011e594e1d9b800918cea18fcadadcce864a2046b" -dependencies = [ - "borsh-derive 0.10.3", - "hashbrown 0.13.2", -] - -[[package]] -name = "borsh-derive" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6441c552f230375d18e3cc377677914d2ca2b0d36e52129fe15450a2dce46775" -dependencies = [ - "borsh-derive-internal 0.9.3", - "borsh-schema-derive-internal 0.9.3", - "proc-macro-crate 0.1.5", - "proc-macro2", - "syn 1.0.109", -] - -[[package]] -name = "borsh-derive" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0754613691538d51f329cce9af41d7b7ca150bc973056f1156611489475f54f7" -dependencies = [ - "borsh-derive-internal 0.10.3", - "borsh-schema-derive-internal 0.10.3", - "proc-macro-crate 0.1.5", - "proc-macro2", - "syn 1.0.109", -] - -[[package]] -name = "borsh-derive-internal" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5449c28a7b352f2d1e592a8a28bf139bc71afb0764a14f3c02500935d8c44065" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "borsh-derive-internal" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afb438156919598d2c7bad7e1c0adf3d26ed3840dbc010db1a882a65583ca2fb" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "borsh-schema-derive-internal" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdbd5696d8bfa21d53d9fe39a714a18538bad11492a42d066dbbc395fb1951c0" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "borsh-schema-derive-internal" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634205cc43f74a1b9046ef87c4540ebda95696ec0f315024860cad7c5b0f5ccd" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "brotli" -version = "3.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "516074a47ef4bce09577a3b379392300159ce5b1ba2e501ff1c819950066100f" -dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", - "brotli-decompressor", -] - -[[package]] -name = "brotli-decompressor" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da74e2b81409b1b743f8f0c62cc6254afefb8b8e50bbfe3735550f7aeefa3448" -dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", -] - -[[package]] -name = "bs58" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" - -[[package]] -name = "bs58" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5353f36341f7451062466f0b755b96ac3a9547e4d7f6b70d603fc721a7d7896" -dependencies = [ - "tinyvec", -] - -[[package]] -name = "bstr" -version = "1.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c2f7349907b712260e64b0afe2f84692af14a454be26187d9df565c7f69266a" -dependencies = [ - "memchr", - "serde", -] - -[[package]] -name = "bumpalo" -version = "3.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" - -[[package]] -name = "bv" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8834bb1d8ee5dc048ee3124f2c7c1afcc6bc9aed03f11e9dfd8c69470a5db340" -dependencies = [ - "feature-probe", - "serde", -] - -[[package]] -name = "bytecheck" -version = "0.6.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6372023ac861f6e6dc89c8344a8f398fb42aaba2b5dbc649ca0c0e9dbcb627" -dependencies = [ - "bytecheck_derive", - "ptr_meta", - "simdutf8", -] - -[[package]] -name = "bytecheck_derive" -version = "0.6.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7ec4c6f261935ad534c0c22dbef2201b45918860eb1c574b972bd213a76af61" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "bytemuck" -version = "1.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" -dependencies = [ - "bytemuck_derive", -] - -[[package]] -name = "bytemuck_derive" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "965ab7eb5f8f97d2a083c799f3a1b994fc397b2fe2da5d1da1626ce15a39f2b1" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.38", -] - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - -[[package]] -name = "bytes" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" - -[[package]] -name = "cadence" -version = "0.29.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f39286bc075b023101dccdb79456a1334221c768b8faede0c2aff7ed29a9482d" -dependencies = [ - "crossbeam-channel", -] - -[[package]] -name = "cadence-macros" -version = "0.29.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a9f07a3c8a329df611200b46f7969235cf6377ad01d5b3d6e92555d4fc70781" -dependencies = [ - "cadence", -] - -[[package]] -name = "cc" -version = "1.0.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" -dependencies = [ - "jobserver", - "libc", -] - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "chrono" -version = "0.4.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" -dependencies = [ - "android-tzdata", - "iana-time-zone", - "js-sys", - "num-traits", - "serde", - "wasm-bindgen", - "windows-targets", -] - -[[package]] -name = "cipher" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" -dependencies = [ - "generic-array", -] - -[[package]] -name = "combine" -version = "3.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da3da6baa321ec19e1cc41d31bf599f00c783d0517095cdaf0332e3fe8d20680" -dependencies = [ - "ascii", - "byteorder", - "either", - "memchr", - "unreachable", -] - -[[package]] -name = "console_error_panic_hook" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" -dependencies = [ - "cfg-if", - "wasm-bindgen", -] - -[[package]] -name = "console_log" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89f72f65e8501878b8a004d5a1afb780987e2ce2b4532c562e367a72c57499f" -dependencies = [ - "log", - "web-sys", -] - -[[package]] -name = "constant_time_eq" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" - -[[package]] -name = "core-foundation" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" - -[[package]] -name = "cpufeatures" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" -dependencies = [ - "libc", -] - -[[package]] -name = "crc" -version = "3.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86ec7a15cbe22e59248fc7eadb1907dab5ba09372595da4d73dd805ed4417dfe" -dependencies = [ - "crc-catalog", -] - -[[package]] -name = "crc-catalog" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cace84e55f07e7301bae1c519df89cdad8cc3cd868413d3fdbdeca9ff3db484" - -[[package]] -name = "crc32fast" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "crossbeam-channel" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" -dependencies = [ - "cfg-if", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" -dependencies = [ - "cfg-if", - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" -dependencies = [ - "autocfg", - "cfg-if", - "crossbeam-utils", - "memoffset", - "scopeguard", -] - -[[package]] -name = "crossbeam-queue" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add" -dependencies = [ - "cfg-if", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "crunchy" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "crypto-mac" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" -dependencies = [ - "generic-array", - "subtle", -] - -[[package]] -name = "ctr" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "049bb91fb4aaf0e3c7efa6cd5ef877dbbbd15b39dad06d9948de4ec8a75761ea" -dependencies = [ - "cipher", -] - -[[package]] -name = "curve25519-dalek" -version = "3.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90f9d052967f590a76e62eb387bd0bbb1b000182c3cefe5364db6b7211651bc0" -dependencies = [ - "byteorder", - "digest 0.9.0", - "rand_core 0.5.1", - "serde", - "subtle", - "zeroize", -] - -[[package]] -name = "darling" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" -dependencies = [ - "darling_core 0.13.4", - "darling_macro 0.13.4", -] - -[[package]] -name = "darling" -version = "0.20.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" -dependencies = [ - "darling_core 0.20.3", - "darling_macro 0.20.3", -] - -[[package]] -name = "darling_core" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn 1.0.109", -] - -[[package]] -name = "darling_core" -version = "0.20.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn 2.0.38", -] - -[[package]] -name = "darling_macro" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" -dependencies = [ - "darling_core 0.13.4", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "darling_macro" -version = "0.20.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" -dependencies = [ - "darling_core 0.20.3", - "quote", - "syn 2.0.38", -] - -[[package]] -name = "das_api" -version = "0.7.2" -dependencies = [ - "anchor-lang", - "async-trait", - "blockbuster", - "bs58 0.4.0", - "cadence", - "cadence-macros", - "digital_asset_types", - "env_logger 0.10.0", - "figment", - "hyper", - "jsonrpsee", - "jsonrpsee-core", - "log", - "metrics", - "mpl-bubblegum", - "mpl-candy-guard", - "mpl-candy-machine-core", - "mpl-token-metadata", - "open-rpc-derive", - "open-rpc-schema", - "schemars", - "schemars_derive", - "sea-orm", - "serde", - "serde_json", - "solana-sdk", - "sqlx", - "thiserror", - "tokio", - "tokio-postgres", - "tower", - "tower-http", - "tracing", -] - -[[package]] -name = "deranged" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2696e8a945f658fd14dc3b87242e6b80cd0f36ff04ea560fa39082368847946" -dependencies = [ - "serde", -] - -[[package]] -name = "derivation-path" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e5c37193a1db1d8ed868c03ec7b152175f26160a5b740e5e484143877e0adf0" - -[[package]] -name = "derivative" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "digest" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" -dependencies = [ - "generic-array", -] - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer 0.10.4", - "crypto-common", - "subtle", -] - -[[package]] -name = "digital_asset_types" -version = "0.7.2" -dependencies = [ - "async-trait", - "blockbuster", - "bs58 0.4.0", - "futures", - "indexmap 1.9.3", - "jsonpath_lib", - "log", - "mime_guess", - "num-derive 0.3.3", - "num-traits", - "reqwest", - "schemars", - "schemars_derive", - "sea-orm", - "sea-query 0.28.5", - "serde", - "serde_json", - "solana-sdk", - "spl-concurrent-merkle-tree", - "thiserror", - "tokio", - "url", -] - -[[package]] -name = "dirs" -version = "4.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" -dependencies = [ - "dirs-sys", -] - -[[package]] -name = "dirs-sys" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" -dependencies = [ - "libc", - "redox_users", - "winapi", -] - -[[package]] -name = "dotenvy" -version = "0.15.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" - -[[package]] -name = "dyn-clone" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23d2f3407d9a573d666de4b5bdf10569d73ca9478087346697dcbae6244bfbcd" - -[[package]] -name = "eager" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abe71d579d1812060163dff96056261deb5bf6729b100fa2e36a68b9649ba3d3" - -[[package]] -name = "ed25519" -version = "1.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7" -dependencies = [ - "signature", -] - -[[package]] -name = "ed25519-dalek" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" -dependencies = [ - "curve25519-dalek", - "ed25519", - "rand 0.7.3", - "serde", - "sha2 0.9.9", - "zeroize", -] - -[[package]] -name = "ed25519-dalek-bip32" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d2be62a4061b872c8c0873ee4fc6f101ce7b889d039f019c5fa2af471a59908" -dependencies = [ - "derivation-path", - "ed25519-dalek", - "hmac 0.12.1", - "sha2 0.10.8", -] - -[[package]] -name = "either" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" -dependencies = [ - "serde", -] - -[[package]] -name = "encoding_rs" -version = "0.8.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "enum-iterator" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7add3873b5dd076766ee79c8e406ad1a472c385476b9e38849f8eec24f1be689" -dependencies = [ - "enum-iterator-derive", -] - -[[package]] -name = "enum-iterator-derive" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eecf8589574ce9b895052fa12d69af7a233f99e6107f5cb8dd1044f2a17bfdcb" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.38", -] - -[[package]] -name = "env_logger" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" -dependencies = [ - "atty", - "humantime", - "log", - "regex", - "termcolor", -] - -[[package]] -name = "env_logger" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" -dependencies = [ - "humantime", - "is-terminal", - "log", - "regex", - "termcolor", -] - -[[package]] -name = "equivalent" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" - -[[package]] -name = "errno" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860" -dependencies = [ - "libc", - "windows-sys", -] - -[[package]] -name = "event-listener" -version = "2.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" - -[[package]] -name = "fallible-iterator" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" - -[[package]] -name = "fastrand" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" - -[[package]] -name = "feature-probe" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "835a3dc7d1ec9e75e2b5fb4ba75396837112d2060b03f7d43bc1897c7f7211da" - -[[package]] -name = "figment" -version = "0.10.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a014ac935975a70ad13a3bff2463b1c1b083b35ae4cb6309cfc59476aa7a181f" -dependencies = [ - "atomic", - "pear", - "serde", - "uncased", - "version_check", -] - -[[package]] -name = "finl_unicode" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fcfdc7a0362c9f4444381a9e697c79d435fe65b52a37466fc2c1184cee9edc6" - -[[package]] -name = "flatbuffers" -version = "23.5.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dac53e22462d78c16d64a1cd22371b54cc3fe94aa15e7886a2fa6e5d1ab8640" -dependencies = [ - "bitflags 1.3.2", - "rustc_version", -] - -[[package]] -name = "flate2" -version = "1.0.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6c98ee8095e9d1dcbf2fcc6d95acccb90d1c81db1e44725c6a984b1dbdfb010" -dependencies = [ - "crc32fast", - "miniz_oxide", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - -[[package]] -name = "form_urlencoded" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "funty" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" - -[[package]] -name = "futures" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" - -[[package]] -name = "futures-executor" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-intrusive" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a604f7a68fbf8103337523b1fadc8ade7361ee3f112f7c680ad179651616aed5" -dependencies = [ - "futures-core", - "lock_api", - "parking_lot 0.11.2", -] - -[[package]] -name = "futures-io" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" - -[[package]] -name = "futures-macro" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.38", -] - -[[package]] -name = "futures-sink" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" - -[[package]] -name = "futures-task" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" - -[[package]] -name = "futures-util" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "slab", -] - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "serde", - "typenum", - "version_check", -] - -[[package]] -name = "gethostname" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1ebd34e35c46e00bb73e81363248d627782724609fe1b6396f553f68fe3862e" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "getrandom" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" -dependencies = [ - "cfg-if", - "js-sys", - "libc", - "wasi 0.9.0+wasi-snapshot-preview1", - "wasm-bindgen", -] - -[[package]] -name = "getrandom" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" -dependencies = [ - "cfg-if", - "js-sys", - "libc", - "wasi 0.11.0+wasi-snapshot-preview1", - "wasm-bindgen", -] - -[[package]] -name = "gimli" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" - -[[package]] -name = "globset" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "759c97c1e17c55525b57192c06a267cda0ac5210b222d6b82189a2338fa1c13d" -dependencies = [ - "aho-corasick", - "bstr", - "fnv", - "log", - "regex", -] - -[[package]] -name = "goblin" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7666983ed0dd8d21a6f6576ee00053ca0926fb281a5522577a4dbd0f1b54143" -dependencies = [ - "log", - "plain", - "scroll", -] - -[[package]] -name = "h2" -version = "0.3.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91fc23aa11be92976ef4729127f1a74adf36d8436f7816b185d18df956790833" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http", - "indexmap 1.9.3", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "hash32" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" -dependencies = [ - "byteorder", -] - -[[package]] -name = "hashbrown" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" -dependencies = [ - "ahash 0.7.6", -] - -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" -dependencies = [ - "ahash 0.7.6", -] - -[[package]] -name = "hashbrown" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" -dependencies = [ - "ahash 0.8.3", -] - -[[package]] -name = "hashbrown" -version = "0.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dfda62a12f55daeae5015f81b0baea145391cb4520f86c248fc615d72640d12" -dependencies = [ - "ahash 0.8.3", - "allocator-api2", -] - -[[package]] -name = "hashlink" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" -dependencies = [ - "hashbrown 0.14.1", -] - -[[package]] -name = "hdrhistogram" -version = "7.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f19b9f54f7c7f55e31401bb647626ce0cf0f67b0004982ce815b3ee72a02aa8" -dependencies = [ - "byteorder", - "num-traits", -] - -[[package]] -name = "heck" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" -dependencies = [ - "unicode-segmentation", -] - -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" -dependencies = [ - "unicode-segmentation", -] - -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - -[[package]] -name = "hermit-abi" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "hkdf" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437" -dependencies = [ - "hmac 0.12.1", -] - -[[package]] -name = "hmac" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840" -dependencies = [ - "crypto-mac", - "digest 0.9.0", -] - -[[package]] -name = "hmac" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" -dependencies = [ - "digest 0.10.7", -] - -[[package]] -name = "hmac-drbg" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17ea0a1394df5b6574da6e0c1ade9e78868c9fb0a4e5ef4428e32da4676b85b1" -dependencies = [ - "digest 0.9.0", - "generic-array", - "hmac 0.8.1", -] - -[[package]] -name = "http" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "http-body" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" -dependencies = [ - "bytes", - "http", - "pin-project-lite", -] - -[[package]] -name = "http-range-header" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "add0ab9360ddbd88cfeb3bd9574a1d85cfdfa14db10b3e21d3700dbc4328758f" - -[[package]] -name = "httparse" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" - -[[package]] -name = "httpdate" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" - -[[package]] -name = "humantime" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" - -[[package]] -name = "hyper" -version = "0.14.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" -dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "socket2 0.4.9", - "tokio", - "tower-service", - "tracing", - "want", -] - -[[package]] -name = "hyper-rustls" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d78e1e73ec14cf7375674f74d7dde185c8206fd9dea6fb6295e8a98098aaa97" -dependencies = [ - "futures-util", - "http", - "hyper", - "rustls 0.21.7", - "tokio", - "tokio-rustls 0.24.1", -] - -[[package]] -name = "hyper-tls" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" -dependencies = [ - "bytes", - "hyper", - "native-tls", - "tokio", - "tokio-native-tls", -] - -[[package]] -name = "iana-time-zone" -version = "0.1.57" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "wasm-bindgen", - "windows", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" -dependencies = [ - "cc", -] - -[[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - -[[package]] -name = "idna" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "im" -version = "15.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0acd33ff0285af998aaf9b57342af478078f53492322fafc47450e09397e0e9" -dependencies = [ - "bitmaps", - "rand_core 0.6.4", - "rand_xoshiro", - "rayon", - "serde", - "sized-chunks", - "typenum", - "version_check", -] - -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", -] - -[[package]] -name = "indexmap" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897" -dependencies = [ - "equivalent", - "hashbrown 0.14.1", -] - -[[package]] -name = "inlinable_string" -version = "0.1.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8fae54786f62fb2918dcfae3d568594e50eb9b5c25bf04371af6fe7516452fb" - -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "ipnet" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" - -[[package]] -name = "iri-string" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f0f7638c1e223529f1bfdc48c8b133b9e0b434094d1d28473161ee48b235f78" -dependencies = [ - "nom", -] - -[[package]] -name = "is-terminal" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" -dependencies = [ - "hermit-abi 0.3.3", - "rustix", - "windows-sys", -] - -[[package]] -name = "itertools" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" -dependencies = [ - "either", -] - -[[package]] -name = "itertools" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" - -[[package]] -name = "jobserver" -version = "0.1.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2" -dependencies = [ - "libc", -] - -[[package]] -name = "js-sys" -version = "0.3.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "jsonpath_lib" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaa63191d68230cccb81c5aa23abd53ed64d83337cacbb25a7b8c7979523774f" -dependencies = [ - "log", - "serde", - "serde_json", -] - -[[package]] -name = "jsonrpsee" -version = "0.16.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "367a292944c07385839818bb71c8d76611138e2dedb0677d035b8da21d29c78b" -dependencies = [ - "jsonrpsee-core", - "jsonrpsee-proc-macros", - "jsonrpsee-server", - "jsonrpsee-types", - "tracing", -] - -[[package]] -name = "jsonrpsee-core" -version = "0.16.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b5dde66c53d6dcdc8caea1874a45632ec0fcf5b437789f1e45766a1512ce803" -dependencies = [ - "anyhow", - "arrayvec", - "async-trait", - "beef", - "futures-channel", - "futures-util", - "globset", - "hyper", - "jsonrpsee-types", - "parking_lot 0.12.1", - "rand 0.8.5", - "rustc-hash", - "serde", - "serde_json", - "soketto", - "thiserror", - "tokio", - "tracing", -] - -[[package]] -name = "jsonrpsee-proc-macros" -version = "0.16.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44e8ab85614a08792b9bff6c8feee23be78c98d0182d4c622c05256ab553892a" -dependencies = [ - "heck 0.4.1", - "proc-macro-crate 1.3.1", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "jsonrpsee-server" -version = "0.16.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4d945a6008c9b03db3354fb3c83ee02d2faa9f2e755ec1dfb69c3551b8f4ba" -dependencies = [ - "futures-channel", - "futures-util", - "http", - "hyper", - "jsonrpsee-core", - "jsonrpsee-types", - "serde", - "serde_json", - "soketto", - "tokio", - "tokio-stream", - "tokio-util", - "tower", - "tracing", -] - -[[package]] -name = "jsonrpsee-types" -version = "0.16.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "245ba8e5aa633dd1c1e4fae72bce06e71f42d34c14a2767c6b4d173b57bee5e5" -dependencies = [ - "anyhow", - "beef", - "serde", - "serde_json", - "thiserror", - "tracing", -] - -[[package]] -name = "kaigan" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a26f49495f94a283312e7ef45a243540ef20c9356bb01c8d84a61ac8ba5339b" -dependencies = [ - "borsh 0.10.3", -] - -[[package]] -name = "keccak" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" -dependencies = [ - "cpufeatures", -] - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "libc" -version = "0.2.149" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" - -[[package]] -name = "libsecp256k1" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9d220bc1feda2ac231cb78c3d26f27676b8cf82c96971f7aeef3d0cf2797c73" -dependencies = [ - "arrayref", - "base64 0.12.3", - "digest 0.9.0", - "hmac-drbg", - "libsecp256k1-core", - "libsecp256k1-gen-ecmult", - "libsecp256k1-gen-genmult", - "rand 0.7.3", - "serde", - "sha2 0.9.9", - "typenum", -] - -[[package]] -name = "libsecp256k1-core" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0f6ab710cec28cef759c5f18671a27dae2a5f952cdaaee1d8e2908cb2478a80" -dependencies = [ - "crunchy", - "digest 0.9.0", - "subtle", -] - -[[package]] -name = "libsecp256k1-gen-ecmult" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccab96b584d38fac86a83f07e659f0deafd0253dc096dab5a36d53efe653c5c3" -dependencies = [ - "libsecp256k1-core", -] - -[[package]] -name = "libsecp256k1-gen-genmult" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67abfe149395e3aa1c48a2beb32b068e2334402df8181f818d3aee2b304c4f5d" -dependencies = [ - "libsecp256k1-core", -] - -[[package]] -name = "linux-raw-sys" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" - -[[package]] -name = "lock_api" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" - -[[package]] -name = "md-5" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" -dependencies = [ - "cfg-if", - "digest 0.10.7", -] - -[[package]] -name = "memchr" -version = "2.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" - -[[package]] -name = "memmap2" -version = "0.5.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" -dependencies = [ - "libc", -] - -[[package]] -name = "memoffset" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" -dependencies = [ - "autocfg", -] - -[[package]] -name = "merlin" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58c38e2799fc0978b65dfff8023ec7843e2330bb462f19198840b34b6582397d" -dependencies = [ - "byteorder", - "keccak", - "rand_core 0.6.4", - "zeroize", -] - -[[package]] -name = "metrics" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b9b8653cec6897f73b519a43fba5ee3d50f62fe9af80b428accdcc093b4a849" -dependencies = [ - "ahash 0.7.6", - "metrics-macros", - "portable-atomic 0.3.20", -] - -[[package]] -name = "metrics-macros" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "731f8ecebd9f3a4aa847dfe75455e4757a45da40a7793d2f0b1f9b6ed18b23f3" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "mime" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" - -[[package]] -name = "mime_guess" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" -dependencies = [ - "mime", - "unicase", -] - -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - -[[package]] -name = "miniz_oxide" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" -dependencies = [ - "adler", -] - -[[package]] -name = "mio" -version = "0.8.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" -dependencies = [ - "libc", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys", -] - -[[package]] -name = "mpl-bubblegum" -version = "1.0.1-beta.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29346f26192bb7f73330196fde4c8cfb35675bf1a4b026cd088f7ca8fda69f3f" -dependencies = [ - "borsh 0.10.3", - "kaigan", - "num-derive 0.3.3", - "num-traits", - "solana-program", - "thiserror", -] - -[[package]] -name = "mpl-candy-guard" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59c5c2ffb233226e0c531f1cf800909e46120e98722eeb53dae68b0996303a38" -dependencies = [ - "anchor-lang", - "arrayref", - "mpl-candy-guard-derive", - "mpl-candy-machine-core", - "mpl-token-auth-rules", - "mpl-token-metadata", - "solana-gateway", - "solana-program", - "spl-associated-token-account", - "spl-token 4.0.0", - "spl-token-2022 0.9.0", -] - -[[package]] -name = "mpl-candy-guard-derive" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18e4d3002ea881e94a238798faf87a006a687297a24bd4b3f810fbb63611173d" -dependencies = [ - "quote", - "syn 1.0.109", -] - -[[package]] -name = "mpl-candy-machine-core" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4db99e1aac3bdebf907338aec5f1785701b8a82e6bdac5f42a270750d37c5264" -dependencies = [ - "anchor-lang", - "arrayref", - "mpl-token-auth-rules", - "mpl-token-metadata", - "solana-program", - "spl-associated-token-account", - "spl-token 4.0.0", -] - -[[package]] -name = "mpl-token-auth-rules" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66b1ec5ee0570f688cc84ff4624c5c50732f1a2bfc789f6b34af5b563428d971" -dependencies = [ - "borsh 0.10.3", - "bytemuck", - "mpl-token-metadata-context-derive 0.2.1", - "num-derive 0.3.3", - "num-traits", - "rmp-serde", - "serde", - "shank", - "solana-program", - "solana-zk-token-sdk", - "thiserror", -] - -[[package]] -name = "mpl-token-metadata" -version = "2.0.0-beta.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3545bd5fe73416f6514cd93899612e0e138619e72df8bc7d19906a12688c69e" -dependencies = [ - "arrayref", - "borsh 0.10.3", - "mpl-token-auth-rules", - "mpl-token-metadata-context-derive 0.3.0", - "mpl-utils", - "num-derive 0.3.3", - "num-traits", - "serde", - "serde_with 1.14.0", - "shank", - "solana-program", - "spl-associated-token-account", - "spl-token 4.0.0", - "thiserror", -] - -[[package]] -name = "mpl-token-metadata-context-derive" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12989bc45715b0ee91944855130131479f9c772e198a910c3eb0ea327d5bffc3" -dependencies = [ - "quote", - "syn 1.0.109", -] - -[[package]] -name = "mpl-token-metadata-context-derive" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5a739019e11d93661a64ef5fe108ab17c79b35961e944442ff6efdd460ad01a" -dependencies = [ - "quote", - "syn 1.0.109", -] - -[[package]] -name = "mpl-utils" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f2e4f92aec317d5853c0cc4c03c55f5178511c45bb3dbb441aea63117bf3dc9" -dependencies = [ - "arrayref", - "solana-program", - "spl-token-2022 0.6.1", -] - -[[package]] -name = "native-tls" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" -dependencies = [ - "lazy_static", - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - -[[package]] -name = "num" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8536030f9fea7127f841b45bb6243b27255787fb4eb83958aa1ef9d2fdc0c36" -dependencies = [ - "num-bigint 0.2.6", - "num-complex", - "num-integer", - "num-iter", - "num-rational", - "num-traits", -] - -[[package]] -name = "num-bigint" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-bigint" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-complex" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6b19411a9719e753aff12e5187b74d60d3dc449ec3f4dc21e3989c3f554bc95" -dependencies = [ - "autocfg", - "num-traits", -] - -[[package]] -name = "num-derive" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "num-derive" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfb77679af88f8b125209d354a202862602672222e7f2313fdd6dc349bad4712" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.38", -] - -[[package]] -name = "num-integer" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" -dependencies = [ - "autocfg", - "num-traits", -] - -[[package]] -name = "num-iter" -version = "0.1.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef" -dependencies = [ - "autocfg", - "num-bigint 0.2.6", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" -dependencies = [ - "autocfg", -] - -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi 0.3.3", - "libc", -] - -[[package]] -name = "num_enum" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9" -dependencies = [ - "num_enum_derive 0.5.11", -] - -[[package]] -name = "num_enum" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a015b430d3c108a207fd776d2e2196aaf8b1cf8cf93253e3a097ff3085076a1" -dependencies = [ - "num_enum_derive 0.6.1", -] - -[[package]] -name = "num_enum" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70bf6736f74634d299d00086f02986875b3c2d924781a6a2cb6c201e73da0ceb" -dependencies = [ - "num_enum_derive 0.7.0", -] - -[[package]] -name = "num_enum_derive" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799" -dependencies = [ - "proc-macro-crate 1.3.1", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "num_enum_derive" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96667db765a921f7b295ffee8b60472b686a51d4f21c2ee4ffdb94c7013b65a6" -dependencies = [ - "proc-macro-crate 1.3.1", - "proc-macro2", - "quote", - "syn 2.0.38", -] - -[[package]] -name = "num_enum_derive" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56ea360eafe1022f7cc56cd7b869ed57330fb2453d0c7831d99b74c65d2f5597" -dependencies = [ - "proc-macro-crate 1.3.1", - "proc-macro2", - "quote", - "syn 2.0.38", -] - -[[package]] -name = "object" -version = "0.32.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" -dependencies = [ - "memchr", -] - -[[package]] -name = "once_cell" -version = "1.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" - -[[package]] -name = "opaque-debug" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" - -[[package]] -name = "open-rpc-derive" -version = "0.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae3de03a56750973a83c76a40fb4b81969d42fad152cd0e787e25c79dcf54e3f" -dependencies = [ - "open-rpc-schema", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "open-rpc-schema" -version = "0.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6919654a78166b8d8f266f702ce763c0880c11a2e75e1de9cc3e51704abf620" -dependencies = [ - "schemars", - "schemars_derive", - "serde", - "serde_json", -] - -[[package]] -name = "openssl" -version = "0.10.57" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bac25ee399abb46215765b1cb35bc0212377e58a061560d8b29b024fd0430e7c" -dependencies = [ - "bitflags 2.4.0", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.38", -] - -[[package]] -name = "openssl-probe" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" - -[[package]] -name = "openssl-sys" -version = "0.9.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db4d56a4c0478783083cfafcc42493dd4a981d41669da64b4572a2a089b51b1d" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "ouroboros" -version = "0.15.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1358bd1558bd2a083fed428ffeda486fbfb323e698cdda7794259d592ca72db" -dependencies = [ - "aliasable", - "ouroboros_macro", -] - -[[package]] -name = "ouroboros_macro" -version = "0.15.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f7d21ccd03305a674437ee1248f3ab5d4b1db095cf1caf49f1713ddf61956b7" -dependencies = [ - "Inflector", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "parking_lot" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" -dependencies = [ - "instant", - "lock_api", - "parking_lot_core 0.8.6", -] - -[[package]] -name = "parking_lot" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" -dependencies = [ - "lock_api", - "parking_lot_core 0.9.8", -] - -[[package]] -name = "parking_lot_core" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" -dependencies = [ - "cfg-if", - "instant", - "libc", - "redox_syscall 0.2.16", - "smallvec", - "winapi", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall 0.3.5", - "smallvec", - "windows-targets", -] - -[[package]] -name = "paste" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" - -[[package]] -name = "pbkdf2" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "216eaa586a190f0a738f2f918511eecfa90f13295abec0e457cdebcceda80cbd" -dependencies = [ - "crypto-mac", -] - -[[package]] -name = "pbkdf2" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" -dependencies = [ - "digest 0.10.7", -] - -[[package]] -name = "pear" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61a386cd715229d399604b50d1361683fe687066f42d56f54be995bc6868f71c" -dependencies = [ - "inlinable_string", - "pear_codegen", - "yansi", -] - -[[package]] -name = "pear_codegen" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da9f0f13dac8069c139e8300a6510e3f4143ecf5259c60b116a9b271b4ca0d54" -dependencies = [ - "proc-macro2", - "proc-macro2-diagnostics", - "quote", - "syn 2.0.38", -] - -[[package]] -name = "percent-encoding" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" - -[[package]] -name = "percentage" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fd23b938276f14057220b707937bcb42fa76dda7560e57a2da30cb52d557937" -dependencies = [ - "num", -] - -[[package]] -name = "phf" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" -dependencies = [ - "phf_shared", -] - -[[package]] -name = "phf_shared" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" -dependencies = [ - "siphasher", -] - -[[package]] -name = "pin-project" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.38", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "pkg-config" -version = "0.3.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" - -[[package]] -name = "plain" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" - -[[package]] -name = "plerkle_serialization" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f021e409a6a1ec8b7a325db27254e7fa3942e845cfe96f5f8f494977f2646a8" -dependencies = [ - "bs58 0.4.0", - "chrono", - "flatbuffers", - "serde", - "solana-sdk", - "solana-transaction-status", - "thiserror", -] - -[[package]] -name = "polyval" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8419d2b623c7c0896ff2d5d96e2cb4ede590fed28fcc34934f4c33c036e620a1" -dependencies = [ - "cfg-if", - "cpufeatures", - "opaque-debug", - "universal-hash", -] - -[[package]] -name = "portable-atomic" -version = "0.3.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e30165d31df606f5726b090ec7592c308a0eaf61721ff64c9a3018e344a8753e" -dependencies = [ - "portable-atomic 1.4.3", -] - -[[package]] -name = "portable-atomic" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31114a898e107c51bb1609ffaf55a0e011cf6a4d7f1170d0015a165082c0338b" - -[[package]] -name = "postgres-protocol" -version = "0.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49b6c5ef183cd3ab4ba005f1ca64c21e8bd97ce4699cfea9e8d9a2c4958ca520" -dependencies = [ - "base64 0.21.4", - "byteorder", - "bytes", - "fallible-iterator", - "hmac 0.12.1", - "md-5", - "memchr", - "rand 0.8.5", - "sha2 0.10.8", - "stringprep", -] - -[[package]] -name = "postgres-types" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d2234cdee9408b523530a9b6d2d6b373d1db34f6a8e51dc03ded1828d7fb67c" -dependencies = [ - "bytes", - "fallible-iterator", - "postgres-protocol", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" - -[[package]] -name = "proc-macro-crate" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" -dependencies = [ - "toml", -] - -[[package]] -name = "proc-macro-crate" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" -dependencies = [ - "once_cell", - "toml_edit", -] - -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn 1.0.109", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - -[[package]] -name = "proc-macro2" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "proc-macro2-diagnostics" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.38", - "version_check", - "yansi", -] - -[[package]] -name = "ptr_meta" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1" -dependencies = [ - "ptr_meta_derive", -] - -[[package]] -name = "ptr_meta_derive" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "qstring" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d464fae65fff2680baf48019211ce37aaec0c78e9264c84a3e484717f965104e" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "quote" -version = "1.0.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "radium" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" - -[[package]] -name = "rand" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "getrandom 0.1.16", - "libc", - "rand_chacha 0.2.2", - "rand_core 0.5.1", - "rand_hc", -] - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_chacha" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" -dependencies = [ - "ppv-lite86", - "rand_core 0.5.1", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -dependencies = [ - "getrandom 0.1.16", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom 0.2.10", -] - -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core 0.5.1", -] - -[[package]] -name = "rand_xoshiro" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" -dependencies = [ - "rand_core 0.6.4", -] - -[[package]] -name = "rayon" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" -dependencies = [ - "crossbeam-deque", - "crossbeam-utils", -] - -[[package]] -name = "redox_syscall" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "redox_syscall" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "redox_users" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" -dependencies = [ - "getrandom 0.2.10", - "redox_syscall 0.2.16", - "thiserror", -] - -[[package]] -name = "regex" -version = "1.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebee201405406dbf528b8b672104ae6d6d63e6d118cb10e4d51abbc7b58044ff" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59b23e92ee4318893fa3fe3e6fb365258efbfe6ac6ab30f090cdcbb7aa37efa9" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" - -[[package]] -name = "rend" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2571463863a6bd50c32f94402933f03457a3fbaf697a707c5be741e459f08fd" -dependencies = [ - "bytecheck", -] - -[[package]] -name = "reqwest" -version = "0.11.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" -dependencies = [ - "async-compression 0.4.3", - "base64 0.21.4", - "bytes", - "encoding_rs", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "hyper", - "hyper-rustls", - "hyper-tls", - "ipnet", - "js-sys", - "log", - "mime", - "native-tls", - "once_cell", - "percent-encoding", - "pin-project-lite", - "rustls 0.21.7", - "rustls-pemfile", - "serde", - "serde_json", - "serde_urlencoded", - "system-configuration", - "tokio", - "tokio-native-tls", - "tokio-rustls 0.24.1", - "tokio-util", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "webpki-roots 0.25.2", - "winreg", -] - -[[package]] -name = "ring" -version = "0.16.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" -dependencies = [ - "cc", - "libc", - "once_cell", - "spin 0.5.2", - "untrusted 0.7.1", - "web-sys", - "winapi", -] - -[[package]] -name = "ring" -version = "0.17.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "911b295d2d302948838c8ac142da1ee09fa7863163b44e6715bc9357905878b8" -dependencies = [ - "cc", - "getrandom 0.2.10", - "libc", - "spin 0.9.8", - "untrusted 0.9.0", - "windows-sys", -] - -[[package]] -name = "rkyv" -version = "0.7.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0200c8230b013893c0b2d6213d6ec64ed2b9be2e0e016682b7224ff82cff5c58" -dependencies = [ - "bitvec", - "bytecheck", - "hashbrown 0.12.3", - "ptr_meta", - "rend", - "rkyv_derive", - "seahash", - "tinyvec", - "uuid", -] - -[[package]] -name = "rkyv_derive" -version = "0.7.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2e06b915b5c230a17d7a736d1e2e63ee753c256a8614ef3f5147b13a4f5541d" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "rmp" -version = "0.8.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f9860a6cc38ed1da53456442089b4dfa35e7cedaa326df63017af88385e6b20" -dependencies = [ - "byteorder", - "num-traits", - "paste", -] - -[[package]] -name = "rmp-serde" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bffea85eea980d8a74453e5d02a8d93028f3c34725de143085a844ebe953258a" -dependencies = [ - "byteorder", - "rmp", - "serde", -] - -[[package]] -name = "rust_decimal" -version = "1.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4c4216490d5a413bc6d10fa4742bd7d4955941d062c0ef873141d6b0e7b30fd" -dependencies = [ - "arrayvec", - "borsh 0.10.3", - "bytes", - "num-traits", - "rand 0.8.5", - "rkyv", - "serde", - "serde_json", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" - -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - -[[package]] -name = "rustc_version" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" -dependencies = [ - "semver", -] - -[[package]] -name = "rustix" -version = "0.38.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a74ee2d7c2581cd139b42447d7d9389b889bdaad3a73f1ebb16f2a3237bb19c" -dependencies = [ - "bitflags 2.4.0", - "errno", - "libc", - "linux-raw-sys", - "windows-sys", -] - -[[package]] -name = "rustls" -version = "0.20.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b80e3dec595989ea8510028f30c408a4630db12c9cbb8de34203b89d6577e99" -dependencies = [ - "log", - "ring 0.16.20", - "sct", - "webpki", -] - -[[package]] -name = "rustls" -version = "0.21.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd8d6c9f025a446bc4d18ad9632e69aec8f287aa84499ee335599fabd20c3fd8" -dependencies = [ - "log", - "ring 0.16.20", - "rustls-webpki", - "sct", -] - -[[package]] -name = "rustls-pemfile" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" -dependencies = [ - "base64 0.21.4", -] - -[[package]] -name = "rustls-webpki" -version = "0.101.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c7d5dece342910d9ba34d259310cae3e0154b873b35408b787b59bce53d34fe" -dependencies = [ - "ring 0.16.20", - "untrusted 0.7.1", -] - -[[package]] -name = "rustversion" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" - -[[package]] -name = "ryu" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" - -[[package]] -name = "schannel" -version = "0.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" -dependencies = [ - "windows-sys", -] - -[[package]] -name = "schemars" -version = "0.8.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f7b0ce13155372a76ee2e1c5ffba1fe61ede73fbea5630d61eee6fac4929c0c" -dependencies = [ - "dyn-clone", - "schemars_derive", - "serde", - "serde_json", -] - -[[package]] -name = "schemars_derive" -version = "0.8.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e85e2a16b12bdb763244c69ab79363d71db2b4b918a2def53f80b02e0574b13c" -dependencies = [ - "proc-macro2", - "quote", - "serde_derive_internals", - "syn 1.0.109", -] - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "scroll" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04c565b551bafbef4157586fa379538366e4385d42082f255bfd96e4fe8519da" -dependencies = [ - "scroll_derive", -] - -[[package]] -name = "scroll_derive" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1db149f81d46d2deba7cd3c50772474707729550221e69588478ebf9ada425ae" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.38", -] - -[[package]] -name = "sct" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" -dependencies = [ - "ring 0.16.20", - "untrusted 0.7.1", -] - -[[package]] -name = "sea-orm" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88694d01b528a94f90ad87f8d2f546d060d070eee180315c67d158cb69476034" -dependencies = [ - "async-stream", - "async-trait", - "chrono", - "futures", - "futures-util", - "log", - "ouroboros", - "rust_decimal", - "sea-orm-macros", - "sea-query 0.27.2", - "sea-query-binder", - "sea-strum", - "serde", - "serde_json", - "sqlx", - "thiserror", - "time", - "tracing", - "url", - "uuid", -] - -[[package]] -name = "sea-orm-macros" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7216195de9c6b2474fd0efab486173dccd0eff21f28cc54aa4c0205d52fb3af0" -dependencies = [ - "bae", - "heck 0.3.3", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "sea-query" -version = "0.27.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4f0fc4d8e44e1d51c739a68d336252a18bc59553778075d5e32649be6ec92ed" -dependencies = [ - "chrono", - "rust_decimal", - "sea-query-derive 0.2.0", - "serde_json", - "time", - "uuid", -] - -[[package]] -name = "sea-query" -version = "0.28.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbab99b8cd878ab7786157b7eb8df96333a6807cc6e45e8888c85b51534b401a" -dependencies = [ - "sea-query-derive 0.3.0", -] - -[[package]] -name = "sea-query-binder" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c2585b89c985cfacfe0ec9fc9e7bb055b776c1a2581c4e3c6185af2b8bf8865" -dependencies = [ - "chrono", - "rust_decimal", - "sea-query 0.27.2", - "serde_json", - "sqlx", - "time", - "uuid", -] - -[[package]] -name = "sea-query-derive" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34cdc022b4f606353fe5dc85b09713a04e433323b70163e81513b141c6ae6eb5" -dependencies = [ - "heck 0.3.3", - "proc-macro2", - "quote", - "syn 1.0.109", - "thiserror", -] - -[[package]] -name = "sea-query-derive" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63f62030c60f3a691f5fe251713b4e220b306e50a71e1d6f9cce1f24bb781978" -dependencies = [ - "heck 0.4.1", - "proc-macro2", - "quote", - "syn 1.0.109", - "thiserror", -] - -[[package]] -name = "sea-strum" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "391d06a6007842cfe79ac6f7f53911b76dfd69fc9a6769f1cf6569d12ce20e1b" -dependencies = [ - "sea-strum_macros", -] - -[[package]] -name = "sea-strum_macros" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69b4397b825df6ccf1e98bcdabef3bbcfc47ff5853983467850eeab878384f21" -dependencies = [ - "heck 0.3.3", - "proc-macro2", - "quote", - "rustversion", - "syn 1.0.109", -] - -[[package]] -name = "seahash" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" - -[[package]] -name = "security-framework" -version = "2.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "semver" -version = "1.0.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad977052201c6de01a8ef2aa3378c4bd23217a056337d1d6da40468d267a4fb0" - -[[package]] -name = "serde" -version = "1.0.188" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_bytes" -version = "0.11.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab33ec92f677585af6d88c65593ae2375adde54efdbf16d597f2cbc7a6d368ff" -dependencies = [ - "serde", -] - -[[package]] -name = "serde_derive" -version = "1.0.188" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.38", -] - -[[package]] -name = "serde_derive_internals" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "serde_json" -version = "1.0.107" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" -dependencies = [ - "indexmap 2.0.2", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "serde_with" -version = "1.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678b5a069e50bf00ecd22d0cd8ddf7c236f68581b03db652061ed5eb13a312ff" -dependencies = [ - "serde", - "serde_with_macros 1.5.2", -] - -[[package]] -name = "serde_with" -version = "2.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07ff71d2c147a7b57362cead5e22f772cd52f6ab31cfcd9edcd7f6aeb2a0afbe" -dependencies = [ - "serde", - "serde_with_macros 2.3.3", -] - -[[package]] -name = "serde_with_macros" -version = "1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e182d6ec6f05393cc0e5ed1bf81ad6db3a8feedf8ee515ecdd369809bcce8082" -dependencies = [ - "darling 0.13.4", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "serde_with_macros" -version = "2.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "881b6f881b17d13214e5d494c939ebab463d01264ce1811e9d4ac3a882e7695f" -dependencies = [ - "darling 0.20.3", - "proc-macro2", - "quote", - "syn 2.0.38", -] - -[[package]] -name = "sha-1" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" -dependencies = [ - "block-buffer 0.9.0", - "cfg-if", - "cpufeatures", - "digest 0.9.0", - "opaque-debug", -] - -[[package]] -name = "sha1" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.10.7", -] - -[[package]] -name = "sha2" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" -dependencies = [ - "block-buffer 0.9.0", - "cfg-if", - "cpufeatures", - "digest 0.9.0", - "opaque-debug", -] - -[[package]] -name = "sha2" -version = "0.10.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.10.7", -] - -[[package]] -name = "sha3" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809" -dependencies = [ - "block-buffer 0.9.0", - "digest 0.9.0", - "keccak", - "opaque-debug", -] - -[[package]] -name = "sha3" -version = "0.10.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" -dependencies = [ - "digest 0.10.7", - "keccak", -] - -[[package]] -name = "shank" -version = "0.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b63e565b5e95ad88ab38f312e89444c749360641c509ef2de0093b49f55974a5" -dependencies = [ - "shank_macro", -] - -[[package]] -name = "shank_macro" -version = "0.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63927d22a1e8b74bda98cc6e151fcdf178b7abb0dc6c4f81e0bbf5ffe2fc4ec8" -dependencies = [ - "proc-macro2", - "quote", - "shank_macro_impl", - "syn 1.0.109", -] - -[[package]] -name = "shank_macro_impl" -version = "0.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ce03403df682f80f4dc1efafa87a4d0cb89b03726d0565e6364bdca5b9a441" -dependencies = [ - "anyhow", - "proc-macro2", - "quote", - "serde", - "syn 1.0.109", -] - -[[package]] -name = "signal-hook-registry" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" -dependencies = [ - "libc", -] - -[[package]] -name = "signature" -version = "1.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" - -[[package]] -name = "simdutf8" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a" - -[[package]] -name = "siphasher" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" - -[[package]] -name = "sized-chunks" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16d69225bde7a69b235da73377861095455d298f2b970996eec25ddbb42b3d1e" -dependencies = [ - "bitmaps", - "typenum", -] - -[[package]] -name = "slab" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] - -[[package]] -name = "smallvec" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" - -[[package]] -name = "socket2" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "socket2" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e" -dependencies = [ - "libc", - "windows-sys", -] - -[[package]] -name = "soketto" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d1c5305e39e09653383c2c7244f2f78b3bcae37cf50c64cb4789c9f5096ec2" -dependencies = [ - "base64 0.13.1", - "bytes", - "futures", - "http", - "httparse", - "log", - "rand 0.8.5", - "sha-1", -] - -[[package]] -name = "solana-account-decoder" -version = "1.16.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f52aec62a85932e26d1085864b0f7b99b31934aec8dd132429bfef6d7fb1d3a6" -dependencies = [ - "Inflector", - "base64 0.21.4", - "bincode", - "bs58 0.4.0", - "bv", - "lazy_static", - "serde", - "serde_derive", - "serde_json", - "solana-address-lookup-table-program", - "solana-config-program", - "solana-sdk", - "spl-token 4.0.0", - "spl-token-2022 0.9.0", - "spl-token-metadata-interface", - "thiserror", - "zstd", -] - -[[package]] -name = "solana-address-lookup-table-program" -version = "1.16.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee0bd25f4ba0a15fc16c57b41b1e1b14f5271b83214fda158fdedb58758d394e" -dependencies = [ - "bincode", - "bytemuck", - "log", - "num-derive 0.3.3", - "num-traits", - "rustc_version", - "serde", - "solana-frozen-abi", - "solana-frozen-abi-macro", - "solana-program", - "solana-program-runtime", - "solana-sdk", - "thiserror", -] - -[[package]] -name = "solana-config-program" -version = "1.16.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fd0fc1efb91a1661aeb1ff6a691156c3b1bffdaed0aa096589499dd83f9e50b" -dependencies = [ - "bincode", - "chrono", - "serde", - "serde_derive", - "solana-program-runtime", - "solana-sdk", -] - -[[package]] -name = "solana-frozen-abi" -version = "1.16.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02eb4f0ed3eade20f4abdcc0031167344237cd6e16808bd0f33945f9db7861fe" -dependencies = [ - "ahash 0.8.3", - "blake3", - "block-buffer 0.10.4", - "bs58 0.4.0", - "bv", - "byteorder", - "cc", - "either", - "generic-array", - "getrandom 0.1.16", - "im", - "lazy_static", - "log", - "memmap2", - "once_cell", - "rand_core 0.6.4", - "rustc_version", - "serde", - "serde_bytes", - "serde_derive", - "serde_json", - "sha2 0.10.8", - "solana-frozen-abi-macro", - "subtle", - "thiserror", -] - -[[package]] -name = "solana-frozen-abi-macro" -version = "1.16.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28514761a285944cbad5b3d7930546369b80a713ba37d84bcf6ed2753611765" -dependencies = [ - "proc-macro2", - "quote", - "rustc_version", - "syn 2.0.38", -] - -[[package]] -name = "solana-gateway" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d148eb75d0799f6825dc2a840b85c065e3d6d12212845add3e059163f98770e" -dependencies = [ - "borsh 0.10.3", - "num-derive 0.4.1", - "num-traits", - "solana-program", - "thiserror", -] - -[[package]] -name = "solana-logger" -version = "1.16.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c310c6749435ce1ea25a9ae3edfb2fd2c2aed2aa4d4f7e0487a8077a0b1ee30" -dependencies = [ - "env_logger 0.9.3", - "lazy_static", - "log", -] - -[[package]] -name = "solana-measure" -version = "1.16.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d171357580e62aa4ca19c780e25f4e74de064e2780cb8b9f6b6901d986fcd23" -dependencies = [ - "log", - "solana-sdk", -] - -[[package]] -name = "solana-metrics" -version = "1.16.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "013cbb3c82588278d2be18d3317ece5286cb54a3a06d5d38fc31e2a76a6d5e2d" -dependencies = [ - "crossbeam-channel", - "gethostname", - "lazy_static", - "log", - "reqwest", - "solana-sdk", -] - -[[package]] -name = "solana-program" -version = "1.16.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cff2aa5434a77413e9d43e971ceb47bdb003f2e8bbc0365a25b684aca2605c25" -dependencies = [ - "ark-bn254", - "ark-ec", - "ark-ff", - "ark-serialize", - "array-bytes", - "base64 0.21.4", - "bincode", - "bitflags 1.3.2", - "blake3", - "borsh 0.10.3", - "borsh 0.9.3", - "bs58 0.4.0", - "bv", - "bytemuck", - "cc", - "console_error_panic_hook", - "console_log", - "curve25519-dalek", - "getrandom 0.2.10", - "itertools 0.10.5", - "js-sys", - "lazy_static", - "libc", - "libsecp256k1", - "log", - "memoffset", - "num-bigint 0.4.4", - "num-derive 0.3.3", - "num-traits", - "parking_lot 0.12.1", - "rand 0.7.3", - "rand_chacha 0.2.2", - "rustc_version", - "rustversion", - "serde", - "serde_bytes", - "serde_derive", - "serde_json", - "sha2 0.10.8", - "sha3 0.10.8", - "solana-frozen-abi", - "solana-frozen-abi-macro", - "solana-sdk-macro", - "thiserror", - "tiny-bip39", - "wasm-bindgen", - "zeroize", -] - -[[package]] -name = "solana-program-runtime" -version = "1.16.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d1832fefc2187142dac169812518ec20da68b09abad86e4a78f8ae1787e4f56" -dependencies = [ - "base64 0.21.4", - "bincode", - "eager", - "enum-iterator", - "itertools 0.10.5", - "libc", - "log", - "num-derive 0.3.3", - "num-traits", - "percentage", - "rand 0.7.3", - "rustc_version", - "serde", - "solana-frozen-abi", - "solana-frozen-abi-macro", - "solana-measure", - "solana-metrics", - "solana-sdk", - "solana_rbpf", - "thiserror", -] - -[[package]] -name = "solana-sdk" -version = "1.16.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b1002048941cedbd7dd6a96fdaa3dc5238b998aaa70b81946b1e3ec108cc2be" -dependencies = [ - "assert_matches", - "base64 0.21.4", - "bincode", - "bitflags 1.3.2", - "borsh 0.10.3", - "bs58 0.4.0", - "bytemuck", - "byteorder", - "chrono", - "derivation-path", - "digest 0.10.7", - "ed25519-dalek", - "ed25519-dalek-bip32", - "generic-array", - "hmac 0.12.1", - "itertools 0.10.5", - "js-sys", - "lazy_static", - "libsecp256k1", - "log", - "memmap2", - "num-derive 0.3.3", - "num-traits", - "num_enum 0.6.1", - "pbkdf2 0.11.0", - "qstring", - "rand 0.7.3", - "rand_chacha 0.2.2", - "rustc_version", - "rustversion", - "serde", - "serde_bytes", - "serde_derive", - "serde_json", - "serde_with 2.3.3", - "sha2 0.10.8", - "sha3 0.10.8", - "solana-frozen-abi", - "solana-frozen-abi-macro", - "solana-logger", - "solana-program", - "solana-sdk-macro", - "thiserror", - "uriparse", - "wasm-bindgen", -] - -[[package]] -name = "solana-sdk-macro" -version = "1.16.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b41b63b2da4a37ce323aba108db21f4c7bfa638dd1bf58fdc870f83bdce48ba" -dependencies = [ - "bs58 0.4.0", - "proc-macro2", - "quote", - "rustversion", - "syn 2.0.38", -] - -[[package]] -name = "solana-transaction-status" -version = "1.16.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db0b811793e78a908119cc02edca3ff8b54d5660104ebd06cc0e2e7e2f66900b" -dependencies = [ - "Inflector", - "base64 0.21.4", - "bincode", - "borsh 0.10.3", - "bs58 0.4.0", - "lazy_static", - "log", - "serde", - "serde_derive", - "serde_json", - "solana-account-decoder", - "solana-address-lookup-table-program", - "solana-sdk", - "spl-associated-token-account", - "spl-memo 4.0.0", - "spl-token 4.0.0", - "spl-token-2022 0.9.0", - "thiserror", -] - -[[package]] -name = "solana-zk-token-sdk" -version = "1.16.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d1fe77918563768a65fd5d6cd2fa06cf0aeb11e529a1ef8c230b0fe018600e3" -dependencies = [ - "aes-gcm-siv", - "base64 0.21.4", - "bincode", - "bytemuck", - "byteorder", - "curve25519-dalek", - "getrandom 0.1.16", - "itertools 0.10.5", - "lazy_static", - "merlin", - "num-derive 0.3.3", - "num-traits", - "rand 0.7.3", - "serde", - "serde_json", - "sha3 0.9.1", - "solana-program", - "solana-sdk", - "subtle", - "thiserror", - "zeroize", -] - -[[package]] -name = "solana_rbpf" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17d4ba1e58947346e360fabde0697029d36ba83c42f669199b16a8931313cf29" -dependencies = [ - "byteorder", - "combine", - "goblin", - "hash32", - "libc", - "log", - "rand 0.8.5", - "rustc-demangle", - "scroll", - "thiserror", - "winapi", -] - -[[package]] -name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" - -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" - -[[package]] -name = "spl-account-compression" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df052fd79e45c75c84ef20f5f2dcf037aeed230d0f2400bf68fa388cc0ece240" -dependencies = [ - "anchor-lang", - "bytemuck", - "spl-concurrent-merkle-tree", - "spl-noop", -] - -[[package]] -name = "spl-associated-token-account" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "385e31c29981488f2820b2022d8e731aae3b02e6e18e2fd854e4c9a94dc44fc3" -dependencies = [ - "assert_matches", - "borsh 0.10.3", - "num-derive 0.4.1", - "num-traits", - "solana-program", - "spl-token 4.0.0", - "spl-token-2022 0.9.0", - "thiserror", -] - -[[package]] -name = "spl-concurrent-merkle-tree" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "141eaea58588beae81b71d101373a53f096737739873de42d6b1368bc2b8fc30" -dependencies = [ - "bytemuck", - "solana-program", - "thiserror", -] - -[[package]] -name = "spl-discriminator" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cce5d563b58ef1bb2cdbbfe0dfb9ffdc24903b10ae6a4df2d8f425ece375033f" -dependencies = [ - "bytemuck", - "solana-program", - "spl-discriminator-derive", -] - -[[package]] -name = "spl-discriminator-derive" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fadbefec4f3c678215ca72bd71862697bb06b41fd77c0088902dd3203354387b" -dependencies = [ - "quote", - "spl-discriminator-syn", - "syn 2.0.38", -] - -[[package]] -name = "spl-discriminator-syn" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e5f2044ca42c8938d54d1255ce599c79a1ffd86b677dfab695caa20f9ffc3f2" -dependencies = [ - "proc-macro2", - "quote", - "sha2 0.10.8", - "syn 2.0.38", - "thiserror", -] - -[[package]] -name = "spl-memo" -version = "3.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd0dc6f70db6bacea7ff25870b016a65ba1d1b6013536f08e4fd79a8f9005325" -dependencies = [ - "solana-program", -] - -[[package]] -name = "spl-memo" -version = "4.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f180b03318c3dbab3ef4e1e4d46d5211ae3c780940dd0a28695aba4b59a75a" -dependencies = [ - "solana-program", -] - -[[package]] -name = "spl-noop" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dd67ea3d0070a12ff141f5da46f9695f49384a03bce1203a5608f5739437950" -dependencies = [ - "solana-program", -] - -[[package]] -name = "spl-pod" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2881dddfca792737c0706fa0175345ab282b1b0879c7d877bad129645737c079" -dependencies = [ - "borsh 0.10.3", - "bytemuck", - "solana-program", - "solana-zk-token-sdk", - "spl-program-error", -] - -[[package]] -name = "spl-program-error" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "249e0318493b6bcf27ae9902600566c689b7dfba9f1bdff5893e92253374e78c" -dependencies = [ - "num-derive 0.4.1", - "num-traits", - "solana-program", - "spl-program-error-derive", - "thiserror", -] - -[[package]] -name = "spl-program-error-derive" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5269c8e868da17b6552ef35a51355a017bd8e0eae269c201fef830d35fa52c" -dependencies = [ - "proc-macro2", - "quote", - "sha2 0.10.8", - "syn 2.0.38", -] - -[[package]] -name = "spl-tlv-account-resolution" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "062e148d3eab7b165582757453632ffeef490c02c86a48bfdb4988f63eefb3b9" -dependencies = [ - "bytemuck", - "solana-program", - "spl-discriminator", - "spl-pod", - "spl-program-error", - "spl-type-length-value", -] - -[[package]] -name = "spl-token" -version = "3.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e85e168a785e82564160dcb87b2a8e04cee9bfd1f4d488c729d53d6a4bd300d" -dependencies = [ - "arrayref", - "bytemuck", - "num-derive 0.3.3", - "num-traits", - "num_enum 0.5.11", - "solana-program", - "thiserror", -] - -[[package]] -name = "spl-token" -version = "4.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08459ba1b8f7c1020b4582c4edf0f5c7511a5e099a7a97570c9698d4f2337060" -dependencies = [ - "arrayref", - "bytemuck", - "num-derive 0.3.3", - "num-traits", - "num_enum 0.6.1", - "solana-program", - "thiserror", -] - -[[package]] -name = "spl-token-2022" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0043b590232c400bad5ee9eb983ced003d15163c4c5d56b090ac6d9a57457b47" -dependencies = [ - "arrayref", - "bytemuck", - "num-derive 0.3.3", - "num-traits", - "num_enum 0.5.11", - "solana-program", - "solana-zk-token-sdk", - "spl-memo 3.0.1", - "spl-token 3.5.0", - "thiserror", -] - -[[package]] -name = "spl-token-2022" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4abf34a65ba420584a0c35f3903f8d727d1f13ababbdc3f714c6b065a686e86" -dependencies = [ - "arrayref", - "bytemuck", - "num-derive 0.4.1", - "num-traits", - "num_enum 0.7.0", - "solana-program", - "solana-zk-token-sdk", - "spl-memo 4.0.0", - "spl-pod", - "spl-token 4.0.0", - "spl-token-metadata-interface", - "spl-transfer-hook-interface", - "spl-type-length-value", - "thiserror", -] - -[[package]] -name = "spl-token-metadata-interface" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c16ce3ba6979645fb7627aa1e435576172dd63088dc7848cb09aa331fa1fe4f" -dependencies = [ - "borsh 0.10.3", - "solana-program", - "spl-discriminator", - "spl-pod", - "spl-program-error", - "spl-type-length-value", -] - -[[package]] -name = "spl-transfer-hook-interface" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "051d31803f873cabe71aec3c1b849f35248beae5d19a347d93a5c9cccc5d5a9b" -dependencies = [ - "arrayref", - "bytemuck", - "solana-program", - "spl-discriminator", - "spl-pod", - "spl-program-error", - "spl-tlv-account-resolution", - "spl-type-length-value", -] - -[[package]] -name = "spl-type-length-value" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a468e6f6371f9c69aae760186ea9f1a01c2908351b06a5e0026d21cfc4d7ecac" -dependencies = [ - "bytemuck", - "solana-program", - "spl-discriminator", - "spl-pod", - "spl-program-error", -] - -[[package]] -name = "sqlformat" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b7b278788e7be4d0d29c0f39497a0eef3fba6bbc8e70d8bf7fde46edeaa9e85" -dependencies = [ - "itertools 0.11.0", - "nom", - "unicode_categories", -] - -[[package]] -name = "sqlx" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8de3b03a925878ed54a954f621e64bf55a3c1bd29652d0d1a17830405350188" -dependencies = [ - "sqlx-core", - "sqlx-macros", -] - -[[package]] -name = "sqlx-core" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa8241483a83a3f33aa5fff7e7d9def398ff9990b2752b6c6112b83c6d246029" -dependencies = [ - "ahash 0.7.6", - "atoi", - "base64 0.13.1", - "bitflags 1.3.2", - "byteorder", - "bytes", - "chrono", - "crc", - "crossbeam-queue", - "dirs", - "dotenvy", - "either", - "event-listener", - "futures-channel", - "futures-core", - "futures-intrusive", - "futures-util", - "hashlink", - "hex", - "hkdf", - "hmac 0.12.1", - "indexmap 1.9.3", - "itoa", - "libc", - "log", - "md-5", - "memchr", - "num-bigint 0.4.4", - "once_cell", - "paste", - "percent-encoding", - "rand 0.8.5", - "rust_decimal", - "rustls 0.20.9", - "rustls-pemfile", - "serde", - "serde_json", - "sha1", - "sha2 0.10.8", - "smallvec", - "sqlformat", - "sqlx-rt", - "stringprep", - "thiserror", - "time", - "tokio-stream", - "url", - "uuid", - "webpki-roots 0.22.6", - "whoami", -] - -[[package]] -name = "sqlx-macros" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9966e64ae989e7e575b19d7265cb79d7fc3cbbdf179835cb0d716f294c2049c9" -dependencies = [ - "dotenvy", - "either", - "heck 0.4.1", - "hex", - "once_cell", - "proc-macro2", - "quote", - "serde", - "serde_json", - "sha2 0.10.8", - "sqlx-core", - "sqlx-rt", - "syn 1.0.109", - "url", -] - -[[package]] -name = "sqlx-rt" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "804d3f245f894e61b1e6263c84b23ca675d96753b5abfd5cc8597d86806e8024" -dependencies = [ - "once_cell", - "tokio", - "tokio-rustls 0.23.4", -] - -[[package]] -name = "stringprep" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb41d74e231a107a1b4ee36bd1214b11285b77768d2e3824aedafa988fd36ee6" -dependencies = [ - "finl_unicode", - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - -[[package]] -name = "subtle" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" - -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.38" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "system-configuration" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "system-configuration-sys", -] - -[[package]] -name = "system-configuration-sys" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "tap" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" - -[[package]] -name = "tempfile" -version = "3.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" -dependencies = [ - "cfg-if", - "fastrand", - "redox_syscall 0.3.5", - "rustix", - "windows-sys", -] - -[[package]] -name = "termcolor" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "thiserror" -version = "1.0.49" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.49" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.38", -] - -[[package]] -name = "time" -version = "0.3.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "426f806f4089c493dcac0d24c29c01e2c38baf8e30f1b716ee37e83d200b18fe" -dependencies = [ - "deranged", - "itoa", - "serde", - "time-core", - "time-macros", -] - -[[package]] -name = "time-core" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" - -[[package]] -name = "time-macros" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20" -dependencies = [ - "time-core", -] - -[[package]] -name = "tiny-bip39" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffc59cb9dfc85bb312c3a78fd6aa8a8582e310b0fa885d5bb877f6dcc601839d" -dependencies = [ - "anyhow", - "hmac 0.8.1", - "once_cell", - "pbkdf2 0.4.0", - "rand 0.7.3", - "rustc-hash", - "sha2 0.9.9", - "thiserror", - "unicode-normalization", - "wasm-bindgen", - "zeroize", -] - -[[package]] -name = "tinyvec" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - -[[package]] -name = "tokio" -version = "1.33.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f38200e3ef7995e5ef13baec2f432a6da0aa9ac495b2c0e8f3b7eec2c92d653" -dependencies = [ - "backtrace", - "bytes", - "libc", - "mio", - "num_cpus", - "parking_lot 0.12.1", - "pin-project-lite", - "signal-hook-registry", - "socket2 0.5.4", - "tokio-macros", - "windows-sys", -] - -[[package]] -name = "tokio-macros" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.38", -] - -[[package]] -name = "tokio-native-tls" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" -dependencies = [ - "native-tls", - "tokio", -] - -[[package]] -name = "tokio-postgres" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d340244b32d920260ae7448cb72b6e238bddc3d4f7603394e7dd46ed8e48f5b8" -dependencies = [ - "async-trait", - "byteorder", - "bytes", - "fallible-iterator", - "futures-channel", - "futures-util", - "log", - "parking_lot 0.12.1", - "percent-encoding", - "phf", - "pin-project-lite", - "postgres-protocol", - "postgres-types", - "rand 0.8.5", - "socket2 0.5.4", - "tokio", - "tokio-util", - "whoami", -] - -[[package]] -name = "tokio-rustls" -version = "0.23.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" -dependencies = [ - "rustls 0.20.9", - "tokio", - "webpki", -] - -[[package]] -name = "tokio-rustls" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" -dependencies = [ - "rustls 0.21.7", - "tokio", -] - -[[package]] -name = "tokio-stream" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" -dependencies = [ - "futures-core", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "tokio-util" -version = "0.7.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d68074620f57a0b21594d9735eb2e98ab38b17f80d3fcb189fca266771ca60d" -dependencies = [ - "bytes", - "futures-core", - "futures-io", - "futures-sink", - "pin-project-lite", - "tokio", - "tracing", -] - -[[package]] -name = "toml" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" -dependencies = [ - "serde", -] - -[[package]] -name = "toml_datetime" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" - -[[package]] -name = "toml_edit" -version = "0.19.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" -dependencies = [ - "indexmap 2.0.2", - "toml_datetime", - "winnow", -] - -[[package]] -name = "tower" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" -dependencies = [ - "futures-core", - "futures-util", - "hdrhistogram", - "indexmap 1.9.3", - "pin-project", - "pin-project-lite", - "rand 0.8.5", - "slab", - "tokio", - "tokio-util", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "tower-http" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f873044bf02dd1e8239e9c1293ea39dad76dc594ec16185d0a1bf31d8dc8d858" -dependencies = [ - "async-compression 0.3.15", - "base64 0.13.1", - "bitflags 1.3.2", - "bytes", - "futures-core", - "futures-util", - "http", - "http-body", - "http-range-header", - "httpdate", - "iri-string", - "mime", - "mime_guess", - "percent-encoding", - "pin-project-lite", - "tokio", - "tokio-util", - "tower", - "tower-layer", - "tower-service", - "tracing", - "uuid", -] - -[[package]] -name = "tower-layer" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" - -[[package]] -name = "tower-service" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" - -[[package]] -name = "tracing" -version = "0.1.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" -dependencies = [ - "cfg-if", - "log", - "pin-project-lite", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.38", -] - -[[package]] -name = "tracing-core" -version = "0.1.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" -dependencies = [ - "once_cell", -] - -[[package]] -name = "try-lock" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" - -[[package]] -name = "typenum" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" - -[[package]] -name = "uncased" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b9bc53168a4be7402ab86c3aad243a84dd7381d09be0eddc81280c1da95ca68" -dependencies = [ - "version_check", -] - -[[package]] -name = "unicase" -version = "2.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" -dependencies = [ - "version_check", -] - -[[package]] -name = "unicode-bidi" -version = "0.3.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" - -[[package]] -name = "unicode-ident" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "unicode-normalization" -version = "0.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" -dependencies = [ - "tinyvec", -] - -[[package]] -name = "unicode-segmentation" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" - -[[package]] -name = "unicode_categories" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" - -[[package]] -name = "universal-hash" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05" -dependencies = [ - "generic-array", - "subtle", -] - -[[package]] -name = "unreachable" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" -dependencies = [ - "void", -] - -[[package]] -name = "untrusted" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" - -[[package]] -name = "untrusted" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" - -[[package]] -name = "uriparse" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0200d0fc04d809396c2ad43f3c95da3582a2556eba8d453c1087f4120ee352ff" -dependencies = [ - "fnv", - "lazy_static", -] - -[[package]] -name = "url" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", -] - -[[package]] -name = "uuid" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d" -dependencies = [ - "getrandom 0.2.10", - "serde", -] - -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "void" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" - -[[package]] -name = "want" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" -dependencies = [ - "try-lock", -] - -[[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "wasm-bindgen" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" -dependencies = [ - "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" -dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn 2.0.38", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.38", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" - -[[package]] -name = "web-sys" -version = "0.3.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "webpki" -version = "0.22.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed63aea5ce73d0ff405984102c42de94fc55a6b75765d621c65262469b3c9b53" -dependencies = [ - "ring 0.17.2", - "untrusted 0.9.0", -] - -[[package]] -name = "webpki-roots" -version = "0.22.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87" -dependencies = [ - "webpki", -] - -[[package]] -name = "webpki-roots" -version = "0.25.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14247bb57be4f377dfb94c72830b8ce8fc6beac03cf4bf7b9732eadd414123fc" - -[[package]] -name = "whoami" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22fc3756b8a9133049b26c7f61ab35416c130e8c09b660f5b3958b446f52cc50" -dependencies = [ - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-util" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" -dependencies = [ - "winapi", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - -[[package]] -name = "winnow" -version = "0.5.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "037711d82167854aff2018dfd193aa0fef5370f456732f0d5a0c59b0f1b4b907" -dependencies = [ - "memchr", -] - -[[package]] -name = "winreg" -version = "0.50.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" -dependencies = [ - "cfg-if", - "windows-sys", -] - -[[package]] -name = "wyz" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" -dependencies = [ - "tap", -] - -[[package]] -name = "yansi" -version = "1.0.0-rc.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1367295b8f788d371ce2dbc842c7b709c73ee1364d30351dd300ec2203b12377" - -[[package]] -name = "zeroize" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd" -dependencies = [ - "zeroize_derive", -] - -[[package]] -name = "zeroize_derive" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.38", -] - -[[package]] -name = "zstd" -version = "0.11.2+zstd.1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" -dependencies = [ - "zstd-safe", -] - -[[package]] -name = "zstd-safe" -version = "5.0.2+zstd.1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" -dependencies = [ - "libc", - "zstd-sys", -] - -[[package]] -name = "zstd-sys" -version = "2.0.8+zstd.1.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5556e6ee25d32df2586c098bbfa278803692a20d0ab9565e049480d52707ec8c" -dependencies = [ - "cc", - "libc", - "pkg-config", -] diff --git a/das_api/src/error.rs b/das_api/src/error.rs index 3640da765..5b6feba25 100644 --- a/das_api/src/error.rs +++ b/das_api/src/error.rs @@ -2,6 +2,7 @@ use log::{debug, error}; use {jsonrpsee::core::Error as RpcError, jsonrpsee::types::error::CallError, thiserror::Error}; +#[allow(clippy::enum_variant_names)] #[derive(Error, Debug)] pub enum DasApiError { #[error("Config Missing or Error: {0}")] @@ -24,16 +25,16 @@ pub enum DasApiError { DeserializationError(#[from] serde_json::Error), } -impl Into for DasApiError { - fn into(self) -> RpcError { - match self { - Self::ValidationError(_) => { - debug!("{}", self); +impl From for RpcError { + fn from(error: DasApiError) -> RpcError { + match error { + DasApiError::ValidationError(_) => { + debug!("{}", error); } _ => { - error!("{}", self); + error!("{}", error); } } - RpcError::Call(CallError::from_std_error(self)) + RpcError::Call(CallError::from_std_error(error)) } } From 6a8c079d0102bb5dfb3d750613631685458d8ea5 Mon Sep 17 00:00:00 2001 From: Kirill Fomichev Date: Mon, 20 Nov 2023 13:33:25 -0500 Subject: [PATCH 06/23] rust: bump to 1.74.0 --- rust-toolchain.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 22048ac5b..639f4f17d 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,2 +1,2 @@ [toolchain] -channel = "1.70.0" +channel = "1.74.0" From 0dbabcd95de07ff5be6381bf0d602f685248bea0 Mon Sep 17 00:00:00 2001 From: Kirill Fomichev Date: Mon, 20 Nov 2023 13:34:16 -0500 Subject: [PATCH 07/23] rm metaplex-rpc-proxy/Cargo.lock --- metaplex-rpc-proxy/Cargo.lock | 234 ---------------------------------- 1 file changed, 234 deletions(-) delete mode 100644 metaplex-rpc-proxy/Cargo.lock diff --git a/metaplex-rpc-proxy/Cargo.lock b/metaplex-rpc-proxy/Cargo.lock deleted file mode 100644 index a9632d483..000000000 --- a/metaplex-rpc-proxy/Cargo.lock +++ /dev/null @@ -1,234 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "ahash" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" -dependencies = [ - "getrandom", - "once_cell", - "version_check", -] - -[[package]] -name = "aho-corasick" -version = "0.7.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e" -dependencies = [ - "memchr", -] - -[[package]] -name = "bumpalo" -version = "3.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "getrandom" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.11.0+wasi-snapshot-preview1", -] - -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" -dependencies = [ - "ahash", -] - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "libc" -version = "0.2.136" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55edcf6c0bb319052dea84732cf99db461780fd5e8d3eb46ab6ff312ab31f197" - -[[package]] -name = "log" -version = "0.4.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "memchr" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" - -[[package]] -name = "metaplex-rpc-proxy" -version = "0.6.8" -dependencies = [ - "lazy_static", - "log", - "proxy-wasm", - "regex", - "wasi 0.7.0", - "wasm-bindgen", -] - -[[package]] -name = "once_cell" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1" - -[[package]] -name = "proc-macro2" -version = "1.0.66" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "proxy-wasm" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3927081c2674366adadef4d5c5d34c4d849ab764a17bfe4ff2bd04436efb593d" -dependencies = [ - "hashbrown", - "log", -] - -[[package]] -name = "quote" -version = "1.0.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "regex" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.6.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" - -[[package]] -name = "syn" -version = "1.0.103" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "unicode-ident" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "wasi" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d" - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "wasm-bindgen" -version = "0.2.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" -dependencies = [ - "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" -dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" From 0ceda112305a655d4fea557e7d4c42f8dc527168 Mon Sep 17 00:00:00 2001 From: Kirill Fomichev Date: Mon, 20 Nov 2023 13:50:36 -0500 Subject: [PATCH 08/23] add global clippy lints --- Cargo.toml | 6 +++ das_api/Cargo.toml | 3 ++ das_api/src/api/api_impl.rs | 19 ++++---- digital_asset_types/Cargo.toml | 3 ++ digital_asset_types/src/dao/mod.rs | 2 +- digital_asset_types/src/rpc/asset.rs | 4 +- digital_asset_types/tests/get_asset_by_id.rs | 3 +- .../tests/get_assets_by_authority.rs | 9 ++-- .../tests/get_assets_by_creator.rs | 9 ++-- .../tests/get_assets_by_group.rs | 9 ++-- .../tests/get_assets_by_owner.rs | 9 ++-- metaplex-rpc-proxy/Cargo.toml | 3 ++ migration/Cargo.toml | 3 ++ nft_ingester/Cargo.toml | 3 ++ nft_ingester/src/ack.rs | 2 +- nft_ingester/src/backfiller.rs | 4 +- nft_ingester/src/metrics.rs | 2 +- .../src/program_transformers/bubblegum/db.rs | 2 +- nft_ingester/src/stream.rs | 2 +- nft_ingester/src/tasks/mod.rs | 18 +++----- tools/acc_forwarder/Cargo.toml | 3 ++ tools/bgtask_creator/Cargo.toml | 3 ++ tools/bgtask_creator/src/main.rs | 4 +- tools/fetch_trees/Cargo.toml | 3 ++ tools/load_generation/Cargo.toml | 3 ++ tools/load_generation/src/main.rs | 43 +++++++++++++------ tools/tree-status/Cargo.toml | 3 ++ tools/tree-status/src/main.rs | 2 +- tools/txn_forwarder/Cargo.toml | 3 ++ 29 files changed, 111 insertions(+), 71 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6a94be4ef..949618561 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,4 +1,5 @@ [workspace] +resolver = "2" members = [ "das_api", "digital_asset_types", @@ -13,6 +14,11 @@ members = [ "tools/txn_forwarder", ] +[workspace.lints.clippy] +clone_on_ref_ptr = "deny" +missing_const_for_fn = "deny" +trivially_copy_pass_by_ref = "deny" + [profile.release] lto = true codegen-units = 1 diff --git a/das_api/Cargo.toml b/das_api/Cargo.toml index c99d8b21a..22349f789 100644 --- a/das_api/Cargo.toml +++ b/das_api/Cargo.toml @@ -39,3 +39,6 @@ mpl-token-metadata = { version = "=2.0.0-beta.1", features = ["serde-feature"] mpl-candy-machine-core = { version = "2.0.1", features = ["no-entrypoint"] } mpl-bubblegum = "1.0.1-beta.3" mpl-candy-guard = { version = "2.0.0", features = ["no-entrypoint"] } + +[lints] +workspace = true diff --git a/das_api/src/api/api_impl.rs b/das_api/src/api/api_impl.rs index 5b98c1340..9b53bb0a3 100644 --- a/das_api/src/api/api_impl.rs +++ b/das_api/src/api/api_impl.rs @@ -48,8 +48,8 @@ impl DasApi { fn validate_pagination( &self, - limit: &Option, - page: &Option, + limit: Option, + page: Option, before: &Option, after: &Option, ) -> Result<(), DasApiError> { @@ -59,13 +59,13 @@ impl DasApi { if let Some(limit) = limit { // make config item - if *limit > 1000 { + if limit > 1000 { return Err(DasApiError::PaginationError); } } if let Some(page) = page { - if *page == 0 { + if page == 0 { return Err(DasApiError::PaginationEmptyError); } @@ -146,7 +146,7 @@ impl ApiContract for DasApi { let owner_address = validate_pubkey(owner_address.clone())?; let owner_address_bytes = owner_address.to_bytes().to_vec(); let sort_by = sort_by.unwrap_or_default(); - self.validate_pagination(&limit, &page, &before, &after)?; + self.validate_pagination(limit, page, &before, &after)?; get_assets_by_owner( &self.db_connection, owner_address_bytes, @@ -176,7 +176,7 @@ impl ApiContract for DasApi { let before: Option = before.filter(|before| !before.is_empty()); let after: Option = after.filter(|after| !after.is_empty()); let sort_by = sort_by.unwrap_or_default(); - self.validate_pagination(&limit, &page, &before, &after)?; + self.validate_pagination(limit, page, &before, &after)?; get_assets_by_group( &self.db_connection, group_key, @@ -207,7 +207,7 @@ impl ApiContract for DasApi { let creator_address = validate_pubkey(creator_address.clone())?; let creator_address_bytes = creator_address.to_bytes().to_vec(); - self.validate_pagination(&limit, &page, &before, &after)?; + self.validate_pagination(limit, page, &before, &after)?; let sort_by = sort_by.unwrap_or_default(); let only_verified = only_verified.unwrap_or_default(); get_assets_by_creator( @@ -240,7 +240,7 @@ impl ApiContract for DasApi { let authority_address = validate_pubkey(authority_address.clone())?; let authority_address_bytes = authority_address.to_bytes().to_vec(); - self.validate_pagination(&limit, &page, &before, &after)?; + self.validate_pagination(limit, page, &before, &after)?; get_assets_by_authority( &self.db_connection, authority_address_bytes, @@ -257,7 +257,6 @@ impl ApiContract for DasApi { async fn search_assets(&self, payload: SearchAssets) -> Result { let SearchAssets { negate, - /// Defaults to [ConditionType, condition_type, interface, owner_address, @@ -284,7 +283,7 @@ impl ApiContract for DasApi { json_uri, } = payload; // Deserialize search assets query - self.validate_pagination(&limit, &page, &before, &after)?; + self.validate_pagination(limit, page, &before, &after)?; let spec: Option<(SpecificationVersions, SpecificationAssetClass)> = interface.map(|x| x.into()); let specification_version = spec.clone().map(|x| x.0); diff --git a/digital_asset_types/Cargo.toml b/digital_asset_types/Cargo.toml index 8e4b18bb9..e3011ee6f 100644 --- a/digital_asset_types/Cargo.toml +++ b/digital_asset_types/Cargo.toml @@ -38,3 +38,6 @@ reqwest = "0.11.13" default = ["json_types", "sql_types"] json_types = ["serde", "serde_json"] sql_types = ["sea-orm"] + +[lints] +workspace = true diff --git a/digital_asset_types/src/dao/mod.rs b/digital_asset_types/src/dao/mod.rs index 889f57771..a49b0c903 100644 --- a/digital_asset_types/src/dao/mod.rs +++ b/digital_asset_types/src/dao/mod.rs @@ -57,7 +57,7 @@ pub struct SearchAssetsQuery { } impl SearchAssetsQuery { - pub fn count_conditions(&self) -> usize { + pub const fn count_conditions(&self) -> usize { // Initialize counter // todo ever heard of a flipping macro let mut num_conditions = 0; diff --git a/digital_asset_types/src/rpc/asset.rs b/digital_asset_types/src/rpc/asset.rs index 850b92d01..4ec4d4be3 100644 --- a/digital_asset_types/src/rpc/asset.rs +++ b/digital_asset_types/src/rpc/asset.rs @@ -121,11 +121,11 @@ pub type Files = Vec; pub struct MetadataMap(BTreeMap); impl MetadataMap { - pub fn new() -> Self { + pub const fn new() -> Self { Self(BTreeMap::new()) } - pub fn inner(&self) -> &BTreeMap { + pub const fn inner(&self) -> &BTreeMap { &self.0 } diff --git a/digital_asset_types/tests/get_asset_by_id.rs b/digital_asset_types/tests/get_asset_by_id.rs index 3a5bf14c6..f20b443d9 100644 --- a/digital_asset_types/tests/get_asset_by_id.rs +++ b/digital_asset_types/tests/get_asset_by_id.rs @@ -33,8 +33,7 @@ async fn get_asset_by_id() -> Result<(), DbErr> { address: creator_1, share: 100, verified: true, - }] - .to_vec(), + }], seller_fee_basis_points: 100, }; diff --git a/digital_asset_types/tests/get_assets_by_authority.rs b/digital_asset_types/tests/get_assets_by_authority.rs index 921bf7176..5796c6c55 100644 --- a/digital_asset_types/tests/get_assets_by_authority.rs +++ b/digital_asset_types/tests/get_assets_by_authority.rs @@ -44,8 +44,7 @@ async fn get_assets_by_owner() -> Result<(), DbErr> { address: creator_1, share: 100, verified: true, - }] - .to_vec(), + }], seller_fee_basis_points: 100, }; @@ -97,8 +96,7 @@ async fn get_assets_by_owner() -> Result<(), DbErr> { address: creator_2, share: 100, verified: true, - }] - .to_vec(), + }], seller_fee_basis_points: 100, }; @@ -157,8 +155,7 @@ async fn get_assets_by_owner() -> Result<(), DbErr> { share: 90, verified: true, }, - ] - .to_vec(), + ], seller_fee_basis_points: 100, }; diff --git a/digital_asset_types/tests/get_assets_by_creator.rs b/digital_asset_types/tests/get_assets_by_creator.rs index c282be6ad..6bcf85c9c 100644 --- a/digital_asset_types/tests/get_assets_by_creator.rs +++ b/digital_asset_types/tests/get_assets_by_creator.rs @@ -47,8 +47,7 @@ async fn get_assets_by_creator() -> Result<(), DbErr> { address: creator_1, share: 100, verified: true, - }] - .to_vec(), + }], seller_fee_basis_points: 100, }; @@ -100,8 +99,7 @@ async fn get_assets_by_creator() -> Result<(), DbErr> { address: creator_2, share: 100, verified: true, - }] - .to_vec(), + }], seller_fee_basis_points: 100, }; @@ -160,8 +158,7 @@ async fn get_assets_by_creator() -> Result<(), DbErr> { share: 90, verified: true, }, - ] - .to_vec(), + ], seller_fee_basis_points: 100, }; diff --git a/digital_asset_types/tests/get_assets_by_group.rs b/digital_asset_types/tests/get_assets_by_group.rs index 7788a1041..b8bdb35ad 100644 --- a/digital_asset_types/tests/get_assets_by_group.rs +++ b/digital_asset_types/tests/get_assets_by_group.rs @@ -49,8 +49,7 @@ async fn get_assets_by_group() -> Result<(), DbErr> { address: creator_1, share: 100, verified: true, - }] - .to_vec(), + }], seller_fee_basis_points: 100, }; @@ -102,8 +101,7 @@ async fn get_assets_by_group() -> Result<(), DbErr> { address: creator_2, share: 100, verified: true, - }] - .to_vec(), + }], seller_fee_basis_points: 100, }; @@ -164,8 +162,7 @@ async fn get_assets_by_group() -> Result<(), DbErr> { share: 90, verified: true, }, - ] - .to_vec(), + ], seller_fee_basis_points: 100, }; diff --git a/digital_asset_types/tests/get_assets_by_owner.rs b/digital_asset_types/tests/get_assets_by_owner.rs index 921bf7176..5796c6c55 100644 --- a/digital_asset_types/tests/get_assets_by_owner.rs +++ b/digital_asset_types/tests/get_assets_by_owner.rs @@ -44,8 +44,7 @@ async fn get_assets_by_owner() -> Result<(), DbErr> { address: creator_1, share: 100, verified: true, - }] - .to_vec(), + }], seller_fee_basis_points: 100, }; @@ -97,8 +96,7 @@ async fn get_assets_by_owner() -> Result<(), DbErr> { address: creator_2, share: 100, verified: true, - }] - .to_vec(), + }], seller_fee_basis_points: 100, }; @@ -157,8 +155,7 @@ async fn get_assets_by_owner() -> Result<(), DbErr> { share: 90, verified: true, }, - ] - .to_vec(), + ], seller_fee_basis_points: 100, }; diff --git a/metaplex-rpc-proxy/Cargo.toml b/metaplex-rpc-proxy/Cargo.toml index f48977d96..fb7e11c46 100644 --- a/metaplex-rpc-proxy/Cargo.toml +++ b/metaplex-rpc-proxy/Cargo.toml @@ -14,3 +14,6 @@ lazy_static = "1.4.0" regex = "1.6.0" log = "0.4.17" wasi = "0.7.0" + +[lints] +workspace = true diff --git a/migration/Cargo.toml b/migration/Cargo.toml index a7f6a9f94..f5eb28161 100644 --- a/migration/Cargo.toml +++ b/migration/Cargo.toml @@ -20,3 +20,6 @@ features = [ "runtime-tokio-rustls", "sqlx-postgres", ] + +[lints] +workspace = true diff --git a/nft_ingester/Cargo.toml b/nft_ingester/Cargo.toml index 6fb9f998c..bedda13c7 100644 --- a/nft_ingester/Cargo.toml +++ b/nft_ingester/Cargo.toml @@ -63,3 +63,6 @@ clap = { version = "4.2.2", features = ["derive", "cargo"] } [dependencies.num-integer] version = "0.1.44" default-features = false + +[lints] +workspace = true diff --git a/nft_ingester/src/ack.rs b/nft_ingester/src/ack.rs index 0b64fa12d..5601b7ec4 100644 --- a/nft_ingester/src/ack.rs +++ b/nft_ingester/src/ack.rs @@ -41,7 +41,7 @@ pub fn ack_worker( } Some(msg) = rx.recv() => { let (stream, msg) = msg; - let ackstream = acks.entry(stream).or_insert_with(Vec::::new); + let ackstream = acks.entry(stream).or_default(); ackstream.push(msg); } } diff --git a/nft_ingester/src/backfiller.rs b/nft_ingester/src/backfiller.rs index 6a9b1a4c3..f9b014493 100644 --- a/nft_ingester/src/backfiller.rs +++ b/nft_ingester/src/backfiller.rs @@ -147,7 +147,7 @@ struct BackfillTree { } impl BackfillTree { - fn new(unique_tree: UniqueTree, backfill_from_seq_1: bool, slot: u64) -> Self { + const fn new(unique_tree: UniqueTree, backfill_from_seq_1: bool, slot: u64) -> Self { Self { unique_tree, backfill_from_seq_1, @@ -177,7 +177,7 @@ struct GapInfo { } impl GapInfo { - fn new(prev: SimpleBackfillItem, curr: SimpleBackfillItem) -> Self { + const fn new(prev: SimpleBackfillItem, curr: SimpleBackfillItem) -> Self { Self { prev, curr } } } diff --git a/nft_ingester/src/metrics.rs b/nft_ingester/src/metrics.rs index 2f5dde2b3..2e4ebb0d8 100644 --- a/nft_ingester/src/metrics.rs +++ b/nft_ingester/src/metrics.rs @@ -63,7 +63,7 @@ pub fn capture_result( } true } - Err(err) if err == IngesterError::NotImplemented => { + Err(IngesterError::NotImplemented) => { metric! { statsd_count!("ingester.not_implemented", 1, label.0 => label.1, "stream" => stream, "error" => "ni"); } diff --git a/nft_ingester/src/program_transformers/bubblegum/db.rs b/nft_ingester/src/program_transformers/bubblegum/db.rs index c562be2be..b7141e231 100644 --- a/nft_ingester/src/program_transformers/bubblegum/db.rs +++ b/nft_ingester/src/program_transformers/bubblegum/db.rs @@ -23,7 +23,7 @@ where Ok(change_log_event.seq) } -fn node_idx_to_leaf_idx(index: i64, tree_height: u32) -> i64 { +const fn node_idx_to_leaf_idx(index: i64, tree_height: u32) -> i64 { index - 2i64.pow(tree_height) } diff --git a/nft_ingester/src/stream.rs b/nft_ingester/src/stream.rs index 46afbf5b4..34d2293e8 100644 --- a/nft_ingester/src/stream.rs +++ b/nft_ingester/src/stream.rs @@ -15,7 +15,7 @@ pub struct StreamSizeTimer { } impl StreamSizeTimer { - pub fn new( + pub const fn new( interval: Duration, messenger_config: MessengerConfig, stream: &'static str, diff --git a/nft_ingester/src/tasks/mod.rs b/nft_ingester/src/tasks/mod.rs index d7b5ceaef..ec7a813fe 100644 --- a/nft_ingester/src/tasks/mod.rs +++ b/nft_ingester/src/tasks/mod.rs @@ -317,7 +317,7 @@ impl TaskManager { pub fn start_listener(&mut self, process_on_receive: bool) -> JoinHandle<()> { let (producer, mut receiver) = mpsc::unbounded_channel::(); self.producer = Some(producer); - let task_map = self.registered_task_types.clone(); + let task_map = Arc::clone(&self.registered_task_types); let pool = self.pool.clone(); let instance_name = self.instance_name.clone(); @@ -351,7 +351,7 @@ impl TaskManager { instance_name.clone(), name, task, - task_map.clone(), + Arc::clone(&task_map), process_on_receive, ); } @@ -360,7 +360,7 @@ impl TaskManager { } pub fn start_runner(&self, config: Option) -> JoinHandle<()> { - let task_map = self.registered_task_types.clone(); + let task_map = Arc::clone(&self.registered_task_types); let instance_name = self.instance_name.clone(); // Load the config values @@ -428,22 +428,18 @@ impl TaskManager { match tasks_res { Ok(tasks) => { debug!("tasks that need to be executed: {}", tasks.len()); - let _task_map_clone = task_map.clone(); - let instance_name = instance_name.clone(); for task in tasks { - let task_map_clone = task_map.clone(); - let instance_name_clone = instance_name.clone(); + let task_map = Arc::clone(&task_map); + let instance_name = instance_name.clone(); let pool = pool.clone(); tokio::task::spawn(async move { - if let Some(task_executor) = - task_map_clone.clone().get(&*task.task_type) - { + if let Some(task_executor) = task_map.get(&*task.task_type) { let conn = SqlxPostgresConnector::from_sqlx_postgres_pool(pool); let mut active_model: tasks::ActiveModel = task.into(); TaskManager::lock_task( &mut active_model, Duration::seconds(task_executor.lock_duration()), - instance_name_clone, + instance_name, ); // can ignore as txn will bubble up errors let active_model = diff --git a/tools/acc_forwarder/Cargo.toml b/tools/acc_forwarder/Cargo.toml index 04e0ee842..89597dff4 100644 --- a/tools/acc_forwarder/Cargo.toml +++ b/tools/acc_forwarder/Cargo.toml @@ -27,3 +27,6 @@ solana-transaction-status = "~1.16.16" spl-token = { version = ">= 3.5.0, < 5.0", features = ["no-entrypoint"] } tokio = { version = "1.23.0", features = ["macros", "rt-multi-thread", "time"] } txn_forwarder = { path = "../txn_forwarder" } + +[lints] +workspace = true diff --git a/tools/bgtask_creator/Cargo.toml b/tools/bgtask_creator/Cargo.toml index d2f95f151..a262f7ddb 100644 --- a/tools/bgtask_creator/Cargo.toml +++ b/tools/bgtask_creator/Cargo.toml @@ -19,3 +19,6 @@ solana-sdk = "~1.16.16" sqlx = { version = "0.6.2", features = ["macros", "runtime-tokio-rustls", "postgres", "uuid", "offline", "json"] } tokio = { version = "1.23.0", features = ["macros", "rt-multi-thread"] } txn_forwarder = { path = "../txn_forwarder" } + +[lints] +workspace = true diff --git a/tools/bgtask_creator/src/main.rs b/tools/bgtask_creator/src/main.rs index a08dd87d1..35058b42c 100644 --- a/tools/bgtask_creator/src/main.rs +++ b/tools/bgtask_creator/src/main.rs @@ -332,7 +332,7 @@ WHERE let name = instance_name.clone(); if let Ok(hash) = task_data.hash() { let database_pool = database_pool.clone(); - let task_map = task_map.clone(); + let task_map = Arc::clone(&task_map); let name = name.clone(); let tp = asset_data.1.clone(); let new_task = tokio::task::spawn(async move { @@ -360,7 +360,7 @@ WHERE name.clone(), name, task_data, - task_map.clone(), + Arc::clone(&task_map), false, ) .await; diff --git a/tools/fetch_trees/Cargo.toml b/tools/fetch_trees/Cargo.toml index 4035014ca..a6674d905 100644 --- a/tools/fetch_trees/Cargo.toml +++ b/tools/fetch_trees/Cargo.toml @@ -15,3 +15,6 @@ solana-client = "~1.16.16" solana-sdk = "~1.16.16" spl-account-compression = { version = "0.2.0", features = ["no-entrypoint"] } tokio = { version = "1.26.0", features = ["full", "tracing"] } + +[lints] +workspace = true diff --git a/tools/load_generation/Cargo.toml b/tools/load_generation/Cargo.toml index 2f9452300..c9e1a905a 100644 --- a/tools/load_generation/Cargo.toml +++ b/tools/load_generation/Cargo.toml @@ -14,3 +14,6 @@ solana-sdk = "~1.16.16" spl-associated-token-account = { version = ">= 1.1.3, < 3.0", features = ["no-entrypoint"] } spl-token = { version = ">= 3.5.0, < 5.0", features = ["no-entrypoint"] } tokio = { version ="1.25.0", features = ["macros", "rt-multi-thread"] } + +[lints] +workspace = true diff --git a/tools/load_generation/src/main.rs b/tools/load_generation/src/main.rs index b2b52f99b..d6bf340bf 100644 --- a/tools/load_generation/src/main.rs +++ b/tools/load_generation/src/main.rs @@ -36,19 +36,28 @@ async fn main() { ); let kp_new = Arc::new(Keypair::new()); let semaphore = Arc::new(Semaphore::new(carnage)); - let _ = check_balance(le_blockchain.clone(), kp.clone(), network != "mainnet").await; - let nft_collection_thing = - make_a_nft_thing(le_blockchain.clone(), kp.clone(), kp.clone(), None) - .await - .unwrap(); + let _ = check_balance( + Arc::clone(&le_blockchain), + Arc::clone(&kp), + network != "mainnet", + ) + .await; + let nft_collection_thing = make_a_nft_thing( + Arc::clone(&le_blockchain), + Arc::clone(&kp), + Arc::clone(&kp), + None, + ) + .await + .unwrap(); println!("NFT Collection Thing: {:?}", nft_collection_thing); loop { let mut tasks = vec![]; for _ in 0..carnage { - let kp = kp.clone(); - let kp_new = kp_new.clone(); - let le_clone = le_blockchain.clone(); - let semaphore = semaphore.clone(); + let kp = Arc::clone(&kp); + let kp_new = Arc::clone(&kp_new); + let le_clone = Arc::clone(&le_blockchain); + let semaphore = Arc::clone(&semaphore); tasks.push(tokio::spawn(async move { let _permit = semaphore.acquire().await.unwrap(); //wait for le government to allow le action // MINT A MASTER EDITION: @@ -68,7 +77,12 @@ async fn main() { } } } - let _ = check_balance(le_blockchain.clone(), kp.clone(), network != "mainnet").await; + let _ = check_balance( + Arc::clone(&le_blockchain), + Arc::clone(&kp), + network != "mainnet", + ) + .await; } } @@ -150,8 +164,13 @@ pub async fn make_a_nft_thing( owner: Arc, collection_mint: Option, ) -> Result { - let (mint, _token_account) = - make_a_token_thing(solana_client.clone(), payer.clone(), owner.clone(), 1).await?; + let (mint, _token_account) = make_a_token_thing( + Arc::clone(&solana_client), + Arc::clone(&payer), + Arc::clone(&owner), + 1, + ) + .await?; let prg_uid = mpl_token_metadata::id(); let _metadata_seeds = &[ mpl_token_metadata::state::PREFIX.as_bytes(), diff --git a/tools/tree-status/Cargo.toml b/tools/tree-status/Cargo.toml index 52abc07e5..00c826ebc 100644 --- a/tools/tree-status/Cargo.toml +++ b/tools/tree-status/Cargo.toml @@ -30,3 +30,6 @@ sqlx = { version = "0.6.2", features = ["macros", "runtime-tokio-rustls", "postg thiserror = "1.0.31" tokio = { version = "1.23.0", features = ["fs", "macros", "rt-multi-thread", "sync", "time"] } txn_forwarder = { path = "../txn_forwarder" } + +[lints] +workspace = true diff --git a/tools/tree-status/src/main.rs b/tools/tree-status/src/main.rs index e829bcb4c..3b73fe43c 100644 --- a/tools/tree-status/src/main.rs +++ b/tools/tree-status/src/main.rs @@ -815,6 +815,6 @@ fn parse_tx_sequence( Ok(seq_updates) } -fn node_idx_to_leaf_idx(index: i64, tree_height: u32) -> i64 { +const fn node_idx_to_leaf_idx(index: i64, tree_height: u32) -> i64 { index - 2i64.pow(tree_height) } diff --git a/tools/txn_forwarder/Cargo.toml b/tools/txn_forwarder/Cargo.toml index f66f27bd6..f15510ba9 100644 --- a/tools/txn_forwarder/Cargo.toml +++ b/tools/txn_forwarder/Cargo.toml @@ -24,3 +24,6 @@ solana-transaction-status = "~1.16.16" thiserror = "1.0.31" tokio = { version = "1.23.0", features = ["macros", "rt-multi-thread", "sync", "time", "fs"] } tokio-stream = { version = "0.1.14", features = ["io-util"] } + +[lints] +workspace = true From 27f9e7964c2cde48c3413aec5cb2092ab671c2d6 Mon Sep 17 00:00:00 2001 From: Kirill Fomichev Date: Mon, 20 Nov 2023 15:27:59 -0500 Subject: [PATCH 09/23] use workspace --- Cargo.lock | 276 +++++++++++++++---------------- Cargo.toml | 93 +++++++++++ das_api/Cargo.toml | 74 ++++----- digital_asset_types/Cargo.toml | 57 +++---- metaplex-rpc-proxy/Cargo.toml | 17 +- migration/Cargo.toml | 27 +-- nft_ingester/Cargo.toml | 116 ++++++------- tools/acc_forwarder/Cargo.toml | 49 +++--- tools/bgtask_creator/Cargo.toml | 33 ++-- tools/fetch_trees/Cargo.toml | 25 +-- tools/load_generation/Cargo.toml | 23 +-- tools/tree-status/Cargo.toml | 51 +++--- tools/txn_forwarder/Cargo.toml | 43 ++--- 13 files changed, 473 insertions(+), 411 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2f025fb6e..bd2dc1e7f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -18,7 +18,7 @@ version = "0.7.12" dependencies = [ "anyhow", "bs58 0.4.0", - "clap 4.4.6", + "clap 4.4.8", "env_logger 0.10.0", "figment", "flatbuffers", @@ -600,22 +600,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" dependencies = [ "concurrent-queue", - "event-listener", + "event-listener 2.5.3", "futures-core", ] [[package]] -name = "async-compression" -version = "0.3.15" +name = "async-channel" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "942c7cd7ae39e91bde4820d74132e9862e62c2f386c3aa90ccf55949f5bad63a" +checksum = "d37875bd9915b7d67c2f117ea2c30a0989874d0b2cb694fe25403c85763c0c9e" dependencies = [ - "brotli", - "flate2", + "concurrent-queue", + "event-listener 3.1.0", + "event-listener-strategy", "futures-core", - "memchr", "pin-project-lite", - "tokio", ] [[package]] @@ -634,15 +633,15 @@ dependencies = [ [[package]] name = "async-executor" -version = "1.6.0" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b0c4a4f319e45986f347ee47fef8bf5e81c9abc3f6f58dc2391439f30df65f0" +checksum = "fc5ea910c42e5ab19012bab31f53cb4d63d54c3a27730f9a833a88efcf4bb52d" dependencies = [ - "async-lock", + "async-lock 3.1.1", "async-task", "concurrent-queue", "fastrand 2.0.1", - "futures-lite", + "futures-lite 2.0.1", "slab", ] @@ -652,12 +651,12 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1b6f5d7df27bd294849f8eec66ecfc63d11814df7a4f5d74168a2394467b776" dependencies = [ - "async-channel", + "async-channel 1.9.0", "async-executor", "async-io", - "async-lock", + "async-lock 2.8.0", "blocking", - "futures-lite", + "futures-lite 1.13.0", "once_cell", "tokio", ] @@ -668,15 +667,15 @@ version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" dependencies = [ - "async-lock", + "async-lock 2.8.0", "autocfg", "cfg-if", "concurrent-queue", - "futures-lite", + "futures-lite 1.13.0", "log", "parking", "polling", - "rustix 0.37.24", + "rustix 0.37.27", "slab", "socket2 0.4.9", "waker-fn", @@ -688,7 +687,18 @@ version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" dependencies = [ - "event-listener", + "event-listener 2.5.3", +] + +[[package]] +name = "async-lock" +version = "3.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "655b9c7fe787d3b25cc0f804a1a8401790f0c5bc395beb5a64dc77d8de079105" +dependencies = [ + "event-listener 3.1.0", + "event-listener-strategy", + "pin-project-lite", ] [[package]] @@ -697,7 +707,7 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479db852db25d9dbf6204e6cb6253698f175c15726470f78af0d918e99d6156e" dependencies = [ - "event-listener", + "event-listener 2.5.3", ] [[package]] @@ -707,15 +717,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d" dependencies = [ "async-attributes", - "async-channel", + "async-channel 1.9.0", "async-global-executor", "async-io", - "async-lock", + "async-lock 2.8.0", "crossbeam-utils", "futures-channel", "futures-core", "futures-io", - "futures-lite", + "futures-lite 1.13.0", "gloo-timers", "kv-log-macro", "log", @@ -879,7 +889,7 @@ name = "bgtask_creator" version = "0.7.12" dependencies = [ "anyhow", - "clap 4.4.6", + "clap 4.4.8", "digital_asset_types", "futures", "lazy_static", @@ -1002,16 +1012,16 @@ dependencies = [ [[package]] name = "blocking" -version = "1.4.1" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c36a4d0d48574b3dd360b4b7d95cc651d2b6557b6402848a27d4b228a473e2a" +checksum = "6a37913e8dc4ddcc604f0c6d3bf2887c995153af3611de9e23c352b44c1b9118" dependencies = [ - "async-channel", - "async-lock", + "async-channel 2.1.0", + "async-lock 3.1.1", "async-task", "fastrand 2.0.1", "futures-io", - "futures-lite", + "futures-lite 2.0.1", "piper", "tracing", ] @@ -1324,23 +1334,23 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.6" +version = "4.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d04704f56c2cde07f43e8e2c154b43f216dc5c92fc98ada720177362f953b956" +checksum = "2275f18819641850fa26c89acc84d465c1bf91ce57bc2748b28c420473352f64" dependencies = [ "clap_builder", - "clap_derive 4.4.2", + "clap_derive 4.4.7", ] [[package]] name = "clap_builder" -version = "4.4.6" +version = "4.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e231faeaca65ebd1ea3c737966bf858971cd38c3849107aa3ea7de90a804e45" +checksum = "07cdf1b148b25c1e1f7a42225e30a0d99a615cd4637eae7365548dd4529b95bc" dependencies = [ "anstream", "anstyle", - "clap_lex 0.5.1", + "clap_lex 0.6.0", "strsim 0.10.0", ] @@ -1359,9 +1369,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.4.2" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873" +checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" dependencies = [ "heck 0.4.1", "proc-macro2 1.0.69", @@ -1380,9 +1390,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961" +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" [[package]] name = "colorchoice" @@ -1786,6 +1796,12 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "deunicode" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a1abaf4d861455be59f64fd2b55606cb151fce304ede7165f410243ce96bde6" + [[package]] name = "dialoguer" version = "0.10.4" @@ -1824,8 +1840,6 @@ version = "0.7.2" dependencies = [ "async-trait", "blockbuster", - "borsh 0.10.3", - "borsh-derive 0.10.3", "bs58 0.4.0", "futures", "indexmap 1.9.3", @@ -2047,14 +2061,35 @@ version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" +[[package]] +name = "event-listener" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d93877bcde0eb80ca09131a08d23f0a5c18a620b01db137dba666d18cd9b30c2" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d96b852f1345da36d551b9473fa1e2b1eb5c5195585c6c018118bc92a8d91160" +dependencies = [ + "event-listener 3.1.0", + "pin-project-lite", +] + [[package]] name = "fake" -version = "2.8.0" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9af7b0c58ac9d03169e27f080616ce9f64004edca3d2ef4147a811c21b23b319" +checksum = "26221445034074d46b276e13eb97a265ebdb8ed8da705c4dddd3dd20b66b45d2" dependencies = [ + "deunicode", "rand 0.8.5", - "unidecode", ] [[package]] @@ -2091,7 +2126,7 @@ dependencies = [ "anyhow", "async-trait", "borsh 0.10.3", - "clap 4.4.6", + "clap 4.4.8", "mpl-bubblegum", "solana-account-decoder", "solana-client", @@ -2110,7 +2145,7 @@ dependencies = [ "pear", "serde", "serde_yaml", - "toml 0.8.2", + "toml 0.8.8", "uncased", "version_check", ] @@ -2257,6 +2292,20 @@ dependencies = [ "waker-fn", ] +[[package]] +name = "futures-lite" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3831c2651acb5177cbd83943f3d9c8912c5ad03c76afcc0e9511ba568ec5ebb" +dependencies = [ + "fastrand 2.0.1", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite", +] + [[package]] name = "futures-macro" version = "0.3.28" @@ -2467,16 +2516,6 @@ dependencies = [ "hashbrown 0.14.1", ] -[[package]] -name = "hdrhistogram" -version = "7.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "765c9198f173dd59ce26ff9f95ef0aafd0a0fe01fb9d72841bc5066a4c06511d" -dependencies = [ - "byteorder", - "num-traits", -] - [[package]] name = "heck" version = "0.3.3" @@ -2778,15 +2817,6 @@ version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" -[[package]] -name = "iri-string" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f0f7638c1e223529f1bfdc48c8b133b9e0b434094d1d28473161ee48b235f78" -dependencies = [ - "nom", -] - [[package]] name = "is-terminal" version = "0.4.9" @@ -3399,7 +3429,7 @@ dependencies = [ "cadence", "cadence-macros", "chrono", - "clap 4.4.6", + "clap 4.4.8", "digital_asset_types", "env_logger 0.10.0", "figment", @@ -3765,9 +3795,9 @@ dependencies = [ [[package]] name = "os_str_bytes" -version = "6.5.1" +version = "6.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d5d9eb14b174ee9aa2ef96dc2b94637a2d4b6e7cb873c7e171f0c20c6cf3eac" +checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" [[package]] name = "ouroboros" @@ -3800,9 +3830,9 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "parking" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e52c774a4c39359c1d1c52e43f73dd91a75a614652c825408eec30c95a9b2067" +checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" [[package]] name = "parking_lot" @@ -3941,26 +3971,6 @@ dependencies = [ "siphasher", ] -[[package]] -name = "pin-project" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" -dependencies = [ - "proc-macro2 1.0.69", - "quote 1.0.33", - "syn 2.0.38", -] - [[package]] name = "pin-project-lite" version = "0.2.13" @@ -4598,7 +4608,7 @@ version = "0.11.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" dependencies = [ - "async-compression 0.4.3", + "async-compression", "base64 0.21.4", "bytes", "encoding_rs", @@ -4718,23 +4728,23 @@ dependencies = [ [[package]] name = "rpassword" -version = "7.2.0" +version = "7.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6678cf63ab3491898c0d021b493c94c9b221d91295294a2a5746eacbe5928322" +checksum = "80472be3c897911d0137b2d2b9055faf6eeac5b14e324073d83bc17b191d7e3f" dependencies = [ "libc", "rtoolbox", - "winapi", + "windows-sys 0.48.0", ] [[package]] name = "rtoolbox" -version = "0.0.1" +version = "0.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "034e22c514f5c0cb8a10ff341b9b048b5ceb21591f31c8f44c43b960f9b3524a" +checksum = "c247d24e63230cdb56463ae328478bd5eac8b8faa8c69461a77e8e323afac90e" dependencies = [ "libc", - "winapi", + "windows-sys 0.48.0", ] [[package]] @@ -4804,9 +4814,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.24" +version = "0.37.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4279d76516df406a8bd37e7dff53fd37d1a093f997a3c34a5c21658c126db06d" +checksum = "fea8ca367a3a01fe35e6943c400addf443c0f57670e6ec51196f71a4b8762dd2" dependencies = [ "bitflags 1.3.2", "errno", @@ -5236,9 +5246,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186" +checksum = "12022b835073e5b11e90a14f86838ceb1c8fb0325b72416845c487ac0fa95e80" dependencies = [ "serde", ] @@ -6120,7 +6130,7 @@ version = "1.16.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f00e575f2bd5ae2776870fbd1d7379d4ad392c015e2a4e2a328953b821a9d36d" dependencies = [ - "async-channel", + "async-channel 1.9.0", "bytes", "crossbeam-channel", "futures-util", @@ -6641,7 +6651,7 @@ dependencies = [ "dirs", "dotenvy", "either", - "event-listener", + "event-listener 2.5.3", "futures-channel", "futures-core", "futures-intrusive", @@ -6726,7 +6736,7 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6bcb902b974bc20b50c3ad3148022a366a46c9a676b587684ff46c237a3329e" dependencies = [ - "async-channel", + "async-channel 1.9.0", "async-io", "atomic 0.5.3", "crossbeam-channel", @@ -7121,21 +7131,21 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.2" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d" +checksum = "a1a195ec8c9da26928f773888e0742ca3ca1040c6cd859c919c9f59c1954ab35" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.20.2", + "toml_edit 0.21.0", ] [[package]] name = "toml_datetime" -version = "0.6.3" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" dependencies = [ "serde", ] @@ -7153,9 +7163,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.20.2" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" +checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" dependencies = [ "indexmap 2.0.2", "serde", @@ -7170,16 +7180,6 @@ version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" dependencies = [ - "futures-core", - "futures-util", - "hdrhistogram", - "indexmap 1.9.3", - "pin-project", - "pin-project-lite", - "rand 0.8.5", - "slab", - "tokio", - "tokio-util", "tower-layer", "tower-service", "tracing", @@ -7191,8 +7191,6 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f873044bf02dd1e8239e9c1293ea39dad76dc594ec16185d0a1bf31d8dc8d858" dependencies = [ - "async-compression 0.3.15", - "base64 0.13.1", "bitflags 1.3.2", "bytes", "futures-core", @@ -7200,19 +7198,9 @@ dependencies = [ "http", "http-body", "http-range-header", - "httpdate", - "iri-string", - "mime", - "mime_guess", - "percent-encoding", "pin-project-lite", - "tokio", - "tokio-util", - "tower", "tower-layer", "tower-service", - "tracing", - "uuid", ] [[package]] @@ -7263,12 +7251,12 @@ dependencies = [ [[package]] name = "tracing-log" -version = "0.1.3" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" dependencies = [ - "lazy_static", "log", + "once_cell", "tracing-core", ] @@ -7284,9 +7272,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" dependencies = [ "matchers", "nu-ansi-term", @@ -7310,7 +7298,7 @@ dependencies = [ "anchor-client", "anyhow", "bs58 0.4.0", - "clap 4.4.6", + "clap 4.4.8", "digital_asset_types", "env_logger 0.10.0", "flatbuffers", @@ -7375,7 +7363,7 @@ name = "txn_forwarder" version = "0.7.12" dependencies = [ "anyhow", - "clap 4.4.6", + "clap 4.4.8", "env_logger 0.10.0", "figment", "flatbuffers", @@ -7470,12 +7458,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" -[[package]] -name = "unidecode" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "402bb19d8e03f1d1a7450e2bd613980869438e0666331be3e073089124aa1adc" - [[package]] name = "universal-hash" version = "0.4.1" diff --git a/Cargo.toml b/Cargo.toml index 949618561..4b4bb7faf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,99 @@ members = [ "tools/txn_forwarder", ] +[workspace.package] +version = "0.7.2" +edition = "2021" +repository = "https://github.com/metaplex-foundation/digital-asset-rpc-infrastructure" +publish = false + +[workspace.dependencies] +anchor-client = "0.28.0" +anchor-lang = "0.28.0" +anyhow = "1.0.75" +async-std = "1.0.0" +async-trait = "0.1.60" +base64 = "0.21.0" +blockbuster = "0.9.0-beta.1" +borsh = "~0.10.3" +bs58 = "0.4.0" +cadence = "0.29.0" +cadence-macros = "0.29.0" +chrono = "0.4.19" +clap = "4.2.2" +digital_asset_types = { path = "digital_asset_types" } +enum-iterator = "1.2.0" +enum-iterator-derive = "1.1.0" +env_logger = "0.10.0" +fake = "2.5.0" +figment = "0.10.8" +flatbuffers = "23.1.21" +futures = "0.3.28" +futures-util = "0.3.27" +hex = "0.4.3" +hyper = "0.14.23" +indexmap = "1.9.3" +jsonpath_lib = "0.3.0" +jsonrpsee = "0.16.2" +jsonrpsee-core = "0.16.2" +lazy_static = "1.4.0" +log = "0.4.17" +metrics = "0.20.1" +mime_guess = "2.0.4" +mpl-bubblegum = "1.0.1-beta.3" +mpl-candy-guard = "2.0.0" +mpl-candy-machine-core = "2.0.1" +mpl-token-metadata = "=2.0.0-beta.1" +nft_ingester = { path = "nft_ingester" } +num-derive = "0.3.3" +num-integer = { version = "0.1.44", default_features = false } +num-traits = "0.2.15" +open-rpc-derive = "0.0.4" +open-rpc-schema = "0.0.4" +plerkle_messenger = "1.6.0" +plerkle_serialization = "1.6.0" +prometheus = "0.13.3" +proxy-wasm = "0.2.0" +rand = "0.8.5" +redis = "0.22.3" +regex = "1.6.0" +reqwest = "0.11.13" +rust-crypto = "0.2.36" +schemars = "0.8.6" +schemars_derive = "0.8.6" +sea-orm = "0.10.6" +sea-orm-migration = "0.10.6" +sea-query = "0.28.1" +serde = "1.0.137" +serde_json = "1.0.81" +solana-account-decoder = "~1.16.16" +solana-client = "~1.16.16" +solana-geyser-plugin-interface = "~1.16.16" +solana-program = "~1.16.16" +solana-sdk = "~1.16.16" +solana-sdk-macro = "~1.16.16" +solana-transaction-status = "~1.16.16" +spl-account-compression = "0.2.0" +spl-associated-token-account = ">= 1.1.3, < 3.0" +spl-concurrent-merkle-tree = "0.2.0" +spl-noop = "0.2.0" +spl-token = ">= 3.5.0, < 5.0" +sqlx = "0.6.2" +stretto = "0.7.2" +thiserror = "1.0.31" +tokio = "1.30.0" +tokio-postgres = "0.7.7" +tokio-stream = "0.1.14" +tower = "0.4.13" +tower-http = "0.3.5" +tracing = "0.1.35" +tracing-subscriber = "0.3.16" +txn_forwarder = { path = "tools/txn_forwarder" } +url = "2.3.1" +uuid = "1.0.0" +wasi = "0.7.0" +wasm-bindgen = "0.2.83" + [workspace.lints.clippy] clone_on_ref_ptr = "deny" missing_const_for_fn = "deny" diff --git a/das_api/Cargo.toml b/das_api/Cargo.toml index 22349f789..c56afe88f 100644 --- a/das_api/Cargo.toml +++ b/das_api/Cargo.toml @@ -1,44 +1,44 @@ [package] name = "das_api" -version = "0.7.2" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +version = { workspace = true } +edition = { workspace = true } +repository = { workspace = true } +publish = { workspace = true } [dependencies] -digital_asset_types = { path = "../digital_asset_types", features = ["json_types", "sql_types"] } -jsonrpsee = {version = "0.16.2", features = ["server", "macros"]} -jsonrpsee-core = {version = "0.16.2", features =["server"]} -tower-http={version = "0.3.5", features = ["full"]} -tower={version="0.4.13", features = ["full"]} -hyper = "0.14.23" -tracing = "0.1.35" -metrics = "0.20.1" -figment = { version = "0.10.6", features = ["env"] } -serde = "1.0.137" -thiserror = "1.0.31" -tokio = {version="1.23.0"} -async-trait = "0.1.56" -serde_json = "1.0.81" -cadence = "0.29.0" -cadence-macros = "0.29.0" -sqlx = { version = "0.6.2", features = ["macros", "runtime-tokio-rustls", "postgres", "uuid", "offline", "json"] } -sea-orm = { version = "0.10.6", features = ["macros", "runtime-tokio-rustls", "sqlx-postgres"] } -tokio-postgres = "0.7.7" -solana-sdk = "~1.16.16" -bs58 = "0.4.0" -log = "0.4.17" -env_logger = "0.10" -schemars = "0.8.6" -schemars_derive = "0.8.6" -open-rpc-derive = { version = "0.0.4"} -open-rpc-schema = { version = "0.0.4"} -blockbuster = "0.9.0-beta.1" -anchor-lang = "0.28.0" -mpl-token-metadata = { version = "=2.0.0-beta.1", features = ["serde-feature"] } -mpl-candy-machine-core = { version = "2.0.1", features = ["no-entrypoint"] } -mpl-bubblegum = "1.0.1-beta.3" -mpl-candy-guard = { version = "2.0.0", features = ["no-entrypoint"] } +anchor-lang = { workspace = true } +async-trait = { workspace = true } +blockbuster = { workspace = true } +bs58 = { workspace = true } +cadence = { workspace = true } +cadence-macros = { workspace = true } +digital_asset_types = { workspace = true, features = ["json_types", "sql_types"] } +env_logger = { workspace = true } +figment = { workspace = true, features = ["env"] } +hyper = { workspace = true } +jsonrpsee = { workspace = true, features = ["server", "macros"]} +jsonrpsee-core = { workspace = true, features =["server"]} +log = { workspace = true } +metrics = { workspace = true } +mpl-bubblegum = { workspace = true } +mpl-candy-guard = { workspace = true, features = ["no-entrypoint"] } +mpl-candy-machine-core = { workspace = true, features = ["no-entrypoint"] } +mpl-token-metadata = { workspace = true, features = ["serde-feature"] } +open-rpc-derive = { workspace = true } +open-rpc-schema = { workspace = true } +schemars = { workspace = true } +schemars_derive = { workspace = true } +sea-orm = { workspace = true, features = ["macros", "runtime-tokio-rustls", "sqlx-postgres"] } +serde = { workspace = true } +serde_json = { workspace = true } +solana-sdk = { workspace = true } +sqlx = { workspace = true, features = ["macros", "runtime-tokio-rustls", "postgres", "uuid", "offline", "json"] } +thiserror = { workspace = true } +tokio = { workspace = true, features = ["signal"] } +tokio-postgres = { workspace = true } +tower = { workspace = true } +tower-http = { workspace = true, features = ["cors"] } +tracing = { workspace = true } [lints] workspace = true diff --git a/digital_asset_types/Cargo.toml b/digital_asset_types/Cargo.toml index e3011ee6f..72d4b668c 100644 --- a/digital_asset_types/Cargo.toml +++ b/digital_asset_types/Cargo.toml @@ -1,38 +1,33 @@ [package] name = "digital_asset_types" -version = "0.7.2" -edition = "2021" -publish = false - +version = { workspace = true } +edition = { workspace = true } +repository = { workspace = true } +publish = { workspace = true } [dependencies] -spl-concurrent-merkle-tree = "0.2.0" -sea-orm = { optional = true, version = "0.10.6", features = ["macros", "runtime-tokio-rustls", "sqlx-postgres", "with-chrono", "mock"] } -sea-query = { version = "0.28.1", features = ["postgres-array"] } -serde = { version = "1.0.137", optional = true } -serde_json = { version = "1.0.81", optional = true, features=["preserve_order"] } -bs58 = "0.4.0" -borsh = { version = "~0.10.3", optional = true } -borsh-derive = { version = "~0.10.3", optional = true } -solana-sdk = "~1.16.16" -num-traits = "0.2.15" -num-derive = "0.3.3" -thiserror = "1.0.31" -blockbuster = "0.9.0-beta.1" -jsonpath_lib = "0.3.0" -mime_guess = "2.0.4" -url = "2.3.1" -futures = "0.3.25" -reqwest = "0.11.13" -async-trait = "0.1.60" -tokio = { version = "1.22.0", features = ["full"] } -schemars = "0.8.6" -schemars_derive = "0.8.6" -log = "0.4.17" -indexmap = "1.9.3" - -[dev-dependencies] -reqwest = "0.11.13" +async-trait = { workspace = true } +blockbuster = { workspace = true } +bs58 = { workspace = true } +futures = { workspace = true } +indexmap = { workspace = true } +jsonpath_lib = { workspace = true } +log = { workspace = true } +mime_guess = { workspace = true } +num-derive = { workspace = true } +num-traits = { workspace = true } +reqwest = { workspace = true } +schemars = { workspace = true } +schemars_derive = { workspace = true } +sea-orm = { optional = true, features = ["macros", "runtime-tokio-rustls", "sqlx-postgres", "with-chrono", "mock"], workspace = true } +sea-query = { workspace = true, features = ["postgres-array"] } +serde = { workspace = true, optional = true } +serde_json = { workspace = true, features = ["preserve_order"], optional = true } +solana-sdk = { workspace = true } +spl-concurrent-merkle-tree = { workspace = true } +thiserror = { workspace = true } +tokio = { workspace = true } +url = { workspace = true } [features] default = ["json_types", "sql_types"] diff --git a/metaplex-rpc-proxy/Cargo.toml b/metaplex-rpc-proxy/Cargo.toml index fb7e11c46..2e69785dd 100644 --- a/metaplex-rpc-proxy/Cargo.toml +++ b/metaplex-rpc-proxy/Cargo.toml @@ -1,19 +1,20 @@ [package] name = "metaplex-rpc-proxy" version = "0.6.8" -edition = "2021" -publish = false +edition = { workspace = true } +repository = { workspace = true } +publish = { workspace = true } [lib] crate-type = ["cdylib"] [dependencies] -proxy-wasm = "0.2.0" -wasm-bindgen = "0.2.83" -lazy_static = "1.4.0" -regex = "1.6.0" -log = "0.4.17" -wasi = "0.7.0" +lazy_static = { workspace = true } +log = { workspace = true } +proxy-wasm = { workspace = true } +regex = { workspace = true } +wasi = { workspace = true } +wasm-bindgen = { workspace = true } [lints] workspace = true diff --git a/migration/Cargo.toml b/migration/Cargo.toml index f5eb28161..219a7683d 100644 --- a/migration/Cargo.toml +++ b/migration/Cargo.toml @@ -1,25 +1,16 @@ [package] name = "migration" -version = "0.7.2" -edition = "2021" -publish = false - -[lib] -name = "migration" -path = "src/lib.rs" +version = { workspace = true } +edition = { workspace = true } +repository = { workspace = true } +publish = { workspace = true } [dependencies] -async-std = { version = "^1", features = ["attributes", "tokio1", ] } -digital_asset_types = { path = "../digital_asset_types", features = ["json_types", "sql_types"] } -enum-iterator = "1.2.0" -enum-iterator-derive = "1.1.0" - -[dependencies.sea-orm-migration] -version = "0.10.6" -features = [ - "runtime-tokio-rustls", - "sqlx-postgres", -] +async-std = { workspace = true, features = ["attributes", "tokio1"] } +digital_asset_types = { workspace = true, features = ["json_types", "sql_types"] } +enum-iterator = { workspace = true } +enum-iterator-derive = { workspace = true } +sea-orm-migration = { workspace = true, features = ["runtime-tokio-rustls", "sqlx-postgres"] } [lints] workspace = true diff --git a/nft_ingester/Cargo.toml b/nft_ingester/Cargo.toml index bedda13c7..05b98b563 100644 --- a/nft_ingester/Cargo.toml +++ b/nft_ingester/Cargo.toml @@ -1,68 +1,62 @@ [package] name = "nft_ingester" -version = "0.7.2" -edition = "2021" -publish = false +version = { workspace = true } +edition = { workspace = true } +repository = { workspace = true } +publish = { workspace = true } [dependencies] -hex = "0.4.3" -log = "0.4.17" -env_logger = "0.10.0" -redis = { version = "0.22.3", features = ["aio", "tokio-comp", "streams", "tokio-native-tls-comp"] } -futures = {version = "0.3.25"} -futures-util = "0.3.27" -base64 = "0.21.0" -thiserror = "1.0.31" -serde_json = "1.0.81" -tokio = { version = "1.26.0", features = ["full", "tracing"] } -sqlx = { version = "0.6.2", features = ["macros", "runtime-tokio-rustls", "postgres", "uuid", "offline", "json"] } -sea-orm = { version = "0.10.6", features = ["macros", "runtime-tokio-rustls", "sqlx-postgres", "with-chrono", "mock"] } -sea-query = { version = "0.28.1", features = ["postgres-array"] } -chrono = "0.4.19" -tokio-postgres = "0.7.7" -serde = "1.0.136" -bs58 = "0.4.0" -reqwest = "0.11.11" -plerkle_messenger = { version = "1.6.0", features = ['redis'] } -plerkle_serialization = { version = "1.6.0" } -flatbuffers = "23.1.21" -lazy_static = "1.4.0" -regex = "1.5.5" -digital_asset_types = { path = "../digital_asset_types", features = ["json_types", "sql_types"] } -mpl-bubblegum = "1.0.1-beta.3" -spl-account-compression = { version = "0.2.0", features = ["no-entrypoint"] } -spl-concurrent-merkle-tree = "0.2.0" -uuid = "1.0.0" -async-trait = "0.1.53" -num-traits = "0.2.15" -blockbuster = "0.9.0-beta.1" -figment = { version = "0.10.6", features = ["env", "toml", "yaml"] } -cadence = "0.29.0" -cadence-macros = "0.29.0" -solana-sdk = "~1.16.16" -solana-client = "~1.16.16" -spl-token = { version = ">= 3.5.0, < 5.0", features = ["no-entrypoint"] } -solana-transaction-status = "~1.16.16" -solana-account-decoder = "~1.16.16" -solana-geyser-plugin-interface = "~1.16.16" -solana-sdk-macro = "~1.16.16" -rand = "0.8.5" -rust-crypto = "0.2.36" -url="2.3.1" -anchor-lang = "0.28.0" -borsh = "~0.10.3" -stretto = { version = "0.7", features = ["async"] } -tokio-stream = "0.1.12" -tracing-subscriber = { version = "0.3.16", features = [ - "json", - "env-filter", - "ansi", -] } -clap = { version = "4.2.2", features = ["derive", "cargo"] } - -[dependencies.num-integer] -version = "0.1.44" -default-features = false +anchor-lang = { workspace = true } +async-trait = { workspace = true } +base64 = { workspace = true } +blockbuster = { workspace = true } +borsh = { workspace = true } +bs58 = { workspace = true } +cadence = { workspace = true } +cadence-macros = { workspace = true } +chrono = { workspace = true } +clap = { workspace = true, features = ["derive", "cargo"] } +digital_asset_types = { workspace = true, features = ["json_types", "sql_types"] } +env_logger = { workspace = true } +figment = { workspace = true, features = ["env", "toml", "yaml"] } +flatbuffers = { workspace = true } +futures = { workspace = true } +futures-util = { workspace = true } +hex = { workspace = true } +lazy_static = { workspace = true } +log = { workspace = true } +mpl-bubblegum = { workspace = true } +num-integer = { workspace = true } +num-traits = { workspace = true } +plerkle_messenger = { workspace = true, features = ["redis"] } +plerkle_serialization = { workspace = true } +rand = { workspace = true } +redis = { workspace = true, features = ["aio", "tokio-comp", "streams", "tokio-native-tls-comp"] } +regex = { workspace = true } +reqwest = { workspace = true } +rust-crypto = { workspace = true } +sea-orm = { workspace = true, features = ["macros", "runtime-tokio-rustls", "sqlx-postgres", "with-chrono", "mock"] } +sea-query = { workspace = true, features = ["postgres-array"] } +serde = { workspace = true } +serde_json = { workspace = true } +solana-account-decoder = { workspace = true } +solana-client = { workspace = true } +solana-geyser-plugin-interface = { workspace = true } +solana-sdk = { workspace = true } +solana-sdk-macro = { workspace = true } +solana-transaction-status = { workspace = true } +spl-account-compression = { workspace = true, features = ["no-entrypoint"] } +spl-concurrent-merkle-tree = { workspace = true } +spl-token = { workspace = true, features = ["no-entrypoint"] } +sqlx = { workspace = true, features = ["macros", "runtime-tokio-rustls", "postgres", "uuid", "offline", "json"] } +stretto = { workspace = true, features = ["async"] } +thiserror = { workspace = true } +tokio = { workspace = true, features = ["tracing"] } +tokio-postgres = { workspace = true } +tokio-stream = { workspace = true } +tracing-subscriber = { workspace = true, features = ["json", "env-filter", "ansi"] } +url = { workspace = true } +uuid = { workspace = true } [lints] workspace = true diff --git a/tools/acc_forwarder/Cargo.toml b/tools/acc_forwarder/Cargo.toml index 89597dff4..edd45ca81 100644 --- a/tools/acc_forwarder/Cargo.toml +++ b/tools/acc_forwarder/Cargo.toml @@ -1,32 +1,33 @@ [package] name = "acc_forwarder" version = "0.7.12" -edition = "2021" -publish = false +edition = { workspace = true } +repository = { workspace = true } +publish = { workspace = true } [dependencies] -anyhow = "1.0.70" -bs58 = "0.4.0" -clap = { version = "4.1.4", features = ["derive"] } -env_logger = "0.10.0" -figment = "0.10.8" -flatbuffers = "23.1.21" -futures = "0.3.28" -lazy_static = "1.4.0" -log = "0.4.17" -mpl-token-metadata = "=2.0.0-beta.1" -plerkle_serialization = { version = "1.6.0" } -plerkle_messenger = { version = "1.6.0", features = ['redis'] } -prometheus = "0.13.3" -reqwest = { version = "0.11", features = ["json"] } -serde_json = "1.0.81" -solana-account-decoder = "~1.16.16" -solana-client = "~1.16.16" -solana-sdk = "~1.16.16" -solana-transaction-status = "~1.16.16" -spl-token = { version = ">= 3.5.0, < 5.0", features = ["no-entrypoint"] } -tokio = { version = "1.23.0", features = ["macros", "rt-multi-thread", "time"] } -txn_forwarder = { path = "../txn_forwarder" } +anyhow = { workspace = true } +bs58 = { workspace = true } +clap = { workspace = true, features = ["derive"] } +env_logger = { workspace = true } +figment = { workspace = true } +flatbuffers = { workspace = true } +futures = { workspace = true } +lazy_static = { workspace = true } +log = { workspace = true } +mpl-token-metadata = { workspace = true } +plerkle_messenger = { workspace = true, features = ['redis'] } +plerkle_serialization = { workspace = true } +prometheus = { workspace = true } +reqwest = { workspace = true, features = ["json"] } +serde_json = { workspace = true } +solana-account-decoder = { workspace = true } +solana-client = { workspace = true } +solana-sdk = { workspace = true } +solana-transaction-status = { workspace = true } +spl-token = { workspace = true, features = ["no-entrypoint"] } +tokio = { workspace = true, features = ["macros", "rt-multi-thread", "time"] } +txn_forwarder = { workspace = true } [lints] workspace = true diff --git a/tools/bgtask_creator/Cargo.toml b/tools/bgtask_creator/Cargo.toml index a262f7ddb..7011185e5 100644 --- a/tools/bgtask_creator/Cargo.toml +++ b/tools/bgtask_creator/Cargo.toml @@ -1,24 +1,25 @@ [package] name = "bgtask_creator" version = "0.7.12" -edition = "2021" -publish = false +edition = { workspace = true } +repository = { workspace = true } +publish = { workspace = true } [dependencies] -anyhow = "1.0.70" -clap = { version = "4.1.4", features = ["derive", "cargo"] } -digital_asset_types = { path = "../../digital_asset_types", features = ["json_types", "sql_types"] } -futures = "0.3.25" -lazy_static = "1.4.0" -log = "0.4.17" -nft_ingester = { path = "../../nft_ingester" } -prometheus = "0.13.3" -sea-orm = { version = "0.10.6", features = ["macros", "runtime-tokio-rustls", "sqlx-postgres", "with-chrono", "mock"] } -sea-query = { version = "0.28.1", features = ["postgres-array"] } -solana-sdk = "~1.16.16" -sqlx = { version = "0.6.2", features = ["macros", "runtime-tokio-rustls", "postgres", "uuid", "offline", "json"] } -tokio = { version = "1.23.0", features = ["macros", "rt-multi-thread"] } -txn_forwarder = { path = "../txn_forwarder" } +anyhow = { workspace = true } +clap = { workspace = true, features = ["derive", "cargo"] } +digital_asset_types = { workspace = true, features = ["json_types", "sql_types"] } +futures = { workspace = true } +lazy_static = { workspace = true } +log = { workspace = true } +nft_ingester = { workspace = true } +prometheus = { workspace = true } +sea-orm = { workspace = true, features = ["macros", "runtime-tokio-rustls", "sqlx-postgres", "with-chrono", "mock"] } +sea-query = { workspace = true, features = ["postgres-array"] } +solana-sdk = { workspace = true } +sqlx = { workspace = true, features = ["macros", "runtime-tokio-rustls", "postgres", "uuid", "offline", "json"] } +tokio = { workspace = true, features = ["macros", "rt-multi-thread"] } +txn_forwarder = { workspace = true } [lints] workspace = true diff --git a/tools/fetch_trees/Cargo.toml b/tools/fetch_trees/Cargo.toml index a6674d905..eb4f33460 100644 --- a/tools/fetch_trees/Cargo.toml +++ b/tools/fetch_trees/Cargo.toml @@ -1,20 +1,21 @@ [package] name = "fetch_trees" version = "0.7.12" -edition = "2021" -publish = false +edition = { workspace = true } +repository = { workspace = true } +publish = { workspace = true } [dependencies] -anyhow = "1.0.70" -async-trait = "0.1.53" -borsh = "~0.10.3" -clap = { version = "4.2.2", features = ["derive", "cargo"] } -mpl-bubblegum = "1.0.1-beta.3" -solana-account-decoder = "~1.16.16" -solana-client = "~1.16.16" -solana-sdk = "~1.16.16" -spl-account-compression = { version = "0.2.0", features = ["no-entrypoint"] } -tokio = { version = "1.26.0", features = ["full", "tracing"] } +anyhow = { workspace = true } +async-trait = { workspace = true } +borsh = { workspace = true } +clap = { workspace = true, features = ["derive", "cargo"] } +mpl-bubblegum = { workspace = true } +solana-account-decoder = { workspace = true } +solana-client = { workspace = true } +solana-sdk = { workspace = true } +spl-account-compression = { workspace = true, features = ["no-entrypoint"] } +tokio = { workspace = true, features = ["tracing"] } [lints] workspace = true diff --git a/tools/load_generation/Cargo.toml b/tools/load_generation/Cargo.toml index c9e1a905a..bd7b0de3b 100644 --- a/tools/load_generation/Cargo.toml +++ b/tools/load_generation/Cargo.toml @@ -1,19 +1,20 @@ [package] name = "load_generation" version = "0.7.12" -edition = "2021" -publish = false +edition = { workspace = true } +repository = { workspace = true } +publish = { workspace = true } [dependencies] -fake = "2.5.0" -mpl-token-metadata = "=2.0.0-beta.1" -rand = "0.8.5" -solana-client = "~1.16.16" -solana-program = "~1.16.16" -solana-sdk = "~1.16.16" -spl-associated-token-account = { version = ">= 1.1.3, < 3.0", features = ["no-entrypoint"] } -spl-token = { version = ">= 3.5.0, < 5.0", features = ["no-entrypoint"] } -tokio = { version ="1.25.0", features = ["macros", "rt-multi-thread"] } +fake = { workspace = true } +mpl-token-metadata = { workspace = true } +rand = { workspace = true } +solana-client = { workspace = true } +solana-program = { workspace = true } +solana-sdk = { workspace = true } +spl-associated-token-account = { workspace = true, features = ["no-entrypoint"] } +spl-token = { workspace = true, features = ["no-entrypoint"] } +tokio = { workspace = true, features = ["macros", "rt-multi-thread"] } [lints] workspace = true diff --git a/tools/tree-status/Cargo.toml b/tools/tree-status/Cargo.toml index 00c826ebc..da8ccc058 100644 --- a/tools/tree-status/Cargo.toml +++ b/tools/tree-status/Cargo.toml @@ -2,34 +2,35 @@ name = "tree-status" version = "0.7.12" authors = ["Triton One"] -edition = "2021" +edition = { workspace = true } description = "Test state of the sprcified tree" -publish = false +repository = { workspace = true } +publish = { workspace = true } [dependencies] -anchor-client = "0.28.0" -anyhow = "1.0.70" -bs58 = "0.4.0" -clap = { version = "4.1.4", features = ["derive"] } -digital_asset_types = { path = "../../digital_asset_types", features = ["json_types", "sql_types"] } -env_logger = "0.10.0" -flatbuffers = "23.1.21" -futures = "0.3.28" -hex = "0.4.3" -lazy_static = "1.4.0" -log = "0.4.17" -prometheus = "0.13.3" -sea-orm = { version = "0.10.6", features = ["macros", "runtime-tokio-rustls", "sqlx-postgres", "with-chrono", "mock"] } -serde_json = "1.0.81" -solana-client = "~1.16.16" -solana-sdk = "~1.16.16" -solana-transaction-status = "~1.16.16" -spl-account-compression = { version = "0.2.0", features = ["no-entrypoint"] } -spl-noop = { version = "0.2.0", features = ["no-entrypoint"] } -sqlx = { version = "0.6.2", features = ["macros", "runtime-tokio-rustls", "postgres", "uuid", "offline", "json"] } -thiserror = "1.0.31" -tokio = { version = "1.23.0", features = ["fs", "macros", "rt-multi-thread", "sync", "time"] } -txn_forwarder = { path = "../txn_forwarder" } +anchor-client = { workspace = true } +anyhow = { workspace = true } +bs58 = { workspace = true } +clap = { workspace = true, features = ["derive"] } +digital_asset_types = { workspace = true, features = ["json_types", "sql_types"] } +env_logger = { workspace = true } +flatbuffers = { workspace = true } +futures = { workspace = true } +hex = { workspace = true } +lazy_static = { workspace = true } +log = { workspace = true } +prometheus = { workspace = true } +sea-orm = { workspace = true, features = ["macros", "runtime-tokio-rustls", "sqlx-postgres", "with-chrono", "mock"] } +serde_json = { workspace = true } +solana-client = { workspace = true } +solana-sdk = { workspace = true } +solana-transaction-status = { workspace = true } +spl-account-compression = { workspace = true, features = ["no-entrypoint"] } +spl-noop = { workspace = true, features = ["no-entrypoint"] } +sqlx = { workspace = true, features = ["macros", "runtime-tokio-rustls", "postgres", "uuid", "offline", "json"] } +thiserror = { workspace = true } +tokio = { workspace = true, features = ["fs", "macros", "rt-multi-thread", "sync", "time"] } +txn_forwarder = { workspace = true } [lints] workspace = true diff --git a/tools/txn_forwarder/Cargo.toml b/tools/txn_forwarder/Cargo.toml index f15510ba9..c9f5ca999 100644 --- a/tools/txn_forwarder/Cargo.toml +++ b/tools/txn_forwarder/Cargo.toml @@ -1,29 +1,30 @@ [package] name = "txn_forwarder" version = "0.7.12" -edition = "2021" -publish = false +edition = { workspace = true } +repository = { workspace = true } +publish = { workspace = true } [dependencies] -anyhow = "1" -clap = { version = "4.1.4", features = ["derive"] } -env_logger = "0.10.0" -figment = "0.10.8" -flatbuffers = "23.1.21" -futures = "0.3.28" -lazy_static = "1.4.0" -log = "0.4.17" -plerkle_serialization = { version = "1.6.0" } -plerkle_messenger = { version = "1.6.0", features = ['redis'] } -prometheus = "0.13.3" -serde = "1.0.162" -serde_json = "1.0.81" -solana-client = "~1.16.16" -solana-sdk = "~1.16.16" -solana-transaction-status = "~1.16.16" -thiserror = "1.0.31" -tokio = { version = "1.23.0", features = ["macros", "rt-multi-thread", "sync", "time", "fs"] } -tokio-stream = { version = "0.1.14", features = ["io-util"] } +anyhow = { workspace = true } +clap = { workspace = true, features = ["derive"] } +env_logger = { workspace = true } +figment = { workspace = true } +flatbuffers = { workspace = true } +futures = { workspace = true } +lazy_static = { workspace = true } +log = { workspace = true } +plerkle_messenger = { workspace = true, features = ['redis'] } +plerkle_serialization = { workspace = true } +prometheus = { workspace = true } +serde = { workspace = true } +serde_json = { workspace = true } +solana-client = { workspace = true } +solana-sdk = { workspace = true } +solana-transaction-status = { workspace = true } +thiserror = { workspace = true } +tokio = { workspace = true, features = ["macros", "rt-multi-thread", "sync", "time", "fs"] } +tokio-stream = { workspace = true, features = ["io-util"] } [lints] workspace = true From d5e56c1fb9815e457a2580ed8117228f978ca0e5 Mon Sep 17 00:00:00 2001 From: Kirill Fomichev Date: Mon, 20 Nov 2023 16:59:08 -0500 Subject: [PATCH 10/23] update rust-toolchain.toml --- rust-toolchain.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 639f4f17d..e1b65492a 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,2 +1,5 @@ [toolchain] channel = "1.74.0" +components = ["clippy", "rustfmt"] +targets = [] +profile = "minimal" From 0cb2fbca8a689e2f7e1caecf5c9fc2ea1d446dc9 Mon Sep 17 00:00:00 2001 From: Kirill Fomichev Date: Mon, 20 Nov 2023 17:11:44 -0500 Subject: [PATCH 11/23] ci: fix build-api --- .github/workflows/build-api.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-api.yml b/.github/workflows/build-api.yml index 802e82e4d..15684355a 100644 --- a/.github/workflows/build-api.yml +++ b/.github/workflows/build-api.yml @@ -51,7 +51,7 @@ jobs: run: | mv target/release/nft_ingester target/release/nft_ingester22 mv target/release/fetch_trees target/release/fetch_trees22 - mv target/release/migration target/target/release/migration22 + mv target/release/migration target/release/migration22 mv target/release/das_api target/release/das_api22 # This steps can be omited to save space, are mostly in place to validate binaries (manually) and path to them From 1b2759be2bd67aaa6e39554ab918ce9cb449da3d Mon Sep 17 00:00:00 2001 From: Kirill Fomichev Date: Wed, 22 Nov 2023 12:10:23 -0500 Subject: [PATCH 12/23] add crate program_transformers --- Cargo.lock | 21 + Cargo.toml | 1 + nft_ingester/.dockerignore | 1 - program_transformers/Cargo.toml | 26 + program_transformers/src/bubblegum/burn.rs | 70 +++ .../src/bubblegum/cancel_redeem.rs | 76 +++ .../src/bubblegum/collection_verification.rs | 86 ++++ .../src/bubblegum/creator_verification.rs | 110 +++++ program_transformers/src/bubblegum/db.rs | 451 ++++++++++++++++++ .../src/bubblegum/decompress.rs | 34 ++ .../src/bubblegum/delegate.rs | 74 +++ program_transformers/src/bubblegum/mint_v1.rs | 364 ++++++++++++++ program_transformers/src/bubblegum/mod.rs | 108 +++++ program_transformers/src/bubblegum/redeem.rs | 61 +++ .../src/bubblegum/transfer.rs | 76 +++ program_transformers/src/error.rs | 36 ++ program_transformers/src/lib.rs | 220 +++++++++ program_transformers/src/token/mod.rs | 147 ++++++ .../src/token_metadata/master_edition.rs | 98 ++++ .../src/token_metadata/mod.rs | 58 +++ .../src/token_metadata/v1_asset.rs | 393 +++++++++++++++ 21 files changed, 2510 insertions(+), 1 deletion(-) delete mode 100644 nft_ingester/.dockerignore create mode 100644 program_transformers/Cargo.toml create mode 100644 program_transformers/src/bubblegum/burn.rs create mode 100644 program_transformers/src/bubblegum/cancel_redeem.rs create mode 100644 program_transformers/src/bubblegum/collection_verification.rs create mode 100644 program_transformers/src/bubblegum/creator_verification.rs create mode 100644 program_transformers/src/bubblegum/db.rs create mode 100644 program_transformers/src/bubblegum/decompress.rs create mode 100644 program_transformers/src/bubblegum/delegate.rs create mode 100644 program_transformers/src/bubblegum/mint_v1.rs create mode 100644 program_transformers/src/bubblegum/mod.rs create mode 100644 program_transformers/src/bubblegum/redeem.rs create mode 100644 program_transformers/src/bubblegum/transfer.rs create mode 100644 program_transformers/src/error.rs create mode 100644 program_transformers/src/lib.rs create mode 100644 program_transformers/src/token/mod.rs create mode 100644 program_transformers/src/token_metadata/master_edition.rs create mode 100644 program_transformers/src/token_metadata/mod.rs create mode 100644 program_transformers/src/token_metadata/v1_asset.rs diff --git a/Cargo.lock b/Cargo.lock index bd2dc1e7f..08913f59c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4203,6 +4203,27 @@ dependencies = [ "yansi", ] +[[package]] +name = "program_transformers" +version = "0.7.2" +dependencies = [ + "blockbuster", + "bs58 0.4.0", + "digital_asset_types", + "futures", + "mpl-bubblegum", + "num-traits", + "plerkle_serialization", + "sea-orm", + "serde_json", + "solana-sdk", + "spl-account-compression", + "spl-token 4.0.0", + "sqlx", + "thiserror", + "tracing", +] + [[package]] name = "prometheus" version = "0.13.3" diff --git a/Cargo.toml b/Cargo.toml index 4b4bb7faf..a5d08f3cb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,7 @@ members = [ "metaplex-rpc-proxy", "migration", "nft_ingester", + "program_transformers", "tools/acc_forwarder", "tools/bgtask_creator", "tools/fetch_trees", diff --git a/nft_ingester/.dockerignore b/nft_ingester/.dockerignore deleted file mode 100644 index 1de565933..000000000 --- a/nft_ingester/.dockerignore +++ /dev/null @@ -1 +0,0 @@ -target \ No newline at end of file diff --git a/program_transformers/Cargo.toml b/program_transformers/Cargo.toml new file mode 100644 index 000000000..b1c2e7439 --- /dev/null +++ b/program_transformers/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "program_transformers" +version = { workspace = true } +edition = { workspace = true } +repository = { workspace = true } +publish = { workspace = true } + +[dependencies] +blockbuster = { workspace = true } +bs58 = { workspace = true } +digital_asset_types = { workspace = true, features = ["json_types", "sql_types"] } +futures = { workspace = true } +mpl-bubblegum = { workspace = true } +num-traits = { workspace = true } +plerkle_serialization = { workspace = true } +sea-orm = { workspace = true, features = [] } +serde_json = { workspace = true } +solana-sdk = { workspace = true } +spl-account-compression = { workspace = true, features = ["no-entrypoint"] } +spl-token = { workspace = true, features = ["no-entrypoint"] } +sqlx = { workspace = true, features = [] } +thiserror = { workspace = true } +tracing = { workspace = true } + +[lints] +workspace = true diff --git a/program_transformers/src/bubblegum/burn.rs b/program_transformers/src/bubblegum/burn.rs new file mode 100644 index 000000000..736bba7d5 --- /dev/null +++ b/program_transformers/src/bubblegum/burn.rs @@ -0,0 +1,70 @@ +use { + crate::{ + bubblegum::{ + db::{save_changelog_event, upsert_asset_with_seq}, + u32_to_u8_array, + }, + error::{ProgramTransformerError, ProgramTransformerResult}, + }, + blockbuster::{instruction::InstructionBundle, programs::bubblegum::BubblegumInstruction}, + digital_asset_types::dao::asset, + sea_orm::{ + entity::{ActiveValue, EntityTrait}, + query::QueryTrait, + sea_query::query::OnConflict, + ConnectionTrait, DbBackend, TransactionTrait, + }, + solana_sdk::pubkey::Pubkey, + tracing::debug, +}; + +pub async fn burn<'c, T>( + parsing_result: &BubblegumInstruction, + bundle: &InstructionBundle<'c>, + txn: &'c T, + cl_audits: bool, +) -> ProgramTransformerResult<()> +where + T: ConnectionTrait + TransactionTrait, +{ + if let Some(cl) = &parsing_result.tree_update { + let seq = save_changelog_event(cl, bundle.slot, bundle.txn_id, txn, cl_audits).await?; + let leaf_index = cl.index; + let (asset_id, _) = Pubkey::find_program_address( + &[ + "asset".as_bytes(), + cl.id.as_ref(), + u32_to_u8_array(leaf_index).as_ref(), + ], + &mpl_bubblegum::ID, + ); + debug!("Indexing burn for asset id: {:?}", asset_id); + let id_bytes = asset_id.to_bytes(); + + let asset_model = asset::ActiveModel { + id: ActiveValue::Set(id_bytes.to_vec()), + burnt: ActiveValue::Set(true), + ..Default::default() + }; + + // Upsert asset table `burnt` column. + let query = asset::Entity::insert(asset_model) + .on_conflict( + OnConflict::columns([asset::Column::Id]) + .update_columns([ + asset::Column::Burnt, + //TODO maybe handle slot updated. + ]) + .to_owned(), + ) + .build(DbBackend::Postgres); + txn.execute(query).await?; + + upsert_asset_with_seq(txn, id_bytes.to_vec(), seq as i64).await?; + + return Ok(()); + } + Err(ProgramTransformerError::ParsingError( + "Ix not parsed correctly".to_string(), + )) +} diff --git a/program_transformers/src/bubblegum/cancel_redeem.rs b/program_transformers/src/bubblegum/cancel_redeem.rs new file mode 100644 index 000000000..234b5ce44 --- /dev/null +++ b/program_transformers/src/bubblegum/cancel_redeem.rs @@ -0,0 +1,76 @@ +use { + crate::{ + bubblegum::db::{ + save_changelog_event, upsert_asset_with_leaf_info, + upsert_asset_with_owner_and_delegate_info, upsert_asset_with_seq, + }, + error::{ProgramTransformerError, ProgramTransformerResult}, + }, + blockbuster::{ + instruction::InstructionBundle, + programs::bubblegum::{BubblegumInstruction, LeafSchema}, + }, + sea_orm::{ConnectionTrait, TransactionTrait}, +}; + +pub async fn cancel_redeem<'c, T>( + parsing_result: &BubblegumInstruction, + bundle: &InstructionBundle<'c>, + txn: &'c T, + cl_audits: bool, +) -> ProgramTransformerResult<()> +where + T: ConnectionTrait + TransactionTrait, +{ + if let (Some(le), Some(cl)) = (&parsing_result.leaf_update, &parsing_result.tree_update) { + let seq = save_changelog_event(cl, bundle.slot, bundle.txn_id, txn, cl_audits).await?; + #[allow(unreachable_patterns)] + return match le.schema { + LeafSchema::V1 { + id, + owner, + delegate, + .. + } => { + let id_bytes = id.to_bytes(); + let owner_bytes = owner.to_bytes().to_vec(); + let delegate = if owner == delegate || delegate.to_bytes() == [0; 32] { + None + } else { + Some(delegate.to_bytes().to_vec()) + }; + let tree_id = cl.id.to_bytes(); + let nonce = cl.index as i64; + + // Partial update of asset table with just leaf. + upsert_asset_with_leaf_info( + txn, + id_bytes.to_vec(), + nonce, + tree_id.to_vec(), + le.leaf_hash.to_vec(), + le.schema.data_hash(), + le.schema.creator_hash(), + seq as i64, + false, + ) + .await?; + + // Partial update of asset table with just leaf owner and delegate. + upsert_asset_with_owner_and_delegate_info( + txn, + id_bytes.to_vec(), + owner_bytes, + delegate, + seq as i64, + ) + .await?; + + upsert_asset_with_seq(txn, id_bytes.to_vec(), seq as i64).await + } + }; + } + Err(ProgramTransformerError::ParsingError( + "Ix not parsed correctly".to_string(), + )) +} diff --git a/program_transformers/src/bubblegum/collection_verification.rs b/program_transformers/src/bubblegum/collection_verification.rs new file mode 100644 index 000000000..2a4c0eba3 --- /dev/null +++ b/program_transformers/src/bubblegum/collection_verification.rs @@ -0,0 +1,86 @@ +use { + crate::{ + bubblegum::db::{ + save_changelog_event, upsert_asset_with_leaf_info, upsert_asset_with_seq, + upsert_collection_info, + }, + error::{ProgramTransformerError, ProgramTransformerResult}, + }, + blockbuster::{ + instruction::InstructionBundle, + programs::bubblegum::{BubblegumInstruction, LeafSchema, Payload}, + }, + mpl_bubblegum::types::Collection, + sea_orm::{ConnectionTrait, TransactionTrait}, + tracing::debug, +}; + +pub async fn process<'c, T>( + parsing_result: &BubblegumInstruction, + bundle: &InstructionBundle<'c>, + txn: &'c T, + cl_audits: bool, +) -> ProgramTransformerResult<()> +where + T: ConnectionTrait + TransactionTrait, +{ + if let (Some(le), Some(cl), Some(payload)) = ( + &parsing_result.leaf_update, + &parsing_result.tree_update, + &parsing_result.payload, + ) { + let (collection, verify) = match payload { + Payload::CollectionVerification { + collection, verify, .. + } => (*collection, verify), + _ => { + return Err(ProgramTransformerError::ParsingError( + "Ix not parsed correctly".to_string(), + )); + } + }; + debug!( + "Handling collection verification event for {} (verify: {}): {}", + collection, verify, bundle.txn_id + ); + let seq = save_changelog_event(cl, bundle.slot, bundle.txn_id, txn, cl_audits).await?; + let id_bytes = match le.schema { + LeafSchema::V1 { id, .. } => id.to_bytes().to_vec(), + }; + let tree_id = cl.id.to_bytes(); + let nonce = cl.index as i64; + + // Partial update of asset table with just leaf. + upsert_asset_with_leaf_info( + txn, + id_bytes.to_vec(), + nonce, + tree_id.to_vec(), + le.leaf_hash.to_vec(), + le.schema.data_hash(), + le.schema.creator_hash(), + seq as i64, + false, + ) + .await?; + + upsert_asset_with_seq(txn, id_bytes.to_vec(), seq as i64).await?; + + upsert_collection_info( + txn, + id_bytes.to_vec(), + Some(Collection { + key: collection, + verified: *verify, + }), + bundle.slot as i64, + seq as i64, + ) + .await?; + + return Ok(()); + }; + Err(ProgramTransformerError::ParsingError( + "Ix not parsed correctly".to_string(), + )) +} diff --git a/program_transformers/src/bubblegum/creator_verification.rs b/program_transformers/src/bubblegum/creator_verification.rs new file mode 100644 index 000000000..785a500a4 --- /dev/null +++ b/program_transformers/src/bubblegum/creator_verification.rs @@ -0,0 +1,110 @@ +use { + crate::{ + bubblegum::db::{ + save_changelog_event, upsert_asset_with_leaf_info, + upsert_asset_with_owner_and_delegate_info, upsert_asset_with_seq, + upsert_creator_verified, + }, + error::{ProgramTransformerError, ProgramTransformerResult}, + }, + blockbuster::{ + instruction::InstructionBundle, + programs::bubblegum::{BubblegumInstruction, LeafSchema, Payload}, + }, + sea_orm::{ConnectionTrait, TransactionTrait}, + tracing::debug, +}; + +pub async fn process<'c, T>( + parsing_result: &BubblegumInstruction, + bundle: &InstructionBundle<'c>, + txn: &'c T, + value: bool, + cl_audits: bool, +) -> ProgramTransformerResult<()> +where + T: ConnectionTrait + TransactionTrait, +{ + if let (Some(le), Some(cl), Some(payload)) = ( + &parsing_result.leaf_update, + &parsing_result.tree_update, + &parsing_result.payload, + ) { + let (creator, verify) = match payload { + Payload::CreatorVerification { + creator, verify, .. + } => (creator, verify), + _ => { + return Err(ProgramTransformerError::ParsingError( + "Ix not parsed correctly".to_string(), + )); + } + }; + debug!( + "Handling creator verification event for creator {} (verify: {}): {}", + creator, verify, bundle.txn_id + ); + let seq = save_changelog_event(cl, bundle.slot, bundle.txn_id, txn, cl_audits).await?; + + let asset_id_bytes = match le.schema { + LeafSchema::V1 { + id, + owner, + delegate, + .. + } => { + let id_bytes = id.to_bytes(); + let owner_bytes = owner.to_bytes().to_vec(); + let delegate = if owner == delegate || delegate.to_bytes() == [0; 32] { + None + } else { + Some(delegate.to_bytes().to_vec()) + }; + let tree_id = cl.id.to_bytes(); + let nonce = cl.index as i64; + + // Partial update of asset table with just leaf info. + upsert_asset_with_leaf_info( + txn, + id_bytes.to_vec(), + nonce, + tree_id.to_vec(), + le.leaf_hash.to_vec(), + le.schema.data_hash(), + le.schema.creator_hash(), + seq as i64, + false, + ) + .await?; + + // Partial update of asset table with just leaf owner and delegate. + upsert_asset_with_owner_and_delegate_info( + txn, + id_bytes.to_vec(), + owner_bytes, + delegate, + seq as i64, + ) + .await?; + + upsert_asset_with_seq(txn, id_bytes.to_vec(), seq as i64).await?; + + id_bytes.to_vec() + } + }; + + upsert_creator_verified( + txn, + asset_id_bytes, + creator.to_bytes().to_vec(), + value, + seq as i64, + ) + .await?; + + return Ok(()); + } + Err(ProgramTransformerError::ParsingError( + "Ix not parsed correctly".to_string(), + )) +} diff --git a/program_transformers/src/bubblegum/db.rs b/program_transformers/src/bubblegum/db.rs new file mode 100644 index 000000000..ecee1a367 --- /dev/null +++ b/program_transformers/src/bubblegum/db.rs @@ -0,0 +1,451 @@ +use { + crate::error::{ProgramTransformerError, ProgramTransformerResult}, + digital_asset_types::dao::{ + asset, asset_creators, asset_grouping, backfill_items, cl_audits, cl_items, + }, + mpl_bubblegum::types::Collection, + sea_orm::{ + entity::{ActiveValue, ColumnTrait, EntityTrait}, + query::{QueryFilter, QuerySelect, QueryTrait}, + sea_query::query::OnConflict, + ConnectionTrait, DbBackend, TransactionTrait, + }, + spl_account_compression::events::ChangeLogEventV1, + tracing::{debug, info}, +}; + +pub async fn save_changelog_event<'c, T>( + change_log_event: &ChangeLogEventV1, + slot: u64, + txn_id: &str, + txn: &T, + cl_audits: bool, +) -> ProgramTransformerResult +where + T: ConnectionTrait + TransactionTrait, +{ + insert_change_log(change_log_event, slot, txn_id, txn, cl_audits).await?; + Ok(change_log_event.seq) +} + +const fn node_idx_to_leaf_idx(index: i64, tree_height: u32) -> i64 { + index - 2i64.pow(tree_height) +} + +pub async fn insert_change_log<'c, T>( + change_log_event: &ChangeLogEventV1, + slot: u64, + txn_id: &str, + txn: &T, + cl_audits: bool, +) -> ProgramTransformerResult<()> +where + T: ConnectionTrait + TransactionTrait, +{ + let mut i: i64 = 0; + let depth = change_log_event.path.len() - 1; + let tree_id = change_log_event.id.as_ref(); + for p in change_log_event.path.iter() { + let node_idx = p.index as i64; + debug!( + "seq {}, index {} level {}, node {:?}, txn: {:?}", + change_log_event.seq, + p.index, + i, + bs58::encode(p.node).into_string(), + txn_id, + ); + let leaf_idx = if i == 0 { + Some(node_idx_to_leaf_idx(node_idx, depth as u32)) + } else { + None + }; + + let item = cl_items::ActiveModel { + tree: ActiveValue::Set(tree_id.to_vec()), + level: ActiveValue::Set(i), + node_idx: ActiveValue::Set(node_idx), + hash: ActiveValue::Set(p.node.as_ref().to_vec()), + seq: ActiveValue::Set(change_log_event.seq as i64), + leaf_idx: ActiveValue::Set(leaf_idx), + ..Default::default() + }; + + let audit_item: Option = if cl_audits { + let mut ai: cl_audits::ActiveModel = item.clone().into(); + ai.tx = ActiveValue::Set(txn_id.to_string()); + Some(ai) + } else { + None + }; + + i += 1; + let mut query = cl_items::Entity::insert(item) + .on_conflict( + OnConflict::columns([cl_items::Column::Tree, cl_items::Column::NodeIdx]) + .update_columns([ + cl_items::Column::Hash, + cl_items::Column::Seq, + cl_items::Column::LeafIdx, + cl_items::Column::Level, + ]) + .to_owned(), + ) + .build(DbBackend::Postgres); + query.sql = format!("{} WHERE excluded.seq > cl_items.seq", query.sql); + txn.execute(query) + .await + .map_err(|db_err| ProgramTransformerError::StorageWriteError(db_err.to_string()))?; + + // Insert the audit item after the insert into cl_items have been completed + if let Some(audit_item) = audit_item { + cl_audits::Entity::insert(audit_item).exec(txn).await?; + } + } + + // If and only if the entire path of nodes was inserted into the `cl_items` table, then insert + // a single row into the `backfill_items` table. This way if an incomplete path was inserted + // into `cl_items` due to an error, a gap will be created for the tree and the backfiller will + // fix it. + if i - 1 == depth as i64 { + // See if the tree already exists in the `backfill_items` table. + let rows = backfill_items::Entity::find() + .filter(backfill_items::Column::Tree.eq(tree_id)) + .limit(1) + .all(txn) + .await?; + + // If the tree does not exist in `backfill_items` and the sequence number is greater than 1, + // then we know we will need to backfill the tree from sequence number 1 up to the current + // sequence number. So in this case we set at flag to force checking the tree. + let force_chk = rows.is_empty() && change_log_event.seq > 1; + + info!("Adding to backfill_items table at level {}", i - 1); + let item = backfill_items::ActiveModel { + tree: ActiveValue::Set(tree_id.to_vec()), + seq: ActiveValue::Set(change_log_event.seq as i64), + slot: ActiveValue::Set(slot as i64), + force_chk: ActiveValue::Set(force_chk), + backfilled: ActiveValue::Set(false), + failed: ActiveValue::Set(false), + ..Default::default() + }; + + backfill_items::Entity::insert(item).exec(txn).await?; + } + + Ok(()) + //TODO -> set maximum size of path and break into multiple statements +} + +#[allow(clippy::too_many_arguments)] +pub async fn upsert_asset_with_leaf_info( + txn: &T, + id: Vec, + nonce: i64, + tree_id: Vec, + leaf: Vec, + data_hash: [u8; 32], + creator_hash: [u8; 32], + seq: i64, + was_decompressed: bool, +) -> ProgramTransformerResult<()> +where + T: ConnectionTrait + TransactionTrait, +{ + let data_hash = bs58::encode(data_hash).into_string().trim().to_string(); + let creator_hash = bs58::encode(creator_hash).into_string().trim().to_string(); + let model = asset::ActiveModel { + id: ActiveValue::Set(id), + nonce: ActiveValue::Set(Some(nonce)), + tree_id: ActiveValue::Set(Some(tree_id)), + leaf: ActiveValue::Set(Some(leaf)), + data_hash: ActiveValue::Set(Some(data_hash)), + creator_hash: ActiveValue::Set(Some(creator_hash)), + leaf_seq: ActiveValue::Set(Some(seq)), + ..Default::default() + }; + + let mut query = asset::Entity::insert(model) + .on_conflict( + OnConflict::column(asset::Column::Id) + .update_columns([ + asset::Column::Nonce, + asset::Column::TreeId, + asset::Column::Leaf, + asset::Column::LeafSeq, + asset::Column::DataHash, + asset::Column::CreatorHash, + ]) + .to_owned(), + ) + .build(DbBackend::Postgres); + + // If we are indexing decompression we will update the leaf regardless of if we have previously + // indexed decompression and regardless of seq. + if !was_decompressed { + query.sql = format!( + "{} WHERE (NOT asset.was_decompressed) AND (excluded.leaf_seq >= asset.leaf_seq OR asset.leaf_seq IS NULL)", + query.sql + ); + } + + txn.execute(query) + .await + .map_err(|db_err| ProgramTransformerError::StorageWriteError(db_err.to_string()))?; + + Ok(()) +} + +pub async fn upsert_asset_with_leaf_info_for_decompression( + txn: &T, + id: Vec, +) -> ProgramTransformerResult<()> +where + T: ConnectionTrait + TransactionTrait, +{ + let model = asset::ActiveModel { + id: ActiveValue::Set(id), + leaf: ActiveValue::Set(None), + nonce: ActiveValue::Set(Some(0)), + leaf_seq: ActiveValue::Set(None), + data_hash: ActiveValue::Set(None), + creator_hash: ActiveValue::Set(None), + tree_id: ActiveValue::Set(None), + seq: ActiveValue::Set(Some(0)), + ..Default::default() + }; + let query = asset::Entity::insert(model) + .on_conflict( + OnConflict::column(asset::Column::Id) + .update_columns([ + asset::Column::Leaf, + asset::Column::LeafSeq, + asset::Column::Nonce, + asset::Column::DataHash, + asset::Column::CreatorHash, + asset::Column::TreeId, + asset::Column::Seq, + ]) + .to_owned(), + ) + .build(DbBackend::Postgres); + txn.execute(query) + .await + .map_err(|db_err| ProgramTransformerError::StorageWriteError(db_err.to_string()))?; + + Ok(()) +} + +pub async fn upsert_asset_with_owner_and_delegate_info( + txn: &T, + id: Vec, + owner: Vec, + delegate: Option>, + seq: i64, +) -> ProgramTransformerResult<()> +where + T: ConnectionTrait + TransactionTrait, +{ + let model = asset::ActiveModel { + id: ActiveValue::Set(id), + owner: ActiveValue::Set(Some(owner)), + delegate: ActiveValue::Set(delegate), + owner_delegate_seq: ActiveValue::Set(Some(seq)), // gummyroll seq + ..Default::default() + }; + + let mut query = asset::Entity::insert(model) + .on_conflict( + OnConflict::column(asset::Column::Id) + .update_columns([ + asset::Column::Owner, + asset::Column::Delegate, + asset::Column::OwnerDelegateSeq, + ]) + .to_owned(), + ) + .build(DbBackend::Postgres); + query.sql = format!( + "{} WHERE excluded.owner_delegate_seq >= asset.owner_delegate_seq OR asset.owner_delegate_seq IS NULL", + query.sql + ); + + txn.execute(query) + .await + .map_err(|db_err| ProgramTransformerError::StorageWriteError(db_err.to_string()))?; + + Ok(()) +} + +pub async fn upsert_asset_with_compression_info( + txn: &T, + id: Vec, + compressed: bool, + compressible: bool, + supply: i64, + supply_mint: Option>, + was_decompressed: bool, +) -> ProgramTransformerResult<()> +where + T: ConnectionTrait + TransactionTrait, +{ + let model = asset::ActiveModel { + id: ActiveValue::Set(id), + compressed: ActiveValue::Set(compressed), + compressible: ActiveValue::Set(compressible), + supply: ActiveValue::Set(supply), + supply_mint: ActiveValue::Set(supply_mint), + was_decompressed: ActiveValue::Set(was_decompressed), + ..Default::default() + }; + + let mut query = asset::Entity::insert(model) + .on_conflict( + OnConflict::columns([asset::Column::Id]) + .update_columns([ + asset::Column::Compressed, + asset::Column::Compressible, + asset::Column::Supply, + asset::Column::SupplyMint, + asset::Column::WasDecompressed, + ]) + .to_owned(), + ) + .build(DbBackend::Postgres); + query.sql = format!("{} WHERE NOT asset.was_decompressed", query.sql); + txn.execute(query).await?; + + Ok(()) +} + +pub async fn upsert_asset_with_seq( + txn: &T, + id: Vec, + seq: i64, +) -> ProgramTransformerResult<()> +where + T: ConnectionTrait + TransactionTrait, +{ + let model = asset::ActiveModel { + id: ActiveValue::Set(id), + seq: ActiveValue::Set(Some(seq)), + ..Default::default() + }; + + let mut query = asset::Entity::insert(model) + .on_conflict( + OnConflict::column(asset::Column::Id) + .update_columns([asset::Column::Seq]) + .to_owned(), + ) + .build(DbBackend::Postgres); + + query.sql = format!( + "{} WHERE (NOT asset.was_decompressed) AND (excluded.seq >= asset.seq OR asset.seq IS NULL)", + query.sql + ); + + txn.execute(query) + .await + .map_err(|db_err| ProgramTransformerError::StorageWriteError(db_err.to_string()))?; + + Ok(()) +} + +pub async fn upsert_creator_verified( + txn: &T, + asset_id: Vec, + creator: Vec, + verified: bool, + seq: i64, +) -> ProgramTransformerResult<()> +where + T: ConnectionTrait + TransactionTrait, +{ + let model = asset_creators::ActiveModel { + asset_id: ActiveValue::Set(asset_id), + creator: ActiveValue::Set(creator), + verified: ActiveValue::Set(verified), + seq: ActiveValue::Set(Some(seq)), + ..Default::default() + }; + + let mut query = asset_creators::Entity::insert(model) + .on_conflict( + OnConflict::columns([ + asset_creators::Column::AssetId, + asset_creators::Column::Creator, + ]) + .update_columns([ + asset_creators::Column::Verified, + asset_creators::Column::Seq, + ]) + .to_owned(), + ) + .build(DbBackend::Postgres); + + query.sql = format!( + "{} WHERE excluded.seq >= asset_creators.seq OR asset_creators.seq is NULL", + query.sql + ); + + txn.execute(query) + .await + .map_err(|db_err| ProgramTransformerError::StorageWriteError(db_err.to_string()))?; + + Ok(()) +} + +pub async fn upsert_collection_info( + txn: &T, + asset_id: Vec, + collection: Option, + slot_updated: i64, + seq: i64, +) -> ProgramTransformerResult<()> +where + T: ConnectionTrait + TransactionTrait, +{ + let (group_value, verified) = match collection { + Some(c) => (Some(c.key.to_string()), c.verified), + None => (None, false), + }; + + let model = asset_grouping::ActiveModel { + asset_id: ActiveValue::Set(asset_id), + group_key: ActiveValue::Set("collection".to_string()), + group_value: ActiveValue::Set(group_value), + verified: ActiveValue::Set(Some(verified)), + slot_updated: ActiveValue::Set(Some(slot_updated)), + group_info_seq: ActiveValue::Set(Some(seq)), + ..Default::default() + }; + + let mut query = asset_grouping::Entity::insert(model) + .on_conflict( + OnConflict::columns([ + asset_grouping::Column::AssetId, + asset_grouping::Column::GroupKey, + ]) + .update_columns([ + asset_grouping::Column::GroupValue, + asset_grouping::Column::Verified, + asset_grouping::Column::SlotUpdated, + asset_grouping::Column::GroupInfoSeq, + ]) + .to_owned(), + ) + .build(DbBackend::Postgres); + + query.sql = format!( + "{} WHERE excluded.group_info_seq >= asset_grouping.group_info_seq OR asset_grouping.group_info_seq IS NULL", + query.sql + ); + + txn.execute(query) + .await + .map_err(|db_err| ProgramTransformerError::StorageWriteError(db_err.to_string()))?; + + Ok(()) +} diff --git a/program_transformers/src/bubblegum/decompress.rs b/program_transformers/src/bubblegum/decompress.rs new file mode 100644 index 000000000..9db67e8b8 --- /dev/null +++ b/program_transformers/src/bubblegum/decompress.rs @@ -0,0 +1,34 @@ +use { + crate::{ + bubblegum::db::{ + upsert_asset_with_compression_info, upsert_asset_with_leaf_info_for_decompression, + }, + error::ProgramTransformerResult, + }, + blockbuster::{instruction::InstructionBundle, programs::bubblegum::BubblegumInstruction}, + sea_orm::{ConnectionTrait, TransactionTrait}, +}; + +pub async fn decompress<'c, T>( + _parsing_result: &BubblegumInstruction, + bundle: &InstructionBundle<'c>, + txn: &'c T, +) -> ProgramTransformerResult<()> +where + T: ConnectionTrait + TransactionTrait, +{ + let id_bytes = bundle.keys.get(3).unwrap().0.as_slice(); + + // Partial update of asset table with just leaf. + upsert_asset_with_leaf_info_for_decompression(txn, id_bytes.to_vec()).await?; + upsert_asset_with_compression_info( + txn, + id_bytes.to_vec(), + false, + false, + 1, + Some(id_bytes.to_vec()), + true, + ) + .await +} diff --git a/program_transformers/src/bubblegum/delegate.rs b/program_transformers/src/bubblegum/delegate.rs new file mode 100644 index 000000000..5d6a7d1c5 --- /dev/null +++ b/program_transformers/src/bubblegum/delegate.rs @@ -0,0 +1,74 @@ +use { + crate::{ + bubblegum::db::{ + save_changelog_event, upsert_asset_with_leaf_info, + upsert_asset_with_owner_and_delegate_info, upsert_asset_with_seq, + }, + error::{ProgramTransformerError, ProgramTransformerResult}, + }, + blockbuster::{ + instruction::InstructionBundle, + programs::bubblegum::{BubblegumInstruction, LeafSchema}, + }, + sea_orm::{ConnectionTrait, TransactionTrait}, +}; + +pub async fn delegate<'c, T>( + parsing_result: &BubblegumInstruction, + bundle: &InstructionBundle<'c>, + txn: &'c T, + cl_audits: bool, +) -> ProgramTransformerResult<()> +where + T: ConnectionTrait + TransactionTrait, +{ + if let (Some(le), Some(cl)) = (&parsing_result.leaf_update, &parsing_result.tree_update) { + let seq = save_changelog_event(cl, bundle.slot, bundle.txn_id, txn, cl_audits).await?; + return match le.schema { + LeafSchema::V1 { + id, + owner, + delegate, + .. + } => { + let id_bytes = id.to_bytes(); + let owner_bytes = owner.to_bytes().to_vec(); + let delegate = if owner == delegate || delegate.to_bytes() == [0; 32] { + None + } else { + Some(delegate.to_bytes().to_vec()) + }; + let tree_id = cl.id.to_bytes(); + + // Partial update of asset table with just leaf. + upsert_asset_with_leaf_info( + txn, + id_bytes.to_vec(), + cl.index as i64, + tree_id.to_vec(), + le.leaf_hash.to_vec(), + le.schema.data_hash(), + le.schema.creator_hash(), + seq as i64, + false, + ) + .await?; + + // Partial update of asset table with just leaf owner and delegate. + upsert_asset_with_owner_and_delegate_info( + txn, + id_bytes.to_vec(), + owner_bytes, + delegate, + seq as i64, + ) + .await?; + + upsert_asset_with_seq(txn, id_bytes.to_vec(), seq as i64).await + } + }; + } + Err(ProgramTransformerError::ParsingError( + "Ix not parsed correctly".to_string(), + )) +} diff --git a/program_transformers/src/bubblegum/mint_v1.rs b/program_transformers/src/bubblegum/mint_v1.rs new file mode 100644 index 000000000..cccf60d7a --- /dev/null +++ b/program_transformers/src/bubblegum/mint_v1.rs @@ -0,0 +1,364 @@ +use { + crate::{ + bubblegum::db::{ + save_changelog_event, upsert_asset_with_compression_info, upsert_asset_with_leaf_info, + upsert_asset_with_owner_and_delegate_info, upsert_asset_with_seq, + upsert_collection_info, + }, + error::{ProgramTransformerError, ProgramTransformerResult}, + DownloadMetadataInfo, + }, + blockbuster::{ + instruction::InstructionBundle, + programs::bubblegum::{BubblegumInstruction, LeafSchema, Payload}, + token_metadata::{ + pda::find_master_edition_account, + state::{TokenStandard, UseMethod, Uses}, + }, + }, + digital_asset_types::{ + dao::{ + asset, asset_authority, asset_creators, asset_data, asset_v1_account_attachments, + sea_orm_active_enums::{ + ChainMutability, Mutability, OwnerType, RoyaltyTargetType, SpecificationAssetClass, + SpecificationVersions, V1AccountAttachments, + }, + }, + json::ChainDataV1, + }, + num_traits::FromPrimitive, + sea_orm::{ + entity::{ActiveValue, EntityTrait}, + query::{JsonValue, QueryTrait}, + sea_query::query::OnConflict, + ConnectionTrait, DbBackend, TransactionTrait, + }, + std::collections::HashSet, + tracing::warn, +}; + +// TODO -> consider moving structs into these functions to avoid clone + +pub async fn mint_v1<'c, T>( + parsing_result: &BubblegumInstruction, + bundle: &InstructionBundle<'c>, + txn: &'c T, + cl_audits: bool, +) -> ProgramTransformerResult> +where + T: ConnectionTrait + TransactionTrait, +{ + if let (Some(le), Some(cl), Some(Payload::MintV1 { args })) = ( + &parsing_result.leaf_update, + &parsing_result.tree_update, + &parsing_result.payload, + ) { + let seq = save_changelog_event(cl, bundle.slot, bundle.txn_id, txn, cl_audits).await?; + let metadata = args; + #[allow(unreachable_patterns)] + return match le.schema { + LeafSchema::V1 { + id, + delegate, + owner, + nonce, + .. + } => { + let (edition_attachment_address, _) = find_master_edition_account(&id); + let id_bytes = id.to_bytes(); + let slot_i = bundle.slot as i64; + let uri = metadata.uri.replace('\0', ""); + let name = metadata.name.clone().into_bytes(); + let symbol = metadata.symbol.clone().into_bytes(); + let mut chain_data = ChainDataV1 { + name: metadata.name.clone(), + symbol: metadata.symbol.clone(), + edition_nonce: metadata.edition_nonce, + primary_sale_happened: metadata.primary_sale_happened, + token_standard: Some(TokenStandard::NonFungible), + uses: metadata.uses.clone().map(|u| Uses { + use_method: UseMethod::from_u8(u.use_method as u8).unwrap(), + remaining: u.remaining, + total: u.total, + }), + }; + chain_data.sanitize(); + let chain_data_json = serde_json::to_value(chain_data) + .map_err(|e| ProgramTransformerError::DeserializationError(e.to_string()))?; + let chain_mutability = match metadata.is_mutable { + true => ChainMutability::Mutable, + false => ChainMutability::Immutable, + }; + + let data = asset_data::ActiveModel { + id: ActiveValue::Set(id_bytes.to_vec()), + chain_data_mutability: ActiveValue::Set(chain_mutability), + chain_data: ActiveValue::Set(chain_data_json), + metadata_url: ActiveValue::Set(uri.clone()), + metadata: ActiveValue::Set(JsonValue::String("processing".to_string())), + metadata_mutability: ActiveValue::Set(Mutability::Mutable), + slot_updated: ActiveValue::Set(slot_i), + reindex: ActiveValue::Set(Some(true)), + raw_name: ActiveValue::Set(name.to_vec()), + raw_symbol: ActiveValue::Set(symbol.to_vec()), + }; + + let mut query = asset_data::Entity::insert(data) + .on_conflict( + OnConflict::columns([asset_data::Column::Id]) + .update_columns([ + asset_data::Column::ChainDataMutability, + asset_data::Column::ChainData, + asset_data::Column::MetadataUrl, + asset_data::Column::MetadataMutability, + asset_data::Column::SlotUpdated, + asset_data::Column::Reindex, + asset_data::Column::RawName, + asset_data::Column::RawSymbol, + ]) + .to_owned(), + ) + .build(DbBackend::Postgres); + query.sql = format!( + "{} WHERE excluded.slot_updated > asset_data.slot_updated", + query.sql + ); + txn.execute(query).await.map_err(|db_err| { + ProgramTransformerError::AssetIndexError(db_err.to_string()) + })?; + // Insert into `asset` table. + let delegate = if owner == delegate || delegate.to_bytes() == [0; 32] { + None + } else { + Some(delegate.to_bytes().to_vec()) + }; + let tree_id = bundle.keys.get(3).unwrap().0.to_vec(); + + // ActiveValue::Set initial mint info. + let asset_model = asset::ActiveModel { + id: ActiveValue::Set(id_bytes.to_vec()), + owner_type: ActiveValue::Set(OwnerType::Single), + frozen: ActiveValue::Set(false), + tree_id: ActiveValue::Set(Some(tree_id.clone())), + specification_version: ActiveValue::Set(Some(SpecificationVersions::V1)), + specification_asset_class: ActiveValue::Set(Some(SpecificationAssetClass::Nft)), + nonce: ActiveValue::Set(Some(nonce as i64)), + royalty_target_type: ActiveValue::Set(RoyaltyTargetType::Creators), + royalty_target: ActiveValue::Set(None), + royalty_amount: ActiveValue::Set(metadata.seller_fee_basis_points as i32), //basis points + asset_data: ActiveValue::Set(Some(id_bytes.to_vec())), + slot_updated: ActiveValue::Set(Some(slot_i)), + ..Default::default() + }; + + // Upsert asset table base info. + let mut query = asset::Entity::insert(asset_model) + .on_conflict( + OnConflict::columns([asset::Column::Id]) + .update_columns([ + asset::Column::OwnerType, + asset::Column::Frozen, + asset::Column::SpecificationVersion, + asset::Column::SpecificationAssetClass, + asset::Column::RoyaltyTargetType, + asset::Column::RoyaltyTarget, + asset::Column::RoyaltyAmount, + asset::Column::AssetData, + ]) + .to_owned(), + ) + .build(DbBackend::Postgres); + + // Do not overwrite changes that happened after the asset was decompressed. + query.sql = format!( + "{} WHERE excluded.slot_updated > asset.slot_updated OR asset.slot_updated IS NULL", + query.sql + ); + txn.execute(query).await.map_err(|db_err| { + ProgramTransformerError::AssetIndexError(db_err.to_string()) + })?; + + // Partial update of asset table with just compression info elements. + upsert_asset_with_compression_info( + txn, + id_bytes.to_vec(), + true, + false, + 1, + None, + false, + ) + .await?; + + // Partial update of asset table with just leaf. + upsert_asset_with_leaf_info( + txn, + id_bytes.to_vec(), + nonce as i64, + tree_id, + le.leaf_hash.to_vec(), + le.schema.data_hash(), + le.schema.creator_hash(), + seq as i64, + false, + ) + .await?; + + // Partial update of asset table with just leaf owner and delegate. + upsert_asset_with_owner_and_delegate_info( + txn, + id_bytes.to_vec(), + owner.to_bytes().to_vec(), + delegate, + seq as i64, + ) + .await?; + + upsert_asset_with_seq(txn, id_bytes.to_vec(), seq as i64).await?; + + let attachment = asset_v1_account_attachments::ActiveModel { + id: ActiveValue::Set(edition_attachment_address.to_bytes().to_vec()), + slot_updated: ActiveValue::Set(slot_i), + attachment_type: ActiveValue::Set(V1AccountAttachments::MasterEditionV2), + ..Default::default() + }; + + let query = asset_v1_account_attachments::Entity::insert(attachment) + .on_conflict( + OnConflict::columns([asset_v1_account_attachments::Column::Id]) + .do_nothing() + .to_owned(), + ) + .build(DbBackend::Postgres); + txn.execute(query).await.map_err(|db_err| { + ProgramTransformerError::AssetIndexError(db_err.to_string()) + })?; + + // Insert into `asset_creators` table. + let creators = &metadata.creators; + if !creators.is_empty() { + // Vec to hold base creator information. + let mut db_creator_infos = Vec::with_capacity(creators.len()); + + // Vec to hold info on whether a creator is verified. This info is protected by `seq` number. + let mut db_creator_verified_infos = Vec::with_capacity(creators.len()); + + // Set to prevent duplicates. + let mut creators_set = HashSet::new(); + + for (i, c) in creators.iter().enumerate() { + if creators_set.contains(&c.address) { + continue; + } + db_creator_infos.push(asset_creators::ActiveModel { + asset_id: ActiveValue::Set(id_bytes.to_vec()), + creator: ActiveValue::Set(c.address.to_bytes().to_vec()), + position: ActiveValue::Set(i as i16), + share: ActiveValue::Set(c.share as i32), + slot_updated: ActiveValue::Set(Some(slot_i)), + ..Default::default() + }); + + db_creator_verified_infos.push(asset_creators::ActiveModel { + asset_id: ActiveValue::Set(id_bytes.to_vec()), + creator: ActiveValue::Set(c.address.to_bytes().to_vec()), + verified: ActiveValue::Set(c.verified), + seq: ActiveValue::Set(Some(seq as i64)), + ..Default::default() + }); + + creators_set.insert(c.address); + } + + // This statement will update base information for each creator. + let query = asset_creators::Entity::insert_many(db_creator_infos) + .on_conflict( + OnConflict::columns([ + asset_creators::Column::AssetId, + asset_creators::Column::Creator, + ]) + .update_columns([ + asset_creators::Column::Position, + asset_creators::Column::Share, + asset_creators::Column::SlotUpdated, + ]) + .to_owned(), + ) + .build(DbBackend::Postgres); + txn.execute(query).await?; + + // This statement will update whether the creator is verified and the `seq` + // number. `seq` is used to protect the `verified` field, allowing for `mint` + // and `verifyCreator` to be processed out of order. + let mut query = asset_creators::Entity::insert_many(db_creator_verified_infos) + .on_conflict( + OnConflict::columns([ + asset_creators::Column::AssetId, + asset_creators::Column::Creator, + ]) + .update_columns([ + asset_creators::Column::Verified, + asset_creators::Column::Seq, + ]) + .to_owned(), + ) + .build(DbBackend::Postgres); + query.sql = format!( + "{} WHERE excluded.seq > asset_creators.seq OR asset_creators.seq IS NULL", + query.sql + ); + txn.execute(query).await?; + } + + // Insert into `asset_authority` table. + let model = asset_authority::ActiveModel { + asset_id: ActiveValue::Set(id_bytes.to_vec()), + authority: ActiveValue::Set(bundle.keys.get(0).unwrap().0.to_vec()), //TODO - we need to rem,ove the optional bubblegum signer logic + seq: ActiveValue::Set(seq as i64), + slot_updated: ActiveValue::Set(slot_i), + ..Default::default() + }; + + // Do not attempt to modify any existing values: + // `ON CONFLICT ('asset_id') DO NOTHING`. + let query = asset_authority::Entity::insert(model) + .on_conflict( + OnConflict::columns([asset_authority::Column::AssetId]) + .do_nothing() + .to_owned(), + ) + .build(DbBackend::Postgres); + txn.execute(query).await.map_err(|db_err| { + ProgramTransformerError::AssetIndexError(db_err.to_string()) + })?; + + // Upsert into `asset_grouping` table with base collection info. + upsert_collection_info( + txn, + id_bytes.to_vec(), + metadata.collection.clone(), + slot_i, + seq as i64, + ) + .await?; + + if uri.is_empty() { + warn!( + "URI is empty for mint {}. Skipping background task.", + bs58::encode(id).into_string() + ); + return Ok(None); + } + + Ok(Some(DownloadMetadataInfo::new( + id_bytes.to_vec(), + metadata.uri.clone(), + ))) + } + _ => Err(ProgramTransformerError::NotImplemented), + }; + } + Err(ProgramTransformerError::ParsingError( + "Ix not parsed correctly".to_string(), + )) +} diff --git a/program_transformers/src/bubblegum/mod.rs b/program_transformers/src/bubblegum/mod.rs new file mode 100644 index 000000000..4752d9b6d --- /dev/null +++ b/program_transformers/src/bubblegum/mod.rs @@ -0,0 +1,108 @@ +use { + crate::{ + error::{ProgramTransformerError, ProgramTransformerResult}, + DownloadMetadataNotifier, + }, + blockbuster::{ + instruction::InstructionBundle, + programs::bubblegum::{BubblegumInstruction, InstructionName}, + }, + sea_orm::{ConnectionTrait, TransactionTrait}, + tracing::{debug, info}, +}; + +mod burn; +mod cancel_redeem; +mod collection_verification; +mod creator_verification; +mod db; +mod decompress; +mod delegate; +mod mint_v1; +mod redeem; +mod transfer; + +pub async fn handle_bubblegum_instruction<'c, T>( + parsing_result: &'c BubblegumInstruction, + bundle: &'c InstructionBundle<'c>, + txn: &T, + download_metadata_notifier: &DownloadMetadataNotifier, + cl_audits: bool, +) -> ProgramTransformerResult<()> +where + T: ConnectionTrait + TransactionTrait, +{ + let ix_type = &parsing_result.instruction; + + // @TODO this would be much better served by implemneting Debug trait on the InstructionName + // or wrapping it into something that can display it more neatly. + let ix_str = match ix_type { + InstructionName::Unknown => "Unknown", + InstructionName::MintV1 => "MintV1", + InstructionName::MintToCollectionV1 => "MintToCollectionV1", + InstructionName::Redeem => "Redeem", + InstructionName::CancelRedeem => "CancelRedeem", + InstructionName::Transfer => "Transfer", + InstructionName::Delegate => "Delegate", + InstructionName::DecompressV1 => "DecompressV1", + InstructionName::Compress => "Compress", + InstructionName::Burn => "Burn", + InstructionName::CreateTree => "CreateTree", + InstructionName::VerifyCreator => "VerifyCreator", + InstructionName::UnverifyCreator => "UnverifyCreator", + InstructionName::VerifyCollection => "VerifyCollection", + InstructionName::UnverifyCollection => "UnverifyCollection", + InstructionName::SetAndVerifyCollection => "SetAndVerifyCollection", + InstructionName::SetDecompressibleState | InstructionName::UpdateMetadata => todo!(), + }; + info!("BGUM instruction txn={:?}: {:?}", ix_str, bundle.txn_id); + + match ix_type { + InstructionName::Transfer => { + transfer::transfer(parsing_result, bundle, txn, cl_audits).await?; + } + InstructionName::Burn => { + burn::burn(parsing_result, bundle, txn, cl_audits).await?; + } + InstructionName::Delegate => { + delegate::delegate(parsing_result, bundle, txn, cl_audits).await?; + } + InstructionName::MintV1 | InstructionName::MintToCollectionV1 => { + if let Some(info) = mint_v1::mint_v1(parsing_result, bundle, txn, cl_audits).await? { + download_metadata_notifier(info) + .await + .map_err(ProgramTransformerError::DownloadMetadataNotify)?; + } + } + InstructionName::Redeem => { + redeem::redeem(parsing_result, bundle, txn, cl_audits).await?; + } + InstructionName::CancelRedeem => { + cancel_redeem::cancel_redeem(parsing_result, bundle, txn, cl_audits).await?; + } + InstructionName::DecompressV1 => { + decompress::decompress(parsing_result, bundle, txn).await?; + } + InstructionName::VerifyCreator => { + creator_verification::process(parsing_result, bundle, txn, true, cl_audits).await?; + } + InstructionName::UnverifyCreator => { + creator_verification::process(parsing_result, bundle, txn, false, cl_audits).await?; + } + InstructionName::VerifyCollection + | InstructionName::UnverifyCollection + | InstructionName::SetAndVerifyCollection => { + collection_verification::process(parsing_result, bundle, txn, cl_audits).await?; + } + _ => debug!("Bubblegum: Not Implemented Instruction"), + } + Ok(()) +} + +// PDA lookup requires an 8-byte array. +fn u32_to_u8_array(value: u32) -> [u8; 8] { + let bytes: [u8; 4] = value.to_le_bytes(); + let mut result: [u8; 8] = [0; 8]; + result[..4].copy_from_slice(&bytes); + result +} diff --git a/program_transformers/src/bubblegum/redeem.rs b/program_transformers/src/bubblegum/redeem.rs new file mode 100644 index 000000000..894f2bcc7 --- /dev/null +++ b/program_transformers/src/bubblegum/redeem.rs @@ -0,0 +1,61 @@ +use { + crate::{ + bubblegum::{ + db::{save_changelog_event, upsert_asset_with_leaf_info, upsert_asset_with_seq}, + u32_to_u8_array, + }, + error::{ProgramTransformerError, ProgramTransformerResult}, + }, + blockbuster::{instruction::InstructionBundle, programs::bubblegum::BubblegumInstruction}, + sea_orm::{ConnectionTrait, TransactionTrait}, + solana_sdk::pubkey::Pubkey, + tracing::debug, +}; + +pub async fn redeem<'c, T>( + parsing_result: &BubblegumInstruction, + bundle: &InstructionBundle<'c>, + txn: &'c T, + cl_audits: bool, +) -> ProgramTransformerResult<()> +where + T: ConnectionTrait + TransactionTrait, +{ + if let Some(cl) = &parsing_result.tree_update { + let seq = save_changelog_event(cl, bundle.slot, bundle.txn_id, txn, cl_audits).await?; + let leaf_index = cl.index; + let (asset_id, _) = Pubkey::find_program_address( + &[ + "asset".as_bytes(), + cl.id.as_ref(), + u32_to_u8_array(leaf_index).as_ref(), + ], + &mpl_bubblegum::ID, + ); + debug!("Indexing redeem for asset id: {:?}", asset_id); + let id_bytes = asset_id.to_bytes(); + let tree_id = cl.id.to_bytes(); + let nonce = cl.index as i64; + + // Partial update of asset table with just leaf. + upsert_asset_with_leaf_info( + txn, + id_bytes.to_vec(), + nonce, + tree_id.to_vec(), + vec![0; 32], + [0; 32], + [0; 32], + seq as i64, + false, + ) + .await?; + + upsert_asset_with_seq(txn, id_bytes.to_vec(), seq as i64).await?; + + return Ok(()); + } + Err(ProgramTransformerError::ParsingError( + "Ix not parsed correctly".to_string(), + )) +} diff --git a/program_transformers/src/bubblegum/transfer.rs b/program_transformers/src/bubblegum/transfer.rs new file mode 100644 index 000000000..89fc0ef85 --- /dev/null +++ b/program_transformers/src/bubblegum/transfer.rs @@ -0,0 +1,76 @@ +use { + crate::{ + bubblegum::db::{ + save_changelog_event, upsert_asset_with_leaf_info, + upsert_asset_with_owner_and_delegate_info, upsert_asset_with_seq, + }, + error::{ProgramTransformerError, ProgramTransformerResult}, + }, + blockbuster::{ + instruction::InstructionBundle, + programs::bubblegum::{BubblegumInstruction, LeafSchema}, + }, + sea_orm::{ConnectionTrait, TransactionTrait}, +}; + +pub async fn transfer<'c, T>( + parsing_result: &BubblegumInstruction, + bundle: &InstructionBundle<'c>, + txn: &'c T, + cl_audits: bool, +) -> ProgramTransformerResult<()> +where + T: ConnectionTrait + TransactionTrait, +{ + if let (Some(le), Some(cl)) = (&parsing_result.leaf_update, &parsing_result.tree_update) { + let seq = save_changelog_event(cl, bundle.slot, bundle.txn_id, txn, cl_audits).await?; + #[allow(unreachable_patterns)] + return match le.schema { + LeafSchema::V1 { + id, + owner, + delegate, + .. + } => { + let id_bytes = id.to_bytes(); + let owner_bytes = owner.to_bytes().to_vec(); + let delegate = if owner == delegate || delegate.to_bytes() == [0; 32] { + None + } else { + Some(delegate.to_bytes().to_vec()) + }; + let tree_id = cl.id.to_bytes(); + let nonce = cl.index as i64; + + // Partial update of asset table with just leaf. + upsert_asset_with_leaf_info( + txn, + id_bytes.to_vec(), + nonce, + tree_id.to_vec(), + le.leaf_hash.to_vec(), + le.schema.data_hash(), + le.schema.creator_hash(), + seq as i64, + false, + ) + .await?; + + // Partial update of asset table with just leaf owner and delegate. + upsert_asset_with_owner_and_delegate_info( + txn, + id_bytes.to_vec(), + owner_bytes, + delegate, + seq as i64, + ) + .await?; + + upsert_asset_with_seq(txn, id_bytes.to_vec(), seq as i64).await + } + }; + } + Err(ProgramTransformerError::ParsingError( + "Ix not parsed correctly".to_string(), + )) +} diff --git a/program_transformers/src/error.rs b/program_transformers/src/error.rs new file mode 100644 index 000000000..98449f9ef --- /dev/null +++ b/program_transformers/src/error.rs @@ -0,0 +1,36 @@ +use blockbuster::error::BlockbusterError; +use sea_orm::DbErr; + +pub type ProgramTransformerResult = Result; + +#[derive(Debug, thiserror::Error)] +pub enum ProgramTransformerError { + #[error("Storage Write Error: {0}")] + StorageWriteError(String), + #[error("NotImplemented")] + NotImplemented, + #[error("Deserialization Error: {0}")] + DeserializationError(String), + #[error("Data serializaton error: {0}")] + SerializatonError(String), + #[error("Blockbuster Parsing error: {0}")] + ParsingError(String), + #[error("Database Error: {0}")] + DatabaseError(String), + #[error("AssetIndex Error {0}")] + AssetIndexError(String), + #[error("Failed to notify about download metadata: {0}")] + DownloadMetadataNotify(Box), +} + +impl From for ProgramTransformerError { + fn from(err: BlockbusterError) -> Self { + ProgramTransformerError::ParsingError(err.to_string()) + } +} + +impl From for ProgramTransformerError { + fn from(e: DbErr) -> Self { + ProgramTransformerError::StorageWriteError(e.to_string()) + } +} diff --git a/program_transformers/src/lib.rs b/program_transformers/src/lib.rs new file mode 100644 index 000000000..1b58e977b --- /dev/null +++ b/program_transformers/src/lib.rs @@ -0,0 +1,220 @@ +use { + crate::{ + bubblegum::handle_bubblegum_instruction, + error::{ProgramTransformerError, ProgramTransformerResult}, + token::handle_token_program_account, + token_metadata::handle_token_metadata_account, + }, + blockbuster::{ + instruction::{order_instructions, InstructionBundle, IxPair}, + program_handler::ProgramParser, + programs::{ + bubblegum::BubblegumParser, token_account::TokenAccountParser, + token_metadata::TokenMetadataParser, ProgramParseResult, + }, + }, + futures::future::BoxFuture, + plerkle_serialization::{AccountInfo, Pubkey as FBPubkey, TransactionInfo}, + sea_orm::{DatabaseConnection, SqlxPostgresConnector}, + solana_sdk::pubkey::Pubkey, + sqlx::PgPool, + std::collections::{HashMap, HashSet, VecDeque}, + tracing::{debug, error, info}, +}; + +mod bubblegum; +mod error; +mod token; +mod token_metadata; + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct DownloadMetadataInfo { + asset_data_id: Vec, + uri: String, +} + +impl DownloadMetadataInfo { + pub fn new(asset_data_id: Vec, uri: String) -> Self { + Self { + asset_data_id, + uri: uri.trim().replace('\0', ""), + } + } + + pub fn into_inner(self) -> (Vec, String) { + (self.asset_data_id, self.uri) + } +} + +pub type DownloadMetadataNotifier = Box< + dyn Fn( + DownloadMetadataInfo, + ) -> BoxFuture<'static, Result<(), Box>>, +>; + +pub struct ProgramTransformer { + storage: DatabaseConnection, + download_metadata_notifier: DownloadMetadataNotifier, + parsers: HashMap>, + key_set: HashSet, + cl_audits: bool, +} + +impl ProgramTransformer { + pub fn new( + pool: PgPool, + download_metadata_notifier: DownloadMetadataNotifier, + cl_audits: bool, + ) -> Self { + let mut parsers: HashMap> = HashMap::with_capacity(1); + let bgum = BubblegumParser {}; + let token_metadata = TokenMetadataParser {}; + let token = TokenAccountParser {}; + parsers.insert(bgum.key(), Box::new(bgum)); + parsers.insert(token_metadata.key(), Box::new(token_metadata)); + parsers.insert(token.key(), Box::new(token)); + let hs = parsers.iter().fold(HashSet::new(), |mut acc, (k, _)| { + acc.insert(*k); + acc + }); + ProgramTransformer { + storage: SqlxPostgresConnector::from_sqlx_postgres_pool(pool), + download_metadata_notifier, + parsers, + key_set: hs, + cl_audits, + } + } + + pub fn break_transaction<'i>( + &self, + tx: &'i TransactionInfo<'i>, + ) -> VecDeque<(IxPair<'i>, Option>>)> { + let ref_set: HashSet<&[u8]> = self.key_set.iter().map(|k| k.as_ref()).collect(); + order_instructions(ref_set, tx) + } + + #[allow(clippy::borrowed_box)] + pub fn match_program(&self, key: &FBPubkey) -> Option<&Box> { + self.parsers + .get(&Pubkey::try_from(key.0.as_slice()).expect("valid key from FlatBuffer")) + } + + pub async fn handle_transaction<'a>( + &self, + tx: &'a TransactionInfo<'a>, + ) -> ProgramTransformerResult<()> { + let sig: Option<&str> = tx.signature(); + info!("Handling Transaction: {:?}", sig); + let instructions = self.break_transaction(tx); + let accounts = tx.account_keys().unwrap_or_default(); + let slot = tx.slot(); + let txn_id = tx.signature().unwrap_or(""); + let mut keys: Vec = Vec::with_capacity(accounts.len()); + for k in accounts.into_iter() { + keys.push(*k); + } + let mut not_impl = 0; + let ixlen = instructions.len(); + debug!("Instructions: {}", ixlen); + let contains = instructions + .iter() + .filter(|(ib, _inner)| ib.0 .0.as_ref() == mpl_bubblegum::ID.as_ref()); + debug!("Instructions bgum: {}", contains.count()); + for (outer_ix, inner_ix) in instructions { + let (program, instruction) = outer_ix; + let ix_accounts = instruction.accounts().unwrap().iter().collect::>(); + let ix_account_len = ix_accounts.len(); + let max = ix_accounts.iter().max().copied().unwrap_or(0) as usize; + if keys.len() < max { + return Err(ProgramTransformerError::DeserializationError( + "Missing Accounts in Serialized Ixn/Txn".to_string(), + )); + } + let ix_accounts = + ix_accounts + .iter() + .fold(Vec::with_capacity(ix_account_len), |mut acc, a| { + if let Some(key) = keys.get(*a as usize) { + acc.push(*key); + } + acc + }); + let ix = InstructionBundle { + txn_id, + program, + instruction: Some(instruction), + inner_ix, + keys: ix_accounts.as_slice(), + slot, + }; + + if let Some(program) = self.match_program(&ix.program) { + debug!("Found a ix for program: {:?}", program.key()); + let result = program.handle_instruction(&ix)?; + let concrete = result.result_type(); + match concrete { + ProgramParseResult::Bubblegum(parsing_result) => { + handle_bubblegum_instruction( + parsing_result, + &ix, + &self.storage, + &self.download_metadata_notifier, + self.cl_audits, + ) + .await + .map_err(|err| { + error!( + "Failed to handle bubblegum instruction for txn {:?}: {:?}", + sig, err + ); + err + })?; + } + _ => { + not_impl += 1; + } + }; + } + } + + if not_impl == ixlen { + debug!("Not imple"); + return Err(ProgramTransformerError::NotImplemented); + } + Ok(()) + } + + pub async fn handle_account_update<'b>( + &self, + acct: AccountInfo<'b>, + ) -> ProgramTransformerResult<()> { + let owner = acct.owner().unwrap(); + if let Some(program) = self.match_program(owner) { + let result = program.handle_account(&acct)?; + let concrete = result.result_type(); + match concrete { + ProgramParseResult::TokenMetadata(parsing_result) => { + handle_token_metadata_account( + &acct, + parsing_result, + &self.storage, + &self.download_metadata_notifier, + ) + .await + } + ProgramParseResult::TokenProgramAccount(parsing_result) => { + handle_token_program_account( + &acct, + parsing_result, + &self.storage, + &self.download_metadata_notifier, + ) + .await + } + _ => Err(ProgramTransformerError::NotImplemented), + }?; + } + Ok(()) + } +} diff --git a/program_transformers/src/token/mod.rs b/program_transformers/src/token/mod.rs new file mode 100644 index 000000000..690c44cae --- /dev/null +++ b/program_transformers/src/token/mod.rs @@ -0,0 +1,147 @@ +use { + crate::{ + error::{ProgramTransformerError, ProgramTransformerResult}, + DownloadMetadataNotifier, + }, + blockbuster::programs::token_account::TokenProgramAccount, + digital_asset_types::dao::{asset, token_accounts, tokens}, + plerkle_serialization::AccountInfo, + sea_orm::{ + entity::{ActiveModelTrait, ActiveValue, ColumnTrait}, + query::{QueryFilter, QueryTrait}, + sea_query::query::OnConflict, + ConnectionTrait, DatabaseConnection, DbBackend, EntityTrait, TransactionTrait, + }, + solana_sdk::program_option::COption, + spl_token::state::AccountState, +}; + +pub async fn handle_token_program_account<'a, 'b, 'c>( + account_update: &'a AccountInfo<'a>, + parsing_result: &'b TokenProgramAccount, + db: &'c DatabaseConnection, + _download_metadata_notifier: &DownloadMetadataNotifier, +) -> ProgramTransformerResult<()> { + let key = *account_update.pubkey().unwrap(); + let key_bytes = key.0.to_vec(); + let spl_token_program = account_update.owner().unwrap().0.to_vec(); + match &parsing_result { + TokenProgramAccount::TokenAccount(ta) => { + let mint = ta.mint.to_bytes().to_vec(); + let delegate: Option> = match ta.delegate { + COption::Some(d) => Some(d.to_bytes().to_vec()), + COption::None => None, + }; + let frozen = matches!(ta.state, AccountState::Frozen); + let owner = ta.owner.to_bytes().to_vec(); + let model = token_accounts::ActiveModel { + pubkey: ActiveValue::Set(key_bytes), + mint: ActiveValue::Set(mint.clone()), + delegate: ActiveValue::Set(delegate.clone()), + owner: ActiveValue::Set(owner.clone()), + frozen: ActiveValue::Set(frozen), + delegated_amount: ActiveValue::Set(ta.delegated_amount as i64), + token_program: ActiveValue::Set(spl_token_program), + slot_updated: ActiveValue::Set(account_update.slot() as i64), + amount: ActiveValue::Set(ta.amount as i64), + close_authority: ActiveValue::Set(None), + }; + + let mut query = token_accounts::Entity::insert(model) + .on_conflict( + OnConflict::columns([token_accounts::Column::Pubkey]) + .update_columns([ + token_accounts::Column::Mint, + token_accounts::Column::DelegatedAmount, + token_accounts::Column::Delegate, + token_accounts::Column::Amount, + token_accounts::Column::Frozen, + token_accounts::Column::TokenProgram, + token_accounts::Column::Owner, + token_accounts::Column::CloseAuthority, + token_accounts::Column::SlotUpdated, + ]) + .to_owned(), + ) + .build(DbBackend::Postgres); + query.sql = format!( + "{} WHERE excluded.slot_updated > token_accounts.slot_updated", + query.sql + ); + db.execute(query).await?; + let txn = db.begin().await?; + let asset_update: Option = asset::Entity::find_by_id(mint) + .filter(asset::Column::OwnerType.eq("single")) + .one(&txn) + .await?; + if let Some(asset) = asset_update { + // will only update owner if token account balance is non-zero + if ta.amount > 0 { + let mut active: asset::ActiveModel = asset.into(); + active.owner = ActiveValue::Set(Some(owner)); + active.delegate = ActiveValue::Set(delegate); + active.frozen = ActiveValue::Set(frozen); + active.save(&txn).await?; + } + } + txn.commit().await?; + Ok(()) + } + TokenProgramAccount::Mint(m) => { + let freeze_auth: Option> = match m.freeze_authority { + COption::Some(d) => Some(d.to_bytes().to_vec()), + COption::None => None, + }; + let mint_auth: Option> = match m.mint_authority { + COption::Some(d) => Some(d.to_bytes().to_vec()), + COption::None => None, + }; + let model = tokens::ActiveModel { + mint: ActiveValue::Set(key_bytes.clone()), + token_program: ActiveValue::Set(spl_token_program), + slot_updated: ActiveValue::Set(account_update.slot() as i64), + supply: ActiveValue::Set(m.supply as i64), + decimals: ActiveValue::Set(m.decimals as i32), + close_authority: ActiveValue::Set(None), + extension_data: ActiveValue::Set(None), + mint_authority: ActiveValue::Set(mint_auth), + freeze_authority: ActiveValue::Set(freeze_auth), + }; + + let mut query = tokens::Entity::insert(model) + .on_conflict( + OnConflict::columns([tokens::Column::Mint]) + .update_columns([ + tokens::Column::Supply, + tokens::Column::TokenProgram, + tokens::Column::MintAuthority, + tokens::Column::CloseAuthority, + tokens::Column::ExtensionData, + tokens::Column::SlotUpdated, + tokens::Column::Decimals, + tokens::Column::FreezeAuthority, + ]) + .to_owned(), + ) + .build(DbBackend::Postgres); + query.sql = format!( + "{} WHERE excluded.slot_updated > tokens.slot_updated", + query.sql + ); + db.execute(query).await?; + let asset_update: Option = asset::Entity::find_by_id(key_bytes.clone()) + .filter(asset::Column::OwnerType.eq("single")) + .one(db) + .await?; + if let Some(asset) = asset_update { + let mut active: asset::ActiveModel = asset.into(); + active.supply = ActiveValue::Set(m.supply as i64); + active.supply_mint = ActiveValue::Set(Some(key_bytes)); + active.save(db).await?; + } + Ok(()) + } + _ => Err(ProgramTransformerError::NotImplemented), + }?; + Ok(()) +} diff --git a/program_transformers/src/token_metadata/master_edition.rs b/program_transformers/src/token_metadata/master_edition.rs new file mode 100644 index 000000000..2cba19853 --- /dev/null +++ b/program_transformers/src/token_metadata/master_edition.rs @@ -0,0 +1,98 @@ +use { + crate::error::{ProgramTransformerError, ProgramTransformerResult}, + blockbuster::token_metadata::state::{Key, MasterEditionV1, MasterEditionV2}, + digital_asset_types::dao::{ + asset, asset_v1_account_attachments, + sea_orm_active_enums::{SpecificationAssetClass, V1AccountAttachments}, + }, + plerkle_serialization::Pubkey as FBPubkey, + sea_orm::{ + entity::{ActiveModelTrait, ActiveValue, EntityTrait, RelationTrait}, + query::{JoinType, QuerySelect, QueryTrait}, + sea_query::query::OnConflict, + ConnectionTrait, DatabaseTransaction, DbBackend, + }, +}; + +pub async fn save_v2_master_edition( + id: FBPubkey, + slot: u64, + me_data: &MasterEditionV2, + txn: &DatabaseTransaction, +) -> ProgramTransformerResult<()> { + save_master_edition( + V1AccountAttachments::MasterEditionV2, + id, + slot, + me_data, + txn, + ) + .await +} + +pub async fn save_v1_master_edition( + id: FBPubkey, + slot: u64, + me_data: &MasterEditionV1, + txn: &DatabaseTransaction, +) -> ProgramTransformerResult<()> { + let bridge = MasterEditionV2 { + supply: me_data.supply, + max_supply: me_data.max_supply, + key: Key::MasterEditionV1, // is this weird? + }; + save_master_edition( + V1AccountAttachments::MasterEditionV1, + id, + slot, + &bridge, + txn, + ) + .await +} +pub async fn save_master_edition( + _version: V1AccountAttachments, + id: FBPubkey, + slot: u64, + me_data: &MasterEditionV2, + txn: &DatabaseTransaction, +) -> ProgramTransformerResult<()> { + let id_bytes = id.0.to_vec(); + let master_edition: Option<(asset_v1_account_attachments::Model, Option)> = + asset_v1_account_attachments::Entity::find_by_id(id.0.to_vec()) + .find_also_related(asset::Entity) + .join(JoinType::InnerJoin, asset::Relation::AssetData.def()) + .one(txn) + .await?; + let ser = serde_json::to_value(me_data) + .map_err(|e| ProgramTransformerError::SerializatonError(e.to_string()))?; + + let model = asset_v1_account_attachments::ActiveModel { + id: ActiveValue::Set(id_bytes), + attachment_type: ActiveValue::Set(V1AccountAttachments::MasterEditionV1), + data: ActiveValue::Set(Some(ser)), + slot_updated: ActiveValue::Set(slot as i64), + ..Default::default() + }; + + if let Some((_me, Some(asset))) = master_edition { + let mut updatable: asset::ActiveModel = asset.into(); + updatable.supply = ActiveValue::Set(1); + updatable.specification_asset_class = ActiveValue::Set(Some(SpecificationAssetClass::Nft)); + updatable.update(txn).await?; + } + + let query = asset_v1_account_attachments::Entity::insert(model) + .on_conflict( + OnConflict::columns([asset_v1_account_attachments::Column::Id]) + .update_columns([ + asset_v1_account_attachments::Column::AttachmentType, + asset_v1_account_attachments::Column::Data, + asset_v1_account_attachments::Column::SlotUpdated, + ]) + .to_owned(), + ) + .build(DbBackend::Postgres); + txn.execute(query).await?; + Ok(()) +} diff --git a/program_transformers/src/token_metadata/mod.rs b/program_transformers/src/token_metadata/mod.rs new file mode 100644 index 000000000..708b7f867 --- /dev/null +++ b/program_transformers/src/token_metadata/mod.rs @@ -0,0 +1,58 @@ +use { + crate::{ + error::{ProgramTransformerError, ProgramTransformerResult}, + token_metadata::{ + master_edition::{save_v1_master_edition, save_v2_master_edition}, + v1_asset::{burn_v1_asset, save_v1_asset}, + }, + DownloadMetadataNotifier, + }, + blockbuster::programs::token_metadata::{TokenMetadataAccountData, TokenMetadataAccountState}, + plerkle_serialization::AccountInfo, + sea_orm::{DatabaseConnection, TransactionTrait}, +}; + +mod master_edition; +mod v1_asset; + +pub async fn handle_token_metadata_account<'a, 'b, 'c>( + account_update: &'a AccountInfo<'a>, + parsing_result: &'b TokenMetadataAccountState, + db: &'c DatabaseConnection, + download_metadata_notifier: &DownloadMetadataNotifier, +) -> ProgramTransformerResult<()> { + let key = *account_update.pubkey().unwrap(); + match &parsing_result.data { + TokenMetadataAccountData::EmptyAccount => { + burn_v1_asset(db, key, account_update.slot()).await?; + Ok(()) + } + TokenMetadataAccountData::MasterEditionV1(m) => { + let txn = db.begin().await?; + save_v1_master_edition(key, account_update.slot(), m, &txn).await?; + txn.commit().await?; + Ok(()) + } + TokenMetadataAccountData::MetadataV1(m) => { + if let Some(info) = + save_v1_asset(db, m.mint.as_ref().into(), account_update.slot(), m).await? + { + download_metadata_notifier(info) + .await + .map_err(ProgramTransformerError::DownloadMetadataNotify)?; + } + Ok(()) + } + TokenMetadataAccountData::MasterEditionV2(m) => { + let txn = db.begin().await?; + save_v2_master_edition(key, account_update.slot(), m, &txn).await?; + txn.commit().await?; + Ok(()) + } + // TokenMetadataAccountData::EditionMarker(_) => {} + // TokenMetadataAccountData::UseAuthorityRecord(_) => {} + // TokenMetadataAccountData::CollectionAuthorityRecord(_) => {} + _ => Err(ProgramTransformerError::NotImplemented), + }?; + Ok(()) +} diff --git a/program_transformers/src/token_metadata/v1_asset.rs b/program_transformers/src/token_metadata/v1_asset.rs new file mode 100644 index 000000000..47bb76a2c --- /dev/null +++ b/program_transformers/src/token_metadata/v1_asset.rs @@ -0,0 +1,393 @@ +use { + crate::{ + error::{ProgramTransformerError, ProgramTransformerResult}, + DownloadMetadataInfo, + }, + blockbuster::token_metadata::{ + pda::find_master_edition_account, + state::{Metadata, TokenStandard, UseMethod, Uses}, + }, + digital_asset_types::{ + dao::{ + asset, asset_authority, asset_creators, asset_data, asset_grouping, + asset_v1_account_attachments, + sea_orm_active_enums::{ + ChainMutability, Mutability, OwnerType, RoyaltyTargetType, SpecificationAssetClass, + SpecificationVersions, V1AccountAttachments, + }, + token_accounts, tokens, + }, + json::ChainDataV1, + }, + num_traits::FromPrimitive, + plerkle_serialization::Pubkey as FBPubkey, + sea_orm::{ + entity::{ActiveValue, ColumnTrait, EntityTrait}, + query::{Condition, JsonValue, QueryFilter, QueryTrait}, + sea_query::query::OnConflict, + ConnectionTrait, DbBackend, DbErr, TransactionTrait, + }, + std::collections::HashSet, + tracing::warn, +}; + +pub async fn burn_v1_asset( + conn: &T, + id: FBPubkey, + slot: u64, +) -> ProgramTransformerResult<()> { + let (id, slot_i) = (id.0, slot as i64); + let model = asset::ActiveModel { + id: ActiveValue::Set(id.to_vec()), + slot_updated: ActiveValue::Set(Some(slot_i)), + burnt: ActiveValue::Set(true), + ..Default::default() + }; + let mut query = asset::Entity::insert(model) + .on_conflict( + OnConflict::columns([asset::Column::Id]) + .update_columns([asset::Column::SlotUpdated, asset::Column::Burnt]) + .to_owned(), + ) + .build(DbBackend::Postgres); + query.sql = format!( + "{} WHERE excluded.slot_updated > asset.slot_updated", + query.sql + ); + conn.execute(query).await?; + Ok(()) +} + +pub async fn save_v1_asset( + conn: &T, + id: FBPubkey, + slot: u64, + metadata: &Metadata, +) -> ProgramTransformerResult> { + let metadata = metadata.clone(); + let data = metadata.data; + let meta_mint_pubkey = metadata.mint; + let (edition_attachment_address, _) = find_master_edition_account(&meta_mint_pubkey); + let mint = metadata.mint.to_bytes().to_vec(); + let authority = metadata.update_authority.to_bytes().to_vec(); + let id = id.0; + let slot_i = slot as i64; + let uri = data.uri.trim().replace('\0', ""); + let _spec = SpecificationVersions::V1; + let class = match metadata.token_standard { + Some(TokenStandard::NonFungible) => SpecificationAssetClass::Nft, + Some(TokenStandard::FungibleAsset) => SpecificationAssetClass::FungibleAsset, + Some(TokenStandard::Fungible) => SpecificationAssetClass::FungibleToken, + _ => SpecificationAssetClass::Unknown, + }; + let ownership_type = match class { + SpecificationAssetClass::FungibleAsset => OwnerType::Token, + SpecificationAssetClass::FungibleToken => OwnerType::Token, + _ => OwnerType::Single, + }; + + // gets the token and token account for the mint to populate the asset. This is required when the token and token account are indexed, but not the metadata account. If the metadata account is indexed, then the token and ta ingester will update the asset with the correct data + + let (token, token_account): (Option, Option) = + match ownership_type { + OwnerType::Single => { + let token: Option = + tokens::Entity::find_by_id(mint.clone()).one(conn).await?; + // query for token account associated with mint with positive balance + let token_account: Option = token_accounts::Entity::find() + .filter(token_accounts::Column::Mint.eq(mint.clone())) + .filter(token_accounts::Column::Amount.gt(0)) + .one(conn) + .await?; + Ok((token, token_account)) + } + _ => { + let token = tokens::Entity::find_by_id(mint.clone()).one(conn).await?; + Ok((token, None)) + } + } + .map_err(|e: DbErr| ProgramTransformerError::DatabaseError(e.to_string()))?; + + // get supply of token, default to 1 since most cases will be NFTs. Token mint ingester will properly set supply if token_result is None + let (supply, supply_mint) = match token { + Some(t) => (ActiveValue::Set(t.supply), ActiveValue::Set(Some(t.mint))), + None => (ActiveValue::Set(1), ActiveValue::NotSet), + }; + + // owner and delegate should be from the token account with the mint + let (owner, delegate) = match token_account { + Some(ta) => ( + ActiveValue::Set(Some(ta.owner)), + ActiveValue::Set(ta.delegate), + ), + None => (ActiveValue::NotSet, ActiveValue::NotSet), + }; + + let name = data.name.clone().into_bytes(); + let symbol = data.symbol.clone().into_bytes(); + + let mut chain_data = ChainDataV1 { + name: data.name.clone(), + symbol: data.symbol.clone(), + edition_nonce: metadata.edition_nonce, + primary_sale_happened: metadata.primary_sale_happened, + token_standard: metadata.token_standard, + uses: metadata.uses.map(|u| Uses { + use_method: UseMethod::from_u8(u.use_method as u8).unwrap(), + remaining: u.remaining, + total: u.total, + }), + }; + chain_data.sanitize(); + let chain_data_json = serde_json::to_value(chain_data) + .map_err(|e| ProgramTransformerError::DeserializationError(e.to_string()))?; + let chain_mutability = match metadata.is_mutable { + true => ChainMutability::Mutable, + false => ChainMutability::Immutable, + }; + let asset_data_model = asset_data::ActiveModel { + chain_data_mutability: ActiveValue::Set(chain_mutability), + chain_data: ActiveValue::Set(chain_data_json), + metadata_url: ActiveValue::Set(uri.clone()), + metadata: ActiveValue::Set(JsonValue::String("processing".to_string())), + metadata_mutability: ActiveValue::Set(Mutability::Mutable), + slot_updated: ActiveValue::Set(slot_i), + reindex: ActiveValue::Set(Some(true)), + id: ActiveValue::Set(id.to_vec()), + raw_name: ActiveValue::Set(name.to_vec()), + raw_symbol: ActiveValue::Set(symbol.to_vec()), + }; + let txn = conn.begin().await?; + let mut query = asset_data::Entity::insert(asset_data_model) + .on_conflict( + OnConflict::columns([asset_data::Column::Id]) + .update_columns([ + asset_data::Column::ChainDataMutability, + asset_data::Column::ChainData, + asset_data::Column::MetadataUrl, + asset_data::Column::MetadataMutability, + asset_data::Column::SlotUpdated, + asset_data::Column::Reindex, + asset_data::Column::RawName, + asset_data::Column::RawSymbol, + ]) + .to_owned(), + ) + .build(DbBackend::Postgres); + query.sql = format!( + "{} WHERE excluded.slot_updated > asset_data.slot_updated", + query.sql + ); + txn.execute(query) + .await + .map_err(|db_err| ProgramTransformerError::AssetIndexError(db_err.to_string()))?; + let model = asset::ActiveModel { + id: ActiveValue::Set(id.to_vec()), + owner, + owner_type: ActiveValue::Set(ownership_type), + delegate, + frozen: ActiveValue::Set(false), + supply, + supply_mint, + specification_version: ActiveValue::Set(Some(SpecificationVersions::V1)), + specification_asset_class: ActiveValue::Set(Some(class)), + tree_id: ActiveValue::Set(None), + nonce: ActiveValue::Set(Some(0)), + seq: ActiveValue::Set(Some(0)), + leaf: ActiveValue::Set(None), + compressed: ActiveValue::Set(false), + compressible: ActiveValue::Set(false), + royalty_target_type: ActiveValue::Set(RoyaltyTargetType::Creators), + royalty_target: ActiveValue::Set(None), + royalty_amount: ActiveValue::Set(data.seller_fee_basis_points as i32), //basis points + asset_data: ActiveValue::Set(Some(id.to_vec())), + slot_updated: ActiveValue::Set(Some(slot_i)), + burnt: ActiveValue::Set(false), + ..Default::default() + }; + let mut query = asset::Entity::insert(model) + .on_conflict( + OnConflict::columns([asset::Column::Id]) + .update_columns([ + asset::Column::Owner, + asset::Column::OwnerType, + asset::Column::Delegate, + asset::Column::Frozen, + asset::Column::Supply, + asset::Column::SupplyMint, + asset::Column::SpecificationVersion, + asset::Column::SpecificationAssetClass, + asset::Column::TreeId, + asset::Column::Nonce, + asset::Column::Seq, + asset::Column::Leaf, + asset::Column::Compressed, + asset::Column::Compressible, + asset::Column::RoyaltyTargetType, + asset::Column::RoyaltyTarget, + asset::Column::RoyaltyAmount, + asset::Column::AssetData, + asset::Column::SlotUpdated, + asset::Column::Burnt, + ]) + .to_owned(), + ) + .build(DbBackend::Postgres); + query.sql = format!( + "{} WHERE excluded.slot_updated > asset.slot_updated", + query.sql + ); + txn.execute(query) + .await + .map_err(|db_err| ProgramTransformerError::AssetIndexError(db_err.to_string()))?; + let attachment = asset_v1_account_attachments::ActiveModel { + id: ActiveValue::Set(edition_attachment_address.to_bytes().to_vec()), + slot_updated: ActiveValue::Set(slot_i), + attachment_type: ActiveValue::Set(V1AccountAttachments::MasterEditionV2), + ..Default::default() + }; + let query = asset_v1_account_attachments::Entity::insert(attachment) + .on_conflict( + OnConflict::columns([asset_v1_account_attachments::Column::Id]) + .do_nothing() + .to_owned(), + ) + .build(DbBackend::Postgres); + txn.execute(query) + .await + .map_err(|db_err| ProgramTransformerError::AssetIndexError(db_err.to_string()))?; + let model = asset_authority::ActiveModel { + asset_id: ActiveValue::Set(id.to_vec()), + authority: ActiveValue::Set(authority), + seq: ActiveValue::Set(0), + slot_updated: ActiveValue::Set(slot_i), + ..Default::default() + }; + let mut query = asset_authority::Entity::insert(model) + .on_conflict( + OnConflict::columns([asset_authority::Column::AssetId]) + .update_columns([ + asset_authority::Column::Authority, + asset_authority::Column::Seq, + asset_authority::Column::SlotUpdated, + ]) + .to_owned(), + ) + .build(DbBackend::Postgres); + query.sql = format!( + "{} WHERE excluded.slot_updated > asset_authority.slot_updated", + query.sql + ); + txn.execute(query) + .await + .map_err(|db_err| ProgramTransformerError::AssetIndexError(db_err.to_string()))?; + if let Some(c) = &metadata.collection { + let model = asset_grouping::ActiveModel { + asset_id: ActiveValue::Set(id.to_vec()), + group_key: ActiveValue::Set("collection".to_string()), + group_value: ActiveValue::Set(Some(c.key.to_string())), + verified: ActiveValue::Set(Some(c.verified)), + seq: ActiveValue::Set(None), + slot_updated: ActiveValue::Set(Some(slot_i)), + ..Default::default() + }; + let mut query = asset_grouping::Entity::insert(model) + .on_conflict( + OnConflict::columns([ + asset_grouping::Column::AssetId, + asset_grouping::Column::GroupKey, + ]) + .update_columns([ + asset_grouping::Column::GroupKey, + asset_grouping::Column::GroupValue, + asset_grouping::Column::Seq, + asset_grouping::Column::SlotUpdated, + ]) + .to_owned(), + ) + .build(DbBackend::Postgres); + query.sql = format!( + "{} WHERE excluded.slot_updated > asset_grouping.slot_updated", + query.sql + ); + txn.execute(query) + .await + .map_err(|db_err| ProgramTransformerError::AssetIndexError(db_err.to_string()))?; + } + txn.commit().await?; + let creators = data.creators.unwrap_or_default(); + if !creators.is_empty() { + let mut creators_set = HashSet::new(); + let existing_creators: Vec = asset_creators::Entity::find() + .filter( + Condition::all() + .add(asset_creators::Column::AssetId.eq(id.to_vec())) + .add(asset_creators::Column::SlotUpdated.lt(slot_i)), + ) + .all(conn) + .await?; + if !existing_creators.is_empty() { + let mut db_creators = Vec::with_capacity(creators.len()); + for (i, c) in creators.into_iter().enumerate() { + if creators_set.contains(&c.address) { + continue; + } + db_creators.push(asset_creators::ActiveModel { + asset_id: ActiveValue::Set(id.to_vec()), + creator: ActiveValue::Set(c.address.to_bytes().to_vec()), + share: ActiveValue::Set(c.share as i32), + verified: ActiveValue::Set(c.verified), + seq: ActiveValue::Set(Some(0)), + slot_updated: ActiveValue::Set(Some(slot_i)), + position: ActiveValue::Set(i as i16), + ..Default::default() + }); + creators_set.insert(c.address); + } + let txn = conn.begin().await?; + asset_creators::Entity::delete_many() + .filter( + Condition::all() + .add(asset_creators::Column::AssetId.eq(id.to_vec())) + .add(asset_creators::Column::SlotUpdated.lt(slot_i)), + ) + .exec(&txn) + .await?; + if !db_creators.is_empty() { + let mut query = asset_creators::Entity::insert_many(db_creators) + .on_conflict( + OnConflict::columns([ + asset_creators::Column::AssetId, + asset_creators::Column::Position, + ]) + .update_columns([ + asset_creators::Column::Creator, + asset_creators::Column::Share, + asset_creators::Column::Verified, + asset_creators::Column::Seq, + asset_creators::Column::SlotUpdated, + ]) + .to_owned(), + ) + .build(DbBackend::Postgres); + query.sql = format!( + "{} WHERE excluded.slot_updated > asset_creators.slot_updated", + query.sql + ); + txn.execute(query).await.map_err(|db_err| { + ProgramTransformerError::AssetIndexError(db_err.to_string()) + })?; + } + txn.commit().await?; + } + } + if uri.is_empty() { + warn!( + "URI is empty for mint {}. Skipping background task.", + bs58::encode(mint).into_string() + ); + return Ok(None); + } + + Ok(Some(DownloadMetadataInfo::new(id.to_vec(), uri))) +} From 52d17736a46c2bef9f18d4db2cd28bfa97b4053d Mon Sep 17 00:00:00 2001 From: Kirill Fomichev Date: Wed, 22 Nov 2023 22:04:05 -0500 Subject: [PATCH 13/23] nft_ingester: use program_transformers crate --- Cargo.lock | 30 +- Cargo.toml | 7 +- nft_ingester/Cargo.toml | 18 +- nft_ingester/src/account_updates.rs | 40 +- nft_ingester/src/error/mod.rs | 50 +- nft_ingester/src/lib.rs | 1 - nft_ingester/src/main.rs | 1 - nft_ingester/src/metrics.rs | 29 +- .../program_transformers/bubblegum/burn.rs | 65 --- .../bubblegum/cancel_redeem.rs | 74 --- .../bubblegum/collection_verification.rs | 80 ---- .../bubblegum/creator_verification.rs | 107 ----- .../src/program_transformers/bubblegum/db.rs | 442 ------------------ .../bubblegum/decompress.rs | 32 -- .../bubblegum/delegate.rs | 72 --- .../program_transformers/bubblegum/mint_v1.rs | 364 --------------- .../src/program_transformers/bubblegum/mod.rs | 108 ----- .../program_transformers/bubblegum/redeem.rs | 59 --- .../bubblegum/transfer.rs | 75 --- nft_ingester/src/program_transformers/mod.rs | 189 -------- .../src/program_transformers/token/mod.rs | 141 ------ .../token_metadata/master_edition.rs | 94 ---- .../token_metadata/mod.rs | 54 --- .../token_metadata/v1_asset.rs | 393 ---------------- nft_ingester/src/tasks/common/mod.rs | 54 ++- nft_ingester/src/transaction_notifications.rs | 41 +- program_transformers/src/lib.rs | 8 +- 27 files changed, 119 insertions(+), 2509 deletions(-) delete mode 100644 nft_ingester/src/program_transformers/bubblegum/burn.rs delete mode 100644 nft_ingester/src/program_transformers/bubblegum/cancel_redeem.rs delete mode 100644 nft_ingester/src/program_transformers/bubblegum/collection_verification.rs delete mode 100644 nft_ingester/src/program_transformers/bubblegum/creator_verification.rs delete mode 100644 nft_ingester/src/program_transformers/bubblegum/db.rs delete mode 100644 nft_ingester/src/program_transformers/bubblegum/decompress.rs delete mode 100644 nft_ingester/src/program_transformers/bubblegum/delegate.rs delete mode 100644 nft_ingester/src/program_transformers/bubblegum/mint_v1.rs delete mode 100644 nft_ingester/src/program_transformers/bubblegum/mod.rs delete mode 100644 nft_ingester/src/program_transformers/bubblegum/redeem.rs delete mode 100644 nft_ingester/src/program_transformers/bubblegum/transfer.rs delete mode 100644 nft_ingester/src/program_transformers/mod.rs delete mode 100644 nft_ingester/src/program_transformers/token/mod.rs delete mode 100644 nft_ingester/src/program_transformers/token_metadata/master_edition.rs delete mode 100644 nft_ingester/src/program_transformers/token_metadata/mod.rs delete mode 100644 nft_ingester/src/program_transformers/token_metadata/v1_asset.rs diff --git a/Cargo.lock b/Cargo.lock index 08913f59c..373c3b341 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3420,9 +3420,7 @@ dependencies = [ name = "nft_ingester" version = "0.7.2" dependencies = [ - "anchor-lang", "async-trait", - "base64 0.21.4", "blockbuster", "borsh 0.10.3", "bs58 0.4.0", @@ -3431,46 +3429,32 @@ dependencies = [ "chrono", "clap 4.4.8", "digital_asset_types", - "env_logger 0.10.0", "figment", "flatbuffers", "futures", - "futures-util", - "hex", - "lazy_static", "log", "mpl-bubblegum", - "num-integer", - "num-traits", "plerkle_messenger", "plerkle_serialization", + "program_transformers", "rand 0.8.5", "redis", - "regex", "reqwest", "rust-crypto", "sea-orm", - "sea-query 0.28.5", "serde", "serde_json", "solana-account-decoder", "solana-client", - "solana-geyser-plugin-interface", "solana-sdk", - "solana-sdk-macro", "solana-transaction-status", "spl-account-compression", - "spl-concurrent-merkle-tree", - "spl-token 4.0.0", "sqlx", "stretto", "thiserror", "tokio", - "tokio-postgres", - "tokio-stream", "tracing-subscriber", "url", - "uuid", ] [[package]] @@ -5757,18 +5741,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "solana-geyser-plugin-interface" -version = "1.16.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "512372f741974113777872cecd560beee189cf79c3fb2eb84e1c28be69f011d1" -dependencies = [ - "log", - "solana-sdk", - "solana-transaction-status", - "thiserror", -] - [[package]] name = "solana-logger" version = "1.16.16" diff --git a/Cargo.toml b/Cargo.toml index a5d08f3cb..1c967736e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,6 @@ anchor-lang = "0.28.0" anyhow = "1.0.75" async-std = "1.0.0" async-trait = "0.1.60" -base64 = "0.21.0" blockbuster = "0.9.0-beta.1" borsh = "~0.10.3" bs58 = "0.4.0" @@ -43,7 +42,6 @@ fake = "2.5.0" figment = "0.10.8" flatbuffers = "23.1.21" futures = "0.3.28" -futures-util = "0.3.27" hex = "0.4.3" hyper = "0.14.23" indexmap = "1.9.3" @@ -60,12 +58,12 @@ mpl-candy-machine-core = "2.0.1" mpl-token-metadata = "=2.0.0-beta.1" nft_ingester = { path = "nft_ingester" } num-derive = "0.3.3" -num-integer = { version = "0.1.44", default_features = false } num-traits = "0.2.15" open-rpc-derive = "0.0.4" open-rpc-schema = "0.0.4" plerkle_messenger = "1.6.0" plerkle_serialization = "1.6.0" +program_transformers = { path = "program_transformers" } prometheus = "0.13.3" proxy-wasm = "0.2.0" rand = "0.8.5" @@ -82,10 +80,8 @@ serde = "1.0.137" serde_json = "1.0.81" solana-account-decoder = "~1.16.16" solana-client = "~1.16.16" -solana-geyser-plugin-interface = "~1.16.16" solana-program = "~1.16.16" solana-sdk = "~1.16.16" -solana-sdk-macro = "~1.16.16" solana-transaction-status = "~1.16.16" spl-account-compression = "0.2.0" spl-associated-token-account = ">= 1.1.3, < 3.0" @@ -104,7 +100,6 @@ tracing = "0.1.35" tracing-subscriber = "0.3.16" txn_forwarder = { path = "tools/txn_forwarder" } url = "2.3.1" -uuid = "1.0.0" wasi = "0.7.0" wasm-bindgen = "0.2.83" diff --git a/nft_ingester/Cargo.toml b/nft_ingester/Cargo.toml index 05b98b563..f31a589dd 100644 --- a/nft_ingester/Cargo.toml +++ b/nft_ingester/Cargo.toml @@ -6,9 +6,7 @@ repository = { workspace = true } publish = { workspace = true } [dependencies] -anchor-lang = { workspace = true } async-trait = { workspace = true } -base64 = { workspace = true } blockbuster = { workspace = true } borsh = { workspace = true } bs58 = { workspace = true } @@ -17,46 +15,32 @@ cadence-macros = { workspace = true } chrono = { workspace = true } clap = { workspace = true, features = ["derive", "cargo"] } digital_asset_types = { workspace = true, features = ["json_types", "sql_types"] } -env_logger = { workspace = true } figment = { workspace = true, features = ["env", "toml", "yaml"] } flatbuffers = { workspace = true } futures = { workspace = true } -futures-util = { workspace = true } -hex = { workspace = true } -lazy_static = { workspace = true } log = { workspace = true } mpl-bubblegum = { workspace = true } -num-integer = { workspace = true } -num-traits = { workspace = true } plerkle_messenger = { workspace = true, features = ["redis"] } plerkle_serialization = { workspace = true } +program_transformers = { workspace = true } rand = { workspace = true } redis = { workspace = true, features = ["aio", "tokio-comp", "streams", "tokio-native-tls-comp"] } -regex = { workspace = true } reqwest = { workspace = true } rust-crypto = { workspace = true } sea-orm = { workspace = true, features = ["macros", "runtime-tokio-rustls", "sqlx-postgres", "with-chrono", "mock"] } -sea-query = { workspace = true, features = ["postgres-array"] } serde = { workspace = true } serde_json = { workspace = true } solana-account-decoder = { workspace = true } solana-client = { workspace = true } -solana-geyser-plugin-interface = { workspace = true } solana-sdk = { workspace = true } -solana-sdk-macro = { workspace = true } solana-transaction-status = { workspace = true } spl-account-compression = { workspace = true, features = ["no-entrypoint"] } -spl-concurrent-merkle-tree = { workspace = true } -spl-token = { workspace = true, features = ["no-entrypoint"] } sqlx = { workspace = true, features = ["macros", "runtime-tokio-rustls", "postgres", "uuid", "offline", "json"] } stretto = { workspace = true, features = ["async"] } thiserror = { workspace = true } tokio = { workspace = true, features = ["tracing"] } -tokio-postgres = { workspace = true } -tokio-stream = { workspace = true } tracing-subscriber = { workspace = true, features = ["json", "env-filter", "ansi"] } url = { workspace = true } -uuid = { workspace = true } [lints] workspace = true diff --git a/nft_ingester/src/account_updates.rs b/nft_ingester/src/account_updates.rs index 68b6c83a0..354aaf9c6 100644 --- a/nft_ingester/src/account_updates.rs +++ b/nft_ingester/src/account_updates.rs @@ -1,18 +1,22 @@ -use std::sync::Arc; - -use crate::{ - metric, metrics::capture_result, program_transformers::ProgramTransformer, tasks::TaskData, -}; -use cadence_macros::{is_global_default_set, statsd_count, statsd_time}; -use chrono::Utc; -use log::{debug, error}; -use plerkle_messenger::{ConsumptionType, Messenger, MessengerConfig, RecvData}; -use plerkle_serialization::root_as_account_info; -use sqlx::{Pool, Postgres}; -use tokio::{ - sync::mpsc::UnboundedSender, - task::{JoinHandle, JoinSet}, - time::Instant, +use { + crate::{ + metric, + metrics::capture_result, + tasks::{create_download_metadata_notifier, TaskData}, + }, + cadence_macros::{is_global_default_set, statsd_count, statsd_time}, + chrono::Utc, + log::{debug, error}, + plerkle_messenger::{ConsumptionType, Messenger, MessengerConfig, RecvData}, + plerkle_serialization::root_as_account_info, + program_transformers::ProgramTransformer, + sqlx::{Pool, Postgres}, + std::sync::Arc, + tokio::{ + sync::mpsc::UnboundedSender, + task::{JoinHandle, JoinSet}, + time::Instant, + }, }; pub fn account_worker( @@ -26,7 +30,11 @@ pub fn account_worker( tokio::spawn(async move { let source = T::new(config).await; if let Ok(mut msg) = source { - let manager = Arc::new(ProgramTransformer::new(pool, bg_task_sender, false)); + let manager = Arc::new(ProgramTransformer::new( + pool, + create_download_metadata_notifier(bg_task_sender), + false, + )); loop { let e = msg.recv(stream_key, consumption_type.clone()).await; let mut tasks = JoinSet::new(); diff --git a/nft_ingester/src/error/mod.rs b/nft_ingester/src/error/mod.rs index 37ed5f24b..ddeae0ba6 100644 --- a/nft_ingester/src/error/mod.rs +++ b/nft_ingester/src/error/mod.rs @@ -1,27 +1,15 @@ -use crate::tasks::TaskData; -use blockbuster::error::BlockbusterError; -use plerkle_messenger::MessengerError; -use plerkle_serialization::error::PlerkleSerializationError; -use sea_orm::{DbErr, TransactionError}; -use thiserror::Error; -use tokio::sync::mpsc::error::SendError; +use { + crate::tasks::TaskData, plerkle_messenger::MessengerError, + plerkle_serialization::error::PlerkleSerializationError, sea_orm::DbErr, + tokio::sync::mpsc::error::SendError, +}; -#[derive(Error, Debug, PartialEq, Eq)] +#[derive(Debug, thiserror::Error)] pub enum IngesterError { - #[error("ChangeLog Event Malformed")] - ChangeLogEventMalformed, - #[error("Compressed Asset Event Malformed")] - CompressedAssetEventMalformed, #[error("Network Error: {0}")] BatchInitNetworkingError(String), - #[error("Error writing batch files")] - BatchInitIOError, - #[error("Storage listener error: ({msg})")] - StorageListenerError { msg: String }, #[error("Storage Write Error: {0}")] StorageWriteError(String), - #[error("NotImplemented")] - NotImplemented, #[error("Deserialization Error: {0}")] DeserializationError(String), #[error("Task Manager Error: {0}")] @@ -36,12 +24,6 @@ pub enum IngesterError { SerializatonError(String), #[error("Messenger error; {0}")] MessengerError(String), - #[error("Blockbuster Parsing error: {0}")] - ParsingError(String), - #[error("Database Error: {0}")] - DatabaseError(String), - #[error("Unknown Task Type: {0}")] - UnknownTaskType(String), #[error("BG Task Manager Not Started")] TaskManagerNotStarted, #[error("Unrecoverable task error: {0}")] @@ -50,8 +32,6 @@ pub enum IngesterError { CacheStorageWriteError(String), #[error("HttpError {status_code}")] HttpError { status_code: String }, - #[error("AssetIndex Error {0}")] - AssetIndexError(String), } impl From for IngesterError { @@ -72,30 +52,12 @@ impl From for IngesterError { } } -impl From for IngesterError { - fn from(err: BlockbusterError) -> Self { - IngesterError::ParsingError(err.to_string()) - } -} - -impl From for IngesterError { - fn from(_err: std::io::Error) -> Self { - IngesterError::BatchInitIOError - } -} - impl From for IngesterError { fn from(e: DbErr) -> Self { IngesterError::StorageWriteError(e.to_string()) } } -impl From> for IngesterError { - fn from(e: TransactionError) -> Self { - IngesterError::StorageWriteError(e.to_string()) - } -} - impl From> for IngesterError { fn from(err: SendError) -> Self { IngesterError::TaskManagerError(format!("Could not create task: {:?}", err.to_string())) diff --git a/nft_ingester/src/lib.rs b/nft_ingester/src/lib.rs index 48e29aa70..9aee9c6ba 100644 --- a/nft_ingester/src/lib.rs +++ b/nft_ingester/src/lib.rs @@ -5,7 +5,6 @@ pub mod config; pub mod database; pub mod error; pub mod metrics; -pub mod program_transformers; pub mod stream; pub mod tasks; pub mod transaction_notifications; diff --git a/nft_ingester/src/main.rs b/nft_ingester/src/main.rs index 6ae64a15e..1c13320b5 100644 --- a/nft_ingester/src/main.rs +++ b/nft_ingester/src/main.rs @@ -5,7 +5,6 @@ pub mod config; mod database; pub mod error; pub mod metrics; -mod program_transformers; mod stream; pub mod tasks; mod transaction_notifications; diff --git a/nft_ingester/src/metrics.rs b/nft_ingester/src/metrics.rs index 2e4ebb0d8..207c6318f 100644 --- a/nft_ingester/src/metrics.rs +++ b/nft_ingester/src/metrics.rs @@ -1,11 +1,12 @@ -use std::net::UdpSocket; - -use cadence::{BufferedUdpMetricSink, QueuingMetricSink, StatsdClient}; -use cadence_macros::{is_global_default_set, set_global_default, statsd_count, statsd_time}; -use log::{error, warn}; -use tokio::time::Instant; - -use crate::{config::IngesterConfig, error::IngesterError}; +use { + crate::config::IngesterConfig, + cadence::{BufferedUdpMetricSink, QueuingMetricSink, StatsdClient}, + cadence_macros::{is_global_default_set, set_global_default, statsd_count, statsd_time}, + log::{error, warn}, + program_transformers::error::ProgramTransformerError, + std::net::UdpSocket, + tokio::time::Instant, +}; #[macro_export] macro_rules! metric { @@ -42,7 +43,7 @@ pub fn capture_result( stream: &str, label: (&str, &str), tries: usize, - res: Result<(), IngesterError>, + res: Result<(), ProgramTransformerError>, proc: Instant, txn_sig: Option<&str>, account: Option, @@ -63,13 +64,13 @@ pub fn capture_result( } true } - Err(IngesterError::NotImplemented) => { + Err(ProgramTransformerError::NotImplemented) => { metric! { statsd_count!("ingester.not_implemented", 1, label.0 => label.1, "stream" => stream, "error" => "ni"); } true } - Err(IngesterError::DeserializationError(e)) => { + Err(ProgramTransformerError::DeserializationError(e)) => { metric! { statsd_count!("ingester.ingest_error", 1, label.0 => label.1, "stream" => stream, "error" => "de"); } @@ -83,7 +84,7 @@ pub fn capture_result( // Non-retryable error. true } - Err(IngesterError::ParsingError(e)) => { + Err(ProgramTransformerError::ParsingError(e)) => { metric! { statsd_count!("ingester.ingest_error", 1, label.0 => label.1, "stream" => stream, "error" => "parse"); } @@ -97,7 +98,7 @@ pub fn capture_result( // Non-retryable error. true } - Err(IngesterError::DatabaseError(e)) => { + Err(ProgramTransformerError::DatabaseError(e)) => { metric! { statsd_count!("ingester.database_error", 1, label.0 => label.1, "stream" => stream, "error" => "db"); } @@ -108,7 +109,7 @@ pub fn capture_result( } false } - Err(IngesterError::AssetIndexError(e)) => { + Err(ProgramTransformerError::AssetIndexError(e)) => { metric! { statsd_count!("ingester.index_error", 1, label.0 => label.1, "stream" => stream, "error" => "index"); } diff --git a/nft_ingester/src/program_transformers/bubblegum/burn.rs b/nft_ingester/src/program_transformers/bubblegum/burn.rs deleted file mode 100644 index 70ddcfcea..000000000 --- a/nft_ingester/src/program_transformers/bubblegum/burn.rs +++ /dev/null @@ -1,65 +0,0 @@ -use crate::{ - error::IngesterError, - program_transformers::bubblegum::{ - save_changelog_event, u32_to_u8_array, upsert_asset_with_seq, - }, -}; -use anchor_lang::prelude::Pubkey; -use blockbuster::{instruction::InstructionBundle, programs::bubblegum::BubblegumInstruction}; -use digital_asset_types::dao::asset; -use log::debug; -use sea_orm::{ - entity::*, query::*, sea_query::OnConflict, ConnectionTrait, DbBackend, EntityTrait, - TransactionTrait, -}; - -pub async fn burn<'c, T>( - parsing_result: &BubblegumInstruction, - bundle: &InstructionBundle<'c>, - txn: &'c T, - cl_audits: bool, -) -> Result<(), IngesterError> -where - T: ConnectionTrait + TransactionTrait, -{ - if let Some(cl) = &parsing_result.tree_update { - let seq = save_changelog_event(cl, bundle.slot, bundle.txn_id, txn, cl_audits).await?; - let leaf_index = cl.index; - let (asset_id, _) = Pubkey::find_program_address( - &[ - "asset".as_bytes(), - cl.id.as_ref(), - u32_to_u8_array(leaf_index).as_ref(), - ], - &mpl_bubblegum::ID, - ); - debug!("Indexing burn for asset id: {:?}", asset_id); - let id_bytes = asset_id.to_bytes(); - - let asset_model = asset::ActiveModel { - id: Set(id_bytes.to_vec()), - burnt: Set(true), - ..Default::default() - }; - - // Upsert asset table `burnt` column. - let query = asset::Entity::insert(asset_model) - .on_conflict( - OnConflict::columns([asset::Column::Id]) - .update_columns([ - asset::Column::Burnt, - //TODO maybe handle slot updated. - ]) - .to_owned(), - ) - .build(DbBackend::Postgres); - txn.execute(query).await?; - - upsert_asset_with_seq(txn, id_bytes.to_vec(), seq as i64).await?; - - return Ok(()); - } - Err(IngesterError::ParsingError( - "Ix not parsed correctly".to_string(), - )) -} diff --git a/nft_ingester/src/program_transformers/bubblegum/cancel_redeem.rs b/nft_ingester/src/program_transformers/bubblegum/cancel_redeem.rs deleted file mode 100644 index 1b8f5842a..000000000 --- a/nft_ingester/src/program_transformers/bubblegum/cancel_redeem.rs +++ /dev/null @@ -1,74 +0,0 @@ -use crate::{ - error::IngesterError, - program_transformers::bubblegum::{ - save_changelog_event, upsert_asset_with_leaf_info, - upsert_asset_with_owner_and_delegate_info, upsert_asset_with_seq, - }, -}; -use blockbuster::{ - instruction::InstructionBundle, - programs::bubblegum::{BubblegumInstruction, LeafSchema}, -}; -use sea_orm::{ConnectionTrait, TransactionTrait}; - -pub async fn cancel_redeem<'c, T>( - parsing_result: &BubblegumInstruction, - bundle: &InstructionBundle<'c>, - txn: &'c T, - cl_audits: bool, -) -> Result<(), IngesterError> -where - T: ConnectionTrait + TransactionTrait, -{ - if let (Some(le), Some(cl)) = (&parsing_result.leaf_update, &parsing_result.tree_update) { - let seq = save_changelog_event(cl, bundle.slot, bundle.txn_id, txn, cl_audits).await?; - #[allow(unreachable_patterns)] - return match le.schema { - LeafSchema::V1 { - id, - owner, - delegate, - .. - } => { - let id_bytes = id.to_bytes(); - let owner_bytes = owner.to_bytes().to_vec(); - let delegate = if owner == delegate || delegate.to_bytes() == [0; 32] { - None - } else { - Some(delegate.to_bytes().to_vec()) - }; - let tree_id = cl.id.to_bytes(); - let nonce = cl.index as i64; - - // Partial update of asset table with just leaf. - upsert_asset_with_leaf_info( - txn, - id_bytes.to_vec(), - nonce, - tree_id.to_vec(), - le.leaf_hash.to_vec(), - le.schema.data_hash(), - le.schema.creator_hash(), - seq as i64, - false, - ) - .await?; - - // Partial update of asset table with just leaf owner and delegate. - upsert_asset_with_owner_and_delegate_info( - txn, - id_bytes.to_vec(), - owner_bytes, - delegate, - seq as i64, - ) - .await?; - - upsert_asset_with_seq(txn, id_bytes.to_vec(), seq as i64).await - } - }; - } - Err(IngesterError::ParsingError( - "Ix not parsed correctly".to_string(), - )) -} diff --git a/nft_ingester/src/program_transformers/bubblegum/collection_verification.rs b/nft_ingester/src/program_transformers/bubblegum/collection_verification.rs deleted file mode 100644 index 2db92cd60..000000000 --- a/nft_ingester/src/program_transformers/bubblegum/collection_verification.rs +++ /dev/null @@ -1,80 +0,0 @@ -use crate::program_transformers::bubblegum::{upsert_asset_with_seq, upsert_collection_info}; -use blockbuster::{ - instruction::InstructionBundle, - programs::bubblegum::{BubblegumInstruction, LeafSchema, Payload}, -}; -use log::debug; -use mpl_bubblegum::types::Collection; -use sea_orm::query::*; - -use super::{save_changelog_event, upsert_asset_with_leaf_info}; -use crate::error::IngesterError; -pub async fn process<'c, T>( - parsing_result: &BubblegumInstruction, - bundle: &InstructionBundle<'c>, - txn: &'c T, - cl_audits: bool, -) -> Result<(), IngesterError> -where - T: ConnectionTrait + TransactionTrait, -{ - if let (Some(le), Some(cl), Some(payload)) = ( - &parsing_result.leaf_update, - &parsing_result.tree_update, - &parsing_result.payload, - ) { - let (collection, verify) = match payload { - Payload::CollectionVerification { - collection, verify, .. - } => (*collection, verify), - _ => { - return Err(IngesterError::ParsingError( - "Ix not parsed correctly".to_string(), - )); - } - }; - debug!( - "Handling collection verification event for {} (verify: {}): {}", - collection, verify, bundle.txn_id - ); - let seq = save_changelog_event(cl, bundle.slot, bundle.txn_id, txn, cl_audits).await?; - let id_bytes = match le.schema { - LeafSchema::V1 { id, .. } => id.to_bytes().to_vec(), - }; - let tree_id = cl.id.to_bytes(); - let nonce = cl.index as i64; - - // Partial update of asset table with just leaf. - upsert_asset_with_leaf_info( - txn, - id_bytes.to_vec(), - nonce, - tree_id.to_vec(), - le.leaf_hash.to_vec(), - le.schema.data_hash(), - le.schema.creator_hash(), - seq as i64, - false, - ) - .await?; - - upsert_asset_with_seq(txn, id_bytes.to_vec(), seq as i64).await?; - - upsert_collection_info( - txn, - id_bytes.to_vec(), - Some(Collection { - key: collection, - verified: *verify, - }), - bundle.slot as i64, - seq as i64, - ) - .await?; - - return Ok(()); - }; - Err(IngesterError::ParsingError( - "Ix not parsed correctly".to_string(), - )) -} diff --git a/nft_ingester/src/program_transformers/bubblegum/creator_verification.rs b/nft_ingester/src/program_transformers/bubblegum/creator_verification.rs deleted file mode 100644 index 134fe89ca..000000000 --- a/nft_ingester/src/program_transformers/bubblegum/creator_verification.rs +++ /dev/null @@ -1,107 +0,0 @@ -use crate::{ - error::IngesterError, - program_transformers::bubblegum::{ - save_changelog_event, upsert_asset_with_leaf_info, - upsert_asset_with_owner_and_delegate_info, upsert_asset_with_seq, upsert_creator_verified, - }, -}; -use blockbuster::{ - instruction::InstructionBundle, - programs::bubblegum::{BubblegumInstruction, LeafSchema, Payload}, -}; -use log::debug; -use sea_orm::{ConnectionTrait, TransactionTrait}; - -pub async fn process<'c, T>( - parsing_result: &BubblegumInstruction, - bundle: &InstructionBundle<'c>, - txn: &'c T, - value: bool, - cl_audits: bool, -) -> Result<(), IngesterError> -where - T: ConnectionTrait + TransactionTrait, -{ - if let (Some(le), Some(cl), Some(payload)) = ( - &parsing_result.leaf_update, - &parsing_result.tree_update, - &parsing_result.payload, - ) { - let (creator, verify) = match payload { - Payload::CreatorVerification { - creator, verify, .. - } => (creator, verify), - _ => { - return Err(IngesterError::ParsingError( - "Ix not parsed correctly".to_string(), - )); - } - }; - debug!( - "Handling creator verification event for creator {} (verify: {}): {}", - creator, verify, bundle.txn_id - ); - let seq = save_changelog_event(cl, bundle.slot, bundle.txn_id, txn, cl_audits).await?; - - let asset_id_bytes = match le.schema { - LeafSchema::V1 { - id, - owner, - delegate, - .. - } => { - let id_bytes = id.to_bytes(); - let owner_bytes = owner.to_bytes().to_vec(); - let delegate = if owner == delegate || delegate.to_bytes() == [0; 32] { - None - } else { - Some(delegate.to_bytes().to_vec()) - }; - let tree_id = cl.id.to_bytes(); - let nonce = cl.index as i64; - - // Partial update of asset table with just leaf info. - upsert_asset_with_leaf_info( - txn, - id_bytes.to_vec(), - nonce, - tree_id.to_vec(), - le.leaf_hash.to_vec(), - le.schema.data_hash(), - le.schema.creator_hash(), - seq as i64, - false, - ) - .await?; - - // Partial update of asset table with just leaf owner and delegate. - upsert_asset_with_owner_and_delegate_info( - txn, - id_bytes.to_vec(), - owner_bytes, - delegate, - seq as i64, - ) - .await?; - - upsert_asset_with_seq(txn, id_bytes.to_vec(), seq as i64).await?; - - id_bytes.to_vec() - } - }; - - upsert_creator_verified( - txn, - asset_id_bytes, - creator.to_bytes().to_vec(), - value, - seq as i64, - ) - .await?; - - return Ok(()); - } - Err(IngesterError::ParsingError( - "Ix not parsed correctly".to_string(), - )) -} diff --git a/nft_ingester/src/program_transformers/bubblegum/db.rs b/nft_ingester/src/program_transformers/bubblegum/db.rs deleted file mode 100644 index b7141e231..000000000 --- a/nft_ingester/src/program_transformers/bubblegum/db.rs +++ /dev/null @@ -1,442 +0,0 @@ -use crate::error::IngesterError; -use digital_asset_types::dao::{ - asset, asset_creators, asset_grouping, backfill_items, cl_audits, cl_items, -}; -use log::{debug, info}; -use mpl_bubblegum::types::Collection; -use sea_orm::{ - query::*, sea_query::OnConflict, ActiveValue::Set, ColumnTrait, DbBackend, EntityTrait, -}; -use spl_account_compression::events::ChangeLogEventV1; - -pub async fn save_changelog_event<'c, T>( - change_log_event: &ChangeLogEventV1, - slot: u64, - txn_id: &str, - txn: &T, - cl_audits: bool, -) -> Result -where - T: ConnectionTrait + TransactionTrait, -{ - insert_change_log(change_log_event, slot, txn_id, txn, cl_audits).await?; - Ok(change_log_event.seq) -} - -const fn node_idx_to_leaf_idx(index: i64, tree_height: u32) -> i64 { - index - 2i64.pow(tree_height) -} - -pub async fn insert_change_log<'c, T>( - change_log_event: &ChangeLogEventV1, - slot: u64, - txn_id: &str, - txn: &T, - cl_audits: bool, -) -> Result<(), IngesterError> -where - T: ConnectionTrait + TransactionTrait, -{ - let mut i: i64 = 0; - let depth = change_log_event.path.len() - 1; - let tree_id = change_log_event.id.as_ref(); - for p in change_log_event.path.iter() { - let node_idx = p.index as i64; - debug!( - "seq {}, index {} level {}, node {:?}, txn: {:?}", - change_log_event.seq, - p.index, - i, - bs58::encode(p.node).into_string(), - txn_id, - ); - let leaf_idx = if i == 0 { - Some(node_idx_to_leaf_idx(node_idx, depth as u32)) - } else { - None - }; - - let item = cl_items::ActiveModel { - tree: Set(tree_id.to_vec()), - level: Set(i), - node_idx: Set(node_idx), - hash: Set(p.node.as_ref().to_vec()), - seq: Set(change_log_event.seq as i64), - leaf_idx: Set(leaf_idx), - ..Default::default() - }; - - let audit_item: Option = if cl_audits { - let mut ai: cl_audits::ActiveModel = item.clone().into(); - ai.tx = Set(txn_id.to_string()); - Some(ai) - } else { - None - }; - - i += 1; - let mut query = cl_items::Entity::insert(item) - .on_conflict( - OnConflict::columns([cl_items::Column::Tree, cl_items::Column::NodeIdx]) - .update_columns([ - cl_items::Column::Hash, - cl_items::Column::Seq, - cl_items::Column::LeafIdx, - cl_items::Column::Level, - ]) - .to_owned(), - ) - .build(DbBackend::Postgres); - query.sql = format!("{} WHERE excluded.seq > cl_items.seq", query.sql); - txn.execute(query) - .await - .map_err(|db_err| IngesterError::StorageWriteError(db_err.to_string()))?; - - // Insert the audit item after the insert into cl_items have been completed - if let Some(audit_item) = audit_item { - cl_audits::Entity::insert(audit_item).exec(txn).await?; - } - } - - // If and only if the entire path of nodes was inserted into the `cl_items` table, then insert - // a single row into the `backfill_items` table. This way if an incomplete path was inserted - // into `cl_items` due to an error, a gap will be created for the tree and the backfiller will - // fix it. - if i - 1 == depth as i64 { - // See if the tree already exists in the `backfill_items` table. - let rows = backfill_items::Entity::find() - .filter(backfill_items::Column::Tree.eq(tree_id)) - .limit(1) - .all(txn) - .await?; - - // If the tree does not exist in `backfill_items` and the sequence number is greater than 1, - // then we know we will need to backfill the tree from sequence number 1 up to the current - // sequence number. So in this case we set at flag to force checking the tree. - let force_chk = rows.is_empty() && change_log_event.seq > 1; - - info!("Adding to backfill_items table at level {}", i - 1); - let item = backfill_items::ActiveModel { - tree: Set(tree_id.to_vec()), - seq: Set(change_log_event.seq as i64), - slot: Set(slot as i64), - force_chk: Set(force_chk), - backfilled: Set(false), - failed: Set(false), - ..Default::default() - }; - - backfill_items::Entity::insert(item).exec(txn).await?; - } - - Ok(()) - //TODO -> set maximum size of path and break into multiple statements -} - -#[allow(clippy::too_many_arguments)] -pub async fn upsert_asset_with_leaf_info( - txn: &T, - id: Vec, - nonce: i64, - tree_id: Vec, - leaf: Vec, - data_hash: [u8; 32], - creator_hash: [u8; 32], - seq: i64, - was_decompressed: bool, -) -> Result<(), IngesterError> -where - T: ConnectionTrait + TransactionTrait, -{ - let data_hash = bs58::encode(data_hash).into_string().trim().to_string(); - let creator_hash = bs58::encode(creator_hash).into_string().trim().to_string(); - let model = asset::ActiveModel { - id: Set(id), - nonce: Set(Some(nonce)), - tree_id: Set(Some(tree_id)), - leaf: Set(Some(leaf)), - data_hash: Set(Some(data_hash)), - creator_hash: Set(Some(creator_hash)), - leaf_seq: Set(Some(seq)), - ..Default::default() - }; - - let mut query = asset::Entity::insert(model) - .on_conflict( - OnConflict::column(asset::Column::Id) - .update_columns([ - asset::Column::Nonce, - asset::Column::TreeId, - asset::Column::Leaf, - asset::Column::LeafSeq, - asset::Column::DataHash, - asset::Column::CreatorHash, - ]) - .to_owned(), - ) - .build(DbBackend::Postgres); - - // If we are indexing decompression we will update the leaf regardless of if we have previously - // indexed decompression and regardless of seq. - if !was_decompressed { - query.sql = format!( - "{} WHERE (NOT asset.was_decompressed) AND (excluded.leaf_seq >= asset.leaf_seq OR asset.leaf_seq IS NULL)", - query.sql - ); - } - - txn.execute(query) - .await - .map_err(|db_err| IngesterError::StorageWriteError(db_err.to_string()))?; - - Ok(()) -} - -pub async fn upsert_asset_with_leaf_info_for_decompression( - txn: &T, - id: Vec, -) -> Result<(), IngesterError> -where - T: ConnectionTrait + TransactionTrait, -{ - let model = asset::ActiveModel { - id: Set(id), - leaf: Set(None), - nonce: Set(Some(0)), - leaf_seq: Set(None), - data_hash: Set(None), - creator_hash: Set(None), - tree_id: Set(None), - seq: Set(Some(0)), - ..Default::default() - }; - let query = asset::Entity::insert(model) - .on_conflict( - OnConflict::column(asset::Column::Id) - .update_columns([ - asset::Column::Leaf, - asset::Column::LeafSeq, - asset::Column::Nonce, - asset::Column::DataHash, - asset::Column::CreatorHash, - asset::Column::TreeId, - asset::Column::Seq, - ]) - .to_owned(), - ) - .build(DbBackend::Postgres); - txn.execute(query) - .await - .map_err(|db_err| IngesterError::StorageWriteError(db_err.to_string()))?; - - Ok(()) -} - -pub async fn upsert_asset_with_owner_and_delegate_info( - txn: &T, - id: Vec, - owner: Vec, - delegate: Option>, - seq: i64, -) -> Result<(), IngesterError> -where - T: ConnectionTrait + TransactionTrait, -{ - let model = asset::ActiveModel { - id: Set(id), - owner: Set(Some(owner)), - delegate: Set(delegate), - owner_delegate_seq: Set(Some(seq)), // gummyroll seq - ..Default::default() - }; - - let mut query = asset::Entity::insert(model) - .on_conflict( - OnConflict::column(asset::Column::Id) - .update_columns([ - asset::Column::Owner, - asset::Column::Delegate, - asset::Column::OwnerDelegateSeq, - ]) - .to_owned(), - ) - .build(DbBackend::Postgres); - query.sql = format!( - "{} WHERE excluded.owner_delegate_seq >= asset.owner_delegate_seq OR asset.owner_delegate_seq IS NULL", - query.sql - ); - - txn.execute(query) - .await - .map_err(|db_err| IngesterError::StorageWriteError(db_err.to_string()))?; - - Ok(()) -} - -pub async fn upsert_asset_with_compression_info( - txn: &T, - id: Vec, - compressed: bool, - compressible: bool, - supply: i64, - supply_mint: Option>, - was_decompressed: bool, -) -> Result<(), IngesterError> -where - T: ConnectionTrait + TransactionTrait, -{ - let model = asset::ActiveModel { - id: Set(id), - compressed: Set(compressed), - compressible: Set(compressible), - supply: Set(supply), - supply_mint: Set(supply_mint), - was_decompressed: Set(was_decompressed), - ..Default::default() - }; - - let mut query = asset::Entity::insert(model) - .on_conflict( - OnConflict::columns([asset::Column::Id]) - .update_columns([ - asset::Column::Compressed, - asset::Column::Compressible, - asset::Column::Supply, - asset::Column::SupplyMint, - asset::Column::WasDecompressed, - ]) - .to_owned(), - ) - .build(DbBackend::Postgres); - query.sql = format!("{} WHERE NOT asset.was_decompressed", query.sql); - txn.execute(query).await?; - - Ok(()) -} - -pub async fn upsert_asset_with_seq(txn: &T, id: Vec, seq: i64) -> Result<(), IngesterError> -where - T: ConnectionTrait + TransactionTrait, -{ - let model = asset::ActiveModel { - id: Set(id), - seq: Set(Some(seq)), - ..Default::default() - }; - - let mut query = asset::Entity::insert(model) - .on_conflict( - OnConflict::column(asset::Column::Id) - .update_columns([asset::Column::Seq]) - .to_owned(), - ) - .build(DbBackend::Postgres); - - query.sql = format!( - "{} WHERE (NOT asset.was_decompressed) AND (excluded.seq >= asset.seq OR asset.seq IS NULL)", - query.sql - ); - - txn.execute(query) - .await - .map_err(|db_err| IngesterError::StorageWriteError(db_err.to_string()))?; - - Ok(()) -} - -pub async fn upsert_creator_verified( - txn: &T, - asset_id: Vec, - creator: Vec, - verified: bool, - seq: i64, -) -> Result<(), IngesterError> -where - T: ConnectionTrait + TransactionTrait, -{ - let model = asset_creators::ActiveModel { - asset_id: Set(asset_id), - creator: Set(creator), - verified: Set(verified), - seq: Set(Some(seq)), - ..Default::default() - }; - - let mut query = asset_creators::Entity::insert(model) - .on_conflict( - OnConflict::columns([ - asset_creators::Column::AssetId, - asset_creators::Column::Creator, - ]) - .update_columns([ - asset_creators::Column::Verified, - asset_creators::Column::Seq, - ]) - .to_owned(), - ) - .build(DbBackend::Postgres); - - query.sql = format!( - "{} WHERE excluded.seq >= asset_creators.seq OR asset_creators.seq is NULL", - query.sql - ); - - txn.execute(query) - .await - .map_err(|db_err| IngesterError::StorageWriteError(db_err.to_string()))?; - - Ok(()) -} - -pub async fn upsert_collection_info( - txn: &T, - asset_id: Vec, - collection: Option, - slot_updated: i64, - seq: i64, -) -> Result<(), IngesterError> -where - T: ConnectionTrait + TransactionTrait, -{ - let (group_value, verified) = match collection { - Some(c) => (Some(c.key.to_string()), c.verified), - None => (None, false), - }; - - let model = asset_grouping::ActiveModel { - asset_id: Set(asset_id), - group_key: Set("collection".to_string()), - group_value: Set(group_value), - verified: Set(Some(verified)), - slot_updated: Set(Some(slot_updated)), - group_info_seq: Set(Some(seq)), - ..Default::default() - }; - - let mut query = asset_grouping::Entity::insert(model) - .on_conflict( - OnConflict::columns([ - asset_grouping::Column::AssetId, - asset_grouping::Column::GroupKey, - ]) - .update_columns([ - asset_grouping::Column::GroupValue, - asset_grouping::Column::Verified, - asset_grouping::Column::SlotUpdated, - asset_grouping::Column::GroupInfoSeq, - ]) - .to_owned(), - ) - .build(DbBackend::Postgres); - - query.sql = format!( - "{} WHERE excluded.group_info_seq >= asset_grouping.group_info_seq OR asset_grouping.group_info_seq IS NULL", - query.sql - ); - - txn.execute(query) - .await - .map_err(|db_err| IngesterError::StorageWriteError(db_err.to_string()))?; - - Ok(()) -} diff --git a/nft_ingester/src/program_transformers/bubblegum/decompress.rs b/nft_ingester/src/program_transformers/bubblegum/decompress.rs deleted file mode 100644 index a024d5ebe..000000000 --- a/nft_ingester/src/program_transformers/bubblegum/decompress.rs +++ /dev/null @@ -1,32 +0,0 @@ -use crate::{ - error::IngesterError, - program_transformers::bubblegum::upsert_asset_with_leaf_info_for_decompression, -}; -use blockbuster::{instruction::InstructionBundle, programs::bubblegum::BubblegumInstruction}; -use sea_orm::{query::*, ConnectionTrait}; - -use super::upsert_asset_with_compression_info; - -pub async fn decompress<'c, T>( - _parsing_result: &BubblegumInstruction, - bundle: &InstructionBundle<'c>, - txn: &'c T, -) -> Result<(), IngesterError> -where - T: ConnectionTrait + TransactionTrait, -{ - let id_bytes = bundle.keys.get(3).unwrap().0.as_slice(); - - // Partial update of asset table with just leaf. - upsert_asset_with_leaf_info_for_decompression(txn, id_bytes.to_vec()).await?; - upsert_asset_with_compression_info( - txn, - id_bytes.to_vec(), - false, - false, - 1, - Some(id_bytes.to_vec()), - true, - ) - .await -} diff --git a/nft_ingester/src/program_transformers/bubblegum/delegate.rs b/nft_ingester/src/program_transformers/bubblegum/delegate.rs deleted file mode 100644 index 88896de64..000000000 --- a/nft_ingester/src/program_transformers/bubblegum/delegate.rs +++ /dev/null @@ -1,72 +0,0 @@ -use crate::{ - error::IngesterError, - program_transformers::bubblegum::{ - save_changelog_event, upsert_asset_with_leaf_info, - upsert_asset_with_owner_and_delegate_info, upsert_asset_with_seq, - }, -}; -use blockbuster::{ - instruction::InstructionBundle, - programs::bubblegum::{BubblegumInstruction, LeafSchema}, -}; -use sea_orm::{ConnectionTrait, TransactionTrait}; - -pub async fn delegate<'c, T>( - parsing_result: &BubblegumInstruction, - bundle: &InstructionBundle<'c>, - txn: &'c T, - cl_audits: bool, -) -> Result<(), IngesterError> -where - T: ConnectionTrait + TransactionTrait, -{ - if let (Some(le), Some(cl)) = (&parsing_result.leaf_update, &parsing_result.tree_update) { - let seq = save_changelog_event(cl, bundle.slot, bundle.txn_id, txn, cl_audits).await?; - return match le.schema { - LeafSchema::V1 { - id, - owner, - delegate, - .. - } => { - let id_bytes = id.to_bytes(); - let owner_bytes = owner.to_bytes().to_vec(); - let delegate = if owner == delegate || delegate.to_bytes() == [0; 32] { - None - } else { - Some(delegate.to_bytes().to_vec()) - }; - let tree_id = cl.id.to_bytes(); - - // Partial update of asset table with just leaf. - upsert_asset_with_leaf_info( - txn, - id_bytes.to_vec(), - cl.index as i64, - tree_id.to_vec(), - le.leaf_hash.to_vec(), - le.schema.data_hash(), - le.schema.creator_hash(), - seq as i64, - false, - ) - .await?; - - // Partial update of asset table with just leaf owner and delegate. - upsert_asset_with_owner_and_delegate_info( - txn, - id_bytes.to_vec(), - owner_bytes, - delegate, - seq as i64, - ) - .await?; - - upsert_asset_with_seq(txn, id_bytes.to_vec(), seq as i64).await - } - }; - } - Err(IngesterError::ParsingError( - "Ix not parsed correctly".to_string(), - )) -} diff --git a/nft_ingester/src/program_transformers/bubblegum/mint_v1.rs b/nft_ingester/src/program_transformers/bubblegum/mint_v1.rs deleted file mode 100644 index 685649f79..000000000 --- a/nft_ingester/src/program_transformers/bubblegum/mint_v1.rs +++ /dev/null @@ -1,364 +0,0 @@ -use crate::{ - error::IngesterError, - program_transformers::bubblegum::{ - save_changelog_event, upsert_asset_with_compression_info, upsert_asset_with_leaf_info, - upsert_asset_with_owner_and_delegate_info, upsert_asset_with_seq, upsert_collection_info, - }, - tasks::{DownloadMetadata, IntoTaskData, TaskData}, -}; -use blockbuster::{ - instruction::InstructionBundle, - programs::bubblegum::{BubblegumInstruction, LeafSchema, Payload}, - token_metadata::{ - pda::find_master_edition_account, - state::{TokenStandard, UseMethod, Uses}, - }, -}; -use chrono::Utc; -use digital_asset_types::{ - dao::{ - asset, asset_authority, asset_creators, asset_data, asset_v1_account_attachments, - sea_orm_active_enums::{ChainMutability, Mutability, OwnerType, RoyaltyTargetType}, - }, - json::ChainDataV1, -}; -use log::warn; -use num_traits::FromPrimitive; -use sea_orm::{ - entity::*, query::*, sea_query::OnConflict, ConnectionTrait, DbBackend, EntityTrait, JsonValue, -}; -use std::collections::HashSet; - -use digital_asset_types::dao::sea_orm_active_enums::{ - SpecificationAssetClass, SpecificationVersions, V1AccountAttachments, -}; - -// TODO -> consider moving structs into these functions to avoid clone - -pub async fn mint_v1<'c, T>( - parsing_result: &BubblegumInstruction, - bundle: &InstructionBundle<'c>, - txn: &'c T, - cl_audits: bool, -) -> Result, IngesterError> -where - T: ConnectionTrait + TransactionTrait, -{ - if let (Some(le), Some(cl), Some(Payload::MintV1 { args })) = ( - &parsing_result.leaf_update, - &parsing_result.tree_update, - &parsing_result.payload, - ) { - let seq = save_changelog_event(cl, bundle.slot, bundle.txn_id, txn, cl_audits).await?; - let metadata = args; - #[allow(unreachable_patterns)] - return match le.schema { - LeafSchema::V1 { - id, - delegate, - owner, - nonce, - .. - } => { - let (edition_attachment_address, _) = find_master_edition_account(&id); - let id_bytes = id.to_bytes(); - let slot_i = bundle.slot as i64; - let uri = metadata.uri.replace('\0', ""); - let name = metadata.name.clone().into_bytes(); - let symbol = metadata.symbol.clone().into_bytes(); - let mut chain_data = ChainDataV1 { - name: metadata.name.clone(), - symbol: metadata.symbol.clone(), - edition_nonce: metadata.edition_nonce, - primary_sale_happened: metadata.primary_sale_happened, - token_standard: Some(TokenStandard::NonFungible), - uses: metadata.uses.clone().map(|u| Uses { - use_method: UseMethod::from_u8(u.use_method as u8).unwrap(), - remaining: u.remaining, - total: u.total, - }), - }; - chain_data.sanitize(); - let chain_data_json = serde_json::to_value(chain_data) - .map_err(|e| IngesterError::DeserializationError(e.to_string()))?; - let chain_mutability = match metadata.is_mutable { - true => ChainMutability::Mutable, - false => ChainMutability::Immutable, - }; - - let data = asset_data::ActiveModel { - id: Set(id_bytes.to_vec()), - chain_data_mutability: Set(chain_mutability), - chain_data: Set(chain_data_json), - metadata_url: Set(uri.clone()), - metadata: Set(JsonValue::String("processing".to_string())), - metadata_mutability: Set(Mutability::Mutable), - slot_updated: Set(slot_i), - reindex: Set(Some(true)), - raw_name: Set(name.to_vec()), - raw_symbol: Set(symbol.to_vec()), - }; - - let mut query = asset_data::Entity::insert(data) - .on_conflict( - OnConflict::columns([asset_data::Column::Id]) - .update_columns([ - asset_data::Column::ChainDataMutability, - asset_data::Column::ChainData, - asset_data::Column::MetadataUrl, - asset_data::Column::MetadataMutability, - asset_data::Column::SlotUpdated, - asset_data::Column::Reindex, - asset_data::Column::RawName, - asset_data::Column::RawSymbol, - ]) - .to_owned(), - ) - .build(DbBackend::Postgres); - query.sql = format!( - "{} WHERE excluded.slot_updated > asset_data.slot_updated", - query.sql - ); - txn.execute(query) - .await - .map_err(|db_err| IngesterError::AssetIndexError(db_err.to_string()))?; - // Insert into `asset` table. - let delegate = if owner == delegate || delegate.to_bytes() == [0; 32] { - None - } else { - Some(delegate.to_bytes().to_vec()) - }; - let tree_id = bundle.keys.get(3).unwrap().0.to_vec(); - - // Set initial mint info. - let asset_model = asset::ActiveModel { - id: Set(id_bytes.to_vec()), - owner_type: Set(OwnerType::Single), - frozen: Set(false), - tree_id: Set(Some(tree_id.clone())), - specification_version: Set(Some(SpecificationVersions::V1)), - specification_asset_class: Set(Some(SpecificationAssetClass::Nft)), - nonce: Set(Some(nonce as i64)), - royalty_target_type: Set(RoyaltyTargetType::Creators), - royalty_target: Set(None), - royalty_amount: Set(metadata.seller_fee_basis_points as i32), //basis points - asset_data: Set(Some(id_bytes.to_vec())), - slot_updated: Set(Some(slot_i)), - ..Default::default() - }; - - // Upsert asset table base info. - let mut query = asset::Entity::insert(asset_model) - .on_conflict( - OnConflict::columns([asset::Column::Id]) - .update_columns([ - asset::Column::OwnerType, - asset::Column::Frozen, - asset::Column::SpecificationVersion, - asset::Column::SpecificationAssetClass, - asset::Column::RoyaltyTargetType, - asset::Column::RoyaltyTarget, - asset::Column::RoyaltyAmount, - asset::Column::AssetData, - ]) - .to_owned(), - ) - .build(DbBackend::Postgres); - - // Do not overwrite changes that happened after the asset was decompressed. - query.sql = format!( - "{} WHERE excluded.slot_updated > asset.slot_updated OR asset.slot_updated IS NULL", - query.sql - ); - txn.execute(query) - .await - .map_err(|db_err| IngesterError::AssetIndexError(db_err.to_string()))?; - - // Partial update of asset table with just compression info elements. - upsert_asset_with_compression_info( - txn, - id_bytes.to_vec(), - true, - false, - 1, - None, - false, - ) - .await?; - - // Partial update of asset table with just leaf. - upsert_asset_with_leaf_info( - txn, - id_bytes.to_vec(), - nonce as i64, - tree_id, - le.leaf_hash.to_vec(), - le.schema.data_hash(), - le.schema.creator_hash(), - seq as i64, - false, - ) - .await?; - - // Partial update of asset table with just leaf owner and delegate. - upsert_asset_with_owner_and_delegate_info( - txn, - id_bytes.to_vec(), - owner.to_bytes().to_vec(), - delegate, - seq as i64, - ) - .await?; - - upsert_asset_with_seq(txn, id_bytes.to_vec(), seq as i64).await?; - - let attachment = asset_v1_account_attachments::ActiveModel { - id: Set(edition_attachment_address.to_bytes().to_vec()), - slot_updated: Set(slot_i), - attachment_type: Set(V1AccountAttachments::MasterEditionV2), - ..Default::default() - }; - - let query = asset_v1_account_attachments::Entity::insert(attachment) - .on_conflict( - OnConflict::columns([asset_v1_account_attachments::Column::Id]) - .do_nothing() - .to_owned(), - ) - .build(DbBackend::Postgres); - txn.execute(query) - .await - .map_err(|db_err| IngesterError::AssetIndexError(db_err.to_string()))?; - - // Insert into `asset_creators` table. - let creators = &metadata.creators; - if !creators.is_empty() { - // Vec to hold base creator information. - let mut db_creator_infos = Vec::with_capacity(creators.len()); - - // Vec to hold info on whether a creator is verified. This info is protected by `seq` number. - let mut db_creator_verified_infos = Vec::with_capacity(creators.len()); - - // Set to prevent duplicates. - let mut creators_set = HashSet::new(); - - for (i, c) in creators.iter().enumerate() { - if creators_set.contains(&c.address) { - continue; - } - db_creator_infos.push(asset_creators::ActiveModel { - asset_id: Set(id_bytes.to_vec()), - creator: Set(c.address.to_bytes().to_vec()), - position: Set(i as i16), - share: Set(c.share as i32), - slot_updated: Set(Some(slot_i)), - ..Default::default() - }); - - db_creator_verified_infos.push(asset_creators::ActiveModel { - asset_id: Set(id_bytes.to_vec()), - creator: Set(c.address.to_bytes().to_vec()), - verified: Set(c.verified), - seq: Set(Some(seq as i64)), - ..Default::default() - }); - - creators_set.insert(c.address); - } - - // This statement will update base information for each creator. - let query = asset_creators::Entity::insert_many(db_creator_infos) - .on_conflict( - OnConflict::columns([ - asset_creators::Column::AssetId, - asset_creators::Column::Creator, - ]) - .update_columns([ - asset_creators::Column::Position, - asset_creators::Column::Share, - asset_creators::Column::SlotUpdated, - ]) - .to_owned(), - ) - .build(DbBackend::Postgres); - txn.execute(query).await?; - - // This statement will update whether the creator is verified and the `seq` - // number. `seq` is used to protect the `verified` field, allowing for `mint` - // and `verifyCreator` to be processed out of order. - let mut query = asset_creators::Entity::insert_many(db_creator_verified_infos) - .on_conflict( - OnConflict::columns([ - asset_creators::Column::AssetId, - asset_creators::Column::Creator, - ]) - .update_columns([ - asset_creators::Column::Verified, - asset_creators::Column::Seq, - ]) - .to_owned(), - ) - .build(DbBackend::Postgres); - query.sql = format!( - "{} WHERE excluded.seq > asset_creators.seq OR asset_creators.seq IS NULL", - query.sql - ); - txn.execute(query).await?; - } - - // Insert into `asset_authority` table. - let model = asset_authority::ActiveModel { - asset_id: Set(id_bytes.to_vec()), - authority: Set(bundle.keys.get(0).unwrap().0.to_vec()), //TODO - we need to rem,ove the optional bubblegum signer logic - seq: Set(seq as i64), - slot_updated: Set(slot_i), - ..Default::default() - }; - - // Do not attempt to modify any existing values: - // `ON CONFLICT ('asset_id') DO NOTHING`. - let query = asset_authority::Entity::insert(model) - .on_conflict( - OnConflict::columns([asset_authority::Column::AssetId]) - .do_nothing() - .to_owned(), - ) - .build(DbBackend::Postgres); - txn.execute(query) - .await - .map_err(|db_err| IngesterError::AssetIndexError(db_err.to_string()))?; - - // Upsert into `asset_grouping` table with base collection info. - upsert_collection_info( - txn, - id_bytes.to_vec(), - metadata.collection.clone(), - slot_i, - seq as i64, - ) - .await?; - - if uri.is_empty() { - warn!( - "URI is empty for mint {}. Skipping background task.", - bs58::encode(id).into_string() - ); - return Ok(None); - } - - let mut task = DownloadMetadata { - asset_data_id: id_bytes.to_vec(), - uri: metadata.uri.clone(), - created_at: Some(Utc::now().naive_utc()), - }; - task.sanitize(); - let t = task.into_task_data()?; - Ok(Some(t)) - } - _ => Err(IngesterError::NotImplemented), - }; - } - Err(IngesterError::ParsingError( - "Ix not parsed correctly".to_string(), - )) -} diff --git a/nft_ingester/src/program_transformers/bubblegum/mod.rs b/nft_ingester/src/program_transformers/bubblegum/mod.rs deleted file mode 100644 index bcc102c0b..000000000 --- a/nft_ingester/src/program_transformers/bubblegum/mod.rs +++ /dev/null @@ -1,108 +0,0 @@ -use blockbuster::{ - self, - instruction::InstructionBundle, - programs::bubblegum::{BubblegumInstruction, InstructionName}, -}; -use log::{debug, info}; -use sea_orm::{ConnectionTrait, TransactionTrait}; -use tokio::sync::mpsc::UnboundedSender; - -mod burn; -mod cancel_redeem; -mod collection_verification; -mod creator_verification; -mod db; -mod decompress; -mod delegate; -mod mint_v1; -mod redeem; -mod transfer; - -pub use db::*; - -use crate::{error::IngesterError, tasks::TaskData}; - -pub async fn handle_bubblegum_instruction<'c, T>( - parsing_result: &'c BubblegumInstruction, - bundle: &'c InstructionBundle<'c>, - txn: &T, - task_manager: &UnboundedSender, - cl_audits: bool, -) -> Result<(), IngesterError> -where - T: ConnectionTrait + TransactionTrait, -{ - let ix_type = &parsing_result.instruction; - - // @TODO this would be much better served by implemneting Debug trait on the InstructionName - // or wrapping it into something that can display it more neatly. - let ix_str = match ix_type { - InstructionName::Unknown => "Unknown", - InstructionName::MintV1 => "MintV1", - InstructionName::MintToCollectionV1 => "MintToCollectionV1", - InstructionName::Redeem => "Redeem", - InstructionName::CancelRedeem => "CancelRedeem", - InstructionName::Transfer => "Transfer", - InstructionName::Delegate => "Delegate", - InstructionName::DecompressV1 => "DecompressV1", - InstructionName::Compress => "Compress", - InstructionName::Burn => "Burn", - InstructionName::CreateTree => "CreateTree", - InstructionName::VerifyCreator => "VerifyCreator", - InstructionName::UnverifyCreator => "UnverifyCreator", - InstructionName::VerifyCollection => "VerifyCollection", - InstructionName::UnverifyCollection => "UnverifyCollection", - InstructionName::SetAndVerifyCollection => "SetAndVerifyCollection", - InstructionName::SetDecompressibleState | InstructionName::UpdateMetadata => todo!(), - }; - info!("BGUM instruction txn={:?}: {:?}", ix_str, bundle.txn_id); - - match ix_type { - InstructionName::Transfer => { - transfer::transfer(parsing_result, bundle, txn, cl_audits).await?; - } - InstructionName::Burn => { - burn::burn(parsing_result, bundle, txn, cl_audits).await?; - } - InstructionName::Delegate => { - delegate::delegate(parsing_result, bundle, txn, cl_audits).await?; - } - InstructionName::MintV1 | InstructionName::MintToCollectionV1 => { - let task = mint_v1::mint_v1(parsing_result, bundle, txn, cl_audits).await?; - - if let Some(t) = task { - task_manager.send(t)?; - } - } - InstructionName::Redeem => { - redeem::redeem(parsing_result, bundle, txn, cl_audits).await?; - } - InstructionName::CancelRedeem => { - cancel_redeem::cancel_redeem(parsing_result, bundle, txn, cl_audits).await?; - } - InstructionName::DecompressV1 => { - decompress::decompress(parsing_result, bundle, txn).await?; - } - InstructionName::VerifyCreator => { - creator_verification::process(parsing_result, bundle, txn, true, cl_audits).await?; - } - InstructionName::UnverifyCreator => { - creator_verification::process(parsing_result, bundle, txn, false, cl_audits).await?; - } - InstructionName::VerifyCollection - | InstructionName::UnverifyCollection - | InstructionName::SetAndVerifyCollection => { - collection_verification::process(parsing_result, bundle, txn, cl_audits).await?; - } - _ => debug!("Bubblegum: Not Implemented Instruction"), - } - Ok(()) -} - -// PDA lookup requires an 8-byte array. -fn u32_to_u8_array(value: u32) -> [u8; 8] { - let bytes: [u8; 4] = value.to_le_bytes(); - let mut result: [u8; 8] = [0; 8]; - result[..4].copy_from_slice(&bytes); - result -} diff --git a/nft_ingester/src/program_transformers/bubblegum/redeem.rs b/nft_ingester/src/program_transformers/bubblegum/redeem.rs deleted file mode 100644 index b9b7f2c27..000000000 --- a/nft_ingester/src/program_transformers/bubblegum/redeem.rs +++ /dev/null @@ -1,59 +0,0 @@ -use anchor_lang::prelude::Pubkey; -use log::debug; - -use crate::{ - error::IngesterError, - program_transformers::bubblegum::{ - save_changelog_event, u32_to_u8_array, upsert_asset_with_leaf_info, upsert_asset_with_seq, - }, -}; -use blockbuster::{instruction::InstructionBundle, programs::bubblegum::BubblegumInstruction}; -use sea_orm::{ConnectionTrait, TransactionTrait}; - -pub async fn redeem<'c, T>( - parsing_result: &BubblegumInstruction, - bundle: &InstructionBundle<'c>, - txn: &'c T, - cl_audits: bool, -) -> Result<(), IngesterError> -where - T: ConnectionTrait + TransactionTrait, -{ - if let Some(cl) = &parsing_result.tree_update { - let seq = save_changelog_event(cl, bundle.slot, bundle.txn_id, txn, cl_audits).await?; - let leaf_index = cl.index; - let (asset_id, _) = Pubkey::find_program_address( - &[ - "asset".as_bytes(), - cl.id.as_ref(), - u32_to_u8_array(leaf_index).as_ref(), - ], - &mpl_bubblegum::ID, - ); - debug!("Indexing redeem for asset id: {:?}", asset_id); - let id_bytes = asset_id.to_bytes(); - let tree_id = cl.id.to_bytes(); - let nonce = cl.index as i64; - - // Partial update of asset table with just leaf. - upsert_asset_with_leaf_info( - txn, - id_bytes.to_vec(), - nonce, - tree_id.to_vec(), - vec![0; 32], - [0; 32], - [0; 32], - seq as i64, - false, - ) - .await?; - - upsert_asset_with_seq(txn, id_bytes.to_vec(), seq as i64).await?; - - return Ok(()); - } - Err(IngesterError::ParsingError( - "Ix not parsed correctly".to_string(), - )) -} diff --git a/nft_ingester/src/program_transformers/bubblegum/transfer.rs b/nft_ingester/src/program_transformers/bubblegum/transfer.rs deleted file mode 100644 index 573f33a8f..000000000 --- a/nft_ingester/src/program_transformers/bubblegum/transfer.rs +++ /dev/null @@ -1,75 +0,0 @@ -use super::save_changelog_event; -use crate::{ - error::IngesterError, - program_transformers::bubblegum::{ - upsert_asset_with_leaf_info, upsert_asset_with_owner_and_delegate_info, - upsert_asset_with_seq, - }, -}; -use blockbuster::{ - instruction::InstructionBundle, - programs::bubblegum::{BubblegumInstruction, LeafSchema}, -}; -use sea_orm::{ConnectionTrait, TransactionTrait}; - -pub async fn transfer<'c, T>( - parsing_result: &BubblegumInstruction, - bundle: &InstructionBundle<'c>, - txn: &'c T, - cl_audits: bool, -) -> Result<(), IngesterError> -where - T: ConnectionTrait + TransactionTrait, -{ - if let (Some(le), Some(cl)) = (&parsing_result.leaf_update, &parsing_result.tree_update) { - let seq = save_changelog_event(cl, bundle.slot, bundle.txn_id, txn, cl_audits).await?; - #[allow(unreachable_patterns)] - return match le.schema { - LeafSchema::V1 { - id, - owner, - delegate, - .. - } => { - let id_bytes = id.to_bytes(); - let owner_bytes = owner.to_bytes().to_vec(); - let delegate = if owner == delegate || delegate.to_bytes() == [0; 32] { - None - } else { - Some(delegate.to_bytes().to_vec()) - }; - let tree_id = cl.id.to_bytes(); - let nonce = cl.index as i64; - - // Partial update of asset table with just leaf. - upsert_asset_with_leaf_info( - txn, - id_bytes.to_vec(), - nonce, - tree_id.to_vec(), - le.leaf_hash.to_vec(), - le.schema.data_hash(), - le.schema.creator_hash(), - seq as i64, - false, - ) - .await?; - - // Partial update of asset table with just leaf owner and delegate. - upsert_asset_with_owner_and_delegate_info( - txn, - id_bytes.to_vec(), - owner_bytes, - delegate, - seq as i64, - ) - .await?; - - upsert_asset_with_seq(txn, id_bytes.to_vec(), seq as i64).await - } - }; - } - Err(IngesterError::ParsingError( - "Ix not parsed correctly".to_string(), - )) -} diff --git a/nft_ingester/src/program_transformers/mod.rs b/nft_ingester/src/program_transformers/mod.rs deleted file mode 100644 index fc555829d..000000000 --- a/nft_ingester/src/program_transformers/mod.rs +++ /dev/null @@ -1,189 +0,0 @@ -use crate::{error::IngesterError, tasks::TaskData}; -use blockbuster::{ - instruction::{order_instructions, InstructionBundle, IxPair}, - program_handler::ProgramParser, - programs::{ - bubblegum::BubblegumParser, token_account::TokenAccountParser, - token_metadata::TokenMetadataParser, ProgramParseResult, - }, -}; -use log::{debug, error, info}; -use plerkle_serialization::{AccountInfo, Pubkey as FBPubkey, TransactionInfo}; -use sea_orm::{DatabaseConnection, SqlxPostgresConnector}; -use solana_sdk::pubkey::Pubkey; -use sqlx::PgPool; -use std::collections::{HashMap, HashSet, VecDeque}; -use tokio::sync::mpsc::UnboundedSender; - -use crate::program_transformers::{ - bubblegum::handle_bubblegum_instruction, token::handle_token_program_account, - token_metadata::handle_token_metadata_account, -}; - -mod bubblegum; -mod token; -mod token_metadata; - -pub struct ProgramTransformer { - storage: DatabaseConnection, - task_sender: UnboundedSender, - matchers: HashMap>, - key_set: HashSet, - cl_audits: bool, -} - -impl ProgramTransformer { - pub fn new(pool: PgPool, task_sender: UnboundedSender, cl_audits: bool) -> Self { - let mut matchers: HashMap> = HashMap::with_capacity(1); - let bgum = BubblegumParser {}; - let token_metadata = TokenMetadataParser {}; - let token = TokenAccountParser {}; - matchers.insert(bgum.key(), Box::new(bgum)); - matchers.insert(token_metadata.key(), Box::new(token_metadata)); - matchers.insert(token.key(), Box::new(token)); - let hs = matchers.iter().fold(HashSet::new(), |mut acc, (k, _)| { - acc.insert(*k); - acc - }); - let pool: PgPool = pool; - ProgramTransformer { - storage: SqlxPostgresConnector::from_sqlx_postgres_pool(pool), - task_sender, - matchers, - key_set: hs, - cl_audits, - } - } - - pub fn break_transaction<'i>( - &self, - tx: &'i TransactionInfo<'i>, - ) -> VecDeque<(IxPair<'i>, Option>>)> { - let ref_set: HashSet<&[u8]> = self.key_set.iter().map(|k| k.as_ref()).collect(); - order_instructions(ref_set, tx) - } - - #[allow(clippy::borrowed_box)] - pub fn match_program(&self, key: &FBPubkey) -> Option<&Box> { - self.matchers - .get(&Pubkey::try_from(key.0.as_slice()).expect("valid key from FlatBuffer")) - } - - pub async fn handle_transaction<'a>( - &self, - tx: &'a TransactionInfo<'a>, - ) -> Result<(), IngesterError> { - let sig: Option<&str> = tx.signature(); - info!("Handling Transaction: {:?}", sig); - let instructions = self.break_transaction(tx); - let accounts = tx.account_keys().unwrap_or_default(); - let slot = tx.slot(); - let txn_id = tx.signature().unwrap_or(""); - let mut keys: Vec = Vec::with_capacity(accounts.len()); - for k in accounts.into_iter() { - keys.push(*k); - } - let mut not_impl = 0; - let ixlen = instructions.len(); - debug!("Instructions: {}", ixlen); - let contains = instructions - .iter() - .filter(|(ib, _inner)| ib.0 .0.as_ref() == mpl_bubblegum::ID.as_ref()); - debug!("Instructions bgum: {}", contains.count()); - for (outer_ix, inner_ix) in instructions { - let (program, instruction) = outer_ix; - let ix_accounts = instruction.accounts().unwrap().iter().collect::>(); - let ix_account_len = ix_accounts.len(); - let max = ix_accounts.iter().max().copied().unwrap_or(0) as usize; - if keys.len() < max { - return Err(IngesterError::DeserializationError( - "Missing Accounts in Serialized Ixn/Txn".to_string(), - )); - } - let ix_accounts = - ix_accounts - .iter() - .fold(Vec::with_capacity(ix_account_len), |mut acc, a| { - if let Some(key) = keys.get(*a as usize) { - acc.push(*key); - } - acc - }); - let ix = InstructionBundle { - txn_id, - program, - instruction: Some(instruction), - inner_ix, - keys: ix_accounts.as_slice(), - slot, - }; - - if let Some(program) = self.match_program(&ix.program) { - debug!("Found a ix for program: {:?}", program.key()); - let result = program.handle_instruction(&ix)?; - let concrete = result.result_type(); - match concrete { - ProgramParseResult::Bubblegum(parsing_result) => { - handle_bubblegum_instruction( - parsing_result, - &ix, - &self.storage, - &self.task_sender, - self.cl_audits, - ) - .await - .map_err(|err| { - error!( - "Failed to handle bubblegum instruction for txn {:?}: {:?}", - sig, err - ); - err - })?; - } - _ => { - not_impl += 1; - } - }; - } - } - - if not_impl == ixlen { - debug!("Not imple"); - return Err(IngesterError::NotImplemented); - } - Ok(()) - } - - pub async fn handle_account_update<'b>( - &self, - acct: AccountInfo<'b>, - ) -> Result<(), IngesterError> { - let owner = acct.owner().unwrap(); - if let Some(program) = self.match_program(owner) { - let result = program.handle_account(&acct)?; - let concrete = result.result_type(); - match concrete { - ProgramParseResult::TokenMetadata(parsing_result) => { - handle_token_metadata_account( - &acct, - parsing_result, - &self.storage, - &self.task_sender, - ) - .await - } - ProgramParseResult::TokenProgramAccount(parsing_result) => { - handle_token_program_account( - &acct, - parsing_result, - &self.storage, - &self.task_sender, - ) - .await - } - _ => Err(IngesterError::NotImplemented), - }?; - } - Ok(()) - } -} diff --git a/nft_ingester/src/program_transformers/token/mod.rs b/nft_ingester/src/program_transformers/token/mod.rs deleted file mode 100644 index c32cad020..000000000 --- a/nft_ingester/src/program_transformers/token/mod.rs +++ /dev/null @@ -1,141 +0,0 @@ -use crate::{error::IngesterError, tasks::TaskData}; -use blockbuster::programs::token_account::TokenProgramAccount; -use digital_asset_types::dao::{asset, token_accounts, tokens}; -use plerkle_serialization::AccountInfo; -use sea_orm::{ - entity::*, query::*, sea_query::OnConflict, ActiveValue::Set, ConnectionTrait, - DatabaseConnection, DbBackend, EntityTrait, -}; -use solana_sdk::program_option::COption; -use spl_token::state::AccountState; -use tokio::sync::mpsc::UnboundedSender; - -pub async fn handle_token_program_account<'a, 'b, 'c>( - account_update: &'a AccountInfo<'a>, - parsing_result: &'b TokenProgramAccount, - db: &'c DatabaseConnection, - _task_manager: &UnboundedSender, -) -> Result<(), IngesterError> { - let key = *account_update.pubkey().unwrap(); - let key_bytes = key.0.to_vec(); - let spl_token_program = account_update.owner().unwrap().0.to_vec(); - match &parsing_result { - TokenProgramAccount::TokenAccount(ta) => { - let mint = ta.mint.to_bytes().to_vec(); - let delegate: Option> = match ta.delegate { - COption::Some(d) => Some(d.to_bytes().to_vec()), - COption::None => None, - }; - let frozen = matches!(ta.state, AccountState::Frozen); - let owner = ta.owner.to_bytes().to_vec(); - let model = token_accounts::ActiveModel { - pubkey: Set(key_bytes), - mint: Set(mint.clone()), - delegate: Set(delegate.clone()), - owner: Set(owner.clone()), - frozen: Set(frozen), - delegated_amount: Set(ta.delegated_amount as i64), - token_program: Set(spl_token_program), - slot_updated: Set(account_update.slot() as i64), - amount: Set(ta.amount as i64), - close_authority: Set(None), - }; - - let mut query = token_accounts::Entity::insert(model) - .on_conflict( - OnConflict::columns([token_accounts::Column::Pubkey]) - .update_columns([ - token_accounts::Column::Mint, - token_accounts::Column::DelegatedAmount, - token_accounts::Column::Delegate, - token_accounts::Column::Amount, - token_accounts::Column::Frozen, - token_accounts::Column::TokenProgram, - token_accounts::Column::Owner, - token_accounts::Column::CloseAuthority, - token_accounts::Column::SlotUpdated, - ]) - .to_owned(), - ) - .build(DbBackend::Postgres); - query.sql = format!( - "{} WHERE excluded.slot_updated > token_accounts.slot_updated", - query.sql - ); - db.execute(query).await?; - let txn = db.begin().await?; - let asset_update: Option = asset::Entity::find_by_id(mint) - .filter(asset::Column::OwnerType.eq("single")) - .one(&txn) - .await?; - if let Some(asset) = asset_update { - // will only update owner if token account balance is non-zero - if ta.amount > 0 { - let mut active: asset::ActiveModel = asset.into(); - active.owner = Set(Some(owner)); - active.delegate = Set(delegate); - active.frozen = Set(frozen); - active.save(&txn).await?; - } - } - txn.commit().await?; - Ok(()) - } - TokenProgramAccount::Mint(m) => { - let freeze_auth: Option> = match m.freeze_authority { - COption::Some(d) => Some(d.to_bytes().to_vec()), - COption::None => None, - }; - let mint_auth: Option> = match m.mint_authority { - COption::Some(d) => Some(d.to_bytes().to_vec()), - COption::None => None, - }; - let model = tokens::ActiveModel { - mint: Set(key_bytes.clone()), - token_program: Set(spl_token_program), - slot_updated: Set(account_update.slot() as i64), - supply: Set(m.supply as i64), - decimals: Set(m.decimals as i32), - close_authority: Set(None), - extension_data: Set(None), - mint_authority: Set(mint_auth), - freeze_authority: Set(freeze_auth), - }; - - let mut query = tokens::Entity::insert(model) - .on_conflict( - OnConflict::columns([tokens::Column::Mint]) - .update_columns([ - tokens::Column::Supply, - tokens::Column::TokenProgram, - tokens::Column::MintAuthority, - tokens::Column::CloseAuthority, - tokens::Column::ExtensionData, - tokens::Column::SlotUpdated, - tokens::Column::Decimals, - tokens::Column::FreezeAuthority, - ]) - .to_owned(), - ) - .build(DbBackend::Postgres); - query.sql = format!( - "{} WHERE excluded.slot_updated > tokens.slot_updated", - query.sql - ); - db.execute(query).await?; - let asset_update: Option = asset::Entity::find_by_id(key_bytes.clone()) - .filter(asset::Column::OwnerType.eq("single")) - .one(db) - .await?; - if let Some(asset) = asset_update { - let mut active: asset::ActiveModel = asset.into(); - active.supply = Set(m.supply as i64); - active.supply_mint = Set(Some(key_bytes)); - active.save(db).await?; - } - Ok(()) - } - _ => Err(IngesterError::NotImplemented), - }?; - Ok(()) -} diff --git a/nft_ingester/src/program_transformers/token_metadata/master_edition.rs b/nft_ingester/src/program_transformers/token_metadata/master_edition.rs deleted file mode 100644 index 4e30970b6..000000000 --- a/nft_ingester/src/program_transformers/token_metadata/master_edition.rs +++ /dev/null @@ -1,94 +0,0 @@ -use crate::error::IngesterError; -use blockbuster::token_metadata::state::{Key, MasterEditionV1, MasterEditionV2}; -use digital_asset_types::dao::{ - asset, asset_v1_account_attachments, - sea_orm_active_enums::{SpecificationAssetClass, V1AccountAttachments}, -}; -use plerkle_serialization::Pubkey as FBPubkey; -use sea_orm::{ - entity::*, query::*, sea_query::OnConflict, ActiveValue::Set, ConnectionTrait, - DatabaseTransaction, DbBackend, EntityTrait, -}; - -pub async fn save_v2_master_edition( - id: FBPubkey, - slot: u64, - me_data: &MasterEditionV2, - txn: &DatabaseTransaction, -) -> Result<(), IngesterError> { - save_master_edition( - V1AccountAttachments::MasterEditionV2, - id, - slot, - me_data, - txn, - ) - .await -} - -pub async fn save_v1_master_edition( - id: FBPubkey, - slot: u64, - me_data: &MasterEditionV1, - txn: &DatabaseTransaction, -) -> Result<(), IngesterError> { - let bridge = MasterEditionV2 { - supply: me_data.supply, - max_supply: me_data.max_supply, - key: Key::MasterEditionV1, // is this weird? - }; - save_master_edition( - V1AccountAttachments::MasterEditionV1, - id, - slot, - &bridge, - txn, - ) - .await -} -pub async fn save_master_edition( - _version: V1AccountAttachments, - id: FBPubkey, - slot: u64, - me_data: &MasterEditionV2, - txn: &DatabaseTransaction, -) -> Result<(), IngesterError> { - let id_bytes = id.0.to_vec(); - let master_edition: Option<(asset_v1_account_attachments::Model, Option)> = - asset_v1_account_attachments::Entity::find_by_id(id.0.to_vec()) - .find_also_related(asset::Entity) - .join(JoinType::InnerJoin, asset::Relation::AssetData.def()) - .one(txn) - .await?; - let ser = serde_json::to_value(me_data) - .map_err(|e| IngesterError::SerializatonError(e.to_string()))?; - - let model = asset_v1_account_attachments::ActiveModel { - id: Set(id_bytes), - attachment_type: Set(V1AccountAttachments::MasterEditionV1), - data: Set(Some(ser)), - slot_updated: Set(slot as i64), - ..Default::default() - }; - - if let Some((_me, Some(asset))) = master_edition { - let mut updatable: asset::ActiveModel = asset.into(); - updatable.supply = Set(1); - updatable.specification_asset_class = Set(Some(SpecificationAssetClass::Nft)); - updatable.update(txn).await?; - } - - let query = asset_v1_account_attachments::Entity::insert(model) - .on_conflict( - OnConflict::columns([asset_v1_account_attachments::Column::Id]) - .update_columns([ - asset_v1_account_attachments::Column::AttachmentType, - asset_v1_account_attachments::Column::Data, - asset_v1_account_attachments::Column::SlotUpdated, - ]) - .to_owned(), - ) - .build(DbBackend::Postgres); - txn.execute(query).await?; - Ok(()) -} diff --git a/nft_ingester/src/program_transformers/token_metadata/mod.rs b/nft_ingester/src/program_transformers/token_metadata/mod.rs deleted file mode 100644 index 10ab9a74c..000000000 --- a/nft_ingester/src/program_transformers/token_metadata/mod.rs +++ /dev/null @@ -1,54 +0,0 @@ -mod master_edition; -mod v1_asset; - -use crate::{ - error::IngesterError, - program_transformers::token_metadata::{ - master_edition::{save_v1_master_edition, save_v2_master_edition}, - v1_asset::{burn_v1_asset, save_v1_asset}, - }, - tasks::TaskData, -}; -use blockbuster::programs::token_metadata::{TokenMetadataAccountData, TokenMetadataAccountState}; -use plerkle_serialization::AccountInfo; -use sea_orm::{DatabaseConnection, TransactionTrait}; -use tokio::sync::mpsc::UnboundedSender; - -pub async fn handle_token_metadata_account<'a, 'b, 'c>( - account_update: &'a AccountInfo<'a>, - parsing_result: &'b TokenMetadataAccountState, - db: &'c DatabaseConnection, - task_manager: &UnboundedSender, -) -> Result<(), IngesterError> { - let key = *account_update.pubkey().unwrap(); - match &parsing_result.data { - TokenMetadataAccountData::EmptyAccount => { - burn_v1_asset(db, key, account_update.slot()).await?; - Ok(()) - } - TokenMetadataAccountData::MasterEditionV1(m) => { - let txn = db.begin().await?; - save_v1_master_edition(key, account_update.slot(), m, &txn).await?; - txn.commit().await?; - Ok(()) - } - TokenMetadataAccountData::MetadataV1(m) => { - let task = save_v1_asset(db, m.mint.as_ref().into(), account_update.slot(), m).await?; - if let Some(task) = task { - task_manager.send(task)?; - } - Ok(()) - } - TokenMetadataAccountData::MasterEditionV2(m) => { - let txn = db.begin().await?; - save_v2_master_edition(key, account_update.slot(), m, &txn).await?; - txn.commit().await?; - Ok(()) - } - // TokenMetadataAccountData::EditionMarker(_) => {} - // TokenMetadataAccountData::UseAuthorityRecord(_) => {} - // TokenMetadataAccountData::CollectionAuthorityRecord(_) => {} - _ => Err(IngesterError::NotImplemented), - }?; - Ok(()) -} diff --git a/nft_ingester/src/program_transformers/token_metadata/v1_asset.rs b/nft_ingester/src/program_transformers/token_metadata/v1_asset.rs deleted file mode 100644 index 4f81a4636..000000000 --- a/nft_ingester/src/program_transformers/token_metadata/v1_asset.rs +++ /dev/null @@ -1,393 +0,0 @@ -use crate::{error::IngesterError, tasks::TaskData}; -use blockbuster::token_metadata::{ - pda::find_master_edition_account, - state::{Metadata, TokenStandard, UseMethod, Uses}, -}; -use chrono::Utc; -use digital_asset_types::{ - dao::{ - asset, asset_authority, asset_creators, asset_data, asset_grouping, - asset_v1_account_attachments, - sea_orm_active_enums::{ - ChainMutability, Mutability, OwnerType, RoyaltyTargetType, SpecificationAssetClass, - SpecificationVersions, V1AccountAttachments, - }, - token_accounts, tokens, - }, - json::ChainDataV1, -}; - -use crate::tasks::{DownloadMetadata, IntoTaskData}; -use log::warn; -use num_traits::FromPrimitive; -use plerkle_serialization::Pubkey as FBPubkey; -use sea_orm::{ - entity::*, query::*, sea_query::OnConflict, ActiveValue::Set, ConnectionTrait, DbBackend, - DbErr, EntityTrait, JsonValue, -}; -use std::collections::HashSet; - -pub async fn burn_v1_asset( - conn: &T, - id: FBPubkey, - slot: u64, -) -> Result<(), IngesterError> { - let (id, slot_i) = (id.0, slot as i64); - let model = asset::ActiveModel { - id: Set(id.to_vec()), - slot_updated: Set(Some(slot_i)), - burnt: Set(true), - ..Default::default() - }; - let mut query = asset::Entity::insert(model) - .on_conflict( - OnConflict::columns([asset::Column::Id]) - .update_columns([asset::Column::SlotUpdated, asset::Column::Burnt]) - .to_owned(), - ) - .build(DbBackend::Postgres); - query.sql = format!( - "{} WHERE excluded.slot_updated > asset.slot_updated", - query.sql - ); - conn.execute(query).await?; - Ok(()) -} - -pub async fn save_v1_asset( - conn: &T, - id: FBPubkey, - slot: u64, - metadata: &Metadata, -) -> Result, IngesterError> { - let metadata = metadata.clone(); - let data = metadata.data; - let meta_mint_pubkey = metadata.mint; - let (edition_attachment_address, _) = find_master_edition_account(&meta_mint_pubkey); - let mint = metadata.mint.to_bytes().to_vec(); - let authority = metadata.update_authority.to_bytes().to_vec(); - let id = id.0; - let slot_i = slot as i64; - let uri = data.uri.trim().replace('\0', ""); - let _spec = SpecificationVersions::V1; - let class = match metadata.token_standard { - Some(TokenStandard::NonFungible) => SpecificationAssetClass::Nft, - Some(TokenStandard::FungibleAsset) => SpecificationAssetClass::FungibleAsset, - Some(TokenStandard::Fungible) => SpecificationAssetClass::FungibleToken, - _ => SpecificationAssetClass::Unknown, - }; - let ownership_type = match class { - SpecificationAssetClass::FungibleAsset => OwnerType::Token, - SpecificationAssetClass::FungibleToken => OwnerType::Token, - _ => OwnerType::Single, - }; - - // gets the token and token account for the mint to populate the asset. This is required when the token and token account are indexed, but not the metadata account. If the metadata account is indexed, then the token and ta ingester will update the asset with the correct data - - let (token, token_account): (Option, Option) = - match ownership_type { - OwnerType::Single => { - let token: Option = - tokens::Entity::find_by_id(mint.clone()).one(conn).await?; - // query for token account associated with mint with positive balance - let token_account: Option = token_accounts::Entity::find() - .filter(token_accounts::Column::Mint.eq(mint.clone())) - .filter(token_accounts::Column::Amount.gt(0)) - .one(conn) - .await?; - Ok((token, token_account)) - } - _ => { - let token = tokens::Entity::find_by_id(mint.clone()).one(conn).await?; - Ok((token, None)) - } - } - .map_err(|e: DbErr| IngesterError::DatabaseError(e.to_string()))?; - - // get supply of token, default to 1 since most cases will be NFTs. Token mint ingester will properly set supply if token_result is None - let (supply, supply_mint) = match token { - Some(t) => (Set(t.supply), Set(Some(t.mint))), - None => (Set(1), NotSet), - }; - - // owner and delegate should be from the token account with the mint - let (owner, delegate) = match token_account { - Some(ta) => (Set(Some(ta.owner)), Set(ta.delegate)), - None => (NotSet, NotSet), - }; - - let name = data.name.clone().into_bytes(); - let symbol = data.symbol.clone().into_bytes(); - - let mut chain_data = ChainDataV1 { - name: data.name.clone(), - symbol: data.symbol.clone(), - edition_nonce: metadata.edition_nonce, - primary_sale_happened: metadata.primary_sale_happened, - token_standard: metadata.token_standard, - uses: metadata.uses.map(|u| Uses { - use_method: UseMethod::from_u8(u.use_method as u8).unwrap(), - remaining: u.remaining, - total: u.total, - }), - }; - chain_data.sanitize(); - let chain_data_json = serde_json::to_value(chain_data) - .map_err(|e| IngesterError::DeserializationError(e.to_string()))?; - let chain_mutability = match metadata.is_mutable { - true => ChainMutability::Mutable, - false => ChainMutability::Immutable, - }; - let asset_data_model = asset_data::ActiveModel { - chain_data_mutability: Set(chain_mutability), - chain_data: Set(chain_data_json), - metadata_url: Set(uri.clone()), - metadata: Set(JsonValue::String("processing".to_string())), - metadata_mutability: Set(Mutability::Mutable), - slot_updated: Set(slot_i), - reindex: Set(Some(true)), - id: Set(id.to_vec()), - raw_name: Set(name.to_vec()), - raw_symbol: Set(symbol.to_vec()), - }; - let txn = conn.begin().await?; - let mut query = asset_data::Entity::insert(asset_data_model) - .on_conflict( - OnConflict::columns([asset_data::Column::Id]) - .update_columns([ - asset_data::Column::ChainDataMutability, - asset_data::Column::ChainData, - asset_data::Column::MetadataUrl, - asset_data::Column::MetadataMutability, - asset_data::Column::SlotUpdated, - asset_data::Column::Reindex, - asset_data::Column::RawName, - asset_data::Column::RawSymbol, - ]) - .to_owned(), - ) - .build(DbBackend::Postgres); - query.sql = format!( - "{} WHERE excluded.slot_updated > asset_data.slot_updated", - query.sql - ); - txn.execute(query) - .await - .map_err(|db_err| IngesterError::AssetIndexError(db_err.to_string()))?; - let model = asset::ActiveModel { - id: Set(id.to_vec()), - owner, - owner_type: Set(ownership_type), - delegate, - frozen: Set(false), - supply, - supply_mint, - specification_version: Set(Some(SpecificationVersions::V1)), - specification_asset_class: Set(Some(class)), - tree_id: Set(None), - nonce: Set(Some(0)), - seq: Set(Some(0)), - leaf: Set(None), - compressed: Set(false), - compressible: Set(false), - royalty_target_type: Set(RoyaltyTargetType::Creators), - royalty_target: Set(None), - royalty_amount: Set(data.seller_fee_basis_points as i32), //basis points - asset_data: Set(Some(id.to_vec())), - slot_updated: Set(Some(slot_i)), - burnt: Set(false), - ..Default::default() - }; - let mut query = asset::Entity::insert(model) - .on_conflict( - OnConflict::columns([asset::Column::Id]) - .update_columns([ - asset::Column::Owner, - asset::Column::OwnerType, - asset::Column::Delegate, - asset::Column::Frozen, - asset::Column::Supply, - asset::Column::SupplyMint, - asset::Column::SpecificationVersion, - asset::Column::SpecificationAssetClass, - asset::Column::TreeId, - asset::Column::Nonce, - asset::Column::Seq, - asset::Column::Leaf, - asset::Column::Compressed, - asset::Column::Compressible, - asset::Column::RoyaltyTargetType, - asset::Column::RoyaltyTarget, - asset::Column::RoyaltyAmount, - asset::Column::AssetData, - asset::Column::SlotUpdated, - asset::Column::Burnt, - ]) - .to_owned(), - ) - .build(DbBackend::Postgres); - query.sql = format!( - "{} WHERE excluded.slot_updated > asset.slot_updated", - query.sql - ); - txn.execute(query) - .await - .map_err(|db_err| IngesterError::AssetIndexError(db_err.to_string()))?; - let attachment = asset_v1_account_attachments::ActiveModel { - id: Set(edition_attachment_address.to_bytes().to_vec()), - slot_updated: Set(slot_i), - attachment_type: Set(V1AccountAttachments::MasterEditionV2), - ..Default::default() - }; - let query = asset_v1_account_attachments::Entity::insert(attachment) - .on_conflict( - OnConflict::columns([asset_v1_account_attachments::Column::Id]) - .do_nothing() - .to_owned(), - ) - .build(DbBackend::Postgres); - txn.execute(query) - .await - .map_err(|db_err| IngesterError::AssetIndexError(db_err.to_string()))?; - let model = asset_authority::ActiveModel { - asset_id: Set(id.to_vec()), - authority: Set(authority), - seq: Set(0), - slot_updated: Set(slot_i), - ..Default::default() - }; - let mut query = asset_authority::Entity::insert(model) - .on_conflict( - OnConflict::columns([asset_authority::Column::AssetId]) - .update_columns([ - asset_authority::Column::Authority, - asset_authority::Column::Seq, - asset_authority::Column::SlotUpdated, - ]) - .to_owned(), - ) - .build(DbBackend::Postgres); - query.sql = format!( - "{} WHERE excluded.slot_updated > asset_authority.slot_updated", - query.sql - ); - txn.execute(query) - .await - .map_err(|db_err| IngesterError::AssetIndexError(db_err.to_string()))?; - if let Some(c) = &metadata.collection { - let model = asset_grouping::ActiveModel { - asset_id: Set(id.to_vec()), - group_key: Set("collection".to_string()), - group_value: Set(Some(c.key.to_string())), - verified: Set(Some(c.verified)), - seq: Set(None), - slot_updated: Set(Some(slot_i)), - ..Default::default() - }; - let mut query = asset_grouping::Entity::insert(model) - .on_conflict( - OnConflict::columns([ - asset_grouping::Column::AssetId, - asset_grouping::Column::GroupKey, - ]) - .update_columns([ - asset_grouping::Column::GroupKey, - asset_grouping::Column::GroupValue, - asset_grouping::Column::Seq, - asset_grouping::Column::SlotUpdated, - ]) - .to_owned(), - ) - .build(DbBackend::Postgres); - query.sql = format!( - "{} WHERE excluded.slot_updated > asset_grouping.slot_updated", - query.sql - ); - txn.execute(query) - .await - .map_err(|db_err| IngesterError::AssetIndexError(db_err.to_string()))?; - } - txn.commit().await?; - let creators = data.creators.unwrap_or_default(); - if !creators.is_empty() { - let mut creators_set = HashSet::new(); - let existing_creators: Vec = asset_creators::Entity::find() - .filter( - Condition::all() - .add(asset_creators::Column::AssetId.eq(id.to_vec())) - .add(asset_creators::Column::SlotUpdated.lt(slot_i)), - ) - .all(conn) - .await?; - if !existing_creators.is_empty() { - let mut db_creators = Vec::with_capacity(creators.len()); - for (i, c) in creators.into_iter().enumerate() { - if creators_set.contains(&c.address) { - continue; - } - db_creators.push(asset_creators::ActiveModel { - asset_id: Set(id.to_vec()), - creator: Set(c.address.to_bytes().to_vec()), - share: Set(c.share as i32), - verified: Set(c.verified), - seq: Set(Some(0)), - slot_updated: Set(Some(slot_i)), - position: Set(i as i16), - ..Default::default() - }); - creators_set.insert(c.address); - } - let txn = conn.begin().await?; - asset_creators::Entity::delete_many() - .filter( - Condition::all() - .add(asset_creators::Column::AssetId.eq(id.to_vec())) - .add(asset_creators::Column::SlotUpdated.lt(slot_i)), - ) - .exec(&txn) - .await?; - if !db_creators.is_empty() { - let mut query = asset_creators::Entity::insert_many(db_creators) - .on_conflict( - OnConflict::columns([ - asset_creators::Column::AssetId, - asset_creators::Column::Position, - ]) - .update_columns([ - asset_creators::Column::Creator, - asset_creators::Column::Share, - asset_creators::Column::Verified, - asset_creators::Column::Seq, - asset_creators::Column::SlotUpdated, - ]) - .to_owned(), - ) - .build(DbBackend::Postgres); - query.sql = format!( - "{} WHERE excluded.slot_updated > asset_creators.slot_updated", - query.sql - ); - txn.execute(query) - .await - .map_err(|db_err| IngesterError::AssetIndexError(db_err.to_string()))?; - } - txn.commit().await?; - } - } - if uri.is_empty() { - warn!( - "URI is empty for mint {}. Skipping background task.", - bs58::encode(mint).into_string() - ); - return Ok(None); - } - - let mut task = DownloadMetadata { - asset_data_id: id.to_vec(), - uri, - created_at: Some(Utc::now().naive_utc()), - }; - task.sanitize(); - let t = task.into_task_data()?; - Ok(Some(t)) -} diff --git a/nft_ingester/src/tasks/common/mod.rs b/nft_ingester/src/tasks/common/mod.rs index bf39e455d..28d067a14 100644 --- a/nft_ingester/src/tasks/common/mod.rs +++ b/nft_ingester/src/tasks/common/mod.rs @@ -1,16 +1,46 @@ -use super::{BgTask, FromTaskData, IngesterError, IntoTaskData, TaskData}; -use async_trait::async_trait; -use chrono::NaiveDateTime; -use digital_asset_types::dao::asset_data; -use log::debug; -use reqwest::{Client, ClientBuilder}; -use sea_orm::*; -use serde::{Deserialize, Serialize}; -use std::{ - fmt::{Display, Formatter}, - time::Duration, +use { + super::{BgTask, FromTaskData, IngesterError, IntoTaskData, TaskData}, + async_trait::async_trait, + chrono::{NaiveDateTime, Utc}, + digital_asset_types::dao::asset_data, + futures::future::BoxFuture, + log::debug, + program_transformers::{DownloadMetadataInfo, DownloadMetadataNotifier}, + reqwest::{Client, ClientBuilder}, + sea_orm::*, + serde::{Deserialize, Serialize}, + std::{ + fmt::{Display, Formatter}, + time::Duration, + }, + tokio::sync::mpsc::UnboundedSender, + url::Url, }; -use url::Url; + +pub fn create_download_metadata_notifier( + bg_task_sender: UnboundedSender, +) -> DownloadMetadataNotifier { + Box::new( + move |info: DownloadMetadataInfo| -> BoxFuture< + 'static, + Result<(), Box>, + > { + let (asset_data_id, uri) = info.into_inner(); + let task = DownloadMetadata { + asset_data_id, + uri, + created_at: Some(Utc::now().naive_utc()), + }; + let task = task + .into_task_data() + .and_then(|task| { + bg_task_sender.send(task).map_err(Into::into) + }) + .map_err(Into::into); + Box::pin(async move { task }) + }, + ) +} const TASK_NAME: &str = "DownloadMetadata"; diff --git a/nft_ingester/src/transaction_notifications.rs b/nft_ingester/src/transaction_notifications.rs index 02aa5d971..e3932eaf6 100644 --- a/nft_ingester/src/transaction_notifications.rs +++ b/nft_ingester/src/transaction_notifications.rs @@ -1,19 +1,22 @@ -use std::sync::Arc; - -use crate::{ - metric, metrics::capture_result, program_transformers::ProgramTransformer, tasks::TaskData, -}; -use cadence_macros::{is_global_default_set, statsd_count, statsd_time}; -use chrono::Utc; -use log::{debug, error}; -use plerkle_messenger::{ConsumptionType, Messenger, MessengerConfig, RecvData}; -use plerkle_serialization::root_as_transaction_info; - -use sqlx::{Pool, Postgres}; -use tokio::{ - sync::mpsc::UnboundedSender, - task::{JoinHandle, JoinSet}, - time::Instant, +use { + crate::{ + metric, + metrics::capture_result, + tasks::{create_download_metadata_notifier, TaskData}, + }, + cadence_macros::{is_global_default_set, statsd_count, statsd_time}, + chrono::Utc, + log::{debug, error}, + plerkle_messenger::{ConsumptionType, Messenger, MessengerConfig, RecvData}, + plerkle_serialization::root_as_transaction_info, + program_transformers::ProgramTransformer, + sqlx::{Pool, Postgres}, + std::sync::Arc, + tokio::{ + sync::mpsc::UnboundedSender, + task::{JoinHandle, JoinSet}, + time::Instant, + }, }; pub fn transaction_worker( @@ -28,7 +31,11 @@ pub fn transaction_worker( tokio::spawn(async move { let source = T::new(config).await; if let Ok(mut msg) = source { - let manager = Arc::new(ProgramTransformer::new(pool, bg_task_sender, cl_audits)); + let manager = Arc::new(ProgramTransformer::new( + pool, + create_download_metadata_notifier(bg_task_sender), + cl_audits, + )); loop { let e = msg.recv(stream_key, consumption_type.clone()).await; let mut tasks = JoinSet::new(); diff --git a/program_transformers/src/lib.rs b/program_transformers/src/lib.rs index 1b58e977b..03f582060 100644 --- a/program_transformers/src/lib.rs +++ b/program_transformers/src/lib.rs @@ -23,7 +23,7 @@ use { }; mod bubblegum; -mod error; +pub mod error; mod token; mod token_metadata; @@ -48,8 +48,10 @@ impl DownloadMetadataInfo { pub type DownloadMetadataNotifier = Box< dyn Fn( - DownloadMetadataInfo, - ) -> BoxFuture<'static, Result<(), Box>>, + DownloadMetadataInfo, + ) -> BoxFuture<'static, Result<(), Box>> + + Sync + + Send, >; pub struct ProgramTransformer { From 5dc8bd5901d11d7e5eb7c873b4cbcebaad9c259c Mon Sep 17 00:00:00 2001 From: Kirill Fomichev Date: Thu, 23 Nov 2023 11:02:05 -0500 Subject: [PATCH 14/23] remove not used deps --- Cargo.lock | 200 +----------------- Cargo.toml | 10 - das_api/Cargo.toml | 12 +- digital_asset_types/Cargo.toml | 24 +-- digital_asset_types/src/json/chain_data.rs | 2 +- digital_asset_types/src/lib.rs | 4 - digital_asset_types/src/rpc/asset.rs | 3 - digital_asset_types/tests/common.rs | 2 +- digital_asset_types/tests/get_asset_by_id.rs | 2 +- .../tests/get_assets_by_authority.rs | 2 +- .../tests/get_assets_by_creator.rs | 2 +- .../tests/get_assets_by_group.rs | 2 +- .../tests/get_assets_by_owner.rs | 2 +- digital_asset_types/tests/json_parsing.rs | 4 +- metaplex-rpc-proxy/Cargo.toml | 2 - migration/Cargo.toml | 3 +- nft_ingester/Cargo.toml | 3 +- nft_ingester/src/backfiller.rs | 2 +- program_transformers/Cargo.toml | 2 +- tools/acc_forwarder/Cargo.toml | 4 +- tools/bgtask_creator/Cargo.toml | 3 +- tools/fetch_trees/Cargo.toml | 1 - tools/load_generation/Cargo.toml | 4 +- tools/tree-status/Cargo.toml | 5 +- 24 files changed, 32 insertions(+), 268 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 373c3b341..c8940e494 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -29,13 +29,11 @@ dependencies = [ "plerkle_messenger", "plerkle_serialization", "prometheus", - "reqwest", "serde_json", "solana-account-decoder", "solana-client", "solana-sdk", "solana-transaction-status", - "spl-token 4.0.0", "tokio", "txn_forwarder", ] @@ -897,7 +895,6 @@ dependencies = [ "nft_ingester", "prometheus", "sea-orm", - "sea-query 0.28.5", "solana-sdk", "sqlx", "tokio", @@ -1706,9 +1703,7 @@ dependencies = [ name = "das_api" version = "0.7.2" dependencies = [ - "anchor-lang", "async-trait", - "blockbuster", "bs58 0.4.0", "cadence", "cadence-macros", @@ -1717,13 +1712,7 @@ dependencies = [ "figment", "hyper", "jsonrpsee", - "jsonrpsee-core", "log", - "metrics", - "mpl-bubblegum", - "mpl-candy-guard", - "mpl-candy-machine-core", - "mpl-token-metadata", "open-rpc-derive", "open-rpc-schema", "schemars", @@ -1735,10 +1724,8 @@ dependencies = [ "sqlx", "thiserror", "tokio", - "tokio-postgres", "tower", "tower-http", - "tracing", ] [[package]] @@ -1796,12 +1783,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "deunicode" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a1abaf4d861455be59f64fd2b55606cb151fce304ede7165f410243ce96bde6" - [[package]] name = "dialoguer" version = "0.10.4" @@ -1838,26 +1819,19 @@ dependencies = [ name = "digital_asset_types" version = "0.7.2" dependencies = [ - "async-trait", - "blockbuster", "bs58 0.4.0", - "futures", "indexmap 1.9.3", "jsonpath_lib", "log", "mime_guess", - "num-derive 0.3.3", - "num-traits", - "reqwest", + "mpl-token-metadata", "schemars", "schemars_derive", "sea-orm", - "sea-query 0.28.5", "serde", "serde_json", "solana-sdk", "spl-concurrent-merkle-tree", - "thiserror", "tokio", "url", ] @@ -2082,22 +2056,6 @@ dependencies = [ "pin-project-lite", ] -[[package]] -name = "fake" -version = "2.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26221445034074d46b276e13eb97a265ebdb8ed8da705c4dddd3dd20b66b45d2" -dependencies = [ - "deunicode", - "rand 0.8.5", -] - -[[package]] -name = "fallible-iterator" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" - [[package]] name = "fastrand" version = "1.9.0" @@ -2124,7 +2082,6 @@ name = "fetch_trees" version = "0.7.12" dependencies = [ "anyhow", - "async-trait", "borsh 0.10.3", "clap 4.4.8", "mpl-bubblegum", @@ -2781,7 +2738,7 @@ dependencies = [ "console", "instant", "number_prefix", - "portable-atomic 1.4.3", + "portable-atomic", "unicode-width", ] @@ -3087,9 +3044,7 @@ checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" name = "load_generation" version = "0.7.12" dependencies = [ - "fake", "mpl-token-metadata", - "rand 0.8.5", "solana-client", "solana-program", "solana-sdk", @@ -3189,30 +3144,6 @@ dependencies = [ "log", "proxy-wasm", "regex", - "wasi 0.7.0", - "wasm-bindgen", -] - -[[package]] -name = "metrics" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b9b8653cec6897f73b519a43fba5ee3d50f62fe9af80b428accdcc093b4a849" -dependencies = [ - "ahash 0.7.6", - "metrics-macros", - "portable-atomic 0.3.20", -] - -[[package]] -name = "metrics-macros" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "731f8ecebd9f3a4aa847dfe75455e4757a45da40a7793d2f0b1f9b6ed18b23f3" -dependencies = [ - "proc-macro2 1.0.69", - "quote 1.0.33", - "syn 1.0.109", ] [[package]] @@ -3222,7 +3153,6 @@ dependencies = [ "async-std", "digital_asset_types", "enum-iterator", - "enum-iterator-derive", "sea-orm-migration", ] @@ -3421,7 +3351,6 @@ name = "nft_ingester" version = "0.7.2" dependencies = [ "async-trait", - "blockbuster", "borsh 0.10.3", "bs58 0.4.0", "cadence", @@ -3937,24 +3866,6 @@ dependencies = [ "num", ] -[[package]] -name = "phf" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" -dependencies = [ - "phf_shared", -] - -[[package]] -name = "phf_shared" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" -dependencies = [ - "siphasher", -] - [[package]] name = "pin-project-lite" version = "0.2.13" @@ -4063,50 +3974,12 @@ dependencies = [ "universal-hash", ] -[[package]] -name = "portable-atomic" -version = "0.3.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e30165d31df606f5726b090ec7592c308a0eaf61721ff64c9a3018e344a8753e" -dependencies = [ - "portable-atomic 1.4.3", -] - [[package]] name = "portable-atomic" version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "31114a898e107c51bb1609ffaf55a0e011cf6a4d7f1170d0015a165082c0338b" -[[package]] -name = "postgres-protocol" -version = "0.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49b6c5ef183cd3ab4ba005f1ca64c21e8bd97ce4699cfea9e8d9a2c4958ca520" -dependencies = [ - "base64 0.21.4", - "byteorder", - "bytes", - "fallible-iterator", - "hmac 0.12.1", - "md-5", - "memchr", - "rand 0.8.5", - "sha2 0.10.8", - "stringprep", -] - -[[package]] -name = "postgres-types" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d2234cdee9408b523530a9b6d2d6b373d1db34f6a8e51dc03ded1828d7fb67c" -dependencies = [ - "bytes", - "fallible-iterator", - "postgres-protocol", -] - [[package]] name = "ppv-lite86" version = "0.2.17" @@ -4995,7 +4868,7 @@ dependencies = [ "ouroboros", "rust_decimal", "sea-orm-macros", - "sea-query 0.27.2", + "sea-query", "sea-query-binder", "sea-strum", "serde", @@ -5061,21 +4934,12 @@ checksum = "a4f0fc4d8e44e1d51c739a68d336252a18bc59553778075d5e32649be6ec92ed" dependencies = [ "chrono", "rust_decimal", - "sea-query-derive 0.2.0", + "sea-query-derive", "serde_json", "time 0.3.29", "uuid", ] -[[package]] -name = "sea-query" -version = "0.28.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbab99b8cd878ab7786157b7eb8df96333a6807cc6e45e8888c85b51534b401a" -dependencies = [ - "sea-query-derive 0.3.0", -] - [[package]] name = "sea-query-binder" version = "0.2.2" @@ -5084,7 +4948,7 @@ checksum = "9c2585b89c985cfacfe0ec9fc9e7bb055b776c1a2581c4e3c6185af2b8bf8865" dependencies = [ "chrono", "rust_decimal", - "sea-query 0.27.2", + "sea-query", "serde_json", "sqlx", "time 0.3.29", @@ -5104,19 +4968,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "sea-query-derive" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63f62030c60f3a691f5fe251713b4e220b306e50a71e1d6f9cce1f24bb781978" -dependencies = [ - "heck 0.4.1", - "proc-macro2 1.0.69", - "quote 1.0.33", - "syn 1.0.109", - "thiserror", -] - [[package]] name = "sea-schema" version = "0.10.3" @@ -5124,7 +4975,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38d5fda574d980e9352b6c7abd6fc75697436fe0078cac2b548559b52643ad3b" dependencies = [ "futures", - "sea-query 0.27.2", + "sea-query", "sea-schema-derive", ] @@ -5484,12 +5335,6 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a" -[[package]] -name = "siphasher" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" - [[package]] name = "sized-chunks" version = "0.6.5" @@ -7024,32 +6869,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "tokio-postgres" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d340244b32d920260ae7448cb72b6e238bddc3d4f7603394e7dd46ed8e48f5b8" -dependencies = [ - "async-trait", - "byteorder", - "bytes", - "fallible-iterator", - "futures-channel", - "futures-util", - "log", - "parking_lot 0.12.1", - "percent-encoding", - "phf", - "pin-project-lite", - "postgres-protocol", - "postgres-types", - "rand 0.8.5", - "socket2 0.5.4", - "tokio", - "tokio-util", - "whoami", -] - [[package]] name = "tokio-rustls" version = "0.23.4" @@ -7294,7 +7113,6 @@ dependencies = [ "clap 4.4.8", "digital_asset_types", "env_logger 0.10.0", - "flatbuffers", "futures", "hex", "lazy_static", @@ -7582,12 +7400,6 @@ dependencies = [ "try-lock", ] -[[package]] -name = "wasi" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d" - [[package]] name = "wasi" version = "0.9.0+wasi-snapshot-preview1" diff --git a/Cargo.toml b/Cargo.toml index 1c967736e..5aff0b7fe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,9 +36,7 @@ chrono = "0.4.19" clap = "4.2.2" digital_asset_types = { path = "digital_asset_types" } enum-iterator = "1.2.0" -enum-iterator-derive = "1.1.0" env_logger = "0.10.0" -fake = "2.5.0" figment = "0.10.8" flatbuffers = "23.1.21" futures = "0.3.28" @@ -47,17 +45,12 @@ hyper = "0.14.23" indexmap = "1.9.3" jsonpath_lib = "0.3.0" jsonrpsee = "0.16.2" -jsonrpsee-core = "0.16.2" lazy_static = "1.4.0" log = "0.4.17" -metrics = "0.20.1" mime_guess = "2.0.4" mpl-bubblegum = "1.0.1-beta.3" -mpl-candy-guard = "2.0.0" -mpl-candy-machine-core = "2.0.1" mpl-token-metadata = "=2.0.0-beta.1" nft_ingester = { path = "nft_ingester" } -num-derive = "0.3.3" num-traits = "0.2.15" open-rpc-derive = "0.0.4" open-rpc-schema = "0.0.4" @@ -92,7 +85,6 @@ sqlx = "0.6.2" stretto = "0.7.2" thiserror = "1.0.31" tokio = "1.30.0" -tokio-postgres = "0.7.7" tokio-stream = "0.1.14" tower = "0.4.13" tower-http = "0.3.5" @@ -100,8 +92,6 @@ tracing = "0.1.35" tracing-subscriber = "0.3.16" txn_forwarder = { path = "tools/txn_forwarder" } url = "2.3.1" -wasi = "0.7.0" -wasm-bindgen = "0.2.83" [workspace.lints.clippy] clone_on_ref_ptr = "deny" diff --git a/das_api/Cargo.toml b/das_api/Cargo.toml index c56afe88f..e414ef103 100644 --- a/das_api/Cargo.toml +++ b/das_api/Cargo.toml @@ -6,24 +6,16 @@ repository = { workspace = true } publish = { workspace = true } [dependencies] -anchor-lang = { workspace = true } async-trait = { workspace = true } -blockbuster = { workspace = true } bs58 = { workspace = true } cadence = { workspace = true } cadence-macros = { workspace = true } -digital_asset_types = { workspace = true, features = ["json_types", "sql_types"] } +digital_asset_types = { workspace = true } env_logger = { workspace = true } figment = { workspace = true, features = ["env"] } hyper = { workspace = true } jsonrpsee = { workspace = true, features = ["server", "macros"]} -jsonrpsee-core = { workspace = true, features =["server"]} log = { workspace = true } -metrics = { workspace = true } -mpl-bubblegum = { workspace = true } -mpl-candy-guard = { workspace = true, features = ["no-entrypoint"] } -mpl-candy-machine-core = { workspace = true, features = ["no-entrypoint"] } -mpl-token-metadata = { workspace = true, features = ["serde-feature"] } open-rpc-derive = { workspace = true } open-rpc-schema = { workspace = true } schemars = { workspace = true } @@ -35,10 +27,8 @@ solana-sdk = { workspace = true } sqlx = { workspace = true, features = ["macros", "runtime-tokio-rustls", "postgres", "uuid", "offline", "json"] } thiserror = { workspace = true } tokio = { workspace = true, features = ["signal"] } -tokio-postgres = { workspace = true } tower = { workspace = true } tower-http = { workspace = true, features = ["cors"] } -tracing = { workspace = true } [lints] workspace = true diff --git a/digital_asset_types/Cargo.toml b/digital_asset_types/Cargo.toml index 72d4b668c..770f628c2 100644 --- a/digital_asset_types/Cargo.toml +++ b/digital_asset_types/Cargo.toml @@ -6,33 +6,23 @@ repository = { workspace = true } publish = { workspace = true } [dependencies] -async-trait = { workspace = true } -blockbuster = { workspace = true } bs58 = { workspace = true } -futures = { workspace = true } indexmap = { workspace = true } jsonpath_lib = { workspace = true } log = { workspace = true } mime_guess = { workspace = true } -num-derive = { workspace = true } -num-traits = { workspace = true } -reqwest = { workspace = true } +mpl-token-metadata = { workspace = true, features = ["no-entrypoint", "serde-feature"] } schemars = { workspace = true } schemars_derive = { workspace = true } -sea-orm = { optional = true, features = ["macros", "runtime-tokio-rustls", "sqlx-postgres", "with-chrono", "mock"], workspace = true } -sea-query = { workspace = true, features = ["postgres-array"] } -serde = { workspace = true, optional = true } -serde_json = { workspace = true, features = ["preserve_order"], optional = true } -solana-sdk = { workspace = true } +sea-orm = { workspace = true, features = ["macros", "runtime-tokio-rustls", "sqlx-postgres", "with-chrono", "mock"] } +serde = { workspace = true } +serde_json = { workspace = true, features = ["preserve_order"] } spl-concurrent-merkle-tree = { workspace = true } -thiserror = { workspace = true } -tokio = { workspace = true } url = { workspace = true } -[features] -default = ["json_types", "sql_types"] -json_types = ["serde", "serde_json"] -sql_types = ["sea-orm"] +[dev-dependencies] +solana-sdk = { workspace = true } +tokio = { workspace = true, features = ["rt-multi-thread", "macros", "fs"] } [lints] workspace = true diff --git a/digital_asset_types/src/json/chain_data.rs b/digital_asset_types/src/json/chain_data.rs index aebbb7383..78da24d39 100644 --- a/digital_asset_types/src/json/chain_data.rs +++ b/digital_asset_types/src/json/chain_data.rs @@ -1,4 +1,4 @@ -use blockbuster::token_metadata::state::{TokenStandard, Uses}; +use mpl_token_metadata::state::{TokenStandard, Uses}; use serde::{Deserialize, Serialize}; pub enum ChainData { diff --git a/digital_asset_types/src/lib.rs b/digital_asset_types/src/lib.rs index cf5ec1679..bf016562a 100644 --- a/digital_asset_types/src/lib.rs +++ b/digital_asset_types/src/lib.rs @@ -1,8 +1,4 @@ -#[cfg(feature = "sql_types")] pub mod dao; -#[cfg(feature = "sql_types")] pub mod dapi; -#[cfg(feature = "json_types")] pub mod json; -#[cfg(feature = "json_types")] pub mod rpc; diff --git a/digital_asset_types/src/rpc/asset.rs b/digital_asset_types/src/rpc/asset.rs index 4ec4d4be3..4be554393 100644 --- a/digital_asset_types/src/rpc/asset.rs +++ b/digital_asset_types/src/rpc/asset.rs @@ -1,7 +1,6 @@ use crate::dao::sea_orm_active_enums::{ OwnerType, RoyaltyTargetType, SpecificationAssetClass, SpecificationVersions, }; -#[cfg(feature = "sql_types")] use std::collections::BTreeMap; use crate::dao::sea_orm_active_enums::ChainMutability; @@ -225,7 +224,6 @@ impl From for RoyaltyModel { } } -#[cfg(feature = "sql_types")] impl From for RoyaltyModel { fn from(s: RoyaltyTargetType) -> Self { match s { @@ -276,7 +274,6 @@ impl From for OwnershipModel { } } -#[cfg(feature = "sql_types")] impl From for OwnershipModel { fn from(s: OwnerType) -> Self { match s { diff --git a/digital_asset_types/tests/common.rs b/digital_asset_types/tests/common.rs index 17ef752dc..114a5dd69 100644 --- a/digital_asset_types/tests/common.rs +++ b/digital_asset_types/tests/common.rs @@ -1,4 +1,3 @@ -use blockbuster::token_metadata::state::*; use digital_asset_types::dao::sea_orm_active_enums::{ SpecificationAssetClass, SpecificationVersions, }; @@ -9,6 +8,7 @@ use digital_asset_types::{ }, json::ChainDataV1, }; +use mpl_token_metadata::state::*; use sea_orm::{JsonValue, Set}; use solana_sdk::{pubkey::Pubkey, signature::Keypair, signer::Signer}; diff --git a/digital_asset_types/tests/get_asset_by_id.rs b/digital_asset_types/tests/get_asset_by_id.rs index f20b443d9..f6c2a3117 100644 --- a/digital_asset_types/tests/get_asset_by_id.rs +++ b/digital_asset_types/tests/get_asset_by_id.rs @@ -1,13 +1,13 @@ #[cfg(test)] mod common; -use blockbuster::token_metadata::state::*; use common::*; use digital_asset_types::dao::sea_orm_active_enums::*; use digital_asset_types::dao::{ asset, asset_authority, asset_creators, asset_data, sea_orm_active_enums::{OwnerType, RoyaltyTargetType}, }; +use mpl_token_metadata::state::*; use sea_orm::{entity::prelude::*, DatabaseBackend, MockDatabase}; use solana_sdk::{signature::Keypair, signer::Signer}; diff --git a/digital_asset_types/tests/get_assets_by_authority.rs b/digital_asset_types/tests/get_assets_by_authority.rs index 5796c6c55..ab4da53e2 100644 --- a/digital_asset_types/tests/get_assets_by_authority.rs +++ b/digital_asset_types/tests/get_assets_by_authority.rs @@ -4,13 +4,13 @@ mod common; use sea_orm::{entity::prelude::*, DatabaseBackend, MockDatabase}; use solana_sdk::{signature::Keypair, signer::Signer}; -use blockbuster::token_metadata::state::*; use common::*; use digital_asset_types::dao::sea_orm_active_enums::*; use digital_asset_types::dao::{ asset, asset_authority, asset_creators, asset_data, sea_orm_active_enums::{OwnerType, RoyaltyTargetType}, }; +use mpl_token_metadata::state::*; #[tokio::test] async fn get_assets_by_owner() -> Result<(), DbErr> { diff --git a/digital_asset_types/tests/get_assets_by_creator.rs b/digital_asset_types/tests/get_assets_by_creator.rs index 6bcf85c9c..5c3684181 100644 --- a/digital_asset_types/tests/get_assets_by_creator.rs +++ b/digital_asset_types/tests/get_assets_by_creator.rs @@ -6,13 +6,13 @@ use sea_orm::{ }; use solana_sdk::{signature::Keypair, signer::Signer}; -use blockbuster::token_metadata::state::*; use common::*; use digital_asset_types::dao::sea_orm_active_enums::*; use digital_asset_types::dao::{ asset, asset_authority, asset_creators, asset_data, sea_orm_active_enums::{OwnerType, RoyaltyTargetType}, }; +use mpl_token_metadata::state::*; #[tokio::test] async fn get_assets_by_creator() -> Result<(), DbErr> { diff --git a/digital_asset_types/tests/get_assets_by_group.rs b/digital_asset_types/tests/get_assets_by_group.rs index b8bdb35ad..26f0b3ab7 100644 --- a/digital_asset_types/tests/get_assets_by_group.rs +++ b/digital_asset_types/tests/get_assets_by_group.rs @@ -6,13 +6,13 @@ use sea_orm::{ }; use solana_sdk::{signature::Keypair, signer::Signer}; -use blockbuster::token_metadata::state::*; use common::*; use digital_asset_types::dao::sea_orm_active_enums::*; use digital_asset_types::dao::{ asset, asset_authority, asset_creators, asset_data, asset_grouping, sea_orm_active_enums::{OwnerType, RoyaltyTargetType}, }; +use mpl_token_metadata::state::*; #[tokio::test] async fn get_assets_by_group() -> Result<(), DbErr> { diff --git a/digital_asset_types/tests/get_assets_by_owner.rs b/digital_asset_types/tests/get_assets_by_owner.rs index 5796c6c55..ab4da53e2 100644 --- a/digital_asset_types/tests/get_assets_by_owner.rs +++ b/digital_asset_types/tests/get_assets_by_owner.rs @@ -4,13 +4,13 @@ mod common; use sea_orm::{entity::prelude::*, DatabaseBackend, MockDatabase}; use solana_sdk::{signature::Keypair, signer::Signer}; -use blockbuster::token_metadata::state::*; use common::*; use digital_asset_types::dao::sea_orm_active_enums::*; use digital_asset_types::dao::{ asset, asset_authority, asset_creators, asset_data, sea_orm_active_enums::{OwnerType, RoyaltyTargetType}, }; +use mpl_token_metadata::state::*; #[tokio::test] async fn get_assets_by_owner() -> Result<(), DbErr> { diff --git a/digital_asset_types/tests/json_parsing.rs b/digital_asset_types/tests/json_parsing.rs index 85681cf6a..800ebc6db 100644 --- a/digital_asset_types/tests/json_parsing.rs +++ b/digital_asset_types/tests/json_parsing.rs @@ -1,11 +1,11 @@ -#[cfg(test)] -use blockbuster::token_metadata::state::TokenStandard as TSBlockbuster; use digital_asset_types::dao::asset_data; use digital_asset_types::dao::sea_orm_active_enums::{ChainMutability, Mutability}; use digital_asset_types::dapi::common::v1_content_from_json; use digital_asset_types::json::ChainDataV1; use digital_asset_types::rpc::Content; use digital_asset_types::rpc::File; +#[cfg(test)] +use mpl_token_metadata::state::TokenStandard as TSBlockbuster; use solana_sdk::signature::Keypair; use solana_sdk::signer::Signer; diff --git a/metaplex-rpc-proxy/Cargo.toml b/metaplex-rpc-proxy/Cargo.toml index 2e69785dd..06b801543 100644 --- a/metaplex-rpc-proxy/Cargo.toml +++ b/metaplex-rpc-proxy/Cargo.toml @@ -13,8 +13,6 @@ lazy_static = { workspace = true } log = { workspace = true } proxy-wasm = { workspace = true } regex = { workspace = true } -wasi = { workspace = true } -wasm-bindgen = { workspace = true } [lints] workspace = true diff --git a/migration/Cargo.toml b/migration/Cargo.toml index 219a7683d..2856d768f 100644 --- a/migration/Cargo.toml +++ b/migration/Cargo.toml @@ -7,9 +7,8 @@ publish = { workspace = true } [dependencies] async-std = { workspace = true, features = ["attributes", "tokio1"] } -digital_asset_types = { workspace = true, features = ["json_types", "sql_types"] } +digital_asset_types = { workspace = true } enum-iterator = { workspace = true } -enum-iterator-derive = { workspace = true } sea-orm-migration = { workspace = true, features = ["runtime-tokio-rustls", "sqlx-postgres"] } [lints] diff --git a/nft_ingester/Cargo.toml b/nft_ingester/Cargo.toml index f31a589dd..e310cc647 100644 --- a/nft_ingester/Cargo.toml +++ b/nft_ingester/Cargo.toml @@ -7,14 +7,13 @@ publish = { workspace = true } [dependencies] async-trait = { workspace = true } -blockbuster = { workspace = true } borsh = { workspace = true } bs58 = { workspace = true } cadence = { workspace = true } cadence-macros = { workspace = true } chrono = { workspace = true } clap = { workspace = true, features = ["derive", "cargo"] } -digital_asset_types = { workspace = true, features = ["json_types", "sql_types"] } +digital_asset_types = { workspace = true } figment = { workspace = true, features = ["env", "toml", "yaml"] } flatbuffers = { workspace = true } futures = { workspace = true } diff --git a/nft_ingester/src/backfiller.rs b/nft_ingester/src/backfiller.rs index f9b014493..2045ca582 100644 --- a/nft_ingester/src/backfiller.rs +++ b/nft_ingester/src/backfiller.rs @@ -958,7 +958,7 @@ impl<'a, T: Messenger> Backfiller<'a, T> { // Filter out transactions that don't have to do with the tree we are interested in or // the Bubblegum program. let tb = tree.to_bytes(); - let bubblegum = blockbuster::programs::bubblegum::ID.to_bytes(); + let bubblegum = mpl_bubblegum::ID.to_bytes(); if account_keys.iter().all(|pk| *pk != tb && *pk != bubblegum) { continue; } diff --git a/program_transformers/Cargo.toml b/program_transformers/Cargo.toml index b1c2e7439..330e85b43 100644 --- a/program_transformers/Cargo.toml +++ b/program_transformers/Cargo.toml @@ -8,7 +8,7 @@ publish = { workspace = true } [dependencies] blockbuster = { workspace = true } bs58 = { workspace = true } -digital_asset_types = { workspace = true, features = ["json_types", "sql_types"] } +digital_asset_types = { workspace = true } futures = { workspace = true } mpl-bubblegum = { workspace = true } num-traits = { workspace = true } diff --git a/tools/acc_forwarder/Cargo.toml b/tools/acc_forwarder/Cargo.toml index edd45ca81..ea8da1726 100644 --- a/tools/acc_forwarder/Cargo.toml +++ b/tools/acc_forwarder/Cargo.toml @@ -15,17 +15,15 @@ flatbuffers = { workspace = true } futures = { workspace = true } lazy_static = { workspace = true } log = { workspace = true } -mpl-token-metadata = { workspace = true } +mpl-token-metadata = { workspace = true, features = ["no-entrypoint"]} plerkle_messenger = { workspace = true, features = ['redis'] } plerkle_serialization = { workspace = true } prometheus = { workspace = true } -reqwest = { workspace = true, features = ["json"] } serde_json = { workspace = true } solana-account-decoder = { workspace = true } solana-client = { workspace = true } solana-sdk = { workspace = true } solana-transaction-status = { workspace = true } -spl-token = { workspace = true, features = ["no-entrypoint"] } tokio = { workspace = true, features = ["macros", "rt-multi-thread", "time"] } txn_forwarder = { workspace = true } diff --git a/tools/bgtask_creator/Cargo.toml b/tools/bgtask_creator/Cargo.toml index 7011185e5..f8c2af406 100644 --- a/tools/bgtask_creator/Cargo.toml +++ b/tools/bgtask_creator/Cargo.toml @@ -8,14 +8,13 @@ publish = { workspace = true } [dependencies] anyhow = { workspace = true } clap = { workspace = true, features = ["derive", "cargo"] } -digital_asset_types = { workspace = true, features = ["json_types", "sql_types"] } +digital_asset_types = { workspace = true } futures = { workspace = true } lazy_static = { workspace = true } log = { workspace = true } nft_ingester = { workspace = true } prometheus = { workspace = true } sea-orm = { workspace = true, features = ["macros", "runtime-tokio-rustls", "sqlx-postgres", "with-chrono", "mock"] } -sea-query = { workspace = true, features = ["postgres-array"] } solana-sdk = { workspace = true } sqlx = { workspace = true, features = ["macros", "runtime-tokio-rustls", "postgres", "uuid", "offline", "json"] } tokio = { workspace = true, features = ["macros", "rt-multi-thread"] } diff --git a/tools/fetch_trees/Cargo.toml b/tools/fetch_trees/Cargo.toml index eb4f33460..919679b01 100644 --- a/tools/fetch_trees/Cargo.toml +++ b/tools/fetch_trees/Cargo.toml @@ -7,7 +7,6 @@ publish = { workspace = true } [dependencies] anyhow = { workspace = true } -async-trait = { workspace = true } borsh = { workspace = true } clap = { workspace = true, features = ["derive", "cargo"] } mpl-bubblegum = { workspace = true } diff --git a/tools/load_generation/Cargo.toml b/tools/load_generation/Cargo.toml index bd7b0de3b..2f9e09cc7 100644 --- a/tools/load_generation/Cargo.toml +++ b/tools/load_generation/Cargo.toml @@ -6,9 +6,7 @@ repository = { workspace = true } publish = { workspace = true } [dependencies] -fake = { workspace = true } -mpl-token-metadata = { workspace = true } -rand = { workspace = true } +mpl-token-metadata = { workspace = true, features = ["no-entrypoint"]} solana-client = { workspace = true } solana-program = { workspace = true } solana-sdk = { workspace = true } diff --git a/tools/tree-status/Cargo.toml b/tools/tree-status/Cargo.toml index da8ccc058..64cd02e30 100644 --- a/tools/tree-status/Cargo.toml +++ b/tools/tree-status/Cargo.toml @@ -12,11 +12,10 @@ anchor-client = { workspace = true } anyhow = { workspace = true } bs58 = { workspace = true } clap = { workspace = true, features = ["derive"] } -digital_asset_types = { workspace = true, features = ["json_types", "sql_types"] } +digital_asset_types = { workspace = true } env_logger = { workspace = true } -flatbuffers = { workspace = true } futures = { workspace = true } -hex = { workspace = true } +hex = { worksspace = true } lazy_static = { workspace = true } log = { workspace = true } prometheus = { workspace = true } From b9aafc19af014d14680214a2fcb608fd88ad94c6 Mon Sep 17 00:00:00 2001 From: Kirill Fomichev Date: Thu, 23 Nov 2023 17:33:54 -0500 Subject: [PATCH 15/23] remove AccountInfo --- Cargo.lock | 2 -- Cargo.toml | 3 ++ nft_ingester/src/account_updates.rs | 19 ++++++++-- nft_ingester/src/lib.rs | 1 + nft_ingester/src/main.rs | 1 + nft_ingester/src/plerkle.rs | 26 ++++++++++++++ program_transformers/src/lib.rs | 35 +++++++++++-------- program_transformers/src/token/mod.rs | 23 ++++++------ .../src/token_metadata/master_edition.rs | 14 ++++---- .../src/token_metadata/mod.rs | 25 ++++++------- .../src/token_metadata/v1_asset.rs | 12 +++---- 11 files changed, 102 insertions(+), 59 deletions(-) create mode 100644 nft_ingester/src/plerkle.rs diff --git a/Cargo.lock b/Cargo.lock index c8940e494..5cf0c6eee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -985,8 +985,6 @@ checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" [[package]] name = "blockbuster" version = "0.9.0-beta.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e0240c1218958c0d51284d783fa055f551d769bb8b7a4abf635b17fa9620dc" dependencies = [ "anchor-lang", "async-trait", diff --git a/Cargo.toml b/Cargo.toml index 5aff0b7fe..1f93607d7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -93,6 +93,9 @@ tracing-subscriber = "0.3.16" txn_forwarder = { path = "tools/txn_forwarder" } url = "2.3.1" +[patch.crates-io] +blockbuster = { path = "/home/kirill/projects/blockbuster/blockbuster" } + [workspace.lints.clippy] clone_on_ref_ptr = "deny" missing_const_for_fn = "deny" diff --git a/nft_ingester/src/account_updates.rs b/nft_ingester/src/account_updates.rs index 354aaf9c6..02cf4bdb6 100644 --- a/nft_ingester/src/account_updates.rs +++ b/nft_ingester/src/account_updates.rs @@ -2,6 +2,7 @@ use { crate::{ metric, metrics::capture_result, + plerkle::{parse_pubkey, parse_vector}, tasks::{create_download_metadata_notifier, TaskData}, }, cadence_macros::{is_global_default_set, statsd_count, statsd_time}, @@ -9,7 +10,7 @@ use { log::{debug, error}, plerkle_messenger::{ConsumptionType, Messenger, MessengerConfig, RecvData}, plerkle_serialization::root_as_account_info, - program_transformers::ProgramTransformer, + program_transformers::{error::ProgramTransformerResult, AccountInfo, ProgramTransformer}, sqlx::{Pool, Postgres}, std::sync::Arc, tokio::{ @@ -103,7 +104,7 @@ async fn handle_account( account = Some(bs58::encode(pubkey.0.as_slice()).into_string()); } let begin_processing = Instant::now(); - let res = manager.handle_account_update(account_update).await; + let res = handle_account_update(manager, account_update).await; let should_ack = capture_result( id.clone(), stream_key, @@ -120,3 +121,17 @@ async fn handle_account( } ret_id } + +async fn handle_account_update<'a>( + manager: Arc, + account_update: plerkle_serialization::AccountInfo<'_>, +) -> ProgramTransformerResult<()> { + manager + .handle_account_update(&AccountInfo { + slot: account_update.slot(), + pubkey: &parse_pubkey(account_update.pubkey())?, + owner: &parse_pubkey(account_update.owner())?, + data: parse_vector(account_update.data())?, + }) + .await +} diff --git a/nft_ingester/src/lib.rs b/nft_ingester/src/lib.rs index 9aee9c6ba..84f5852f5 100644 --- a/nft_ingester/src/lib.rs +++ b/nft_ingester/src/lib.rs @@ -5,6 +5,7 @@ pub mod config; pub mod database; pub mod error; pub mod metrics; +pub mod plerkle; pub mod stream; pub mod tasks; pub mod transaction_notifications; diff --git a/nft_ingester/src/main.rs b/nft_ingester/src/main.rs index 1c13320b5..b533458c5 100644 --- a/nft_ingester/src/main.rs +++ b/nft_ingester/src/main.rs @@ -5,6 +5,7 @@ pub mod config; mod database; pub mod error; pub mod metrics; +mod plerkle; mod stream; pub mod tasks; mod transaction_notifications; diff --git a/nft_ingester/src/plerkle.rs b/nft_ingester/src/plerkle.rs new file mode 100644 index 000000000..530a8bc98 --- /dev/null +++ b/nft_ingester/src/plerkle.rs @@ -0,0 +1,26 @@ +use { + flatbuffers::Vector, + plerkle_serialization::Pubkey as FBPubkey, + program_transformers::error::{ProgramTransformerError, ProgramTransformerResult}, + solana_sdk::pubkey::Pubkey, +}; + +pub fn parse_pubkey(pubkey: Option<&FBPubkey>) -> ProgramTransformerResult { + Ok(Pubkey::try_from( + pubkey + .ok_or_else(|| { + ProgramTransformerError::DeserializationError( + "Could not deserialize data".to_owned(), + ) + })? + .0 + .as_slice(), + ) + .expect("valid key from FlatBuffer")) +} + +pub fn parse_vector(data: Option>) -> ProgramTransformerResult<&[u8]> { + data.map(|data| data.bytes()).ok_or_else(|| { + ProgramTransformerError::DeserializationError("Could not deserialize data".to_owned()) + }) +} diff --git a/program_transformers/src/lib.rs b/program_transformers/src/lib.rs index 03f582060..bf4ac0623 100644 --- a/program_transformers/src/lib.rs +++ b/program_transformers/src/lib.rs @@ -14,7 +14,7 @@ use { }, }, futures::future::BoxFuture, - plerkle_serialization::{AccountInfo, Pubkey as FBPubkey, TransactionInfo}, + plerkle_serialization::{Pubkey as FBPubkey, TransactionInfo}, sea_orm::{DatabaseConnection, SqlxPostgresConnector}, solana_sdk::pubkey::Pubkey, sqlx::PgPool, @@ -27,6 +27,14 @@ pub mod error; mod token; mod token_metadata; +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct AccountInfo<'a> { + pub slot: u64, + pub pubkey: &'a Pubkey, + pub owner: &'a Pubkey, + pub data: &'a [u8], +} + #[derive(Debug, Clone, PartialEq, Eq)] pub struct DownloadMetadataInfo { asset_data_id: Vec, @@ -97,9 +105,8 @@ impl ProgramTransformer { } #[allow(clippy::borrowed_box)] - pub fn match_program(&self, key: &FBPubkey) -> Option<&Box> { - self.parsers - .get(&Pubkey::try_from(key.0.as_slice()).expect("valid key from FlatBuffer")) + pub fn match_program(&self, key: &Pubkey) -> Option<&Box> { + self.parsers.get(key) } pub async fn handle_transaction<'a>( @@ -151,7 +158,9 @@ impl ProgramTransformer { slot, }; - if let Some(program) = self.match_program(&ix.program) { + let program_key = + Pubkey::try_from(ix.program.0.as_slice()).expect("valid key from FlatBuffer"); + if let Some(program) = self.match_program(&program_key) { debug!("Found a ix for program: {:?}", program.key()); let result = program.handle_instruction(&ix)?; let concrete = result.result_type(); @@ -187,18 +196,16 @@ impl ProgramTransformer { Ok(()) } - pub async fn handle_account_update<'b>( + pub async fn handle_account_update( &self, - acct: AccountInfo<'b>, + account_info: &AccountInfo<'_>, ) -> ProgramTransformerResult<()> { - let owner = acct.owner().unwrap(); - if let Some(program) = self.match_program(owner) { - let result = program.handle_account(&acct)?; - let concrete = result.result_type(); - match concrete { + if let Some(program) = self.match_program(account_info.owner) { + let result = program.handle_account(account_info.data)?; + match result.result_type() { ProgramParseResult::TokenMetadata(parsing_result) => { handle_token_metadata_account( - &acct, + account_info, parsing_result, &self.storage, &self.download_metadata_notifier, @@ -207,7 +214,7 @@ impl ProgramTransformer { } ProgramParseResult::TokenProgramAccount(parsing_result) => { handle_token_program_account( - &acct, + account_info, parsing_result, &self.storage, &self.download_metadata_notifier, diff --git a/program_transformers/src/token/mod.rs b/program_transformers/src/token/mod.rs index 690c44cae..5098d743a 100644 --- a/program_transformers/src/token/mod.rs +++ b/program_transformers/src/token/mod.rs @@ -1,11 +1,10 @@ use { crate::{ error::{ProgramTransformerError, ProgramTransformerResult}, - DownloadMetadataNotifier, + AccountInfo, DownloadMetadataNotifier, }, blockbuster::programs::token_account::TokenProgramAccount, digital_asset_types::dao::{asset, token_accounts, tokens}, - plerkle_serialization::AccountInfo, sea_orm::{ entity::{ActiveModelTrait, ActiveValue, ColumnTrait}, query::{QueryFilter, QueryTrait}, @@ -16,15 +15,14 @@ use { spl_token::state::AccountState, }; -pub async fn handle_token_program_account<'a, 'b, 'c>( - account_update: &'a AccountInfo<'a>, - parsing_result: &'b TokenProgramAccount, - db: &'c DatabaseConnection, +pub async fn handle_token_program_account( + account_info: &AccountInfo<'_>, + parsing_result: &TokenProgramAccount, + db: &DatabaseConnection, _download_metadata_notifier: &DownloadMetadataNotifier, ) -> ProgramTransformerResult<()> { - let key = *account_update.pubkey().unwrap(); - let key_bytes = key.0.to_vec(); - let spl_token_program = account_update.owner().unwrap().0.to_vec(); + let key_bytes = account_info.pubkey.to_bytes().to_vec(); + let spl_token_program = account_info.owner.to_bytes().to_vec(); match &parsing_result { TokenProgramAccount::TokenAccount(ta) => { let mint = ta.mint.to_bytes().to_vec(); @@ -42,7 +40,7 @@ pub async fn handle_token_program_account<'a, 'b, 'c>( frozen: ActiveValue::Set(frozen), delegated_amount: ActiveValue::Set(ta.delegated_amount as i64), token_program: ActiveValue::Set(spl_token_program), - slot_updated: ActiveValue::Set(account_update.slot() as i64), + slot_updated: ActiveValue::Set(account_info.slot as i64), amount: ActiveValue::Set(ta.amount as i64), close_authority: ActiveValue::Set(None), }; @@ -99,7 +97,7 @@ pub async fn handle_token_program_account<'a, 'b, 'c>( let model = tokens::ActiveModel { mint: ActiveValue::Set(key_bytes.clone()), token_program: ActiveValue::Set(spl_token_program), - slot_updated: ActiveValue::Set(account_update.slot() as i64), + slot_updated: ActiveValue::Set(account_info.slot as i64), supply: ActiveValue::Set(m.supply as i64), decimals: ActiveValue::Set(m.decimals as i32), close_authority: ActiveValue::Set(None), @@ -142,6 +140,5 @@ pub async fn handle_token_program_account<'a, 'b, 'c>( Ok(()) } _ => Err(ProgramTransformerError::NotImplemented), - }?; - Ok(()) + } } diff --git a/program_transformers/src/token_metadata/master_edition.rs b/program_transformers/src/token_metadata/master_edition.rs index 2cba19853..af41f1eee 100644 --- a/program_transformers/src/token_metadata/master_edition.rs +++ b/program_transformers/src/token_metadata/master_edition.rs @@ -5,17 +5,17 @@ use { asset, asset_v1_account_attachments, sea_orm_active_enums::{SpecificationAssetClass, V1AccountAttachments}, }, - plerkle_serialization::Pubkey as FBPubkey, sea_orm::{ entity::{ActiveModelTrait, ActiveValue, EntityTrait, RelationTrait}, query::{JoinType, QuerySelect, QueryTrait}, sea_query::query::OnConflict, ConnectionTrait, DatabaseTransaction, DbBackend, }, + solana_sdk::pubkey::Pubkey, }; pub async fn save_v2_master_edition( - id: FBPubkey, + id: &Pubkey, slot: u64, me_data: &MasterEditionV2, txn: &DatabaseTransaction, @@ -31,7 +31,7 @@ pub async fn save_v2_master_edition( } pub async fn save_v1_master_edition( - id: FBPubkey, + id: &Pubkey, slot: u64, me_data: &MasterEditionV1, txn: &DatabaseTransaction, @@ -52,14 +52,14 @@ pub async fn save_v1_master_edition( } pub async fn save_master_edition( _version: V1AccountAttachments, - id: FBPubkey, + id: &Pubkey, slot: u64, me_data: &MasterEditionV2, txn: &DatabaseTransaction, ) -> ProgramTransformerResult<()> { - let id_bytes = id.0.to_vec(); + let id = id.to_bytes().to_vec(); let master_edition: Option<(asset_v1_account_attachments::Model, Option)> = - asset_v1_account_attachments::Entity::find_by_id(id.0.to_vec()) + asset_v1_account_attachments::Entity::find_by_id(id.clone()) .find_also_related(asset::Entity) .join(JoinType::InnerJoin, asset::Relation::AssetData.def()) .one(txn) @@ -68,7 +68,7 @@ pub async fn save_master_edition( .map_err(|e| ProgramTransformerError::SerializatonError(e.to_string()))?; let model = asset_v1_account_attachments::ActiveModel { - id: ActiveValue::Set(id_bytes), + id: ActiveValue::Set(id), attachment_type: ActiveValue::Set(V1AccountAttachments::MasterEditionV1), data: ActiveValue::Set(Some(ser)), slot_updated: ActiveValue::Set(slot as i64), diff --git a/program_transformers/src/token_metadata/mod.rs b/program_transformers/src/token_metadata/mod.rs index 708b7f867..4be03f1b2 100644 --- a/program_transformers/src/token_metadata/mod.rs +++ b/program_transformers/src/token_metadata/mod.rs @@ -5,38 +5,34 @@ use { master_edition::{save_v1_master_edition, save_v2_master_edition}, v1_asset::{burn_v1_asset, save_v1_asset}, }, - DownloadMetadataNotifier, + AccountInfo, DownloadMetadataNotifier, }, blockbuster::programs::token_metadata::{TokenMetadataAccountData, TokenMetadataAccountState}, - plerkle_serialization::AccountInfo, sea_orm::{DatabaseConnection, TransactionTrait}, }; mod master_edition; mod v1_asset; -pub async fn handle_token_metadata_account<'a, 'b, 'c>( - account_update: &'a AccountInfo<'a>, - parsing_result: &'b TokenMetadataAccountState, - db: &'c DatabaseConnection, +pub async fn handle_token_metadata_account( + account_info: &AccountInfo<'_>, + parsing_result: &TokenMetadataAccountState, + db: &DatabaseConnection, download_metadata_notifier: &DownloadMetadataNotifier, ) -> ProgramTransformerResult<()> { - let key = *account_update.pubkey().unwrap(); match &parsing_result.data { TokenMetadataAccountData::EmptyAccount => { - burn_v1_asset(db, key, account_update.slot()).await?; + burn_v1_asset(db, account_info.pubkey, account_info.slot).await?; Ok(()) } TokenMetadataAccountData::MasterEditionV1(m) => { let txn = db.begin().await?; - save_v1_master_edition(key, account_update.slot(), m, &txn).await?; + save_v1_master_edition(account_info.pubkey, account_info.slot, m, &txn).await?; txn.commit().await?; Ok(()) } TokenMetadataAccountData::MetadataV1(m) => { - if let Some(info) = - save_v1_asset(db, m.mint.as_ref().into(), account_update.slot(), m).await? - { + if let Some(info) = save_v1_asset(db, &m.mint, account_info.slot, m).await? { download_metadata_notifier(info) .await .map_err(ProgramTransformerError::DownloadMetadataNotify)?; @@ -45,7 +41,7 @@ pub async fn handle_token_metadata_account<'a, 'b, 'c>( } TokenMetadataAccountData::MasterEditionV2(m) => { let txn = db.begin().await?; - save_v2_master_edition(key, account_update.slot(), m, &txn).await?; + save_v2_master_edition(account_info.pubkey, account_info.slot, m, &txn).await?; txn.commit().await?; Ok(()) } @@ -53,6 +49,5 @@ pub async fn handle_token_metadata_account<'a, 'b, 'c>( // TokenMetadataAccountData::UseAuthorityRecord(_) => {} // TokenMetadataAccountData::CollectionAuthorityRecord(_) => {} _ => Err(ProgramTransformerError::NotImplemented), - }?; - Ok(()) + } } diff --git a/program_transformers/src/token_metadata/v1_asset.rs b/program_transformers/src/token_metadata/v1_asset.rs index 47bb76a2c..c57407369 100644 --- a/program_transformers/src/token_metadata/v1_asset.rs +++ b/program_transformers/src/token_metadata/v1_asset.rs @@ -20,25 +20,25 @@ use { json::ChainDataV1, }, num_traits::FromPrimitive, - plerkle_serialization::Pubkey as FBPubkey, sea_orm::{ entity::{ActiveValue, ColumnTrait, EntityTrait}, query::{Condition, JsonValue, QueryFilter, QueryTrait}, sea_query::query::OnConflict, ConnectionTrait, DbBackend, DbErr, TransactionTrait, }, + solana_sdk::pubkey::Pubkey, std::collections::HashSet, tracing::warn, }; pub async fn burn_v1_asset( conn: &T, - id: FBPubkey, + id: &Pubkey, slot: u64, ) -> ProgramTransformerResult<()> { - let (id, slot_i) = (id.0, slot as i64); + let (id, slot_i) = (id.to_bytes().to_vec(), slot as i64); let model = asset::ActiveModel { - id: ActiveValue::Set(id.to_vec()), + id: ActiveValue::Set(id), slot_updated: ActiveValue::Set(Some(slot_i)), burnt: ActiveValue::Set(true), ..Default::default() @@ -60,7 +60,7 @@ pub async fn burn_v1_asset( pub async fn save_v1_asset( conn: &T, - id: FBPubkey, + id: &Pubkey, slot: u64, metadata: &Metadata, ) -> ProgramTransformerResult> { @@ -70,7 +70,7 @@ pub async fn save_v1_asset( let (edition_attachment_address, _) = find_master_edition_account(&meta_mint_pubkey); let mint = metadata.mint.to_bytes().to_vec(); let authority = metadata.update_authority.to_bytes().to_vec(); - let id = id.0; + let id = id.to_bytes().to_vec(); let slot_i = slot as i64; let uri = data.uri.trim().replace('\0', ""); let _spec = SpecificationVersions::V1; From c13ad57cf24be6278f4417e891bae572b7a1e263 Mon Sep 17 00:00:00 2001 From: Kirill Fomichev Date: Thu, 23 Nov 2023 22:11:52 -0500 Subject: [PATCH 16/23] remove plerkle from program_transformers --- Cargo.lock | 4 +- Cargo.toml | 2 +- nft_ingester/src/account_updates.rs | 4 +- nft_ingester/src/plerkle.rs | 88 +++++++++++++++---- nft_ingester/src/transaction_notifications.rs | 25 +++++- program_transformers/Cargo.toml | 2 +- .../src/bubblegum/decompress.rs | 16 +--- program_transformers/src/bubblegum/mint_v1.rs | 4 +- program_transformers/src/lib.rs | 60 +++++++------ 9 files changed, 138 insertions(+), 67 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5cf0c6eee..60d423344 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -985,6 +985,7 @@ checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" [[package]] name = "blockbuster" version = "0.9.0-beta.1" +source = "git+https://github.com/rpcpool/blockbuster.git?tag=blockbuster-rm-plerkle-v0.9.0-beta.1#acbb64c569c700cccedad3c9289e1000deb0ab01" dependencies = [ "anchor-lang", "async-trait", @@ -999,6 +1000,7 @@ dependencies = [ "mpl-token-metadata", "plerkle_serialization", "solana-sdk", + "solana-transaction-status", "spl-account-compression", "spl-noop", "spl-token 4.0.0", @@ -4068,10 +4070,10 @@ dependencies = [ "futures", "mpl-bubblegum", "num-traits", - "plerkle_serialization", "sea-orm", "serde_json", "solana-sdk", + "solana-transaction-status", "spl-account-compression", "spl-token 4.0.0", "sqlx", diff --git a/Cargo.toml b/Cargo.toml index 1f93607d7..5c31592f1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -94,7 +94,7 @@ txn_forwarder = { path = "tools/txn_forwarder" } url = "2.3.1" [patch.crates-io] -blockbuster = { path = "/home/kirill/projects/blockbuster/blockbuster" } +blockbuster = { git = "https://github.com/rpcpool/blockbuster.git", tag = "blockbuster-rm-plerkle-v0.9.0-beta.1" } [workspace.lints.clippy] clone_on_ref_ptr = "deny" diff --git a/nft_ingester/src/account_updates.rs b/nft_ingester/src/account_updates.rs index 02cf4bdb6..c49b6cd5e 100644 --- a/nft_ingester/src/account_updates.rs +++ b/nft_ingester/src/account_updates.rs @@ -2,7 +2,7 @@ use { crate::{ metric, metrics::capture_result, - plerkle::{parse_pubkey, parse_vector}, + plerkle::{parse_pubkey, parse_slice}, tasks::{create_download_metadata_notifier, TaskData}, }, cadence_macros::{is_global_default_set, statsd_count, statsd_time}, @@ -131,7 +131,7 @@ async fn handle_account_update<'a>( slot: account_update.slot(), pubkey: &parse_pubkey(account_update.pubkey())?, owner: &parse_pubkey(account_update.owner())?, - data: parse_vector(account_update.data())?, + data: parse_slice(account_update.data())?, }) .await } diff --git a/nft_ingester/src/plerkle.rs b/nft_ingester/src/plerkle.rs index 530a8bc98..c206583e6 100644 --- a/nft_ingester/src/plerkle.rs +++ b/nft_ingester/src/plerkle.rs @@ -1,26 +1,78 @@ use { - flatbuffers::Vector, - plerkle_serialization::Pubkey as FBPubkey, + flatbuffers::{ForwardsUOffset, Vector}, + plerkle_serialization::{ + CompiledInnerInstructions as FBCompiledInnerInstructions, + CompiledInstruction as FBCompiledInstruction, Pubkey as FBPubkey, + }, program_transformers::error::{ProgramTransformerError, ProgramTransformerResult}, - solana_sdk::pubkey::Pubkey, + solana_sdk::{instruction::CompiledInstruction, pubkey::Pubkey, signature::Signature}, + solana_transaction_status::{InnerInstruction, InnerInstructions}, }; +fn deser_err() -> ProgramTransformerError { + ProgramTransformerError::DeserializationError("Could not deserialize data".to_owned()) +} + pub fn parse_pubkey(pubkey: Option<&FBPubkey>) -> ProgramTransformerResult { - Ok(Pubkey::try_from( - pubkey - .ok_or_else(|| { - ProgramTransformerError::DeserializationError( - "Could not deserialize data".to_owned(), - ) - })? - .0 - .as_slice(), - ) - .expect("valid key from FlatBuffer")) + Ok(Pubkey::try_from(pubkey.ok_or_else(deser_err)?.0.as_slice()) + .expect("valid key from FlatBuffer")) +} + +pub fn parse_slice(data: Option>) -> ProgramTransformerResult<&[u8]> { + data.map(|data| data.bytes()).ok_or_else(deser_err) +} + +pub fn parse_signature(data: Option<&str>) -> ProgramTransformerResult { + data.ok_or_else(deser_err)? + .parse() + .map_err(|_error| deser_err()) +} + +pub fn parse_account_keys( + keys: Option>, +) -> ProgramTransformerResult> { + let mut account_keys = vec![]; + for key in keys.ok_or_else(deser_err)? { + account_keys.push(Pubkey::try_from(key.0.as_slice()).expect("valid key from FlatBuffer")); + } + Ok(account_keys) +} + +pub fn parse_message_instructions( + vec_cix: Option>>, +) -> ProgramTransformerResult> { + let mut message_instructions = vec![]; + for cix in vec_cix.ok_or_else(deser_err)? { + message_instructions.push(CompiledInstruction { + program_id_index: cix.program_id_index(), + accounts: cix.accounts().ok_or_else(deser_err)?.bytes().to_vec(), + data: cix.data().ok_or_else(deser_err)?.bytes().to_vec(), + }) + } + Ok(message_instructions) } -pub fn parse_vector(data: Option>) -> ProgramTransformerResult<&[u8]> { - data.map(|data| data.bytes()).ok_or_else(|| { - ProgramTransformerError::DeserializationError("Could not deserialize data".to_owned()) - }) +pub fn parse_meta_inner_instructions( + vec_ixs: Option>>, +) -> ProgramTransformerResult> { + let mut meta_inner_instructions = vec![]; + for ixs in vec_ixs.ok_or_else(deser_err)? { + let mut instructions = vec![]; + for ix in ixs.instructions().ok_or_else(deser_err)? { + let cix = ix.compiled_instruction().ok_or_else(deser_err)?; + instructions.push(InnerInstruction { + instruction: CompiledInstruction { + program_id_index: cix.program_id_index(), + accounts: cix.accounts().ok_or_else(deser_err)?.bytes().to_vec(), + data: cix.data().ok_or_else(deser_err)?.bytes().to_vec(), + }, + stack_height: Some(ix.stack_height() as u32), + }); + } + meta_inner_instructions.push(InnerInstructions { + index: ixs.index(), + instructions, + }) + } + Ok(meta_inner_instructions) } diff --git a/nft_ingester/src/transaction_notifications.rs b/nft_ingester/src/transaction_notifications.rs index e3932eaf6..0859a658c 100644 --- a/nft_ingester/src/transaction_notifications.rs +++ b/nft_ingester/src/transaction_notifications.rs @@ -2,6 +2,10 @@ use { crate::{ metric, metrics::capture_result, + plerkle::{ + parse_account_keys, parse_message_instructions, parse_meta_inner_instructions, + parse_signature, + }, tasks::{create_download_metadata_notifier, TaskData}, }, cadence_macros::{is_global_default_set, statsd_count, statsd_time}, @@ -9,7 +13,7 @@ use { log::{debug, error}, plerkle_messenger::{ConsumptionType, Messenger, MessengerConfig, RecvData}, plerkle_serialization::root_as_transaction_info, - program_transformers::ProgramTransformer, + program_transformers::{error::ProgramTransformerResult, ProgramTransformer, TransactionInfo}, sqlx::{Pool, Postgres}, std::sync::Arc, tokio::{ @@ -101,7 +105,7 @@ async fn handle_transaction( } let begin = Instant::now(); - let res = manager.handle_transaction(&tx).await; + let res = handle_transaction_update(manager, tx).await; let should_ack = capture_result( id.clone(), stream_key, @@ -118,3 +122,20 @@ async fn handle_transaction( } ret_id } + +async fn handle_transaction_update<'a>( + manager: Arc, + tx: plerkle_serialization::TransactionInfo<'_>, +) -> ProgramTransformerResult<()> { + manager + .handle_transaction(&TransactionInfo { + slot: tx.slot(), + signature: &parse_signature(tx.signature())?, + account_keys: parse_account_keys(tx.account_keys())?, + message_instructions: &parse_message_instructions(tx.outer_instructions())?, + meta_inner_instructions: &parse_meta_inner_instructions( + tx.compiled_inner_instructions(), + )?, + }) + .await +} diff --git a/program_transformers/Cargo.toml b/program_transformers/Cargo.toml index 330e85b43..31d35871f 100644 --- a/program_transformers/Cargo.toml +++ b/program_transformers/Cargo.toml @@ -12,10 +12,10 @@ digital_asset_types = { workspace = true } futures = { workspace = true } mpl-bubblegum = { workspace = true } num-traits = { workspace = true } -plerkle_serialization = { workspace = true } sea-orm = { workspace = true, features = [] } serde_json = { workspace = true } solana-sdk = { workspace = true } +solana-transaction-status = { workspace = true } spl-account-compression = { workspace = true, features = ["no-entrypoint"] } spl-token = { workspace = true, features = ["no-entrypoint"] } sqlx = { workspace = true, features = [] } diff --git a/program_transformers/src/bubblegum/decompress.rs b/program_transformers/src/bubblegum/decompress.rs index 9db67e8b8..208e9aabc 100644 --- a/program_transformers/src/bubblegum/decompress.rs +++ b/program_transformers/src/bubblegum/decompress.rs @@ -17,18 +17,10 @@ pub async fn decompress<'c, T>( where T: ConnectionTrait + TransactionTrait, { - let id_bytes = bundle.keys.get(3).unwrap().0.as_slice(); + let id_bytes = bundle.keys.get(3).unwrap().to_bytes().to_vec(); // Partial update of asset table with just leaf. - upsert_asset_with_leaf_info_for_decompression(txn, id_bytes.to_vec()).await?; - upsert_asset_with_compression_info( - txn, - id_bytes.to_vec(), - false, - false, - 1, - Some(id_bytes.to_vec()), - true, - ) - .await + upsert_asset_with_leaf_info_for_decompression(txn, id_bytes.clone()).await?; + upsert_asset_with_compression_info(txn, id_bytes.clone(), false, false, 1, Some(id_bytes), true) + .await } diff --git a/program_transformers/src/bubblegum/mint_v1.rs b/program_transformers/src/bubblegum/mint_v1.rs index cccf60d7a..b182e112d 100644 --- a/program_transformers/src/bubblegum/mint_v1.rs +++ b/program_transformers/src/bubblegum/mint_v1.rs @@ -132,7 +132,7 @@ where } else { Some(delegate.to_bytes().to_vec()) }; - let tree_id = bundle.keys.get(3).unwrap().0.to_vec(); + let tree_id = bundle.keys.get(3).unwrap().to_bytes().to_vec(); // ActiveValue::Set initial mint info. let asset_model = asset::ActiveModel { @@ -313,7 +313,7 @@ where // Insert into `asset_authority` table. let model = asset_authority::ActiveModel { asset_id: ActiveValue::Set(id_bytes.to_vec()), - authority: ActiveValue::Set(bundle.keys.get(0).unwrap().0.to_vec()), //TODO - we need to rem,ove the optional bubblegum signer logic + authority: ActiveValue::Set(bundle.keys.get(0).unwrap().to_bytes().to_vec()), //TODO - we need to rem,ove the optional bubblegum signer logic seq: ActiveValue::Set(seq as i64), slot_updated: ActiveValue::Set(slot_i), ..Default::default() diff --git a/program_transformers/src/lib.rs b/program_transformers/src/lib.rs index bf4ac0623..5cf1c0ced 100644 --- a/program_transformers/src/lib.rs +++ b/program_transformers/src/lib.rs @@ -14,9 +14,9 @@ use { }, }, futures::future::BoxFuture, - plerkle_serialization::{Pubkey as FBPubkey, TransactionInfo}, sea_orm::{DatabaseConnection, SqlxPostgresConnector}, - solana_sdk::pubkey::Pubkey, + solana_sdk::{instruction::CompiledInstruction, pubkey::Pubkey, signature::Signature}, + solana_transaction_status::InnerInstructions, sqlx::PgPool, std::collections::{HashMap, HashSet, VecDeque}, tracing::{debug, error, info}, @@ -35,6 +35,15 @@ pub struct AccountInfo<'a> { pub data: &'a [u8], } +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct TransactionInfo<'a> { + pub slot: u64, + pub signature: &'a Signature, + pub account_keys: Vec, + pub message_instructions: &'a [CompiledInstruction], + pub meta_inner_instructions: &'a [InnerInstructions], +} + #[derive(Debug, Clone, PartialEq, Eq)] pub struct DownloadMetadataInfo { asset_data_id: Vec, @@ -96,12 +105,16 @@ impl ProgramTransformer { } } - pub fn break_transaction<'i>( + pub fn break_transaction<'a>( &self, - tx: &'i TransactionInfo<'i>, - ) -> VecDeque<(IxPair<'i>, Option>>)> { - let ref_set: HashSet<&[u8]> = self.key_set.iter().map(|k| k.as_ref()).collect(); - order_instructions(ref_set, tx) + tx_info: &'a TransactionInfo<'_>, + ) -> VecDeque<(IxPair<'a>, Option>>)> { + order_instructions( + &self.key_set, + &tx_info.account_keys, + tx_info.message_instructions, + tx_info.meta_inner_instructions, + ) } #[allow(clippy::borrowed_box)] @@ -109,33 +122,25 @@ impl ProgramTransformer { self.parsers.get(key) } - pub async fn handle_transaction<'a>( + pub async fn handle_transaction( &self, - tx: &'a TransactionInfo<'a>, + tx_info: &TransactionInfo<'_>, ) -> ProgramTransformerResult<()> { - let sig: Option<&str> = tx.signature(); - info!("Handling Transaction: {:?}", sig); - let instructions = self.break_transaction(tx); - let accounts = tx.account_keys().unwrap_or_default(); - let slot = tx.slot(); - let txn_id = tx.signature().unwrap_or(""); - let mut keys: Vec = Vec::with_capacity(accounts.len()); - for k in accounts.into_iter() { - keys.push(*k); - } + info!("Handling Transaction: {:?}", tx_info.signature); + let instructions = self.break_transaction(tx_info); let mut not_impl = 0; let ixlen = instructions.len(); debug!("Instructions: {}", ixlen); let contains = instructions .iter() - .filter(|(ib, _inner)| ib.0 .0.as_ref() == mpl_bubblegum::ID.as_ref()); + .filter(|(ib, _inner)| ib.0 == mpl_bubblegum::ID); debug!("Instructions bgum: {}", contains.count()); for (outer_ix, inner_ix) in instructions { let (program, instruction) = outer_ix; - let ix_accounts = instruction.accounts().unwrap().iter().collect::>(); + let ix_accounts = &instruction.accounts; let ix_account_len = ix_accounts.len(); let max = ix_accounts.iter().max().copied().unwrap_or(0) as usize; - if keys.len() < max { + if tx_info.account_keys.len() < max { return Err(ProgramTransformerError::DeserializationError( "Missing Accounts in Serialized Ixn/Txn".to_string(), )); @@ -144,22 +149,21 @@ impl ProgramTransformer { ix_accounts .iter() .fold(Vec::with_capacity(ix_account_len), |mut acc, a| { - if let Some(key) = keys.get(*a as usize) { + if let Some(key) = tx_info.account_keys.get(*a as usize) { acc.push(*key); } acc }); let ix = InstructionBundle { - txn_id, + txn_id: &tx_info.signature.to_string(), program, instruction: Some(instruction), inner_ix, keys: ix_accounts.as_slice(), - slot, + slot: tx_info.slot, }; - let program_key = - Pubkey::try_from(ix.program.0.as_slice()).expect("valid key from FlatBuffer"); + let program_key = ix.program; if let Some(program) = self.match_program(&program_key) { debug!("Found a ix for program: {:?}", program.key()); let result = program.handle_instruction(&ix)?; @@ -177,7 +181,7 @@ impl ProgramTransformer { .map_err(|err| { error!( "Failed to handle bubblegum instruction for txn {:?}: {:?}", - sig, err + tx_info.signature, err ); err })?; From 5d6ae16b077929d8a62d1b49a3263bda2343a913 Mon Sep 17 00:00:00 2001 From: Kirill Fomichev Date: Sun, 26 Nov 2023 19:14:56 -0500 Subject: [PATCH 17/23] nft_ingester2: grpc2redis --- Cargo.lock | 805 +++++++++++++++++++++++++--- Cargo.toml | 24 +- nft_ingester/Cargo.toml | 2 +- nft_ingester2/Cargo.toml | 39 ++ nft_ingester2/build.rs | 38 ++ nft_ingester2/config-grpc2redis.yml | 24 + nft_ingester2/src/config.rs | 180 +++++++ nft_ingester2/src/grpc.rs | 151 ++++++ nft_ingester2/src/ingester.rs | 5 + nft_ingester2/src/main.rs | 75 +++ nft_ingester2/src/prom.rs | 106 ++++ nft_ingester2/src/redis.rs | 25 + nft_ingester2/src/tracing.rs | 32 ++ nft_ingester2/src/util.rs | 16 + nft_ingester2/src/version.rs | 22 + tools/tree-status/Cargo.toml | 2 +- 16 files changed, 1469 insertions(+), 77 deletions(-) create mode 100644 nft_ingester2/Cargo.toml create mode 100644 nft_ingester2/build.rs create mode 100644 nft_ingester2/config-grpc2redis.yml create mode 100644 nft_ingester2/src/config.rs create mode 100644 nft_ingester2/src/grpc.rs create mode 100644 nft_ingester2/src/ingester.rs create mode 100644 nft_ingester2/src/main.rs create mode 100644 nft_ingester2/src/prom.rs create mode 100644 nft_ingester2/src/redis.rs create mode 100644 nft_ingester2/src/tracing.rs create mode 100644 nft_ingester2/src/util.rs create mode 100644 nft_ingester2/src/version.rs diff --git a/Cargo.lock b/Cargo.lock index 60d423344..259306caf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -821,6 +821,60 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "autotools" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aef8da1805e028a172334c3b680f93e71126f2327622faef2ec3d893c0a4ad77" +dependencies = [ + "cc", +] + +[[package]] +name = "axum" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" +dependencies = [ + "async-trait", + "axum-core", + "bitflags 1.3.2", + "bytes", + "futures-util", + "http", + "http-body", + "hyper", + "itoa", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "rustversion", + "serde", + "sync_wrapper", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "axum-core" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" +dependencies = [ + "async-trait", + "bytes", + "futures-util", + "http", + "http-body", + "mime", + "rustversion", + "tower-layer", + "tower-service", +] + [[package]] name = "backtrace" version = "0.3.69" @@ -1257,6 +1311,18 @@ dependencies = [ "thiserror", ] +[[package]] +name = "cargo-lock" +version = "9.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e11c675378efb449ed3ce8de78d75d0d80542fc98487c26aba28eb3b82feac72" +dependencies = [ + "semver", + "serde", + "toml 0.7.8", + "url", +] + [[package]] name = "cc" version = "1.0.83" @@ -2113,6 +2179,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8fcfdc7a0362c9f4444381a9e697c79d435fe65b52a37466fc2c1184cee9edc6" +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + [[package]] name = "flatbuffers" version = "23.5.26" @@ -2363,6 +2435,32 @@ version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" +[[package]] +name = "git-version" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13ad01ffa8221f7fe8b936d6ffb2a3e7ad428885a04fad51866a5f33eafda57c" +dependencies = [ + "git-version-macro", +] + +[[package]] +name = "git-version-macro" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84488ccbdb24ad6f56dc1863b4a8154a7856cd3c6c7610401634fab3cb588dae" +dependencies = [ + "proc-macro2 1.0.69", + "quote 1.0.33", + "syn 2.0.38", +] + +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + [[package]] name = "globset" version = "0.4.13" @@ -2557,6 +2655,15 @@ dependencies = [ "hmac 0.8.1", ] +[[package]] +name = "home" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" +dependencies = [ + "windows-sys 0.48.0", +] + [[package]] name = "http" version = "0.2.9" @@ -2641,6 +2748,18 @@ dependencies = [ "tokio-rustls 0.24.1", ] +[[package]] +name = "hyper-timeout" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" +dependencies = [ + "hyper", + "pin-project-lite", + "tokio", + "tokio-io-timeout", +] + [[package]] name = "hyper-tls" version = "0.5.0" @@ -2757,6 +2876,12 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "integer-encoding" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bb03732005da905c88227371639bf1ad885cc712789c011c31c5fb3ab3ccf02" + [[package]] name = "io-lifetimes" version = "1.0.11" @@ -2827,6 +2952,17 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "json5" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96b0db21af676c1ce64250b5f40f3ce2cf27e4e47cb91ed91eb6fe9350b430c1" +dependencies = [ + "pest", + "pest_derive", + "serde", +] + [[package]] name = "jsonpath_lib" version = "0.3.0" @@ -3081,6 +3217,12 @@ dependencies = [ "regex-automata 0.1.10", ] +[[package]] +name = "matchit" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" + [[package]] name = "md-5" version = "0.10.6" @@ -3328,6 +3470,12 @@ dependencies = [ "spl-token-2022 0.6.1", ] +[[package]] +name = "multimap" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" + [[package]] name = "native-tls" version = "0.2.11" @@ -3386,6 +3534,37 @@ dependencies = [ "url", ] +[[package]] +name = "nft_ingester2" +version = "0.7.2" +dependencies = [ + "anyhow", + "atty", + "cargo-lock", + "clap 4.4.8", + "futures", + "git-version", + "hyper", + "json5", + "lazy_static", + "opentelemetry", + "opentelemetry-jaeger", + "opentelemetry_sdk", + "prometheus", + "redis", + "serde", + "serde_yaml", + "solana-sdk", + "tokio", + "tracing", + "tracing-opentelemetry", + "tracing-subscriber", + "vergen", + "yellowstone-grpc-client", + "yellowstone-grpc-proto", + "yellowstone-grpc-tools", +] + [[package]] name = "nix" version = "0.26.4" @@ -3602,6 +3781,15 @@ dependencies = [ "syn 2.0.38", ] +[[package]] +name = "num_threads" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" +dependencies = [ + "libc", +] + [[package]] name = "number_prefix" version = "0.4.0" @@ -3706,6 +3894,87 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "opentelemetry" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e32339a5dc40459130b3bd269e9892439f55b33e772d2a9d402a789baaf4e8a" +dependencies = [ + "futures-core", + "futures-sink", + "indexmap 2.0.2", + "js-sys", + "once_cell", + "pin-project-lite", + "thiserror", + "urlencoding", +] + +[[package]] +name = "opentelemetry-jaeger" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e617c66fd588e40e0dbbd66932fdc87393095b125d4459b1a3a10feb1712f8a1" +dependencies = [ + "async-trait", + "futures-core", + "futures-util", + "opentelemetry", + "opentelemetry-semantic-conventions", + "opentelemetry_sdk", + "thrift", + "tokio", +] + +[[package]] +name = "opentelemetry-semantic-conventions" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5774f1ef1f982ef2a447f6ee04ec383981a3ab99c8e77a1a7b30182e65bbc84" +dependencies = [ + "opentelemetry", +] + +[[package]] +name = "opentelemetry_sdk" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "968ba3f2ca03e90e5187f5e4f46c791ef7f2c163ae87789c8ce5f5ca3b7b7de5" +dependencies = [ + "async-trait", + "crossbeam-channel", + "futures-channel", + "futures-executor", + "futures-util", + "glob", + "once_cell", + "opentelemetry", + "ordered-float 4.1.1", + "percent-encoding", + "rand 0.8.5", + "thiserror", + "tokio", + "tokio-stream", +] + +[[package]] +name = "ordered-float" +version = "2.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68f19d67e5a2795c94e73e0bb1cc1a7edeb2e28efd39e2e1c9b7a40c1108b11c" +dependencies = [ + "num-traits", +] + +[[package]] +name = "ordered-float" +version = "4.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "536900a8093134cf9ccf00a27deb3532421099e958d9dd431135d0c7543ca1e8" +dependencies = [ + "num-traits", +] + [[package]] name = "os_str_bytes" version = "6.6.1" @@ -3866,6 +4135,81 @@ dependencies = [ "num", ] +[[package]] +name = "pest" +version = "2.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae9cee2a55a544be8b89dc6848072af97a20f2422603c10865be2a42b580fff5" +dependencies = [ + "memchr", + "thiserror", + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81d78524685f5ef2a3b3bd1cafbc9fcabb036253d9b1463e726a91cd16e2dfc2" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68bd1206e71118b5356dae5ddc61c8b11e28b09ef6a31acbd15ea48a28e0c227" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2 1.0.69", + "quote 1.0.33", + "syn 2.0.38", +] + +[[package]] +name = "pest_meta" +version = "2.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c747191d4ad9e4a4ab9c8798f1e82a39affe7ef9648390b7e5548d18e099de6" +dependencies = [ + "once_cell", + "pest", + "sha2 0.10.8", +] + +[[package]] +name = "petgraph" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" +dependencies = [ + "fixedbitset", + "indexmap 2.0.2", +] + +[[package]] +name = "pin-project" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" +dependencies = [ + "proc-macro2 1.0.69", + "quote 1.0.33", + "syn 2.0.38", +] + [[package]] name = "pin-project-lite" version = "0.2.13" @@ -3986,6 +4330,16 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[package]] +name = "prettyplease" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae005bd773ab59b4725093fd7df83fd7892f7d8eafb48dbd7de6e024e4215f9d" +dependencies = [ + "proc-macro2 1.0.69", + "syn 2.0.38", +] + [[package]] name = "proc-macro-crate" version = "0.1.5" @@ -4096,12 +4450,75 @@ dependencies = [ "thiserror", ] +[[package]] +name = "prost" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "146c289cda302b98a28d40c8b3b90498d6e526dd24ac2ecea73e4e491685b94a" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-build" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c55e02e35260070b6f716a2423c2ff1c3bb1642ddca6f99e1f26d06268a0e2d2" +dependencies = [ + "bytes", + "heck 0.4.1", + "itertools 0.11.0", + "log", + "multimap", + "once_cell", + "petgraph", + "prettyplease", + "prost", + "prost-types", + "regex", + "syn 2.0.38", + "tempfile", + "which", +] + +[[package]] +name = "prost-derive" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" +dependencies = [ + "anyhow", + "itertools 0.11.0", + "proc-macro2 1.0.69", + "quote 1.0.33", + "syn 2.0.38", +] + +[[package]] +name = "prost-types" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "193898f59edcf43c26227dcd4c8427f00d99d61e95dcde58dabd49fa291d470e" +dependencies = [ + "prost", +] + [[package]] name = "protobuf" version = "2.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94" +[[package]] +name = "protobuf-src" +version = "1.1.0+21.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7ac8852baeb3cc6fb83b93646fb93c0ffe5d14bf138c945ceb4b9948ee0e3c1" +dependencies = [ + "autotools", +] + [[package]] name = "proxy-wasm" version = "0.2.1" @@ -5047,12 +5464,15 @@ name = "semver" version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad977052201c6de01a8ef2aa3378c4bd23217a056337d1d6da40468d267a4fb0" +dependencies = [ + "serde", +] [[package]] name = "serde" -version = "1.0.188" +version = "1.0.193" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" +checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" dependencies = [ "serde_derive", ] @@ -5068,9 +5488,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.188" +version = "1.0.193" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" +checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" dependencies = [ "proc-macro2 1.0.69", "quote 1.0.33", @@ -5167,9 +5587,9 @@ dependencies = [ [[package]] name = "serde_yaml" -version = "0.9.25" +version = "0.9.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a49e178e4452f45cb61d0cd8cebc1b0fafd3e41929e996cef79aa3aca91f574" +checksum = "3cc7a1570e38322cfe4154732e5110f887ea57e22b76f4bfd32b5bdd3368666c" dependencies = [ "indexmap 2.0.2", "itoa", @@ -5398,9 +5818,9 @@ dependencies = [ [[package]] name = "solana-account-decoder" -version = "1.16.16" +version = "1.16.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f52aec62a85932e26d1085864b0f7b99b31934aec8dd132429bfef6d7fb1d3a6" +checksum = "5d8ea963f393c09376f21f7f5217d5701a18d65c821a68337188b6cf9c1255db" dependencies = [ "Inflector", "base64 0.21.4", @@ -5423,9 +5843,9 @@ dependencies = [ [[package]] name = "solana-address-lookup-table-program" -version = "1.16.16" +version = "1.16.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee0bd25f4ba0a15fc16c57b41b1e1b14f5271b83214fda158fdedb58758d394e" +checksum = "5c284096b2d4595b13f61004142c6caff4f3dc40ba77dbd5f4071d67c256e15c" dependencies = [ "bincode", "bytemuck", @@ -5444,9 +5864,9 @@ dependencies = [ [[package]] name = "solana-clap-utils" -version = "1.16.16" +version = "1.16.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e963043668c640183d48472b281ebb9f713e0c36df0271961d23e6a394e09070" +checksum = "b4371b20d9dff6a0e769cd103385e7c257d511efec11efd94c65ab52a39255e2" dependencies = [ "chrono", "clap 2.34.0", @@ -5462,9 +5882,9 @@ dependencies = [ [[package]] name = "solana-client" -version = "1.16.16" +version = "1.16.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52ccf7bb34fb81c74582a9011babaa2e0220da56c71186e77f45a6f352017fdb" +checksum = "78ee4db75f979886731e603f7bd22eeb3386cd1477a7592931e21623326da83b" dependencies = [ "async-trait", "bincode", @@ -5495,9 +5915,9 @@ dependencies = [ [[package]] name = "solana-config-program" -version = "1.16.16" +version = "1.16.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fd0fc1efb91a1661aeb1ff6a691156c3b1bffdaed0aa096589499dd83f9e50b" +checksum = "ae9df684ad70f3e3cb716a085652b545a64dfbc9299c59f768112ec69d4f4392" dependencies = [ "bincode", "chrono", @@ -5509,9 +5929,9 @@ dependencies = [ [[package]] name = "solana-connection-cache" -version = "1.16.16" +version = "1.16.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8759e9cb9b1e92a94c31812169ecb5e65b5e215fb70fb68691e03655de5b7b6c" +checksum = "c58c2e8007f2fd5ae0302ccaa7df72bdb6b1b40fd9f4b6c67f5e928dc58d9f35" dependencies = [ "async-trait", "bincode", @@ -5530,9 +5950,9 @@ dependencies = [ [[package]] name = "solana-frozen-abi" -version = "1.16.16" +version = "1.16.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02eb4f0ed3eade20f4abdcc0031167344237cd6e16808bd0f33945f9db7861fe" +checksum = "9ab680d7d65fcecdea832cadb063fc3898121bc56cab15aee54f2c5db71af535" dependencies = [ "ahash 0.8.3", "blake3", @@ -5563,9 +5983,9 @@ dependencies = [ [[package]] name = "solana-frozen-abi-macro" -version = "1.16.16" +version = "1.16.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28514761a285944cbad5b3d7930546369b80a713ba37d84bcf6ed2753611765" +checksum = "b02411fefc004154edf3fe61cedb1dfb26ef82b659148b0a4b21ce3184d40ebc" dependencies = [ "proc-macro2 1.0.69", "quote 1.0.33", @@ -5588,9 +6008,9 @@ dependencies = [ [[package]] name = "solana-logger" -version = "1.16.16" +version = "1.16.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c310c6749435ce1ea25a9ae3edfb2fd2c2aed2aa4d4f7e0487a8077a0b1ee30" +checksum = "f9c7f0c4504c512f93aed16fb07449cafa5fa0c54ef7cfff6f377b2a5ed34553" dependencies = [ "env_logger 0.9.3", "lazy_static", @@ -5599,9 +6019,9 @@ dependencies = [ [[package]] name = "solana-measure" -version = "1.16.16" +version = "1.16.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d171357580e62aa4ca19c780e25f4e74de064e2780cb8b9f6b6901d986fcd23" +checksum = "ceb54a32ad5125ed514c058639ac86508efcffc2412f713e3140eb70291d9843" dependencies = [ "log", "solana-sdk", @@ -5609,9 +6029,9 @@ dependencies = [ [[package]] name = "solana-metrics" -version = "1.16.16" +version = "1.16.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "013cbb3c82588278d2be18d3317ece5286cb54a3a06d5d38fc31e2a76a6d5e2d" +checksum = "ef674e1c16731541af6f58515ebdae519f68d374a3018675dc9ee3480b4a640e" dependencies = [ "crossbeam-channel", "gethostname", @@ -5623,9 +6043,9 @@ dependencies = [ [[package]] name = "solana-net-utils" -version = "1.16.16" +version = "1.16.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c50d7cac0694b1fe07499de25404a0c7d6836457e359aba3b08c3983c3dc5eb6" +checksum = "a39ab5b49d50c50411fe1990b097458dd3d23aee1753db9b13f69a2f946409f5" dependencies = [ "bincode", "clap 3.2.25", @@ -5645,9 +6065,9 @@ dependencies = [ [[package]] name = "solana-perf" -version = "1.16.16" +version = "1.16.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "395d559e5be2c439551298e9fa95561807f24921fd9a1e08bb82a3dc05c02dea" +checksum = "710431ce6bc8a070c3b54999f9602b8b4c94358836615e89e357114ea0ae1fe5" dependencies = [ "ahash 0.8.3", "bincode", @@ -5672,9 +6092,9 @@ dependencies = [ [[package]] name = "solana-program" -version = "1.16.16" +version = "1.16.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cff2aa5434a77413e9d43e971ceb47bdb003f2e8bbc0365a25b684aca2605c25" +checksum = "aedf18ad0e74ce21123eb94c45d8b469d280a6a3e4f1bf6411fc4ca8fc7c2eac" dependencies = [ "ark-bn254", "ark-ec", @@ -5727,9 +6147,9 @@ dependencies = [ [[package]] name = "solana-program-runtime" -version = "1.16.16" +version = "1.16.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d1832fefc2187142dac169812518ec20da68b09abad86e4a78f8ae1787e4f56" +checksum = "d9e3ff03078645ddd91e2a3eb2d58a90a5a6c9d7e8c2b9c2b3511f24ea03b711" dependencies = [ "base64 0.21.4", "bincode", @@ -5755,9 +6175,9 @@ dependencies = [ [[package]] name = "solana-pubsub-client" -version = "1.16.16" +version = "1.16.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89388addbc3192407d948634f82c95c4dbe1efbe578582abfd136720e059556e" +checksum = "8c7d115473531dbc447989e3e6eb24a418bf3c0b7ffb86da17c4a1271d1ce553" dependencies = [ "crossbeam-channel", "futures-util", @@ -5780,9 +6200,9 @@ dependencies = [ [[package]] name = "solana-quic-client" -version = "1.16.16" +version = "1.16.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7897b876a6df2d97b3a5ddfd764155c0591e3497e863fd7fdf32b54de4e2644" +checksum = "bca1af43f5b44321e2a5f48798d07ade968c7d95c3191ef2f8e167a481ed4d37" dependencies = [ "async-mutex", "async-trait", @@ -5808,9 +6228,9 @@ dependencies = [ [[package]] name = "solana-rayon-threadlimit" -version = "1.16.16" +version = "1.16.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ba17a930f9974a17a9a6c6e82e7f89b40127e9cc0f9c17cfc29fc5b149d2c38" +checksum = "cb5a290bb5b316654d165326c1ed22cf15a40559523824097308913cce2dcad7" dependencies = [ "lazy_static", "num_cpus", @@ -5818,9 +6238,9 @@ dependencies = [ [[package]] name = "solana-remote-wallet" -version = "1.16.16" +version = "1.16.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80fb35e3fa78ef1d08a6a1d852e2c357e6ae388cb307d24fad359f57c34429f0" +checksum = "a082793597a5467271d35cbee5e3782e42a0b52849521f293b6bc07f9514d018" dependencies = [ "console", "dialoguer", @@ -5837,9 +6257,9 @@ dependencies = [ [[package]] name = "solana-rpc-client" -version = "1.16.16" +version = "1.16.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c512944689d747a87f76936c89bb59f5be6c9a3189631857f49746cfa47d5bd1" +checksum = "b6ed31f6dd0546a92daf7493c94b602e6c06e59b474d5a81559ff88d6d3e8afa" dependencies = [ "async-trait", "base64 0.21.4", @@ -5863,9 +6283,9 @@ dependencies = [ [[package]] name = "solana-rpc-client-api" -version = "1.16.16" +version = "1.16.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e918b75f8ac4c358a6b512bf8b7dafc8166ddcb52ded5164c6235e0693ccb09" +checksum = "e846fb99c6aa3d044cb556f40156a585dd3f4cb1e416b5b8319028d3f731b6a8" dependencies = [ "base64 0.21.4", "bs58 0.4.0", @@ -5885,9 +6305,9 @@ dependencies = [ [[package]] name = "solana-rpc-client-nonce-utils" -version = "1.16.16" +version = "1.16.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6e360ea2f3a756bdf6256c1f6ef13f8b01b5d2a7855b4f16cafb4a4017f0557" +checksum = "cc5ac3f71c723bf061e684c1bcf9be29b99d07fd6be54cf9e12f1cc1629d4f74" dependencies = [ "clap 2.34.0", "solana-clap-utils", @@ -5898,9 +6318,9 @@ dependencies = [ [[package]] name = "solana-sdk" -version = "1.16.16" +version = "1.16.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b1002048941cedbd7dd6a96fdaa3dc5238b998aaa70b81946b1e3ec108cc2be" +checksum = "d6aea1e7067980ca1ef57a31c498413547b82aa392d9e7ec5539968f1a8dec1c" dependencies = [ "assert_matches", "base64 0.21.4", @@ -5951,9 +6371,9 @@ dependencies = [ [[package]] name = "solana-sdk-macro" -version = "1.16.16" +version = "1.16.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b41b63b2da4a37ce323aba108db21f4c7bfa638dd1bf58fdc870f83bdce48ba" +checksum = "dbca599523925e4c55e0326d93eef0a8e1918df5f93897811abf3f5972e21bec" dependencies = [ "bs58 0.4.0", "proc-macro2 1.0.69", @@ -5964,9 +6384,9 @@ dependencies = [ [[package]] name = "solana-streamer" -version = "1.16.16" +version = "1.16.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f00e575f2bd5ae2776870fbd1d7379d4ad392c015e2a4e2a328953b821a9d36d" +checksum = "2147a8042ec522d31a5ec67ef06000d7c4d528d7ce49a2e5225687fb5ad08ea8" dependencies = [ "async-channel 1.9.0", "bytes", @@ -5997,9 +6417,9 @@ dependencies = [ [[package]] name = "solana-thin-client" -version = "1.16.16" +version = "1.16.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df328e2624cce68c9949a53eac317a264eceb997131cb9bd22175698a5f5dc74" +checksum = "8af1069859646695b53b88cf071ba3c2ce49f0fbe9b19014440676e1869704f5" dependencies = [ "bincode", "log", @@ -6012,9 +6432,9 @@ dependencies = [ [[package]] name = "solana-tpu-client" -version = "1.16.16" +version = "1.16.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8ce6fe221c0e1fd8aa3078b8fcb0cc3f4c27942f1256b57a60608d81ae5348" +checksum = "d9bc57c809b5ee98570bd0981c3ecce339d4053f8473ab2d57a9487ad3aea5af" dependencies = [ "async-trait", "bincode", @@ -6037,9 +6457,9 @@ dependencies = [ [[package]] name = "solana-transaction-status" -version = "1.16.16" +version = "1.16.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db0b811793e78a908119cc02edca3ff8b54d5660104ebd06cc0e2e7e2f66900b" +checksum = "f225ca544e1005918608bfe67f97c1cfdfe43bb6ab41e0bd77491258a7e5e8f8" dependencies = [ "Inflector", "base64 0.21.4", @@ -6063,9 +6483,9 @@ dependencies = [ [[package]] name = "solana-udp-client" -version = "1.16.16" +version = "1.16.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897ff303a15ba956e80573dee4cf96d94d41a69adc5362898b98851e347505ad" +checksum = "be1dbf725b5e31863f34553c1333e8d8e098c6259bbed433630022aa59e9a175" dependencies = [ "async-trait", "solana-connection-cache", @@ -6078,9 +6498,9 @@ dependencies = [ [[package]] name = "solana-version" -version = "1.16.16" +version = "1.16.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9513754d3b2203a0e1045a211c5d68e72e4ed135e477344c21d096897fd2bf70" +checksum = "cc8ac5da4f0044a857cb35bf0a146e76400541fce72f0638b9377fd368cf2da0" dependencies = [ "log", "rustc_version", @@ -6094,9 +6514,9 @@ dependencies = [ [[package]] name = "solana-vote-program" -version = "1.16.16" +version = "1.16.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b6bfc5302ce0383eb129aa3a916705a20d22c4ad448144ef684b7b028d4053f" +checksum = "ee3c171647345a050eaf80846d99f888c55c2bcbdd0297dfae38597950ca6054" dependencies = [ "bincode", "log", @@ -6116,9 +6536,9 @@ dependencies = [ [[package]] name = "solana-zk-token-sdk" -version = "1.16.16" +version = "1.16.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d1fe77918563768a65fd5d6cd2fa06cf0aeb11e529a1ef8c230b0fe018600e3" +checksum = "b8d5a0aa72c38c45b134e6fc008569fe1b0882c7cff5fceb7e42c0406925d3e5" dependencies = [ "aes-gcm-siv", "base64 0.21.4", @@ -6649,6 +7069,12 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + [[package]] name = "synstructure" version = "0.12.6" @@ -6755,6 +7181,28 @@ dependencies = [ "once_cell", ] +[[package]] +name = "threadpool" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" +dependencies = [ + "num_cpus", +] + +[[package]] +name = "thrift" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e54bc85fc7faa8bc175c4bab5b92ba8d9a3ce893d0e9f42cc455c8ab16a9e09" +dependencies = [ + "byteorder", + "integer-encoding", + "log", + "ordered-float 2.10.1", + "threadpool", +] + [[package]] name = "time" version = "0.1.45" @@ -6774,6 +7222,8 @@ checksum = "426f806f4089c493dcac0d24c29c01e2c38baf8e30f1b716ee37e83d200b18fe" dependencies = [ "deranged", "itoa", + "libc", + "num_threads", "serde", "time-core", "time-macros", @@ -6848,6 +7298,16 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "tokio-io-timeout" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" +dependencies = [ + "pin-project-lite", + "tokio", +] + [[package]] name = "tokio-macros" version = "2.1.0" @@ -6941,6 +7401,18 @@ dependencies = [ "serde", ] +[[package]] +name = "toml" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit 0.19.15", +] + [[package]] name = "toml" version = "0.8.8" @@ -6969,6 +7441,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ "indexmap 2.0.2", + "serde", + "serde_spanned", "toml_datetime", "winnow", ] @@ -6986,12 +7460,79 @@ dependencies = [ "winnow", ] +[[package]] +name = "tonic" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d560933a0de61cf715926b9cac824d4c883c2c43142f787595e48280c40a1d0e" +dependencies = [ + "async-stream", + "async-trait", + "axum", + "base64 0.21.4", + "bytes", + "flate2", + "h2", + "http", + "http-body", + "hyper", + "hyper-timeout", + "percent-encoding", + "pin-project", + "prost", + "rustls 0.21.7", + "rustls-native-certs", + "rustls-pemfile", + "tokio", + "tokio-rustls 0.24.1", + "tokio-stream", + "tower", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tonic-build" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d021fc044c18582b9a2408cd0dd05b1596e3ecdb5c4df822bb0183545683889" +dependencies = [ + "prettyplease", + "proc-macro2 1.0.69", + "prost-build", + "quote 1.0.33", + "syn 2.0.38", +] + +[[package]] +name = "tonic-health" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f80db390246dfb46553481f6024f0082ba00178ea495dbb99e70ba9a4fafb5e1" +dependencies = [ + "async-stream", + "prost", + "tokio", + "tokio-stream", + "tonic", +] + [[package]] name = "tower" version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" dependencies = [ + "futures-core", + "futures-util", + "indexmap 1.9.3", + "pin-project", + "pin-project-lite", + "rand 0.8.5", + "slab", + "tokio", + "tokio-util", "tower-layer", "tower-service", "tracing", @@ -7072,6 +7613,24 @@ dependencies = [ "tracing-core", ] +[[package]] +name = "tracing-opentelemetry" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c67ac25c5407e7b961fafc6f7e9aa5958fd297aada2d20fa2ae1737357e55596" +dependencies = [ + "js-sys", + "once_cell", + "opentelemetry", + "opentelemetry_sdk", + "smallvec", + "tracing", + "tracing-core", + "tracing-log", + "tracing-subscriber", + "web-time", +] + [[package]] name = "tracing-serde" version = "0.1.3" @@ -7200,6 +7759,12 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +[[package]] +name = "ucd-trie" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" + [[package]] name = "uncased" version = "0.9.9" @@ -7327,6 +7892,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "urlencoding" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" + [[package]] name = "utf-8" version = "0.7.6" @@ -7373,6 +7944,18 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" +[[package]] +name = "vergen" +version = "8.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1290fd64cc4e7d3c9b07d7f333ce0ce0007253e32870e632624835cc80b83939" +dependencies = [ + "anyhow", + "rustc_version", + "rustversion", + "time 0.3.29", +] + [[package]] name = "version_check" version = "0.9.4" @@ -7494,6 +8077,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "web-time" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57099a701fb3a8043f993e8228dc24229c7b942e2b009a1b962e54489ba1d3bf" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "webpki" version = "0.22.4" @@ -7530,6 +8123,18 @@ dependencies = [ "triomphe", ] +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix 0.38.18", +] + [[package]] name = "whoami" version = "1.4.1" @@ -7794,6 +8399,66 @@ dependencies = [ "time 0.3.29", ] +[[package]] +name = "yellowstone-grpc-client" +version = "1.12.0+solana.1.16.19" +source = "git+https://github.com/rpcpool/yellowstone-grpc.git?tag=v1.11.1+solana.1.16.19#8b8618dd19d70ed58b942021768d826e31408cd8" +dependencies = [ + "bytes", + "futures", + "http", + "thiserror", + "tonic", + "tonic-health", + "yellowstone-grpc-proto", +] + +[[package]] +name = "yellowstone-grpc-proto" +version = "1.11.0+solana.1.16.19" +source = "git+https://github.com/rpcpool/yellowstone-grpc.git?tag=v1.11.1+solana.1.16.19#8b8618dd19d70ed58b942021768d826e31408cd8" +dependencies = [ + "anyhow", + "bincode", + "prost", + "protobuf-src", + "solana-account-decoder", + "solana-sdk", + "solana-transaction-status", + "tonic", + "tonic-build", +] + +[[package]] +name = "yellowstone-grpc-tools" +version = "1.0.0-rc.7+solana.1.16.19" +source = "git+https://github.com/rpcpool/yellowstone-grpc.git?tag=v1.11.1+solana.1.16.19#8b8618dd19d70ed58b942021768d826e31408cd8" +dependencies = [ + "anyhow", + "async-trait", + "atty", + "cargo-lock", + "clap 4.4.8", + "futures", + "git-version", + "hyper", + "json5", + "lazy_static", + "prometheus", + "serde", + "serde_json", + "serde_yaml", + "tokio", + "tokio-stream", + "tonic", + "tonic-health", + "tracing", + "tracing-subscriber", + "vergen", + "yellowstone-grpc-client", + "yellowstone-grpc-proto", +] + [[package]] name = "zeroize" version = "1.3.0" diff --git a/Cargo.toml b/Cargo.toml index 5c31592f1..50ac5c3f3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,7 @@ members = [ "metaplex-rpc-proxy", "migration", "nft_ingester", + "nft_ingester2", "program_transformers", "tools/acc_forwarder", "tools/bgtask_creator", @@ -27,11 +28,13 @@ anchor-lang = "0.28.0" anyhow = "1.0.75" async-std = "1.0.0" async-trait = "0.1.60" +atty = "0.2.14" blockbuster = "0.9.0-beta.1" borsh = "~0.10.3" bs58 = "0.4.0" cadence = "0.29.0" cadence-macros = "0.29.0" +cargo-lock = "9.0.0" chrono = "0.4.19" clap = "4.2.2" digital_asset_types = { path = "digital_asset_types" } @@ -40,9 +43,11 @@ env_logger = "0.10.0" figment = "0.10.8" flatbuffers = "23.1.21" futures = "0.3.28" +git-version = "0.3.5" hex = "0.4.3" hyper = "0.14.23" indexmap = "1.9.3" +json5 = "0.4.1" jsonpath_lib = "0.3.0" jsonrpsee = "0.16.2" lazy_static = "1.4.0" @@ -54,6 +59,9 @@ nft_ingester = { path = "nft_ingester" } num-traits = "0.2.15" open-rpc-derive = "0.0.4" open-rpc-schema = "0.0.4" +opentelemetry = "0.21.0" +opentelemetry-jaeger = "0.20.0" +opentelemetry_sdk = "0.21.1" plerkle_messenger = "1.6.0" plerkle_serialization = "1.6.0" program_transformers = { path = "program_transformers" } @@ -71,11 +79,12 @@ sea-orm-migration = "0.10.6" sea-query = "0.28.1" serde = "1.0.137" serde_json = "1.0.81" -solana-account-decoder = "~1.16.16" -solana-client = "~1.16.16" -solana-program = "~1.16.16" -solana-sdk = "~1.16.16" -solana-transaction-status = "~1.16.16" +serde_yaml = "0.9.27" +solana-account-decoder = "=1.16.19" +solana-client = "=1.16.19" +solana-program = "=1.16.19" +solana-sdk = "=1.16.19" +solana-transaction-status = "=1.16.19" spl-account-compression = "0.2.0" spl-associated-token-account = ">= 1.1.3, < 3.0" spl-concurrent-merkle-tree = "0.2.0" @@ -89,9 +98,14 @@ tokio-stream = "0.1.14" tower = "0.4.13" tower-http = "0.3.5" tracing = "0.1.35" +tracing-opentelemetry = "0.22.0" tracing-subscriber = "0.3.16" txn_forwarder = { path = "tools/txn_forwarder" } url = "2.3.1" +vergen = "8.2.1" +yellowstone-grpc-client = { git = "https://github.com/rpcpool/yellowstone-grpc.git", tag = "v1.11.1+solana.1.16.19" } # tag is geyser plugin +yellowstone-grpc-proto = { git = "https://github.com/rpcpool/yellowstone-grpc.git", tag = "v1.11.1+solana.1.16.19" } # tag is geyser plugin +yellowstone-grpc-tools = { git = "https://github.com/rpcpool/yellowstone-grpc.git", tag = "v1.11.1+solana.1.16.19", default-features = false } # tag is geyser plugin [patch.crates-io] blockbuster = { git = "https://github.com/rpcpool/blockbuster.git", tag = "blockbuster-rm-plerkle-v0.9.0-beta.1" } diff --git a/nft_ingester/Cargo.toml b/nft_ingester/Cargo.toml index e310cc647..1bba7556b 100644 --- a/nft_ingester/Cargo.toml +++ b/nft_ingester/Cargo.toml @@ -38,7 +38,7 @@ sqlx = { workspace = true, features = ["macros", "runtime-tokio-rustls", "postgr stretto = { workspace = true, features = ["async"] } thiserror = { workspace = true } tokio = { workspace = true, features = ["tracing"] } -tracing-subscriber = { workspace = true, features = ["json", "env-filter", "ansi"] } +tracing-subscriber = { workspace = true } url = { workspace = true } [lints] diff --git a/nft_ingester2/Cargo.toml b/nft_ingester2/Cargo.toml new file mode 100644 index 000000000..f665f07d7 --- /dev/null +++ b/nft_ingester2/Cargo.toml @@ -0,0 +1,39 @@ +[package] +name = "nft_ingester2" +version = { workspace = true } +edition = { workspace = true } +repository = { workspace = true } +publish = { workspace = true } + +[dependencies] +anyhow = { workspace = true } +atty = { workspace = true } +clap = { workspace = true, features = ["cargo", "derive"] } +futures = { workspace = true } +hyper = { workspace = true, features = ["server"] } +json5 = { workspace = true } +lazy_static = { workspace = true } +opentelemetry = { workspace = true } +opentelemetry-jaeger = { workspace = true, features = ["rt-tokio"] } +opentelemetry_sdk = { workspace = true, features = ["trace"] } +prometheus = { workspace = true } +redis = { workspace = true, features = ["tokio-comp", "tokio-native-tls-comp"] } +serde = { workspace = true } +serde_yaml = { workspace = true } +solana-sdk = { workspace = true } # only prom rn +tokio = { workspace = true, features = ["rt-multi-thread", "macros", "time", "fs", "tracing"] } +tracing = { workspace = true } +tracing-opentelemetry = { workspace = true } +tracing-subscriber = { workspace = true, features = ["env-filter", "json"] } +yellowstone-grpc-client = { workspace = true } +yellowstone-grpc-proto = { workspace = true } +yellowstone-grpc-tools = { workspace = true } + +[build-dependencies] +anyhow = { workspace = true } +cargo-lock = { workspace = true } +git-version = { workspace = true } +vergen = { workspace = true, features = ["build", "rustc"] } + +[lints] +workspace = true diff --git a/nft_ingester2/build.rs b/nft_ingester2/build.rs new file mode 100644 index 000000000..92e1f4c7c --- /dev/null +++ b/nft_ingester2/build.rs @@ -0,0 +1,38 @@ +use {cargo_lock::Lockfile, std::collections::HashSet}; + +fn main() -> anyhow::Result<()> { + let mut envs = vergen::EmitBuilder::builder(); + envs.all_build().all_rustc(); + envs.emit()?; + + // vergen git version does not looks cool + println!( + "cargo:rustc-env=GIT_VERSION={}", + git_version::git_version!() + ); + + // Extract packages version + let lockfile = Lockfile::load("../Cargo.lock")?; + println!( + "cargo:rustc-env=SOLANA_SDK_VERSION={}", + get_pkg_version(&lockfile, "solana-sdk") + ); + println!( + "cargo:rustc-env=YELLOWSTONE_GRPC_PROTO_VERSION={}", + get_pkg_version(&lockfile, "yellowstone-grpc-proto") + ); + + Ok(()) +} + +fn get_pkg_version(lockfile: &Lockfile, pkg_name: &str) -> String { + lockfile + .packages + .iter() + .filter(|pkg| pkg.name.as_str() == pkg_name) + .map(|pkg| pkg.version.to_string()) + .collect::>() + .into_iter() + .collect::>() + .join(",") +} diff --git a/nft_ingester2/config-grpc2redis.yml b/nft_ingester2/config-grpc2redis.yml new file mode 100644 index 000000000..73ed908f4 --- /dev/null +++ b/nft_ingester2/config-grpc2redis.yml @@ -0,0 +1,24 @@ +prometheus: 127.0.0.1:8873 +endpoint: http://127.0.0.1:10000 +x_token: null +commitment: processed +accounts: + stream: ACCOUNTS + stream_maxlen: 100_000_000 + stream_data_key: data + filters: + - owner: + - TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA + - metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s +transactions: + stream: TRANSACTIONS + stream_maxlen: 10_000_000 + stream_data_key: data + filters: + - account_include: + - BGUMAp9Gq7iTEuizy4pqaxsTyUCBK68MDfK752saRPUY +redis: + url: redis://localhost:6379 + pipeline_max_size: 10 + pipeline_max_idle_ms: 10 + max_xadd_in_process: 100 diff --git a/nft_ingester2/src/config.rs b/nft_ingester2/src/config.rs new file mode 100644 index 000000000..a5e0a0fe4 --- /dev/null +++ b/nft_ingester2/src/config.rs @@ -0,0 +1,180 @@ +use { + anyhow::Context, + serde::{de, Deserialize}, + std::{collections::HashMap, net::SocketAddr, path::Path, time::Duration}, + tokio::fs, + yellowstone_grpc_proto::prelude::SubscribeRequest, + yellowstone_grpc_tools::config::{ + deserialize_usize_str, ConfigGrpcRequestAccounts, ConfigGrpcRequestCommitment, + ConfigGrpcRequestTransactions, GrpcRequestToProto, + }, +}; + +pub const REDIS_STREAM_ACCOUNTS: &str = "ACCOUNTS"; +pub const REDIS_STREAM_TRANSACTIONS: &str = "TRANSACTIONS"; + +pub async fn load(path: impl AsRef + Copy) -> anyhow::Result +where + T: de::DeserializeOwned, +{ + let text = fs::read_to_string(path) + .await + .context("failed to read config from file")?; + + match path.as_ref().extension().and_then(|e| e.to_str()) { + Some("yaml") | Some("yml") => { + serde_yaml::from_str(&text).context("failed to parse config from YAML file") + } + Some("json") => json5::from_str(&text).context("failed to parse config from JSON file"), + value => anyhow::bail!("unknown config extension: {value:?}"), + } +} + +#[derive(Debug, Default, Deserialize)] +#[serde(default)] +pub struct ConfigPrometheus { + pub prometheus: Option, +} + +#[derive(Debug, Deserialize)] +pub struct ConfigGrpc { + pub endpoint: String, + pub x_token: Option, + + pub commitment: ConfigGrpcRequestCommitment, + pub accounts: ConfigGrpcAccounts, + pub transactions: ConfigGrpcTransactions, + + pub redis: ConfigGrpcRedis, +} + +impl ConfigGrpc { + pub fn create_subscribe_request(&self) -> SubscribeRequest { + let mut accounts = HashMap::new(); + for (i, item) in self.accounts.filters.iter().enumerate() { + accounts.insert(i.to_string(), item.clone().to_proto()); + } + + let mut transactions = HashMap::new(); + for (i, item) in self.transactions.filters.iter().enumerate() { + transactions.insert(i.to_string(), item.clone().to_proto()); + } + + SubscribeRequest { + slots: HashMap::new(), + accounts, + transactions, + entry: HashMap::new(), + blocks: HashMap::new(), + blocks_meta: HashMap::new(), + commitment: Some(self.commitment.to_proto() as i32), + accounts_data_slice: vec![], + ping: None, + } + } +} + +#[derive(Debug, Deserialize)] +pub struct ConfigGrpcAccounts { + #[serde(default = "ConfigGrpcAccounts::default_stream")] + pub stream: String, + #[serde( + default = "ConfigGrpcAccounts::default_stream_maxlen", + deserialize_with = "deserialize_usize_str" + )] + pub stream_maxlen: usize, + #[serde(default = "ConfigGrpcAccounts::default_stream_data_key")] + pub stream_data_key: String, + + pub filters: Vec, +} + +impl ConfigGrpcAccounts { + pub fn default_stream() -> String { + REDIS_STREAM_ACCOUNTS.to_owned() + } + + pub const fn default_stream_maxlen() -> usize { + 100_000_000 + } + + pub fn default_stream_data_key() -> String { + "data".to_owned() + } +} + +#[derive(Debug, Deserialize)] +pub struct ConfigGrpcTransactions { + #[serde(default = "ConfigGrpcTransactions::default_stream")] + pub stream: String, + #[serde( + default = "ConfigGrpcTransactions::default_stream_maxlen", + deserialize_with = "deserialize_usize_str" + )] + pub stream_maxlen: usize, + #[serde(default = "ConfigGrpcTransactions::default_stream_data_key")] + pub stream_data_key: String, + + pub filters: Vec, +} + +impl ConfigGrpcTransactions { + pub fn default_stream() -> String { + REDIS_STREAM_TRANSACTIONS.to_owned() + } + + pub const fn default_stream_maxlen() -> usize { + 10_000_000 + } + + pub fn default_stream_data_key() -> String { + "data".to_owned() + } +} + +#[derive(Debug, Deserialize)] +pub struct ConfigGrpcRedis { + pub url: String, + #[serde( + default = "ConfigGrpcRedis::default_pipeline_max_size", + deserialize_with = "deserialize_usize_str" + )] + pub pipeline_max_size: usize, + #[serde( + default = "ConfigGrpcRedis::default_pipeline_max_idle_ms", + deserialize_with = "deserialize_duration_str" + )] + pub pipeline_max_idle_ms: Duration, + #[serde( + default = "ConfigGrpcRedis::max_xadd_in_process", + deserialize_with = "deserialize_usize_str" + )] + pub max_xadd_in_process: usize, +} + +impl ConfigGrpcRedis { + pub const fn default_pipeline_max_size() -> usize { + 10 + } + + pub const fn default_pipeline_max_idle_ms() -> Duration { + Duration::from_millis(10) + } + + pub const fn max_xadd_in_process() -> usize { + 100 + } +} + +pub fn deserialize_duration_str<'de, D>(deserializer: D) -> Result +where + D: de::Deserializer<'de>, +{ + let ms = deserialize_usize_str(deserializer)?; + Ok(Duration::from_millis(ms as u64)) +} + +#[derive(Debug, Deserialize)] +pub struct ConfigIngester { + // +} diff --git a/nft_ingester2/src/grpc.rs b/nft_ingester2/src/grpc.rs new file mode 100644 index 000000000..20ffb6d7e --- /dev/null +++ b/nft_ingester2/src/grpc.rs @@ -0,0 +1,151 @@ +use { + crate::{ + config::ConfigGrpc, prom::redis_xadd_status_inc, redis::metrics_xlen, util::create_shutdown, + }, + anyhow::Context, + futures::stream::StreamExt, + redis::{streams::StreamMaxlen, RedisResult, Value as RedisValue}, + std::{sync::Arc, time::Duration}, + tokio::{ + signal::unix::SignalKind, + task::JoinSet, + time::{sleep, Instant}, + }, + yellowstone_grpc_client::GeyserGrpcClient, + yellowstone_grpc_proto::{prelude::subscribe_update::UpdateOneof, prost::Message}, +}; + +pub async fn run(config: ConfigGrpc) -> anyhow::Result<()> { + let config = Arc::new(config); + + // Connect to Redis + let client = redis::Client::open(config.redis.url.clone())?; + let connection = client.get_multiplexed_tokio_connection().await?; + + // Check stream length for the metrics + let jh_metrics_xlen = tokio::spawn({ + let connection = connection.clone(); + let streams = vec![ + config.accounts.stream.clone(), + config.transactions.stream.clone(), + ]; + async move { metrics_xlen(connection, &streams).await } + }); + tokio::pin!(jh_metrics_xlen); + + // Create gRPC client, subscribe and handle messages + let mut client = GeyserGrpcClient::connect_with_timeout( + config.endpoint.clone(), + config.x_token.clone(), + None, + Some(Duration::from_secs(10)), + Some(Duration::from_secs(5)), + false, + ) + .await + .context("failed to connect go gRPC")?; + let mut geyser = client + .subscribe_once2(config.create_subscribe_request()) + .await?; + + // recv-send loop + let mut shutdown = create_shutdown()?; + let mut pipe = redis::pipe(); + let mut pipe_accounts = 0; + let mut pipe_transactions = 0; + let deadline = sleep(config.redis.pipeline_max_idle_ms); + tokio::pin!(deadline); + let mut tasks = JoinSet::new(); + + let result = loop { + tokio::select! { + biased; + result = &mut jh_metrics_xlen => match result { + Ok(Ok(_)) => unreachable!(), + Ok(Err(error)) => break Err(error), + Err(error) => break Err(error.into()), + }, + signal = &mut shutdown => { + let signal = if signal == SignalKind::interrupt() { + "SIGINT" + } else if signal == SignalKind::terminate() { + "SIGTERM" + } else { + "UNKNOWN" + }; + tracing::warn!("{signal} received, waiting spawned tasks..."); + break Ok(()); + }, + msg = geyser.next() => { + match msg { + Some(Ok(msg)) => match msg.update_oneof { + Some(UpdateOneof::Account(account)) => { + pipe.xadd_maxlen( + &config.accounts.stream, + StreamMaxlen::Approx(config.accounts.stream_maxlen), + "*", + &[(&config.accounts.stream_data_key, account.encode_to_vec())], + ); + pipe_accounts += 1; + } + Some(UpdateOneof::Slot(_)) => continue, + Some(UpdateOneof::Transaction(transaction)) => { + pipe.xadd_maxlen( + &config.transactions.stream, + StreamMaxlen::Approx(config.transactions.stream_maxlen), + "*", + &[(&config.transactions.stream_data_key, transaction.encode_to_vec())] + ); + pipe_transactions += 1; + } + Some(UpdateOneof::Block(_)) => continue, + Some(UpdateOneof::Ping(_)) => continue, + Some(UpdateOneof::Pong(_)) => continue, + Some(UpdateOneof::BlockMeta(_)) => continue, + Some(UpdateOneof::Entry(_)) => continue, + None => break Err(anyhow::anyhow!("received invalid update gRPC message")), + }, + Some(Err(error)) => break Err(error.into()), + None => break Err(anyhow::anyhow!("geyser gRPC request is finished")), + }; + if pipe_accounts + pipe_transactions < config.redis.pipeline_max_size { + continue; + } + }, + _ = &mut deadline => {}, + }; + + let mut pipe = std::mem::replace(&mut pipe, redis::pipe()); + let pipe_accounts = std::mem::replace(&mut pipe_accounts, 0); + let pipe_transactions = std::mem::replace(&mut pipe_transactions, 0); + deadline + .as_mut() + .reset(Instant::now() + config.redis.pipeline_max_idle_ms); + + tasks.spawn({ + let mut connection = connection.clone(); + let config = Arc::clone(&config); + async move { + let result: RedisResult = + pipe.atomic().query_async(&mut connection).await; + + let status = if result.is_ok() { Ok(()) } else { Err(()) }; + redis_xadd_status_inc(&config.accounts.stream, status, pipe_accounts); + redis_xadd_status_inc(&config.transactions.stream, status, pipe_transactions); + + Ok::<(), anyhow::Error>(()) + } + }); + while tasks.len() >= config.redis.max_xadd_in_process { + if let Some(result) = tasks.join_next().await { + result??; + } + } + }; + + while let Some(result) = tasks.join_next().await { + result??; + } + + result +} diff --git a/nft_ingester2/src/ingester.rs b/nft_ingester2/src/ingester.rs new file mode 100644 index 000000000..475769af2 --- /dev/null +++ b/nft_ingester2/src/ingester.rs @@ -0,0 +1,5 @@ +use crate::config::ConfigIngester; + +pub async fn run(_config: ConfigIngester) -> anyhow::Result<()> { + todo!() +} diff --git a/nft_ingester2/src/main.rs b/nft_ingester2/src/main.rs new file mode 100644 index 000000000..7b72c18a9 --- /dev/null +++ b/nft_ingester2/src/main.rs @@ -0,0 +1,75 @@ +use { + crate::{ + config::{load as config_load, ConfigGrpc, ConfigIngester, ConfigPrometheus}, + prom::run_server as prometheus_run_server, + tracing::init as tracing_init, + }, + anyhow::Context, + clap::{Parser, Subcommand}, + std::net::SocketAddr, +}; + +mod config; +mod grpc; +mod ingester; +mod prom; +mod redis; +mod tracing; +mod util; +mod version; + +#[derive(Debug, Parser)] +#[clap(author, version)] +struct Args { + /// Path to config file + #[clap(short, long)] + config: String, + + /// Prometheus listen address + #[clap(long)] + prometheus: Option, + + #[command(subcommand)] + action: ArgsAction, +} + +#[derive(Debug, Clone, Subcommand)] +enum ArgsAction { + /// Subscribe on Geyser events using gRPC and send them to Redis + #[command(name = "grpc2redis")] + Grpc, + /// Run ingester process (process events from Redis) + #[command(name = "run")] + Ingester, +} + +#[tokio::main] +async fn main() -> anyhow::Result<()> { + tracing_init()?; + + let args = Args::parse(); + + // Run prometheus server + let config = config_load::(&args.config) + .await + .with_context(|| format!("failed to parse prometheus config from: {}", args.config))?; + if let Some(address) = args.prometheus.or(config.prometheus) { + prometheus_run_server(address)?; + } + + // Run grpc / ingester + match args.action { + ArgsAction::Grpc => { + let config = config_load::(&args.config) + .await + .with_context(|| format!("failed to parse config from: {}", args.config))?; + grpc::run(config).await + } + ArgsAction::Ingester => { + let config = config_load::(&args.config) + .await + .with_context(|| format!("failed to parse config from: {}", args.config))?; + ingester::run(config).await + } + } +} diff --git a/nft_ingester2/src/prom.rs b/nft_ingester2/src/prom.rs new file mode 100644 index 000000000..bf24a984a --- /dev/null +++ b/nft_ingester2/src/prom.rs @@ -0,0 +1,106 @@ +use { + crate::version::VERSION as VERSION_INFO, + hyper::{ + server::conn::AddrStream, + service::{make_service_fn, service_fn}, + Body, Request, Response, Server, StatusCode, + }, + prometheus::{IntCounterVec, IntGaugeVec, Opts, Registry, TextEncoder}, + std::{net::SocketAddr, sync::Once}, + tracing::{error, info}, +}; + +lazy_static::lazy_static! { + static ref REGISTRY: Registry = Registry::new(); + + static ref VERSION: IntCounterVec = IntCounterVec::new( + Opts::new("version", "Plugin version info"), + &["buildts", "git", "package", "proto", "rustc", "solana", "version"] + ).unwrap(); + + static ref REDIS_STREAM_LEN: IntGaugeVec = IntGaugeVec::new( + Opts::new("redis_stream_len", "Length of stream in Redis"), + &["stream"] + ).unwrap(); + + static ref REDIS_XADD_STATUS: IntCounterVec = IntCounterVec::new( + Opts::new("redis_xadd_status", "Status of messages sent to Redis stream"), + &["stream", "status"] + ).unwrap(); +} + +pub fn run_server(address: SocketAddr) -> anyhow::Result<()> { + static REGISTER: Once = Once::new(); + REGISTER.call_once(|| { + macro_rules! register { + ($collector:ident) => { + REGISTRY + .register(Box::new($collector.clone())) + .expect("collector can't be registered"); + }; + } + register!(VERSION); + register!(REDIS_STREAM_LEN); + register!(REDIS_XADD_STATUS); + + VERSION + .with_label_values(&[ + VERSION_INFO.buildts, + VERSION_INFO.git, + VERSION_INFO.package, + VERSION_INFO.proto, + VERSION_INFO.rustc, + VERSION_INFO.solana, + VERSION_INFO.version, + ]) + .inc(); + }); + + let make_service = make_service_fn(move |_: &AddrStream| async move { + Ok::<_, hyper::Error>(service_fn(move |req: Request| async move { + let response = match req.uri().path() { + "/metrics" => metrics_handler(), + _ => not_found_handler(), + }; + Ok::<_, hyper::Error>(response) + })) + }); + let server = Server::try_bind(&address)?.serve(make_service); + info!("prometheus server started: {address:?}"); + tokio::spawn(async move { + if let Err(error) = server.await { + error!("prometheus server failed: {error:?}"); + } + }); + + Ok(()) +} + +fn metrics_handler() -> Response { + let metrics = TextEncoder::new() + .encode_to_string(®ISTRY.gather()) + .unwrap_or_else(|error| { + error!("could not encode custom metrics: {}", error); + String::new() + }); + Response::builder().body(Body::from(metrics)).unwrap() +} + +fn not_found_handler() -> Response { + Response::builder() + .status(StatusCode::NOT_FOUND) + .body(Body::empty()) + .unwrap() +} + +pub fn redis_stream_len_set(stream: &str, len: usize) { + REDIS_STREAM_LEN + .with_label_values(&[stream]) + .set(len as i64); +} + +pub fn redis_xadd_status_inc(stream: &str, status: Result<(), ()>, delta: usize) { + REDIS_XADD_STATUS + .with_label_values(&[stream, if status.is_ok() { "success" } else { "failed" }]) + .inc_by(delta as u64); +} diff --git a/nft_ingester2/src/redis.rs b/nft_ingester2/src/redis.rs new file mode 100644 index 000000000..9e1c16ca4 --- /dev/null +++ b/nft_ingester2/src/redis.rs @@ -0,0 +1,25 @@ +use { + crate::prom::redis_stream_len_set, + redis::AsyncCommands, + std::convert::Infallible, + tokio::time::{sleep, Duration}, +}; + +pub async fn metrics_xlen( + mut connection: C, + streams: &[String], +) -> anyhow::Result { + loop { + let mut pipe = redis::pipe(); + for stream in streams { + pipe.xlen(stream); + } + let xlens: Vec = pipe.query_async(&mut connection).await?; + + for (stream, xlen) in streams.iter().zip(xlens.into_iter()) { + redis_stream_len_set(stream, xlen); + } + + sleep(Duration::from_millis(100)).await; + } +} diff --git a/nft_ingester2/src/tracing.rs b/nft_ingester2/src/tracing.rs new file mode 100644 index 000000000..36ba4db56 --- /dev/null +++ b/nft_ingester2/src/tracing.rs @@ -0,0 +1,32 @@ +use { + opentelemetry_sdk::trace::{self, Sampler}, + std::env, + tracing_subscriber::{filter::EnvFilter, layer::SubscriberExt, util::SubscriberInitExt}, +}; + +pub fn init() -> anyhow::Result<()> { + let open_tracer = opentelemetry_jaeger::new_agent_pipeline() + .with_service_name(env::var("CARGO_PKG_NAME")?) + .with_auto_split_batch(true) + .with_trace_config(trace::config().with_sampler(Sampler::TraceIdRatioBased(0.25))) + .install_batch(opentelemetry_sdk::runtime::Tokio)?; + let jeager_layer = tracing_opentelemetry::layer().with_tracer(open_tracer); + + let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info")); + + let is_atty = atty::is(atty::Stream::Stdout) && atty::is(atty::Stream::Stderr); + let io_layer = tracing_subscriber::fmt::layer().with_ansi(is_atty); + + let registry = tracing_subscriber::registry() + .with(jeager_layer) + .with(env_filter) + .with(io_layer); + + if env::var_os("RUST_LOG_JSON").is_some() { + let json_layer = tracing_subscriber::fmt::layer().json().flatten_event(true); + registry.with(json_layer).try_init() + } else { + registry.try_init() + } + .map_err(Into::into) +} diff --git a/nft_ingester2/src/util.rs b/nft_ingester2/src/util.rs new file mode 100644 index 000000000..6de97e42f --- /dev/null +++ b/nft_ingester2/src/util.rs @@ -0,0 +1,16 @@ +use { + futures::future::{BoxFuture, FutureExt}, + tokio::signal::unix::{signal, SignalKind}, +}; + +pub fn create_shutdown() -> anyhow::Result> { + let mut sigint = signal(SignalKind::interrupt())?; + let mut sigterm = signal(SignalKind::terminate())?; + Ok(async move { + tokio::select! { + _ = sigint.recv() => SignalKind::interrupt(), + _ = sigterm.recv() => SignalKind::terminate(), + } + } + .boxed()) +} diff --git a/nft_ingester2/src/version.rs b/nft_ingester2/src/version.rs new file mode 100644 index 000000000..b9da62845 --- /dev/null +++ b/nft_ingester2/src/version.rs @@ -0,0 +1,22 @@ +use {serde::Serialize, std::env}; + +#[derive(Debug, Serialize)] +pub struct Version { + pub package: &'static str, + pub version: &'static str, + pub proto: &'static str, + pub solana: &'static str, + pub git: &'static str, + pub rustc: &'static str, + pub buildts: &'static str, +} + +pub const VERSION: Version = Version { + package: env!("CARGO_PKG_NAME"), + version: env!("CARGO_PKG_VERSION"), + proto: env!("YELLOWSTONE_GRPC_PROTO_VERSION"), + solana: env!("SOLANA_SDK_VERSION"), + git: env!("GIT_VERSION"), + rustc: env!("VERGEN_RUSTC_SEMVER"), + buildts: env!("VERGEN_BUILD_TIMESTAMP"), +}; diff --git a/tools/tree-status/Cargo.toml b/tools/tree-status/Cargo.toml index 64cd02e30..44b760aab 100644 --- a/tools/tree-status/Cargo.toml +++ b/tools/tree-status/Cargo.toml @@ -15,7 +15,7 @@ clap = { workspace = true, features = ["derive"] } digital_asset_types = { workspace = true } env_logger = { workspace = true } futures = { workspace = true } -hex = { worksspace = true } +hex = { workspace = true } lazy_static = { workspace = true } log = { workspace = true } prometheus = { workspace = true } From 36971613991f4148706f9fdca3878e588dce8743 Mon Sep 17 00:00:00 2001 From: Kirill Fomichev Date: Mon, 27 Nov 2023 21:29:06 -0500 Subject: [PATCH 18/23] add redis streaming for ingester --- nft_ingester2/README.md | 33 +++ nft_ingester2/config-run.yml | 19 ++ nft_ingester2/src/config.rs | 148 +++++++++++++- nft_ingester2/src/grpc.rs | 5 +- nft_ingester2/src/ingester.rs | 75 ++++++- nft_ingester2/src/main.rs | 1 + nft_ingester2/src/postgres.rs | 1 + nft_ingester2/src/prom.rs | 22 +- nft_ingester2/src/redis.rs | 375 +++++++++++++++++++++++++++++++++- 9 files changed, 654 insertions(+), 25 deletions(-) create mode 100644 nft_ingester2/README.md create mode 100644 nft_ingester2/config-run.yml create mode 100644 nft_ingester2/src/postgres.rs diff --git a/nft_ingester2/README.md b/nft_ingester2/README.md new file mode 100644 index 000000000..a2afa2226 --- /dev/null +++ b/nft_ingester2/README.md @@ -0,0 +1,33 @@ +## Dev process + +### geyser gRPC source + +Use [Triton One](https://triton.one/) provided endpoint or run own node with geyser plugin: https://github.com/rpcpool/yellowstone-grpc + +### Redis server + +``` +redis-server +``` + +### PostgreSQL server + +Run: + +``` +docker run -it --rm -e POSTGRES_PASSWORD=solana -e POSTGRES_USER=solana -e POSTGRES_DB=solana -p 5432:5432 postgres +``` + +Schema: + +> Also note: The migration `m20230224_093722_performance_improvements` needs to be commented out of the migration lib.rs in order for the Sea ORM `Relations` to generate correctly. + +``` +DATABASE_URL=postgres://solana:solana@localhost/solana INIT_FILE_PATH=init.sql cargo run -p migration --bin migration -- up +``` + +psql: + +``` +PGPASSWORD=solana psql -h localhost -U solana -d solana +``` diff --git a/nft_ingester2/config-run.yml b/nft_ingester2/config-run.yml new file mode 100644 index 000000000..281f6a1fd --- /dev/null +++ b/nft_ingester2/config-run.yml @@ -0,0 +1,19 @@ +prometheus: 127.0.0.1:8874 +redis: + url: redis://localhost:6379 + group: ingester + consumer: consumer # every new ingester instance should uniq name + streams: + - type: account # possible values: `account` and `transaction`, required for message decoding + stream: ACCOUNTS + data_key: data + - type: transaction + stream: TRANSACTIONS + data_key: data + xack_batch_max_size: 100 + xack_batch_max_idle_ms: 10 + xack_max_in_process: 100 + prefetch_queue_size: 1_000 # max number of messages available in the read queue for processing + xpending_max: 250 # used for reading pending messages + xpending_only: false # exit once all pending messages consumed (should be applied if you want downscale number of ingesters) + xreadgroup_max: 1_000 # applied per each stream in one request diff --git a/nft_ingester2/src/config.rs b/nft_ingester2/src/config.rs index a5e0a0fe4..39f3eaba3 100644 --- a/nft_ingester2/src/config.rs +++ b/nft_ingester2/src/config.rs @@ -12,6 +12,7 @@ use { pub const REDIS_STREAM_ACCOUNTS: &str = "ACCOUNTS"; pub const REDIS_STREAM_TRANSACTIONS: &str = "TRANSACTIONS"; +pub const REDIS_STREAM_DATA_KEY: &str = "data"; pub async fn load(path: impl AsRef + Copy) -> anyhow::Result where @@ -99,7 +100,7 @@ impl ConfigGrpcAccounts { } pub fn default_stream_data_key() -> String { - "data".to_owned() + REDIS_STREAM_DATA_KEY.to_owned() } } @@ -128,7 +129,7 @@ impl ConfigGrpcTransactions { } pub fn default_stream_data_key() -> String { - "data".to_owned() + REDIS_STREAM_DATA_KEY.to_owned() } } @@ -141,12 +142,13 @@ pub struct ConfigGrpcRedis { )] pub pipeline_max_size: usize, #[serde( - default = "ConfigGrpcRedis::default_pipeline_max_idle_ms", - deserialize_with = "deserialize_duration_str" + default = "ConfigGrpcRedis::default_pipeline_max_idle", + deserialize_with = "deserialize_duration_str", + rename = "pipeline_max_idle_ms" )] - pub pipeline_max_idle_ms: Duration, + pub pipeline_max_idle: Duration, #[serde( - default = "ConfigGrpcRedis::max_xadd_in_process", + default = "ConfigGrpcRedis::default_max_xadd_in_process", deserialize_with = "deserialize_usize_str" )] pub max_xadd_in_process: usize, @@ -157,11 +159,11 @@ impl ConfigGrpcRedis { 10 } - pub const fn default_pipeline_max_idle_ms() -> Duration { + pub const fn default_pipeline_max_idle() -> Duration { Duration::from_millis(10) } - pub const fn max_xadd_in_process() -> usize { + pub const fn default_max_xadd_in_process() -> usize { 100 } } @@ -176,5 +178,133 @@ where #[derive(Debug, Deserialize)] pub struct ConfigIngester { - // + pub redis: ConfigIngesterRedis, +} + +#[derive(Debug, Deserialize)] +pub struct ConfigIngesterRedis { + pub url: String, + #[serde(default = "ConfigIngesterRedis::default_group")] + pub group: String, + #[serde(default = "ConfigIngesterRedis::default_consumer")] + pub consumer: String, + pub streams: Vec, + #[serde( + default = "ConfigIngesterRedis::default_prefetch_queue_size", + deserialize_with = "deserialize_usize_str" + )] + pub prefetch_queue_size: usize, + #[serde( + default = "ConfigIngesterRedis::default_xpending_max", + deserialize_with = "deserialize_usize_str" + )] + pub xpending_max: usize, + #[serde(default = "ConfigIngesterRedis::default_xpending_only")] + pub xpending_only: bool, + #[serde( + default = "ConfigIngesterRedis::default_xreadgroup_max", + deserialize_with = "deserialize_usize_str" + )] + pub xreadgroup_max: usize, +} + +impl ConfigIngesterRedis { + pub fn default_group() -> String { + "ingester".to_owned() + } + + pub fn default_consumer() -> String { + "consumer".to_owned() + } + + pub const fn default_prefetch_queue_size() -> usize { + 1_000 + } + + pub const fn default_xpending_max() -> usize { + 100 + } + + pub const fn default_xpending_only() -> bool { + false + } + + pub const fn default_xreadgroup_max() -> usize { + 1_000 + } +} + +#[derive(Debug, Clone)] +pub struct ConfigIngesterRedisStream { + pub stream_type: ConfigIngesterRedisStreamType, + pub stream: String, + pub data_key: String, + pub xack_batch_max_size: usize, + pub xack_batch_max_idle: Duration, + pub xack_max_in_process: usize, +} + +impl<'de> Deserialize<'de> for ConfigIngesterRedisStream { + fn deserialize(deserializer: D) -> Result + where + D: de::Deserializer<'de>, + { + #[derive(Debug, Deserialize)] + struct Raw { + #[serde(rename = "type")] + pub stream_type: ConfigIngesterRedisStreamType, + pub stream: Option, + pub data_key: Option, + #[serde( + default = "default_xack_batch_max_size", + deserialize_with = "deserialize_usize_str" + )] + pub xack_batch_max_size: usize, + #[serde( + default = "default_xack_batch_max_idle", + deserialize_with = "deserialize_duration_str", + rename = "xack_batch_max_idle_ms" + )] + pub xack_batch_max_idle: Duration, + #[serde( + default = "default_xack_max_in_process", + deserialize_with = "deserialize_usize_str" + )] + pub xack_max_in_process: usize, + } + + const fn default_xack_batch_max_size() -> usize { + 100 + } + + const fn default_xack_batch_max_idle() -> Duration { + Duration::from_millis(10) + } + + const fn default_xack_max_in_process() -> usize { + 100 + } + + let raw = Raw::deserialize(deserializer)?; + Ok(Self { + stream_type: raw.stream_type, + stream: raw.stream.unwrap_or_else(|| match raw.stream_type { + ConfigIngesterRedisStreamType::Account => REDIS_STREAM_ACCOUNTS.to_owned(), + ConfigIngesterRedisStreamType::Transaction => REDIS_STREAM_TRANSACTIONS.to_owned(), + }), + data_key: raw + .data_key + .unwrap_or_else(|| REDIS_STREAM_DATA_KEY.to_owned()), + xack_batch_max_size: raw.xack_batch_max_size, + xack_batch_max_idle: raw.xack_batch_max_idle, + xack_max_in_process: raw.xack_max_in_process, + }) + } +} + +#[derive(Debug, Deserialize, Clone, Copy, PartialEq, Eq)] +#[serde(rename_all = "lowercase")] +pub enum ConfigIngesterRedisStreamType { + Account, + Transaction, } diff --git a/nft_ingester2/src/grpc.rs b/nft_ingester2/src/grpc.rs index 20ffb6d7e..5ec284b1b 100644 --- a/nft_ingester2/src/grpc.rs +++ b/nft_ingester2/src/grpc.rs @@ -53,13 +53,12 @@ pub async fn run(config: ConfigGrpc) -> anyhow::Result<()> { let mut pipe = redis::pipe(); let mut pipe_accounts = 0; let mut pipe_transactions = 0; - let deadline = sleep(config.redis.pipeline_max_idle_ms); + let deadline = sleep(config.redis.pipeline_max_idle); tokio::pin!(deadline); let mut tasks = JoinSet::new(); let result = loop { tokio::select! { - biased; result = &mut jh_metrics_xlen => match result { Ok(Ok(_)) => unreachable!(), Ok(Err(error)) => break Err(error), @@ -120,7 +119,7 @@ pub async fn run(config: ConfigGrpc) -> anyhow::Result<()> { let pipe_transactions = std::mem::replace(&mut pipe_transactions, 0); deadline .as_mut() - .reset(Instant::now() + config.redis.pipeline_max_idle_ms); + .reset(Instant::now() + config.redis.pipeline_max_idle); tasks.spawn({ let mut connection = connection.clone(); diff --git a/nft_ingester2/src/ingester.rs b/nft_ingester2/src/ingester.rs index 475769af2..1e02e03ed 100644 --- a/nft_ingester2/src/ingester.rs +++ b/nft_ingester2/src/ingester.rs @@ -1,5 +1,74 @@ -use crate::config::ConfigIngester; +use { + crate::{ + config::ConfigIngester, + redis::{metrics_xlen, RedisStream}, + util::create_shutdown, + }, + futures::future::{Fuse, FusedFuture, FutureExt}, + tokio::signal::unix::SignalKind, +}; -pub async fn run(_config: ConfigIngester) -> anyhow::Result<()> { - todo!() +pub async fn run(config: ConfigIngester) -> anyhow::Result<()> { + println!("{:#?}", config); + + // connect to Redis + let client = redis::Client::open(config.redis.url.clone())?; + let connection = client.get_multiplexed_tokio_connection().await?; + + // check stream length for the metrics in spawned task + let jh_metrics_xlen = tokio::spawn({ + let connection = connection.clone(); + let streams = config + .redis + .streams + .iter() + .map(|config| config.stream.clone()) + .collect::>(); + async move { metrics_xlen(connection, &streams).await } + }); + tokio::pin!(jh_metrics_xlen); + + // create redis stream reader + let (mut redis_messages, redis_tasks) = RedisStream::new(config.redis, connection).await?; + let redis_tasks_fut = Fuse::terminated(); + tokio::pin!(redis_tasks_fut); + redis_tasks_fut.set(redis_tasks.fuse()); + + // read messages in the loop + let mut shutdown = create_shutdown()?; + let result = loop { + tokio::select! { + result = &mut jh_metrics_xlen => match result { + Ok(Ok(_)) => unreachable!(), + Ok(Err(error)) => break Err(error), + Err(error) => break Err(error.into()), + }, + signal = &mut shutdown => { + let signal = if signal == SignalKind::interrupt() { + "SIGINT" + } else if signal == SignalKind::terminate() { + "SIGTERM" + } else { + "UNKNOWN" + }; + tracing::warn!("{signal} received, waiting spawned tasks..."); + break Ok(()); + }, + result = &mut redis_tasks_fut => break result, + msg = redis_messages.recv() => match msg { + Some(msg) => { + // TODO: process messages here + msg.ack()?; + } + None => break Ok(()), + } + }; + }; + + redis_messages.shutdown(); + if !redis_tasks_fut.is_terminated() { + redis_tasks_fut.await?; + } + + result } diff --git a/nft_ingester2/src/main.rs b/nft_ingester2/src/main.rs index 7b72c18a9..0bd1f9b8d 100644 --- a/nft_ingester2/src/main.rs +++ b/nft_ingester2/src/main.rs @@ -12,6 +12,7 @@ use { mod config; mod grpc; mod ingester; +mod postgres; mod prom; mod redis; mod tracing; diff --git a/nft_ingester2/src/postgres.rs b/nft_ingester2/src/postgres.rs new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/nft_ingester2/src/postgres.rs @@ -0,0 +1 @@ + diff --git a/nft_ingester2/src/prom.rs b/nft_ingester2/src/prom.rs index bf24a984a..b6794b615 100644 --- a/nft_ingester2/src/prom.rs +++ b/nft_ingester2/src/prom.rs @@ -18,8 +18,8 @@ lazy_static::lazy_static! { &["buildts", "git", "package", "proto", "rustc", "solana", "version"] ).unwrap(); - static ref REDIS_STREAM_LEN: IntGaugeVec = IntGaugeVec::new( - Opts::new("redis_stream_len", "Length of stream in Redis"), + static ref REDIS_XLEN_TOTAL: IntGaugeVec = IntGaugeVec::new( + Opts::new("redis_xlen_total", "Length of stream in Redis"), &["stream"] ).unwrap(); @@ -27,6 +27,11 @@ lazy_static::lazy_static! { Opts::new("redis_xadd_status", "Status of messages sent to Redis stream"), &["stream", "status"] ).unwrap(); + + static ref REDIS_XACK_TOTAL: IntCounterVec = IntCounterVec::new( + Opts::new("redis_xack_total", "Total number of processed messages"), + &["stream"] + ).unwrap(); } pub fn run_server(address: SocketAddr) -> anyhow::Result<()> { @@ -40,8 +45,9 @@ pub fn run_server(address: SocketAddr) -> anyhow::Result<()> { }; } register!(VERSION); - register!(REDIS_STREAM_LEN); + register!(REDIS_XLEN_TOTAL); register!(REDIS_XADD_STATUS); + register!(REDIS_XACK_TOTAL); VERSION .with_label_values(&[ @@ -93,8 +99,8 @@ fn not_found_handler() -> Response { .unwrap() } -pub fn redis_stream_len_set(stream: &str, len: usize) { - REDIS_STREAM_LEN +pub fn redis_xlen_set(stream: &str, len: usize) { + REDIS_XLEN_TOTAL .with_label_values(&[stream]) .set(len as i64); } @@ -104,3 +110,9 @@ pub fn redis_xadd_status_inc(stream: &str, status: Result<(), ()>, delta: usize) .with_label_values(&[stream, if status.is_ok() { "success" } else { "failed" }]) .inc_by(delta as u64); } + +pub fn redis_xack_inc(stream: &str, delta: usize) { + REDIS_XACK_TOTAL + .with_label_values(&[stream]) + .inc_by(delta as u64) +} diff --git a/nft_ingester2/src/redis.rs b/nft_ingester2/src/redis.rs index 9e1c16ca4..47f4584f3 100644 --- a/nft_ingester2/src/redis.rs +++ b/nft_ingester2/src/redis.rs @@ -1,8 +1,34 @@ use { - crate::prom::redis_stream_len_set, - redis::AsyncCommands, - std::convert::Infallible, - tokio::time::{sleep, Duration}, + crate::{ + config::{ConfigIngesterRedis, ConfigIngesterRedisStreamType}, + prom::{redis_xack_inc, redis_xlen_set}, + }, + futures::future::{BoxFuture, FutureExt}, + redis::{ + aio::MultiplexedConnection, + streams::{ + StreamClaimReply, StreamId, StreamKey, StreamPendingCountReply, StreamReadOptions, + StreamReadReply, + }, + AsyncCommands, ErrorKind as RedisErrorKind, RedisResult, Value as RedisValue, + }, + std::{ + collections::HashMap, + convert::Infallible, + sync::{ + atomic::{AtomicBool, Ordering}, + Arc, + }, + }, + tokio::{ + sync::mpsc, + task::JoinSet, + time::{sleep, Duration, Instant}, + }, + yellowstone_grpc_proto::{ + prelude::{SubscribeUpdateAccount, SubscribeUpdateTransaction}, + prost::Message, + }, }; pub async fn metrics_xlen( @@ -17,9 +43,348 @@ pub async fn metrics_xlen( let xlens: Vec = pipe.query_async(&mut connection).await?; for (stream, xlen) in streams.iter().zip(xlens.into_iter()) { - redis_stream_len_set(stream, xlen); + redis_xlen_set(stream, xlen); } sleep(Duration::from_millis(100)).await; } } + +pub async fn xgroup_create( + connection: &mut C, + name: &str, + group: &str, + consumer: &str, +) -> anyhow::Result<()> { + let result: RedisResult = connection.xgroup_create_mkstream(name, group, "0").await; + if let Err(error) = result { + if !(error.kind() == RedisErrorKind::ExtensionError + && error.detail() == Some("Consumer Group name already exists") + && error.code() == Some("BUSYGROUP")) + { + return Err(error.into()); + } + } + + // XGROUP CREATECONSUMER key group consumer + redis::cmd("XGROUP") + .arg("CREATECONSUMER") + .arg(name) + .arg(group) + .arg(consumer) + .query_async(connection) + .await?; + + Ok(()) +} + +#[derive(Debug)] +struct RedisStreamInfo { + group: String, + consumer: String, + stream_name: String, + stream_type: ConfigIngesterRedisStreamType, + stream_data_key: String, + xack_batch_max_size: usize, + xack_batch_max_idle: Duration, + xack_max_in_process: usize, +} + +#[allow(clippy::large_enum_variant)] +#[derive(Debug)] +pub enum RedisStreamMessage { + Account(SubscribeUpdateAccount), + Transaction(SubscribeUpdateTransaction), +} + +#[derive(Debug)] +pub struct RedisStreamMessageInfo { + id: String, + data: RedisStreamMessage, + ack_tx: mpsc::UnboundedSender, +} + +impl RedisStreamMessageInfo { + fn parse( + stream: &RedisStreamInfo, + StreamId { id, map }: StreamId, + ack_tx: mpsc::UnboundedSender, + ) -> anyhow::Result { + let data = match map.get(&stream.stream_data_key) { + Some(RedisValue::Data(vec)) => match stream.stream_type { + ConfigIngesterRedisStreamType::Account => { + RedisStreamMessage::Account(SubscribeUpdateAccount::decode(vec.as_ref())?) + } + ConfigIngesterRedisStreamType::Transaction => RedisStreamMessage::Transaction( + SubscribeUpdateTransaction::decode(vec.as_ref())?, + ), + }, + Some(_) => anyhow::bail!( + "invalid data (key: {:?}) from stream {:?}", + stream.stream_data_key, + stream.stream_name + ), + None => anyhow::bail!( + "failed to get data (key: {:?}) from stream {:?}", + stream.stream_data_key, + stream.stream_name + ), + }; + Ok(Self { id, data, ack_tx }) + } + + pub fn ack(self) -> anyhow::Result<()> { + self.ack_tx + .send(self.id) + .map_err(|_error| anyhow::anyhow!("failed to send message to ack channel",)) + } +} + +#[derive(Debug)] +pub struct RedisStream { + shutdown: Arc, + messages_rx: mpsc::Receiver, +} + +impl RedisStream { + pub async fn new( + config: ConfigIngesterRedis, + mut connection: MultiplexedConnection, + ) -> anyhow::Result<(Self, BoxFuture<'static, anyhow::Result<()>>)> { + // create group with consumer per stream + for stream in config.streams.iter() { + xgroup_create( + &mut connection, + &stream.stream, + &config.group, + &config.consumer, + ) + .await?; + } + + // shutdown flag + let shutdown = Arc::new(AtomicBool::new(false)); + + // create stream info wrapped by Arc + let mut ack_tasks = vec![]; + let streams = config + .streams + .iter() + .map(|stream| { + let (ack_tx, ack_rx) = mpsc::unbounded_channel(); + let info = Arc::new(RedisStreamInfo { + group: config.group.clone(), + consumer: config.consumer.clone(), + stream_name: stream.stream.clone(), + stream_type: stream.stream_type, + stream_data_key: stream.data_key.clone(), + xack_batch_max_size: stream.xack_batch_max_size, + xack_batch_max_idle: stream.xack_batch_max_idle, + xack_max_in_process: stream.xack_max_in_process, + }); + ack_tasks.push((Arc::clone(&info), ack_rx)); + (stream.stream.clone(), (ack_tx, info)) + }) + .collect::>(); + + // spawn ack tasks + let mut tasks = ack_tasks + .into_iter() + .map(|(stream, ack_rx)| { + let connection = connection.clone(); + tokio::spawn(async move { Self::run_ack(stream, connection, ack_rx).await }) + }) + .collect::>(); + + // spawn prefetch task + let (messages_tx, messages_rx) = mpsc::channel(config.prefetch_queue_size); + tasks.push(tokio::spawn({ + let shutdown = Arc::clone(&shutdown); + async move { Self::run_prefetch(config, streams, connection, messages_tx, shutdown).await } + })); + + // merge spawn tasks + let spawned_tasks = async move { + for task in tasks.into_iter() { + task.await??; + } + Ok::<(), anyhow::Error>(()) + } + .boxed(); + + Ok(( + Self { + shutdown, + messages_rx, + }, + spawned_tasks, + )) + } + + pub async fn recv(&mut self) -> Option { + self.messages_rx.recv().await + } + + pub fn shutdown(self) { + self.shutdown.store(true, Ordering::Relaxed); + } + + async fn run_prefetch( + config: ConfigIngesterRedis, + streams: HashMap, Arc)>, + mut connection: MultiplexedConnection, + messages_tx: mpsc::Sender, + shutdown: Arc, + ) -> anyhow::Result<()> { + // read pending first + for (ack_tx, stream) in streams.values() { + let mut start = "-".to_owned(); + while !shutdown.load(Ordering::Relaxed) { + let StreamPendingCountReply { ids: pending_ids } = redis::cmd("XPENDING") + .arg(&stream.stream_name) + .arg(&stream.group) + .arg(&start) + .arg("+") + .arg(config.xpending_max) + .arg(&stream.consumer) // we can't use `xpending_count` because it doesn't support `consumer` filter + .query_async(&mut connection) + .await?; + + // drop first item if we do not start from the beginning + let used_ids = if start == "-" { 0.. } else { 1.. }; + let ids_str = pending_ids[used_ids] + .iter() + .map(|pending| pending.id.as_str()) + .collect::>(); + + // check that we fetched all pendings and update start + match pending_ids.last() { + Some(id) => { + if id.id == start { + break; + } else { + start = id.id.clone(); + } + } + None => break, + } + + // read pending keys + let StreamClaimReply { ids: pendings } = connection + .xclaim( + &stream.stream_name, + &stream.group, + &stream.consumer, + 0, + &ids_str, + ) + .await?; + for pending in pendings { + let item = RedisStreamMessageInfo::parse(stream, pending, ack_tx.clone())?; + messages_tx.send(item).await.map_err(|_error| { + anyhow::anyhow!("failed to send item to prefetch channel") + })?; + } + } + } + + // exit if need to handle only pending + if config.xpending_only { + return Ok(()); + } + + let streams_keys = streams.keys().map(|name| name.as_str()).collect::>(); + let streams_ids = (0..streams_keys.len()).map(|_| ">").collect::>(); + while !shutdown.load(Ordering::Relaxed) { + let opts = StreamReadOptions::default() + .count(config.xreadgroup_max) + .group(&config.group, &config.consumer); + let results: StreamReadReply = connection + .xread_options(&streams_keys, &streams_ids, &opts) + .await?; + if results.keys.is_empty() { + sleep(Duration::from_millis(5)).await; + continue; + } + + for StreamKey { key, ids } in results.keys { + let (ack_tx, stream) = match streams.get(&key) { + Some(value) => value, + None => anyhow::bail!("unknown stream: {:?}", key), + }; + + for id in ids { + let item = RedisStreamMessageInfo::parse(stream, id, ack_tx.clone())?; + messages_tx.send(item).await.map_err(|_error| { + anyhow::anyhow!("failed to send item to prefetch channel") + })?; + } + } + } + + Ok(()) + } + + async fn run_ack( + stream: Arc, + connection: MultiplexedConnection, + mut ack_rx: mpsc::UnboundedReceiver, + ) -> anyhow::Result<()> { + let mut ids = vec![]; + let deadline = sleep(stream.xack_batch_max_idle); + tokio::pin!(deadline); + let mut tasks = JoinSet::new(); + + let result = loop { + let terminated = tokio::select! { + msg = ack_rx.recv() => match msg { + Some(msg) => { + ids.push(msg); + if ids.len() < stream.xack_batch_max_size { + continue; + } + false + } + None => true, + }, + _ = &mut deadline => false, + }; + + let ids = std::mem::take(&mut ids); + deadline + .as_mut() + .reset(Instant::now() + stream.xack_batch_max_idle); + if !ids.is_empty() { + tasks.spawn({ + let stream = Arc::clone(&stream); + let mut connection = connection.clone(); + async move { + redis::pipe() + .atomic() + .xack(&stream.stream_name, &stream.group, &ids) + .xdel(&stream.stream_name, &ids) + .query_async(&mut connection) + .await?; + redis_xack_inc(&stream.stream_name, ids.len()); + Ok::<(), anyhow::Error>(()) + } + }); + while tasks.len() >= stream.xack_max_in_process { + if let Some(result) = tasks.join_next().await { + result??; + } + } + } + + if terminated { + break Ok(()); + } + }; + + while let Some(result) = tasks.join_next().await { + result??; + } + + result + } +} From 7e0de78735ed8e9c1c457d5358963f5f1751ea72 Mon Sep 17 00:00:00 2001 From: Kirill Fomichev Date: Tue, 28 Nov 2023 21:57:16 -0500 Subject: [PATCH 19/23] create pg pool --- Cargo.lock | 2 ++ nft_ingester2/Cargo.toml | 2 ++ nft_ingester2/config-run.yml | 6 +++++- nft_ingester2/src/config.rs | 26 ++++++++++++++++++++++++++ nft_ingester2/src/ingester.rs | 17 +++++++++++++++++ nft_ingester2/src/postgres.rs | 30 ++++++++++++++++++++++++++++++ nft_ingester2/src/prom.rs | 21 +++++++++++++++++++++ nft_ingester2/src/redis.rs | 6 +++--- 8 files changed, 106 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 259306caf..88d813f40 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3550,11 +3550,13 @@ dependencies = [ "opentelemetry", "opentelemetry-jaeger", "opentelemetry_sdk", + "program_transformers", "prometheus", "redis", "serde", "serde_yaml", "solana-sdk", + "sqlx", "tokio", "tracing", "tracing-opentelemetry", diff --git a/nft_ingester2/Cargo.toml b/nft_ingester2/Cargo.toml index f665f07d7..739937c98 100644 --- a/nft_ingester2/Cargo.toml +++ b/nft_ingester2/Cargo.toml @@ -16,11 +16,13 @@ lazy_static = { workspace = true } opentelemetry = { workspace = true } opentelemetry-jaeger = { workspace = true, features = ["rt-tokio"] } opentelemetry_sdk = { workspace = true, features = ["trace"] } +program_transformers = { workspace = true } prometheus = { workspace = true } redis = { workspace = true, features = ["tokio-comp", "tokio-native-tls-comp"] } serde = { workspace = true } serde_yaml = { workspace = true } solana-sdk = { workspace = true } # only prom rn +sqlx = { workspace = true, features = ["runtime-tokio-rustls", "postgres"] } tokio = { workspace = true, features = ["rt-multi-thread", "macros", "time", "fs", "tracing"] } tracing = { workspace = true } tracing-opentelemetry = { workspace = true } diff --git a/nft_ingester2/config-run.yml b/nft_ingester2/config-run.yml index 281f6a1fd..3acd4ea24 100644 --- a/nft_ingester2/config-run.yml +++ b/nft_ingester2/config-run.yml @@ -2,7 +2,7 @@ prometheus: 127.0.0.1:8874 redis: url: redis://localhost:6379 group: ingester - consumer: consumer # every new ingester instance should uniq name + consumer: consumer # every new ingester instance should have uniq name streams: - type: account # possible values: `account` and `transaction`, required for message decoding stream: ACCOUNTS @@ -17,3 +17,7 @@ redis: xpending_max: 250 # used for reading pending messages xpending_only: false # exit once all pending messages consumed (should be applied if you want downscale number of ingesters) xreadgroup_max: 1_000 # applied per each stream in one request +postgres: + url: postgres://solana:solana@localhost/solana + min_connections: 10 + max_connections: 25 diff --git a/nft_ingester2/src/config.rs b/nft_ingester2/src/config.rs index 39f3eaba3..898a4bf0b 100644 --- a/nft_ingester2/src/config.rs +++ b/nft_ingester2/src/config.rs @@ -179,6 +179,7 @@ where #[derive(Debug, Deserialize)] pub struct ConfigIngester { pub redis: ConfigIngesterRedis, + pub postgres: ConfigIngesterPostgres, } #[derive(Debug, Deserialize)] @@ -308,3 +309,28 @@ pub enum ConfigIngesterRedisStreamType { Account, Transaction, } + +#[derive(Debug, Deserialize)] +pub struct ConfigIngesterPostgres { + pub url: String, + #[serde( + default = "ConfigIngesterPostgres::default_min_connections", + deserialize_with = "deserialize_usize_str" + )] + pub min_connections: usize, + #[serde( + default = "ConfigIngesterPostgres::default_max_connections", + deserialize_with = "deserialize_usize_str" + )] + pub max_connections: usize, +} + +impl ConfigIngesterPostgres { + pub const fn default_min_connections() -> usize { + 10 + } + + pub const fn default_max_connections() -> usize { + 25 + } +} diff --git a/nft_ingester2/src/ingester.rs b/nft_ingester2/src/ingester.rs index 1e02e03ed..054be0d5a 100644 --- a/nft_ingester2/src/ingester.rs +++ b/nft_ingester2/src/ingester.rs @@ -1,10 +1,13 @@ use { crate::{ config::ConfigIngester, + postgres::{create_pool as pg_create_pool, metrics_pgpool}, redis::{metrics_xlen, RedisStream}, util::create_shutdown, }, futures::future::{Fuse, FusedFuture, FutureExt}, + program_transformers::ProgramTransformer, + std::sync::Arc, tokio::signal::unix::SignalKind, }; @@ -28,6 +31,13 @@ pub async fn run(config: ConfigIngester) -> anyhow::Result<()> { }); tokio::pin!(jh_metrics_xlen); + // open connection to postgres + let pgpool = pg_create_pool(config.postgres).await?; + tokio::spawn({ + let pgpool = Arc::clone(&pgpool); + async move { metrics_pgpool(pgpool).await } + }); + // create redis stream reader let (mut redis_messages, redis_tasks) = RedisStream::new(config.redis, connection).await?; let redis_tasks_fut = Fuse::terminated(); @@ -69,6 +79,13 @@ pub async fn run(config: ConfigIngester) -> anyhow::Result<()> { if !redis_tasks_fut.is_terminated() { redis_tasks_fut.await?; } + pgpool.close().await; result } + +async fn run_program_transformers() -> anyhow::Result<()> { + // let pt_accounts = ProgramTransformer::new() + + todo!() +} diff --git a/nft_ingester2/src/postgres.rs b/nft_ingester2/src/postgres.rs index 8b1378917..6f7bc3c0d 100644 --- a/nft_ingester2/src/postgres.rs +++ b/nft_ingester2/src/postgres.rs @@ -1 +1,31 @@ +use { + crate::{ + config::ConfigIngesterPostgres, + prom::{pgpool_connections_set, PgpoolConnectionsKind}, + }, + sqlx::{ + postgres::{PgConnectOptions, PgPoolOptions}, + PgPool, + }, + std::sync::Arc, + tokio::time::{sleep, Duration}, +}; +pub async fn create_pool(config: ConfigIngesterPostgres) -> anyhow::Result> { + let options: PgConnectOptions = config.url.parse()?; + PgPoolOptions::new() + .min_connections(config.min_connections.try_into()?) + .max_connections(config.max_connections.try_into()?) + .connect_with(options) + .await + .map(Arc::new) + .map_err(Into::into) +} + +pub async fn metrics_pgpool(pgpool: Arc) { + loop { + pgpool_connections_set(PgpoolConnectionsKind::Total, pgpool.size() as usize); + pgpool_connections_set(PgpoolConnectionsKind::Idle, pgpool.num_idle()); + sleep(Duration::from_millis(100)).await; + } +} diff --git a/nft_ingester2/src/prom.rs b/nft_ingester2/src/prom.rs index b6794b615..1b048671e 100644 --- a/nft_ingester2/src/prom.rs +++ b/nft_ingester2/src/prom.rs @@ -32,6 +32,11 @@ lazy_static::lazy_static! { Opts::new("redis_xack_total", "Total number of processed messages"), &["stream"] ).unwrap(); + + static ref PGPOOL_CONNECTIONS_TOTAL: IntGaugeVec = IntGaugeVec::new( + Opts::new("pgpool_connections_total", "Total number of connections in Postgres Pool"), + &["kind"] + ).unwrap(); } pub fn run_server(address: SocketAddr) -> anyhow::Result<()> { @@ -48,6 +53,7 @@ pub fn run_server(address: SocketAddr) -> anyhow::Result<()> { register!(REDIS_XLEN_TOTAL); register!(REDIS_XADD_STATUS); register!(REDIS_XACK_TOTAL); + register!(PGPOOL_CONNECTIONS_TOTAL); VERSION .with_label_values(&[ @@ -116,3 +122,18 @@ pub fn redis_xack_inc(stream: &str, delta: usize) { .with_label_values(&[stream]) .inc_by(delta as u64) } + +#[derive(Debug, Clone, Copy)] +pub enum PgpoolConnectionsKind { + Total, + Idle, +} + +pub fn pgpool_connections_set(kind: PgpoolConnectionsKind, size: usize) { + PGPOOL_CONNECTIONS_TOTAL + .with_label_values(&[match kind { + PgpoolConnectionsKind::Total => "total", + PgpoolConnectionsKind::Idle => "idle", + }]) + .set(size as i64) +} diff --git a/nft_ingester2/src/redis.rs b/nft_ingester2/src/redis.rs index 47f4584f3..554f02c6e 100644 --- a/nft_ingester2/src/redis.rs +++ b/nft_ingester2/src/redis.rs @@ -136,7 +136,7 @@ impl RedisStreamMessageInfo { pub fn ack(self) -> anyhow::Result<()> { self.ack_tx .send(self.id) - .map_err(|_error| anyhow::anyhow!("failed to send message to ack channel",)) + .map_err(|_error| anyhow::anyhow!("failed to send message to ack channel")) } } @@ -187,7 +187,7 @@ impl RedisStream { }) .collect::>(); - // spawn ack tasks + // spawn xack tasks let mut tasks = ack_tasks .into_iter() .map(|(stream, ack_rx)| { @@ -203,7 +203,7 @@ impl RedisStream { async move { Self::run_prefetch(config, streams, connection, messages_tx, shutdown).await } })); - // merge spawn tasks + // merge spawned xack / prefetch tasks let spawned_tasks = async move { for task in tasks.into_iter() { task.await??; From ab12e21a1f3002647d4435683f9013080aac07e7 Mon Sep 17 00:00:00 2001 From: Kirill Fomichev Date: Tue, 28 Nov 2023 23:01:47 -0500 Subject: [PATCH 20/23] parse incoming message from redis --- Cargo.lock | 6 +- Cargo.toml | 6 +- nft_ingester/src/account_updates.rs | 6 +- nft_ingester/src/transaction_notifications.rs | 6 +- nft_ingester2/Cargo.toml | 2 +- nft_ingester2/config-run.yml | 3 + nft_ingester2/src/config.rs | 22 +++ nft_ingester2/src/ingester.rs | 171 +++++++++++++++--- nft_ingester2/src/postgres.rs | 6 +- nft_ingester2/src/prom.rs | 36 +++- nft_ingester2/src/redis.rs | 90 +++++++-- program_transformers/src/lib.rs | 32 ++-- program_transformers/src/token/mod.rs | 2 +- .../src/token_metadata/mod.rs | 8 +- 14 files changed, 322 insertions(+), 74 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 88d813f40..507db2f19 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8404,7 +8404,7 @@ dependencies = [ [[package]] name = "yellowstone-grpc-client" version = "1.12.0+solana.1.16.19" -source = "git+https://github.com/rpcpool/yellowstone-grpc.git?tag=v1.11.1+solana.1.16.19#8b8618dd19d70ed58b942021768d826e31408cd8" +source = "git+https://github.com/rpcpool/yellowstone-grpc.git?branch=1.16-proto-convert-from#44325ab067896ee61c1ffdcce66137a1a203359e" dependencies = [ "bytes", "futures", @@ -8418,7 +8418,7 @@ dependencies = [ [[package]] name = "yellowstone-grpc-proto" version = "1.11.0+solana.1.16.19" -source = "git+https://github.com/rpcpool/yellowstone-grpc.git?tag=v1.11.1+solana.1.16.19#8b8618dd19d70ed58b942021768d826e31408cd8" +source = "git+https://github.com/rpcpool/yellowstone-grpc.git?branch=1.16-proto-convert-from#44325ab067896ee61c1ffdcce66137a1a203359e" dependencies = [ "anyhow", "bincode", @@ -8434,7 +8434,7 @@ dependencies = [ [[package]] name = "yellowstone-grpc-tools" version = "1.0.0-rc.7+solana.1.16.19" -source = "git+https://github.com/rpcpool/yellowstone-grpc.git?tag=v1.11.1+solana.1.16.19#8b8618dd19d70ed58b942021768d826e31408cd8" +source = "git+https://github.com/rpcpool/yellowstone-grpc.git?branch=1.16-proto-convert-from#44325ab067896ee61c1ffdcce66137a1a203359e" dependencies = [ "anyhow", "async-trait", diff --git a/Cargo.toml b/Cargo.toml index 50ac5c3f3..98c8efe9f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -103,9 +103,9 @@ tracing-subscriber = "0.3.16" txn_forwarder = { path = "tools/txn_forwarder" } url = "2.3.1" vergen = "8.2.1" -yellowstone-grpc-client = { git = "https://github.com/rpcpool/yellowstone-grpc.git", tag = "v1.11.1+solana.1.16.19" } # tag is geyser plugin -yellowstone-grpc-proto = { git = "https://github.com/rpcpool/yellowstone-grpc.git", tag = "v1.11.1+solana.1.16.19" } # tag is geyser plugin -yellowstone-grpc-tools = { git = "https://github.com/rpcpool/yellowstone-grpc.git", tag = "v1.11.1+solana.1.16.19", default-features = false } # tag is geyser plugin +yellowstone-grpc-client = { git = "https://github.com/rpcpool/yellowstone-grpc.git", branch = "1.16-proto-convert-from" } # TODO: use tag, when branch merged +yellowstone-grpc-proto = { git = "https://github.com/rpcpool/yellowstone-grpc.git", branch = "1.16-proto-convert-from" } # TODO: use tag, when branch merged +yellowstone-grpc-tools = { git = "https://github.com/rpcpool/yellowstone-grpc.git", branch = "1.16-proto-convert-from", default-features = false } # TODO: use tag, when branch merged [patch.crates-io] blockbuster = { git = "https://github.com/rpcpool/blockbuster.git", tag = "blockbuster-rm-plerkle-v0.9.0-beta.1" } diff --git a/nft_ingester/src/account_updates.rs b/nft_ingester/src/account_updates.rs index c49b6cd5e..f9943a0b7 100644 --- a/nft_ingester/src/account_updates.rs +++ b/nft_ingester/src/account_updates.rs @@ -129,9 +129,9 @@ async fn handle_account_update<'a>( manager .handle_account_update(&AccountInfo { slot: account_update.slot(), - pubkey: &parse_pubkey(account_update.pubkey())?, - owner: &parse_pubkey(account_update.owner())?, - data: parse_slice(account_update.data())?, + pubkey: parse_pubkey(account_update.pubkey())?, + owner: parse_pubkey(account_update.owner())?, + data: parse_slice(account_update.data())?.to_vec(), }) .await } diff --git a/nft_ingester/src/transaction_notifications.rs b/nft_ingester/src/transaction_notifications.rs index 0859a658c..2205c6ae9 100644 --- a/nft_ingester/src/transaction_notifications.rs +++ b/nft_ingester/src/transaction_notifications.rs @@ -130,10 +130,10 @@ async fn handle_transaction_update<'a>( manager .handle_transaction(&TransactionInfo { slot: tx.slot(), - signature: &parse_signature(tx.signature())?, + signature: parse_signature(tx.signature())?, account_keys: parse_account_keys(tx.account_keys())?, - message_instructions: &parse_message_instructions(tx.outer_instructions())?, - meta_inner_instructions: &parse_meta_inner_instructions( + message_instructions: parse_message_instructions(tx.outer_instructions())?, + meta_inner_instructions: parse_meta_inner_instructions( tx.compiled_inner_instructions(), )?, }) diff --git a/nft_ingester2/Cargo.toml b/nft_ingester2/Cargo.toml index 739937c98..b440287f5 100644 --- a/nft_ingester2/Cargo.toml +++ b/nft_ingester2/Cargo.toml @@ -21,7 +21,7 @@ prometheus = { workspace = true } redis = { workspace = true, features = ["tokio-comp", "tokio-native-tls-comp"] } serde = { workspace = true } serde_yaml = { workspace = true } -solana-sdk = { workspace = true } # only prom rn +solana-sdk = { workspace = true } sqlx = { workspace = true, features = ["runtime-tokio-rustls", "postgres"] } tokio = { workspace = true, features = ["rt-multi-thread", "macros", "time", "fs", "tracing"] } tracing = { workspace = true } diff --git a/nft_ingester2/config-run.yml b/nft_ingester2/config-run.yml index 3acd4ea24..19a1b3f84 100644 --- a/nft_ingester2/config-run.yml +++ b/nft_ingester2/config-run.yml @@ -21,3 +21,6 @@ postgres: url: postgres://solana:solana@localhost/solana min_connections: 10 max_connections: 25 +program_transformer: + transactions_cl_audits: false + max_tasks_in_process: 100 diff --git a/nft_ingester2/src/config.rs b/nft_ingester2/src/config.rs index 898a4bf0b..8c8d2fa4b 100644 --- a/nft_ingester2/src/config.rs +++ b/nft_ingester2/src/config.rs @@ -180,6 +180,7 @@ where pub struct ConfigIngester { pub redis: ConfigIngesterRedis, pub postgres: ConfigIngesterPostgres, + pub program_transformer: ConfigIngesterProgramTransformer, } #[derive(Debug, Deserialize)] @@ -334,3 +335,24 @@ impl ConfigIngesterPostgres { 25 } } + +#[derive(Debug, Deserialize)] +pub struct ConfigIngesterProgramTransformer { + #[serde(default = "ConfigIngesterProgramTransformer::default_transactions_cl_audits")] + pub transactions_cl_audits: bool, + #[serde( + default = "ConfigIngesterProgramTransformer::default_max_tasks_in_process", + deserialize_with = "deserialize_usize_str" + )] + pub max_tasks_in_process: usize, +} + +impl ConfigIngesterProgramTransformer { + pub const fn default_transactions_cl_audits() -> bool { + false + } + + pub const fn default_max_tasks_in_process() -> usize { + 100 + } +} diff --git a/nft_ingester2/src/ingester.rs b/nft_ingester2/src/ingester.rs index 054be0d5a..0d7d43478 100644 --- a/nft_ingester2/src/ingester.rs +++ b/nft_ingester2/src/ingester.rs @@ -2,13 +2,28 @@ use { crate::{ config::ConfigIngester, postgres::{create_pool as pg_create_pool, metrics_pgpool}, - redis::{metrics_xlen, RedisStream}, + prom::{ + program_transformer_task_status_inc, program_transformer_tasks_total_set, + ProgramTransformerTaskStatusKind, + }, + redis::{metrics_xlen, ProgramTransformerInfo, RedisStream}, util::create_shutdown, }, - futures::future::{Fuse, FusedFuture, FutureExt}, - program_transformers::ProgramTransformer, - std::sync::Arc, - tokio::signal::unix::SignalKind, + futures::future::{pending, BoxFuture, FusedFuture, FutureExt}, + program_transformers::{ + error::ProgramTransformerError, DownloadMetadataInfo, DownloadMetadataNotifier, + ProgramTransformer, + }, + std::sync::{ + atomic::{AtomicUsize, Ordering}, + Arc, + }, + tokio::{ + signal::unix::SignalKind, + task::JoinSet, + time::{sleep, Duration}, + }, + tracing::warn, }; pub async fn run(config: ConfigIngester) -> anyhow::Result<()> { @@ -34,20 +49,55 @@ pub async fn run(config: ConfigIngester) -> anyhow::Result<()> { // open connection to postgres let pgpool = pg_create_pool(config.postgres).await?; tokio::spawn({ - let pgpool = Arc::clone(&pgpool); + let pgpool = pgpool.clone(); async move { metrics_pgpool(pgpool).await } }); // create redis stream reader - let (mut redis_messages, redis_tasks) = RedisStream::new(config.redis, connection).await?; - let redis_tasks_fut = Fuse::terminated(); + let (mut redis_messages, redis_tasks_fut) = RedisStream::new(config.redis, connection).await?; tokio::pin!(redis_tasks_fut); - redis_tasks_fut.set(redis_tasks.fuse()); - // read messages in the loop + // program transforms related + let pt_accounts = Arc::new(ProgramTransformer::new( + pgpool.clone(), + create_notifier(), + false, + )); + let pt_transactions = Arc::new(ProgramTransformer::new( + pgpool.clone(), + create_notifier(), + config.program_transformer.transactions_cl_audits, + )); + let pt_max_tasks_in_process = config.program_transformer.max_tasks_in_process; + let mut pt_tasks = JoinSet::new(); + let pt_tasks_len = Arc::new(AtomicUsize::new(0)); + tokio::spawn({ + let pt_tasks_len = Arc::clone(&pt_tasks_len); + async move { + loop { + program_transformer_tasks_total_set(pt_tasks_len.load(Ordering::Relaxed)); + sleep(Duration::from_millis(100)).await; + } + } + }); + + // read and process messages in the loop let mut shutdown = create_shutdown()?; let result = loop { - tokio::select! { + pt_tasks_len.store(pt_tasks.len(), Ordering::Relaxed); + + let redis_messages_recv = if pt_tasks.len() == pt_max_tasks_in_process { + pending().boxed() + } else { + redis_messages.recv().boxed() + }; + let pt_tasks_next = if pt_tasks.is_empty() { + pending().boxed() + } else { + pt_tasks.join_next().boxed() + }; + + let msg = tokio::select! { result = &mut jh_metrics_xlen => match result { Ok(Ok(_)) => unreachable!(), Ok(Err(error)) => break Err(error), @@ -61,21 +111,94 @@ pub async fn run(config: ConfigIngester) -> anyhow::Result<()> { } else { "UNKNOWN" }; - tracing::warn!("{signal} received, waiting spawned tasks..."); + warn!("{signal} received, waiting spawned tasks..."); break Ok(()); }, result = &mut redis_tasks_fut => break result, - msg = redis_messages.recv() => match msg { - Some(msg) => { - // TODO: process messages here - msg.ack()?; - } + msg = redis_messages_recv => match msg { + Some(msg) => msg, None => break Ok(()), + }, + result = pt_tasks_next => { + if let Some(result) = result { + result??; + } + continue; } }; + + pt_tasks.spawn({ + let pt_accounts = Arc::clone(&pt_accounts); + let pt_transactions = Arc::clone(&pt_transactions); + async move { + let result = match &msg.get_data() { + ProgramTransformerInfo::Account(account) => { + pt_accounts.handle_account_update(account).await + } + ProgramTransformerInfo::Transaction(transaction) => { + pt_transactions.handle_transaction(transaction).await + } + }; + + macro_rules! log_or_bail { + ($action:path, $msg:expr, $error:ident) => { + match msg.get_data() { + ProgramTransformerInfo::Account(account) => { + $action!("{} account {}: {:?}", $msg, account.pubkey, $error) + } + ProgramTransformerInfo::Transaction(transaction) => { + $action!( + "{} transaction {}: {:?}", + $msg, + transaction.signature, + $error + ) + } + } + }; + } + + match result { + Ok(()) => program_transformer_task_status_inc( + ProgramTransformerTaskStatusKind::Success, + ), + Err(ProgramTransformerError::NotImplemented) => { + program_transformer_task_status_inc( + ProgramTransformerTaskStatusKind::NotImplemented, + ) + } + Err(ProgramTransformerError::DeserializationError(error)) => { + program_transformer_task_status_inc( + ProgramTransformerTaskStatusKind::DeserializationError, + ); + log_or_bail!(warn, "failed to deserialize", error) + } + Err(ProgramTransformerError::ParsingError(error)) => { + program_transformer_task_status_inc( + ProgramTransformerTaskStatusKind::ParsingError, + ); + log_or_bail!(warn, "failed to parse", error) + } + Err(ProgramTransformerError::DatabaseError(error)) => { + log_or_bail!(anyhow::bail, "database error for", error) + } + Err(ProgramTransformerError::AssetIndexError(error)) => { + log_or_bail!(anyhow::bail, "indexing error for ", error) + } + Err(error) => { + log_or_bail!(anyhow::bail, "failed to handle", error) + } + } + + msg.ack() + } + }); }; redis_messages.shutdown(); + while let Some(result) = pt_tasks.join_next().await { + result??; + } if !redis_tasks_fut.is_terminated() { redis_tasks_fut.await?; } @@ -84,8 +207,14 @@ pub async fn run(config: ConfigIngester) -> anyhow::Result<()> { result } -async fn run_program_transformers() -> anyhow::Result<()> { - // let pt_accounts = ProgramTransformer::new() - - todo!() +fn create_notifier() -> DownloadMetadataNotifier { + Box::new( + move |_info: DownloadMetadataInfo| -> BoxFuture< + 'static, + Result<(), Box>, + > { + // TODO + Box::pin(async move { Ok(()) }) + }, + ) } diff --git a/nft_ingester2/src/postgres.rs b/nft_ingester2/src/postgres.rs index 6f7bc3c0d..05e535b4d 100644 --- a/nft_ingester2/src/postgres.rs +++ b/nft_ingester2/src/postgres.rs @@ -7,22 +7,20 @@ use { postgres::{PgConnectOptions, PgPoolOptions}, PgPool, }, - std::sync::Arc, tokio::time::{sleep, Duration}, }; -pub async fn create_pool(config: ConfigIngesterPostgres) -> anyhow::Result> { +pub async fn create_pool(config: ConfigIngesterPostgres) -> anyhow::Result { let options: PgConnectOptions = config.url.parse()?; PgPoolOptions::new() .min_connections(config.min_connections.try_into()?) .max_connections(config.max_connections.try_into()?) .connect_with(options) .await - .map(Arc::new) .map_err(Into::into) } -pub async fn metrics_pgpool(pgpool: Arc) { +pub async fn metrics_pgpool(pgpool: PgPool) { loop { pgpool_connections_set(PgpoolConnectionsKind::Total, pgpool.size() as usize); pgpool_connections_set(PgpoolConnectionsKind::Idle, pgpool.num_idle()); diff --git a/nft_ingester2/src/prom.rs b/nft_ingester2/src/prom.rs index 1b048671e..884407760 100644 --- a/nft_ingester2/src/prom.rs +++ b/nft_ingester2/src/prom.rs @@ -5,7 +5,7 @@ use { service::{make_service_fn, service_fn}, Body, Request, Response, Server, StatusCode, }, - prometheus::{IntCounterVec, IntGaugeVec, Opts, Registry, TextEncoder}, + prometheus::{IntCounterVec, IntGauge, IntGaugeVec, Opts, Registry, TextEncoder}, std::{net::SocketAddr, sync::Once}, tracing::{error, info}, }; @@ -37,6 +37,15 @@ lazy_static::lazy_static! { Opts::new("pgpool_connections_total", "Total number of connections in Postgres Pool"), &["kind"] ).unwrap(); + + static ref PROGRAM_TRANSFORMER_TASKS_TOTAL: IntGauge = IntGauge::new( + "program_transformer_tasks_total", "Number of tasks spawned for program transform" + ).unwrap(); + + static ref PROGRAM_TRANSFORMER_TASK_STATUS: IntCounterVec = IntCounterVec::new( + Opts::new("program_transformer_task_status", "Status of processed messages"), + &["status"], + ).unwrap(); } pub fn run_server(address: SocketAddr) -> anyhow::Result<()> { @@ -54,6 +63,8 @@ pub fn run_server(address: SocketAddr) -> anyhow::Result<()> { register!(REDIS_XADD_STATUS); register!(REDIS_XACK_TOTAL); register!(PGPOOL_CONNECTIONS_TOTAL); + register!(PROGRAM_TRANSFORMER_TASKS_TOTAL); + register!(PROGRAM_TRANSFORMER_TASK_STATUS); VERSION .with_label_values(&[ @@ -137,3 +148,26 @@ pub fn pgpool_connections_set(kind: PgpoolConnectionsKind, size: usize) { }]) .set(size as i64) } + +pub fn program_transformer_tasks_total_set(size: usize) { + PROGRAM_TRANSFORMER_TASKS_TOTAL.set(size as i64) +} + +#[derive(Debug, Clone, Copy)] +pub enum ProgramTransformerTaskStatusKind { + Success, + NotImplemented, + DeserializationError, + ParsingError, +} + +pub fn program_transformer_task_status_inc(kind: ProgramTransformerTaskStatusKind) { + PROGRAM_TRANSFORMER_TASK_STATUS + .with_label_values(&[match kind { + ProgramTransformerTaskStatusKind::Success => "success", + ProgramTransformerTaskStatusKind::NotImplemented => "not_implemented", + ProgramTransformerTaskStatusKind::DeserializationError => "deserialization_error", + ProgramTransformerTaskStatusKind::ParsingError => "parsing_error", + }]) + .inc() +} diff --git a/nft_ingester2/src/redis.rs b/nft_ingester2/src/redis.rs index 554f02c6e..b823f4fee 100644 --- a/nft_ingester2/src/redis.rs +++ b/nft_ingester2/src/redis.rs @@ -3,7 +3,8 @@ use { config::{ConfigIngesterRedis, ConfigIngesterRedisStreamType}, prom::{redis_xack_inc, redis_xlen_set}, }, - futures::future::{BoxFuture, FutureExt}, + futures::future::{BoxFuture, Fuse, FutureExt}, + program_transformers::{AccountInfo, TransactionInfo}, redis::{ aio::MultiplexedConnection, streams::{ @@ -12,6 +13,7 @@ use { }, AsyncCommands, ErrorKind as RedisErrorKind, RedisResult, Value as RedisValue, }, + solana_sdk::{pubkey::Pubkey, signature::Signature}, std::{ collections::HashMap, convert::Infallible, @@ -26,6 +28,9 @@ use { time::{sleep, Duration, Instant}, }, yellowstone_grpc_proto::{ + convert_from::{ + create_message_instructions, create_meta_inner_instructions, create_pubkey_vec, + }, prelude::{SubscribeUpdateAccount, SubscribeUpdateTransaction}, prost::Message, }, @@ -90,17 +95,16 @@ struct RedisStreamInfo { xack_max_in_process: usize, } -#[allow(clippy::large_enum_variant)] #[derive(Debug)] -pub enum RedisStreamMessage { - Account(SubscribeUpdateAccount), - Transaction(SubscribeUpdateTransaction), +pub enum ProgramTransformerInfo { + Account(AccountInfo), + Transaction(TransactionInfo), } #[derive(Debug)] pub struct RedisStreamMessageInfo { id: String, - data: RedisStreamMessage, + data: ProgramTransformerInfo, ack_tx: mpsc::UnboundedSender, } @@ -110,14 +114,69 @@ impl RedisStreamMessageInfo { StreamId { id, map }: StreamId, ack_tx: mpsc::UnboundedSender, ) -> anyhow::Result { + let to_anyhow = |error: String| anyhow::anyhow!(error); + let data = match map.get(&stream.stream_data_key) { Some(RedisValue::Data(vec)) => match stream.stream_type { ConfigIngesterRedisStreamType::Account => { - RedisStreamMessage::Account(SubscribeUpdateAccount::decode(vec.as_ref())?) + let SubscribeUpdateAccount { account, slot, .. } = + Message::decode(vec.as_ref())?; + + let account = account.ok_or_else(|| { + anyhow::anyhow!("received invalid SubscribeUpdateAccount") + })?; + + ProgramTransformerInfo::Account(AccountInfo { + slot, + pubkey: Pubkey::try_from(account.pubkey.as_slice())?, + owner: Pubkey::try_from(account.owner.as_slice())?, + data: account.data, + }) + } + ConfigIngesterRedisStreamType::Transaction => { + let SubscribeUpdateTransaction { transaction, slot } = + Message::decode(vec.as_ref())?; + + let transaction = transaction.ok_or_else(|| { + anyhow::anyhow!("received invalid SubscribeUpdateTransaction") + })?; + let tx = transaction.transaction.ok_or_else(|| { + anyhow::anyhow!( + "received invalid transaction in SubscribeUpdateTransaction" + ) + })?; + let message = tx.message.ok_or_else(|| { + anyhow::anyhow!("received invalid message in SubscribeUpdateTransaction") + })?; + let meta = transaction.meta.ok_or_else(|| { + anyhow::anyhow!("received invalid meta in SubscribeUpdateTransaction") + })?; + + let mut account_keys = + create_pubkey_vec(message.account_keys).map_err(to_anyhow)?; + for pubkey in + create_pubkey_vec(meta.loaded_writable_addresses).map_err(to_anyhow)? + { + account_keys.push(pubkey); + } + for pubkey in + create_pubkey_vec(meta.loaded_readonly_addresses).map_err(to_anyhow)? + { + account_keys.push(pubkey); + } + + ProgramTransformerInfo::Transaction(TransactionInfo { + slot, + signature: Signature::try_from(transaction.signature.as_slice())?, + account_keys, + message_instructions: create_message_instructions(message.instructions) + .map_err(to_anyhow)?, + meta_inner_instructions: create_meta_inner_instructions( + meta.inner_instructions, + ) + .map_err(to_anyhow)?, + }) } - ConfigIngesterRedisStreamType::Transaction => RedisStreamMessage::Transaction( - SubscribeUpdateTransaction::decode(vec.as_ref())?, - ), }, Some(_) => anyhow::bail!( "invalid data (key: {:?}) from stream {:?}", @@ -133,6 +192,10 @@ impl RedisStreamMessageInfo { Ok(Self { id, data, ack_tx }) } + pub const fn get_data(&self) -> &ProgramTransformerInfo { + &self.data + } + pub fn ack(self) -> anyhow::Result<()> { self.ack_tx .send(self.id) @@ -150,7 +213,7 @@ impl RedisStream { pub async fn new( config: ConfigIngesterRedis, mut connection: MultiplexedConnection, - ) -> anyhow::Result<(Self, BoxFuture<'static, anyhow::Result<()>>)> { + ) -> anyhow::Result<(Self, Fuse>>)> { // create group with consumer per stream for stream in config.streams.iter() { xgroup_create( @@ -209,15 +272,14 @@ impl RedisStream { task.await??; } Ok::<(), anyhow::Error>(()) - } - .boxed(); + }; Ok(( Self { shutdown, messages_rx, }, - spawned_tasks, + spawned_tasks.boxed().fuse(), )) } diff --git a/program_transformers/src/lib.rs b/program_transformers/src/lib.rs index 5cf1c0ced..996a0ffac 100644 --- a/program_transformers/src/lib.rs +++ b/program_transformers/src/lib.rs @@ -27,21 +27,21 @@ pub mod error; mod token; mod token_metadata; -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct AccountInfo<'a> { +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct AccountInfo { pub slot: u64, - pub pubkey: &'a Pubkey, - pub owner: &'a Pubkey, - pub data: &'a [u8], + pub pubkey: Pubkey, + pub owner: Pubkey, + pub data: Vec, } #[derive(Debug, Clone, PartialEq, Eq)] -pub struct TransactionInfo<'a> { +pub struct TransactionInfo { pub slot: u64, - pub signature: &'a Signature, + pub signature: Signature, pub account_keys: Vec, - pub message_instructions: &'a [CompiledInstruction], - pub meta_inner_instructions: &'a [InnerInstructions], + pub message_instructions: Vec, + pub meta_inner_instructions: Vec, } #[derive(Debug, Clone, PartialEq, Eq)] @@ -107,13 +107,13 @@ impl ProgramTransformer { pub fn break_transaction<'a>( &self, - tx_info: &'a TransactionInfo<'_>, + tx_info: &'a TransactionInfo, ) -> VecDeque<(IxPair<'a>, Option>>)> { order_instructions( &self.key_set, &tx_info.account_keys, - tx_info.message_instructions, - tx_info.meta_inner_instructions, + &tx_info.message_instructions, + &tx_info.meta_inner_instructions, ) } @@ -124,7 +124,7 @@ impl ProgramTransformer { pub async fn handle_transaction( &self, - tx_info: &TransactionInfo<'_>, + tx_info: &TransactionInfo, ) -> ProgramTransformerResult<()> { info!("Handling Transaction: {:?}", tx_info.signature); let instructions = self.break_transaction(tx_info); @@ -202,10 +202,10 @@ impl ProgramTransformer { pub async fn handle_account_update( &self, - account_info: &AccountInfo<'_>, + account_info: &AccountInfo, ) -> ProgramTransformerResult<()> { - if let Some(program) = self.match_program(account_info.owner) { - let result = program.handle_account(account_info.data)?; + if let Some(program) = self.match_program(&account_info.owner) { + let result = program.handle_account(&account_info.data)?; match result.result_type() { ProgramParseResult::TokenMetadata(parsing_result) => { handle_token_metadata_account( diff --git a/program_transformers/src/token/mod.rs b/program_transformers/src/token/mod.rs index 5098d743a..facdb0ded 100644 --- a/program_transformers/src/token/mod.rs +++ b/program_transformers/src/token/mod.rs @@ -16,7 +16,7 @@ use { }; pub async fn handle_token_program_account( - account_info: &AccountInfo<'_>, + account_info: &AccountInfo, parsing_result: &TokenProgramAccount, db: &DatabaseConnection, _download_metadata_notifier: &DownloadMetadataNotifier, diff --git a/program_transformers/src/token_metadata/mod.rs b/program_transformers/src/token_metadata/mod.rs index 4be03f1b2..5cba81946 100644 --- a/program_transformers/src/token_metadata/mod.rs +++ b/program_transformers/src/token_metadata/mod.rs @@ -15,19 +15,19 @@ mod master_edition; mod v1_asset; pub async fn handle_token_metadata_account( - account_info: &AccountInfo<'_>, + account_info: &AccountInfo, parsing_result: &TokenMetadataAccountState, db: &DatabaseConnection, download_metadata_notifier: &DownloadMetadataNotifier, ) -> ProgramTransformerResult<()> { match &parsing_result.data { TokenMetadataAccountData::EmptyAccount => { - burn_v1_asset(db, account_info.pubkey, account_info.slot).await?; + burn_v1_asset(db, &account_info.pubkey, account_info.slot).await?; Ok(()) } TokenMetadataAccountData::MasterEditionV1(m) => { let txn = db.begin().await?; - save_v1_master_edition(account_info.pubkey, account_info.slot, m, &txn).await?; + save_v1_master_edition(&account_info.pubkey, account_info.slot, m, &txn).await?; txn.commit().await?; Ok(()) } @@ -41,7 +41,7 @@ pub async fn handle_token_metadata_account( } TokenMetadataAccountData::MasterEditionV2(m) => { let txn = db.begin().await?; - save_v2_master_edition(account_info.pubkey, account_info.slot, m, &txn).await?; + save_v2_master_edition(&account_info.pubkey, account_info.slot, m, &txn).await?; txn.commit().await?; Ok(()) } From ec74b61681808df3f1c92b675af559612b51b76d Mon Sep 17 00:00:00 2001 From: Kirill Fomichev Date: Wed, 29 Nov 2023 22:10:42 -0500 Subject: [PATCH 21/23] add force shutdown with signals --- Cargo.lock | 1 + Cargo.toml | 1 + nft_ingester2/Cargo.toml | 1 + nft_ingester2/src/grpc.rs | 27 +++++++++++----------- nft_ingester2/src/ingester.rs | 43 ++++++++++++++++++++--------------- nft_ingester2/src/redis.rs | 14 +++++++----- nft_ingester2/src/util.rs | 15 +++++++----- 7 files changed, 59 insertions(+), 43 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 507db2f19..a7d18c629 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3539,6 +3539,7 @@ name = "nft_ingester2" version = "0.7.2" dependencies = [ "anyhow", + "async-stream", "atty", "cargo-lock", "clap 4.4.8", diff --git a/Cargo.toml b/Cargo.toml index 98c8efe9f..2ee41f36e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,6 +27,7 @@ anchor-client = "0.28.0" anchor-lang = "0.28.0" anyhow = "1.0.75" async-std = "1.0.0" +async-stream = "0.3.5" async-trait = "0.1.60" atty = "0.2.14" blockbuster = "0.9.0-beta.1" diff --git a/nft_ingester2/Cargo.toml b/nft_ingester2/Cargo.toml index b440287f5..df11b29fb 100644 --- a/nft_ingester2/Cargo.toml +++ b/nft_ingester2/Cargo.toml @@ -7,6 +7,7 @@ publish = { workspace = true } [dependencies] anyhow = { workspace = true } +async-stream = { workspace = true } atty = { workspace = true } clap = { workspace = true, features = ["cargo", "derive"] } futures = { workspace = true } diff --git a/nft_ingester2/src/grpc.rs b/nft_ingester2/src/grpc.rs index 5ec284b1b..66b4ead4c 100644 --- a/nft_ingester2/src/grpc.rs +++ b/nft_ingester2/src/grpc.rs @@ -7,10 +7,10 @@ use { redis::{streams::StreamMaxlen, RedisResult, Value as RedisValue}, std::{sync::Arc, time::Duration}, tokio::{ - signal::unix::SignalKind, task::JoinSet, time::{sleep, Instant}, }, + tracing::warn, yellowstone_grpc_client::GeyserGrpcClient, yellowstone_grpc_proto::{prelude::subscribe_update::UpdateOneof, prost::Message}, }; @@ -64,15 +64,8 @@ pub async fn run(config: ConfigGrpc) -> anyhow::Result<()> { Ok(Err(error)) => break Err(error), Err(error) => break Err(error.into()), }, - signal = &mut shutdown => { - let signal = if signal == SignalKind::interrupt() { - "SIGINT" - } else if signal == SignalKind::terminate() { - "SIGTERM" - } else { - "UNKNOWN" - }; - tracing::warn!("{signal} received, waiting spawned tasks..."); + Some(signal) = shutdown.next() => { + warn!("{signal} received, waiting spawned tasks..."); break Ok(()); }, msg = geyser.next() => { @@ -142,9 +135,17 @@ pub async fn run(config: ConfigGrpc) -> anyhow::Result<()> { } }; - while let Some(result) = tasks.join_next().await { - result??; - } + tokio::select! { + Some(signal) = shutdown.next() => { + anyhow::bail!("{signal} received, force shutdown..."); + } + result = async move { + while let Some(result) = tasks.join_next().await { + result??; + } + Ok::<(), anyhow::Error>(()) + } => result?, + }; result } diff --git a/nft_ingester2/src/ingester.rs b/nft_ingester2/src/ingester.rs index 0d7d43478..479e5bddb 100644 --- a/nft_ingester2/src/ingester.rs +++ b/nft_ingester2/src/ingester.rs @@ -9,7 +9,10 @@ use { redis::{metrics_xlen, ProgramTransformerInfo, RedisStream}, util::create_shutdown, }, - futures::future::{pending, BoxFuture, FusedFuture, FutureExt}, + futures::{ + future::{pending, BoxFuture, FusedFuture, FutureExt}, + stream::StreamExt, + }, program_transformers::{ error::ProgramTransformerError, DownloadMetadataInfo, DownloadMetadataNotifier, ProgramTransformer, @@ -19,7 +22,6 @@ use { Arc, }, tokio::{ - signal::unix::SignalKind, task::JoinSet, time::{sleep, Duration}, }, @@ -103,14 +105,7 @@ pub async fn run(config: ConfigIngester) -> anyhow::Result<()> { Ok(Err(error)) => break Err(error), Err(error) => break Err(error.into()), }, - signal = &mut shutdown => { - let signal = if signal == SignalKind::interrupt() { - "SIGINT" - } else if signal == SignalKind::terminate() { - "SIGTERM" - } else { - "UNKNOWN" - }; + Some(signal) = shutdown.next() => { warn!("{signal} received, waiting spawned tasks..."); break Ok(()); }, @@ -195,14 +190,26 @@ pub async fn run(config: ConfigIngester) -> anyhow::Result<()> { }); }; - redis_messages.shutdown(); - while let Some(result) = pt_tasks.join_next().await { - result??; - } - if !redis_tasks_fut.is_terminated() { - redis_tasks_fut.await?; - } - pgpool.close().await; + tokio::select! { + Some(signal) = shutdown.next() => { + anyhow::bail!("{signal} received, force shutdown..."); + } + result = async move { + // shutdown `prefetch` channel (but not Receiver) + redis_messages.shutdown(); + // wait all `program_transformer` spawned tasks + while let Some(result) = pt_tasks.join_next().await { + result??; + } + // wait all `ack` spawned tasks + if !redis_tasks_fut.is_terminated() { + redis_tasks_fut.await?; + } + // shutdown database connection + pgpool.close().await; + Ok::<(), anyhow::Error>(()) + } => result?, + }; result } diff --git a/nft_ingester2/src/redis.rs b/nft_ingester2/src/redis.rs index b823f4fee..1baec8799 100644 --- a/nft_ingester2/src/redis.rs +++ b/nft_ingester2/src/redis.rs @@ -251,7 +251,7 @@ impl RedisStream { .collect::>(); // spawn xack tasks - let mut tasks = ack_tasks + let ack_jh_vec = ack_tasks .into_iter() .map(|(stream, ack_rx)| { let connection = connection.clone(); @@ -261,15 +261,16 @@ impl RedisStream { // spawn prefetch task let (messages_tx, messages_rx) = mpsc::channel(config.prefetch_queue_size); - tasks.push(tokio::spawn({ + let jh_prefetch = tokio::spawn({ let shutdown = Arc::clone(&shutdown); async move { Self::run_prefetch(config, streams, connection, messages_tx, shutdown).await } - })); + }); // merge spawned xack / prefetch tasks let spawned_tasks = async move { - for task in tasks.into_iter() { - task.await??; + jh_prefetch.await??; + for jh in ack_jh_vec.into_iter() { + jh.await??; } Ok::<(), anyhow::Error>(()) }; @@ -287,8 +288,9 @@ impl RedisStream { self.messages_rx.recv().await } - pub fn shutdown(self) { + pub fn shutdown(mut self) { self.shutdown.store(true, Ordering::Relaxed); + tokio::spawn(async move { while self.messages_rx.recv().await.is_some() {} }); } async fn run_prefetch( diff --git a/nft_ingester2/src/util.rs b/nft_ingester2/src/util.rs index 6de97e42f..0a7800a12 100644 --- a/nft_ingester2/src/util.rs +++ b/nft_ingester2/src/util.rs @@ -1,15 +1,18 @@ use { - futures::future::{BoxFuture, FutureExt}, + async_stream::stream, + futures::stream::{BoxStream, StreamExt}, tokio::signal::unix::{signal, SignalKind}, }; -pub fn create_shutdown() -> anyhow::Result> { +pub fn create_shutdown() -> anyhow::Result> { let mut sigint = signal(SignalKind::interrupt())?; let mut sigterm = signal(SignalKind::terminate())?; - Ok(async move { - tokio::select! { - _ = sigint.recv() => SignalKind::interrupt(), - _ = sigterm.recv() => SignalKind::terminate(), + Ok(stream! { + loop { + yield tokio::select! { + _ = sigint.recv() => "SIGINT", + _ = sigterm.recv() => "SIGTERM", + }; } } .boxed()) From 485bfbab541b5ffaa2af3db87af1c5246dfe0675 Mon Sep 17 00:00:00 2001 From: Kirill Fomichev Date: Thu, 30 Nov 2023 21:20:38 -0500 Subject: [PATCH 22/23] insert download metadata tasks --- Cargo.lock | 6 +++ nft_ingester2/Cargo.toml | 5 ++ nft_ingester2/config-run.yml | 6 ++- nft_ingester2/src/config.rs | 29 ++++++++++- nft_ingester2/src/ingester.rs | 85 +++++++++++++++++++++++++-------- nft_ingester2/src/main.rs | 1 + nft_ingester2/src/prom.rs | 11 ++++- program_transformers/Cargo.toml | 1 + program_transformers/src/lib.rs | 3 +- 9 files changed, 121 insertions(+), 26 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a7d18c629..b104b5e84 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3542,7 +3542,9 @@ dependencies = [ "async-stream", "atty", "cargo-lock", + "chrono", "clap 4.4.8", + "digital_asset_types", "futures", "git-version", "hyper", @@ -3554,7 +3556,10 @@ dependencies = [ "program_transformers", "prometheus", "redis", + "rust-crypto", + "sea-orm", "serde", + "serde_json", "serde_yaml", "solana-sdk", "sqlx", @@ -4428,6 +4433,7 @@ dependencies = [ "mpl-bubblegum", "num-traits", "sea-orm", + "serde", "serde_json", "solana-sdk", "solana-transaction-status", diff --git a/nft_ingester2/Cargo.toml b/nft_ingester2/Cargo.toml index df11b29fb..f8e82b55b 100644 --- a/nft_ingester2/Cargo.toml +++ b/nft_ingester2/Cargo.toml @@ -9,7 +9,9 @@ publish = { workspace = true } anyhow = { workspace = true } async-stream = { workspace = true } atty = { workspace = true } +chrono = { workspace = true } clap = { workspace = true, features = ["cargo", "derive"] } +digital_asset_types = { workspace = true } futures = { workspace = true } hyper = { workspace = true, features = ["server"] } json5 = { workspace = true } @@ -20,7 +22,10 @@ opentelemetry_sdk = { workspace = true, features = ["trace"] } program_transformers = { workspace = true } prometheus = { workspace = true } redis = { workspace = true, features = ["tokio-comp", "tokio-native-tls-comp"] } +rust-crypto = { workspace = true } +sea-orm = { workspace = true, features = ["sqlx-postgres"] } serde = { workspace = true } +serde_json = { workspace = true } serde_yaml = { workspace = true } solana-sdk = { workspace = true } sqlx = { workspace = true, features = ["runtime-tokio-rustls", "postgres"] } diff --git a/nft_ingester2/config-run.yml b/nft_ingester2/config-run.yml index 19a1b3f84..3af3ad2e7 100644 --- a/nft_ingester2/config-run.yml +++ b/nft_ingester2/config-run.yml @@ -20,7 +20,9 @@ redis: postgres: url: postgres://solana:solana@localhost/solana min_connections: 10 - max_connections: 25 + max_connections: 50 # `max_connection` should be bigger than `program_transformer.max_tasks_in_process` otherwise unresolved lock is possible program_transformer: transactions_cl_audits: false - max_tasks_in_process: 100 + max_tasks_in_process: 40 +download_metadata_handler: + max_attempts: 3 diff --git a/nft_ingester2/src/config.rs b/nft_ingester2/src/config.rs index 8c8d2fa4b..665283dd8 100644 --- a/nft_ingester2/src/config.rs +++ b/nft_ingester2/src/config.rs @@ -3,6 +3,7 @@ use { serde::{de, Deserialize}, std::{collections::HashMap, net::SocketAddr, path::Path, time::Duration}, tokio::fs, + tracing::warn, yellowstone_grpc_proto::prelude::SubscribeRequest, yellowstone_grpc_tools::config::{ deserialize_usize_str, ConfigGrpcRequestAccounts, ConfigGrpcRequestCommitment, @@ -181,6 +182,15 @@ pub struct ConfigIngester { pub redis: ConfigIngesterRedis, pub postgres: ConfigIngesterPostgres, pub program_transformer: ConfigIngesterProgramTransformer, + pub download_metadata_handler: ConfigDownloadMetadataHandler, +} + +impl ConfigIngester { + pub fn check(&self) { + if self.postgres.max_connections < self.program_transformer.max_tasks_in_process { + warn!("`postgres.max_connections` should be bigger than `program_transformer.max_tasks_in_process` otherwise unresolved lock is possible"); + } + } } #[derive(Debug, Deserialize)] @@ -332,7 +342,7 @@ impl ConfigIngesterPostgres { } pub const fn default_max_connections() -> usize { - 25 + 50 } } @@ -353,6 +363,21 @@ impl ConfigIngesterProgramTransformer { } pub const fn default_max_tasks_in_process() -> usize { - 100 + 40 + } +} + +#[derive(Debug, Clone, Copy, Deserialize)] +pub struct ConfigDownloadMetadataHandler { + #[serde( + default = "ConfigDownloadMetadataHandler::default_max_attempts", + deserialize_with = "deserialize_usize_str" + )] + pub max_attempts: usize, +} + +impl ConfigDownloadMetadataHandler { + pub const fn default_max_attempts() -> usize { + 3 } } diff --git a/nft_ingester2/src/ingester.rs b/nft_ingester2/src/ingester.rs index 479e5bddb..22f4311c2 100644 --- a/nft_ingester2/src/ingester.rs +++ b/nft_ingester2/src/ingester.rs @@ -1,14 +1,17 @@ use { crate::{ - config::ConfigIngester, + config::{ConfigDownloadMetadataHandler, ConfigIngester}, postgres::{create_pool as pg_create_pool, metrics_pgpool}, prom::{ - program_transformer_task_status_inc, program_transformer_tasks_total_set, - ProgramTransformerTaskStatusKind, + download_metadata_inserted_total_inc, program_transformer_task_status_inc, + program_transformer_tasks_total_set, ProgramTransformerTaskStatusKind, }, redis::{metrics_xlen, ProgramTransformerInfo, RedisStream}, util::create_shutdown, }, + chrono::Utc, + crypto::{digest::Digest, sha2::Sha256}, + digital_asset_types::dao::{sea_orm_active_enums::TaskStatus, tasks}, futures::{ future::{pending, BoxFuture, FusedFuture, FutureExt}, stream::StreamExt, @@ -17,9 +20,18 @@ use { error::ProgramTransformerError, DownloadMetadataInfo, DownloadMetadataNotifier, ProgramTransformer, }, - std::sync::{ - atomic::{AtomicUsize, Ordering}, - Arc, + sea_orm::{ + entity::{ActiveModelTrait, ActiveValue}, + error::{DbErr, RuntimeErr}, + SqlxPostgresConnector, + }, + sqlx::{Error as SqlxError, PgPool}, + std::{ + borrow::Cow, + sync::{ + atomic::{AtomicUsize, Ordering}, + Arc, + }, }, tokio::{ task::JoinSet, @@ -29,8 +41,6 @@ use { }; pub async fn run(config: ConfigIngester) -> anyhow::Result<()> { - println!("{:#?}", config); - // connect to Redis let client = redis::Client::open(config.redis.url.clone())?; let connection = client.get_multiplexed_tokio_connection().await?; @@ -62,12 +72,12 @@ pub async fn run(config: ConfigIngester) -> anyhow::Result<()> { // program transforms related let pt_accounts = Arc::new(ProgramTransformer::new( pgpool.clone(), - create_notifier(), + create_download_metadata_notifier(pgpool.clone(), config.download_metadata_handler)?, false, )); let pt_transactions = Arc::new(ProgramTransformer::new( pgpool.clone(), - create_notifier(), + create_download_metadata_notifier(pgpool.clone(), config.download_metadata_handler)?, config.program_transformer.transactions_cl_audits, )); let pt_max_tasks_in_process = config.program_transformer.max_tasks_in_process; @@ -214,14 +224,49 @@ pub async fn run(config: ConfigIngester) -> anyhow::Result<()> { result } -fn create_notifier() -> DownloadMetadataNotifier { - Box::new( - move |_info: DownloadMetadataInfo| -> BoxFuture< - 'static, - Result<(), Box>, - > { - // TODO - Box::pin(async move { Ok(()) }) - }, - ) +fn create_download_metadata_notifier( + pgpool: PgPool, + config: ConfigDownloadMetadataHandler, +) -> anyhow::Result { + let max_attempts = config.max_attempts.try_into()?; + Ok(Box::new(move |info: DownloadMetadataInfo| -> BoxFuture< + 'static, + Result<(), Box>, + > { + let pgpool = pgpool.clone(); + Box::pin(async move { + const NAME: &str = "DownloadMetadata"; + + let data = serde_json::to_value(info)?; + + let mut hasher = Sha256::new(); + hasher.input(NAME.as_bytes()); + hasher.input(serde_json::to_vec(&data)?.as_slice()); + let hash = hasher.result_str(); + + let model = tasks::ActiveModel { + id: ActiveValue::Set(hash), + task_type: ActiveValue::Set(NAME.to_owned()), + data: ActiveValue::Set(data), + status: ActiveValue::Set(TaskStatus::Pending), + created_at: ActiveValue::Set(Utc::now().naive_utc()), + locked_until: ActiveValue::Set(None), + locked_by: ActiveValue::Set(None), + max_attempts: ActiveValue::Set(max_attempts), + attempts: ActiveValue::Set(0), + duration: ActiveValue::Set(None), + errors: ActiveValue::Set(None), + }; + let conn = SqlxPostgresConnector::from_sqlx_postgres_pool(pgpool); + + match model.insert(&conn).await.map(|_mode| ()) { + // skip unique_violation error + Err(DbErr::Query(RuntimeErr::SqlxError(SqlxError::Database(dberr)))) if dberr.code() == Some(Cow::Borrowed("23505")) => {}, + value => value?, + }; + download_metadata_inserted_total_inc(); + + Ok(()) + }) + })) } diff --git a/nft_ingester2/src/main.rs b/nft_ingester2/src/main.rs index 0bd1f9b8d..7622b8aec 100644 --- a/nft_ingester2/src/main.rs +++ b/nft_ingester2/src/main.rs @@ -70,6 +70,7 @@ async fn main() -> anyhow::Result<()> { let config = config_load::(&args.config) .await .with_context(|| format!("failed to parse config from: {}", args.config))?; + config.check(); ingester::run(config).await } } diff --git a/nft_ingester2/src/prom.rs b/nft_ingester2/src/prom.rs index 884407760..e81de4255 100644 --- a/nft_ingester2/src/prom.rs +++ b/nft_ingester2/src/prom.rs @@ -5,7 +5,7 @@ use { service::{make_service_fn, service_fn}, Body, Request, Response, Server, StatusCode, }, - prometheus::{IntCounterVec, IntGauge, IntGaugeVec, Opts, Registry, TextEncoder}, + prometheus::{IntCounter, IntCounterVec, IntGauge, IntGaugeVec, Opts, Registry, TextEncoder}, std::{net::SocketAddr, sync::Once}, tracing::{error, info}, }; @@ -46,6 +46,10 @@ lazy_static::lazy_static! { Opts::new("program_transformer_task_status", "Status of processed messages"), &["status"], ).unwrap(); + + static ref DOWNLOAD_METADATA_INSERTED_TOTAL: IntCounter = IntCounter::new( + "download_metadata_inserted_total", "Total number of inserted tasks for download metadata" + ).unwrap(); } pub fn run_server(address: SocketAddr) -> anyhow::Result<()> { @@ -65,6 +69,7 @@ pub fn run_server(address: SocketAddr) -> anyhow::Result<()> { register!(PGPOOL_CONNECTIONS_TOTAL); register!(PROGRAM_TRANSFORMER_TASKS_TOTAL); register!(PROGRAM_TRANSFORMER_TASK_STATUS); + register!(DOWNLOAD_METADATA_INSERTED_TOTAL); VERSION .with_label_values(&[ @@ -171,3 +176,7 @@ pub fn program_transformer_task_status_inc(kind: ProgramTransformerTaskStatusKin }]) .inc() } + +pub fn download_metadata_inserted_total_inc() { + DOWNLOAD_METADATA_INSERTED_TOTAL.inc() +} diff --git a/program_transformers/Cargo.toml b/program_transformers/Cargo.toml index 31d35871f..f600caf98 100644 --- a/program_transformers/Cargo.toml +++ b/program_transformers/Cargo.toml @@ -13,6 +13,7 @@ futures = { workspace = true } mpl-bubblegum = { workspace = true } num-traits = { workspace = true } sea-orm = { workspace = true, features = [] } +serde = { workspace = true } serde_json = { workspace = true } solana-sdk = { workspace = true } solana-transaction-status = { workspace = true } diff --git a/program_transformers/src/lib.rs b/program_transformers/src/lib.rs index 996a0ffac..237603996 100644 --- a/program_transformers/src/lib.rs +++ b/program_transformers/src/lib.rs @@ -15,6 +15,7 @@ use { }, futures::future::BoxFuture, sea_orm::{DatabaseConnection, SqlxPostgresConnector}, + serde::Serialize, solana_sdk::{instruction::CompiledInstruction, pubkey::Pubkey, signature::Signature}, solana_transaction_status::InnerInstructions, sqlx::PgPool, @@ -44,7 +45,7 @@ pub struct TransactionInfo { pub meta_inner_instructions: Vec, } -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize)] pub struct DownloadMetadataInfo { asset_data_id: Vec, uri: String, From d0958c2b8ee683be9f41596ea57c05701db47e53 Mon Sep 17 00:00:00 2001 From: Kirill Fomichev Date: Fri, 1 Dec 2023 22:34:46 -0500 Subject: [PATCH 23/23] download-metadata subtask --- Cargo.lock | 1 + nft_ingester2/Cargo.toml | 1 + nft_ingester2/config-download-metadata.yml | 12 + .../{config-run.yml => config-ingester.yml} | 2 +- nft_ingester2/src/config.rs | 67 ++++- nft_ingester2/src/download_metadata.rs | 236 ++++++++++++++++++ nft_ingester2/src/ingester.rs | 25 +- nft_ingester2/src/main.rs | 19 +- nft_ingester2/src/tracing.rs | 3 +- program_transformers/src/lib.rs | 4 +- 10 files changed, 345 insertions(+), 25 deletions(-) create mode 100644 nft_ingester2/config-download-metadata.yml rename nft_ingester2/{config-run.yml => config-ingester.yml} (97%) create mode 100644 nft_ingester2/src/download_metadata.rs diff --git a/Cargo.lock b/Cargo.lock index b104b5e84..64be3e889 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3556,6 +3556,7 @@ dependencies = [ "program_transformers", "prometheus", "redis", + "reqwest", "rust-crypto", "sea-orm", "serde", diff --git a/nft_ingester2/Cargo.toml b/nft_ingester2/Cargo.toml index f8e82b55b..073f642d7 100644 --- a/nft_ingester2/Cargo.toml +++ b/nft_ingester2/Cargo.toml @@ -22,6 +22,7 @@ opentelemetry_sdk = { workspace = true, features = ["trace"] } program_transformers = { workspace = true } prometheus = { workspace = true } redis = { workspace = true, features = ["tokio-comp", "tokio-native-tls-comp"] } +reqwest = { workspace = true } rust-crypto = { workspace = true } sea-orm = { workspace = true, features = ["sqlx-postgres"] } serde = { workspace = true } diff --git a/nft_ingester2/config-download-metadata.yml b/nft_ingester2/config-download-metadata.yml new file mode 100644 index 000000000..c42307be4 --- /dev/null +++ b/nft_ingester2/config-download-metadata.yml @@ -0,0 +1,12 @@ +# Important: only ONE `download-metadata` instance is supported right now! +prometheus: 127.0.0.1:8875 +postgres: + url: postgres://solana:solana@localhost/solana + min_connections: 10 + max_connections: 50 +download_metadata: + max_in_process: 50 # maximum tasks in process (downloading metadata) + prefetch_queue_size: 100 + limit_to_fetch: 200 # maximum number of tasks fetched from database + wait_tasks_max_idle_ms: 100 # if we do not have pending tasks, wait max ms + download_timeout_ms: 5_000 diff --git a/nft_ingester2/config-run.yml b/nft_ingester2/config-ingester.yml similarity index 97% rename from nft_ingester2/config-run.yml rename to nft_ingester2/config-ingester.yml index 3af3ad2e7..bbb377a81 100644 --- a/nft_ingester2/config-run.yml +++ b/nft_ingester2/config-ingester.yml @@ -24,5 +24,5 @@ postgres: program_transformer: transactions_cl_audits: false max_tasks_in_process: 40 -download_metadata_handler: +download_metadata: max_attempts: 3 diff --git a/nft_ingester2/src/config.rs b/nft_ingester2/src/config.rs index 665283dd8..8eb513c0b 100644 --- a/nft_ingester2/src/config.rs +++ b/nft_ingester2/src/config.rs @@ -182,7 +182,7 @@ pub struct ConfigIngester { pub redis: ConfigIngesterRedis, pub postgres: ConfigIngesterPostgres, pub program_transformer: ConfigIngesterProgramTransformer, - pub download_metadata_handler: ConfigDownloadMetadataHandler, + pub download_metadata: ConfigIngesterDownloadMetadata, } impl ConfigIngester { @@ -368,16 +368,75 @@ impl ConfigIngesterProgramTransformer { } #[derive(Debug, Clone, Copy, Deserialize)] -pub struct ConfigDownloadMetadataHandler { +pub struct ConfigIngesterDownloadMetadata { #[serde( - default = "ConfigDownloadMetadataHandler::default_max_attempts", + default = "ConfigIngesterDownloadMetadata::default_max_attempts", deserialize_with = "deserialize_usize_str" )] pub max_attempts: usize, } -impl ConfigDownloadMetadataHandler { +impl ConfigIngesterDownloadMetadata { pub const fn default_max_attempts() -> usize { 3 } } + +#[derive(Debug, Deserialize)] +pub struct ConfigDownloadMetadata { + pub postgres: ConfigIngesterPostgres, + pub download_metadata: ConfigDownloadMetadataOpts, +} + +#[derive(Debug, Clone, Copy, Deserialize)] +pub struct ConfigDownloadMetadataOpts { + #[serde( + default = "ConfigDownloadMetadataOpts::default_max_in_process", + deserialize_with = "deserialize_usize_str" + )] + pub max_in_process: usize, + #[serde( + default = "ConfigDownloadMetadataOpts::default_prefetch_queue_size", + deserialize_with = "deserialize_usize_str" + )] + pub prefetch_queue_size: usize, + #[serde( + default = "ConfigDownloadMetadataOpts::default_limit_to_fetch", + deserialize_with = "deserialize_usize_str" + )] + pub limit_to_fetch: usize, + #[serde( + default = "ConfigDownloadMetadataOpts::default_wait_tasks_max_idle", + deserialize_with = "deserialize_duration_str", + rename = "wait_tasks_max_idle_ms" + )] + pub wait_tasks_max_idle: Duration, + #[serde( + default = "ConfigDownloadMetadataOpts::default_download_timeout", + deserialize_with = "deserialize_duration_str", + rename = "download_timeout_ms" + )] + pub download_timeout: Duration, +} + +impl ConfigDownloadMetadataOpts { + pub const fn default_max_in_process() -> usize { + 50 + } + + pub const fn default_prefetch_queue_size() -> usize { + 100 + } + + pub const fn default_limit_to_fetch() -> usize { + 200 + } + + pub const fn default_wait_tasks_max_idle() -> Duration { + Duration::from_millis(100) + } + + pub const fn default_download_timeout() -> Duration { + Duration::from_millis(5_000) + } +} diff --git a/nft_ingester2/src/download_metadata.rs b/nft_ingester2/src/download_metadata.rs new file mode 100644 index 000000000..4392710b2 --- /dev/null +++ b/nft_ingester2/src/download_metadata.rs @@ -0,0 +1,236 @@ +use { + crate::{ + config::{ConfigDownloadMetadata, ConfigDownloadMetadataOpts}, + postgres::{create_pool as pg_create_pool, metrics_pgpool}, + util::create_shutdown, + }, + digital_asset_types::dao::{asset_data, sea_orm_active_enums::TaskStatus, tasks}, + futures::{ + future::{pending, FutureExt}, + stream::StreamExt, + }, + program_transformers::DownloadMetadataInfo, + reqwest::{ClientBuilder, StatusCode}, + sea_orm::{ + entity::{ActiveValue, ColumnTrait, EntityTrait}, + query::{Condition, Order, QueryFilter, QueryOrder, QuerySelect}, + sea_query::expr::Expr, + SqlxPostgresConnector, TransactionTrait, + }, + sqlx::PgPool, + std::{sync::Arc, time::Duration}, + tokio::{ + sync::{mpsc, Notify}, + task::JoinSet, + time::sleep, + }, + tracing::{info, warn}, +}; + +pub const TASK_TYPE: &str = "DownloadMetadata"; + +pub async fn run(config: ConfigDownloadMetadata) -> anyhow::Result<()> { + let mut shutdown = create_shutdown()?; + + // open connection to postgres + let pool = pg_create_pool(config.postgres).await?; + tokio::spawn({ + let pool = pool.clone(); + async move { metrics_pgpool(pool).await } + }); + + // reset previously runned tasks + tokio::select! { + result = reset_pending_tasks(pool.clone()) => { + let updated = result?; + info!("Reset {updated} tasks to Pending status"); + }, + Some(signal) = shutdown.next() => { + warn!("{signal} received, waiting spawned tasks..."); + return Ok(()) + }, + } + + // prefetch queue + let (tasks_tx, mut tasks_rx) = mpsc::channel(config.download_metadata.prefetch_queue_size); + let prefetch_shutdown = Arc::new(Notify::new()); + let prefetch_jh = { + let pool = pool.clone(); + let download_metadata = config.download_metadata; + let shutdown = Arc::clone(&prefetch_shutdown); + async move { + tokio::select! { + result = get_pending_tasks(pool, tasks_tx, download_metadata) => result, + _ = shutdown.notified() => Ok(()) + } + } + }; + tokio::pin!(prefetch_jh); + + // process tasks + let mut tasks = JoinSet::new(); + loop { + let pending_task_fut = if tasks.len() >= config.download_metadata.max_in_process { + pending().boxed() + } else { + tasks_rx.recv().boxed() + }; + + let tasks_fut = if tasks.is_empty() { + pending().boxed() + } else { + tasks.join_next().boxed() + }; + + tokio::select! { + Some(signal) = shutdown.next() => { + warn!("{signal} received, waiting spawned tasks..."); + break Ok(()); + }, + result = &mut prefetch_jh => break result, + Some(result) = tasks_fut => { + result??; + }, + Some(pending_task) = pending_task_fut => { + tasks.spawn(execute_task(pool.clone(), pending_task, config.download_metadata.download_timeout)); + } + }; + }?; + + tokio::select! { + Some(signal) = shutdown.next() => { + anyhow::bail!("{signal} received, force shutdown..."); + } + result = async move { + // shutdown `prefetch` channel + prefetch_shutdown.notify_one(); + // wait all spawned tasks + while let Some(result) = tasks.join_next().await { + result??; + } + // shutdown database connection + pool.close().await; + Ok::<(), anyhow::Error>(()) + } => result, + } +} + +// On startup reset tasks status +async fn reset_pending_tasks(pool: PgPool) -> anyhow::Result { + let conn = SqlxPostgresConnector::from_sqlx_postgres_pool(pool); + tasks::Entity::update_many() + .set(tasks::ActiveModel { + status: ActiveValue::Set(TaskStatus::Pending), + ..Default::default() + }) + .filter( + Condition::all() + .add(tasks::Column::Status.eq(TaskStatus::Running)) + .add(tasks::Column::TaskType.eq(TASK_TYPE)), + ) + .exec(&conn) + .await + .map(|result| result.rows_affected) + .map_err(Into::into) +} + +// Select Pending tasks, update status to Running and send to prefetch queue +async fn get_pending_tasks( + pool: PgPool, + tasks_tx: mpsc::Sender, + config: ConfigDownloadMetadataOpts, +) -> anyhow::Result<()> { + let conn = SqlxPostgresConnector::from_sqlx_postgres_pool(pool); + loop { + let pending_tasks = tasks::Entity::find() + .filter( + Condition::all() + .add(tasks::Column::Status.eq(TaskStatus::Pending)) + .add( + Expr::col(tasks::Column::Attempts) + .less_or_equal(Expr::col(tasks::Column::MaxAttempts)), + ), + ) + .order_by(tasks::Column::Attempts, Order::Asc) + .order_by(tasks::Column::CreatedAt, Order::Desc) + .limit(config.limit_to_fetch as u64) + .all(&conn) + .await?; + + if pending_tasks.is_empty() { + sleep(config.wait_tasks_max_idle).await; + } else { + tasks::Entity::update_many() + .set(tasks::ActiveModel { + status: ActiveValue::Set(TaskStatus::Running), + ..Default::default() + }) + .filter(tasks::Column::Id.is_in(pending_tasks.iter().map(|v| v.id.clone()))) + .exec(&conn) + .await?; + + for task in pending_tasks { + tasks_tx + .send(task) + .await + .map_err(|_error| anyhow::anyhow!("failed to send task to prefetch queue"))?; + } + } + } +} + +// Try to download metadata and remove task with asset_data update or update tasks to Pending/Failed +async fn execute_task(pool: PgPool, task: tasks::Model, timeout: Duration) -> anyhow::Result<()> { + let conn = SqlxPostgresConnector::from_sqlx_postgres_pool(pool); + match download_metadata(task.data, timeout).await { + Ok((asset_data_id, metadata)) => { + // Remove task and set metadata in transacstion + let txn = conn.begin().await?; + tasks::Entity::delete_by_id(task.id).exec(&txn).await?; + asset_data::Entity::update(asset_data::ActiveModel { + id: ActiveValue::Unchanged(asset_data_id), + metadata: ActiveValue::Set(metadata), + reindex: ActiveValue::Set(Some(false)), + ..Default::default() + }) + .exec(&txn) + .await?; + txn.commit().await?; + } + Err(error) => { + let status = if task.attempts + 1 == task.max_attempts { + TaskStatus::Failed + } else { + TaskStatus::Pending + }; + tasks::Entity::update(tasks::ActiveModel { + id: ActiveValue::Unchanged(task.id), + status: ActiveValue::Set(status), + attempts: ActiveValue::Set(task.attempts + 1), + errors: ActiveValue::Set(Some(error.to_string())), + ..Default::default() + }) + .exec(&conn) + .await?; + } + } + Ok(()) +} + +async fn download_metadata( + data: serde_json::Value, + timeout: Duration, +) -> anyhow::Result<(Vec, serde_json::Value)> { + let (id, uri) = serde_json::from_value::(data)?.into_inner(); + + // Need to check for malicious sites ? + let client = ClientBuilder::new().timeout(timeout).build()?; + let response = client.get(uri).send().await?; + + anyhow::ensure!( + response.status() == StatusCode::OK, + "HttpError status_code: {}", + response.status().as_str() + ); + Ok((id, response.json().await?)) +} diff --git a/nft_ingester2/src/ingester.rs b/nft_ingester2/src/ingester.rs index 22f4311c2..82cdc3cb5 100644 --- a/nft_ingester2/src/ingester.rs +++ b/nft_ingester2/src/ingester.rs @@ -1,6 +1,7 @@ use { crate::{ - config::{ConfigDownloadMetadataHandler, ConfigIngester}, + config::{ConfigIngester, ConfigIngesterDownloadMetadata}, + download_metadata::TASK_TYPE, postgres::{create_pool as pg_create_pool, metrics_pgpool}, prom::{ download_metadata_inserted_total_inc, program_transformer_task_status_inc, @@ -72,12 +73,12 @@ pub async fn run(config: ConfigIngester) -> anyhow::Result<()> { // program transforms related let pt_accounts = Arc::new(ProgramTransformer::new( pgpool.clone(), - create_download_metadata_notifier(pgpool.clone(), config.download_metadata_handler)?, + create_download_metadata_notifier(pgpool.clone(), config.download_metadata)?, false, )); let pt_transactions = Arc::new(ProgramTransformer::new( pgpool.clone(), - create_download_metadata_notifier(pgpool.clone(), config.download_metadata_handler)?, + create_download_metadata_notifier(pgpool.clone(), config.download_metadata)?, config.program_transformer.transactions_cl_audits, )); let pt_max_tasks_in_process = config.program_transformer.max_tasks_in_process; @@ -95,7 +96,7 @@ pub async fn run(config: ConfigIngester) -> anyhow::Result<()> { // read and process messages in the loop let mut shutdown = create_shutdown()?; - let result = loop { + loop { pt_tasks_len.store(pt_tasks.len(), Ordering::Relaxed); let redis_messages_recv = if pt_tasks.len() == pt_max_tasks_in_process { @@ -198,7 +199,7 @@ pub async fn run(config: ConfigIngester) -> anyhow::Result<()> { msg.ack() } }); - }; + }?; tokio::select! { Some(signal) = shutdown.next() => { @@ -218,15 +219,13 @@ pub async fn run(config: ConfigIngester) -> anyhow::Result<()> { // shutdown database connection pgpool.close().await; Ok::<(), anyhow::Error>(()) - } => result?, - }; - - result + } => result, + } } fn create_download_metadata_notifier( pgpool: PgPool, - config: ConfigDownloadMetadataHandler, + config: ConfigIngesterDownloadMetadata, ) -> anyhow::Result { let max_attempts = config.max_attempts.try_into()?; Ok(Box::new(move |info: DownloadMetadataInfo| -> BoxFuture< @@ -235,18 +234,16 @@ fn create_download_metadata_notifier( > { let pgpool = pgpool.clone(); Box::pin(async move { - const NAME: &str = "DownloadMetadata"; - let data = serde_json::to_value(info)?; let mut hasher = Sha256::new(); - hasher.input(NAME.as_bytes()); + hasher.input(TASK_TYPE.as_bytes()); hasher.input(serde_json::to_vec(&data)?.as_slice()); let hash = hasher.result_str(); let model = tasks::ActiveModel { id: ActiveValue::Set(hash), - task_type: ActiveValue::Set(NAME.to_owned()), + task_type: ActiveValue::Set(TASK_TYPE.to_owned()), data: ActiveValue::Set(data), status: ActiveValue::Set(TaskStatus::Pending), created_at: ActiveValue::Set(Utc::now().naive_utc()), diff --git a/nft_ingester2/src/main.rs b/nft_ingester2/src/main.rs index 7622b8aec..9ca97d111 100644 --- a/nft_ingester2/src/main.rs +++ b/nft_ingester2/src/main.rs @@ -1,6 +1,9 @@ use { crate::{ - config::{load as config_load, ConfigGrpc, ConfigIngester, ConfigPrometheus}, + config::{ + load as config_load, ConfigDownloadMetadata, ConfigGrpc, ConfigIngester, + ConfigPrometheus, + }, prom::run_server as prometheus_run_server, tracing::init as tracing_init, }, @@ -10,6 +13,7 @@ use { }; mod config; +mod download_metadata; mod grpc; mod ingester; mod postgres; @@ -40,8 +44,11 @@ enum ArgsAction { #[command(name = "grpc2redis")] Grpc, /// Run ingester process (process events from Redis) - #[command(name = "run")] + #[command(name = "ingester")] Ingester, + /// Run metadata downloader + #[command(name = "download-metadata")] + DownloadMetadata, } #[tokio::main] @@ -58,7 +65,7 @@ async fn main() -> anyhow::Result<()> { prometheus_run_server(address)?; } - // Run grpc / ingester + // Run grpc / ingester / download-metadata match args.action { ArgsAction::Grpc => { let config = config_load::(&args.config) @@ -73,5 +80,11 @@ async fn main() -> anyhow::Result<()> { config.check(); ingester::run(config).await } + ArgsAction::DownloadMetadata => { + let config = config_load::(&args.config) + .await + .with_context(|| format!("failed to parse config from: {}", args.config))?; + download_metadata::run(config).await + } } } diff --git a/nft_ingester2/src/tracing.rs b/nft_ingester2/src/tracing.rs index 36ba4db56..2d50f785c 100644 --- a/nft_ingester2/src/tracing.rs +++ b/nft_ingester2/src/tracing.rs @@ -12,7 +12,8 @@ pub fn init() -> anyhow::Result<()> { .install_batch(opentelemetry_sdk::runtime::Tokio)?; let jeager_layer = tracing_opentelemetry::layer().with_tracer(open_tracer); - let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info")); + let env_filter = EnvFilter::builder() + .parse(env::var(EnvFilter::DEFAULT_ENV).unwrap_or_else(|_| "info,sqlx=warn".to_owned()))?; let is_atty = atty::is(atty::Stream::Stdout) && atty::is(atty::Stream::Stderr); let io_layer = tracing_subscriber::fmt::layer().with_ansi(is_atty); diff --git a/program_transformers/src/lib.rs b/program_transformers/src/lib.rs index 237603996..1b56b6cc3 100644 --- a/program_transformers/src/lib.rs +++ b/program_transformers/src/lib.rs @@ -15,7 +15,7 @@ use { }, futures::future::BoxFuture, sea_orm::{DatabaseConnection, SqlxPostgresConnector}, - serde::Serialize, + serde::{Deserialize, Serialize}, solana_sdk::{instruction::CompiledInstruction, pubkey::Pubkey, signature::Signature}, solana_transaction_status::InnerInstructions, sqlx::PgPool, @@ -45,7 +45,7 @@ pub struct TransactionInfo { pub meta_inner_instructions: Vec, } -#[derive(Debug, Clone, PartialEq, Eq, Serialize)] +#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] pub struct DownloadMetadataInfo { asset_data_id: Vec, uri: String,