Gixing websocket subscriptions for signatures and slot (#403)
* Updating send transaction method signature * fixing issues with pubsub * remove test code
This commit is contained in:
parent
f990f857ab
commit
129d6a830e
|
@ -182,6 +182,7 @@ fn create_grpc_multiplex_block_info_task(
|
|||
.expect("block_time from geyser block meta")
|
||||
.timestamp
|
||||
as u64,
|
||||
parent: block_meta.parent_slot,
|
||||
};
|
||||
|
||||
let send_started_at = Instant::now();
|
||||
|
|
|
@ -324,5 +324,6 @@ fn map_block_info(produced_block: &ProducedBlock) -> BlockInfo {
|
|||
blockhash: produced_block.blockhash,
|
||||
commitment_config: produced_block.commitment_config,
|
||||
block_time: produced_block.block_time,
|
||||
parent: produced_block.parent_slot,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use solana_sdk::commitment_config::{CommitmentConfig, CommitmentLevel};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[repr(C)]
|
||||
pub enum Commitment {
|
||||
Processed = 0,
|
||||
|
|
|
@ -1,45 +1,29 @@
|
|||
use crate::commitment_utils::Commitment;
|
||||
use crate::{structures::produced_block::TransactionInfo, types::SubscptionHanderSink};
|
||||
use dashmap::DashMap;
|
||||
use solana_client::rpc_response::{ProcessedSignatureResult, RpcSignatureResult};
|
||||
use solana_sdk::signature::Signature;
|
||||
use solana_sdk::{
|
||||
commitment_config::{CommitmentConfig, CommitmentLevel},
|
||||
slot_history::Slot,
|
||||
};
|
||||
use solana_sdk::{commitment_config::CommitmentConfig, slot_history::Slot};
|
||||
use std::{sync::Arc, time::Duration};
|
||||
use tokio::time::Instant;
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub struct SubscriptionStore {
|
||||
pub signature_subscribers:
|
||||
Arc<DashMap<(Signature, CommitmentConfig), (SubscptionHanderSink, Instant)>>,
|
||||
Arc<DashMap<(Signature, Commitment), (SubscptionHanderSink, Instant)>>,
|
||||
}
|
||||
|
||||
impl SubscriptionStore {
|
||||
#[allow(deprecated)]
|
||||
pub fn get_supported_commitment_config(
|
||||
commitment_config: CommitmentConfig,
|
||||
) -> CommitmentConfig {
|
||||
match commitment_config.commitment {
|
||||
CommitmentLevel::Finalized | CommitmentLevel::Root | CommitmentLevel::Max => {
|
||||
CommitmentConfig {
|
||||
commitment: CommitmentLevel::Finalized,
|
||||
}
|
||||
}
|
||||
_ => CommitmentConfig {
|
||||
commitment: CommitmentLevel::Confirmed,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn signature_subscribe(
|
||||
&self,
|
||||
signature: Signature,
|
||||
commitment_config: CommitmentConfig,
|
||||
sink: SubscptionHanderSink,
|
||||
) {
|
||||
let commitment_config = Self::get_supported_commitment_config(commitment_config);
|
||||
self.signature_subscribers
|
||||
.insert((signature, commitment_config), (sink, Instant::now()));
|
||||
self.signature_subscribers.insert(
|
||||
(signature, Commitment::from(commitment_config)),
|
||||
(sink, Instant::now()),
|
||||
);
|
||||
}
|
||||
|
||||
pub fn signature_un_subscribe(
|
||||
|
@ -47,9 +31,8 @@ impl SubscriptionStore {
|
|||
signature: Signature,
|
||||
commitment_config: CommitmentConfig,
|
||||
) {
|
||||
let commitment_config = Self::get_supported_commitment_config(commitment_config);
|
||||
self.signature_subscribers
|
||||
.remove(&(signature, commitment_config));
|
||||
.remove(&(signature, Commitment::from(commitment_config)));
|
||||
}
|
||||
|
||||
pub async fn notify(
|
||||
|
@ -58,13 +41,20 @@ impl SubscriptionStore {
|
|||
transaction_info: &TransactionInfo,
|
||||
commitment_config: CommitmentConfig,
|
||||
) {
|
||||
if let Some((_sig, (sink, _))) = self
|
||||
.signature_subscribers
|
||||
.remove(&(transaction_info.signature, commitment_config))
|
||||
{
|
||||
if let Some((_sig, (sink, _))) = self.signature_subscribers.remove(&(
|
||||
transaction_info.signature,
|
||||
Commitment::from(commitment_config),
|
||||
)) {
|
||||
let signature_result =
|
||||
RpcSignatureResult::ProcessedSignature(ProcessedSignatureResult {
|
||||
err: transaction_info.err.clone(),
|
||||
});
|
||||
// none if transaction succeeded
|
||||
sink.send(slot, serde_json::json!({ "err": transaction_info.err }))
|
||||
.await;
|
||||
sink.send(
|
||||
slot,
|
||||
serde_json::to_value(signature_result).expect("Should be serializable in json"),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ use solana_sdk::hash::Hash;
|
|||
#[derive(Clone, Debug)]
|
||||
pub struct BlockInfo {
|
||||
pub slot: u64,
|
||||
pub parent: u64,
|
||||
pub block_height: u64,
|
||||
pub blockhash: Hash,
|
||||
pub commitment_config: CommitmentConfig,
|
||||
|
|
|
@ -3,10 +3,11 @@ use jsonrpsee::core::RpcResult;
|
|||
use prometheus::{opts, register_int_counter, IntCounter};
|
||||
use solana_account_decoder::UiAccount;
|
||||
use solana_lite_rpc_accounts::account_service::AccountService;
|
||||
use solana_lite_rpc_core::encoding::{BASE58, BASE64};
|
||||
use solana_lite_rpc_prioritization_fees::account_prio_service::AccountPrioService;
|
||||
use solana_lite_rpc_prioritization_fees::prioritization_fee_calculation_method::PrioritizationFeeCalculationMethod;
|
||||
use solana_rpc_client::nonblocking::rpc_client::RpcClient;
|
||||
use solana_rpc_client_api::config::RpcAccountInfoConfig;
|
||||
use solana_rpc_client_api::config::{RpcAccountInfoConfig, RpcSendTransactionConfig};
|
||||
use solana_rpc_client_api::response::{OptionalContext, RpcKeyedAccount};
|
||||
use solana_rpc_client_api::{
|
||||
config::{
|
||||
|
@ -21,28 +22,27 @@ use solana_rpc_client_api::{
|
|||
},
|
||||
};
|
||||
use solana_sdk::epoch_info::EpochInfo;
|
||||
use solana_sdk::packet::PACKET_DATA_SIZE;
|
||||
use solana_sdk::signature::Signature;
|
||||
use solana_sdk::{commitment_config::CommitmentConfig, pubkey::Pubkey, slot_history::Slot};
|
||||
use solana_transaction_status::{TransactionStatus, UiConfirmedBlock};
|
||||
use solana_transaction_status::{
|
||||
TransactionBinaryEncoding, TransactionStatus, UiConfirmedBlock, UiTransactionEncoding,
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
|
||||
use solana_lite_rpc_blockstore::history::History;
|
||||
use solana_lite_rpc_core::solana_utils::hash_from_str;
|
||||
use solana_lite_rpc_core::{
|
||||
encoding,
|
||||
stores::{block_information_store::BlockInformation, data_cache::DataCache},
|
||||
use solana_lite_rpc_core::stores::{
|
||||
block_information_store::BlockInformation, data_cache::DataCache,
|
||||
};
|
||||
use solana_lite_rpc_services::{
|
||||
transaction_service::TransactionService, tx_sender::TXS_IN_CHANNEL,
|
||||
};
|
||||
|
||||
use crate::rpc_errors::RpcErrors;
|
||||
use crate::{
|
||||
configs::{IsBlockHashValidConfig, SendTransactionConfig},
|
||||
rpc::LiteRpcServer,
|
||||
};
|
||||
use crate::{configs::IsBlockHashValidConfig, rpc::LiteRpcServer};
|
||||
use solana_lite_rpc_prioritization_fees::rpc_data::{AccountPrioFeesStats, PrioFeesStats};
|
||||
use solana_lite_rpc_prioritization_fees::PrioFeesService;
|
||||
|
||||
|
@ -347,7 +347,7 @@ impl LiteRpcServer for LiteBridge {
|
|||
async fn send_transaction(
|
||||
&self,
|
||||
tx: String,
|
||||
send_transaction_config: Option<SendTransactionConfig>,
|
||||
send_transaction_config: Option<RpcSendTransactionConfig>,
|
||||
) -> RpcResult<String> {
|
||||
RPC_SEND_TX.inc();
|
||||
|
||||
|
@ -355,29 +355,51 @@ impl LiteRpcServer for LiteBridge {
|
|||
const MAX_BASE58_SIZE: usize = 1683;
|
||||
const MAX_BASE64_SIZE: usize = 1644;
|
||||
|
||||
let SendTransactionConfig {
|
||||
let RpcSendTransactionConfig {
|
||||
encoding,
|
||||
max_retries,
|
||||
..
|
||||
} = send_transaction_config.unwrap_or_default();
|
||||
|
||||
let encoding = encoding.unwrap_or(UiTransactionEncoding::Base58);
|
||||
let expected_size = match encoding {
|
||||
encoding::BinaryEncoding::Base58 => MAX_BASE58_SIZE,
|
||||
encoding::BinaryEncoding::Base64 => MAX_BASE64_SIZE,
|
||||
UiTransactionEncoding::Base58 => MAX_BASE58_SIZE,
|
||||
UiTransactionEncoding::Base64 => MAX_BASE64_SIZE,
|
||||
_ => usize::MAX,
|
||||
};
|
||||
if tx.len() > expected_size {
|
||||
return Err(jsonrpsee::types::error::ErrorCode::OversizedRequest.into());
|
||||
}
|
||||
|
||||
let raw_tx = match encoding.decode(tx) {
|
||||
Ok(raw_tx) => raw_tx,
|
||||
Err(_) => {
|
||||
return Err(jsonrpsee::types::error::ErrorCode::InvalidParams.into());
|
||||
let binary_encoding = encoding
|
||||
.into_binary_encoding()
|
||||
.ok_or(jsonrpsee::types::error::ErrorCode::InvalidParams)?;
|
||||
|
||||
let wire_output = match binary_encoding {
|
||||
TransactionBinaryEncoding::Base58 => {
|
||||
if tx.len() > MAX_BASE58_SIZE {
|
||||
return Err(jsonrpsee::types::error::ErrorCode::OversizedRequest.into());
|
||||
}
|
||||
BASE58
|
||||
.decode(tx)
|
||||
.map_err(|_| jsonrpsee::types::error::ErrorCode::InvalidParams)?
|
||||
}
|
||||
TransactionBinaryEncoding::Base64 => {
|
||||
if tx.len() > MAX_BASE64_SIZE {
|
||||
return Err(jsonrpsee::types::error::ErrorCode::OversizedRequest.into());
|
||||
}
|
||||
BASE64
|
||||
.decode(tx)
|
||||
.map_err(|_| jsonrpsee::types::error::ErrorCode::InvalidParams)?
|
||||
}
|
||||
};
|
||||
|
||||
if wire_output.len() > PACKET_DATA_SIZE {
|
||||
return Err(jsonrpsee::types::error::ErrorCode::OversizedRequest.into());
|
||||
}
|
||||
let max_retries = max_retries.map(|x| x as u16);
|
||||
match self
|
||||
.transaction_service
|
||||
.send_wire_transaction(raw_tx, max_retries)
|
||||
.send_wire_transaction(wire_output, max_retries)
|
||||
.await
|
||||
{
|
||||
Ok(sig) => {
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
use prometheus::{opts, register_int_counter, IntCounter};
|
||||
use solana_lite_rpc_accounts::account_service::AccountService;
|
||||
use solana_lite_rpc_core::{
|
||||
commitment_utils::Commitment, stores::data_cache::DataCache,
|
||||
structures::account_data::AccountNotificationMessage, types::BlockStream,
|
||||
commitment_utils::Commitment,
|
||||
stores::data_cache::DataCache,
|
||||
structures::account_data::AccountNotificationMessage,
|
||||
types::{BlockInfoStream, BlockStream},
|
||||
};
|
||||
use std::{str::FromStr, sync::Arc, time::Duration};
|
||||
use tokio::sync::broadcast::error::RecvError::{Closed, Lagged};
|
||||
|
@ -48,7 +50,8 @@ pub struct LitePubSubBridge {
|
|||
data_cache: DataCache,
|
||||
prio_fees_service: PrioFeesService,
|
||||
account_priofees_service: AccountPrioService,
|
||||
block_stream: BlockStream,
|
||||
_block_stream: BlockStream,
|
||||
block_info_stream: BlockInfoStream,
|
||||
accounts_service: Option<AccountService>,
|
||||
}
|
||||
|
||||
|
@ -58,13 +61,15 @@ impl LitePubSubBridge {
|
|||
prio_fees_service: PrioFeesService,
|
||||
account_priofees_service: AccountPrioService,
|
||||
block_stream: BlockStream,
|
||||
block_info_stream: BlockInfoStream,
|
||||
accounts_service: Option<AccountService>,
|
||||
) -> Self {
|
||||
Self {
|
||||
data_cache,
|
||||
prio_fees_service,
|
||||
account_priofees_service,
|
||||
block_stream,
|
||||
_block_stream: block_stream,
|
||||
block_info_stream,
|
||||
accounts_service,
|
||||
}
|
||||
}
|
||||
|
@ -74,17 +79,14 @@ impl LitePubSubBridge {
|
|||
impl LiteRpcPubSubServer for LitePubSubBridge {
|
||||
async fn slot_subscribe(&self, pending: PendingSubscriptionSink) -> SubscriptionResult {
|
||||
let sink = pending.accept().await?;
|
||||
let mut block_stream = self.block_stream.resubscribe();
|
||||
let mut block_info_stream = self.block_info_stream.resubscribe();
|
||||
tokio::spawn(async move {
|
||||
loop {
|
||||
match block_stream.recv().await {
|
||||
Ok(produced_block) => {
|
||||
if !produced_block.commitment_config.is_processed() {
|
||||
continue;
|
||||
}
|
||||
match block_info_stream.recv().await {
|
||||
Ok(block_info) => {
|
||||
let slot_info = SlotInfo {
|
||||
slot: produced_block.slot,
|
||||
parent: produced_block.parent_slot,
|
||||
slot: block_info.slot,
|
||||
parent: block_info.parent,
|
||||
root: 0,
|
||||
};
|
||||
let result_message = jsonrpsee::SubscriptionMessage::from_json(&slot_info);
|
||||
|
@ -137,10 +139,11 @@ impl LiteRpcPubSubServer for LitePubSubBridge {
|
|||
async fn signature_subscribe(
|
||||
&self,
|
||||
pending: PendingSubscriptionSink,
|
||||
signature: Signature,
|
||||
signature: String,
|
||||
config: RpcSignatureSubscribeConfig,
|
||||
) -> SubscriptionResult {
|
||||
RPC_SIGNATURE_SUBSCRIBE.inc();
|
||||
let signature = Signature::from_str(&signature)?;
|
||||
let sink = pending.accept().await?;
|
||||
|
||||
let jsonrpsee_sink = JsonRpseeSubscriptionHandlerSink::new(sink);
|
||||
|
|
|
@ -356,6 +356,7 @@ pub async fn start_lite_rpc(args: Config, rpc_client: Arc<RpcClient>) -> anyhow:
|
|||
block_priofees_service,
|
||||
account_priofees_service,
|
||||
blocks_notifier,
|
||||
blockinfo_notifier,
|
||||
accounts_service.clone(),
|
||||
);
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::configs::{IsBlockHashValidConfig, SendTransactionConfig};
|
||||
use crate::configs::IsBlockHashValidConfig;
|
||||
use jsonrpsee::core::RpcResult;
|
||||
use jsonrpsee::proc_macros::rpc;
|
||||
use solana_account_decoder::UiAccount;
|
||||
|
@ -7,7 +7,7 @@ use solana_lite_rpc_prioritization_fees::rpc_data::{AccountPrioFeesStats, PrioFe
|
|||
use solana_rpc_client_api::config::{
|
||||
RpcAccountInfoConfig, RpcBlocksConfigWrapper, RpcContextConfig, RpcGetVoteAccountsConfig,
|
||||
RpcLeaderScheduleConfig, RpcProgramAccountsConfig, RpcRequestAirdropConfig,
|
||||
RpcSignatureStatusConfig, RpcSignaturesForAddressConfig,
|
||||
RpcSendTransactionConfig, RpcSignatureStatusConfig, RpcSignaturesForAddressConfig,
|
||||
};
|
||||
use solana_rpc_client_api::response::{
|
||||
OptionalContext, Response as RpcResponse, RpcBlockhash,
|
||||
|
@ -133,7 +133,7 @@ pub trait LiteRpc {
|
|||
async fn send_transaction(
|
||||
&self,
|
||||
tx: String,
|
||||
send_transaction_config: Option<SendTransactionConfig>,
|
||||
send_transaction_config: Option<RpcSendTransactionConfig>,
|
||||
) -> RpcResult<String>;
|
||||
|
||||
// ***********************
|
||||
|
|
|
@ -5,7 +5,6 @@ use solana_rpc_client_api::config::{
|
|||
RpcProgramAccountsConfig, RpcSignatureSubscribeConfig, RpcTransactionLogsConfig,
|
||||
RpcTransactionLogsFilter,
|
||||
};
|
||||
use solana_sdk::signature::Signature;
|
||||
|
||||
pub type Result<T> = std::result::Result<T, jsonrpsee::core::Error>;
|
||||
|
||||
|
@ -15,29 +14,21 @@ pub trait LiteRpcPubSub {
|
|||
// Direct Subscription Domain
|
||||
// ***********************
|
||||
|
||||
#[subscription(name = "slotSubscribe" => "slotNotification", unsubscribe="slotUnsubscribe", item=Slot)]
|
||||
#[subscription(name = "slotSubscribe" => "slotNotification", unsubscribe="slotUnsubscribe", item=String)]
|
||||
async fn slot_subscribe(&self) -> SubscriptionResult;
|
||||
|
||||
#[subscription(name = "blockSubscribe" => "blockNotification", unsubscribe="blockUnsubscribe", item=RpcResponse<UiConfirmedBlock>)]
|
||||
#[subscription(name = "blockSubscribe" => "blockNotification", unsubscribe="blockUnsubscribe", item=String)]
|
||||
async fn block_subscribe(
|
||||
&self,
|
||||
filter: RpcBlockSubscribeFilter,
|
||||
config: Option<RpcBlockSubscribeConfig>,
|
||||
) -> SubscriptionResult;
|
||||
|
||||
// [transactionSubscribe](https://github.com/solana-foundation/solana-improvement-documents/pull/69)
|
||||
//
|
||||
//#[subscription(name = "transactionSubscribe" => "transactionNotification", unsubscribe="transactionUnsubscribe", item=RpcResponse<RpcConfirmedTransactionStatusWithSignature>)]
|
||||
//async fn transaction_subscribe(
|
||||
// &self,
|
||||
// commitment_config: CommitmentConfig,
|
||||
//) -> SubscriptionResult;
|
||||
|
||||
// ***********************
|
||||
// Indirect Subscription Domain
|
||||
// ***********************
|
||||
|
||||
#[subscription(name = "logsSubscribe" => "logsNotification", unsubscribe="logsUnsubscribe", item=RpcResponse<RpcLogsResponse>)]
|
||||
#[subscription(name = "logsSubscribe" => "logsNotification", unsubscribe="logsUnsubscribe", item=String)]
|
||||
async fn logs_subscribe(
|
||||
&self,
|
||||
filter: RpcTransactionLogsFilter,
|
||||
|
@ -45,34 +36,34 @@ pub trait LiteRpcPubSub {
|
|||
) -> SubscriptionResult;
|
||||
|
||||
// WARN: enable_received_notification: bool is ignored
|
||||
#[subscription(name = "signatureSubscribe" => "signatureNotification", unsubscribe="signatureUnsubscribe", item=RpcResponse<serde_json::Value>)]
|
||||
#[subscription(name = "signatureSubscribe" => "signatureNotification", unsubscribe="signatureUnsubscribe", item=String)]
|
||||
async fn signature_subscribe(
|
||||
&self,
|
||||
signature: Signature,
|
||||
signature: String,
|
||||
config: RpcSignatureSubscribeConfig,
|
||||
) -> SubscriptionResult;
|
||||
|
||||
#[subscription(name = "slotUpdatesSubscribe" => "slotUpdatesNotification", unsubscribe="slotUpdatesUnsubscribe", item=SlotUpdate)]
|
||||
#[subscription(name = "slotUpdatesSubscribe" => "slotUpdatesNotification", unsubscribe="slotUpdatesUnsubscribe", item=String)]
|
||||
async fn slot_updates_subscribe(&self) -> SubscriptionResult;
|
||||
|
||||
#[subscription(name = "voteSubscribe" => "voteNotification", unsubscribe="voteUnsubscribe", item=RpcVote)]
|
||||
#[subscription(name = "voteSubscribe" => "voteNotification", unsubscribe="voteUnsubscribe", item=String)]
|
||||
async fn vote_subscribe(&self) -> SubscriptionResult;
|
||||
|
||||
/// subscribe to prio fees distribution per block; uses confirmation level "confirmed"
|
||||
#[subscription(name = "blockPrioritizationFeesSubscribe" => "blockPrioritizationFeesNotification", unsubscribe="blockPrioritizationFeesUnsubscribe", item=PrioFeesStats)]
|
||||
#[subscription(name = "blockPrioritizationFeesSubscribe" => "blockPrioritizationFeesNotification", unsubscribe="blockPrioritizationFeesUnsubscribe", item=String)]
|
||||
async fn latest_block_priofees_subscribe(&self) -> SubscriptionResult;
|
||||
|
||||
#[subscription(name = "accountPrioritizationFeesSubscribe" => "accountPrioritizationFeesNotification", unsubscribe="accountPrioritizationFeesUnsubscribe", item=AccountPrioFeesStats)]
|
||||
#[subscription(name = "accountPrioritizationFeesSubscribe" => "accountPrioritizationFeesNotification", unsubscribe="accountPrioritizationFeesUnsubscribe", item=String)]
|
||||
async fn latest_account_priofees_subscribe(&self, account: String) -> SubscriptionResult;
|
||||
|
||||
#[subscription(name = "accountSubscribe" => "accountNotification", unsubscribe="accountUnsubscribe", item=RpcResponse<UiAccount>)]
|
||||
#[subscription(name = "accountSubscribe" => "accountNotification", unsubscribe="accountUnsubscribe", item=String)]
|
||||
async fn account_subscribe(
|
||||
&self,
|
||||
account: String,
|
||||
config: Option<RpcAccountInfoConfig>,
|
||||
) -> SubscriptionResult;
|
||||
|
||||
#[subscription(name = "programSubscribe" => "programNotification", unsubscribe="programUnsubscribe", item=RpcResponse<RpcKeyedAccount>)]
|
||||
#[subscription(name = "programSubscribe" => "programNotification", unsubscribe="programUnsubscribe", item=String)]
|
||||
async fn program_subscribe(
|
||||
&self,
|
||||
pubkey_str: String,
|
||||
|
|
|
@ -16,6 +16,8 @@ pub struct ServerConfiguration {
|
|||
pub max_response_body_size: u32,
|
||||
|
||||
pub max_connection: u32,
|
||||
|
||||
pub max_subscriptions_per_connection: u32,
|
||||
}
|
||||
|
||||
impl Default for ServerConfiguration {
|
||||
|
@ -24,6 +26,7 @@ impl Default for ServerConfiguration {
|
|||
max_request_body_size: 50 * (1 << 10), // 50kb
|
||||
max_response_body_size: 500_000 * (1 << 10), // 500MB response size
|
||||
max_connection: 1000000,
|
||||
max_subscriptions_per_connection: 1000,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -41,6 +44,8 @@ pub async fn start_servers(
|
|||
|
||||
let ws_server_handle = ServerBuilder::default()
|
||||
.ws_only()
|
||||
.max_connections(server_configuration.max_connection)
|
||||
.max_subscriptions_per_connection(server_configuration.max_subscriptions_per_connection)
|
||||
.build(ws_addr.clone())
|
||||
.await?
|
||||
.start(pubsub);
|
||||
|
|
|
@ -18,7 +18,7 @@ solana-sdk = { workspace = true }
|
|||
solana-streamer = { workspace = true }
|
||||
solana-transaction-status = { workspace = true }
|
||||
solana-net-utils = { workspace = true }
|
||||
rustls = { workspace = true, features = ["dangerous_configuration"]}
|
||||
rustls = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
bincode = { workspace = true }
|
||||
|
|
|
@ -17,7 +17,6 @@ use solana_client::rpc_response::RpcVoteAccountStatus;
|
|||
use solana_lite_rpc_core::stores::data_cache::DataCache;
|
||||
use solana_lite_rpc_core::structures::leaderschedule::CalculatedSchedule;
|
||||
use solana_lite_rpc_core::structures::leaderschedule::LeaderScheduleData;
|
||||
use solana_program::slot_history::Slot;
|
||||
use solana_sdk::account::Account;
|
||||
use solana_sdk::commitment_config::CommitmentConfig;
|
||||
use solana_sdk::epoch_info::EpochInfo;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Connection, Keypair, sendAndConfirmTransaction, Transaction, PublicKey, TransactionInstruction, BlockheightBasedTransactionConfirmationStrategy } from "@solana/web3.js";
|
||||
import { Connection, Keypair, sendAndConfirmTransaction, Transaction, PublicKey, TransactionInstruction, BlockheightBasedTransactionConfirmationStrategy, TransactionMessage, VersionedTransaction } from "@solana/web3.js";
|
||||
import * as fs from "fs";
|
||||
import * as os from "os";
|
||||
import * as crypto from "crypto";
|
||||
|
@ -6,7 +6,7 @@ import * as crypto from "crypto";
|
|||
jest.setTimeout(60000);
|
||||
|
||||
const MEMO_PROGRAM_ID = new PublicKey("MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr");
|
||||
const connection = new Connection('http://0.0.0.0:8899', 'confirmed');
|
||||
const connection = new Connection('http://0.0.0.0:8890', 'confirmed');
|
||||
const keypair_file = fs.readFileSync(`${os.homedir}/.config/solana/id.json`, 'utf-8');
|
||||
const payer = Keypair.fromSecretKey(Uint8Array.from(JSON.parse(keypair_file)));
|
||||
|
||||
|
@ -27,16 +27,22 @@ function createTransaction(): Transaction {
|
|||
test('send and confirm transaction BlockheightBasedTransactionConfirmationStrategy', async () => {
|
||||
const tx = createTransaction();
|
||||
const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash();
|
||||
|
||||
const signature = await connection.sendTransaction(tx, [payer]);
|
||||
console.log(`https://explorer.solana.com/tx/${signature}`);
|
||||
await connection.confirmTransaction({
|
||||
blockhash,
|
||||
lastValidBlockHeight,
|
||||
signature,
|
||||
abortSignal: undefined
|
||||
});
|
||||
});
|
||||
|
||||
console.log(`https://explorer.solana.com/tx/${signature}`)
|
||||
test('send and confirm transaction legacy confrim', async () => {
|
||||
const tx = createTransaction();
|
||||
const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash();
|
||||
const signature = await connection.sendTransaction(tx, [payer]);
|
||||
console.log(`https://explorer.solana.com/tx/${signature}`);
|
||||
await connection.confirmTransaction(signature);
|
||||
});
|
||||
|
||||
test('send and confirm transaction', async () => {
|
||||
|
@ -46,45 +52,45 @@ test('send and confirm transaction', async () => {
|
|||
});
|
||||
|
||||
|
||||
test('get epoch info', async () => {
|
||||
{
|
||||
const {epoch, absoluteSlot, slotIndex, slotsInEpoch} = await connection.getEpochInfo();
|
||||
expect(Math.floor(absoluteSlot/slotsInEpoch)).toBe(epoch);
|
||||
}
|
||||
// test('get epoch info', async () => {
|
||||
// {
|
||||
// const {epoch, absoluteSlot, slotIndex, slotsInEpoch} = await connection.getEpochInfo();
|
||||
// expect(Math.floor(absoluteSlot/slotsInEpoch)).toBe(epoch);
|
||||
// }
|
||||
|
||||
let process_absoluteSlot;
|
||||
{
|
||||
const {epoch, absoluteSlot, slotIndex, slotsInEpoch} = await connection.getEpochInfo({ commitment: 'processed' });
|
||||
expect(Math.floor(absoluteSlot/slotsInEpoch)).toBe(epoch);
|
||||
process_absoluteSlot = absoluteSlot;
|
||||
}
|
||||
// let process_absoluteSlot;
|
||||
// {
|
||||
// const {epoch, absoluteSlot, slotIndex, slotsInEpoch} = await connection.getEpochInfo({ commitment: 'processed' });
|
||||
// expect(Math.floor(absoluteSlot/slotsInEpoch)).toBe(epoch);
|
||||
// process_absoluteSlot = absoluteSlot;
|
||||
// }
|
||||
|
||||
let confirmed_absoluteSlot;
|
||||
{
|
||||
const {epoch, absoluteSlot, slotIndex, slotsInEpoch} = await connection.getEpochInfo({ commitment: 'confirmed' });
|
||||
expect(Math.floor(absoluteSlot/slotsInEpoch)).toBe(epoch);
|
||||
confirmed_absoluteSlot = absoluteSlot;
|
||||
}
|
||||
expect(confirmed_absoluteSlot >= process_absoluteSlot);
|
||||
// let confirmed_absoluteSlot;
|
||||
// {
|
||||
// const {epoch, absoluteSlot, slotIndex, slotsInEpoch} = await connection.getEpochInfo({ commitment: 'confirmed' });
|
||||
// expect(Math.floor(absoluteSlot/slotsInEpoch)).toBe(epoch);
|
||||
// confirmed_absoluteSlot = absoluteSlot;
|
||||
// }
|
||||
// expect(confirmed_absoluteSlot >= process_absoluteSlot);
|
||||
|
||||
let finalized_absoluteSlot;
|
||||
{
|
||||
const {epoch, absoluteSlot, slotIndex, slotsInEpoch} = await connection.getEpochInfo({ commitment: 'finalized' });
|
||||
expect(Math.floor(absoluteSlot/slotsInEpoch)).toBe(epoch);
|
||||
finalized_absoluteSlot = absoluteSlot;
|
||||
}
|
||||
expect(process_absoluteSlot > finalized_absoluteSlot);
|
||||
expect(confirmed_absoluteSlot > finalized_absoluteSlot);
|
||||
// let finalized_absoluteSlot;
|
||||
// {
|
||||
// const {epoch, absoluteSlot, slotIndex, slotsInEpoch} = await connection.getEpochInfo({ commitment: 'finalized' });
|
||||
// expect(Math.floor(absoluteSlot/slotsInEpoch)).toBe(epoch);
|
||||
// finalized_absoluteSlot = absoluteSlot;
|
||||
// }
|
||||
// expect(process_absoluteSlot > finalized_absoluteSlot);
|
||||
// expect(confirmed_absoluteSlot > finalized_absoluteSlot);
|
||||
|
||||
});
|
||||
// });
|
||||
|
||||
|
||||
test('get leader schedule', async () => {
|
||||
{
|
||||
const leaderSchedule = await connection.getLeaderSchedule();
|
||||
expect(Object.keys(leaderSchedule).length > 0);
|
||||
}
|
||||
});
|
||||
// test('get leader schedule', async () => {
|
||||
// {
|
||||
// const leaderSchedule = await connection.getLeaderSchedule();
|
||||
// expect(Object.keys(leaderSchedule).length > 0);
|
||||
// }
|
||||
// });
|
||||
|
||||
|
||||
|
||||
|
|
105
yarn.lock
105
yarn.lock
|
@ -22,7 +22,7 @@
|
|||
resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.20.10.tgz"
|
||||
integrity sha512-sEnuDPpOJR/fcafHMjpcpGN5M2jbUGUHwmuWKM/YdPzeEDJg8bgmbcWQFUfE32MQjti1koACvoPVsDe8Uq+idg==
|
||||
|
||||
"@babel/core@^7.0.0", "@babel/core@^7.0.0-0", "@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.8.0", "@babel/core@>=7.0.0-beta.0 <8":
|
||||
"@babel/core@^7.11.6", "@babel/core@^7.12.3":
|
||||
version "7.20.12"
|
||||
resolved "https://registry.npmjs.org/@babel/core/-/core-7.20.12.tgz"
|
||||
integrity sha512-XsMfHovsUYHFMdrIHkZphTN/2Hzzi78R08NuHfDBehym2VsPDL6Zn/JAD/JQdnRvbSsbQc4mVaU1m6JgtTEElg==
|
||||
|
@ -501,7 +501,7 @@
|
|||
slash "^3.0.0"
|
||||
write-file-atomic "^4.0.1"
|
||||
|
||||
"@jest/types@^29.0.0", "@jest/types@^29.3.1":
|
||||
"@jest/types@^29.3.1":
|
||||
version "29.3.1"
|
||||
resolved "https://registry.npmjs.org/@jest/types/-/types-29.3.1.tgz"
|
||||
integrity sha512-d0S0jmmTpjnhCmNpApgX3jrUZgZ22ivKJRvL2lli5hpCRoNnp1f85r2/wpKfXuYu8E7Jjh1hGfhPyup1NM5AmA==
|
||||
|
@ -540,7 +540,7 @@
|
|||
resolved "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz"
|
||||
integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==
|
||||
|
||||
"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@1.4.14":
|
||||
"@jridgewell/sourcemap-codec@1.4.14", "@jridgewell/sourcemap-codec@^1.4.10":
|
||||
version "1.4.14"
|
||||
resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz"
|
||||
integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==
|
||||
|
@ -613,7 +613,7 @@
|
|||
"@solana/buffer-layout-utils" "^0.2.0"
|
||||
buffer "^6.0.3"
|
||||
|
||||
"@solana/web3.js@^1.32.0", "@solana/web3.js@^1.47.4", "@solana/web3.js@^1.73.0":
|
||||
"@solana/web3.js@^1.32.0", "@solana/web3.js@^1.73.0":
|
||||
version "1.73.0"
|
||||
resolved "https://registry.npmjs.org/@solana/web3.js/-/web3.js-1.73.0.tgz"
|
||||
integrity sha512-YrgX3Py7ylh8NYkbanoINUPCj//bWUjYZ5/WPy9nQ9SK3Cl7QWCR+NmbDjmC/fTspZGR+VO9LTQslM++jr5PRw==
|
||||
|
@ -743,6 +743,14 @@
|
|||
dependencies:
|
||||
"@types/yargs-parser" "*"
|
||||
|
||||
JSONStream@^1.3.5:
|
||||
version "1.3.5"
|
||||
resolved "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz"
|
||||
integrity sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==
|
||||
dependencies:
|
||||
jsonparse "^1.2.0"
|
||||
through ">=2.2.7 <3"
|
||||
|
||||
agentkeepalive@^4.2.1:
|
||||
version "4.2.1"
|
||||
resolved "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.2.1.tgz"
|
||||
|
@ -798,7 +806,7 @@ argparse@^1.0.7:
|
|||
dependencies:
|
||||
sprintf-js "~1.0.2"
|
||||
|
||||
babel-jest@^29.0.0, babel-jest@^29.3.1:
|
||||
babel-jest@^29.3.1:
|
||||
version "29.3.1"
|
||||
resolved "https://registry.npmjs.org/babel-jest/-/babel-jest-29.3.1.tgz"
|
||||
integrity sha512-aard+xnMoxgjwV70t0L6wkW/3HQQtV+O0PEimxKgzNqCJnbYmroPojdP2tqKSOAt8QAKV/uSZU8851M7B5+fcA==
|
||||
|
@ -923,7 +931,7 @@ braces@^3.0.2:
|
|||
dependencies:
|
||||
fill-range "^7.0.1"
|
||||
|
||||
browserslist@^4.21.3, "browserslist@>= 4.21.0":
|
||||
browserslist@^4.21.3:
|
||||
version "4.21.4"
|
||||
resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz"
|
||||
integrity sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==
|
||||
|
@ -959,14 +967,6 @@ buffer-from@^1.0.0:
|
|||
resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz"
|
||||
integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==
|
||||
|
||||
buffer@^6.0.3, buffer@~6.0.3:
|
||||
version "6.0.3"
|
||||
resolved "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz"
|
||||
integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==
|
||||
dependencies:
|
||||
base64-js "^1.3.1"
|
||||
ieee754 "^1.2.1"
|
||||
|
||||
buffer@6.0.1:
|
||||
version "6.0.1"
|
||||
resolved "https://registry.npmjs.org/buffer/-/buffer-6.0.1.tgz"
|
||||
|
@ -975,6 +975,14 @@ buffer@6.0.1:
|
|||
base64-js "^1.3.1"
|
||||
ieee754 "^1.2.1"
|
||||
|
||||
buffer@^6.0.3, buffer@~6.0.3:
|
||||
version "6.0.3"
|
||||
resolved "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz"
|
||||
integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==
|
||||
dependencies:
|
||||
base64-js "^1.3.1"
|
||||
ieee754 "^1.2.1"
|
||||
|
||||
bufferutil@^4.0.1:
|
||||
version "4.0.7"
|
||||
resolved "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.7.tgz"
|
||||
|
@ -1067,16 +1075,16 @@ color-convert@^2.0.1:
|
|||
dependencies:
|
||||
color-name "~1.1.4"
|
||||
|
||||
color-name@~1.1.4:
|
||||
version "1.1.4"
|
||||
resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz"
|
||||
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
|
||||
|
||||
color-name@1.1.3:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz"
|
||||
integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==
|
||||
|
||||
color-name@~1.1.4:
|
||||
version "1.1.4"
|
||||
resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz"
|
||||
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
|
||||
|
||||
commander@^2.20.3:
|
||||
version "2.20.3"
|
||||
resolved "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz"
|
||||
|
@ -1087,12 +1095,7 @@ concat-map@0.0.1:
|
|||
resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz"
|
||||
integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
|
||||
|
||||
convert-source-map@^1.6.0:
|
||||
version "1.9.0"
|
||||
resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz"
|
||||
integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==
|
||||
|
||||
convert-source-map@^1.7.0:
|
||||
convert-source-map@^1.6.0, convert-source-map@^1.7.0:
|
||||
version "1.9.0"
|
||||
resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz"
|
||||
integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==
|
||||
|
@ -1248,7 +1251,7 @@ eyes@^0.1.8:
|
|||
resolved "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz"
|
||||
integrity sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ==
|
||||
|
||||
fast-json-stable-stringify@^2.1.0, fast-json-stable-stringify@2.x:
|
||||
fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz"
|
||||
integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
|
||||
|
@ -1290,6 +1293,11 @@ fs.realpath@^1.0.0:
|
|||
resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz"
|
||||
integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
|
||||
|
||||
fsevents@^2.3.2:
|
||||
version "2.3.3"
|
||||
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
|
||||
integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
|
||||
|
||||
function-bind@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz"
|
||||
|
@ -1494,13 +1502,13 @@ jayson@^3.4.4:
|
|||
"@types/connect" "^3.4.33"
|
||||
"@types/node" "^12.12.54"
|
||||
"@types/ws" "^7.4.4"
|
||||
JSONStream "^1.3.5"
|
||||
commander "^2.20.3"
|
||||
delay "^5.0.0"
|
||||
es6-promisify "^5.0.0"
|
||||
eyes "^0.1.8"
|
||||
isomorphic-ws "^4.0.1"
|
||||
json-stringify-safe "^5.0.1"
|
||||
JSONStream "^1.3.5"
|
||||
lodash "^4.17.20"
|
||||
uuid "^8.3.2"
|
||||
ws "^7.4.5"
|
||||
|
@ -1708,7 +1716,7 @@ jest-resolve-dependencies@^29.3.1:
|
|||
jest-regex-util "^29.2.0"
|
||||
jest-snapshot "^29.3.1"
|
||||
|
||||
jest-resolve@*, jest-resolve@^29.3.1:
|
||||
jest-resolve@^29.3.1:
|
||||
version "29.3.1"
|
||||
resolved "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.3.1.tgz"
|
||||
integrity sha512-amXJgH/Ng712w3Uz5gqzFBBjxV8WFLSmNjoreBGMqxgCz5cH7swmBZzgBaCIOsvb0NbpJ0vgaSFdJqMdT+rADw==
|
||||
|
@ -1856,7 +1864,7 @@ jest-worker@^29.3.1:
|
|||
merge-stream "^2.0.0"
|
||||
supports-color "^8.0.0"
|
||||
|
||||
jest@^29.0.0, jest@^29.3.1:
|
||||
jest@^29.3.1:
|
||||
version "29.3.1"
|
||||
resolved "https://registry.npmjs.org/jest/-/jest-29.3.1.tgz"
|
||||
integrity sha512-6iWfL5DTT0Np6UYs/y5Niu7WIfNv/wRTtN5RSXt2DIEft3dx3zPuw/3WJQBCJfmEzvDiEKwoqMbGD9n49+qLSA==
|
||||
|
@ -1904,14 +1912,6 @@ jsonparse@^1.2.0:
|
|||
resolved "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz"
|
||||
integrity sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==
|
||||
|
||||
JSONStream@^1.3.5:
|
||||
version "1.3.5"
|
||||
resolved "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz"
|
||||
integrity sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==
|
||||
dependencies:
|
||||
jsonparse "^1.2.0"
|
||||
through ">=2.2.7 <3"
|
||||
|
||||
kleur@^3.0.3:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz"
|
||||
|
@ -2002,7 +2002,7 @@ minimatch@^3.0.4, minimatch@^3.1.1:
|
|||
dependencies:
|
||||
brace-expansion "^1.1.7"
|
||||
|
||||
ms@^2.0.0, ms@2.1.2:
|
||||
ms@2.1.2, ms@^2.0.0:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz"
|
||||
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
|
||||
|
@ -2214,25 +2214,18 @@ safe-buffer@^5.0.1:
|
|||
resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz"
|
||||
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
|
||||
|
||||
semver@7.x, semver@^7.3.5:
|
||||
version "7.3.8"
|
||||
resolved "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz"
|
||||
integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==
|
||||
dependencies:
|
||||
lru-cache "^6.0.0"
|
||||
|
||||
semver@^6.0.0, semver@^6.3.0:
|
||||
version "6.3.0"
|
||||
resolved "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz"
|
||||
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
|
||||
|
||||
semver@^7.3.5:
|
||||
version "7.3.8"
|
||||
resolved "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz"
|
||||
integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==
|
||||
dependencies:
|
||||
lru-cache "^6.0.0"
|
||||
|
||||
semver@7.x:
|
||||
version "7.3.8"
|
||||
resolved "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz"
|
||||
integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==
|
||||
dependencies:
|
||||
lru-cache "^6.0.0"
|
||||
|
||||
shebang-command@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz"
|
||||
|
@ -2420,9 +2413,9 @@ type-fest@^0.21.3:
|
|||
resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz"
|
||||
integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==
|
||||
|
||||
typescript@^4.9.5, typescript@>=4.3:
|
||||
typescript@^4.9.4:
|
||||
version "4.9.5"
|
||||
resolved "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a"
|
||||
integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==
|
||||
|
||||
update-browserslist-db@^1.0.9:
|
||||
|
@ -2433,7 +2426,7 @@ update-browserslist-db@^1.0.9:
|
|||
escalade "^3.1.1"
|
||||
picocolors "^1.0.0"
|
||||
|
||||
utf-8-validate@^5.0.2, utf-8-validate@>=5.0.2:
|
||||
utf-8-validate@^5.0.2:
|
||||
version "5.0.10"
|
||||
resolved "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz"
|
||||
integrity sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==
|
||||
|
@ -2503,7 +2496,7 @@ write-file-atomic@^4.0.1:
|
|||
imurmurhash "^0.1.4"
|
||||
signal-exit "^3.0.7"
|
||||
|
||||
ws@*, ws@^7.4.5:
|
||||
ws@^7.4.5:
|
||||
version "7.5.9"
|
||||
resolved "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz"
|
||||
integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==
|
||||
|
|
Loading…
Reference in New Issue